Современный фронтенд несётся скоростным поездом, в окнах мелькают es6, es7 es2015, react, redux и куча других пассажиров. И не везде этот поезд останавливается. Но на станциях по-прежнему полно …jQuery.

И сегодня понадобилось дополнить “чужой” обработчик события (для простоты пусть будет onClick) дополнительными проверками, которые “чужим” не предусмотрен:

jQuery('element').bind('click', function() {
   if (checkIt()) {
      doIt();
   }
});

В дополнение к checkIt() необходимо позвать ещё и testIt().

В простейшем случае обработчик события может быть именованной функцией и задача становится тривиальной:

// editable "original"
function clickHandler(event) {
   if (checkIt()) {
      doIt();
   }
}
jQuery('element').bind('click', clickHandler);

// custom code

jQuery('element').unbind('click').bind(function(e) {
  if (testIt()) {
     clickHandler(e);
  }
});

Но “чужой” код изменить нельзя, а значит обработчик события останется анонимной функцией. Как до неё добраться ?

Беглый поиск по исходникам jQuery помог найти недокументированный метод jQuery._data, который поможет добраться до скрытых в его недрах обработчиков события. Несмотря на наличие комментария:

_Never_ expose “private” data to user code (TODO: Drop _data, _removeData)

в интересующей меня ветке 1.xx, методы (вместе с комментарием) перекочевали в последнюю на данный момент версию 3.1, а значит я без риска и страха использую их и даже порекомендую вам сделать тоже самое, но всё же на ваш страх и риск, в похожей небезвыходной ситуации.

И так к делу:

// original HARDcode
jQuery('element').bind('click', function() {
   if (checkIt()) {
      doIt();
   }
});

// custom code
var originalClickHandler = jQuery._data( element ).events.click[0].handler; // save handler

jQuery('element')
  .unbind('click') // remove handler
  .bind('click', function(e) {
    if (testIt()) { // wrap old handler with custom logic
      originalClickHandler(e)
    }
  });

Буду надеятся что таким чудо{вищным} методом никому больше воспользоваться не придётся.

Оборачиваем событие jQuery собственным обработчиком
Tagged on:     

Leave a Reply