2012-03-27 2 views
0

У меня есть класс div MyClass Я хочу подключить до двух обработчиков. Этот класс генерируется динамически, и это то, что я делаю:jquery, задающий порядок обработчиков

$('#MainDiv').on({ 
click: function() { Handler1($(this)); } 
}, '.MyClass'); 

$('#SpecialChildDiv').on({ 
click: function() { Handler2($(this)); } 
}, '.MyClass'); 

Как контролировать, какой обработчик вызывается в первую очередь? Handler2 делает некоторые дополнительные работы, но он не вызывается для каждого MyClass, потому что его нет в SpecialChildDiv. Я хочу, чтобы обработчик 2 назывался AFTER Handler1.

Спасибо.

+0

Это два разных обработчика ... Я не уверен, что вы просите ... – Neal

+0

Прошу прощения, но что такое '' .myClass'', должно быть, там происходит в конце? http://api.jquery.com/on/ – Blazemonger

+0

Я подозреваю, что это работает изнутри. –

ответ

1

Поскольку SpecialChildDiv предположительно является потомком MainDiv, он будет называться первым. Это происходит потому, что событие пузырится от цели и вызывает обработчики, найденные вдоль пути вверх в этом порядке.

Одним из возможных вариантов было бы сделать вызов Handler2 в SpecialChildDivобработчика асинхронного с помощью setTimeout.

$('#MainDiv').on({ 
    click: function() { 
     Handler1($(this)); 
    } 
}, '.MyClass'); 

$('#SpecialChildDiv').on({ 
    click: function() { 
     setTimeout($.proxy(function() { 
      Handler2($(this)); 
     }, this), 0); 
    } 
}, '.MyClass'); 

Таким образом, сам обработчик будет вызываться сразу, но ваша Handler2 функция не будет работать до тех пор, после того, как Handler1 был вызван.

Я также использовал $.proxy, чтобы сохранить правильное значение this в функции, которую вы передаете, до setTimeout.


Немного не по теме, но вы можете сделать свой код понятнее, если вы измените Handler1 и Handler2 так что this является ссылкой на элемент, вместо того, чтобы передать его в качестве аргумента ...

$('#MainDiv').on({ 
    click: Handler1 
}, '.MyClass'); 

$('#SpecialChildDiv').on({ 
    click: function() { 
     setTimeout($.proxy(Handler2, this), 0); 
    } 
}, '.MyClass'); 

Вам нужно всего лишь сделать $(this) внутри своих функций, чтобы обернуть элемент в объект jQuery. Хотя это может быть не полезно, если есть другие аргументы.


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

высыхать код, вы можете создать фабрику для обработчиков клик ...

function async_handler_factory(the_handler) { 
    return function() { 
     setTimeout($.proxy(function() { 
      the_handler($(this)); 
     }, this), 0); 
    }; 
} 

... затем использовать его как это ...

$('#MainDiv').on({ 
    click: Handler1 
}, '.MyClass'); 

$('#SpecialChildDiv').on({ 
    click: async_handler_factory(Handler2) 
}, '.MyClass'); 

$('#AnotherChildDiv').on({ 
    click: async_handler_factory(Handler3) 
}, '.MyClass'); 

Так что это такой же принцип. Просто передайте свою HandlerN функции на async_handler_factory, и она создаст и вернет функцию обработчика click, которая делает то же самое, что и мой исходный код, вызвав HandlerN в setTimeout.


Просто, чтобы избежать путаницы о $.proxy, вот обновленная версия, которая устраняет его.

function async_handler_factory(the_handler) { 
    return function() { 
     var self = this; 
     setTimeout(function() { 
      the_handler($(self)); 
     }, 0); 
    }; 
} 

Это показывает, что это на самом деле setTimeout, что делает вашу работу решения.


EDIT: Если бы другое имя для async_handler_factory в разных местах. Исправлена.

+1

Ребята, которые построили jquery, действительно думали обо всем !! Спасибо, что ознакомили меня с этой функцией прокси! – frenchie

+0

@frenchie: Добро пожаловать. Да, '$ .proxy' пригодится, и я думаю, что это немного лучше, чем делать' var self = this; 'then' Handler2 ($ (self));' –

+0

Я просто что-то подумал: есть ли способ заставить его работать наоборот? Другими словами, вместо использования функции прокси в SpecialChildDiv работать с MainDiv? На самом деле существует несколько разных SpecialChildDiv, и я хочу избежать проблемы прокси для каждого случая. – frenchie

0

Так не называют второй по нажатию - назвать это после того, как первый обработчик выполняется:

$('#MainDiv').on({ 
    click: function (e) { 
     Handler1($(this)); 
     if ($(e.target).attr('id')==="SpecialChildDiv") { 
      specialChildClick(); 
     } 
    } 
}, '.MyClass'); 

specialChildClick = function() { 
    Handler2($('#SpecialChildDiv')); 
} 
+0

Да, я думал об этом, но в моем случае это грязно. MyClass на самом деле является датой в пользовательском календаре, и я хочу, чтобы логика календаря была отделена от логики другого элемента управления, использующего календарь. – frenchie

Смежные вопросы