jQuery는 객체에 등록 된 이벤트 핸들러를 찾습니다.


555

객체에 등록 된 이벤트 핸들러를 찾아야합니다.

예를 들면 다음과 같습니다.

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

$("#el")클릭 하고 마우스 오버 등록.

그것을 알아 내고 이벤트 처리기를 반복 할 수있는 기능이 있습니까?

적절한 메소드를 통해 jQuery 객체에서 가능하지 않은 경우 일반 DOM 객체에서 가능합니까?


5

2
jQuery 사전 및 사후 1.8 모두 지원 :var events = (jQuery._data || jQuery.data)(elem, 'events');
oriadam

2
FF 및 Chrome dev-tools (F12)를 사용하여 이러한 이벤트 리스너를 볼 수 있습니다. 참조 developers.google.com/web/tools/chrome-devtools/debug/...developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/...
oriadam

답변:


691

jQuery 1.8부터는 이벤트 데이터를 "공용 API"에서 더 이상 사용할 수 없습니다. 이 jQuery 블로그 게시물을 읽으십시오 . 이제 이것을 대신 사용해야합니다.

jQuery._data( elem, "events" );

elem jQuery 객체 또는 선택자가 아닌 HTML 요소 여야합니다.

내부 '비공개'구조이므로 수정해서는 안됩니다. 디버깅 목적으로 만 사용하십시오.

이전 버전의 jQuery에서는 다음과 같은 이전 방법을 사용해야합니다.

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

222
하지만 여전히 사용할 수 있습니다 $._data($(elem).get(0), "events")
bullgare

10
blog.jquery.com/2011/11/08/building-a-slimmer-jquery .data ( "events") : jQuery는 이벤트 관련 데이터를 각 요소의 (대기 중) 이벤트라는 데이터 객체에 저장합니다. 이것은 내부 데이터 구조이므로 1.8에서는 사용자 데이터 네임 스페이스에서 제거되므로 동일한 이름의 항목과 충돌하지 않습니다. jQuery의 이벤트 데이터는 여전히 jQuery._data (element, "events")를 통해 액세스 할 수 있지만, 이는 문서화되지 않았으며 수정해서는 안되는 내부 데이터 구조입니다.
Sam Greenhalgh

