I just finished a pretty intense debugging session where my cucumber test code would work using webkit but wouldn't work using selenium. The problem was solved by being very specific about the exact DOM element that was clicked. I needed to specify clicking a deeply nested <span> element. This brought up a question for which I'm not sure how to answer:
How do I know what element, initially, received an event?
I've read a bit about event bubbling, so even if my element's event handler fires, it doesn't mean that it was the initial element to receive the event. I don't understand why Chrome was able to accept a click event that was propagated down to the correct element that fired off my handler, but Firefox didn't propagate the event down.
This question on debugging events doesn't quite capture my question, because in this case I didn't know what element to examine. I basically guessed correctly. I'd love a more methodical process to use to debug. Bonus points for helping me understand better the JS event bubbling/propagation model.
It's target property of the event object.
domElement.addEventListener('click', function(e){
console.log(e.target);
});
Related
Is there any way in Javascript to tell what the most recently-fired event was? Reason I'm asking is I'm working on a site that isn't behaving properly on one of those new Ultrabooks that's running Windows 8 and is a laptop with a touch screen. If you use the standard mouse functionality (with a touchpad or an actual mouse), things work fine, but if you use the touch screen, things don't.
This only happens with IE; Chrome has its own issues (which I have fixed in the code), and Firefox hasn't given us any problems.
Basically, the functionality we have includes a "hoverIntent" block, and if you use the touch screen on IE, it registers both the "over" and "out" functions, which is a problem.
However, if there was a way for me to tell whether the last thing that happened was that the user TOUCHED THE SCREEN or CLICKED WITH A MOUSE, I'd have a solution in place. But I couldn't tell if there's a way to do that.
The only thing I could find was tacking on ".data('events')" on an element, but what returns is "click" regardless of whether it was an actual mouse click or a tap on the screen.
Is there a way to do this?
The browser does not have a standard way of recording events that happened previously. If you want to know what events happened prior to the current event, then you will have to install an event handler for those events and record them yourself so you can then look back at them at some future time.
For events that propagate, you could install some event handlers on the document object and record both event and target for the last N events.
If you're just trying to figure out what event the current event is, then you can examine the type property of the event object that is passed into the event handler as in e.type.
You can add an event to your function arguments and then use event.type to check which event is triggered.
ex:
var x = function(e) {
alert(e.type);
}
So I found out that IE has a completely different set of touch events from what EVERY OTHER BROWSER IN THE UNIVERSE has. ughhh. Instead of "touchstart," you use "MSPointerDown," etc. My solution was basically to write new event handlers for MSIE's touch device events.
In short
Is there a way in which, when listening to a native event, I can detect if the event was somehow used by CKEditor before it propagated to my listener, or prevent it from propagating at all?
Use case
I'm listening to the keyup event using jQuery, to detect when escape is pressed. When it is, the user is prompted if they want to discard changes, and the CKEditor instance is destroyed and its element removed from the DOM.
$('body').on('keyup', function(e){
if(e.which==27){
CKEDITOR.instances.myDiv.destroy();
$('#myDiv').remove();
}
});
The problem here is that CKEditor allows the user to interact with certain UI elements using the escape key. For instance to close a dialog window or drop-down list.
So my event should only execute its code if CKEditor did not already use the event to close a UI element of its own.
Attempt
I tried to listen to the dialogShow and dialogHide events to detect if a dialog window is open, and my action should thus be ignored. This didn't work for two reasons:
CKEditor handles the event first, so by the time the event propagates to my listener, no dialog windows are open and my code is executed.
Even if it would work, it wouldn't for drop-down lists as they do not trigger the dialog* events.
Ideas
I don't know enough about the workings of CKEditor to come up with a solution, but I think I'm looking for something along the lines of:
A setting in CKEditor to prevent event propagation: CKEDITOR.instances[0].noEventPropagation = true
An indication in the original event object: if(event.CKEditorWasHere){/*do nothing*/}
A plugin providing functionality that I can use.
Worst case scenario: A setTimeout in the dialogHide event which I'll use to suppress my own events for a short time.
So
Maybe I'm completely overlooking something. This seems to me like a common problem which should have a simple solution.
Thanks for your time.
I know that using Firebug or other inspectors will show you all events firing, but is there any way to do this from in-page JavaScript (especially if you don't know the event name that you're looking for?)
This is my use case: the new Galaxy S4 has "air gestures" - when you gesture in front of the web page, it will scroll up and down. I'm trying to find out whether these generate events detectable by content or are they swallowed by the OS.
You probably already know that JS event handlers can for example choose to stop the immediate propagation of events so that no other handlers get called for the event in question.
This means that in order to do what you propose, you 'd have to attach handlers for all events on all elements and those handlers would have to be first in each and every case so that your handler gets called before anyone else has a chance to stop that from happening. It goes without saying that you 'd also have to know the event names.
So no, you can't really do that.
I thought it will be better to rephrase the whole question after gathering some information on how to resolve my problem.
The simple question now is how to create a custom event out of window.onhashchange functionality.
I wanted to do this because as you may know you cannot attach handler on javascript loaded content, you will be able to solve this by
$('parent').on('event', 'child', func) right? which is equivalent to jquery delegate functionality.
How can I create a custom event out of window.onhashchange
Ohhhh. Okay. Well, window is the only thing that it makes sense for hashchange to trigger on so I'm not sure why you would want event delegation. Listen to the window. When there is a hash change, do what you want to whatever HTML currently exists.
You actually can attach handlers to JavaScript-appended content. If it's in the DOM, it's something you can manipulate and listen for events on. The problem is when you replace the html content. The original dom node is gone so if for instance you had a click event, it's registered to a node that no longer exists.
But window can only be replaced by reloading the page and that's the only thing a hash change should be relevant to. Also 'hashchange' isn't a real DOM event. If it made sense for it to trigger on an element I'm not sure it would still bubble like an event like 'click' does.
Short version: I'm not sure you're having the problem you think you're having if you need something to happen on this 'hashchange' event.
I have a couple of questions regarding events attached to DOM nodes. Consider the following:
http://jsfiddle.net/hXq6r/15/
Basic:
[1?] What level is the [I] (class="fixed") dom node? What level is the [II] class="container"> dom node?
[2?] How do you describe the relationship between the objects mentioned in 1? Ancestors are siblings?
[3?] When clicking the .fixed - why is the hyperlink event not triggered?
Problem:
All runs as expected. Now running this code in the Android WebView causes the problem: The click event is fired first on #button and then again on the hyperlink. I am running phonegap 1.4.1 I have no event handler attached to the hyperlink, it is just the default hyperlink event.
[4?] How is the default hyperlink event named? Click?
Advanced:
[5?] Which of the elements fires the click event first? Does it depend on the 1. level in the dom?
[6?] It seems that [I] fires first.
[7?] How can I stop the click event on [II] from firing if [I] fired previously? I just set a variable to check. Is this the best solution?
[8?] Event propagation - I assume this is of no use for this example, because we are looking at children, no ancestors. Should I delegate the event on a higher level?
Thanks : ). Hopefully this helps me with grasping the whole event basics.
Useful:
http://www.quirksmode.org/js/introevents.html
http://www.quirksmode.org/js/events_order.html