Как лучше всего организовать ненавязчивый JavaScript на нескольких страницах?

Мне нравится jQuery, но у меня проблемы с сайтом большего размера и несколькими страницами. Моя проблема в том, что каждая страница имеет уникальные требования, и мне нужно знать, как лучше всего сообщить jQuery, какие страницы нужно активировать. Например, для некоторых форм требуется подключаемый модуль Validator, а для некоторых - t, некоторые таблицы используют подключаемый модуль DataTables, а некоторые нет и т. д.

Теперь я думаю, что мог бы встроить сложную логику (операторы переключения) в свой файл JavaScript приложения, который запускает различные действия в зависимости от того, на какой странице они находятся, но это просто кажется неприятным запахом. Какая здесь лучшая практика?

ОБНОВЛЕНИЕ: было много хороших идей по этому вопросу, но это не совсем то, что я ищу. Позвольте мне перефразировать вопрос в более общем виде.

В настоящее время я использую Rails и его помощники по прототипам для создания своих компонентов AJAX, но я хочу перейти на UJS. Как мне сообщить jQuery, какие ссылки / кнопки использовать AJAX, а каких избегать? И, учитывая, что я могу различать те, которые должны иметь AJAX, как мне дать каждой ссылке свои собственные параметры (метод, обновление и т. Д.), Как я мог бы с помощниками?

Я имею в виду, помимо создания огромной страницы конкретных селекторов jQuery, нацеленных на каждую отдельную ссылку / кнопку. :)


person Richard Hurt    schedule 01.01.2010    source источник


Ответы (5)


Хорошая практика - иметь код, который требуется для всех страниц в одном файле, и иметь определенные файлы javascript для страниц, требующих определенных функций. Похоже, что вы все равно этим занимаетесь, так что у нас есть хорошая основа для дальнейшего развития.

Существует множество способов указать, какие страницы и какие файлы нужны, но помните, что в нормальных условиях файлы javascript кэшируются браузером, так что эти файлы нужно загружать только один раз.

В свете этого комментария

Да, но что, если у вас есть несколько страниц с одинаковыми элементами DOM? Например, мой плагин validator () настроен как $ ('form'). Validate (), но иногда я не хочу, чтобы он воздействовал на все формы на странице, только на некоторые из них. Что мне делать в этом случае?

Я предлагаю придумать соглашение, по которому будут отмечаться элементы, общие для всех страниц, для которых требуются определенные плагины jQuery, «прикрепленные» к ним. Например, если у вас есть элемент <form> на нескольких разных страницах, для которых требуется плагин validator(), но на любой конкретной странице есть более одного элемента <form> (и не все элементы <form> должны иметь плагин validator()), я предлагаю с помощью класса CSS для различения <form> элементов, которым нужен плагин.

<!-- HTML -->

<!-- need to apply plugin to this -->    
<form class="validator"> ... </form>

<!-- but not to this -->
<form> ... </form>

<script type="text/javascript">
// jQuery Code (in a separate file)

$(function() {
    $('form.validator').validator();
});
</script>

Таким образом, плагин будет применяться только к тем <form> элементам, которые соответствуют селектору.

РЕДАКТИРОВАТЬ:

Я не уверен, как работают помощники в рельсах, но вы можете передавать данные в обработчик событий в jQuery, используя параметр data в _ 10_ для любых данных, которые не являются непосредственно частью самого <a> элемента (например, такого атрибута, как href). Если для некоторых ссылок требуется AJAX, тогда имеет смысл пометить их классом CSS и сохранить URL-адрес в href для элемента. Затем в вашем коде jQuery, который можно использовать на любых страницах со ссылками, которые отправляют запросы через AJAX, вы можете сделать что-то вроде

<a class="ajax-link" href="/get/someData.php">Data retrieved through AJAX</a>

<a href="/normalLink.php">Standard link with no AJAX</a>

<script type="text/javascript">
$('a.ajax-link').bind('click',ajaxRequest);

function ajaxRequest(e) {
    e.preventDefault(); 
    $.get(e.target.href, function(data) {
      $('#loadDiv').html(data);
    });
}
</script>

