jQuery .change() event is triggered with .click() in newer versions? - javascript

I'm currently upgrading my application to use jQuery 1.6.1 (previously using 1.4.4) and found that now the .click() event automatically triggers a .change() event as well.
I created a simple example here: http://jsfiddle.net/wDKPN/
Notice if you include 1.4.4 the .change() function will not fire when the .click() event is triggered. But when switching to 1.6, the .change() event is fired when .click() is triggered.
Two questions:
Is this a bug? It seems that programmatically triggering .click() shouldn't also fire other events (for example, it would seem wrong to also automatically fire .blur() and .focus(), to help "mimic" a user's click).
What is the proper way for me to bind a change() event and then trigger both a click() and change() event for that element? Do I simply call .click(), and rely on the fact that .change() will also fire?
$('#myelement').change(function() {
// do some stuff
});
$('#myelement').click(); // both click and change will fire, yay!
In my old code I'm using this pattern to initialize some checkboxes (and their checked states and values) after an ajax call:
$('#myelement').change(function() {
// do some stuff including ajax work
}).click().change();
But in 1.6.1 my logic fires twice (once for .click() and once for .change()). Can I rely on just removing the .change() trigger and hope that jQuery continues to behave this way in future versions?

Best way to do this is:
$('#myelement').bind('initCheckboxes change', function() {
// do some stuff including ajax work
}).trigger('initCheckboxes');
To do your initialization stuff you just bind to it a custom event, which you trigger it the first time the page loads. This, no one will take away from you on any versions.
Whereas change event, I believe, will continue to be there on all versions, because it has been for so long, and it just works nicely that way.
In the end, this is a happy ending story, because the custom event initCheckboxes will fire just once on page load and change event will always listen and fire on change state.

I would say this was a bug in jQuery 1.4.4. Removing the jQuery event handlers and using standard addEventListener produces the same result as jquery 1.6.1.
http://jsfiddle.net/jruddell/wDKPN/26/
window.count = 0;
document.getElementById('mycheckbox').addEventListener('change', function() {
window.count++;
jQuery('#output').append('I fired: ' + window.count + ' times<br />');
});
document.getElementById('mycheckbox').click();
Also I would use triggerHandler to specifically invoke a jQuery event handler. If you want the event model to determine which handlers to call, then use click, change etc.

Forget about the click event for checkboxes. The change event handles everything.
$('#myelement').change(function() {
// do some stuff
});
$('#myelement').trigger('change');
See for yourself: http://jsfiddle.net/zupa/UcwdT/
(This demo is set to jQuery 1.8 but works in 1.6 as well.)

I think you can make it work for both jQuery 1.4.4 and 1.6 implementations by putting change() within click handler and then triggering the click.
$('.myelement').click(function(){
$('.myelement').change();
alert($(this).val());
});
$('.myelement').trigger('click');
Have a look there for simple example.

Related

jQuery $(window).blur vs native window.onblur

What are the advantages of using jQuery's
$(window).blur(function() { ... })
to attach an event handler versus setting it directly with
window.onblur = function() { ... }
It seems that the latter is less robust because it only supports one blur handler, and when used with other packages, other code might override the window.blur value with another function. However, couldn't this also happen with the jQuery implementation too, which presumably uses window.blur as its underlying implementation?
EDIT: Several people have also mentioned the window.addEventListener alternative, which can be used to add an 'onblur' event apart from the methods above.
$(window).blur(function() { ... })
Lets you add one or more event handlers.
window.onblur = function() { ... }
Lets you only have one event handler handling the blur event.
The former uses the jQuery's own event handle mechanism. The call to .blur() will delegate to jQuery.fn.on() which in turn will delegate to jQuery.event.add. This add() method will create it's own handler for the given event type and tell addEventListener() to call this handler whenever a event of given type is fired. So basically jQuery has it's own way of event handling which relies on addEventListener() to execute properly.
The latter is just an attribute which can only contain one value so queueing event handlers is impossible.
I wrote a little demonstration to prove this point: http://jsfiddle.net/GnNZm/1/
With the jQuery method, you can attach multiple event handlers. By setting window.onblur, you can only have a single handler.
Pure JavaScript also has this: window.addEventListener(). In fact, i'm sure jQuery uses this internally. (Yes they do.)
(EDIT)
The window.onblur property is basically a shortcut for setting a single handler. Using addEventListener() (or the jQuery wrapper) basically creates a list of event handlers, which all get fired when the event happens. I haven't tested, but i think you can even use the two together. Because it's a list, not a single value, multiple handlers shouldn't interfere with each other. They can also be removed separately or all at once.
jQuery's event handlers, using on(), also let you namespace your handlers, to prevent clashes if a plugin removes its handlers. Pure JS doesn't seem to have this easily.
For jquery blur
The blur event does not bubble in Internet Explorer. Therefore,
scripts that rely on event delegation with the blur event will not
work consistently across browsers. As of version 1.4.2, however,
jQuery works around this limitation by mapping blur to the focusout
event in its event delegation methods, .live() and .delegate().
taken from jquery doc https://api.jquery.com/blur/
Also jquery allows you bind multiple event handlers
When you attach an event there is the possibility of overwriting an event already attached to an event handler. This used to happen a lot with window.onload() where different scripts overwrote each others event handlers.
eg:
//lightbox.js
window.onload = function() { /* do lightbox stuff */ }
//carousel.js
window.onload = function() { /* do carousel stuff */ }
So the common practice used to be something like this:
var existing_event_handlers = window.onload;
window.onload = function(){
//my event code
alert('onready fired');
//call other event handlers after
existing_event_handlers();
}
Using window.onblur = function() { ... } still has an advantage because you can specifically dictate if you want your event fired before or after other attached events.
Like many other answers already pointed out jQuery abstracts you from most browser differences. Version before IE9 used attachEvent() rather than addEventListener().

