css, html, php, javascript, jQuery, ajax … – решения, примеры, рецепты
26 Авг
За последнее время было много просьб рассказать о том, как написать свой собственный плагин к jQuery. Идя навстречу пожеланиям трудящихся бескрайних полей Интернета – выполняю эти просьбы…
Для того, чтобы лучше понять принципы, поставим себе какую-нибудь несложную задачу, имеющую хотя бы минимальную практическую пользу. Давайте вместе напишем плагин к jQuery, который будет раскрашивать в разный цвет четные и нечетные строки любой имеющейся таблицы. Причем мы должны иметь возможность передавать нашему плагину в качестве параметров значение цвета для четных и нечетных строк таблицы, а также значение цвета шрифта в четных и нечетных строках. Еще неплохо сделать, чтобы при перемещении указателя мыши над строкой, цвет фона строки и цвет шрифта тоже изменялся. Задача определена – приступаем к ее выполнению.
Для начала усвоим правила, которым необходимо следовать при написании плагина для jQuery:
Следуя первому правилу, назовем файл нашего плагина jquery.zebra.js и первое, что мы напишем в этом файле, будет определение плагина:
jQuery.fn.zebra = function(){
// тут мы разместим код плагина
};
И хотя наш плагин еще не содержит вообще никакого кода, его уже можно вызвать следующим образом:
$("selector").zebra();
Но мы договорились, что наш плагин должен уметь принимать некоторые параметры, поэтому давайте немного дополним наш код:
jQuery.fn.zebra = function(options){
// тут мы разместим код плагина
};
где options – это объект, который может содержит пользовательские настройки. А может и не содержать…. Поэтому первое, что мы сделаем – определим настройки по умолчанию, воспользовавшись для этого jQuery.extend(object).
jQuery.fn.zebra = function(options){
// настройки по умолчанию
var options = jQuery.extend({
bgEven: '#FFC080', // бэкграунд для четных строк
bgOdd: '#FFDFBF', // бэкграунд для нечетных строк
fontEven: '#AA7239', // цвет шрифта четных строк
fontOdd: '#AA7239', // цвет шрифта нечетных строк
bgHover: '#FF8000', // бэкграунд при hover
fontHover: '#55391C' // цвет шрифта при hover
},options);
// тут мы разместим код
};
Переменная options – это объект, состоящий из пар ключ/значение в которых передаются значения соответствующих опций. Если нашему плагину не будут переданы пользовательские настройки – мы используем настройки по умолчанию. Если же опции, все или некоторые, будут переданы, тогда будут использованы именно они.
Двигаемся дальше, и сейчас самое время вспомнить одно из правил написания плагинов к jQuery – вы должны использовать this.each, чтобы выполнить итерации по текущему набору элементов. Заодно вспомним и это правило тоже – метод должен возвратить объект jQuery, если не предусмотрено иное. Проделаем это:
jQuery.fn.zebra = function(options){
// настройки по умолчанию
var options = jQuery.extend({
bgEven: '#FFC080', // бэкграунд для четных строк
bgOdd: '#FFDFBF', // бэкграунд для нечетных строк
fontEven: '#AA7239', // цвет шрифта четных строк
fontOdd: '#AA7239', // цвет шрифта нечетных строк
bgHover: '#FF8000', // бэкграунд при hover
fontHover: '#55391C' // цвет шрифта при hover
},options);
return this.each(function() {
// тут мы разместим код
});
};
Вспомним еще одно правило (или скорее памятку) – this – это ссылка на текущий объект jQuery. Действительно, в нашем случае this содержит ссылку на объект, который определит пользователь нашего плагина в jQuery-селекторе, например:
$("table.example").zebra();
здесь объект jQuery будет содержать таблицу (или таблицы) с классом example.
Теперь напишем собственно код, который должен реализовать задуманную нами функциональность. Займемся для начала четными строками – отыщем их:
jQuery(this).find('tr:even');
Тут все ясно – this содержит ссылку на текущую таблицу, и в этой таблице мы отбираем только четные строки. Но надо еще установить цвет фона и цвет шрифта для этого набора строк. Воспользуемся для этого css-свойствами background-color и color:
jQuery(this).find('tr:even')
.css('background-color', options.bgEven)
.css('color', options.fontEven);
Для всех строк, присутствующих в текущем наборе (сейчас это четные строки текущей таблицы) мы устанавливаем css-свойства background-color и color, получая их значения из объекта options.
Но и этого будет маловато… Нужно обработать прохождение указателя мыши над строкой. Допишем наш код еще немного:
jQuery(this).find('tr:even')
.css('background-color', options.bgEven)
.css('color', options.fontEven)
.hover(
function () {
jQuery(this)
.css('background-color', options.bgHover)
.css('color', options.fontHover);
},
function () {
jQuery(this)
.css('background-color', options.bgEven)
.css('color', options.fontEven);
}
);
Мы воспользовались методом hover() библиотеки jQuery, передав ему две функции. Первая определит css-свойства в момент, когда указатель мыши находится над строкой, а вторая – вернет старые значения, когда он выйдет за пределы строки.
Точно такой же код нужно написать и для нечетных строк текущей таблицы и в итоге получится следующее:
jQuery.fn.zebra = function(options){
// настройки по умолчанию
var options = jQuery.extend({
bgEven: '#FFC080', // бэкграунд для четных строк
bgOdd: '#FFDFBF', // бэкграунд для нечетных строк
fontEven: '#AA7239', // цвет шрифта четных строк
fontOdd: '#AA7239', // цвет шрифта нечетных строк
bgHover: '#FF8000', // бэкграунд при hover
fontHover: '#55391C' // цвет шрифта при hover
},options);
return this.each(function() {
// четные строки
jQuery(this).find('tr:even')
.css('background-color', options.bgEven)
.css('color', options.fontEven)
.hover(
function () {
jQuery(this)
.css('background-color', options.bgHover)
.css('color', options.fontHover);
},
function () {
jQuery(this)
.css('background-color', options.bgEven)
.css('color', options.fontEven);
}
);
// нечетные строки
jQuery(this).find('tr:odd')
.css('background-color', options.bgOdd)
.css('color', options.fontOdd)
.hover(
function () {
jQuery(this)
.css('background-color', options.bgHover)
.css('color', options.fontHover);
},
function () {
jQuery(this)
.css('background-color', options.bgOdd)
.css('color', options.fontOdd);
}
);
});
};
Вот такой небольшой, но вполне рабочий плагин у нас получился. А теперь займемся пожалуй даже более важным, чем собственно написание плагина – написанием документации к нему. И для начала сообщим пользователям, а для чего оно вообще надо. Затем опишем этапы установки плагина, приведем список доступных опций и примеры использования. Естественно дадим ссылку на работающий пример.
Плагин jquery.zebra.js позволяет легко изменять цвет фона и шрифта для четных и нечетных строк таблицы, выделяет цветом строку над которой находится указатель мыши. Совместим с IE 6.0+, FF 2+, Safari 2.0+, Opera 9.0+.
Подключите к странице требующиеся для работы файлы – библиотеку jQuery и файл плагина:
<script type="text/javascript" src="js/jquery.js"></script> <script type="text/javascript" src="js/jquery.zebra.js"></script>
1. Использование плагина с настройками по умолчанию:
<script type="text/javascript">
$(document).ready(function(){
$("table.bClass").zebra();
});
</script>
В этом примере плагин работает с таблицей (или таблицами), которая имеет класс bClass. К четным и нечетным строкам таблицы будут применены css-правила, которые зададут для них разный цвет фона и разный цвет шрифта. В примере будут использованы настройки по умолчанию.
2. Использование плагина с пользовательскими настройками:
<script type="text/javascript">
$(document).ready(function(){
$("table.cClass").zebra({
bgEven: "#CC66CC",
bgOdd: "#E6ACE6",
fontEven: "#662266",
fontOdd: "#662266",
bgHover: "#331133",
fontHover: "#FFFFFF"
});
});
</script>
В этом примере мы передаем плагину объект, содержащий пользовательские настройки, которые и определяют цвет фона и цвет шрифта в строках таблицы.
bgEven – строка: цвет фона для четных строк.
bgOdd – строка: цвет фона для нечетных строк.
fontEven – строка: цвет шрифта четных строк.
fontOdd – строка: цвет шрифта нечетных строк.
bgHover – строка: цвет фона при прохождении указателя мыши над строкой.
fontHover – строка: цвет шрифта при прохождении указателя мыши над строкой.
Здесь можно посмотреть демо
Скачать исходный код примера можно здесь. Архив содержит все необходимые файлы.
Вот и все. Осталось разве что привести пару ссылок по теме:
http://docs.jquery.com/Plugins/Authoring
http://www.learningjquery.com/…/a-plugin-development-pattern
и теперь Вы знаете как написать свой плагин для библиотеки jQuery. Удачи!
Отзывов (54) на «Как написать плагин для jQuery.»
Что-то демо у вас не работает…
Как насчет включить поддержку JavaScript в браузере? Без нее плагин естественно работать не будет. А так… Неужели Вы вправду думаете, что я вывалил статью не проверив работоспособность плагина?
Спасибо большое. Простой и понятный пример… даже кажется что все просто
Единственный момент которого я не понял:
var options = jQuery.extend({
//параметры
},options);
Зачем в скобках через запятую еще раз указывается options, в документации ответа не нашел.
В option (после запятой) – пользовательские настройки (если переданы плагину в объекте option). Если нет – используются по умолчанию. Т.е. в итоге в option оказываются либо настройки по умолчанию, либо пользовательские, либо их смесь, если пользовательские переданы только частично.
Понял спасибо…
Пишите еще статьи такого рода!!!
Хм… а как соотносится призыв «всегда используйте jQuery вместо $ в коде Вашего плагина» и код колбэк-функций, в котором везде используется $?
To Oleg Lobach
Действительно пропустил… Но уже исправился…
З.Ы. А вообще мне нравится такое развитие событий – не успел статью повесить – и столько комментариев уже…
Извините за оффтоп, недавно обнаружил проблему с jQuery – ie6 перестал реагировать на навешиваемые обработчики событий в таком виде:
$(«»).click(someFunction).appendTo(field);
Пробовал в разных вариантах
field.append(..),
присваивал обьект через промежуточные переменные
var x = $(«»); x.click… ).
Не работает, причем если вызвать программно
x.click()
после навешивания обработчика – он срабатывает.
Убрал Доктайп — все заработало. Следует ли из этого, что в ишаке работает только в Quirks mode?
Прошу прощения еще раз, с английским очень туго
Если несложно, скиньте какой-нибудь конкретный пример, законченный кусок кода. Интересно было бы посмотреть.
Сложил весь код в архив:
http://www.sendspace.com/file/wjn4me
Собственно проблема скрывается в методе Irv.Field.build() — он не работает в ие6 и 7 с указаным доктайпом.
Это мой маленький домашний проект, за качество кода извиняюсь, с вебом знакомитсься стал относительно недавно.
Простите, не то написал: метод Irv.Field.build() работает, но в нем обработчик события не срабатывает при указаных событиях (хотя программно можно вызвать)
Архив я взял – посмотрю и отпишу…
Спасибо заранее!
Mur, проблема не в ie6 – Вы некорректно указываете DOCTYPE. В первом случае Вы указываете:
во втором случае пишете:
– это некорректно, для Strict надо указать:
Я еще эксперементировал с XHTML 1.0 Strict. Если DOCTYPE задавать корректно (в Вашем исходнике, если убрать комментарии перед доктайпом – тоже не фурычит) – в IE к сожалению не работает ни при каком раскладе. Надо копать в этом направлении, что-то ему не нравится.
Добавьте в свой арсенал HTML Validator и CSS Validator – полезные вещи однако…
Спасибо Вам огромное!
Моя IDE просто предложила мне такой вариант доктайпа, а я вот не проверил. С валидаторами знаком, просто не додумался проверить
Кстати, насчет IDE, чем Вы пользуетесь для работы? Я использую Intellij IDEA, т.к. моя основная работа — это java, однако те средства, что есть в этой шикарной среде разработки, позволяют очень удобно работать с связкой html + js + css (правда вот с доктайпами оказывается косячок небольшой). Для js наверное самая мощная среда, которую я видел, позволяет делать множество инетерсный вещей, как то несколько методов для рефакторинга, оптимизация кода и т.д. Плюс есть плагины для php и официальная поддержка ruby. Не знаю, можно ли рекомендовать IDE с персональной лицензией за $249, но лично я в нее влюблен уже два года
(На сайте утверждают, что для опенсорса лицензия бесплатная)
Спасибо за статью. Очень интересно.
To Mur:
Zend Studio – поскольку в основном с PHP связан.
Спасибо, все очень понятно и доступно.
Статья просто оболденная, все понятно и доступно для простых смертных))) Прочитал с удовольсвием)))) А в данное время модифицирую плагин под jQuery , все лазил гадал , эксперементировал, а после прочтения твоей статьи сразу «врубился» что к чему)))) Спасибо большое, чувак )))))))))))
Статья просто супер.
10 балов по 5ти бальной шкале
Всё просто и понятно
а если всетаки использовать $
то как я понял можно вместо
jQuery.fn.zebra = function()
{
// тут мы разместим код плагина
};
написать
(function($)
{
$.fn.zebra = function()
{
// тут мы разместим код плагина
}
})(jQuery);
Да, можно.
Гиганское спасибо!!! Все статьи которые читаю тут дают такой мозговой потенциал что все остальные кто не читал где-то далеко с зади!!! Спасибо!!!
А можно ли вызывать функции плагина отдельно ? Например мне нужно обновить 1 из элементов объекта измененного данным плагином. Функция для данного действия содержится в плагине, но вот как ее вызвать отдельно…
Ответь мне пожалуйста на такой вопрос, чем функции объекта отличаются от методов?
Я вроде задал вопрос, а не просил задать мне.
Александр, я попробую на примере пояснить, чтобы в теоретические дебри не углубляться. Ну, скажем, есть такой плагин фотогалереи – FancyBox.
Приведу фрагмент JS-кода:
$.fn.fancybox.close = function() { ....... }т.е. в коде плагина присутствует анонимная функция, которая является значением свойства close объекта fancybox, который в свою очередь является свойством объекта fn… (хотел же без теории
).
В общем вызвать ее можно так:
Спасибо за неигнорирование Генадий (без сарказма). На самом деле проблему я уже решил, суть проблемы была в том, что мне нужно вызвать функцию уже существующего объекта, то есть если взять ваш пример.
a=$(‘селектор’).fancybox();
для того что бы вызвать функцию close (как мне вначале казалось) требуется конструкция вида
a.close();
а как оказалось, возвращается не объект, а массив объектов, в итоге конструкция приобрела вид
a[0].close();
Спасибо вам…
Вообще, работаю с JS дано, но только сейчас начал работать с JQuery – великолепная библиотека.
Читаю ваш блог регулярно! ))
Спасибо за статью, читал книгу Бибо и Кац, но там не так ясно и наглядно это написано, как у Вас.
Есть еще вопрос. Одно из правил, которыми мы пользуемся при написании плагина >>»всегда используйте jQuery вместо $ «.
В книге рекомендуется использовать такой способ:
(function($){
….
})(jQuery)
Мне такой способ кажется более простым (указанный в книге). Код получается короче, как следствие немного проще для восприятия.
Есть ли разница какого стиля написания кода придерживаться или и тот, и другой способ верный, и тут дело вкуса?
Скорее дело вкуса. В книге написано так, а когда я писал статью, использовал в качестве источника информацию с оф.сайта jQuery.
Здравствуйте, Геннадий. Такой вопрос, можно ли добавить этому плагину отдельные методы-функции, которые можно было бы вызывать отдельно, т.е. при объявлении строки раскрасились, а позже при нажатии на кнопку, например, заработало подсвечивание строк при наведении указателя мышки? И если можно, то как?)
т.е. как-то так:
$(«selector»).zebra();
и позже
$(«selector»).zebra.podsvetka();
Заранее благодарен.
Точнее проблема в том, что я не могу использовать this в jQuery.fn.zebra.podsvetka(), this в этой функции почему-то указывает на function(), а не на $(”selector”).
Сделайте проще – добавьте в конце плагина например:
jQuery.fn.zebraRed = function() { return this.each(function() { jQuery(this).find('tr:odd') .css('background-color', '#f00'); }); };тогда при клике скажем на какой-то кнопке, четные строки таблицы с классом aClass станут красными:
$("button").click(function(){ $('table.aClass').zebraRed(); });Хочется красоты)
Может быть есть какой-то способ?
В той же fancybox они используют такие функции ($.fn.fancybox.start, $.fn.fancybox.changeItem, $.fn.fancybox.showLoading, …), но они обращаются к объекту по селектору.
у меня задача в общем такая:
$.fn.popup(…) – инициализация
$.fn.popup.open(…) – открытие поп-апа
$.fn.popup.close(…) – закрытие поп-апа
…
Я не особо озадачивался написанием плагинов. Обычно расширяют существующее свойство fn объекта jQuery, добавляя ему свойство (в нашем случае zebra), значением которой является некоторая функция, т.е плагин. Попробуйте посмотреть рекомендации по написанию плагинов вот тут:
http://docs.jquery.com/Plugins/Authoring
В любом случае спасибо)
Решил задачу следующим образом:
$(«div»).popup({action: ‘open’, …});
либо
$(«div»).popup(‘open’);
…
Доброго времени суток.
Столкнулся с такой проблемой. Есть самописный плагин, назовем его Tree (в принципе актуальна проблема и для любого другого плагина). Этот плагин подгружается в основной документ (каркас). Плагин рабочий – проверено.
Итак, имеем объект JQuery с подгруженным плагином $().Tree
В документе есть div, который используется в качестве контейнера для AJAX запросов.
После выполнения AJAX запроса, в div помещается результат (кусок HTML) .
// Загрузка обработанного содержимого промежуточного контейнера в основной бизнес контейнер
$(‘#’+this._targetCont).empty();
document.getElementById(this._targetCont).innerHTML = content.innerHTML;
Далее весь div с помощью метода clone() кланируется и помещается в хэш JS (сделано это для того, чтобы можно было реализовать кнопку historyBack).
cpGlbMenuHistory[form_name].push($(‘#main_container’).clone());
В определенный момент, мне нужно вместо текущего div вставить клонированный ранее кусок DOM (такой же div, но с другим содержимым), вот так:
$(‘#main_container’).after(cpGlbMenuHistory[form_name][0]).remove();
И вот тут то и возникает проблема. Плагин Tree становится недоступен, т.е. по-сути его больше нет в объекте $()
Вы случайно не сталкивались с такой проблемой?
Максим, если я все верно понял, суть в том, что функциональность плагина не может быть использована для элементов, которые появились в DOM после инициализации плагина. Те элементы, с которыми была изначально связана функциональность плагина оказались удалены (замещены) элементами, которые появились потом, т.е. выходит, что для них плагин нужно вновь инициализировать.
Вероятно дело в этом… Попробуйте посмотреть еще эту статью – Обработка событий для элементов DOM, загружаемых через ajax, в ней очень просто все объясняется…
Генадий, благодарю за столь быстрый ответ. Приведенную Вами статью я читал, но на мой взгляд здесь немного другая ситуация… Я не применяю плагин к элементам, по событию $(document).ready … На начальном этапе формирования каркаса я лишь его загрузил в HTML и соответственно проинициализировал. Далее при загрузке какой-то формы в основной контейнер (div) я его применяю к элементам DOM. С этим все ок. А вот далее происходит, то что я написал в предыдущем посте. Я вижу пока только один выход – это загрузка плагина при смене контента основного контейнера. Тогда все работает.
Возможно Вы сможете мне подсказать как переинициализировать плагин, без его повторной загрузки? Ведь, по-идее, загруженный в каркас (основной HTML) JS с плагином никуда не девается.
Прошу прощения Геннадий. Опечатался в Вашем имени в предыдущем посте.
Хочу еще обратить внимание, что контент в основной контейнер помещается так:
$(‘#’+this._targetCont).empty();
document.getElementById(this._targetCont).innerHTML = content.innerHTML;
При этом плагин никуда не девается.
Такой же подход работает и для historyBack, но тогда такие ьраузеры как FF и Opera теряют состояние элементов форм (сбрасывают radio, checkbox и т.д.)
Нашел еще один выход, но немного кривоватый
При инициализации каркаса сохраняем плагин в переменной.
var Plugin = $().Tree;
Далее при historyBack, делаем так:
$.fn.Tree = Plugin;
И тогда наступает счастье … но кривенько как-то
Ну, даже «кривенько» лучше, чем ничего. Вы уж извините Максим, но тут я Вам вряд ли еще что-то смогу подсказать.
Вообще очень сложно помочь, когда решаются частные задачи. Какие-то общие принципы – тут ясно, а когда конкретика, вникать глубоко надо… А это ес-но время, которого никогда не хватает
Во общем, решил проблему таким «кривеньким» путем, но чуть более универсальным. Работает, а это самое главное. Спасибо, что уделили мне время. У Вас очень хороший ресурс по JQuery
Спасибо большое за статьи которые вы пишите, и в частности за данную! Вы пишите все очень простым и понятным языком.
Было бы очень хорошо если бы предоставили информацию в структурированном виде, что бы была удобная навигация. А то например мне нужно найти статью про работу с атрибутами. Для этого я должен нажать в меню «jQuery», найти нужную страницу, а потом и нужную статью. Это не очень удобно. Вы можете сделать к примеру как на сайте visualjquery.com. А эту статью вы могли бы разбить к примеру на части:
1) Правила создания плагина.
…
n) Написание документации к плагину
Еще раз спасибо вам!!
http://www.linkexchanger.su/sitemap
Формат блога свои ограничения накладывает, да и все-таки несколько разные вещи, когда чистый перевод доков и когда пытаешься написать как можно более понятным языком. Я как раз пытаюсь писать именно в формате популярных статей. А доков и так хватает – посмотрите справа вверху, в блогролле.
Здравствуйте, хотеось бы поподробнее узнать о конструкци.
(function($){
….
})(jQuery)
Т.е (function)(object)
Она как я понял подменяет $ на jQuery.
Но хотелось бы почитать о такой конструкии, не могли бы это вкрадце объяснть или дать ссылку на документацию?
Ок, уже разобрался.
Так задаётся и исполняется анонимная функция. Во вторых скобках указываются дефолтные параметры.
Т.е
(function($){
….
})(jQuery)
Аналогично :
function myfunction($) {
…
};
myfunction(jQuery);
Скажите пожалуйста, вот в вашем примере, плагин вызывается с привязкой к селектору:
$(«selector»).zebra();
А как следует писать чтобы можно было вызывать плагин так:
$(«selector»).click(function() {
$.zebra();
});
Что-то вроде этого:
$('selector').click(function() { $('otherSelector').zebra(); });Т.е. клик по чему-нибудь инициализирует плагин для элемента(-ов), выбрвнных с помощью otherSelector.
Нет, вы меня не поняли. Я к тому, если нашему плагину zebra не нужна привязка к селектору.
Он по определению работает с таблицами, раскрашивая их строки… Т.е. можно рассматривать любой плагин, как дополнительный («самописный») метод библиотеки. Такой же как например show() или там toggle(). Методы «работают» с каким-либо набором элементов, выбираемых при помощи селекторов.
), которая просто выполняет какие-то действия, не требуя для этого никаких элементов… Типичный пример – $.ajax(options)
То, о чем говорите Вы – вспомогательная функция («условность конечно, но так принято, исторически сложилось
Натолкнулся на такую проблему.
При использовании на одной странице двух экземпляров одного плагина работает только последний.
Может я ошибаюсь?
[...] ответы Новые Лучшие 0 Прочитать статью "Как написать плагин для jQuery" и [...]
Оставьте отзыв