動的にアタッチされるイベント・リスナーが存在するかどうかを確認するには?

動的にアタッチされたイベント・リスナーの存在をチェックすることは可能でしょうか?あるいは、DOMの"onclick"(?)プロパティの状態をチェックする方法はありますか?Stack Overflowのようにインターネットを検索してみましたが、解決策は見つかりませんでした。以下は私のhtmlです:

<a id="link1" onclick="linkclick(event)"> link 1 </a>
<a id="link2"> link 2 </a> <!-- without inline onclick handler -->

そして、Javascriptで動的に作成したイベントリスナーを2番目のリンクにアタッチします:

document.getElementById('link2').addEventListener('click', linkclick, false);

コードはうまく実行されますが、このリスナーを検出しようとすると、すべて失敗します:

// test for #link2 - dynamically created eventlistener
alert(elem.onclick); // null
alert(elem.hasAttribute('onclick')); // false
alert(elem.click); // function click(){[native code]} // btw, what's this?

[jsFiddleはこちら](https://jsfiddle.net/qv0k7Lor/)。 をクリックしてから "[リンク2]" をクリックすると、イベントはうまく発火します、 しかし、"Test link 2"は常にfalseを報告します。 誰か助けてください。

質問へのコメント (5)
ソリューション

動的にアタッチされるイベント・リスナーが存在するかどうかをチェックする方法はない。

イベント・リスナーがアタッチされているかどうかを確認する唯一の方法は、このようにイベント・リスナーをアタッチすることです:

elem.onclick = function () { console.log (1) }

イベントリスナーが onclick にアタッチされているかどうかを調べるには、!!elem.onclick(または同様のもの)を返します。

解説 (1)

私はそのようなことをしました:

const element = document.getElementById('div');

if (element.getAttribute('listener') !== 'true') {
     element.addEventListener('click', function (e) {
         const elementClicked = e.target;
         elementClicked.setAttribute('listener', 'true');
         console.log('event has been attached');
    });
}

リスナーが添付されているときに要素の特別な属性を作成し、それが存在するかどうかを確認します。

解説 (2)

最初はFALSEで、イベントをアタッチしたときにTRUEに設定されるブール値を関数の外に作成します。これは、イベントを再度アタッチする前に、ある種のフラグとして機能します。以下はその例です。

// initial load
var attached = false;

// this will only execute code once
doSomething = function() {
  if (!attached) {
    attached = true;
    //code
  }
} 

//attach your function with change event
window.onload = function() {
    var txtbox = document.getElementById("textboxID");
    if(window.addEventListener){
        txtbox.addEventListener("change", doSomething, false);
    } else if(window.attachEvent){
        txtbox.attachEvent("onchange", doSomething);
    }
}
解説 (1)

tl; dr :いいえ、ネイティブにサポートされている方法でこれを行うことはできません。

___。

これを達成するために私が知っている唯一の方法は、追加されたリスナーの記録を保持するカスタムストレージオブジェクトを作成することです。 次の線に沿った何か:

/* Create a storage object. */
var CustomEventStorage = [];

ステップ1:まず、ストレージオブジェクトをトラバースして、要素(またはfalse)を指定した要素のレコードを返すことができる関数が必要です。

/* The function that finds a record in the storage by a given element. */
function findRecordByElement (element) {
    /* Iterate over every entry in the storage object. */
    for (var index = 0, length = CustomEventStorage.length; index < length; index++) {
        /* Cache the record. */
        var record = CustomEventStorage[index];

        /* Check whether the given element exists. */
        if (element == record.element) {
            /* Return the record. */
            return record;
        }
    }

    /* Return false by default. */
    return false;
}

ステップ2:次に、イベントリスナーを追加できる機能が必要ですが、リスナーをストレージオブジェクトに挿入することもできます。

/* The function that adds an event listener, while storing it in the storage object. */
function insertListener (element, event, listener, options) {
    /* Use the element given to retrieve the record. */
    var record = findRecordByElement(element);

    /* Check whether any record was found. */
    if (record) {
        /* Normalise the event of the listeners object, in case it doesn't exist. */
        record.listeners[event] = record.listeners[event] || [];
    }
    else {
        /* Create an object to insert into the storage object. */
        record = {
            element: element,
            listeners: {}
        };

        /* Create an array for event in the record. */
        record.listeners[event] = [];

        /* Insert the record in the storage. */
        CustomEventStorage.push(record);
    }

    /* Insert the listener to the event array. */
    record.listeners[event].push(listener);

    /* Add the event listener to the element. */
    element.addEventListener(event, listener, options);
}

ステップ3:質問の実際の要件に関して、要素が指定されたイベントのイベントリスナーに追加されているかどうかを確認するには、次の機能が必要です。

/* The function that checks whether an event listener is set for a given event. */
function listenerExists (element, event, listener) {
    /* Use the element given to retrieve the record. */
    var record = findRecordByElement(element);

    /* Check whether a record was found & if an event array exists for the given event. */
    if (record && event in record.listeners) {
        /* Return whether the given listener exists. */
        return !!~record.listeners[event].indexOf(listener);
    }

    /* Return false by default. */
    return false;
}

ステップ4:最後に、ストレージオブジェクトからリスナーを削除できる関数が必要になります。

/* The function that removes a listener from a given element & its storage record. */
function removeListener (element, event, listener, options) {
    /* Use the element given to retrieve the record. */
    var record = findRecordByElement(element);

    /* Check whether any record was found and, if found, whether the event exists. */
    if (record && event in record.listeners) {
        /* Cache the index of the listener inside the event array. */
        var index = record.listeners[event].indexOf(listener);

        /* Check whether listener is not -1. */
        if (~index) {
            /* Delete the listener from the event array. */
            record.listeners[event].splice(index, 1);
        }

        /* Check whether the event array is empty or not. */
        if (!record.listeners[event].length) {
            /* Delete the event array. */
            delete record.listeners[event];
        }
    }

    /* Add the event listener to the element. */
    element.removeEventListener(event, listener, options);
}

___。

スニペット:

window.onload = function () {
  var
    /* Cache the test element. */
    element = document.getElementById("test"),

    /* Create an event listener. */
    listener = function (e) {
      console.log(e.type + "triggered!");
    };

  /* Insert the listener to the element. */
  insertListener(element, "mouseover", listener);

  /* Log whether the listener exists. */
  console.log(listenerExists(element, "mouseover", listener));

  /* Remove the listener from the element. */
  removeListener(element, "mouseover", listener);

  /* Log whether the listener exists. */
  console.log(listenerExists(element, "mouseover", listener));
};

<script src = "https://cdn.rawgit.com/angelpolitis/custom-event-storage/master/main.js"></script>


<div id = "test" style = "background:#000; height:50px; width: 50px"></div>

___。

OPが質問を投稿してから5年以上が経過しましたが、将来この回答に遭遇した人はこの回答の恩恵を受けると思いますので、提案や改善を行ってください。 😊

解説 (0)

たとえば、Chromeインスペクタを使用してEventListenerが存在するかどうかを常に手動で確認できます。 [要素]タブには、従来の[スタイル]サブタブがあり、その近くに別のサブタブがあります:[イベントリスナー]。 これにより、リンクされた要素を持つすべてのEventListenersのリストが表示されます。

解説 (0)

重複の可能性:https://stackoverflow.com/questions/28056716/check-if-an-element-has-event-listener-on-it-no-jquery/41137585。 そこで私の答えを見つけてください。

基本的に、これがChromium(Chrome)ブラウザのトリックです。

getEventListeners(document.querySelector('your-element-selector'));
解説 (0)

動的にアタッチされたイベント・リスナーの存在をチェックするために使用したスクリプトを紹介します。jQueryを使って要素にイベントハンドラをアタッチし、そのイベント(この場合は 'click'イベント)をトリガーしています。こうすることで、イベント・ハンドラがアタッチされている場合にのみ存在するイベント・プロパティを取得し、キャプチャすることができます。

var eventHandlerType;

$('#contentDiv').on('click', clickEventHandler).triggerHandler('click');

function clickEventHandler(e) {
    eventHandlerType = e.type;
}

if (eventHandlerType === 'click') {
    console.log('EventHandler "click" has been applied');
}
解説 (1)

この方法が存在しないのは奇妙に思われます。 最後に追加する時が来ました?

あなたがしたいなら、次のようなことができます(テストされていません):

var _addEventListener = EventTarget.prototype.addEventListener;
var _removeEventListener = EventTarget.prototype.removeEventListener;
EventTarget.prototype.events = {};
EventTarget.prototype.addEventListener = function(name, function, etc) {
   var events = EventTarget.prototype.events;
   if (events[name]==null) {
      events[name] = [];
   }

   if (events[name].indexOf(function)==-1) {
      events[name].push(function);
   }

   _addEventListener(name, function);
}
EventTarget.prototype.removeEventListener = function(name) {
   var events = EventTarget.prototype.events;

   if (events[name]!=null && events[name].indexOf(function)!=-1) {
      events[name].splice(events[name].indexOf(function), 1);
   }

   _removeEventListener(name, function);
}
EventTarget.prototype.hasEventListener = function(name) {
   var events = EventTarget.prototype.events;
   if (events[name]==null) {
      return false;
   }

   return events[name].length);
}
解説 (0)

