I have a jQuery UI datepicker that, when you click on a date, clears my URL hash to #, and doesn't change the date in the textbox.
I assume there's some other JavaScript utility somewhere that has some sort of delegated event that's also being called, throwing an error, and killing the jquery handler.
How can I step through, and or see all delegated events match this dom element.
Chrome's dev tools can help with this:
Point Chrome at the page
Right-click the date in the jQuery UI datepicker and choose "inspect element".
On the far right-hand side, there's an accordian with various things. Near the bottom is "Event Listeners". (Current versions of Chrome's dev tools are very smart about this, including querying jQuery's handler chain.)
Expand the "Event Listeners" tree item and you'll see a list of hooked events related to that element, even if the handler isn't set specifically on that element. (For instance, if you did this with the upvote button on the question, you'd see that click is hooked both for a.vote-up-off and document.) So you can kick around those to see what direct and delegated handlers relate to that event for that element.
Other than that, you could use the un-minified version of jQuery and walk through the event dispatch when you click the date in the datepicker.
And of course, Gabe's shown how you can get the jQuery-specific handlers via the undocumented jQuery events data. (That won't show you delegated handlers (unless you walk the ancestor tree), and won't show you non-jQuery handlers that might be attached, but it's still pretty useful stuff.)
With jQuery you can see all the elements events by accessing the events key of the data.
jsFiddle
Example:
HTML
<input type="text" id="myelement" />
JS
$(function() {
var myelement = $('#myelement');
myelement.click(function() {
console.log('anonymous event');
});
myelement.click(anotherEvent);
myelement.change(anotherEvent);
var events = myelement.data('events');
console.log('Number of click events:' + events.click.length);
console.log('Number of change events:' + events.change.length);
});
function anotherEvent(){
console.log('another event');
}
Related
I am working with a very large application with a lot of JavaScript. I am trying to determine how I can find the location where a click event is being removed from a specific element.
There is a simple event listener on a specific field added via jQuery (this is an example).
$(document).ready(function() {
$('#id-name').on('click', function(e) {
window.alert('hello');
});
});
If break execution right after this and examine the element in Chrome Inspector, I see the event attached to the element. However, once I continue execution and the page finishes loading, the element no longer has the event. Something is removing it, but I can't find out where this is happening.
Is there a way to listen for "event removal" and trigger code then, so that I can identify where and how this is getting removed? Any other suggestions in locating where the click event is being removed?
Maybe you could override the removeEventListener method and trace it back to see what's calling it.
window.removeEventListener = (type, listener, useCapture)=>console.trace(type, listener, useCapture)
I tried to trace back which function hooked into a click event of .someclass. I open Chrome Dev Tool and type this
getEventListeners(document.querySelector('.someclass'));
The result is this
Object {}
I cannot click and open it to find out the name of the object or the source code that handle click event.
Is there a way to find out?
UPDATE 1:
Followed Krasimir's advise below. There could be only two events: mousemove or mouseover. So how do I find out the exact function handling that event for canvas.overlay? There are just too many to drill down into.
Open the DevTools
Open the Elements tab and locate your element (.someclass)
There are four tabs per element - Styles, Properties, DOM Breakpoints and Event Listeners
Select Event Listeners
You are getting an empty object when calling
getEventListeners(document.querySelector('.someclass'));
probably because the listener isn't hooked up to .someclass element itself (direct event), but to one of it's ancestors (delegated event). There is a good explanation of this here.
You can list both delegated and direct events by calling getEventListeners for specified node and all it's ancestors. This function should do the trick:
getAllEventListeners = function(el) {
var allListeners = {}, listeners;
while(el) {
listeners = getEventListeners(el);
for(event in listeners) {
allListeners[event] = allListeners[event] || [];
allListeners[event].push({listener: listeners[event], element: el});
}
el = el.parentNode;
}
return allListeners;
}
However, this will output exactly the same thing as the "Event Listeners" tab (with "Filter" option set to "All nodes") that Krasimir mentioned in his answer.
I guess you are using jQuery to bind the events to that element.
That's why you can't see the actual handler code in the drill down menu.
Without wrapped by jQuery, the actual code should be displayed in "listenerBody" like this:
EDIT: The Issue has been solved, as it turns out, the Select2 library had a custom command for this typa thing:
$("#element").on("change", function (e) { ... }
// Defined as "change"
I'm using a dropdown menu library called Select2 3.2. In short, the code takes a bunch of select and option tags, and generates a cool drop down search list.
However, after the site is rendered; when I click 'view source', all my select and option tags are still there, but when I right click the fancy new generated menus themselves and select "inspect element" (using google chrome), the html is TOTALLY different.
I think that this is causing the problem, all this new code is rendered from the custom library's JS, and after my jQuery event commands.
Specifically, here is my command:
$(document.body).on('click', '.select2-result-label', function() {
var name = $(this).text();
var post_to = '/myurl/';
$.post(post_to, { dat: dat},
function(response) {
...
}, 'json'
)
I believe the on() method takes care of this kinda stuff but apparently not, any help would be appreciated!
RELEVANT EDIT:
Here is a blurb from another Stack Overflow post:
The view page source page shows you the exact text that
was returned by the server.
Inspect element actually shows you the fully rendered DOM tree.
Knowing that, maybe solving this will be easier.
Here is a JS Fiddle related:
http://jsfiddle.net/JpvDt/47/
Try to make the alert "worked" appear when you click on an "x" in the multi bar.
Right now my code has it to register the class which contains the x's.
$(document.body).on("click", ".select2-search-choice-close", alert("worked"));
Scenario 1:
Your problem is may be you bind on method for whole DOM which is really BAD. So always try to bind that to the closest div (closest parent element) which your controls are exist.
About Event performance from Jquery API says like below.
Attaching many delegated event handlers near the top of the document
tree can degrade performance. Each time the event occurs, jQuery must
compare all selectors of all attached events of that type to every
element in the path from the event target up to the top of the
document. For best performance, attach delegated events at a document
location as close as possible to the target elements. Avoid excessive
use of document or document.body for delegated events on large
documents.
Scenario 2:
Call your on event like below (with off event).
$(#yourElement).off('click').on('click', '.select2-result-label', function() {
var name = $(this).text();
var post_to = '/myurl/';
$.post(post_to, { dat: dat},
function(response) {
...
}, 'json'
)
I hope this will help to you.
As it turns out, the Select2 library had a custom command for future changes to the toolbar.
Read more here: http://ivaynberg.github.com/select2/#programmatic
It's vital to note that many standardized jQuery calls won't work with Select2, you must use their custom set-up.
$("#element").on("change", function (e) { ... }
// Defined as "change"
Just replace $(document.body) by $(document)
I tried to find an answer to my problem, but was not successful - apologies if the answer is very obvious:). Here is the premise of the issue I am trying to solve.
I have lots of UI elements (buttons, hyperlinks etc) that have native events attached to them (eg, clicking a link executes a function)
I do not have access to those event listeners, nor I know what functions/handlers need to be Invoked
I would like to do a generic function which would:
o transverse thru DOM, find the UI elements like button or hyperlink, and attach additional listeners to it that would execute the same handlers/functions (eg, I want to attach “touchend” listeners that would execute the same handlers/functions as “click” event)
Is there a way for me to somehow find out what event handler(s) is(are) used for a particular UI element, and then append the new listener for same handler via .on() method?
Hiya even though your quandary is bit open ended, hope this helps your cause :)
Read this - Things you may not know about JQuery = http://james.padolsey.com/javascript/things-you-may-not-know-about-jquery/
You can access all event handlers bound to an element (or any object) through jQuery’s event storage:
// List bound events:
console.dir( jQuery('#elem').data('events') );
// Log ALL handlers for ALL events:
jQuery.each($('#elem').data('events'), function(i, event){
jQuery.each(event, function(i, handler){
console.log( handler.toString() );
});
});
// You can see the actual functions which will occur
// on certain events; great for debugging!
P.S. - I would recommend to know your DOM better but above should help. B-)
Assume I get a table element with ID="emTab", how do I call JS to click it?
Thanks.
document.getElementById("emTab").onclick = function() {
// your code goes here
};
See element.onclick
To trigger click event
document.getElementById("emTab").click();
See element.click
The click method is intended to be
used with INPUT elements of type
button, checkbox, radio, reset or
submit. Gecko does not implement the
click method on other elements that
might be expected to respond to
mouse–clicks such as links (A
elements), nor will it necessarily
fire the click event of other
elements.
Non–Gecko DOMs may behave differently.
When a click is used with elements
that support it (e.g. one of the INPUT
types listed above), it also fires the
element's click event which will
bubble up to elements higher up the
document tree (or event chain) and
fire their click events too. However,
bubbling of a click event will not
cause an A element to initiate
navigation as if a real mouse-click
had been received.
Cross browser way
If you can use jQuery then it would be
$("#emTab").trigger("click");
Firing events cross-browser - http://jehiah.cz/archive/firing-javascript-events-properly
its simple using JQuery
$('#emTab').click(functionToCall);
while in JS
document.getElementById('emTab').onclick = function() {};
for details on DOM events:
http://www.howtocreate.co.uk/tutorials/javascript/domevents