Мне нужно найти, какие обработчики событий зарегистрированы над объектом.
Например:
$("#el").click(function() {...});
$("#el").mouseover(function() {...});
$("#el")
зарегистрирован клик и мышь.
Есть ли функция, чтобы узнать это и, возможно, перебрать обработчики событий?
Если это невозможно для объекта jQuery с помощью правильных методов, возможно ли это на простом объекте DOM?
Как и в jQuery 1.8, данные событий больше не доступны из "общедоступного API" для данных. Прочитайте это сообщение в блоге jQuery. Теперь вы должны использовать это:
jQuery._data( elem, "events" );
elem
должен быть HTML-элементом, а не объектом jQuery или селектором.
Обратите внимание, что это внутренняя структура 'private' и не должна изменяться. Используйте это только для целей отладки.
В более старых версиях 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"); }'
Для jQuery 1.8+ это больше не будет работать, потому что внутренние данные помещаются в другой объект.
Последний неофициальный (но работает и в предыдущих версиях, по крайней мере, в версии 1.7.2) теперь -
$._data(element, "events")
Подчеркивание ( "_" ) - вот что здесь делает разницу. Внутри он вызывает $.data(element, name, null, true)
, последний (четвертый) параметр является внутренним ( "pvt" ).
Бесстыдный плагин, но вы можете использовать findHandlerJS
Чтобы использовать его, вам просто нужно включить findHandlersJS (или просто скопировать и вставить необработанный код javascript to chrome console) и укажите тип события и селектор jquery для интересующих вас элементов.
В вашем примере вы можете быстро найти обработчики событий, о которых вы упомянули, выполнив
findEventHandlers("click", "#el")
findEventHandlers("mouseover", "#el")
Это то, что возвращается:
Вы можете попробовать здесь
Я использую 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 нет документального способа получения событий, кроме использования плагина Migrate для восстановления старого поведения. Вы можете использовать метод _.data(), как упоминает jps, но это внутренний метод. Так что просто делайте правильно и используйте плагин Migrate, если вам нужна эта функциональность.
Из документации jQuery по .data("events")
До 1.9, data ( "events" ) можно использовать для извлечения jQuery's недокументированная внутренняя структура данных событий для элемента, если нет другого код определил элемент данных с именем "события". Этот специальный случай был удален в 1.9. Нет никакого открытого интерфейса для извлечения эта внутренняя структура данных, и она остается недокументированной. Однако, плагин jQuery Migrate восстанавливает это поведение для кода, который зависит на нем.
jQuery._data( elem, "events" );
...
В современном браузере с ECMAScript 5.1/ Array.prototype.map
вы также можете использовать
jQuery._data(DOCUMENTELEMENT,'events')["EVENT_NAME"].map(function(elem){return elem.handler;});
в консоли браузера, который будет печатать источник обработчиков с разделителями-запятыми. Полезно для просмотра того, что все работает на конкретном событии.
jQuery._data('ct100_ContentPlaceHolder1_lcsSection','events')["EVENT_NAME"].map(function(elem){return elem.handler;});
Uncaught TypeError: Невозможно прочитать свойство 'EVENT_NAME' с неопределенным значением <anonymous>: 1: 62
'ct100_ContentPlaceHolder1_lcsSection'
является строкой, а не элементом DOM.
Я создал настраиваемый селектор 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)")
Это приведет к возврату элементов, к которым прикреплен обработчик кликов.
Я должен сказать, что многие из ответов интересны, но в последнее время у меня была аналогичная проблема, и решение было чрезвычайно простым, перейдя по пути 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;
}
}
});
}
События могут быть получены с помощью:
jQuery(elem).data('events');
или jQuery 1.8 +:
jQuery._data(elem, 'events');
Примечание:
События, ограниченные использованием $('selector').live('event', handler)
могут быть получены с помощью:
jQuery(document).data('events')
Другой способ сделать это - просто использовать jQuery для захвата элемента, а затем перейти через фактический Javascript для получения и установки и воспроизведения с обработчиками событий. Например:
var oldEventHandler = $('#element')[0].onclick;
// Remove event handler
$('#element')[0].onclick = null;
// Switch it back
$('#element')[0].onclick = oldEventHandler;
Чтобы проверить события на элементе:
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])
Попробуйте использовать juggery debugger plugin, если вы используете хром: https://chrome.google.com/webstore/detail/jquery-debugger/dbhhnnnpaeobfddmlalhnehgclcmjimi?hl=en
var events = (jQuery._data || jQuery.data)(elem, 'events');