追加する前にイベントを削除してください:

document.getElementById('link2').removeEventListener('click', linkclick, false);
document.getElementById('link2').addEventListener('click', linkclick, false);
解説 (0)

これを実現できるスクリプトを書きました。 2つのグローバル機能を提供します: hasEvent(Node elm、String event)getEvents(Node elm)を利用できます。 EventTargetプロトタイプメソッド add / RemoveEventListenerを変更し、HTMLマークアップまたは elm.on_event =のJavaScript構文を通じて追加されたイベントでは機能しないことに注意してください。 ...

GitHubの詳細

[ライブデモ][2]

スクリプト:

var hasEvent,getEvents;!function(){function b(a,b,c){c?a.dataset.events+=","+b:a.dataset.events=a.dataset.events.replace(new RegExp(b),"")}function c(a,c){var d=EventTarget.prototype[a+"EventListener"];return function(a,e,f,g,h){this.dataset.events||(this.dataset.events="");var i=hasEvent(this,a);return c&&i||!c&&!i?(h&&h(),!1):(d.call(this,a,e,f),b(this,a,c),g&&g(),!0)}}hasEvent=function(a,b){var c=a.dataset.events;return c?new RegExp(b).test(c):!1},getEvents=function(a){return a.dataset.events.replace(/(^,+)|(,+$)/g,"").split(",").filter(function(a){return""!==a})},EventTarget.prototype.addEventListener=c("add",!0),EventTarget.prototype.removeEventListener=c("remove",!1)}();
解説 (0)

