
jquery-debounce - issue #1
Теряется контекст для обработчиков событий, привязанных к элементам через jQuery
Дим, в рамках своего кода и использования jQuery 1.3.2 я нашел в твоих функциях, в моем случае, существенный недостаток. Суть в том, что при биндинге обработчика события через обертку одной из твоих функций, в теле обработчика перестает быть доступной переменная this. Опишу на примере:
У меня есть обработчик события для hover:
<pre> var onHover = function() { $(this).addClass('hover'); }, onLeave = function() { $(this).removeClass('hover'); }; </pre>
Как известно при биндинге обработчиков jQuery контекстом выполнения функции является DOM элемент, породивший событие.
Биндинг: $('.i-have-hover').hover( onHover, onLeave );
Пример выше работает, но как только мы обернем один из обработчиков функциями throttle или debounce, то код перестанет работать из-за отсутствия контекста.
При это мы не можем указать контекст в обертке, т.к., естественно, не знаем его.
Что-то мне подсказывает, что следующий код не будет работать так, как нужно, т.к. на каждое событие throttle вернет новую функцию со своим персональным таймером.
<pre> $('.i-have-hover').hover(function() { $.throttle(onHover, 300)(); }); </pre>
Соответственно выход один: исправить ситуация в коде плагина. Тут можно пойти двумя путями:
Первый, который я реализовал и мне он больше нравится, но на данный момент у меня нет времени подумать глубже, может быть он и плох, поэтому ниже есть второй :)
И так изменения к плагину: поскольку каждая функция (throttle, debounce) возвращает указатель на вновь созданную функцию, то в теле этой новой функции я добавляю переменную ctx:
<pre> var ctx = context || this; </pre>
Она заполняется либо указанным при инициализации обретки контекстом, либо контекстом, в котором вызывают нашу обертку. Далее в вызове самой функции, которую оборачивали, я указываю контекстом выполнения переменную ctx вместо context.
Пример для throttle:
<pre> throttle: function(fn, timeout, context) { var timer;
return function() {
var args = arguments, ctx = context || this;
if (!timer) {
(function() {
if (args) {
fn.apply(ctx, args);
args = null;
timer =
setTimeout(arguments.callee, timeout); } else { timer = null; } })(); } }; } </pre>
Во втором варианте я предлагаю создать объект-хеш, в котором хранить таймеры для оборачиваемых функций. Но тут нужно подумать, я не рассматривал этот вариант глубоко.
Спасибо за внимание :)
Кстати, исправленный исходник в аттаче.
- jquery.debounce.js 1.2KB
Comment #1
Posted on Feb 24, 2010 by Happy Dog(No comment was entered for this change.)
Status: Fixed
Labels:
Type-Defect
Priority-Medium