why method remove is working like method detach in jquery [duplicate] - javascript

What is the functional difference between these three jQuery methods:
detach()
hide()
remove()

hide() sets the matched elements' CSS display property to none.
remove() removes the matched elements from the DOM completely.
detach() is like remove(), but keeps the stored data and events associated with the matched elements.
To re-insert a detached element into the DOM, simply insert the returned jQuery set from detach():
var span = $('span').detach();
...
span.appendTo('body');

Imagine a piece of paper on a table with some notes written with pencil.
hide -> throw a clothe onto it
empty -> remove the notes with an eraser
detach -> grab the paper in your hand and keep it there for whatever future plans
remove -> grab the paper and throw it to the dustbin
The table represents the current DOM space, the paper represents the element, and the notes represent the contents (child nodes) of the element.
A bit simplified and not completely accurate, but easy to understand.

hide() sets the matched element's display to none.
detach() removes the matched elements, including all text and child nodes.
This method stores all the data associated with the element and so can be used to restore the element's data as well as event handlers.
remove() also removes the matched elements, including all text and child nodes.
However, in this case only the element's data can be restored, not its event handlers can't.

In jQuery, there are three methods for removing elements from the DOM. These three methods are .empty(), .remove(), and .detach(). All these methods are used for removing elements from the DOM, but they all are different.
.hide()
Hide the matched elements. With no parameters, the .hide() method is the simplest way to hide an HTML element:
$(".box").hide();
.empty()
The .empty() method removes all child nodes and content from the selected elements. This method does not remove the element itself, or its attributes.
Note
The .empty() method does not accept any argument to avoid memory leaks. jQuery removes other constructs, such as data and event handlers, from the child elements before removing the elements themselves.
Example
<div class="content">
<div class="hai">Hai</div>
<div class="goodevening">good evening</div>
</div>
<script>
$("div.hai").empty();
</script>
This will result in a DOM structure with the Hai text deleted:
<div class="content">
<div class="hai"></div>
<div class="goodevening">good evening</div>
</div>
If we had any number of nested elements inside <div class="hai">, they would be removed too.
.remove()
The .remove() method removes the selected elements, including all text and child nodes. This method also removes the data and events of the selected elements.
Note
Use .remove() when you want to remove the element itself, as well as everything inside it. In addition to this, all bound events and jQuery data associated with the elements are removed.
EXAMPLE
Consider the following html:
<div class="content">
<div class="hai">Hai</div>
<div class="goodevening">good evening</div>
</div>
<script>
$("div.hai").remove();
</script>
This will result in a DOM structure with the <div> element deleted:
<div class="content">
<div class="goodevening">good evening</div>
</div
If we had any number of nested elements inside <div class="hai">, they would be removed too. Other jQuery constructs, such as data or event handlers, are erased as well.
.detach()
The .detach() method removes the selected elements, including all text and child nodes. However, it keeps data and events. This method also keeps a copy of the removed elements, which allows them to be reinserted at a later time.
Note
The .detach() method is useful when removed elements are to be reinserted into the DOM at a later time.
Example
<!doctype html>
<html>
<head>
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<p>Hai!</p>Good <p>Afternoo</p>
<button>Attach/detach paragraphs</button>
<script>
$( "p" ).click(function() {
$( this ).toggleClass( "off" );
});
var p;
$( "button" ).click(function() {
if ( p ) {
p.appendTo( "body" );
p = null;
} else {
p = $( "p" ).detach();
}
});
</script>
</body>
</html>
For more info, visit: http://www.scriptcafe.in/2014/03/what-is-difference-between-jquery_15.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
</head>
<body>
<script>
$(document).ready(function(){
var $span;
$span = $("<span>");
$span.text("Ngoc Xuan");
function addEvent() {
$span.on("click",function(){
alert("I'm Span");
});
}
function addSpan() {
$span.appendTo("body");
}
function addButton(name) {
var $btn = $("<input>");
$btn.attr({value:name,
type:'submit'});
if(name=="remove"){
$btn.on("click",function(){
$("body").find("span").remove();
})
}else if(name=="detach"){
$btn.on("click",function(){
$("body").find("span").detach();
})
}else if(name=="Add") {
$btn.on("click",function(){
addSpan();
})
}else if(name=="Event"){
$btn.on("click",function(){
addEvent();
})
}else if (name == "Hide") {
$btn.on("click",function(){
if($span.text()!= '')
$span.hide();
})
}else {
$btn.on("click",function(){
$span.show();
})
}
$btn.appendTo("body");
}
(function () {
addButton("remove");
addButton("detach");
addButton("Add");
addButton("Event");
addButton("Hide");
addButton("Show");
})();
});
</script>
</body>
</html>

Related

