I'm trying to - in one line - remove the parent element of a clicked element and the parent's lone sibling element. This is my two-liner solution here:
$(document).ready(function() {
$('.close').click(function() {
$(this).parent().siblings('.sibling').remove();
$(this).parent().remove();
});
});
Here's a working fiddle. I'm looking to avoid navigating the DOM twice since I've already found the parent of the clicked element when I remove the sibling, there's no reason I should be doing it again. I'm aware that I could wrap both the parent and sibling in an element and just remove that super element, but at this point I'd like to avoid that as well.
I've looked into using jQuery's .add() function, but I can't seem to get that to work. Thanks for your help!
You're looking for .addBack():
$(this).parent().siblings('.sibling').addBack().remove();
Demo
andSelf is an equivalent to .addBack() for jQuery < 1.8
With .add(), you would have to store the parent in a variable to avoid traversing to it twice:
var $father = $(this).parent();
$father.siblings('.sibling').add($father).remove();
//one-liner without storing in a variable would traverse the DOM twice:
$(this).parent().siblings('.sibling').add($(this).parent()).remove();
As you can see, the addBack method is more practical in this case.
In case the element's parent and the parent's sibling are the only elements inside their parent, you can also use:
$(this.parentNode.parentNode).empty();
Demo
The native parentNode property is a bit faster than jQuery's .parent() method. It is up to which to use.
Note that such small traversing has very little overhead either way. Your original code and these versions have very little difference performance-wise.
Related
I have a task where I need to move elements with classname clearOnHover on click to another "div" element with classname sortingContainer. For that I wrote the following code.
$("body").on('click','.clearOnHover',function(){
$('.sortingContainer').append(this);
});
"this" variable removed the tags with classname "clearOnHover" from its original place in DOM and appended it to "sortingConatiner" div.
Can you help me understand why the element was removed from the DOM, and what exactly caused it.?
http://jsfiddle.net/NMWwL/1/
append() will always remove the DOM element from it's original position. If you need to copy it, use clone() instead.
From the jquery docs :
If an element selected this way is inserted into a single location elsewhere in the DOM, it will be moved into the target (not cloned)
Is it better to attach the on() event to the document or a closer parent?
Note: Initially this question had another aspect and a different topic. It became obsolete really quickly (typo in the source code)
The best key for performance using jQuery is to use an id as the initial identifier. For example:
$('#my_id').on('click', 'tag.my_class', function () {
...
});
This allows jQuery to go straight to the container, and then begin trawling from there.
if you bind the "on" event to the closest parent will produce exactly what are you looking for, click function will works fine even if it is appended to document, but in future if you append any elements with class "clickable" will also get binded. so its always good practice to append the "on" event to closest parent rather than whole document.
if you want more specific you can use
$("ul.media-grid").on('click', 'li.clickable', function () {
alert("works")
});
as it will get the ul with the class "media-grid" and appends the event to the li's with class "clickable"
I use .append to add to a div
$(this).append('<ul><li>test</li></ul>');
how can I search for a <ul> and remove it if it exists in the children of $(this)?
You could use remove(). More information on jQuery remove().
$(this).children("ul").remove();
Note that this will remove all ul elements that are children.
The opposite of .append() is .prepend().
From the jQuery documentation for prepend…
The .prepend() method inserts the specified content as the first child of each element in the jQuery collection (To insert it as the last child, use .append()).
I realize this doesn’t answer the OP’s specific case. But it does answer the question heading. :) And it’s the first hit on Google for “jquery opposite append”.
Use the remove() method:
$(this).children("ul").remove();
What you also should consider, is keeping a reference to the created element, then you can easily remove it specificly:
var newUL = $('<ul><li>test</li></ul>');
$(this).append(newUL);
// Later ...
newUL.remove();
just had the same problem and ive come across this - which actually does the trick for me:
// $("#the_div").contents().remove();
// or short:
$("#the_div").empty();
$("#the_div").append("HTML goes in here...");
Opposite up is children(), but opposite in position is prepend().
Here a very good tutorial.
I understand that $fn.insertAfter() is used to insert element after the element supplied as the argument. How's $fn.after() different from it?
$.fn.after()help inserts an element after the target element, on which you call it.
$('div').after('<div>new div</div>');
whereas, $.fn.insertAfter inserts the target element after the node you specify:
$('<div>new div</div>').insertAfter($('#someid'));
The latter is mostly prefered, because you keep a reference to the newly created element and can chain more methods on it. So for instance:
$('<div>new div</div>')
.insertAfter($('#someid'))
.attr('foo', 'bar')
.css({
'background-color': 'red'
});
is possible. You cannot do that with .after()help. The same thing is for .append()help / .appendTo()help and .insertBefore()help / .before()help
This is an example of the same thing, the difference is the context of the selector. insertAfter inserts the selected element after the parameter
after inserts the parameter after the selected element.
$('<div id="foo"></div>').insertAfter('#bar');
$('#bar').after('<div id="foo"></div>');
Quoting straight from the documentation:
The .after() and .insertAfter()
methods perform the same task. The
major difference is in the
syntax—specifically, in the placement
of the content and target. With
.after(), the selector expression
preceding the method is the container
after which the content is inserted.
With .insertAfter(), on the other
hand, the content precedes the method,
either as a selector expression or as
markup created on the fly, and it is
inserted after the target container.
This mentions that they perform the same task but have different syntax.
When a user clicks on a <li>-element or on a child element of it, I want to add a class to this <li>-element.
This works fine, but for performance enhancement I decided to bind this event to the <ul>-element, so unbinding and binding this event is much faster in a list consisting of 1000 <li>-elements. The only change I thought I had to make was to replace this with event.target BUT event.target can also refer to a child element of a list item or even to a grandchild.
Is there an easy way to check this target element is part of a list item or do I need to walk the path from event.target till I reach a <li> element?
This is what I had before I decided to bind an event to the <ul> tag, which works but is not fast enough:
$('#list li').mousedown(function(){
$(this).addClass('green');
});
And this is what I have now which doesn't work properly, mousedown on a child element doesn't give the <li> another classname:
$('#list').mousedown(function(event){
if(event.target.nodeName == 'LI'){
$(event.target).addClass('green');
}
});
I wonder if my second way to achieve this is faster if there is not a simple solution to check if that target element is part of a list item...
Well, you could do all of this with the jQuery on tool:
$('#list li').on('mousedown', function() {
$(this).addClass('green');
});
You can read about what on does here: http://api.jquery.com/on/
You need to check if there is a LI tag in the parents of the target element.
All of the common frameworks have a way of determining this, it is up() in prototype, ancestor() in YUI3, and looking at the JQuery docs, it seems like it has a parent(), and parents() function that you can use for this.
See: http://docs.jquery.com/Traversing
Haven't used JQuery, but it I assume checking for $(event.target).parent('li') is the answer.