jQuery .on trigger event listener

There is a best practice to invoke a jQuery change handler immediately afters its definition to re-use the code and initialise the GUI, like
$("#mySelect").change(function() {
$("#myTextField").val( $(this).text());
}).change(); // here the element is immediately triggered, so one does not need a separate code path for the init-case
Without the immediate call using .change() the GUI would not reflect the initial value of #mySelect in #myTextfield.
With newer versions of jQuery I would like to use event-delegation and do the same stuff using the .on() API.
$("#myForm").on('change', '#mySelect', function() {
$("#myTextField").val( $(this).text());
}).change();
This does not work anymore, because the .change() is not triggered on the right element and not with the right event.target, so jQuery can't call my event handler.
This works, but does no longer reflect the best practice without the separate init code-path:
$("#myForm").on('change', '#mySelect', function() {
$("#myTextField").val( $(this).text());
});
$("#mySelect").change();
Question: Any good way to solve this, without re-selecting the element and triggering the event?
You would need to find all the elements and call trigger on them... Because delegation delegates the handling to some other element up the DOM (as you likely know)
You would essentially have to do what you have done in your 3rd example. I know of no other way to achieve this.

jQuery On() is not working for $(document)

I am currently in the process of integrating the dropkick.js plugin into my app, but I have run into a few snags. When I change backbone views the events do not work properly and the .live() event associated in dropkick.js just flat out doesn't work at all. Nothing fires. I decided to upgrade this to using the .on() function and got it sort of working (even though it still deletes my url for some reason).
This doesn't work at all:
$(document).on("click", ".dk_toggle", function() {
This only works somewhat:
$(".content").on("click", ".dk_toggle", function() {
Do you know why document doesn't work at all?
My backbone $el is $(".content").
Instead of document, use body. It basically gives the same behavior.
$('body').on("click", ".dk_toggle", function() {
//....
});
The first example demonstrates event delegation.
The second example binds the event handler directly to the element. The event will still bubble (unless you prevent that in the handler) but since the handler is bound to the target, you won't see the effects of this process.
Test Run

Listening to Trigger

I am using a library that when complete will trigger an event via $(document).trigger('playlistDone');. I am listening to this trigger but I am not getting the alert() I am expecting.
$(document).bind('playlistDone', function() {
alert('done');
});
What am I doing wrong?
First off, as of jQuery 1.7 the preferred method for attaching events is on, not bind (see http://api.jquery.com/on/).
Second, your basic syntax looks ok, but it's important to understand you're dealing with custom events, not browser events. This means that your library must be using jQuery to trigger its event, or else jQuery won't detect it when it happens.
Use .on(). From jQuery documentation :
The .on() method attaches event handlers to the currently selected set
of elements in the jQuery object. As of jQuery 1.7, the .on() method
provides all functionality required for attaching event handlers.
Try something like that:
$(document).on('playlistDone', function( a ) {
alert( a );
});
and
var data = 'Done';
$(document).trigger('playlistDone', data );

How can I execute EventListener 'click' from JavaScript

I have event listener myObject.addEventListener('click',this.doSomething,false) on element.
It works fine when I do mouse click but I cannot figure out how to trigger click from JavaScript. It seems like element.click() does not work for divs?
I am using jQuery and I have also tried trigger('click') but nothing is happening.
How can I in JavaScript execute the EventListener?
Update:
Here is sample code http://jsbin.com/iniwi5/2
Can you bind the event using jQuery instead?
$(myobject).click(function() {
});
Then
myobject.trigger('click');
would programmatically trigger the click.
To trigger a click event listener added via addEventListener, you need to manually dispatch a click event, using either dispatchEvent (for standards-compliant browsers) or fireEvent (for IE < 9).
Try this:
myObject.click; // no `()`
OR:
(myObject.click)();

Categories

Resources