JQuery найти обработчики событий, зарегистрированных с объектом

475

Мне нужно найти, какие обработчики событий зарегистрированы над объектом.

Например:

$("#el").click(function() {...});
$("#el").mouseover(function() {...});

$("#el") зарегистрирован клик и мышь.

Есть ли функция, чтобы узнать это и, возможно, перебрать обработчики событий?

Если это невозможно для объекта jQuery с помощью правильных методов, возможно ли это на простом объекте DOM?

Показать ещё 1 комментарий
Теги:
dom
events

14 ответов

590
Лучший ответ

Как и в jQuery 1.8, данные событий больше не доступны из "общедоступного API" для данных. Прочитайте это сообщение в блоге jQuery. Теперь вы должны использовать это:

jQuery._data( elem, "events" );

elem должен быть HTML-элементом, а не объектом jQuery или селектором.

Обратите внимание, что это внутренняя структура 'private' и не должна изменяться. Используйте это только для целей отладки.

В более старых версиях jQuery вам может понадобиться старый метод, который:

jQuery( elem ).data( "events" );
  • 0
    отличный! Меня устраивает
  • 19
    его больше нет: bugs.jquery.com/ticket/10589
Показать ещё 15 комментариев
70

Вы можете сделать это следующим образом:

$("#el").click(function(){ alert("click");});
$("#el").mouseover(function(){ alert("mouseover"); });

$.each($("#el").data("events"), function(i, e) {
    alert(i);
});
//alerts 'click' then 'mouseover'

Если вы используете jQuery 1.4+, это будет предупреждать о том, что событие и функции связаны с ним:

$.each($("#el").data("events"), function(i, event) {
    alert(i);
    $.each(event, function(j, h) {
        alert(h.handler);
    });
});
//alerts: 
//'click'
//'function (){ alert("click"); }'
//'mouseover'
//'function(){ alert("mouseover"); }'

Вы можете играть с ним на jsFiddle здесь  

  • 2
    Это правильный ответ. Важнейший момент - вторая половина. Это помогло мне найти проблему менее чем за минуту, которая заняла бы больше часа, если бы мне пришлось перебирать весь код. Спасибо!
  • 2
    Работает с 1.4, но не в jQuery 1.8.2.
Показать ещё 1 комментарий
37

Для jQuery 1.8+ это больше не будет работать, потому что внутренние данные помещаются в другой объект.

Последний неофициальный (но работает и в предыдущих версиях, по крайней мере, в версии 1.7.2) теперь - $._data(element, "events")

Подчеркивание ( "_" ) - вот что здесь делает разницу. Внутри он вызывает $.data(element, name, null, true), последний (четвертый) параметр является внутренним ( "pvt" ).

  • 0
    $ ._ data ("body", "events") undefined $ (). jquery; «1.7.1» (пробовал 1.7.2 и 1.8.1 все время «не определено»)
  • 2
    @Michal - api.jquery.com/jQuery.data говорит, что принимает элемент, а не селектор.
Показать ещё 2 комментария
29

Бесстыдный плагин, но вы можете использовать findHandlerJS

Чтобы использовать его, вам просто нужно включить findHandlersJS (или просто скопировать и вставить необработанный код javascript to chrome console) и укажите тип события и селектор jquery для интересующих вас элементов.

В вашем примере вы можете быстро найти обработчики событий, о которых вы упомянули, выполнив

findEventHandlers("click", "#el")
findEventHandlers("mouseover", "#el")

Это то, что возвращается:

  • элемент
    Фактический элемент, в котором обработчик событий был зарегистрирован в
  • события
    Массив с информацией о обработчиках событий jquery для интересующего типа события (например, щелчок, изменение и т.д.).
    • Обработчик
      Фактический метод обработчика событий, который вы можете увидеть, щелкнув его правой кнопкой мыши и выбрав "Показать определение функции"

    • селекторного Селектор предоставил делегированные события. Он будет пуст для прямых событий.
    • цели
      Список с элементами, для которых нацелен этот обработчик событий. Например, для делегированного обработчика событий, который зарегистрирован в объекте документа и предназначен для всех кнопок на странице, это свойство отобразит все кнопки на странице. Вы можете навести их на них и увидеть, что они выделены хром.

