обработчики событий jQuery find, зарегистрированные в объекте

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

например:

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

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

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

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

14 ответов


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

jQuery._data( elem, "events" );

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

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

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

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

Вы можете сделать это так:

$("#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 здесь


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

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

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


промоушен, но вы можете использовать findHandlerJS

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

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

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

Это то, что получает вернулся:

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

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


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


Я объединил оба решения от @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.


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

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

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


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

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

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


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

у меня было изображение в ряд:

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

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

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;
      }
    }
  });
}

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

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

или jQuery 1.8+:

jQuery._data(elem, 'events');

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

jQuery(document).data('events')

Я создал пользовательский селектор 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)")

это вернет элементы, которые имеют обработчик щелчка, прикрепленный к ним.


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

var oldEventHandler = $('#element')[0].onclick;
// Remove event handler
$('#element')[0].onclick = null;
// Switch it back
$('#element')[0].onclick = oldEventHandler;

попробуйте плагин отладчика jquery, если вы используете chrome: https://chrome.google.com/webstore/detail/jquery-debugger/dbhhnnnpaeobfddmlalhnehgclcmjimi?hl=en


для проверки событий на элементе:

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>

A более полный способ проверки, включающий динамические прослушиватели, установленные с помощью $(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])