web-dev-qa-db-ja.com

動的に接続されたイベントリスナーが存在するかどうかを確認する方法

ここに私の問題があります:動的にアタッチされたイベントリスナーの存在を何らかの方法で確認することは可能ですか?または、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はこちら 。 [onclick for 2を追加]をクリックしてから[[link 2]]をクリックすると、イベントは正常に起動しますが、「Test link 2」は常にfalseを報告します。誰か助けてもらえますか?

58
Stano

動的に接続されたイベントリスナーが存在するかどうかを確認する方法はありません。

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

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

その後、!!elem.onclick(または同様のもの)を返すことにより、イベントリスナーがonclickにアタッチされているかどうかをテストできます。

33
Ivan

私がすることは、関数の外側に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);
    }
}
17
Cesar

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

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

リスナーがアタッチされたときに要素の特別な属性を作成し、存在するかどうかを確認します。

16
Karol Grabowski

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));
};
<!-- Include the Custom Event Storage file -->
<script src = "https://cdn.rawgit.com/angelpolitis/custom-event-storage/master/main.js"></script>

<!-- A Test HTML element -->
<div id = "test" style = "background:#000; height:50px; width: 50px"></div>

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

6
Angel Politis

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

5
Paul Leclerc

これは、動的に接続されたイベントリスナーの存在を確認するために使用したスクリプトです。 jQueryを使用して、イベントハンドラーを要素にアタッチし、そのイベント(この場合は「クリック」イベント)をトリガーしました。このようにして、イベントハンドラーが接続されている場合にのみ存在するイベントプロパティを取得およびキャプチャできます。

var eventHandlerType;

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

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

if (eventHandlerType === 'click') {
    console.log('EventHandler "click" has been applied');
}
3
dsmith63

重複の可能性: 要素にイベントリスナーがあるかどうかを確認します。jqueryなし 。そこで答えを見つけてください。

基本的に、Chromium(Chrome)ブラウザーのトリックは次のとおりです。

getEventListeners(document.querySelector('your-element-selector'));
3
arufian

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

GitHubの詳細

ライブデモ

スクリプト:

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
Gaurang Tandon

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

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

var listenerPresent=false

次に、リスナーを設定する場合は、値を変更するだけです。

listenerPresent=true

次に、eventListenerのコールバック内で特定の機能を内部に割り当て、これと同じ方法で、変数としての状態に応じて機能へのアクセスを分散できます。

accessFirstFunctionality=false
accessSecondFunctionality=true
accessThirdFunctionality=true
0
Webwoman

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

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

Firefox

まず、開発者ツール内のInspectorタブで要素を表示します。これを行うことができます:

  • ページで、検査するWebページ上の項目を右クリックし、メニューから[要素の検査]を選択します。
  • console内で、document.querySelectorなどの要素を選択する関数を使用して、要素の横のアイコンをクリックするInspectorタブで表示します。

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

クローム

最初に、開発者ツール内のElementsタブで要素を表示します。これを行うことができます:

  • ページで検査したいウェブページ上のアイテムを右クリックし、メニューから「検査」を選択します
  • console内で、document.querySelectorなどの要素を選択する関数を使用して、要素を右クリックして選択します。 「要素パネルで表示」をクリックして、インスペクタータブに表示します。

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

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

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

for (var i=0; i <= elems.length; i++) {
    var listeners = getEventListeners(elems[i]);

    if (Object.keys(listeners).length < 1) {
        continue;
    }

    console.log(elems[i]);

    for (var j in listeners) {
        console.log('Event: '+j);

        for (var k=0; k < listeners[j].length; k++) {
            console.log(listeners[j][k].listener);
        }
    }
}

特定のブラウザまたは他のブラウザでこれを行う方法を知っている場合は、この回答を編集してください。

0
Dave F