I have the following set in my JS:
$('.selector').selectpicker();
When new DOM elements are added to the page, the above method doesn't work on the new DOM elements. I know that, in other cases, I can do the following such that newly added DOM elements work:
$(document).on("click", ".class-here", function() {
});
But how can a method like the first changed to work with new DOM elements (rather than calling that same method again)?
The answer will depend on the function you're calling (here selectpicker).
If you're talking about the bootstrap function, you would do:
$('.selector').selectpicker("refresh");
After having changed the DOM.
You might use the level 3 event for DOM node creation, like .on("DOMNodeInserted",(selector),(function)) to execute your function whenever an element fitting the selector is inserted. See How to catch creation of DOM elements and manipulate them with jQuery
Your problem is regarding binding new element in DOM, Prior version of jquery use bind and unbind method for new element in dom.
But If you use jQuery 1.3+ then you can write
$('selector').live('event',function (){ //do some action });
In above jquery, You didn't need to bind/unbind element on DOM.
But latest version of jQuery 1.7+, You can directly use .on() method which you mentioned above, It mean that you didn't care to bind, unbind on 'DOM change'.
On() is simple that you can write common callback for multiple events on particular selector.
I hope that this details is useful to you and you got your answer. If you use 'on()' then you not need to bind element in DOM.
Related
I’ve read many posts already on the $.each and newly added elements + event attachment. Many of the current Questions regarding this topic on StackOverflow don’t seem to work for me. $.on() is normally recommended since it allows us to append new elements and still maintain a single event listener + handler.
In my current code:
1.$(‘input[type="checkbox"]’).on(“change”, function(e){});
//I do a logical if-statement, if(this.checked) else
//With-in the if-statement I run $.each, however, once I have appended new element in this context a new li to the ul, it stops working.
Out of the curiosity has anyone encountered something like this before, and if YES, how have you folks solved this?
Some StackOverflow posts I have already seen:
jQuery $(element).each function doesn't work on newly added elements
jquery: dynamically appending li items to ul then adding click, but click runs through each li
Event binding on dynamically created elements?
Currently what you are using is called a "direct" binding which will only attach to element that exist on the page at the time your code makes the event binding call.
Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time.
As you are creating elements.
You need to use Event Delegation. You have to use .on() using delegated-events approach.
General Syntax
$(document).on(event, selector, eventHandler);
Ideally you should replace document with closest static container.
Example
$(document).on('change', 'input[type="checkbox"]', function(){
//Your code
});
I have been searching this on internet, I have found some answers which were helpful like but they were not enough to solve my problem (e.g.
Similar Problem but no solution provided for my problem)
I am using JRate plugin, I am adding a div inside a div using jQuery. The problem is that when I add it using jQuery and use the JRate Functions then they are not working. But they are working without appending a new div.
I know how to make it work. I will have to use $(document) but I dont know how to use it with this code.
Here is HTML
<div class="jRate"></div>
Here is my Jquery
$(".jRate").jRate({
onSet: function(rating) {
alert(rating);
}
});
Here is my appending code
var divjRate = "<div class='jRate'></div>";
$(divjRate).appendTo('.fb-jRate');
Can any one tell me how can I use $(document) here or any other alternative solution you have.
You need to append the html element first so that it is registered in the DOM. Then, you can call jRate on it
var divjRate = "<div><div class='jRate'></div></div>";
// Append new element to container of choice
$(divjRate).appendTo('.fb-jRate');
// Use plugin on new element
$('.jRate').jRate({
onSet: function(rating) {
alert(rating);
}
});
The solution you have linked applies to binding event listeners, which is not the case with a typical jQuery plugin that usually involves DOM replacement and other things.
You will need to apply the method to newly added DOM elements. The DOM mutation event specification is deprecated due to performance issues, and it is not realistic to expect the browser to keep track of all changes (and what kind of changes) happening in the DOM.
For example, if you're adding new content with an AJAX call, you can apply the method to newly added content within the jqXHR.done() function.
Update: OP provided with some code, so I have adding a way to initialize the plugin for newly added DOM element:
// Declare new element
var divjRate = "<div><div class='jRate'></div></div>";
// Use plugin on new element
$(divjRate).find('.jRate').jRate({
onSet: function(rating) {
alert(rating);
}
});
// Append new element to container of choice
$(divjRate).appendTo('.fb-jRate');
I have two codes. This one works like a charm-
$("input:radio").on('change',showRatingSection);
But this one throws "Object has no method 'live'" error-
$("input:radio").live('change',showRatingSection);
Any ideas why?
If I assume that you can't call live method on radios, then how would I bind an event on the radios which will be added to my DOM in future? I know I can bind as soon as they get added but I am looking for an alternative to live() if it can't be used with radios.
Use the best method!
$("body").delegate('input:radio','change',function(){
//do code here
});
This work with AJAX, without ajax. I had the similar problem with "live" function too, but since I use this anywhere, I have no problem at all.
You can try this, it's called Event Delegation: elements that are generated dynamically in the DOM you can fire events using the syntax following
$(document.body).on('click', "input:radio", showRatingSection);
and .live() has been deprecated since 1.7 version of jQuery
document.body refers to the closest parent element in the DOM,
Delegate the event:
$(document).on('change', "input:radio", showRatingSection);
"Object has no method 'live'"
Yes because in the latest jQuery versions live has been removed.
I am looking for an alternative to live()
Yes you have an alertnative to this as suggested in this answer and others, with use of .on() it has a special syntax for it.
$(document).on('event', "selector", function);
Note:
Delegating to $(document) is very costly (in terms of performance) so you should always try to delegate to the closest static parent (Which was available at the doc ready).
Also there is a point if you are delegating to the closest static parent you should put that event inside doc ready block but if you are delegating to $(document) then there is no need to put it in doc ready block.
Functions on JavaScript/jQuery selectors apply to elements that were on the page before the function is read. For example,
$('.foo').css('color', 'red');
applies to elements with class foo at the time this part of code was read, but do not apply to elements that were inserted later via JavaScript/jQuery functions such as append(), etc. Is there a way to define a hook that applies automatically at the time when an element is inserted?
Using $('.foo') as your selector will match all elements with the foo class whether they've been added after load or not.
For events:
.live() has been removed from newer versions of jQuery so you should use .on(). Here's an example:
$(document).on('click', '.foo', function(){
// click event code here
});
This event will match .foo elements when the page loads as well as any which are loaded via .append(), .html() etc.
UPDATE:
I think I understand what you mean now. There's a plugin called Live Query which should solve your problem. Just include it then use:
$('.foo').livequery(function() {
$(this).css('color', 'red');
});
Here's a working demo: http://jsfiddle.net/5jJAE/
I'm not sure I completely understand your question but let me try and answer.
Dynamic Elements do count!
When you call a method on a JQuery selector it applies to all objects in the DOM that match your selector criteria.
Just to be clear, this includes elements that were added dynamically. For example, take the method "hide" below, applying to a dynamically inserted element.
$('body').append('<h1 id="test" style="display:none;">HI!</h1>');
$('#test').show();
So, it's not that JQuery won't apply to dynamically inserted elements, BUT it just won't apply to elements that don't exist yet. In other words, it won't apply to any elements that are added AFTER your call.
The live() method
However, JQuery does have a clever little method called "live()" which might apply to your needs.
Description: Attach an event handler for all elements which match the current selector, now and in the future.
http://api.jquery.com/live/
Update - live() is deprecated but on() can be used
The replacement to live() is on(). However on() doesn't work quite like live() and to make it work for future elements you have to place an "on" event handler in the PARENT element of future elements.
See this answer for more detailed info: Turning live() into on() in jQuery
I'm semi-new to Javascript/jQuery so apologies in advanced if I'm missing something basic. I have a function that is triggered whenever a user types in an element with a specific class.
$('.relevantClass').keyup(function(){
//code...
});
Now this function may end up, depending on the situation, creating a good deal of new HTML including new instances of relevantClass through the .append() method.
var newHTML = <div class='relevantclass'>Content...</div>;
$('#wrapper').append(newHtml);
However, the jQuery selector does not seem to detect and execute the function when a user types in the newly created relevantClasses. I've checked the newly created Html and it has the correct class tags and old instances of the relevant class due work.
I'm guessing this has something to do with .append(); messing with the DOM and I need someway to "refresh" the selector and let it do its jQuery thing researching the DOM to find the new classes. Any thoughts on how to do this? Is there some jQuery method I can't find?
You have to use on() to attach events that work on dynamic content:
var $parent = $("selector"); //the element you're appending .relevantClass to
$parent.on("keyup",".relevantClass",function(){
//code...
});
Keep in mind that to work with dynamic content, you have to attach the event to relevantClass's closest parent that exists on page load.
Some people use body, but you should get used to using parent elements as close as you can get to the dynamic content. This is so that event delegation occurs on a smaller scale.
More info on on() here.
Also, I hope that newhtml variable is wrapped in quotes.
$('.relevantClass').on('keyup', function(){
//code...
});
Try something like
$('body').on('keyup', '.relevantClass', function() { ... }
The idea is that you use an existing root element and use your class selector as a filter. See the examples here.