이 방법을 사용하여 버튼의 클릭 이벤트를 시도했습니다. Chrome 콘솔 handler: function () {에서 클릭 속성 내부에 표시되었습니다. 함수의 전체 내용을 확장하고 표시하려면 함수 부분을 두 번 클릭해야했습니다.
Jim

@ jim yeaaah, 더블 클릭이 답입니다
Adib Aroui

2
두 옵션을 완벽하게 지원합니다 :var events = (jQuery._data || jQuery.data)(elem, 'events');
oriadam

84

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>


2
이것이 정답입니다. 결정적인 부분은 후반입니다. 이를 통해 모든 코드를 검색해야하는 경우 1 시간 이상 걸리는 문제를 찾는 데 도움이되었습니다. 감사합니다!
Andrew Ensley

2
1.4에서는 작동하지만 jQuery 1.8.2에서는 작동하지 않습니다.
Timo Kähkönen 2016

15
jQuery를 1.8 이상 들어 있어야합니다 '개인 정보'방법을 사용하십시오 jQuery._data( jQuery("#el")[0], "events" );대신 '공공 데이터'방법을 : jQuery("#el").data("events"). events객체가 실제로 저장되어 있지 않은 .data()오랜 시간 동안, 우리는 "공개 API '에서이"프록시 "를 제거하여 코드의 몇 바이트에서 손질
gnarf

36

jQuery 1.8 이상에서는 내부 데이터가 다른 객체에 배치되므로 더 이상 작동하지 않습니다.

최신 비공식 (그러나 이전 버전에서도 작동하지만 적어도 1.7.2에서는 작동) 방식은 다음과 같습니다. $._data(element, "events")

밑줄 ( "_")이 여기서 차이를 만듭니다. 내부적으로는 호출 중이며 $.data(element, name, null, true)마지막 (4 번째) 매개 변수는 내부 매개 변수 ( "pvt")입니다.


$ ._ data ( "body", "events") undefined $ (). jquery; "1.7.1"(1.7.2 및 1.8.1 모든 시간 "미등록"을 시도)
화성 로버트슨

2
@Michal-api.jquery.com/ jQuery.data 는 선택기가 아닌 요소를 허용한다고 말합니다.
PhistucK

1
이제 잘 작동합니다 : $ ._ data ($ ( "body"). get (0), "events") 또는 더 나은 : $ ( "body"). data ( "events")!
화성 로버트슨

2
FWIW-우리가 구체적으로 문서화하지 않은 매개 변수를 사용하여 다른 데이터 함수를 '내부적으로'호출한다고 지적하면 필요하지 않습니다. 그러나 jQuery._data( element, "events" )지금이 정보를 얻는 '올바른'방법입니다.
gnarf

34

뻔뻔한 플러그,하지만 당신은 findHandlerJS 를 사용할 수 있습니다

그것을 사용하려면 findHandlersJS 를 포함 (또는 원시 자바 스크립트 코드 를 크롬의 콘솔 창에 복사하여 붙여 넣기 )하고 관심있는 요소의 이벤트 유형과 jquery 선택기를 지정해야합니다.

예를 들어, 언급 한 이벤트 핸들러를 신속하게 찾을 수 있습니다.

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

이것이 반환되는 것입니다 :

  • element
    이벤트 핸들러가 등록 된 실제 요소
  • events
    우리가 관심있는 이벤트 유형에 대한 jquery 이벤트 핸들러에 대한 정보가있는 배열 (예 : 클릭, 변경 등)
    • handler
      마우스 오른쪽 단추로 클릭하고 함수 정의 표시를 선택하여 볼 수있는 실제 이벤트 핸들러 메소드
    • 선택기
      위임 된 이벤트에 제공되는 선택기. 직접 이벤트의 경우 비어 있습니다.
    • targets
      이 이벤트 핸들러가 대상으로하는 요소와 함께 나열하십시오. 예를 들어, 문서 객체에 등록되어 페이지의 모든 버튼을 대상으로하는 위임 된 이벤트 핸들러의 경우이 속성은 페이지의 모든 버튼을 나열합니다. 마우스를 가져 가서 크롬으로 강조 표시된 것을 볼 수 있습니다.

여기서 시도해 볼 수 있습니다


나는 그것이 대답으로 받아 들여 져야한다고 생각한다. 그것은 나에게도 효과가있는 유일한 것입니다. 이벤트를 검색하는 모든 요소를 ​​거치므로 매우 철저합니다.
Marquinho Peli

12

나는 이 목적을 위해 이벤트 버그 플러그인을 사용하여 파이어 버그를 사용 합니다.


고마워, 좋은 팁. 이 확장 프로그램은 페이지의 이벤트를 표시하는 탭을 Firebug ( "이벤트")에 추가하므로 쉽게 확인할 수 있습니다.
Gruber

11
또한 Chrome 개발자 도구의 '요소'탭 아래에 '이벤트 리스너'가 있고 '소스'탭에 '이벤트 리스너 중단 점'이 있습니다.
clayzermk1

10

@jps에서 하나의 함수로 두 솔루션을 결합했습니다.

jQuery.fn.getEvents = function() {
    if (typeof(jQuery._data) === 'function') {
        return jQuery._data(this.get(0), 'events') || {};
    }

    // jQuery version < 1.7.?
    if (typeof(this.data) === 'function') {
        return this.data('events') || {};
    }

    return {};
};

그러나이 함수는 jQuery 자체를 사용하여 설정된 이벤트 만 반환 할 수 있습니다.


5

1.9부터 Migrate 플러그인을 사용하여 이전 동작을 복원하는 것 외에는 이벤트를 검색하는 문서화 된 방법이 없습니다. jps에서 언급했듯이 _.data () 메소드를 사용할 수 있지만 내부 메소드입니다. 이 기능이 필요한 경우 올바른 작업을 수행하고 마이그레이션 플러그인을 사용하십시오.

의 jQuery 문서에서 .data("events")

1.9 이전에는 다른 코드에서 "events"라는 데이터 요소를 정의하지 않은 경우 .data ( "events")를 사용하여 요소에 대한 jQuery의 문서화되지 않은 내부 이벤트 데이터 구조를 검색 할 수있었습니다. 이 특별한 경우는 1.9에서 제거되었습니다. 이 내부 데이터 구조를 검색 할 공용 인터페이스가 없으며 문서화되지 않은 상태로 유지됩니다. 그러나 jQuery Migrate 플러그인은 종속 된 코드에 대해이 동작을 복원합니다.


허용 된 답변은 또한 최근 버전에 대한 새롭고 올바른 방법을 명확하게 보여줍니다 . jQuery._data( elem, "events" );...
Ian

2
문서화되지 않은 개인적인 방법은 결코 올바른 방법이 아닙니다. 문서화, 공개 및 의도 된 올바른 방법은 마이그레이션 플러그인을 사용하는 것입니다.
oligofren

3
Migrate 플러그인의 요점을 오해하는 것 같습니다. jQuery는 더 이상 사용되지 않는 기능을 제거했으며 Migrate 플러그인은 개발자의 코드를 최신 버전으로 마이그레이션 하여 새로운 기능과 개선 사항을 즉시 활용할 수는 있지만 기능을 잃지 않도록하는 것입니다. 새로운 버전의 jQuery를 올바르게 사용하기 위해 코더가해야 할 일을 파악할 수 있도록 돕기위한 것입니다. 프로덕션 환경에서는이 기능 을 사용 하여 기능 을 복원 해서는 안됩니다 . 또한 많은 것들이 jQuery 문서에 문서화되어 있지 않고 최신의 것으로 문서화되어 있습니다. 이전에 지적 했으므로 그 이유가 없습니다
Ian

또한 jQuery 블로그에 제안으로 포함되어 있으면 블로그를 사용하십시오. blog.jquery.com/2012/08/09/jquery-1-8-released
Ian

Migrate 플러그인에 대한 당신의 추론은 합리적입니다. 내 답변을 삭제하면 OK?
oligofren

5

요소에서 이벤트를 확인하려면 다음을 수행하십시오.

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

getEvents방법은 전반적으로 훌륭하지만 IE11에서 중복 항목을 제공합니다 (IE는 다시 알고 있지만 회사는 필요합니다 ...). 편집 : $ ._ data FF에 포함되어 있지 않더라도 요소에 대한 중복 이벤트가 포함되어 있습니다 ... 이상한 IE 세계. 그러나 중복 이벤트가 발생할 가능성에주의해야합니다.
Dominik Szymański

오, Tom, 실제로이 방법을 실행할 때마다 이벤트를 곱하는 코드입니다. 안좋다.
Dominik Szymański

4

할당 된 이벤트 핸들러의 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

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;}); 잡히지 않은 TypeError : <anonymous> : 1 : 62에 정의되지 않은 'EVENT_NAME'속성을 읽을 수 없습니다
Mike W

