How can I select the text infront of the unordered list below?
<li class="foo">
How can I remove this text?
<ul class="bar">
<li>Link</li>
</ul>
</li>
I tried doing something like this:
$('ul.bar').previousSibling().remove();
But I think that would only work with another element, and I'm not entirely sure how to go about selecting text that isn't contained inside tags.
Is the solution you're looking for.
$('.foo').contents().filter(function(){
return (this.nodeType == 3);
}).remove();
Demo here
The nodeType property returns the node type, as a number, of the
specified node.
If the node is a text node, the nodeType property will return 3.
Non jQuery version:
Get the Parent Node. Get all the Children nodes of the Parent. Convert the collection of Nodes to an array. Loop through the array. Check the nodeType on every iteration. If the nodeType === 3 then it's a text node. Then delete it.
Array.prototype.slice.call(document.getElementById('parent_node_id_here').childNodes, 0).forEach(function (value) {
if (value.nodeType === 3) {
value.remove();
}
});
$(".foo").contents().get(0).remove()
or without jquery
document.getElementsByClassName("foo")[0].childNodes[0].remove()
Try
$(".foo").replaceWith($.parseHTML($(".foo").html()).slice(1));
$(".foo").replaceWith($.parseHTML($(".foo").html()).slice(1));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<li class="foo">
How can I remove this text?
<ul class="bar">
<li>Link</li>
</ul>
</li>
Related
I am looking for a way to compare elements using jQuery. Basically for every element with a certain data attribute, I want to "appendChild" another element that has a matching ID.
So in the following example, 'a' has a data attribute of data-dropdown="drop-delivery-options". The second element has an ID="drop-delivery-options", so they match. I can select elements with this ID but how do I select elements that match data-attributes/IDs?
So a function that would be like:
If elementA[data-attribute] = elementB[ID] {
(elementA).appendChild(elementB)
}
Add Option
<div id="drop-delivery-options" data-dropdown-content class="f-dropdown content table-options drop-delivery-options">
<ul>
<li>Add Deposit Account</li>
<li>Add Cash Pickup</li>
<li>Send to Card</li>
<li>Add Home Delivery</li>
</ul>
</div>
You can use the data-dropdown attribute to select the select element, then use appendTo() to append it to the a. Note though that given your example you will end up with nested a elements, which is invalid. You should look to change the parent a element to something else.
$('.button').click(function() {
$('#' + $(this).data('dropdown')).appendTo(this);
});
Working example
Could someone clarify why the code below returns #text instead of 'li'
?
Shouldn't the next sibling of first li be li ?
Similarly previous sibling of last li be li ?
<body>
<ul>
<!-- comment -->
<li id="A"></li>
<li id="B"></li>
<!-- comment -->
</ul>
<script>
//cache selection of the ul
var ul = document.querySelector('ul');
//What is the nextSibling of the first li?
console.log(ul.querySelector('#A').nextSibling.nodeName); //logs text
//What is the previousSibling of the last li?
console.log(ul.querySelector('#B').previousSibling.nodeName); //logs text
</script>
</body>
The whitespace between the two is also a node. That's why JS libraries exist. To give you options like retrieving element siblings.
If the HTML source looked like this:
<ul>
<li id="A"></li><li id="B"></li>
</ul>
It would work as you expect it, because there's no whitespace between the li elements.
More recently, two more properties have been introduced, called previousElementSibling and nextElementSibling, which ignore that whitespace. It works from IE9 and up, with the other major browsers supporting it for a while now.
beter is use 'nextElementSibling' and 'previousElementSibling'
how can i get the Value / Text of a <li> item ?
I found on the internet much ways to get the value for a dropdown list.
But not for a <li> item.
This is what I have tried so far:
var listt = document.getElementById('content1');
var selectedvalue = [listt.selectedIndex].text;
You can use the innerText property for most browsers, but the textContent property for Firefox:
<ul>
<li id="myLi">Hello, world</li>
</ul>
var li = document.getElementById("myLi")
console.log(li.textContent || li.innerText);
Here is a fiddle to demonstrate.
If you are using jQuery (you say you are, but I see no evidence) it would be as simple as using the .text() function:
$("#myLi").text();
If your <li> contains HTML markup too, you may want that. In this case you need to use the innerHTML property:
document.getElementById("myLi").innerHTML;
Again, jQuery has it's own equivalent .html() which caters for all sorts of different browsers:
$("#myLi").html();
Assuming myLi is a reference to the <li> element you want to get the text of, it's as simple as:
myLi.innerText
Note that <li> elements don't have values, because they're not inputs. They have content which can be a string of text or HTML defining other page elements. If your <li> element contained other elements, and you wanted the HTML of those as a string, you could instead do:
myLi.innerHTML
What's the difference? Let's assume your HTML looked like this:
<li><span>Some text</span></li>
Then
console.log(myLi.innerHTML); // outputs: <span>Some text</span>
console.log(myLi.innerText); // outputs: Some text
I would just use innerHTML if your list item has an ID or class name and assuming there is no other html in your list item.
<ul>
<li class="list-item">Item1</li>
<li class="list-item">Item2</li>
<li class="list-item">Item3</li>
</ul>
<script>
var list = document.getElementsByClassName('list-item');
var listArray=[];
for (var i=0;i<list.length;i++){
listArray.push(list[i].innerHTML);
console.log(listArray[i]);
}
</script>
//output
Item1
Item2
Item3
You could also try using the textContent property perhaps or innerHTML for that matter if you wanna get plain text.
var li_item=document.getElementById('content1');
console.log(li_item.textContent)
How would I only select Item A and Item B pragmatically while excluding the sub item?
<div id="nav">
<ul>
<li>
<p>Item A</p>
<ul>
<li>
<p>Sub Item A</p>
</li>
</ul>
</li>
<li>Item B</li>
</ul>
</div>
Well after a quick test run - this is my contribution to this issue
$("#nav p:first, #nav > ul > li:eq(1)");
You specified that you wanted only those two items and no sub items so this is what jQuery will capture :
[<p>Item A</p>, <li>Item B</li>]
You can easily separate selectors by placing a comma between them.
Now that you have seen my solution I would strongly suggest that you take Xenon06's advice...
Giving your markup classes really helps you to keep track of them. Especially with jQuery. The class attribute while IMO mostly used for styling is a perfectly valid selector to use and abuse in your jQuery code. That is of course if you actually have access to that HTML. If you don't kindly ignore my last paragraph :)
This will select any first level li's that have only text and no children and any children of a li that isnt a ul. Given this is not a good way to do it. You should really put classes on your stuff to start with. But if that's not an option this will get you there.
$($('#nav').children()).children().each(function(){
if($(this).text() !== "" && $(this).children().length === 0 ){
$(this).addClass("IwantThisElement");
}
});
$($($('#nav') .children()) .children()) .children(':not(ul)').each(function(){
if($(this).text() !== ""){
$(this).addClass("IwantThisElement");
}
});
$('.IwantThisElement').text('Assuming Control');
Well, if your structure was more consistent, you could use direct children selectors, ie:
$("#nav ul li > p")
However your Item B is not in a paragraph. Without defining more what you want, you'll need to put classes on the items you want and do
$("#nav .yourclass")
I am trying to convert a nested li into one single li using recursive method using jquery
html as follows
<ul>
<li>item-1
<ul>
<li>item-1.1</li>
</ul>
</li>
<li>item-2
<ul>
<li>item-2.1</li>
<li>item-2.2
<ul>
<li>item-2.2.1</li>
<li>item-2.2.2</li>
</ul>
</li>
</ul>
</li>
<li>item-3
<ul>
<li>item-3.1</li>
</ul>
</li>
<li>item-4</li>
<li>item-5</li>
</ul>
Final single li as below
<ul>
<li>item-1</li>
<li>item-2</li>
<li>item-3</li>
<li>item-4</li>
<li>item-5</li>
<li>item-1.1</li>
<li>item-2.1</li>
<li>item-2.2</li>
<li>item-3.1</li>
<li>item-2.2.1</li>
<li>item-2.2.2</li>
</ul>
basically loop through each level then append to the end of the list.
Any ideas how I can achieve this? so it can handle any level of the list item.
Here is a recursive approach that will give the output you're looking for:
function recurseFetchListItems($ul)
{
var $li = $ul.remove().children("li").remove();
if ($li.length) {
$li = $li.add(recurseFetchListItems($li.children("ul")));
}
return $li;
}
It uses add() to accumulate the different levels of list items, while removing each level from the document. It also uses children() instead of find() in order to process a single depth level per call.
From there, you only have to start from the first <ul> element, add the cumulated set of list items back to the document, and wrap them in a new <ul> element:
$(document).ready(function() {
recurseFetchListItems($("ul:first")).appendTo("body").wrapAll("<ul>");
});
You can see the results in this fiddle.
Original (misguided) answer follows:
You don't really need a recursive function to do that, because whole DOM element trees can be matched with a single selector. For instance, $("li") matches all the list items, whatever their depth is.
So, to achieve what you want, we only need to match all the <li> elements, remove their parent <ul> elements from the document, then wrap the list items into a new <ul> element using wrapAll() and add that element back:
$(document).ready(function() {
$("li").parent().remove().end().appendTo("body").wrapAll("<ul>");
});
You can see the results in this fiddle.