Как правильно запускать пользовательские события JavaScript

Я изо всех сил пытаюсь понять, как настраиваемый тип события связан с конкретным действием/триггером пользователя. Вся документация, кажется, отправляет событие без какого-либо взаимодействия с пользователем.

В следующем примере я хочу, чтобы событие было отправлено после того, как пользователь наведет курсор на элемент в течение 3 секунд.

var img = document.createElement('img');img.src = 'http://placehold.it/100x100';
document.body.appendChild(img)
var event = new CustomEvent("hoveredforthreeseconds");

img.addEventListener('hoveredforthreeseconds', function(e) { console.log(e.type)}, true);


var thetrigger = function (element, event) {
    var timeout = null;
    element.addEventListener('mouseover',function() {
        timeout = setTimeout(element.dispatchEvent(event), 3000);
    },true);
    element.addEventListener('mouseout', function() {
        clearTimeout(timeout);
    },true);
};

У меня есть триггер, но нет логического способа связать его с событием.

Я думал о создании объекта с именем CustomEventTrigger, который по сути является CustomEvent, но имеет третий параметр для триггера, а также о создании метода с именем addCustomEventListener, который работает так же, как addEventListener, но при инициализации он затем передает целевой элемент пользовательскому триггеру события, который затем отправляет событие по указанию.


person TarranJones    schedule 25.06.2015    source источник


Ответы (2)


Пользовательские события должны запускаться программно через dispatchEvent, они не запускаются DOM. Вам всегда нужно будет явно вызывать их в своем коде, например, в ответ на сгенерированное пользователем событие, такое как onmouseover, или изменение состояния, такое как onload.

Вы очень близки к рабочей реализации, однако сразу вызываете dispatchEvent в своем setTimeout. Если вы сохраните его в замыкании (как показано ниже), вы можете вызвать dispatchEvent при передаче вашего элемента после того, как setTimeout завершит тайм-аут.

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

var img = document.createElement('img'), timeout, event, thetrigger;

img.src = 'http://placehold.it/100x100';
document.body.appendChild(img);

img.addEventListener("hoveredForThreeSeconds", afterHover, false);

thetrigger = function (element, event) {
    timeout = null;
    element.addEventListener('mouseover',function() {
      timeout = setTimeout(function(){ element.dispatchEvent(event) }, 3000);
    },true);
    element.addEventListener('mouseout', function() {
        clearTimeout(timeout);
    },true);
};

function afterHover(e) {
    console.log("Event is called: " + e.type);
}

event = new CustomEvent("hoveredForThreeSeconds");

thetrigger(img, event);
person teacup    schedule 25.06.2015
comment
спасибо, но я надеялся не слишком запускать каждое событие вручную. - person TarranJones; 25.06.2015

Я создал метод с именем addCustomEventListener, который работает так же, как addEventListener, но при инициализации передает целевой элемент пользовательскому триггеру события, который отправляет событие, когда он говорит, поэтому в этом случае он отправляет только в том случае, если тайм-аут достигает 3 секунд.

var img = document.getElementById('img');

window.mouseover3000 = new CustomEvent('mouseover3000', {
  detail: {
    trigger: function(element, type) {
      timeout = null;
      element.addEventListener('mouseover', function() {
        timeout = setTimeout(function() {
          element.dispatchEvent(window[type])
        }, 3000);
      }, false);
      element.addEventListener('mouseout', function() {
        clearTimeout(timeout);
      }, false)
    }
  }
});

window.tripleclick = new CustomEvent('tripleclick', {
  detail: {
    trigger: function(element, type) {
      element.addEventListener('click', function(e) {
        if(e.detail ===3){
          element.dispatchEvent(window[type])
        }    
      }, false);
    }
  }
});
EventTarget.prototype.addCustomEventListener = function(type, listener, useCapture, wantsUntrusted) {

  this.addEventListener(type, listener, useCapture, wantsUntrusted);
  window[type].detail.trigger(this, type);
}

var eventTypeImage = function(e) {
  this.src = "http://placehold.it/200x200?text=" + e.type;
}

img.addEventListener('mouseout', eventTypeImage, false);
img.addEventListener('mouseover', eventTypeImage, false);
img.addCustomEventListener('mouseover3000', eventTypeImage, false);
img.addCustomEventListener('tripleclick', eventTypeImage, false);
<img id="img" src="http://placehold.it/200x200?text=No+hover" ;/>

Я думаю, что это может быть полезно для других, поэтому, пожалуйста, не стесняйтесь улучшать это.

person TarranJones    schedule 25.06.2015