'ct100_ContentPlaceHolder1_lcsSection'DOM 요소가 아닌 문자열입니다.
Jesan Fafon

2

다음을 사용하여 이벤트를 검색 할 수 있습니다.

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

또는 jQuery 1.8 이상 :

jQuery._data(elem, 'events');

참고 : 다음을 사용하여 범위 $('selector').live('event', handler) 가 지정된 이벤트를 검색 할 수 있습니다.

jQuery(document).data('events')

2
jQuery (document) .data ( 'events') 나에게 정의되지 않음
Mike W

1

나는 많은 답변이 흥미 롭다고 말해야하지만 최근에는 비슷한 문제가 있었고 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 클릭 이벤트 핸들러에 넣었습니다. 매력처럼 작동합니다.

이제 일반적인 경우입니다. 이전 jQuery 이전에는 Douglas Crockford 가 우리에게 필적할만한 두 가지 간단하지만 강력한 기능을 사용하여 객체에 모든 이벤트를 첨부 할 수있었습니다 .

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


0

다른 방법은 jQuery를 사용하여 요소를 가져온 다음 실제 Javascript를 통해 이벤트 핸들러를 가져 와서 설정하고 재생하는 것입니다. 예를 들어 :

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

1
jQuery는 이벤트 처리 최적화를 수행한다고 생각합니다. 여기서 귀하의 코드로 우회한다고 생각합니다.
Emile Bergeron

고마워, 그래, 나는 이것이 해키 느낌이 들었다-그 최적화에 대해 더 배울 수있는 좋은 링크?
tempranova

0

위의 답변 중 일부를 결합하고 주어진 요소에서 대부분의 이벤트 리스너를 희망적으로 나열하는이 미친 듯하지만 기능적인 스크립트를 만들었습니다. 여기에서 자유롭게 최적화하십시오.

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>


0

jQuery는 단순히 주어진 요소에 대한 이벤트에 액세스하는 것을 허용하지 않습니다. 문서화되지 않은 내부 방법을 사용하여 액세스 할 수 있습니다

$._data(element, "events")

그러나 여전히 모든 이벤트를 제공하지는 않습니다. 정확히 지정된 이벤트는 표시하지 않습니다.

$([selector|element]).on()

이러한 이벤트는 문서 안에 저장되므로 다음을 통해 찾아 볼 수 있습니다.

$._data(document, "events")

전체 웹 페이지에 대한 이벤트가 있기 때문에 어려운 작업입니다.

위의 Tom G는 주어진 요소의 이벤트에 대해서만 문서를 필터링하고 두 메소드의 출력을 병합하는 함수를 만들었지 만 출력에서 ​​이벤트를 복제하는 데 결함이 있습니다 (요소의 jQuery 내부 이벤트 목록에서 효과적으로 응용 프로그램을 망칠 수 있음). 그 결함을 수정했으며 아래 코드를 찾을 수 있습니다. 개발자 콘솔이나 앱 코드에 붙여 넣고 주어진 요소에 대한 모든 이벤트 목록을 얻으려면 필요할 때 실행하십시오.

주목해야 할 것은 element는 실제로 jQuery 객체가 아닌 HTMLElement입니다.

function getEvents(element) {
    var elemEvents = $._data(element, "events");
    var allDocEvnts = $._data(document, "events");
    function equalEvents(evt1, evt2)
    {
        return evt1.guid === evt2.guid;
    }

    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] = [];
                    }
                    if(!elemEvents[evntType].some(function(evt) { return equalEvents(evt, evts[i]); })) {
                        elemEvents[evntType].push(evts[i]);
                    }
                }
            }
        }
    }
    return elemEvents;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.