Javascript Event Bubbling/Caputuring - javascript

Since every browser works different, whats the approach for a well working website?
I Mean i cannot know if I want attach it to bubbling or capturing phase since I don't know what the different Browser do first. And I don't want to write code for every browser. Corrent me if I'm wrong, but I read that every browser acts different.
So do I have to add a listener to every "child-widget" i have on the website and do stopPropagation() and cancelBubble = true; in every listener to have wanted behaviour for sure?

I Mean i cannot know if I want attach it to bubbling or capturing
phase since I don't know what the different Browser do first.
The behavior of events is fully defined in the DOM spec. The capture phase happens before the bubble one. See the following graphic from Event dispatch and DOM event flow:
Modern browsers are compliant.
Correct me if I'm wrong, but I read that every browser acts different.
Only old browsers behave unreliably.

Related

How to tell what Javascript event just fired

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.

How do I show all events firing in a web page without using a plugin/extension?

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.

Unbind inline javascript events from HTML elements in memory

How do I completely unbind inline javascript events from their HTML elements?
I've tried:
undelegating the event from the body element
unbinding the event from the element
and even removing the event attribute from the HTML element
To my surprise at least, only removing the onchange attribute (.removeAttr('onchange')) was able to prevent the event from firing again.
<input type="text" onchange="validateString(this)"></input>
I know this is possible with delegates and that's probably the best way to go, but just play along here. This example is purely hypothetical just for the sake of proposing the question.
So the hypothetical situation is this:
I'm writing a javascript validation library that has javascript events tied to input fields via inline HTML attributes like so:
<input type="text" onchange="validateString(this)"></input>
But, I'd like to make the library a little better by unbinding my events, so that people working with this library in a single-page application don't have to manage my event handlers and so that they don't have to clutter their code at all by wiring up input events to functions in my hypothetical validation library... whatever. None of that's true, but it seems like a decent usecase.
Here's the "sample" code of Hypothetical Validation Library.js:
http://jsfiddle.net/CoryDanielson/jwTTf/
To test, just type in the textbox and then click elsewhere to fire the change event. Do this with the web inspector open and recording on the Timeline tab. Highlight the region of the timeline that correlates to when you've fired the change event (fire the change event multiple times) and you'll see the event listeners (in the window below) increase by 100 on each change event. If managed & removed properly, each event listener would be properly removed before rendering a new input, but I have not found a way to properly do that with inline javascript events.
What that code does is this:
onChange, the input element triggers a validation function
That function validates the input and colors the border if successful
Then after 1 second (to demonstrate the memory leak) the input element is replaced with identical HTML 100 times in a row without unbinding the change event (because I don't know how to do that.. that's the problem here). This simulates changing the view within a single-page app. This creates 100 new eventListeners in the DOM, which is visible through the web inspector.
Interesting Note. $('input').removeAttr('onchange'); will actually prevent the onchange event from being fired in the future, but does not garbage collect the eventListener/DOM stuff that is visible in the web inspector.
This screenshot is after change event fires 3 times. Each time, 100 new DOM nodes are rendered with identical HTML and I've attempted to unbind the onchange event from each node before replacing the HTML.
Update: I came back to this question and just did a quick little test using the JSFiddle to make sure that the answer was valid. I ran the 'test' dozens of times and then waited -- sure enough, the GC came through and took care of business.
I don't think you have anything to worry about. Although the memory can no longer be referenced and will eventually be garbage collected, it still shows up in the Web Inspector memory window. The memory will be garbage collected when the GC decides to garbage collect it (e.g., when the browser is low on memory or after some fixed time). The details are up to the GC implementer. You can verify this by just clicking the "Collect Garbage" button at the bottom of the Web Insepctor window. I'm running Chrome 23 and after I enter text in your validation box about 5 or 6 times, the memory usage comes crashing down, apparently due to garbage collection.
This phenomenon is not specific to inline events. I saw a similar pattern just by repeatedly allocating a large array and then overwriting the reference to that large array, leaving lots of orphaned memory for GC. Memory ramps up for a while, then the GC kicks in and does its job.
My first sggestion would have been to use off('change') but it seems you've already tried that. It's possible that the reason it's not working is because the handler wasn't attached with .on('change'). I don't know too much about how jQuery handles listener like this internally, but try attaching with .on('change', function ()... or .bind('change', function ()... instead.