jQuery transform both existing and dynamically created elements

Suppose I want to transform all (existing and dynamically created) <a> tags having a data-params property, e.g. by setting the href attribute.
It seems that this code:
$('body').on('change', 'a[data-params]', function() { ... })
only works on dynamically created elements, not existing elements.
On the other hand, this code:
$('a[data-params]').each(function(index) { ... });
only works on existing elements.
So if I want both (existing and dynamically created), I need both codes, ideally defining my transformation function first, then:
$('a[data-params]').each(function(index) { processDataParams(this); });
$('body').on('change', 'a[data-params]', function() { processDataParams(this); });
or am I missing some simpler way to do this?
$('a[data-params]') returns all nodes with this data attribute. Always.
I think that the problem is before, in the creation of dinamic elements. Avoid use the jQuery data method when you add the elements, because it does not update the DOM (don't adds the desired data-params attribute).
// Add some elements to the current doc
['magenta', 'olive'].forEach(color => {
$('<a>', {html:color})
// .data('params', color) <-- this don't updates de DOM, 👎 jQuery
.attr('data-params', color)
.appendTo('#root')
})
// Element unable to find with $('a[data-params]')
$('<a>', {html: 'This elemnt won\'t update'})
.data('params', 'purple')
.appendTo('#root')
function transform() {
$('a[data-params]').each((i, node) => {
$(node).css('color', $(node).data('params'))
$(node).attr('href', '#' + $(node).data('params'))
})
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="display: flex; flex-direction: column" id="root">
<a data-params='red'>red</a>
<a data-params='blue'>blue</a>
<a data-params='green'>green</a>
</div>
<hr>
<button onclick="transform()">Transform Elements</button>
Edited with the corrections of #Spectric and #RokoC.Buljan. Thanks to all.
You can use Jquery Event Delegation to run code (an event listener) on all child (internal) elements of an element, whether or not they already exist (because its set on the parent, which does already exist). You can read more about Event Delegation in JQuery's docs - https://learn.jquery.com/events/event-delegation/
Example:
$('ul').on('click', 'li', function(event) {
//code that will run on al <li> element clicks
});
this code is set on ul element, and allows an event listener to be set for all current and future li elements that are within the ul.

.on click does not return .closest of "e"

I am trying to get the text inside a <h4> that is closest to my clicked icon <i>
The following registers the click OK, but it does not return the value inside the h4. Instead, it returns a very long array of details as you can see, too long for Codepen:
<p class="icon heart">
<i>icon</i>
</p>
<h4>this text</h4>
$('body').on('click', '.icon.heart i', function(e){
var property = [];
console.log('clicked!');
console.log($(e).closest( ".intro-text h4" ));
});
Where am I going wrong?
http://codepen.io/franhaselden/pen/pboYvZ
EDIT:
I have updated the HTML to be more representative of my code layout. How can I access the content inside the <h4>?
https://jsfiddle.net/0jsxjqzx/3/
Your first problem is that e is an Event object, not a DOM Element.
You, presumably, mean this or e.target
You then have a second problem (which I didn't notice at first because you failed to include the HTML in the question, I fixed that for you).
Look at the documentation of closest:
For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
The h4 is not an ancestor of the italic text! So it won't be found.
You need to go up to the paragraph and then find its sibling instead.
$(this).closest("p").next("h4");
You can do it like this:
$(document).ready(function() {
$('body').on('click', '.icon.heart i', function() {
var property = [];
console.log('clicked!');
console.log($(this).closest(':has(.intro-text)').find('h4').html());
});
});
Full example here: https://jsfiddle.net/cn8trrhn/
You were missing the closing parenthesis on the last console.log.
h4 is not a parent of i, so closest won't work, you may want to use nextAll .
jQuery(document).ready(function() {
$('.iconheart').on('click', function(){
var property = [];
console.log('clicked!');
console.log($(this).nextAll( "h4" ).html());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="iconheart">
<i>icon</i>
</p>
<h4>this text</h4>

jQuery .text() on multiple elements within the same class

I'm attempting to use .text() on multiple (unknown number of) elements on a page.
Consider:
<div class="myClass">element1</div>
<div class="myClass">element2</div>
<div class="myClass">element3</div>
and
$(document).ready(function(){
$( ".myClass" ).click(function() {
var text = $('.myClass').text()
alert(text)
});
});
The problem is, the .text() will return all the elements at the same time (in this example: "element1element2element3").
I'd need to return only the text within the clicked class, for example: click on element2, it returns "element2" as .text().
Context is key.
Event callbacks are run in the context of the trigger element. In other words, this points to that element. So instead of repeating the selector, as you currently are (unnecessarily wasteful in terms of performance), reference this:
$( ".myClass" ).click(function() {
var text = $(this).text(); //this === the clicked element
console.log(text);
});
Use $(this):
$(document).ready(function(){
$(".myClass").click(function() {
var text = $(this).text();
console.log(text);
});
});
Inside event callback this refers to the current (i.e. clicked) element.
Also, console.log() is better for debugging than alert().
Although there are answers already been posted but I would post mine with little explanation:
See, currently you have bound an event on class selector and in the web browser class selector returns a collection. So, that means there will be more than one element in the list.
More additions to this there are tag name selectors too which also returns a collection.
While on the other selector ID selector returns only one element always because as per standards or better to say as per rule IDs should have to be unique for each element. And that's why it always returns a single element from the DOM.
That's the reason you get different behavior. To overcome this issue you need to understand the context of the selector. Which is a good topic to get info about this.
So, this represents the DOM node and in your case you need jQuery object. So, wrap it with jQuery wrapper $() to have a jQuery object with $(this).
$( ".myClass" ).click(function() {
var text = $(this).text(); // the elem in context
console.log(text);
});
You can use the event object to find out which element is clicked and then can show it's text
$(document).ready(function(){
$( ".myClass" ).click(function(event) {
var text = $(event.target).text()
alert(text)
});
});
JSFIDDLE

jquery clone work the first time but not later

Add row will clone the div but when I continue to click it doesn't clone single element but multiples, what's the flaw of the logic here?
$('#addRow').click(function () {
$(this).siblings('.elem').clone().appendTo($(this).siblings('.elem'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="elem">elem</div>
<a id="addRow">+</a>
You want to only select one element, and the siblings('.elem') call is selecting all of them (except the current), including the cloned ones.
You can call first() after you call siblings() to select only one.
You also probably want to append them to the parent, not the same collection of all siblings.
var $clone = $(this).siblings('.elem').first().clone();
$clone.appendTo($(this).parent());
Alternatively, you could insertAfter() the last element ($(this).siblings('.elem').last()).
You are having multiple cloning because each time the element is cloned a new element with class="elem" is generated and hence all the elements having class="elem" are cloned on each click.
To address this problem use first() which only selects the first element with class="elem" and thus only one element is cloned on each click.
Below is a simplified version of the code,
$("#addRow").click(function(){
$(".elem").first().clone().appendTo("body");
});
Here is the JSFiddle for this solution
Instead of appending it to "body" use the id of the element to which you want to append the cloned elements. Hope this helps.
The problem is that your .elem selector matches more and more elements each time you click the button.
A way to resolve this is to keep a reference to one element and use that to clone and then append; additionally, it makes sense to group those elements in another <div> for easier reference.
jQuery(function() {
var $elem = $('#rows .elem'); // keep as reference
$('#addRow').click(function () {
$('#rows').append($elem.clone());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="rows">
<div class="elem">elem</div>
</div>
<a id="addRow">+</a>
Clone only the first element and insert it just once, after the last instance.
$('#addRow').click(function () {
$(this).siblings('.elem:first').clone().insertAfter($(this).siblings('.elem:last'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="elem">elem</div>
<a id="addRow">+</a>

use of Jquery .after() for moving an element around

I'm reading the jquery manual regarding the .after() function:
$('.container').after($('h2'));
and it says
"If an element selected this way is inserted elsewhere, it will be
moved rather than cloned"
So if I have multiple
<div class='before' onclick='afterfunction();'><div>,
and I would want to place <div class='after'></div> after whichever div is clicked (have it move, not clone) would I do something like this?
var afterdiv = "<div class='after'></div>";
function afterfunction() {
$(this).after(afterdiv);
}
Thanks for all your help!
Like you said:
An element in the DOM can also be selected and inserted after another element:
$('.container').after($('h2'));
If an element selected this way is inserted elsewhere,
it will be moved rather than cloned:
But you missed the bold part.
$('.before').click(function() {
afterfunction(this);
});
// this will not work cause you'll append a string to your DOM
// var afterdiv = "<div class='after'>ola</div>";
// and will repeatedly be appended after each action.
// instead define your element by wrapping it into a $( )
var afterdiv = $("<div class='after'>ola</div>");
// now 'afterdiv' variable is binded to that element only once inside the DOM
function afterfunction(elem) {
$(elem).after(afterdiv);
}
And you don't need to .remove() it (like wrongly suggested in an answer here.)
demo jsFiddle
Make .before div like this:
<div class='before'><div/>
Then try,
$('.before').on('click', function() {
afterfunction(this);
});
function afterfunction(el) {
var afterdiv = "<div class='after'></div>";
$('.after').remove(); // remove previous `.after`
$(el).after(afterdiv); // add newly after the clicked div
}
DEMO

Categories

Resources