Вы можете попробовать здесь

  • 5
    Огромное спасибо. Ни одно из других решений не сработало для меня, но это сработало!
  • 0
    Я думаю, что это должен быть принятый ответ. Это единственный, который работает для меня тоже. Это очень тщательно, так как проходит через все элементы поиска событий.
Показать ещё 1 комментарий
13

Я использую eventbug плагин для Firebug для этой цели.

  • 0
    Спасибо, отличный совет. Расширение добавляет в Firebug вкладку («События»), на которой отображаются события страницы, поэтому вы можете легко их просмотреть.
  • 11
    Кроме того, в Chrome Developer Tools есть «Прослушиватели событий» на вкладке «Элементы» и «Точки останова прослушивателей событий» на вкладке «Источники».
8

Я объединил оба решения от @jps к одной функции:

jQuery.fn.getEvents = function() {
    if (typeof(jQuery._data) == 'function') {
        return jQuery._data(this.get(0), 'events') || {};
    } else if (typeof(this.data) == 'function') { // jQuery version < 1.7.?
        return this.data('events') || {};
    }
    return {};
};

Но будьте осторожны, эта функция может возвращать только те события, которые были установлены с помощью самого jQuery.

6

Начиная с версии 1.9 нет документального способа получения событий, кроме использования плагина Migrate для восстановления старого поведения. Вы можете использовать метод _.data(), как упоминает jps, но это внутренний метод. Так что просто делайте правильно и используйте плагин Migrate, если вам нужна эта функциональность.

Из документации jQuery по .data("events")

До 1.9, data ( "events" ) можно использовать для извлечения jQuery's недокументированная внутренняя структура данных событий для элемента, если нет другого код определил элемент данных с именем "события". Этот специальный случай был удален в 1.9. Нет никакого открытого интерфейса для извлечения эта внутренняя структура данных, и она остается недокументированной. Однако, плагин jQuery Migrate восстанавливает это поведение для кода, который зависит на нем.

  • 0
    Принятый ответ также ясно показывает новый, правильный способ его получения для последних версий: jQuery._data( elem, "events" ); ...
  • 1
    Частный, недокументированный способ никогда не будет правильным . Правильный путь - то есть документированный, публичный и предполагаемый - это использовать плагин Migrate.
Показать ещё 4 комментария
3

В современном браузере с ECMAScript 5.1/ Array.prototype.map вы также можете использовать

jQuery._data(DOCUMENTELEMENT,'events')["EVENT_NAME"].map(function(elem){return elem.handler;});

в консоли браузера, который будет печатать источник обработчиков с разделителями-запятыми. Полезно для просмотра того, что все работает на конкретном событии.

  • 0
    jQuery._data('ct100_ContentPlaceHolder1_lcsSection','events')["EVENT_NAME"].map(function(elem){return elem.handler;}); Uncaught TypeError: Невозможно прочитать свойство 'EVENT_NAME' с неопределенным значением <anonymous>: 1: 62
  • 0
    'ct100_ContentPlaceHolder1_lcsSection' является строкой, а не элементом DOM.
2

Я создал настраиваемый селектор jQuery, который проверяет как кеш jQuery назначенных обработчиков событий, так и элементы, которые используют собственный метод для их добавления:

(function($){

    $.find.selectors[":"].event = function(el, pos, match) {

        var search = (function(str){
            if (str.substring(0,2) === "on") {str = str.substring(2);}
            return str;
        })(String(match[3]).trim().toLowerCase());

        if (search) {
            var events = $._data(el, "events");
            return ((events && events.hasOwnProperty(search)) || el["on"+search]);
        }

        return false;

    };

})(jQuery);

Пример:

$(":event(click)")

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

2

Я должен сказать, что многие из ответов интересны, но в последнее время у меня была аналогичная проблема, и решение было чрезвычайно простым, перейдя по пути DOM. Это другое, потому что вы не итерации, а нацелитесь непосредственно на нужное вам событие, но ниже я дам более общий ответ.

У меня было изображение подряд:

<table>
  <td><tr><img class="folder" /></tr><tr>...</tr></td>
