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

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

Например:

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

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

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

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

Ответ 1

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

jQuery._data( elem, "events" );

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

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

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

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

Ответ 2

Вы можете сделать это, просматривая события (начиная с jQuery 1. 8+), например так:

$.each($._data($("#id")[0], "events"), function(i, event) {
  // i is the event type, like "click"
  $.each(event, function(j, h) {
    // h.handler is the function being called
  });
});

Вот пример, с которым вы можете поиграть:

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

  $.each($._data($("#el")[0], "events"), function(i, event) {
    output(i);
    $.each(event, function(j, h) {
        output("- " + h.handler);
    });
  });
});

function output(text) {
    $("#output").html(function(i, h) {
        return h + text + "<br />";
    });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="el">Test</div>
<code>
    <span id="output"></span>
</code>

Ответ 3

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

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

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

Ответ 4

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

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

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

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

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

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

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

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

Ответ 5

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

Ответ 6

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

Ответ 7

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

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

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

Ответ 8

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

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

Ответ 9

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

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

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

Ответ 10

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

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])

Ответ 11

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

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

или jQuery 1.8 +:

jQuery._data(elem, 'events');

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

jQuery(document).data('events')

Ответ 12

Я должен сказать, что многие из ответов интересны, но в последнее время у меня была аналогичная проблема, и решение было чрезвычайно простым, перейдя по пути 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;
      }
    }
  });
}

Ответ 14

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

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

Ответ 15

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

var element = $("#some-element");

// sample event handlers
element.on("mouseover", function () {
  alert("foo");
});

$(".parent-element").on("mousedown", "span", function () {
  alert("bar");
});

$(document).on("click", "span", function () {
  alert("xyz");
});

var collection = element.parents()
  .add(element)
  .add($(document));
collection.each(function() {
  var currentEl = $(this) ? $(this) : $(document);
  var tagName = $(this)[0].tagName ? $(this)[0].tagName : "DOCUMENT";
  var events = $._data($(this)[0], "events");
  var isItself = $(this)[0] === element[0]
  if (!events) return;
  $.each(events, function(i, event) {
    if (!event) return;
    $.each(event, function(j, h) {
      var found = false;        
      if (h.selector && h.selector.length > 0) {
        currentEl.find(h.selector).each(function () {
          if ($(this)[0] === element[0]) {
            found = true;
          }
        });
      } else if (!h.selector && isItself) {
        found = true;
      }

      if (found) {
        console.log("################ " + tagName);
        console.log("event: " + i);
        console.log("selector: '" + h.selector + "'");
        console.log(h.handler);
      }
    });
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="parent-element">
  <span id="some-element"></span>
</div>