Related
I have attached an event to a text box using addEventListener. It works fine. My problem arose when I wanted to trigger the event programmatically from another function.
How can I do it?
Note: the initEvent method is now deprecated. Other answers feature up-to-date and recommended practice.
You can use fireEvent on IE 8 or lower, and W3C's dispatchEvent on most other browsers. To create the event you want to fire, you can use either createEvent or createEventObject depending on the browser.
Here is a self-explanatory piece of code (from prototype) that fires an event dataavailable on an element:
var event; // The custom event that will be created
if(document.createEvent){
event = document.createEvent("HTMLEvents");
event.initEvent("dataavailable", true, true);
event.eventName = "dataavailable";
element.dispatchEvent(event);
} else {
event = document.createEventObject();
event.eventName = "dataavailable";
event.eventType = "dataavailable";
element.fireEvent("on" + event.eventType, event);
}
A working example:
// Add an event listener
document.addEventListener("name-of-event", function(e) {
console.log(e.detail); // Prints "Example of an event"
});
// Create the event
var event = new CustomEvent("name-of-event", { "detail": "Example of an event" });
// Dispatch/Trigger/Fire the event
document.dispatchEvent(event);
For older browsers polyfill and more complex examples, see MDN docs.
See support tables for EventTarget.dispatchEvent and CustomEvent.
If you don't want to use jQuery and aren't especially concerned about backwards compatibility, just use:
let element = document.getElementById(id);
element.dispatchEvent(new Event("change")); // or whatever the event type might be
See the documentation here and here.
EDIT: Depending on your setup you might want to add bubbles: true:
let element = document.getElementById(id);
element.dispatchEvent(new Event('change', { 'bubbles': true }));
if you use jQuery, you can simple do
$('#yourElement').trigger('customEventName', [arg0, arg1, ..., argN]);
and handle it with
$('#yourElement').on('customEventName',
function (objectEvent, [arg0, arg1, ..., argN]){
alert ("customEventName");
});
where "[arg0, arg1, ..., argN]" means that these args are optional.
Note: the initCustomEvent method is now deprecated. Other answers feature up-to-date and recommended practice.
If you are supporting IE9+ the you can use the following. The same concept is incorporated in You Might Not Need jQuery.
function addEventListener(el, eventName, handler) {
if (el.addEventListener) {
el.addEventListener(eventName, handler);
} else {
el.attachEvent('on' + eventName, function() {
handler.call(el);
});
}
}
function triggerEvent(el, eventName, options) {
var event;
if (window.CustomEvent) {
event = new CustomEvent(eventName, options);
} else {
event = document.createEvent('CustomEvent');
event.initCustomEvent(eventName, true, true, options);
}
el.dispatchEvent(event);
}
// Add an event listener.
addEventListener(document, 'customChangeEvent', function(e) {
document.body.innerHTML = e.detail;
});
// Trigger the event.
triggerEvent(document, 'customChangeEvent', {
detail: 'Display on trigger...'
});
If you are already using jQuery, here is the jQuery version of the code above.
$(function() {
// Add an event listener.
$(document).on('customChangeEvent', function(e, opts) {
$('body').html(opts.detail);
});
// Trigger the event.
$(document).trigger('customChangeEvent', {
detail: 'Display on trigger...'
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
I searched for firing click, mousedown and mouseup event on mouseover using JavaScript. I found an answer provided by Juan Mendes. For the answer click here.
Click here is the live demo and below is the code:
function fireEvent(node, eventName) {
// Make sure we use the ownerDocument from the provided node to avoid cross-window problems
var doc;
if (node.ownerDocument) {
doc = node.ownerDocument;
} else if (node.nodeType == 9) {
// the node may be the document itself, nodeType 9 = DOCUMENT_NODE
doc = node;
} else {
throw new Error("Invalid node passed to fireEvent: " + node.id);
}
if (node.dispatchEvent) {
// Gecko-style approach (now the standard) takes more work
var eventClass = "";
// Different events have different event classes.
// If this switch statement can't map an eventName to an eventClass,
// the event firing is going to fail.
switch (eventName) {
case "click": // Dispatching of 'click' appears to not work correctly in Safari. Use 'mousedown' or 'mouseup' instead.
case "mousedown":
case "mouseup":
eventClass = "MouseEvents";
break;
case "focus":
case "change":
case "blur":
case "select":
eventClass = "HTMLEvents";
break;
default:
throw "fireEvent: Couldn't find an event class for event '" + eventName + "'.";
break;
}
var event = doc.createEvent(eventClass);
var bubbles = eventName == "change" ? false : true;
event.initEvent(eventName, bubbles, true); // All events created as bubbling and cancelable.
event.synthetic = true; // allow detection of synthetic events
// The second parameter says go ahead with the default action
node.dispatchEvent(event, true);
} else if (node.fireEvent) {
// IE-old school style
var event = doc.createEventObject();
event.synthetic = true; // allow detection of synthetic events
node.fireEvent("on" + eventName, event);
}
};
The accepted answer didn’t work for me, none of the createEvent ones did.
What worked for me in the end was:
targetElement.dispatchEvent(
new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window,
}));
Here’s a snippet:
const clickBtn = document.querySelector('.clickme');
const viaBtn = document.querySelector('.viame');
viaBtn.addEventListener('click', function(event) {
clickBtn.dispatchEvent(
new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window,
}));
});
clickBtn.addEventListener('click', function(event) {
console.warn(`I was accessed via the other button! A ${event.type} occurred!`);
});
<button class="clickme">Click me</button>
<button class="viame">Via me</button>
From reading:
https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent
Modified #Dorian's answer to work with IE:
document.addEventListener("my_event", function(e) {
console.log(e.detail);
});
var detail = 'Event fired';
try {
// For modern browsers except IE:
var event = new CustomEvent('my_event', {detail:detail});
} catch(err) {
// If IE 11 (or 10 or 9...?) do it this way:
// Create the event.
var event = document.createEvent('Event');
// Define that the event name is 'build'.
event.initEvent('my_event', true, true);
event.detail = detail;
}
// Dispatch/Trigger/Fire the event
document.dispatchEvent(event);
FIDDLE: https://jsfiddle.net/z6zom9d0/1/
SEE ALSO:
https://caniuse.com/#feat=customevent
Just to suggest an alternative that does not involve the need to manually invoke a listener event:
Whatever your event listener does, move it into a function and call that function from the event listener.
Then, you can also call that function anywhere else that you need to accomplish the same thing that the event does when it fires.
I find this less "code intensive" and easier to read.
I just used the following (seems to be much simpler):
element.blur();
element.focus();
In this case the event is triggered only if value was really changed just as you would trigger it by normal focus locus lost performed by user.
function fireMouseEvent(obj, evtName) {
if (obj.dispatchEvent) {
//var event = new Event(evtName);
var event = document.createEvent("MouseEvents");
event.initMouseEvent(evtName, true, true, window,
0, 0, 0, 0, 0, false, false, false, false, 0, null);
obj.dispatchEvent(event);
} else if (obj.fireEvent) {
event = document.createEventObject();
event.button = 1;
obj.fireEvent("on" + evtName, event);
obj.fireEvent(evtName);
} else {
obj[evtName]();
}
}
var obj = document.getElementById("......");
fireMouseEvent(obj, "click");
You could use this function i compiled together.
if (!Element.prototype.trigger)
{
Element.prototype.trigger = function(event)
{
var ev;
try
{
if (this.dispatchEvent && CustomEvent)
{
ev = new CustomEvent(event, {detail : event + ' fired!'});
this.dispatchEvent(ev);
}
else
{
throw "CustomEvent Not supported";
}
}
catch(e)
{
if (document.createEvent)
{
ev = document.createEvent('HTMLEvents');
ev.initEvent(event, true, true);
this.dispatchEvent(event);
}
else
{
ev = document.createEventObject();
ev.eventType = event;
this.fireEvent('on'+event.eventType, event);
}
}
}
}
Trigger an event below:
var dest = document.querySelector('#mapbox-directions-destination-input');
dest.trigger('focus');
Watch Event:
dest.addEventListener('focus', function(e){
console.log(e);
});
Hope this helps!
You can use below code to fire event using Element method:
if (!Element.prototype.triggerEvent) {
Element.prototype.triggerEvent = function (eventName) {
var event;
if (document.createEvent) {
event = document.createEvent("HTMLEvents");
event.initEvent(eventName, true, true);
} else {
event = document.createEventObject();
event.eventType = eventName;
}
event.eventName = eventName;
if (document.createEvent) {
this.dispatchEvent(event);
} else {
this.fireEvent("on" + event.eventType, event);
}
};
}
if (!Element.prototype.triggerEvent) {
Element.prototype.triggerEvent = function (eventName) {
var event;
if (document.createEvent) {
event = document.createEvent("HTMLEvents");
event.initEvent(eventName, true, true);
} else {
event = document.createEventObject();
event.eventType = eventName;
}
event.eventName = eventName;
if (document.createEvent) {
this.dispatchEvent(event);
} else {
this.fireEvent("on" + event.eventType, event);
}
};
}
var input = document.getElementById("my_input");
var button = document.getElementById("my_button");
input.addEventListener('change', function (e) {
alert('change event fired');
});
button.addEventListener('click', function (e) {
input.value = "Bye World";
input.triggerEvent("change");
});
<input id="my_input" type="input" value="Hellow World">
<button id="my_button">Change Input</button>
What's worth noticing, is the fact that we can create, any kind of pre-defined events, and listen to it from anywhere.
We are not limited to classical built-in events.
In this base example, a custom event interfacebuiltsuccessuserdefinedevent is dispatched every 3 seconds, on the self.document
self.document.addEventListener('interfacebuiltsuccessuserdefinedevent', () => console.log("WOW"), false)
setInterval(() => { // Test
self.document.dispatchEvent(new Event('interfacebuiltsuccessuserdefinedevent'))
}, 3000 ) // Test
Interesting fact: elements can listen for events that haven't been created yet.
The most efficient way is to call the very same function that has been registered with addEventListener directly.
You can also trigger a fake event with CustomEvent and co.
Finally some elements such as <input type="file"> support a .click() method.
var btn = document.getElementById('btn-test');
var event = new Event(null);
event.initEvent('beforeinstallprompt', true, true);
btn.addEventListener('beforeinstallprompt', null, false);
btn.dispatchEvent(event);
this will imediattely trigger an event 'beforeinstallprompt'
HTML
myLink
<button onclick="fireLink(event)"> Call My Link </button>
JS
// click event listener of the link element --------------
document.getElementById('myLink').addEventListener("click", callLink);
function callLink(e) {
// code to fire
}
// function invoked by the button element ----------------
function fireLink(event) {
document.getElementById('myLink').click(); // script calls the "click" event of the link element
}
Use jquery event call.
Write the below line where you want to trigger onChange of any element.
$("#element_id").change();
element_id is the ID of the element whose onChange you want to trigger.
Avoid the use of
element.fireEvent("onchange");
Because it has very less support. Refer this document for its support.
What you want is something like this:
document.getElementByClassName("example").click();
Using jQuery, it would be something like this:
$(".example").trigger("click");
Here is an event listener added, if I want to test if this event listener is working or not, how do I test? window.postMessage doesn't seem to be triggering this event. Basically, how do I trigger "some_event" so that my EventListener runs?
window.addEventListener('some_event', function() {
console.log("some_event triggered");
});
Please note, I was able to reproduce with "click" event, but what I want to know is, how do I know if any string is passed as an event. Example:
window.addEventListener('add_to_cart', function() {
console.log("some_event triggered");
});
So I would like to simulate this event listener to check if it's working or not. How do I test this?
You need to use some concrete event name like for example click - and click on browser page window - eg:
window.addEventListener('click', function() {
console.log("some_event triggered");
});
Here is some info about events and situations when they are trigger.
After question update
Yes you can define and fire arbitrary events - read here. And here is some example code:
var event = new Event('some_event');
// Listen for the event.
window.addEventListener('some_event', function (e) {
console.log('some_event triggered')
}, false);
// Dispatch the event.
window.dispatchEvent(event);
So you fire event using window.dispatchEvent(event) and this is the way you can test it.
You can trigger an event using dispatchEvent and fireEvent in IE.
var ev, element = window;
if (document.createEvent) {
ev = document.createEvent("HTMLEvents");
ev.initEvent("eventname", true, true);
ev.eventName = "eventname";
element.dispatchEvent(ev);
} else {
ev = document.createEventObject();
ev.eventType = "eventname";
ev.eventName = "eventname";
element.fireEvent("on" + ev.eventType, event);
}
function triggerEvent(elem, name){
var ev;
if (document.createEvent) {
ev = document.createEvent("HTMLEvents");
ev.initEvent(name, true, true);
ev.eventName = name;
elem.dispatchEvent(ev);
} else {
ev = document.createEventObject();
ev.eventType = name;
ev.eventName = name;
elem.fireEvent("on" + ev.eventType, event);
}
}
window.addEventListener("click", function(e){
console.log("Clicked");
});
window.addEventListener("custom_event", function(e){
console.log("custom_event triggered");
});
triggerEvent(window, "click");
triggerEvent(window, "custom_event");
I have following code which listens for keydown event in given array of nodeList.
var obj = {
method: function(nodeSelector) {
var nodeContainers = document.querySelectorAll(nodeSelector);
var keyListenerFunc = this.keyListener.bind(this);
this.bindListener(nodeContainers, keyListenerFunc);
},
isListNode: function (evt){
return evt.target.nodeName.toLowerCase() === 'li';
},
isContainer: function(evt){
return evt.target.parentNode.classList.contains(this.indicatorClass);
},
keyListener: function(evt) {
if (evt.keyCode === 32 && (this.isContainer(evt) && this.isListNode(evt))) {
evt.preventDefault();
evt.target.click();
}
},
bindListener: function(targets, callbackFunc) {
[].forEach.call(targets, function(item) {
item.addEventListener('keydown', callbackFunc);
});
},
indicatorClass: 'indicator'
};
I'm using it like: obj.method('.someClassNames');
But now I want to test it completely including the triggering of keydown event. How can I attach event listener and then trigger keydown event on given dom nodes so that my Jasmine tests would work ? How can I create some dummy html code here and then trigger event on it ? I am expecting to write tests of this type =>
it('It should put event listeners on each carousel passed to the service', function(){});
it('It should call event.preventDefault', function(){});
it('It should call event.target.click', function(){});
My markup is follwing
var html = '<div class="someClassNames">'+
'<div class="indicator">'+
'<li>text</li>'+
'</div>'
'</div>';
I am assuming that I am going to need to trigger following keydown event but I am not sure as to how to trigger is on the given markup and check in the test description.
var e = new window.KeyboardEvent('keydown', {
bubbles: true
});
Object.defineProperty(e, 'keyCode', {'value': 32});
I am very much new to testing with Jasmine and I couldn't find any examples that would help me test this scenario. I hope my example makes it clear.
few observations:
Note that the callbackFunc is actually assigned to the onkeydown
attribute of the element. Hence you may want to spy on the
element.onkeydown rather than obj.keyListener
Sometimes the render of the UI element may take place after spec has
been run.
So to ensure that you have the element is present, I've used the
setTimeout with a jasmine clock
If you really want to test your obk.keyListener, try using an
anonymous function like here
here is how I've it running. I've used mouseover as I'm lazy :)
var obj = {
testVar : "Object",
method: function(nodeSelector) {
var nodeContainers = document.querySelectorAll(nodeSelector);
var keyListenerFunc = this.keyListener.bind(this);
this.bindListener(nodeContainers, keyListenerFunc);
},
isListNode: function(evt) {
return evt.target.nodeName.toLowerCase() === 'li';
},
isContainer: function(evt) {
return evt.target.parentNode.classList.contains(this.indicatorClass);
},
keyListener: function(evt) {
console.log('Yo! You hovered!');
},
bindListener: function(targets, callbackFunc) {
targets.forEach(function(item) {
item.addEventListener('mouseover', callbackFunc, false);
});
},
indicatorClass: 'indicator'
};
describe('Sample tests', function() {
//this ensures you have the element set up
beforeEach(function() {
jasmine.clock().install();
jasmine.DEFAULT_TIMEOUT_INTERVAL = 200;
setTimeout(function() {
obj.method('div.indicator');
}, 0);
});
it('It should put event listeners', function() {
jasmine.clock().tick(10);
var ele= document.getElementsByClassName("indicator")[0];
spyOn(ele, 'onmouseover').and.callThrough();
$('.indicator').trigger('mouseover');
expect(ele.onmouseover).toHaveBeenCalled();
expect(typeof ele.onmouseover).toBe('function');
});
});
HTML CONTENT:
<div class="someClassNames">
<div class="indicator">
<li>text</li>
<br/> </div>
</div>
I am attempting to create a jQuery plugin for my own use that can be used to setup a handler for jQuery mobile dialogs using a single command as such: $('#dialog').setup_dialog({ callback: callback_function });
However, my handler has a rather obvious memory leak due to closures in it:
$.fn.setup_dialog = function( options ) {
var settings = $.extend({
callback : 0
}, options);
var that = this;
return this.live('pagebeforeshow', function(event, ui) {
console.log("outside");
$('form', that).submit( function(e) {
var $inputs = $('form :input', that); // get all form inputs
var values = {};
$inputs.each(function() {
values[this.name] = $(this).val();
});
that.dialog('close');
if ( settings.callback && typeof(settings.callback) === "function" ) {
$('#'+ui.prevPage[0].id).live('pagebeforeshow', function() {
settings.callback(values, that);
console.log("inside");
});
}
return e.preventDefault();
});
});
}; /* setup_dialog */
If you ran the above code, you would see "inside" and "outside" printed first once, then three times (twice from a single submit), then six times (three times from a single submit), etc.
The intent of the code is to attach an event handler to the jQuery Mobile dialog when it comes up that will catch form submission, collect all the form values, and then pass them to a callback function that will modify the original page (that launched the dialog).
Note that because of the way jQuery Mobile uses AJAX to switch between pages, I need to use .live to bind the events (.bind or .one won't work).
Any ideas how I can avoid the events accumulating (and maybe clean up the code a bit as well)?
You are binding event handlers inside of other event handlers. And the outer event handlers are not unique events (they occur more than once) which means that your inner event handlers are being bound more than once.
A good fix is to remove the submit event handler from the pagebeforeshow event handler and place it in a pagecreate or pageinit event handler (these are unique and will only run once per dialog).
If you want to keep your current logic then you can just unbind event handlers when they run, so you won't be stacking multiple event handlers that do the same thing:
$.fn.setup_dialog = function( options ) {
var settings = $.extend({
callback : 0
}, options);
var that = this;
return this.live('pagebeforeshow', function(event, ui) {
console.log("outside");
$('form', that).submit( function(e) {
var $inputs = $('form :input', that); // get all form inputs
var values = {};
$inputs.each(function() {
values[this.name] = $(this).val();
});
that.dialog('close');
if ( settings.callback && typeof(settings.callback) === "function" ) {
$('#'+ui.prevPage[0].id).live('pagebeforeshow', function() {
settings.callback(values, that);
console.log("inside");
$(this).die('pagebeforeshow');//NEW, unbind the pagebeforeshow event handler for this element
//since it will be bound the next time the dialog is shown anyway
});
}
$(this).die('submit');//NEW, unbind the submit event handler for this form
//since it will be bound the next time the dialog is shown anyway
return e.preventDefault();
});
});
}; /* setup_dialog */
Here is the documentation for .die(): http://api.jquery.com/die/
The solution appears to be the following:
$.fn.setup_dialog = function( options ) {
var settings = $.extend({
callback : 0
}, options);
var that = this; var values = {}; var submitted = 0;
this.on('pageinit', function(event, ui) {
$('form', that).submit(function(e) {
var $inputs = $('form :input', that); // get all form inputs
submitted = 1;
$inputs.each(function() {
values[this.name] = $(this).val();
});
that.dialog('close');
return e.preventDefault();
});
$('.cancel-button', that).click(function() {
submitted = 0;
});
});
this.on('pagebeforehide', function(event, ui) {
if ( submitted && settings.callback && typeof(settings.callback) === "function" ) {
settings.callback(values, that);
}
});
}; /* setup_dialog */
There were multiple ways to do this, including creating a closure and calling $('#'+ui.prevPage[0].id).die().live('pagebeforeshow', function() {
Not convinced this is the nicest solution though, so I'd love to hear some better ideas.
I'd like to see all the events fired by an input field as a user interacts with it. This includes stuff like:
Clicking on it.
Clicking off it.
Tabbing into it.
Tabbing away from it.
Ctrl+C and Ctrl+V on the keyboard.
Right click -> Paste.
Right click -> Cut.
Right click -> Copy.
Dragging and dropping text from another application.
Modifying it with Javascript.
Modifying it with a debug tool, like Firebug.
I'd like to display it using console.log. Is this possible in Javascript/jQuery, and if so, how do I do it?
I have no idea why no-one uses this... (maybe because it's only a webkit thing)
Open console:
monitorEvents(document.body); // logs all events on the body
monitorEvents(document.body, 'mouse'); // logs mouse events on the body
monitorEvents(document.body.querySelectorAll('input')); // logs all events on inputs
$(element).on("click mousedown mouseup focus blur keydown change",function(e){
console.log(e);
});
That will get you a lot (but not all) of the information on if an event is fired... other than manually coding it like this, I can't think of any other way to do that.
There is a nice generic way using the .data('events') collection:
function getEventsList($obj) {
var ev = new Array(),
events = $obj.data('events'),
i;
for(i in events) { ev.push(i); }
return ev.join(' ');
}
$obj.on(getEventsList($obj), function(e) {
console.log(e);
});
This logs every event that has been already bound to the element by jQuery the moment this specific event gets fired. This code was pretty damn helpful for me many times.
Btw: If you want to see every possible event being fired on an object use firebug: just right click on the DOM element in html tab and check "Log Events". Every event then gets logged to the console (this is sometimes a bit annoying because it logs every mouse movement...).
$('body').on("click mousedown mouseup focus blur keydown change mouseup click dblclick mousemove mouseover mouseout mousewheel keydown keyup keypress textInput touchstart touchmove touchend touchcancel resize scroll zoom focus blur select change submit reset",function(e){
console.log(e);
});
I know the answer has already been accepted to this, but I think there might be a slightly more reliable way where you don't necessarily have to know the name of the event beforehand. This only works for native events though as far as I know, not custom ones that have been created by plugins. I opted to omit the use of jQuery to simplify things a little.
let input = document.getElementById('inputId');
Object.getOwnPropertyNames(input)
.filter(key => key.slice(0, 2) === 'on')
.map(key => key.slice(2))
.forEach(eventName => {
input.addEventListener(eventName, event => {
console.log(event.type);
console.log(event);
});
});
I hope this helps anyone who reads this.
EDIT
So I saw another question here that was similar, so another suggestion would be to do the following:
monitorEvents(document.getElementById('inputId'));
Old thread, I know. I needed also something to monitor events and wrote this very handy (excellent) solution. You can monitor all events with this hook (in windows programming this is called a hook). This hook does not affects the operation of your software/program.
In the console log you can see something like this:
Explanation of what you see:
In the console log you will see all events you select (see below "how to use") and shows the object-type, classname(s), id, <:name of function>, <:eventname>.
The formatting of the objects is css-like.
When you click a button or whatever binded event, you will see it in the console log.
The code I wrote:
function setJQueryEventHandlersDebugHooks(bMonTrigger, bMonOn, bMonOff)
{
jQuery.fn.___getHookName___ = function()
{
// First, get object name
var sName = new String( this[0].constructor ),
i = sName.indexOf(' ');
sName = sName.substr( i, sName.indexOf('(')-i );
// Classname can be more than one, add class points to all
if( typeof this[0].className === 'string' )
{
var sClasses = this[0].className.split(' ');
sClasses[0]='.'+sClasses[0];
sClasses = sClasses.join('.');
sName+=sClasses;
}
// Get id if there is one
sName+=(this[0].id)?('#'+this[0].id):'';
return sName;
};
var bTrigger = (typeof bMonTrigger !== "undefined")?bMonTrigger:true,
bOn = (typeof bMonOn !== "undefined")?bMonOn:true,
bOff = (typeof bMonOff !== "undefined")?bMonOff:true,
fTriggerInherited = jQuery.fn.trigger,
fOnInherited = jQuery.fn.on,
fOffInherited = jQuery.fn.off;
if( bTrigger )
{
jQuery.fn.trigger = function()
{
console.log( this.___getHookName___()+':trigger('+arguments[0]+')' );
return fTriggerInherited.apply(this,arguments);
};
}
if( bOn )
{
jQuery.fn.on = function()
{
if( !this[0].__hooked__ )
{
this[0].__hooked__ = true; // avoids infinite loop!
console.log( this.___getHookName___()+':on('+arguments[0]+') - binded' );
$(this).on( arguments[0], function(e)
{
console.log( $(this).___getHookName___()+':'+e.type );
});
}
var uResult = fOnInherited.apply(this,arguments);
this[0].__hooked__ = false; // reset for another event
return uResult;
};
}
if( bOff )
{
jQuery.fn.off = function()
{
if( !this[0].__unhooked__ )
{
this[0].__unhooked__ = true; // avoids infinite loop!
console.log( this.___getHookName___()+':off('+arguments[0]+') - unbinded' );
$(this).off( arguments[0] );
}
var uResult = fOffInherited.apply(this,arguments);
this[0].__unhooked__ = false; // reset for another event
return uResult;
};
}
}
Examples how to use it:
Monitor all events:
setJQueryEventHandlersDebugHooks();
Monitor all triggers only:
setJQueryEventHandlersDebugHooks(true,false,false);
Monitor all ON events only:
setJQueryEventHandlersDebugHooks(false,true,false);
Monitor all OFF unbinds only:
setJQueryEventHandlersDebugHooks(false,false,true);
Remarks/Notice:
Use this for debugging only, turn it off when using in product final
version
If you want to see all events, you have to call this function
directly after jQuery is loaded
If you want to see only less events, you can call the function on the time you need it
If you want to auto execute it, place ( )(); around function
Hope it helps! ;-)
https://github.com/robertleeplummerjr/wiretap.js
new Wiretap({
add: function() {
//fire when an event is bound to element
},
before: function() {
//fire just before an event executes, arguments are automatic
},
after: function() {
//fire just after an event executes, arguments are automatic
}
});
Just add this to the page and no other worries, will handle rest for you:
$('input').live('click mousedown mouseup focus keydown change blur', function(e) {
console.log(e);
});
You can also use console.log('Input event:' + e.type) to make it easier.
STEP 1: Check the events for an HTML element on the developer console:
STEP 2: Listen to the events we want to capture:
$(document).on('ch-ui-container-closed ch-ui-container-opened', function(evt){
console.log(evt);
});
Good Luck...
I recently found and modified this snippet from an existing SO post that I have not been able to find again but I've found it very useful
// specify any elements you've attached listeners to here
const nodes = [document]
// https://developer.mozilla.org/en-US/docs/Web/Events
const logBrowserEvents = () => {
const AllEvents = {
AnimationEvent: ['animationend', 'animationiteration', 'animationstart'],
AudioProcessingEvent: ['audioprocess'],
BeforeUnloadEvent: ['beforeunload'],
CompositionEvent: [
'compositionend',
'compositionstart',
'compositionupdate',
],
ClipboardEvent: ['copy', 'cut', 'paste'],
DeviceLightEvent: ['devicelight'],
DeviceMotionEvent: ['devicemotion'],
DeviceOrientationEvent: ['deviceorientation'],
DeviceProximityEvent: ['deviceproximity'],
DragEvent: [
'drag',
'dragend',
'dragenter',
'dragleave',
'dragover',
'dragstart',
'drop',
],
Event: [
'DOMContentLoaded',
'abort',
'afterprint',
'beforeprint',
'cached',
'canplay',
'canplaythrough',
'change',
'chargingchange',
'chargingtimechange',
'checking',
'close',
'dischargingtimechange',
'downloading',
'durationchange',
'emptied',
'ended',
'error',
'fullscreenchange',
'fullscreenerror',
'input',
'invalid',
'languagechange',
'levelchange',
'loadeddata',
'loadedmetadata',
'noupdate',
'obsolete',
'offline',
'online',
'open',
'open',
'orientationchange',
'pause',
'play',
'playing',
'pointerlockchange',
'pointerlockerror',
'ratechange',
'readystatechange',
'reset',
'seeked',
'seeking',
'stalled',
'submit',
'success',
'suspend',
'timeupdate',
'updateready',
'visibilitychange',
'volumechange',
'waiting',
],
FocusEvent: [
'DOMFocusIn',
'DOMFocusOut',
'Unimplemented',
'blur',
'focus',
'focusin',
'focusout',
],
GamepadEvent: ['gamepadconnected', 'gamepaddisconnected'],
HashChangeEvent: ['hashchange'],
KeyboardEvent: ['keydown', 'keypress', 'keyup'],
MessageEvent: ['message'],
MouseEvent: [
'click',
'contextmenu',
'dblclick',
'mousedown',
'mouseenter',
'mouseleave',
'mousemove',
'mouseout',
'mouseover',
'mouseup',
'show',
],
// https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events
MutationNameEvent: ['DOMAttributeNameChanged', 'DOMElementNameChanged'],
MutationEvent: [
'DOMAttrModified',
'DOMCharacterDataModified',
'DOMNodeInserted',
'DOMNodeInsertedIntoDocument',
'DOMNodeRemoved',
'DOMNodeRemovedFromDocument',
'DOMSubtreeModified',
],
OfflineAudioCompletionEvent: ['complete'],
OtherEvent: ['blocked', 'complete', 'upgradeneeded', 'versionchange'],
UIEvent: [
'DOMActivate',
'abort',
'error',
'load',
'resize',
'scroll',
'select',
'unload',
],
PageTransitionEvent: ['pagehide', 'pageshow'],
PopStateEvent: ['popstate'],
ProgressEvent: [
'abort',
'error',
'load',
'loadend',
'loadstart',
'progress',
],
SensorEvent: ['compassneedscalibration', 'Unimplemented', 'userproximity'],
StorageEvent: ['storage'],
SVGEvent: [
'SVGAbort',
'SVGError',
'SVGLoad',
'SVGResize',
'SVGScroll',
'SVGUnload',
],
SVGZoomEvent: ['SVGZoom'],
TimeEvent: ['beginEvent', 'endEvent', 'repeatEvent'],
TouchEvent: [
'touchcancel',
'touchend',
'touchenter',
'touchleave',
'touchmove',
'touchstart',
],
TransitionEvent: ['transitionend'],
WheelEvent: ['wheel'],
}
const RecentlyLoggedDOMEventTypes = {}
Object.keys(AllEvents).forEach((DOMEvent) => {
const DOMEventTypes = AllEvents[DOMEvent]
if (Object.prototype.hasOwnProperty.call(AllEvents, DOMEvent)) {
DOMEventTypes.forEach((DOMEventType) => {
const DOMEventCategory = `${DOMEvent} ${DOMEventType}`
nodes.forEach((node) => {
node.addEventListener(
DOMEventType,
(e) => {
if (RecentlyLoggedDOMEventTypes[DOMEventCategory]) return
RecentlyLoggedDOMEventTypes[DOMEventCategory] = true
// NOTE: throttle continuous events
setTimeout(() => {
RecentlyLoggedDOMEventTypes[DOMEventCategory] = false
}, 1000)
const isActive = e.target === document.activeElement
// https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement
const hasActiveElement = document.activeElement !== document.body
const msg = [
DOMEventCategory,
'target:',
e.target,
...(hasActiveElement
? ['active:', document.activeElement]
: []),
]
if (isActive) {
console.info(...msg)
}
},
true,
)
})
})
}
})
}
logBrowserEvents()
// export default logBrowserEvents
function bindAllEvents (el) {
for (const key in el) {
if (key.slice(0, 2) === 'on') {
el.addEventListener(key.slice(2), e => console.log(e.type));
}
}
}
bindAllEvents($('.yourElement'))
This uses a bit of ES6 for prettiness, but can easily be translated for legacy browsers as well. In the function attached to the event listeners, it's currently just logging out what kind of event occurred but this is where you could print out additional information, or using a switch case on the e.type, you could only print information on specific events
Here is a non-jquery way to monitor events in the console with your code and without the use of monitorEvents() because that only works in Chrome Developer Console. You can also choose to not monitor certain events by editing the no_watch array.
function getEvents(obj) {
window["events_list"] = [];
var no_watch = ['mouse', 'pointer']; // Array of event types not to watch
var no_watch_reg = new RegExp(no_watch.join("|"));
for (var prop in obj) {
if (prop.indexOf("on") === 0) {
prop = prop.substring(2); // remove "on" from beginning
if (!prop.match(no_watch_reg)) {
window["events_list"].push(prop);
window.addEventListener(prop, function() {
console.log(this.event); // Display fired event in console
} , false);
}
}
}
window["events_list"].sort(); // Alphabetical order
}
getEvents(document); // Put window, document or any html element here
console.log(events_list); // List every event on element
How to listen for all events on an Element (Vanilla JS)
For all native events, we can retrieve a list of supported events by iterating over the target.onevent properties and installing our listener for all of them.
for (const key in target) {
if(/^on/.test(key)) {
const eventType = key.substr(2);
target.addEventListener(eventType, listener);
}
}
The only other way that events are emitted which I know of is via EventTarget.dispatchEvent, which every Node and thefore every Element inherits.
To listen for all these manually triggered events, we can proxy the dispatchEvent method globally and install our listener just-in-time for the event whose name we just saw ✨ ^^
const dispatchEvent_original = EventTarget.prototype.dispatchEvent;
EventTarget.prototype.dispatchEvent = function (event) {
if (!alreadyListenedEventTypes.has(event.type)) {
target.addEventListener(event.type, listener, ...otherArguments);
alreadyListenedEventTypes.add(event.type);
}
dispatchEvent_original.apply(this, arguments);
};
🔥 function snippet 🔥
function addEventListenerAll(target, listener, ...otherArguments) {
// install listeners for all natively triggered events
for (const key in target) {
if (/^on/.test(key)) {
const eventType = key.substr(2);
target.addEventListener(eventType, listener, ...otherArguments);
}
}
// dynamically install listeners for all manually triggered events, just-in-time before they're dispatched ;D
const dispatchEvent_original = EventTarget.prototype.dispatchEvent;
function dispatchEvent(event) {
target.addEventListener(event.type, listener, ...otherArguments); // multiple identical listeners are automatically discarded
dispatchEvent_original.apply(this, arguments);
}
EventTarget.prototype.dispatchEvent = dispatchEvent;
if (EventTarget.prototype.dispatchEvent !== dispatchEvent) throw new Error(`Browser is smarter than you think!`);
}
// usage example
const input = document.querySelector('input');
addEventListenerAll(input, (evt) => {
console.log(evt.type);
});
input.focus();
input.click();
input.dispatchEvent(new Event('omg!', { bubbles: true }));
// usage example with `useCapture`
// (also receives `bubbles: false` events, but in reverse order)
addEventListenerAll(
input,
(evt) => { console.log(evt.type); },
true
);
document.body.dispatchEvent(new Event('omfggg!', { bubbles: false }));