How do i turn this jQuery to javascript?

I have a facebook connect button on this site here is the code
<fb:login-button onlogin="javascript:jfbc.login.login_button_click();"
perms="email,publish_stream,user_about_me,user_hometown,user_location,user_birthday,user_religion_politics,user_interests,user_activities,user_website"
size="medium" v="2"><a class="fb_button fb_button_medium">
<span class="fb_button_text"\>Login With Facebook</span></a></fb:login-button>
and i want to trigger this button with a javascript call and doing research i found this jquery that seems that it would do the trick (havent tested though) and i was wondering if there is an equivelent javascript or mootool because jquery is not installed. I can install it if i cant find a solution. Or if anyone has another idea on how to trigger this facebook button
$("fb\:login-button").trigger("click");
There are two ways to "trigger" a listener:
call it directly (e.g. element.onclick())
dispatch an event into the DOM that the listener will respond to
The trouble with the first method is that it doesn't replicate a bubbling event so the listener may not work as intended (e.g. there is no associated event object or bubbling, the listener's this keyword may not be correctly set).
The trouble with the second is that some browsers will not allow programatically dispatched events to do certain things (click on links for example). Also, in some browsers you have to use the W3C dispatchEvent and in others the Microsoft fireEvent.
So unless the listener has been designed specifically to work with one method or the other and is called appropriately, your chances of triggering the listener successfully are quite low.
PS. Some libraries provide their own event system, with custom events and bubbling of otherwise non-bubbling events, but in that case you have to set and trigger the listener using that library, otherwise it will probably not respond to either of the above methods.
You should be able to just invoke the same code that is invoked inline:
jfbc.login.login_button_click();
I suppose it would be something like
document.getElementsByTagName("fb\:login-button")[0].click();
I'm sure that would work very well with a "normal" DOM element that handles the click event; however, I'm not entirely sure it will work in all browsers with the fb:login-button element shimmed into HTML. You'll have to let me know.
Looks like you should be able to do:
document.body.getElementsByTagName("fb\:login-button")[0].click();
It looks like you want a namespaced element selector, so you should use:
document.getElementsByTagNameNS('fb', 'login-button')[0].click();
The : is the namespace separator.
I ran into this tonight, absolutely positioned a new button image over the iframe, and was planning on using pointer-events:none to pass through and click the iframe, but I was looking for a cross-browser solution, here you go.
jQuery('.button_fb_connect').live('click', function(){ FB.login() })
Your simply running the js function FB.login() after clicking your new element, obviously you can use whatever event you want.
Thats in jQuery of course, but thats the function you want, not just a simple click event trigger.

Event fired on select box (html) being populated

I've been wondering if browsers fire any event when select box is dynamicaly populated? I would expect 'onchange' being fired, but that doesn't happen.
As it has been pointed out already, onchange event is responsible for User-made changes. However, when you change the DOM programmatically, the DOM Mutation event is fired by some browsers, but that standard is not very well supported.
Mutation events might be what you're looking for. They feature options like DOMSubtreeModified, DOMNodeInserted, and some others. Apparently there is a jQuery project on github to include support for Mutation-events. Check it out at http://github.com/jollytoad/jquery.mutation-events/tree/master
Not that I'm aware of. For the most part, the only events that are dispatched are those initiated by the user.
A <select> receiving new options is technically initiated by the browser (even though it may happen as a result of a user action).
Although I agree that it would be particularly useful and cool if you could listen for changes on any arbitrary DOM property and bind handlers to react to those changes.
You can, however, look into a signals and slots implementation in javascript which might help you.

Categories

Resources