I am struggling to understand how a custom event type is linked to a specific user action/trigger. All documentation seems to dispatch the event without any user interaction.
In the following example I want the event to be dispatched once a user has been hovering on the element for 3 seconds.
var img = document.createElement('img');img.src = '';
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);
};
I have a trigger but no logical way of connecting it to the event.
I was thinking about creating an object called CustomEventTrigger
which is essentially CustomEvent
but has a third parameter for the trigger and also creating a method called addCustomEventListener
, which works the same as addEventListener
but when initialised it then passes the target Element to the custom event trigger which then dispatches the event when it's instructed to.
I am struggling to understand how a custom event type is linked to a specific user action/trigger. All documentation seems to dispatch the event without any user interaction.
In the following example I want the event to be dispatched once a user has been hovering on the element for 3 seconds.
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);
};
I have a trigger but no logical way of connecting it to the event.
I was thinking about creating an object called CustomEventTrigger
which is essentially CustomEvent
but has a third parameter for the trigger and also creating a method called addCustomEventListener
, which works the same as addEventListener
but when initialised it then passes the target Element to the custom event trigger which then dispatches the event when it's instructed to.
2 Answers
Reset to default 2Custom events have to be triggered programatically through dispatchEvent
, they are not fired by the DOM. You will always need to explictly call them in your code, such as in response to a user-generated event such as onmouseover
, or a change of state such as onload
.
You're very close to a working implementation, however you're immediately invoking dispatchEvent
in your setTimeout
. If you save it into a closure (as below) you can invoke dispatchEvent
while passing your element after setTimeout
has finished the timeout.
It's also good practice to declare your variables at the top of a file, to avoid possible scope issues.
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);
I have created a method called addCustomEventListener
, which works the same as addEventListener
but when initialised passes the target Element to the custom event trigger which dispatches the event when it says, so in this case it only dispatches if the timeout reaches 3 seconds.
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" ;/>
I think this could be useful to others so please feel free to improve on this.