jquery append and appendTo - javascript

I just want to know if there is any difference (especially in terms of performance) between these two approaches:
1)
$('.container').append('<div class="divChild">test div</div>');
$('.container .divChild').click(function() { alert('test'); });
2)
var $childDiv = $('<div class="divChild">test div</div>');
$childDiv.appendTo($('.container')).click(function() { alert('test'); });
So basically the second approach seems to be much faster since I don't really have to search for the divChild div twice, but I need to add click event to the div.
Is that so?

The first point to make here is: Unless you're doing this a lot (thousands of times in a very short period of time), it's unlikely to matter.
But I would suspect the most efficient thing to do would be to remember the result of $('.container') and then use children on it:
var c = $('.container');
c.append('<div class="divChild">test div</div>');
c.children('.divChild').click(function() { alert('test'); });
Or actually, technically, you don't need the variable:
$('.container')
.append('<div class="divChild">test div</div>')
.children('.divChild')
.click(function() { alert('test'); });
But I find long chains like that hard to read, hard to maintain, and hard to debug.

Another option is:
$('<div/>', {
'class': 'divChild',
'text': 'test div',
'click': function(){
alert('test');
}
}).appendTo('.container');
http://jsfiddle.net/SANMW/

Related

is this javascript code correct?

I am trying to remove a class when clicking on an element with a specific class. I made this javascript and it does work. But is this correct syntax to do it this way Can this be more efficient?
// Clear notifications alerts
$(document).on('click', '.js-clear-notifications', function() {
$('.AlertNotifications').remove();
});
// clear inbox alerts
$(document).on('click', '.js-clear-inbox', function() {
$('.AlertInbox').remove();
});
Your javascript code is correct, provided that you load jQuery as well.
Furthermore you have the most efficient solution, where you use a single event handler to handle events that originate on multiple elements.
The alternative would be:
$('.js-clear-notifications').on('click', function() {
$('.AlertNotifications').remove();
});
Which attaches as many event handlers as there are elements in the jQuery object. Slightly less efficient, though probably you would never notice except in extreme cases.
To me a more proper way to do it is something like this:
...
$('.js-clear-inbox').on('click', function() {
$('.AlertInbox').remove();
});
...
I will also suggest to have more specific selectors i.e.
$('div .js-clear-inbox')
I hope that this helps.
I am editing this in response to the feedback in the comments.
If what you want is to remove all elements with AlertNotifications class, which is what your code does, then what you have is correct.
If what you want is to remove only the class, which is what the text of the post said, you want removeClass, not remove:
$('.js-clear-notifications').on('click',function() {
$(this).removeClass('AlertNotificitions');
}
The new way, if you have already defined the variable, the proper way to delete it from the DOM would be:
var elem = document.getElementById("myDiv");
elem.remove();
But if you are just beginning out, .remove would be your best opinion.

jQuery unbind after first click

This causes multiple buttons to take action:
$(document).on("click", ".file-this-email", fileThisEmail);
When fileThisEmail runs, I'd like to remove it from ONLY the current one (there are others on the page that still need it):
window.fileThisEmail = function(e) {
console.log('this was clicked');
}
I tried off, but couldn't seem to get it right. Any ideas?
In this case, you have to make the current element no longer match the ".file-this-email" selector.
$(document).on("click", ".file-this-email", function() {
console.log('this was clicked');
$(this).removeClass("file-this-email");
});
An alternative would be to add a filter to the selector, with the same concept.
$(document).on("click", ".file-this-email:not(.clicked)", function() {
console.log('this was clicked');
$(this).addClass("clicked");
});
Or, don't use delegation for this particular case. Delegation isn't some new technology that replaces direct binding, it's just another way of binding events. If used correctly, it can make code more efficient. The opposite is true too; if used incorrectly, it can make the code very bloated.
$(".file-this-email").on("click", function () {
console.log("this was clicked");
$(this).off("click");
});
// or even better (thanks #overachiever):
$(".file-this-email").one("click", function () {
console.log("this was clicked");
});
Bind individual handlers to each element like this:
$(".file-this-email").one("click",fileThisEmail);
What you should do is
$(document).on("click", ".file-this-email", fileThisEmail);
change this to
$(document).ready(function(){
$(".file-this-email").on("click",fileThisEmail);
$(".file-this-email").click(function(){
$(this).off("click",fileThisEmail);
});
});
The .one() method is good for this. http://api.jquery.com/one/
$(document).ready(function(){
$('.file-this-email').one('click', fileThisEmail);
});

jQuery simpler way to detach and re attach element

Sorry I could not come up with a better title. I am curious to know what the better, simpler, shorter way to write below function. Specially moving the elements around.
It basically for each img creates a parent div and places the img in there. It also adds img's title attribute in another div inside above container.
$('.view-sidebar .field-item img').each(
function(){
$(this).parent().append('<div class="img-container"></div>');
$(this).appendTo($(this).parent().find('.img-container'));
$(this).parent().append('<div class="img-caption">'+$(this).attr('alt')+'</div>');
});
I think you should just use .wrap(), there wont be need to append/detach/attach in this case.
$(this).wrap('<div class="img-container"></div>');
$('.view-sidebar .field-item img').each(function () {
var div = $('<div/>', {
class: 'img-caption',
text: this.alt
});
$(this).wrap('<div class="img-container"></div>').after(div);
});
Demo

How to use jQuery after new objects are injected into DOM?

I am making a Sentence Generator. So far, it can take a list of words. Then it gets data from sentence.yourdictionary.com to take a sentence. I display the first sentence from sentence.yourdictionary.com using $("ul.example>li").first().Then it is put into a paragraph <p id="sents">.
So if you entered in the words yo and nose your output would be
<p id="sents"><li id="yo"><strong>Yo</strong> ' money
back a hund'd times, de preacher says!</li><li id="nose">I will no longer be caught with a
bleeding <strong>nose</strong>, heart palpatations, week long benders or hurting myself in any major way.</li></p>
I want a function to be called when you hover over the new list items.
$(document).ready( function() {
$("li").hover( function () {
$(this).append("<span>Testing</span>");
var id = $(this).attr("id");
console.log(id);
}, function () {
$(this).find("span:last").remove();
});
});
This doesnt work after the new list items are injected into the DOM. I tried adding an event listener for mousemove, but then when you hover over it the word "test" shows up a bunch of times! How can I make it happen after the new list items are injected?
Here is a jfiddle if you want some clarification: http://jsfiddle.net/varhawk5/cNKyx/1/
Thank you so much. Sorry I'm just learning javascript!
EDIT
To fix this issue, I used the .on() function as the comments suggested. There is no "hover" event though, so I think this is the only way.
$("body").on("mouseenter", "li#topWord", function() {
var word = $(this).data("word");
var sents = sentences[word]
$(this).html("<div class='restOfSents' data-word='" + word +"'></div>");
for(var i=1; i<sentences[word].length; i++) {
$(".restOfSents").append($(sentences[word][i]));
}
console.log(sents);
});
$("body").on("mouseleave", "li", function() {
// Remove the new div
});
$(document).ready( function() {
$(document).on('hover','li', function () {
$(this).append("<span>Testing</span>");
var id = $(this).attr("id");
console.log(id);
}, function () {
$(this).find("span:last").remove();
});
});
You're right! The reason for this, is that $(document).ready() only gets called on page load. You can either manually add a new event hook to each new element as you add it, or take advantage of jQuery's "on" functionality which will automatically detect new dom elements which match your criteria.
You should make use of .on() rather than .hover():
$('li').on('mouseenter', function() { ... })
Also you shouldn't use IDs for this. Make use of data-* attributes instead. Otherwise your code will break when a user enters the same word twice (as IDs are unique).
var id = $(this).attr('data-example');

Do looping through items and adding handlers to it hurt performance

Does it hurt in performance when I loop through list-items and add a click-handler to all separate items?
The reason I do this is because I would only like to make the list item clickable if it contains an hyperlink.
The code I'm currently using is:
$('ul.paginator li').each(function() {
if ($('a', this).length > 0) {
$(this).css('cursor', 'pointer');
$(this).click(function() {
location.href = $('a', this).attr('href');
});
}
});
I'm not sure how much it might hurt performance, but have you considered using a somewhat simplified jQuery selector:
$('ul.paginator li:has(a)').each(
function(){
$(this).css('cursor','pointer').click(
function(){
location.href = $(this).find('a').attr('href');
});
});
Incidentally, the performance would depend on the number of elements you're searching through more than anything else. Just a few and it's likely to be imperceptible, a few thousand and it will (probably) be noticeable.
Edited to reduce the expense of has():
$('ul.paginator li a').each(
function(){
var address = this.href;
$(this).closest('li').css('cursor','pointer').click(
function(){
location.href = address;
});
});
This should be less expensive, as it will select only those a elements within an li, and then move up to affect that li element.
depends how many rows there are. If there are thousands of them, then yes. If there are a modest amount then not really enough to be noticeable.
An alternative approach would be to put the click handler on the element that contains the items, and then when a click event comes in, to use the data in the event passed to the handler to determine what to do. One handler.
Yes, it is better to use delegate with a proper selector that selects only the items you want.
There will be only one handler created and attached.
If you don't want to use has() than this will be enough (no need for multiple handlers):
$('ul.paginator').delegate('click', 'li', function() {
var link = $('a', this);
if (link.length > 0) {
location.href = link.attr('href');
}
});

Categories

Resources