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;
}
}
});
}
Ответ 13
Попробуйте использовать juggery debugger plugin, если вы используете хром: https://chrome.google.com/webstore/detail/jquery-debugger/dbhhnnnpaeobfddmlalhnehgclcmjimi?hl=en
Ответ 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>