ссылка будет работать как обычная ссылка, когда у пользователя отключен JavaScript, но будет делать запрос данных AJAX, когда JavaScript включен. Я использовал здесь именованную функцию ajaxRequest, поскольку она может упростить отладку сценария (и, возможно, также повторно использовать), но вы можете использовать анонимную функцию, если хотите.

person Russ Cam    schedule 01.01.2010
comment
Отличное понимание. В моем случае есть конкретная (очень большая) форма, для которой не нужен плагин validator (), поэтому я, вероятно, буду использовать селектор NOT, чтобы исключить его. Что-то вроде $ ('form: not (.no-validate)'). Validate (); ... - person Richard Hurt; 01.01.2010
comment
Конечно, если вам нужно применить плагин ко всем элементам, кроме одного <form>, тогда использование селектора :not, возможно, будет лучше, чем применение класса CSS ко всем элементам, которым действительно нужен плагин. Может быть немного быстрее просто захватить все <form> элементы, а затем использовать filter() для удаления ненужного, а не использовать сложную строку селектора. - person Russ Cam; 01.01.2010

Плагины jQuery обычно активируются для элементов DOM, например:

$("#element").myPlugin();

Если элемент не существует на странице, плагины обычно ведут себя безопасно, не активируя плагин.

Если ваш плагин не соответствует этой структуре, я бы посоветовал сделать что-то вроде этого:

if($("#element").length) $("#element").myPlugin();
person Luca Matteis    schedule 01.01.2010
comment
Условие if всегда будет оцениваться как true как объект со свойством length, и будет возвращено значение 0 (среди других свойств). Поэтому вы должны проверить свойство длины - if($("#element").length) { .... } - person Russ Cam; 01.01.2010
comment
Да, но что, если у вас есть несколько страниц с одинаковыми элементами DOM? Например, мой плагин validator () настроен как $ ('form'). Validate (), но иногда я не хочу, чтобы он воздействовал на все формы на странице, только на некоторые из них. Что мне делать в этом случае? - person Richard Hurt; 01.01.2010
comment
@Richard: дать формы, которые вы хотите проверить, специальный класс? - person Christoph; 01.01.2010
comment
@Christoph: Да, я просто подумал об этом. Иногда вам нужно отталкивать вещи от других людей, прежде чем они обретут смысл в вашей собственной голове. :) - person Richard Hurt; 01.01.2010

Нашел красивое индивидуальное решение

http://topsecretproject.finitestatemachine.com/2010/04/how-to-organizing-javascript-in-ruby-on-rails/

person Ivailo Bardarov    schedule 31.03.2011

Я всегда делаю одно: добавляю id к тегу body каждой страницы, где id - это имя страницы (<body id="contact">). Это упрощает выбор как javascript, так и css.

Например:

<!-- HTML -->

<!-- need to apply plugin to these forms -->    
<form> ... </form> on the about.php page

<!-- but not to this -->
<form> ... </form> on the index.php page

<script type="text/javascript">
// jQuery Code (in a separate file)

$(function() {
    $('body#about form').validator();
});
</script>
person Isley Aardvark    schedule 01.01.2010
comment
Это довольно хороший способ выполнять разные действия на разных страницах. Однако я использую Rails и не думаю, что это так работает. Я мог бы создать отдельный файл макета для каждого типа страницы, но это было бы не очень СУХОЕ и затруднило бы кеширование заголовка. - person Richard Hurt; 02.01.2010

Вы можете передавать пары ключ-значение в свой основной модуль JavaScript, сообщая, какие плагины следует импортировать. Этот метод используется scriptaculous.

<script type="text/javascript" src="scriptaculous.js?load=effects,dragdrop">

Another approach is to define in server side which media files are needed for each form/page, so the html can be rendered automatically with links to the scripts that are going to be used. Django has a good implementation of this technique:

class CalendarWidget(forms.TextInput):
    class Media:
        css = {
            'all': ('pretty.css',)
        }
        js = ('animations.js', 'actions.js')
person jbochi    schedule 01.01.2010
comment
Это довольно крутая техника, но я использую Rails, и, насколько мне известно, в ней нет ничего подобного. - person Richard Hurt; 02.01.2010