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.
Related
To hopefully head off the "primarily-opinion-based" close-button-clickers, I'm not looking for opinions on the "best" way to do this; I'm just wondering if there is a more straightforward solution that I'm missing.
My goal is to add the same onclick method to all of the (hundreds of) checkboxes on my page. My first attempt at a jQuery solution was this:
$('input[type="checkbox"]').prop('onclick', function(){alert("Boop!");})
But that runs into the computed-value behavior of $.prop() and calls the function immediately for each checkbox.
So I can do this:
$('input[type="checkbox"]').prop('onclick', function(){return function() {alert("Boop!");}})
But that feels awfully workaround-y. Alternatively, I could do this:
$('input[type="checkbox"]').each(function(_, cb) {
cb.onclick = function(){alert("Boop!");};
});
But that seems uncharacteristically manual for jQuery.
So am I missing a more straightforward solution?
Declare the function and then simply refer to it by name:
function handler() { alert("Boop!"); }
$("input[type='checkbox']").on("click", handler);
Note that you shouldn't be setting up event handlers by setting the "onfoo" properties.
edit — if what you want to avoid is adding the handler over and over again, use delegation:
$("body").on("click", "input:checkbox", handler);
That creates only one event handler registration. As "click" events bubble up the DOM to the body, jQuery will check to see which ones targeted elements that match the selector, and invoke your handler for those that do. (Opinion — I've mostly adopted the practice of exclusively using body-level delegation for all events. It makes things a lot less messy.)
you have to write event no use prop:
$('input:checkbox').on('click', function(){alert("Boop!");})
i will suggest to use change event for checkbox not click:
$('input:checkbox').on('change', function(){
if(this.checked)
{
alert("checked");
}
});
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
I am trying to bind click handlers to incoming ajaxed content. I used to use 'live'
$('#div').live('click', function(event) {
alert('I got clicked, Live style');
});
But now as my site is getting more complicated, I am realizing how crazy things can get using live and having everything bubble to the top of the DOM. Which is not ideal.
So I started using on(),
$('#div').on('click', function(event) {
alert('I got clicked, On style');
});
But I miss the fact that using live() I could just initialize the click handlers once and be done with it instead of reinitialize them every time new content is loaded. Is there a best of both worlds?
Is there a better way to "reload" click handlers to recognize new ajax content aside from creating the handlers in the ajax callback function? To me that seems highly suspect. Whats the appropriate way to do this?
As of jQuery 1.7 the following .on() event binding is equivalent to the deprecated live:
$(document).on('click', '#div', function(event) {
alert('I got clicked, On style');
});
You can also bind the event to some fixed element further down the DOM which doesn't get re-generated, this functionality would be the same as .delegate():
$('#parentofdiv').on('click', '#div', function(event) {
alert('I got clicked, On style');
});
It is advisable to use the second form to narrow down the scope of the event binding as much as possible to make it easier to maintain.
Edit: For the record, what you originally did in your post would be the preferred replacement for your .bind() calls in your code.
Have you looked at using .delegate? http://api.jquery.com/delegate/
jQuery's on() method can be used to attach various events to already existing items as well as items added by ajax calls to the DOM in the future:
$(document).on("click", ".ajax-added-content", function(event) {
alert('I got clicked, On style');
});
It is possible to do what you want with
.on()
and it is actually the recommended method.
.live()
is deprecated as of jquery 1.7.
You can attach your event to the body and use this overload of "on" to get the functionality you desire. Check the next to last example in jquery's doco of .on
$("body").on("click", "#div", function(){
alert('I got clicked, On style');
});
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.
I have an group of checkboxes with id's starting with somename and I want catch the click event of these checkboxes. Previously I have done this through jQuery. i.e.:
$("input[id^='somename']").click(function(){
// my code follows here
})
but this is not working this time around. Why?
P.S. The element is created via JavaScript after the page is fully loaded after making some ajax request. I don't know if this may be the problem?
just use live if elements are created after the page is loaded.
$("input[id^='somename']").live('click', function(){ // my code follows here })
P.S : Your search selector is "somename" but you search it on the attribute ID, are you sure that you don't want :
$("input[name^='somename']").live('click', function(){ // my code follows here })
instead?
This indeed could be the problem. Replace .click with .live()
$("input[id^='somename']").live('click', function(){ // my code follows here })
and you should be fine.
Since a call to .click is just a shortcut for .bind('click', fnc), this will not work if the element is not in the DOM when calling this. Even better than using .live() would be to use .delegate(). Have a read:
.live(), .delegate()
Using the standard binding functions only works on elements that exist at the time of the bind. You need to use something called event delegation, where elements further up the DOM tree are notified of events on descendant elements. The best way to do this is with .delegate():
$('#containingElement').delegate("input[id^='somename']", 'click', function(){
// your code here
});
This assumes that you have an element #containingElement that contains all the elements that you want to capture the events on.
NB that other answers recomment live. live and delegate use the same backend code, but for various reasons delegate is more efficient.
I believe that because you want this applied to dynamically created elements in the DOM you are going to have to use the the jQuery .live() method:
$("input[id^='somename']").live('click', function(e) {
// Your code
});
Instead of .click() try .change() event.