I want to inject some html using jQuery, just before some element like this:
$(element).before(content);
This content has some typeahead controls, so I need to call:
$('.ajax-typeahead').typeahead( ....
to make these control to become "typeahead".
The problem is that my page already had some Typeahead controls already configured and calling above command, mass all of them.
There is a way to apply this command only in the new content?
Before injecting the newly generated HTML element, attache the event handler to them.
$(element).before($('new content').find('newly created selectors').typeahead());
There are two main ways to achieve this: one is to call typeahead on the content prior to insertion into the DOM. The content has to be a jQuery object, e.g. $('<div>...</div>') or the likes.
var newContent = content.find('.ajax-typeahead').typeahead(...);
$(element).before(newContent);
However, this trick may fail under certain circumstances, such as for plugins that require computation of element dimensions — element dimensions are not computed prior to DOM insertion.
The alternative method is to perform DOM transversal using .prev(). However, not knowing how your content is, it might be a good idea to wrap them with a <div> or a semantically relevant element (e.g. <article>, <section>...)
$(element)
.before(content.wrap('<div />')) // Wrap content in <div> and insert prior to $(element)
.prev('div') // Transverse the DOM to access the inserted <div>
.find('.ajax-typeahead') // Find element with the class .ajax-typeahead
.typeahead(...); // Call typeahead()
Related
I am curious about how I would go about writing a one-liner to take every div and surround its contents with marquee tags using jquery. For example I would like it to take
<div class="foo">Hello <div class="bar">World</div></div>
and turn it into
<div class="foo"><marquee>Hello <div class="bar"><marquee>World</marquee></div></marquee></div>
My original attempt that failed:
$("div").each(function() $(this).html("<marquee>"+$(this).html()+"</marquee>")});
It failed when it reached nested div tags because the outermost tag's contents was replaced when its marquee tag was added thus invalidating references to the inner tags. I'm not super worried about executing JavaScript again .
How would you do this?
Consider the recommendations from other users about not using deprecated elements, but for exemplification purposes, the following solution:
From the jQuery docs about .html():
When .html() is used to set an element's content, any content that was in that element is completely replaced by the new content. Additionally, jQuery removes other constructs such as data and event handlers from child elements before replacing those elements with the new content.
The references and even events of children are removed by jQuery (well, not removed, they are just being created as new elements again, so you don't keep the previous events and references).
Don't use .html() then, and instead create a new marquee element and append the children of the original div to it, then append that marquee to the div:
$("div").each(function(){
var newMarquee = $('<marquee>');
newMarquee.append($(this).children());
$(this).append(newMarquee);
});
This is my jquery scenario:
User click on div
It triggers an ajax call to save some data on DB
when callback received, we show an update msg <--everything good
until here
Now, when user click on the same element, it shows the information
from the DB, the same should happen with the other divs!
Noticed that when you click, the same text that you saved later is showing up in all the divs!!! it is not refreshing, but the actual source IS showing
the changes!
It looks like only the DOM is not reflecting the changes!
I am trying to put the text in the divs using .text();
All the divs are using the same element id!, I am just updating its data!
Thanks,
Marco
All the divs are using the same element id! - never ever should two elements have the same ID, because it breaks the principles on which HTML is built on and 3rd party libraries rely on.
If you need to target multiple elements use classes.
In case your elements have the class yourClass and you want to set them the text "foo", then
var yourResponseText = "foo";
$('.yourClass').text(yourResponseText);
Especially if you use jQuery - the ID selector is implemented in such way, that when it finds an element with that ID it doesn't look for another - the settings will only affect the first (from the viewpoint of DOM) element. On the other hand, when you're using the class selector, then simply said you're doing a forEach cycle through the elements with that class.
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 a popup plugin which sets the html content of a <div/> with the response of an AJAX call.
Every time i open the popup, in the code i just call $("#popup").html(response). This overrides the existing html content with the new content.
Should i call $("popup").empty() before i call $("popup").html(response) so i release the browser memory used by the objects which were previously in the $("popup") div? (eventually prevent memory leaks)
PS: what if i call $("popup")[0].innerHTML = response ? should i call .empty() method?
Short answer no.
jQuery.fn.html uses DOMNode.innerHTML = after doing several other things. One is to remove any stored data on nodes (stored via $.fn.data), see http://james.padolsey.com/jquery/#v=git&fn=jQuery.fn.html for full source overview.
.innerHTML removes the children and replaces with the new html. But beware of memory leaks. I would use jQuery.fn.empty before setting innerHTML. eg.
var a = document.createElement('div'),
b = document.createElement('div');
b.appendChild(a);
b.innerHTML = 'new innerHMTL'.
You would think everything is ok. But the node replaces/removed is still captured in the varible a and therefore isn't thrown to the garbage collector. I'm not sure wether or not that jQuery stores DOMNodes internal until you call jQuery.removeData etc.
JQuery documentation of html method says:
When .html() is used to set an element's content, any content that was in that element is completely replaced by the new content. Additionally, jQuery removes other constructs such as data and event handlers from child elements before replacing those elements with the new content.
So you don't need to call empty().
No need to call empty().html(response) method ovverides the existing content.
No difference except .empty() runs faster and .html() can overwrite the content of the context
http://jsperf.com/jquery-empty-vs-html/17
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.