特定の要素で登録されたイベントを検索するクロスブラウザ関数はないようです。

ただし、一部のブラウザーでは、開発ツールを使用して要素のコールバック関数を表示できます。 これは、Webページの機能を決定しようとするとき、またはコードをデバッグするときに役立ちます。

Firefox

まず、開発者ツール内の[インスペクター]タブで要素を表示します。 これは可能です:

-ページ上で、検査するWebページのアイテムを右クリックし、メニューから[要素の検査]を選択します。 -コンソール内で、 document.querySelector などの関数を使用して要素を選択し、要素の横にあるアイコンをクリックして、[インスペクター]タブで表示します。

イベントが要素に登録されている場合は、要素の横に「イベント」という単語を含むボタンが表示されます。 クリックすると、要素に登録されているイベントを確認できます。 イベントの横にある矢印をクリックすると、そのコールバック関数を表示できます。

クローム

まず、開発者ツール内の[要素]タブで要素を表示します。 これは可能です:

-ページ上で、検査するWebページのアイテムを右クリックして、メニューから[検査]を選択します。 -コンソール内関数を使用して document.querySelector などの要素を選択し、要素を右クリックして[要素のリビール]を選択し、[インスペクター]タブで表示します。

Webページの要素を含むツリーを表示するウィンドウのセクションの近くに、「イベントリスナー」というタイトルのタブがある別のセクションがあるはずです。 選択すると、要素に登録されたイベントが表示されます。 特定のイベントのコードを表示するには、その右側にあるリンクをクリックします。

Chromeでは、要素のイベントは getEventListeners 関数を使用して見つけることもできます。 ただし、私のテストでは、 getEventListeners 関数は、複数の要素が渡されたときにイベントをリストしません。 リスナーがいるページ上のすべての要素を見つけ、それらのリスナーのコールバック関数を表示する場合は、コンソールで次のコードを使用してこれを行うことができます。


var elems = document.querySelectorAll('*');

for (var i=0; i 
解説 (0)

私がよく理解している場合、リスナーがチェックされているかどうかを確認することしかできませんが、どのリスナーが特にプレゼンターであるかを確認することはできません。

したがって、一部のアドホックコードは、コーディングフローを処理するためのギャップを埋めます。 実用的な方法は、変数を使用して「状態」を作成することです。 たとえば、次のようにリスナーのチェッカーを添付します。

var listenerPresent=false

次に、リスナーを設定する場合は、値を変更します。

listenerPresent=true

次に、eventListenerのコールバック内で、特定の機能を内部に割り当てることができます。これと同じように、いくつかの状態に応じて、関数へのアクセスを変数として分散できます。例:

accessFirstFunctionality=false
accessSecondFunctionality=true
accessThirdFunctionality=true
解説 (0)

理論的には、piggyback addEventListenerとremoveEventListenerを使用して、フラグを「this」オブジェクトに削除できます。 醜いと私はテストしていません。 ...

解説 (0)

イベントが添付されているかどうかを確認して、これを見つけました。...

あなたがした場合:

item.onclick

「null」を返します。

しかし、あなたがするなら:

item.hasOwnProperty('onclick')

それが「TRUE」です。

「addEventListener」を使用してイベントハンドラーを追加する場合、それにアクセスする唯一の方法は「hasOwnProperty」を使用することだと思います。 理由や方法を知っていればいいのに、残念ながら、調査した結果、説明が見つかりませんでした。

解説 (1)