Книга: JavaScript. Подробное руководство, 6-е издание

19.9. Расширение библиотеки jQuery с помощью модулей расширений

19.9. Расширение библиотеки jQuery с помощью модулей расширений

Библиотека jQuery написана так, что позволяет легко добавлять в нее новые функциональные возможности. Модули, добавляющие новые функциональные возможности, называются расширениями (plug-in), большое количество которых можно отыскать на сайте http://plugins.jquery.com. Расширения для библиотеки jQuery являются обычными файлами с программным кодом на языке JavaScript, и, чтобы задействовать их в своих веб-страницах, достаточно просто подключить их с помощью элемента <script>, как любую другую библиотеку на языке JavaScript (разумеется, расширения должны подключаться после подключения самой библиотеки jQuery).

Создание собственных расширений для библиотеки jQuery является почти тривиальной задачей. Вся хитрость заключается в объекте-прототипе jQuery.fn, который является прототипом для всех объектов jQuery. Если добавить новую функцию в этот объект, она превратится в метод объекта jQuery. Например:

jQuery.fn.println = function() {
  // Объединить все аргументы в одну строку, разделив их пробелами
  var msg = Array.prototype.join.call(arguments, " ");
  // Обойти в цикле все элементы в объекте jQuery
  this.each(function() {
    // В конец каждого из них добавить строку с простым текстом и <br/>.
    jQuery(this).append(document.createTextNode(msg)).append("<br/>");
  });
  // Вернуть объект jQuery, чтобы обеспечить возможность составления цепочек
  return this;
};

Определив эту функцию jQuery.fn.println, мы получаем возможность вызывать метод println() относительно любого объекта jQuery, как показано ниже:

$( "#debug").println("x = ”, х, у = ", у);

В jQuery.fn постоянно добавляются новые методы. Если обнаружится, что приходится «вручную» выполнять обход элементов в объекте jQuery с помощью метода each() и выполнять над ними некоторые операции, - это повод задуматься о необходимости реструктуризации программного кода, чтобы переместить вызов метода each() в дополнительный метод. Если при создании такого метода следовать приемам модульного программирования и соблюдать некоторые соглашения, принятые в библиотеке jQuery, этот дополнительный метод можно назвать расширением и поделиться им с другими. Ниже приводится перечень соглашений, которым необходимо следовать при создании расширений для библиотеки jQuery:

• Не полагайтесь на идентификатор $: подключающая страница может вызывать функцию jQuery.noConflict(), после чего $() уже не будет синонимом функции jQuery(). В коротких расширениях, как в примере выше, можно просто использовать имя jQuery вместо $. Если вы создаете большое расширение, то вы наверняка обернете его единственной анонимной функцией, чтобы избежать создания глобальных переменных. В этом случае можно использовать распространенный прием передачи ссылки на функцию jQuery в виде аргумента и принимать это значение в параметре с именем $:

(function($) { // Анонимная функция с одним параметром $
  // Здесь находится реализация расширения
}(jQuery)); // Вызвать функцию с объектом jQuery в виде аргумента

• Если метод расширения не должен возвращать какое-то свое значение, он должен возвращать объект jQuery, чтобы этот метод можно было использовать в цепочках вызовов. Обычно этот объект передается методам в виде ссылки this, которую можно просто вернуть вызывающей программе. Метод в примере выше завершается строкой return this;. Некоторые методы можно немного сократить (и сделать их сложнее для понимания), используя еще один распространенный прием: возвращая результат метода each(). Например, метод println() мог бы содержать программный код return this.each(function() {...});

• Если метод расширения принимает более двух параметров или параметров настройки, дайте пользователю метода передавать параметры в форме объекта (как мы видели на примере метода animate() в разделе 19.5.2 и функции jQuery.ajax() в разделе 19.6.3).

• Не засоряйте пространство имен jQuery лишними методами. Правильно оформленные расширения для библиотеки jQuery определяют минимальное количество методов, образуя непротиворечивый и удобный прикладной интерфейс. Обычно расширения jQuery определяют в объекте jQuery.fn единственный метод. Этот метод принимает в первом аргументе строку и интерпретирует ее как имя функции, которой следует передать остальные аргументы. Если расширение определяет единственный метод, его имя должно совпадать с именем расширения. Если необходимо определить более одного метода, в именах методов следует использовать имя расширения в качестве префикса.

• Если расширение привязывает обработчики событий, их следует поместить в пространство имен событий (раздел 19.4.4). В качестве имени пространства имен следует использовать имя расширения.

• Если расширение использует метод data() для связывания данных с элементами, все данные следует помещать в единственный объект и хранить его как единственное значение, дав ему имя, совпадающее с именем расширения.

• Файл с программным кодом расширения должен иметь имя в формате «jquery.plugin.js», где подстроку «plugin» следует заменить на имя расширения.

Расширения могут определять новые вспомогательные функции, добавляя их в сам объект jQuery. Например:

// Этот метод выводит свои аргументы (с помощью метода расширения println())
// в элемент с атрибутом. Если такой элемент отсутствует, он будет
// создан и добавлен в документ.
jQuery.debug = function() {
  var elt = jQuery("#debug"); // Отыскать элемент #debug
  if (elt.length == 0) { // Создать, если он отсутствует
    elt = jQuery("<div><h1>Debugging Output</h1></div>");
    jQuery(document.body). append(elt);
  }
  elt.println.apply(elt, arguments); // Вывести в него аргументы
};

Помимо создания новых методов можно также расширять и другие части библиотеки jQuery. В разделе 19.5, например, мы узнали, что имеется возможность добавлять новые имена, определяющие продолжительность визуальных эффектов (вдобавок к «fast» и «slow»), создавая новые свойства в объекте jQuery.fx.speeds, и добавлять новые функции переходов, включая их в объект jQuery.easing. Более того, с помощью расширений можно даже добавлять новые возможности в механизм селекторов библиотеки jQuery! Например, можно определить новые псевдоклассы фильтров (такие как :first и :input), добавив свойства в объект jQuery. ехрг[':']. Ниже приводится пример определения нового фильтра :draggable, который возвращает только элементы с атрибутом draggable=true:

jQuery.expr[draggable = function(e) { return e.draggable === true; };

Добавив этот фильтр, мы сможем выбирать доступные для буксировки изображения вызовом $("img:draggable") вместо более длинного $("img[draggable=true]").

Как можно заметить в примере выше, функции фильтра передается элемент DOM - кандидат на выбор. Она должна вернуть true, если элемент соответствует фильтру, и false - в противном случае. Многие нестандартным фильтрам достаточно одного аргумента с элементом, но в действительности им передается четыре аргумента. Во втором аргументе передается целочисленный индекс, определяющий позицию элемента в массиве кандидатов. Этот массив передается в четвертом аргументе, но ваша функция фильтра не должна модифицировать его. В третьем аргументе передается весьма интересное значение: это массив результатов вызова метода .ехес() объекта RegExp. В четвертом элементе этого массива (с индексом 3) хранится значение, переданное псевдоклассу фильтра в круглых скобках (если оно имеется). Из этого значения удаляются все скобки и кавычки, и остается только строка. Например, ниже показано, как можно было бы реализовать псевдокласс :data(x), возвращающий true только для элементов, имеющих атрибут data-x (раздел 15.4.3):

jQuery.ехрг[data = function(element, index, match, array) {
  // Примечание: В IE версии 7 и ниже метод hasAttгibute() отсутствует
  return element.hasAttribute("data-" + match[3]):
};

Оглавление книги


Генерация: 1.382. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз