Подтвердить что ты не робот

Как проверить, существует ли динамически подключенный прослушиватель событий?

Вот моя проблема: возможно ли как-то проверить наличие динамически подключенного прослушивателя событий? Или как я могу проверить состояние свойства onclick (?) В DOM? Я искал интернет, как и Qaru, для решения, но не повезло. Вот мой 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 this?

jsFiddle здесь. Если вы нажмете "Добавить onclick for 2", а затем "[ссылка 2]", событие срабатывает хорошо, но "Тестовая ссылка 2" всегда сообщает ложь. Может кто-нибудь помочь?

4b9b3361

Ответ 1

Невозможно проверить, существуют ли динамически подключенные прослушиватели событий.

Единственный способ узнать, подключен ли прослушиватель событий, - это добавить прослушиватели событий следующим образом:

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

Затем вы можете проверить, подключен ли прослушиватель событий к onclick, возвращая !!elem.onclick (или что-то подобное).

Ответ 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);
    }
}

Ответ 3

Я сделал что-то вроде этого:

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

Создание специального атрибута для элемента при подключении слушателя, а затем проверки его наличия.

Ответ 4

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>

Ответ 5

Вы всегда можете проверить вручную, если ваш EventListener существует, например, с помощью инспектора Chrome. На вкладке Элемент у вас есть традиционная подкладка "Стили", а рядом с ней - "Слушатели событий". Это даст вам список всех EventListeners со связанными элементами.

Ответ 6

Здесь a script я использовал для проверки наличия динамически подключенного прослушивателя событий. Я использовал 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');
}

Ответ 8

Я только что написал script, который позволяет вам это сделать. Он дает вам две глобальные функции: hasEvent(Node elm, String event) и getEvents(Node elm), которые вы можете использовать. Имейте в виду, что он изменяет метод прототипа EventTarget add/RemoveEventListener и не работает для событий, добавленных через разметку HTML или синтаксис javascript elm.on_event = ...

Дополнительная информация в GitHub

Live Demo

Script:

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

Ответ 9

Похоже, что не существует кросс-браузерная функция, которая ищет события, зарегистрированные в данном элементе.

Тем не менее, можно просматривать функции обратного вызова для элементов в некоторых браузерах, используя их инструменты разработки. Это может быть полезно при попытке определить, как функционирует веб-страница, или для отладки кода.

Firefox

Сначала просмотрите элемент на вкладке "Инспектор" в инструментах разработчика. Это можно сделать:

  • На странице, щелкнув правой кнопкой мыши элемент на веб-странице, который вы хотите проверить, и выбрав в меню "Проверить элемент".
  • Внутри консоли используйте функцию для выбора элемента, например document.querySelector, а затем щелкните значок рядом с элементом, чтобы просмотреть его на вкладке "Инспектор".

Если какие-либо события были зарегистрированы в элементе, вы увидите кнопку, содержащую слово Event рядом с элементом. Нажав на нее, вы увидите события, которые были зарегистрированы с помощью элемента. Нажав на стрелку рядом с событием, вы можете просмотреть функцию обратного вызова для него.

Chrome

Сначала просмотрите элемент на вкладке "Элементы" в инструментах разработчика. Это можно сделать:

  • На странице, щелкнув правой кнопкой мыши на элементе на веб-странице, который вы хотите проверить, и выбрав "Проверить" в меню
  • Внутри консоли с помощью функции для выбора элемента, например document.querySelector, щелкните правой кнопкой мыши элемент и выберите "Показать в панели элементов", чтобы просмотреть его на вкладке "Инспектор".

Рядом с разделом окна, в котором отображается дерево, содержащее элементы веб-страницы, должен быть еще один раздел с вкладкой, озаглавленной "Прослушиватели событий". Выберите его, чтобы увидеть события, которые были зарегистрированы для элемента. Чтобы просмотреть код для данного события, нажмите ссылку справа от него.

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

Пожалуйста, измените этот ответ, если вы знаете способы сделать это в указанных браузерах или в других браузерах.

Ответ 10

Если я хорошо понимаю, вы можете только проверить, проверен ли слушатель, а не какой конкретно слушатель является докладчиком.

Так что некоторый специальный код заполнит пробел для обработки вашего потока кодирования. Практическим методом было бы создать state с использованием переменных. Например, подключите средство проверки прослушивателя следующим образом:

var listenerPresent=false

затем, если вы установите слушателя, просто измените значение:

listenerPresent=true

затем внутри вашего обратного вызова eventListener вы можете назначить определенные функции внутри и таким же образом распределить доступ к функциям в зависимости от некоторого состояния в качестве переменной, например:

accessFirstFunctionality=false
accessSecondFunctionality=true
accessThirdFunctionality=true

Ответ 11

Просто удалите событие перед его добавлением:

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

Ответ 12

Я только что узнал об этом, пытаясь узнать, связано ли мое событие....

если вы выполните:

item.onclick

он вернет "null"

но если вы выполните:

item.hasOwnProperty('onclick')

то это "TRUE"

поэтому я думаю, что когда вы используете addEventListener для добавления обработчиков событий, единственный доступ к нему - через "hasOwnProperty". Хотелось бы, чтобы я знал, почему или как, но, увы, после исследования я не нашел объяснений.

Ответ 13

Теоретически вы можете добавить addEventListener и removeEventListener, чтобы добавить флаг удаления к объекту this. Гадкий, и я не проверял...