Suppose I have the following code:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
Now when I do, $("ul").clone();, it clones the full ul element (all its children also).
I want only to clone <ul> and not its children.
How to do that in jQuery?
I know in pure JavaScript (using cloneNode()), but I can't use this because of additional methods to perform also.
You could empty the element:
$('ul').clone().empty();
There are two problems with the given solutions.
They are unnecessarily inefficient by cloning all children and their data.
They use the native clone, which doesn't clone event handers and other data.
If you want to do a shallow clone with jQuery and transfer all data, detach its contents before the clone operation, then replace them after.
// Fetch the ul and detach its contents
var ul = $("ul");
var contents = ul.contents().detach();
// Do the clone, copying its data
var clone = ul.clone(true);
// Reattach the contents
ul.append(contents);
If there are multiple elements, then do this operation in a loop.
Use .html('') to empty the contents.Try this:
$("ul").clone().html('');
Working Demo
jQuery clone method creates a deep copy of the element.
Description: Create a deep copy of the set of matched elements.
So with jQuery you want be able to get just the ul.
You have two choices:
Empty the object jQuery returns:
$('ul').clone().empty();
Use plain Javascript:
var simpleUl = $($('ul').get(0).cloneNode());
Related
If one does
//=> <ul id="fruits">
// <li class="apple">Apple</li>
// <li class="plum">Plum</li>
// <li class="apple">Apple TOoo</li>
// <li class="pear">Pear</li>
// </ul>
$('.apple').html();
it will output only
<li class="apple">Apple TOoo</li>
but, I want to get the html of all the elements returned combined, currently it only returns the first, as according to the docs: Gets an HTML content string from the first selected element. https://cheerio.js.org/classes/Cheerio.html#html
How do I do this with Cheerio?
If I use the top level .html(node) with a specific node, then if it has subchildren, they render as Object[Object].
But, .text() traverses the whole list of results and combines them. text() doesn't look at the first element only. What is the equivalent for .html()? Alternatively, I don't mind combining the string results of multiple html() calls, but then the children being rendered as literal Object strings messes up the whole thing.
I found that I could have just been using Cheerio.load(..) to load the html instead of trying to render it from each node itself.
let nodes = Cheerio.load(theHtmlBody)('.apple');
return nodes.map( (i, el) => Cheerio.load(el).html() ).get().join("\n");
Thanks to #PA.'s comments above
I make some code width jquery My goal is add lists under the #pivot and above <li>bottom</li> How to do??
When I tried like this the only <li></li> added without text "new row"
Please teach me
HTML
<li>top</li>
<li id="pivot">Pivot</li>
<li>bottom</li>
Javascript
var dom = '<li></li>';
$('a',dom).text('new row');
$('#pivot').after(dom);
That's because you are creating a jQuery object from a string but you don't store/use the created elements.
$(dom) // parse the string and create a jQuery object
.find('a') // find the `a` descendants
.text('new row') // update their textContent
.end() // get the previous jQuery collection
.insertAfter('#pivot'); // insert the collection after `#pivot` element
dom is not a live node. It is just string..
If you create a jquery object out of it first, it will work
var dom = $('<li></li>');
$('a',dom).text('new row');
$('#pivot').after(dom);
So I currently have a list like so on my page
<li class="head">
<b>Introduction</b>
<ul>
<li class="sub">somethingsomething</li>
</ul>
</li>
This list is being used with sortable, so the user can decide on the order, and I am passing this information to a grails controller for use in application logic. So, I am trying to read it in, and place the text contained in the "head" and "sub" classes in 2 different arrays. However, when I use a jquery selector to obtain the head elements, and obtain the text attribute of the element, it contains the inside list as well.
$('#divname').find("ul > li.head").each(function()
{
var current = $(this);
console.log(current.text());
});
results in Introductionsomethingsomething
Is there any way to only obtain the 'Introduction' text from the list, and ignore the text in the nested <ul> and <li.sub>? Due to it being nested, I am unable to figure out how to use jQuery's :not() selector
You can find the b tag using jquery tagname selector.Like this:
var current = $(this).find('b');
console.log(current.text());
Working Demo
May be this is solution:
<script>
$('#divname').find("ul > li.head").each(function()
{
var current = $(this).find("b");
console.log(current.text());
});
</script>
The JQuery "has" method effectively selects all elements where they have particular descendants.
I want to select elements based on the fact they have particular ancestors. I know about parent([selector]) and parents([selector]) but these select the parents and not the children with the parents.
So is there an ancestor equivalent of "has"?
Note: I already have the context of an element further down the hierarchy and I will be selecting based on this so I can't do a "top down" query.
Update
I've obviously explained myself really badly here, so I'll try and clarify:
<ul class="x">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<ul class="y">
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
I have a jQuery object that already consists of elements 2,3,4 and 5. I want to select those elements who have a parent with the class = x.
Hope that makes more sense.
For a clean re-usable solution, consider extending the jQuery.fn object with a custom method used for determining the presence of a particular ancestor for any given element:
// Extend jQuery.fn with our new method
jQuery.extend( jQuery.fn, {
// Name of our method & one argument (the parent selector)
within: function( pSelector ) {
// Returns a subset of items using jQuery.filter
return this.filter(function(){
// Return truthy/falsey based on presence in parent
return $(this).closest( pSelector ).length;
});
}
});
This results in a new method, $.fn.within, that we can use to filter our results:
$("li").within(".x").css("background", "red");
This selects all list items on the document, and then filters to only those that have .x as an ancestor. Because this uses jQuery internally, you could pass in a more complicated selector:
$("li").within(".x, .y").css("background", "red");
This will filter the collection to items that descend from either .x or .y, or both.
Fiddle: http://jsfiddle.net/jonathansampson/6GMN5/
if ( $('.foo').parents('.parentSelector').length ) { // has parent }
If I understand your question correctly, this would do:
$.fn.hasAncestor = function(a) {
return this.filter(function() {
return !!$(this).closest(a).length;
});
};
$('.element').hasAncestor('.container').myAction();
<div class="container">
<span>
<strong class="element">strong</strong>
</span>
</div>
$('body').hasParent('html') //true
$('div#myDiv').hasParent($('body')) //true
#API:
// check if current element has parent element 'e'
$.fn.hasParent = function (e) {
return !!$(this).parents(e).length
}
You can actually use filter directly (without a function calling closest) and it will have better performance. Simply use a selector that matches elements contained within .x:
$("li").filter(".x *")
this also differs slightly from the closest solutions suggested by others in that it will not match if the element itself has the given class but only if it is within an element with that class.
If matching an element with the class is desired as well, this could be modified slightly:
$("li").filter(".x, .x *")
$("li").filter(".x *").css("background", "red");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="x"><li>1</li><li>2</li><li>3</li></ul>
<ul class="y"><li>4</li><li>5</li><li>6</li></ul>
Try this
ul.myList > li > a
This selector selects only links that are direct children of list elements, which are
in turn direct children of elements that have the class myList.
object.each(function(){
element = $(this);
if(element.parent().hasClass("x")){
//do stuff
}
});
this will affect every item in your object that has parent .x
The easy way is this:
// all children of a specific parent match
$('parentSelector').children();
// All children matching a specific pattern, one level deep
$('parentSelector > childSelector');
// or
// $('parentSelector').children('childSelector');
// All children matching a specific pattern, multiple levels deep
$('parentSelector childSelector');
// or
// $('parentSelector').find('childSelector');
or did you really need something more complicated than that?
Edit: If you already have an element, you can combine this with the parent() command, like so:
myElement.parents('parentSelector').find('childSelector'); // Will include self
I realize this is an old question, but I'm leaving this here for future visitors looking for something similar;
There is a $.contains(container, contained) method which returns a boolean.
https://api.jquery.com/jQuery.contains/
Very simple way to do it
$('.x').find('li')
I have been looking at the stackoverflow thread:
How may I sort a list alphabetically using jQuery?
but for my scenario, I have the hierachy:
<ul><li>NAME_TO_SORT_ON</li></ul>
Based on this set-up, how can I modify the solution from thread mentioned here to cater for my scenario which has a tag as I would like to sort on all the name found in NAME_TO_SORT_ON?
Thanks.
I would recommend using a jQuery-based solution for this, because once you start getting into multiple DOM levels (e.g. sorting siblings at one level based on the contents of elements at a deeper level) the simple sort mechanism breaks down. It's an extremely rough solution - essentially blowing away the existing HTML and replacing it in raw text mode with other HTML. We can do better by actually shuffling the DOM elements around:
function sort(list, key) {
$($(list).get().reverse()).each(function(outer) {
var sorting = this;
$($(list).get().reverse()).each(function(inner) {
if($(key, this).text().localeCompare($(key, sorting).text()) > 0) {
this.parentNode.insertBefore(sorting.parentNode.removeChild(sorting), this);
}
});
});
}
To use it, we pass in a selector to the list and a selector to use to locate the key we want to sort on:
<ul class="toBeSorted">
<li>sort me</li>
</ul>
<script type="text/javascript">
sort('ul.toBeSorted>li', 'a');
//we want to sort the <li>'s in ul.toBeSorted;
//and we want to use the text of the first and only <a>
//in each item as the sort key
</script>