</table>

И к этому изображению прикреплен обработчик события клика:

imageNode.click(function () { ... });

Мое намерение состояло в том, чтобы развернуть область с кликами на всю строку, поэтому я сначала получил все изображения и относительные строки:

tableNode.find("img.folder").each(function () {
  var tr;

  tr = $(this).closest("tr");
  // <-- actual answer
});

Теперь в реальной строке anwer я просто сделал следующее, давая ответ на исходный вопрос:

tr.click(this.onclick);

Итак, я извлек обработчик событий непосредственно из элемента DOM и поместил его в обработчик события jQuery click. Работает как шарм.

Теперь, в общем случае. В старые дни до jQuery вы можете получить все события, привязанные к объекту, с двумя простыми, но мощными функциями, подаренными нам смертными Дугласом Крокфордом:

function walkTheDOM(node, func)
{
  func(node);
  node = node.firstChild;
  while (node)
  {
    walkTheDOM(node, func);
    node = node.nextSibling;
  }
}

function purgeEventHandlers(node)
{
  walkTheDOM(node, function (n) {
    var f;

    for (f in n)
    {
      if (typeof n[f] === "function")
      {
        n[f] = null;
      }
    }
  });
}
2

События могут быть получены с помощью:

jQuery(elem).data('events');

или jQuery 1.8 +:

jQuery._data(elem, 'events');

Примечание: События, ограниченные использованием $('selector').live('event', handler) могут быть получены с помощью:

jQuery(document).data('events')
  • 1
    jQuery (документ) .data ('события') дает мне неопределенный
1

Другой способ сделать это - просто использовать jQuery для захвата элемента, а затем перейти через фактический Javascript для получения и установки и воспроизведения с обработчиками событий. Например:

var oldEventHandler = $('#element')[0].onclick;
// Remove event handler
$('#element')[0].onclick = null;
// Switch it back
$('#element')[0].onclick = oldEventHandler;
  • 1
    Я думаю, что jQuery выполняет оптимизацию обработки событий, которая, как мне кажется, обходится вашим кодом здесь.
  • 0
    Спасибо, да, у меня было чувство, что это взломано - есть ли хорошая ссылка, чтобы узнать больше об этой оптимизации?
Показать ещё 1 комментарий
0

Чтобы проверить события на элементе:

var events = $._data(element, "events")

Обратите внимание, что это будет работать только с обработчиками прямых событий, если вы используете $ (document).on("event-name", "jq-selector", function() {//logic}), вы захотите увидеть Функция getEvents в нижней части этого ответа

Например:

 var events = $._data(document.getElementById("myElemId"), "events")

или

 var events = $._data($("#myElemId")[0], "events")

Полный пример:

<html>
    <head>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" type="text/javascript"></script>
        <script>
            $(function() {
                $("#textDiv").click(function() {
                    //Event Handling
                });
                var events = $._data(document.getElementById('textDiv'), "events");
                var hasEvents = (events != null);
            });
        </script>
    </head>
    <body>
        <div id="textDiv">Text</div>
    </body>
</html>

Более полный способ проверки, включающий динамические слушатели, установленный с помощью $ (document).on

function getEvents(element) {
    var elemEvents = $._data(element, "events");
    var allDocEvnts = $._data(document, "events");
    for(var evntType in allDocEvnts) {
        if(allDocEvnts.hasOwnProperty(evntType)) {
            var evts = allDocEvnts[evntType];
            for(var i = 0; i < evts.length; i++) {
                if($(element).is(evts[i].selector)) {
                    if(elemEvents == null) {
                        elemEvents = {};
                    }
                    if(!elemEvents.hasOwnProperty(evntType)) {
                        elemEvents[evntType] = [];
                    }
                    elemEvents[evntType].push(evts[i]);
                }
            }
        }
    }
    return elemEvents;
}

Пример использования:

getEvents($('#myElemId')[0])
0

Попробуйте использовать juggery debugger plugin, если вы используете хром: https://chrome.google.com/webstore/detail/jquery-debugger/dbhhnnnpaeobfddmlalhnehgclcmjimi?hl=en

Ещё вопросы

Сообщество Overcoder
Наверх
Меню