Tag Archives: jQuery
Расширение базового функционала jquery-ui-виджетов
Захотелось сделать более правильную работу с триггерением/навешиванием обработчиков на события, чем это реализовано в jquery-ui. При этом сам функционал надоело копировать из виджета в виджет. В общем, вот простой добавить методы к своим виджетам:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
(function( $ ) { "use strict"; /** * расширение базового функционала jquery-ui */ $.widget( "my.my_extension", { _triggerSmart: function( EventName, Data ) { var me = this; var $me = $( me.element ); $me.trigger( EventName + '.' + me.widgetName, Data ); return me; }, _bindSmart: function( EventName, Handler ) { var me = this; var $me = $( me.element ); // боремся с повторным навешиванием обработчика var events = $.data( $me.get( 0 ), 'events' ); var filteredEvents = []; if ( EventName in events ) { filteredEvents = $.grep( events[EventName], function( Event ) { return Event.type == EventName && Event.namespace == me.widgetName; } ); } if ( ! filteredEvents.length ) { $me.bind( EventName + '.' + me.widgetName, Handler ); } return me; } } ); }( jQuery )); |
Потом для каждого виджета нужно будет указать опциональный второй параметр
1 2 3 4 5 |
$.widget( "my.fast_search", $.my.my_extension, { options: { ... |
Внимание нужно обратить на второй параметр $.my.my_extension, который в …
Как бороться с повторным добавлением обработчика события в jQuery
Нужно было навешивать и снимать обработчик клика динамически, при этом не затронув чужие обработчики, а их на элементе несколько, каждый ставится своим виджетом. Мой jQuery-ui-виджет навешивает клик только если его ещё нет. Для этого сделан отдельный метод:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
_bindClick: function() { var me = this; var $me = $( me.element ); // боремся с повторным навешиванием обработчика var events = $.data( $me.get(0), 'events' ); var filteredEvents = []; if ( 'click' in events ) { filteredEvents = $.grep( events.click, function( Event ) { return Event.type == 'click' && Event.namespace == me.widgetName; } ); } if ( filteredEvents.length ) { return; } $me.bind( 'click.' + me.widgetName, function( Event ) { // логика клика, к примеру: if ( ! me.options.allowDoubleClick ) { $me.unbind( 'click.' + me.widgetName ); } } ); }, //===========================================================================}}} |
Работа с событиями в jQuery 1.7
В jQuery 1.7 добавили .on() и .off() для единообразия работы с событиями. bind, live и delegate могли вести себя непредсказуемо при использовании вместе. Например, $(document).unbind(‘click’) убирал все live(‘click’)-события со всего документа. Новое API событий .on() and .off() призвано как-то унифицировать систему создания обработчиков событий: Старое API Новое API $(elems).bind(events, fn) $(elems).on(events, fn) $(elems).bind(events, { mydata: 42 }, …
jQuery.deferred
В jQuery 1.5 была полностью переработана модель асинхронных запросов. Теперь они возвращают deferred-объект, содержащий promise-объект, который содержит методы, позволяющие узнать состояние запроса или навесить дополнительные обработчики. promise-Объект содержит методы then, done, fail, isResolved и isRejected. Суть нового подхода состоит в следующем:
1 2 3 4 5 6 7 |
$.when($.ajax("/page1.php"), $.ajax("/page2.php")).done(function(a1, a2){ // a1 и a2 - аргументы, отвечающие соответственно за запросы к страницам page1 и page2 var jqXHR = a1[2]; /* массив состоит из [ "success", statusText, jqXHR ] */ if ( /Оппа!/.test(jqXHR.responseText) ) { alert("Где-то на первой странице есть 'Оппа!'."); } }); |
$.when принимает deferred-объект или объекты и возвращает promise-объект. Можно делать и так:
1 2 3 4 5 6 7 8 9 10 11 12 |
var $promise; if ( tt == 1 ) { $promise = $.when( $.getJSON( ... ) ); } else if ( tt == 2 ) { $promise = $.when( $.getJSON( ... ), $.getJSON( ... ), $.post( ... ) ); } else { $promise = $.when( console.log( 'else' ) ); } $promise. then( function() { console.log( 'done', data ) } ); |
…
jQuery.delegate
jQuery.delegate и jQuery.undelegate появились в jQuery 1.4.2. Это аналоги .live и .die(). У .live и .die() есть проблемы с, к примеру, вложенными объектами, с встраиванием в цепочки и много ещё. Синтаксис .delegate отличается от .live и, соответственно, .click и т.п. Пример использования:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Using .live() $("table").each(function(){ $("td", this).live("hover", function(){ $(this).toggleClass("hover"); }); }); // Using .die() $("table").each(function(){ $("td", this).die("hover"); }); // Using .delegate() $("table").delegate("td", "hover", function(){ $(this).toggleClass("hover"); }); // Using .undelegate() $("table").undelegate("td", "hover"); |
http://api.jquery.com/delegate/ Работа с событиями в jQuery 1.7+
Работа с событиями в jQuery-ui
Если нужно из виджета стриггерить событие, это сделать это можно двумя способами:
1 |
this.element.trigger( 'my_event_element', { option1: true } ); |
1 |
this._trigger( '_my_event_widget', null, { option1: true } ); |
Допустим, что наш виджет называется MyCoolWidget. Тогда поймать наши события можно так:
1 2 3 4 |
$( '#div' ).MyCoolWidget(); $( '#div' ). bind( 'my_event_element', function( Event, Ui ) { console.dir( Ui ) } ). bind( 'mycoolwidget_my_event_widget', function( Event, Ui ) { console.dir( Ui ) } ); |
Обратите внимание на второй bind — префиксом к событию в этом случае явлется название виджета в нижнем регистре. Кстати, есть ещё один способ обработать событие от this._trigger — …
Способ узнать, какие события забиндены на элементе в jQuery
1 |
console.log( $( selector ).data('events') ); |
Выдаст все события, которые слушаются обработчиками на элементе.
jQuery templates (расширение jQuery, шаблонизатор)
Всё достаточно просто.
1 2 3 4 5 6 |
$.getJSON( me.options.urlMoreResults ) .success( function( Answer ) { $( '#my-tmpl' ).tmpl( Answer ); } ); |
Шаблон:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<script id="my-tmpl" type="text/x-jquery-tmpl"> <div> {{if songs}} <ul class="song-list"> {{each songs}} <li> <a class="play js-play" href="javascript:void(0);" data-song="${$value.id}"></a> </li> {{/each}} </ul> {{/if}} {{if description}} <div class="description"> <a href="${url}/about" target="_blank"> ${description} </a> </div> {{/if}} </div> </script> |
http://api.jquery.com/category/plugins/templates/ http://habrahabr.ru/blogs/jquery/112843/ http://habrahabr.ru/blogs/jquery/113672/
jQuery — обработка событий с использованием Namespaced Events
Часто события навешиваются на элементы так:
1 |
$('.class').bind('click', function(){}); |
А когда нужно снять обработчик события с элемента, то делается это так:
1 |
$('.class').unbind('click'); |
При этом слетят все обработчики события click с элемента. Можно снимать только конкретный обработчик, но это не очень удобно. Гораздо удобнее группировать обработчики в неймспэйсы по функциональности, а потом снимать обработчики всего неймспэйса:
1 2 3 4 |
$('.class').bind('click.namespace', function(){}); $('.class').bind('click.namespace', function(){}); $('.class').trigger('click.namespace'); $('.class').unbind('click.namespace'); |
При …
Передача параметров с сервера к jQuery. Продвинутый способ.
Старый способ передачи параметров с сервер-сайда на клиент-сайд для jQuery обычно выглядел так:
1 |
<div class="my-class" property1="prop1-value" property2="prop2-value">текст</div> |
Потом в скрипте можно было обращаться к свойствам DOM-элемента
1 |
var property1Initial = $( ".my-class" ).attr( "property1" ); |
Есть более интересный способ, использующий jQuery data:
1 |
<div class="my-class" data-property1="prop1-value" data-property2="prop2-value">текст</div> |
В скрипте можно обратиться к этим свойствам так:
1 |
var property1Initial = $( ".my-class" ).data().property1; |