Hide li have span child withouth jquery - javascript

I need to hide li has a span child without jquery, how can i do it?
<ul class="select2-results__options" role="tree" id="select2-upsell_ids-results">
<li class="select2-results__option">first (#404)</li>
<li class="select2-results__option" >second (#496)</li>
<li class="select2-results__option">abc (#2482)</li>
<li class="select2-results__option">defg (#2484)<span class="description">Size: 47</span></li>
<li class="select2-results__option">hil (#2485)<span class="description">Size: 46,5</span></li>
</ul>

To be fair, #j08691's answer is perfectly valid and neat, and is absolutely not jQuery.
However, if #Geme doesn't like it, take a look at the code below. Trust me none of the code below contains any jQuery.
You can check if there is a span element inside each li by looping through the childNodes of each li.
If the childNode has a constructor of HTMLSpanElement, it is a span element.
var lists = document.getElementsByClassName('select2-results__option'); // NOT JQUERY
var i = 0;
var x = 0;
// NOT JQUERY AT ALL
for (; i < lists.length; i++)
for (; x < lists[i].childNodes.length; x++)
if (lists[i].childNodes[x].constructor === HTMLSpanElement){
lists[i].style.display = 'none';
break;
}
/* ALTERNATIVE */
// NOT JQUERY TOO
Array.prototype.forEach.call(lists, function(li){
var child = li.childNodes,
i = 0,
len = child.length;
for (; i < len; i++)
if (child[i].constructor === HTMLSpanElement)
li.style.display = 'none';
});
<ul class="select2-results__options" role="tree" id="select2-upsell_ids-results">
<li class="select2-results__option">first (#404)</li>
<li class="select2-results__option" >second (#496)</li>
<li class="select2-results__option">abc (#2482)</li>
<li class="select2-results__option">defg (#2484)<span class="description">Size: 47</span></li>
<li class="select2-results__option">hil (#2485)<span class="description">Size: 46,5</span></li>
</ul>

You can use document.querySelectorAll('li > span') to select the elements and then loop to hide them.
var items = document.querySelectorAll('li > span')
for (var item of items) {
item.parentNode.style.display = 'none';
}
<ul class="select2-results__options" role="tree" id="select2-upsell_ids-results">
<li class="select2-results__option">first (#404)</li>
<li class="select2-results__option">second (#496)</li>
<li class="select2-results__option">abc (#2482)</li>
<li class="select2-results__option">defg (#2484)<span class="description">Size: 47</span></li>
<li class="select2-results__option">hil (#2485)<span class="description">Size: 46,5</span></li>
</ul>

Related

How can I remove and append element li?

My html code like this :
<ul class="list">
<li id="thumb-view-1">view 1</li>
<li id="thumb-view-2">view 2</li>
<li id="thumb-upload-3">upload 3</li>
<li id="thumb-view-4">view 4</li>
<li id="thumb-view-5">view 5</li>
</ul>
<button id="test">Test</button>
My javascript code like this :
<script type="text/javascript">
$('#test').on("click", function(e){
var a = 3;
for(var i = 1; i <= 5; i++) {
if(i == a) {
$('#thumb-upload-'+i).remove();
var res = '<li id="thumb-view-'+i+'">view '+i+'</li>';
$('#thumb-view-'+(i-1)).after(res);
}
}
});
</script>
Demo : https://jsfiddle.net/oscar11/eb114sak/
It works
But my case is dynamic. var a has value between 1 - 5. So var a can have value 1 or 2 or 3 or 4 or 5
While ul tag has 5 li tag. And 5 li tag can have different id type
So in addition to the tag li above, I give an example of another form
Like this :
<ul class="list">
<li id="thumb-upload-1">upload 1</li>
<li id="thumb-view-2">view 2</li>
<li id="thumb-view-3">view 3</li>
<li id="thumb-view-4">view 4</li>
<li id="thumb-view-5">view 5</li>
</ul>
etc
If like that, the result still wrong
It seems it should call the li element based on a
So if a = 3 then the third li tag is deleted and append
But, I'm still confused
How can I do it?
Instead of remove / append, try replaceWith:
$('#test').on("click", function(e){
var a = 3;
for(var i = 1; i <= 5; i++) {
if(i == a) {
var res = '<li id="thumb-view-'+i+'">view '+i+'</li>';
$('#thumb-upload-'+i).replaceWith(res);
}
}
});
This will only replace matching #thumb-upload- elements, so it will handle your dynamic cases.
A simple solution could be to use replaceWith and index as
var index = $( "ul.list" ).index( $("li[id^='thumb-upload']") );
This will get the index of li whose class starts with thumb-upload within your unordered list
$("li[id^='thumb-upload']").replaceWith('<li id="thumb-view-'+index +'">view '+index +'</li>';)
And the above statement will replace that list item with your custom HTML
Another simple solution is to just change the ID as I don't see other changes as
$("li[id^='thumb-upload']").attr('id', $("li[id^='thumb-upload']").attr('id').replace('upload','view'));

JavaScript: splitting an HTML list in half

I have a 26-item list with one for each letter of the alphabet
<ul>
<li id="a">A</li>
...
<li id="m">M</li>
<li id="n">N</li>
...
<li id="z">Z</li>
</ul>
How could I use JavaScript to terminate the list after 'M' (i.e. </ul>, add an <h2> element and start another list, beginning with 'N'?
So:
<ul>
...
<li id="m">M</li>
</ul>
<h2>Part 2</h2>
<ul>
<li id="n">N</li>
...
</ul>
I can insert the h2 element fine with .createElement and .insertBefore, but I can't get the closing and opening list tags either side of it. I've tried innerHTML, outerHTML, insertBefore...
The array#slice method doesn't work on DOM elements. We will have to iterate through all of the elements, and create a new array instead.
First we have to remove the original list from the DOM. We can do that with the removeChild function
var originalList = document.getElementById("existingList");
document.body.removeChild(orginalList);
# Or wherever your list was nested under
# find all your list elements. This is assuming you only have 26 list elements
var li = document.getElementsByTagName("li");
var firstLetters, secondLetters = [], [];
# Create array for first half of list elements
for (var i = 0; i < li.length/2; i++) {
firstLetters.push(li[i]);
}
# Create array for second half of list elements
for (var i = li.length/2; i < li.length; i++) {
secondLetters.push(li[i]);
}
var list1 = document.createElement("ul");
var list2 = document.createElement("ul");
document.body.appendChild(list1);
document.body.appendChild(list2);
for (var i = 0; i < firstLetters.length; i++) {
list1.appendChild(firstLetters(i));
}
for (var i = 0; i < secondLetters.length; i++) {
list2.appendChild(secondLetters(i));
}
You can get the ul, clone it, insert the clone, and append the childnodes of the ul after the 13th child element to the clone:
var ul = document.querySelector('ul'),
newUl = ul.cloneNode(false),
last = ul.children[12];
ul.parentNode.insertBefore(newUl, ul.nextSibling);
ul.parentNode.insertBefore(document.createElement('h2'), newUl)
.appendChild(document.createTextNode('Part 2'));
while(last.nextSibling) newUl.appendChild(last.nextSibling);
var ul = document.querySelector('ul'),
newUl = ul.cloneNode(false),
last = ul.children[12];
ul.parentNode.insertBefore(newUl, ul.nextSibling);
ul.parentNode.insertBefore(document.createElement('h2'), newUl).appendChild(document.createTextNode('Part 2'));
while(last.nextSibling) newUl.appendChild(last.nextSibling);
<ul>
<li id="a">A</li>
<li id="b">B</li>
<li id="c">C</li>
<li id="d">D</li>
<li id="e">E</li>
<li id="f">F</li>
<li id="g">G</li>
<li id="h">H</li>
<li id="i">I</li>
<li id="j">J</li>
<li id="k">K</li>
<li id="l">L</li>
<li id="m">M</li>
<li id="n">N</li>
<li id="o">O</li>
<li id="p">P</li>
<li id="q">Q</li>
<li id="r">R</li>
<li id="s">S</li>
<li id="t">T</li>
<li id="u">U</li>
<li id="v">V</li>
<li id="w">W</li>
<li id="x">X</li>
<li id="y">Y</li>
<li id="z">Z</li>
</ul>

How to use getElementId on and ID's Element

Basically I have an Id's Element in CSS that i'm trying to interact with via JavaScript. So I want to use:
document.getElementById('dropMenu').style.opacity = '0';
on
#dropMenu li {
opacity: 1;
}
but I cant work out how to interact with the li part specifically, is it even possible?
Thanks,
James
HTML
<html>
<head>
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<link href="./stylesheet.css" type="text/css" rel="stylesheet">
<title>Index</title>
<script>
function dropMenu(){
if (document.getElementById('dropMenu').style.height != '151px')
{
document.getElementById('dropMenu').style.height = '151px';
document.querySelectorAll('dropMenu li').style.opacity = '1';
console.log("showingObj");
}
else
{
document.getElementById('dropMenu').style.height = '0px';
document.querySelectorAll('dropMenu li').style.opacity = '0';
console.log("hideObj:");
}
}
</script>
</head>
<body>
<nav>
<div id="mainMenu">
<i class="fa fa-bars" onclick="dropMenu()"></i><p>Page Title</p>
</div>
<div id="dropMenu">
<ul>
<li>
<i class="fa fa-pencil fa-5x" id="dm1" style="background: #00bcd4;"></i>
<p style="background: #00acc1;">Projects</p>
</li>
<li>
<i class="fa fa-film fa-5x" id="dm1" style="background: #8bc34a;"></i>
<p style="background: #7cb342;">Media</p>
</li>
<li>
<i class="fa fa-camera-retro fa-5x" id="dm1" style="background: #ffc107;"></i>
<p style="background: #ffb300;">Photography</p>
</li>
<li>
<i class="fa fa-info-circle fa-5x" id="dm1" style="background: #e51c23;"></i>
<p style="background: #dd191d;">About Me</p>
</li>
</ul>
</div>
</nav>
</body>
As an alternative to having to grab the li list, looping over it and programmatically setting the styles you could just add/remove a class on the dropMenu element by using the classList add/remove methods, or if supporting older browsers manipulate the className property
CSS
#dropMenu li {
opacity: 1;
}
#dropMenu.hideli li {
opacity: 0;
}
JS
//to add
document.getElementById("dropMenu").classList.add("hideli");
//to remove
document.getElementById("dropMenu").classList.remove("hideli");
//Quick and dirty could be improved
var ele = document.getElementById("dropMenu");
//to add
ele.className += " hideli";
//to remove
ele.className = ele.className.replace("hideli","");
Demo
setTimeout(function(){
document.getElementById("dropMenu").classList.add("hideli");
},1000);
setTimeout(function(){
document.getElementById("dropMenu").classList.remove("hideli");
},3000);
#dropMenu li {
opacity:1;
}
#dropMenu.hideli li {
opacity:0;
}
<div id="dropMenu">
<ul>
<li>Li 1</li>
<li>Li 2</li>
<li>Li 3</li>
<li>Li 4</li>
</ul>
</div>
Yes, this is possible, but requires some extra JavaScript
1) Using getElementById with getElementsByTagName
var parent = document.getElementById('dropMenu');
var children = parent.getElementsByTagName('li');
// Loop child elements here, using forEach...
Array.prototype.forEach.call(children, ...);
2) Using querySelectorAll
var children = document.querySelectorAll('#dropMenu li');
// Loop child elements here...
Array.prototype.forEach.call(children, ...);
3) If you're open to using jQuery, it's easily done (similar to querySelector)
$('#dropMenu li').each(...);
Within the forEach (or a standard forloop), you'll interact directly with the element.
For example. using a standard for loop:
for (var i = 0, len = children.length; i < len; i++) {
children[i].style.opacity = 0;
}
Using forEach (if you don't mind compatibility issues) might look like this:
Array.prototype.forEach.call(children, function(el){
el.style.opacity = 0;
})
Use querySelectorAll and loop through the items changing their style
var items = document.querySelectorAll('#dropMenu li');
for(var i=0;i<items.length;i++){
items[i].style.opacity="1"
}
in js you can write it as
var elems = document.querySelectorAll('#dropMenu li');
for(var index = 0; index < elems.length; index++) {
elems[index].style.opacity = 0;
}
Your getElementById('dropMenu') is ok, then you can add "sub-query" for all li elements, and scan it:
var dropmenu = document.getElementById('dropMenu');
var lis = dropmenu.getElementsByTagName('li');
for(var i = 0; i < lis.length; i++) {
lis[i].style.opacity = 0;
}

Wrapping groups of lists within divs

What I'm trying to achieve:
<ul>
<li class="group4">
<ul class="group2">
<li class="first">stuff</li>
<li class="last">stuff</li>
</ul>
<ul class="group2">
<li class="first">stuff</li>
<li class="last">stuff</li>
</ul>
</li>
<li class="group4">
<ul class="group2">
<li class="first">stuff</li>
<li class="last">stuff</li>
</ul>
<ul class="group2">
<li class="first">stuff</li>
<li class="last">stuff</li>
</ul>
</li>
</ul>
What I'm currently equipped with:
<ul>
<li class="first">stuff</li>
<li class="last">stuff</li>
<li class="first">stuff</li>
<li class="last">stuff</li>
<li class="first">stuff</li>
<li class="last">stuff</li>
<li class="first">stuff</li>
<li class="last">stuff</li>
</ul>
Essentially this will make the list items appear in rows of 4, and rows of 2 in mobile view.
I can't hardcode this since the list items are retrieved via php.
Is there a script or something that can help me do this?
var $ul = $('ul').find('.first').each(function() {
$(this).next('.last').addBack().wrapAll('<ul class="group2"/>');
}).end();
while( $ul.children('.group2').length )
$ul.children('.group2').slice(0, 2).wrapAll('<li class="group4"/>');
http://jsfiddle.net/Twr9z/
Another way to do it if you don't know how many items will be in each group:
function relist() {
var list = $("ul.list");
var li = list.children("li");
var _li, _ul, item;
for (var i = 0 ; i < li.length; i++) {
if (i % 2 == 1) {
item = list.find("li:eq(" + i + "), li:eq(" + parseInt(i - 1) + ")");
_ul = $("<ul class='group_" + item.length + "'></ul>");
item.wrapAll(_ul);
}
}
var ul = list.find("ul");
for (var j = 0; j < ul.length; j++) {
if (j % 2 == 1) {
item = list.find("ul:eq(" + j + "), ul:eq(" + parseInt(j - 1) + ")");
_li = $("<li class='group_" + item.find('li').length + "'></li>");
item.wrapAll(_li);
}
}
}
$(function () { relist()});
The name of the classes will be group + the number of items under it.
this will do what you want, plus preserving the W3C validation:
$('.first').each(function(){
if(!$(this).data('wrapped')){
$(this).wrap('<ul class="group2"></ul>');
$(this).parent('.group2').append($(this).parent('.group2').nextAll('.last:first').clone()).html();
$(this).parent('.group2').nextAll('.last:first').remove();
$(this).parent('.group2').wrap('<li class="group4"></li>');
$(this).data('wrapped',true);
}
});

Looking for elements with specific depth in JavaScript

I need to write a function in pure JavaScript witn no framework to get all specific tags, but only from first level under parent.
For example: I need to call some function on first <ul> and get all <li> from first level of it (<li> with text 1.2 and <li> with text 2.1)
<div id="sideNavigation">
<ul>
<li class=" act open ">
1.2
<ul>
<li class=" ">
1.2
<ul>
<li class=" ">
1.3
<ul>
<li class=" ">1.4</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li class=" ">
2.1
<ul>
<li class=" ">2.2.1</li>
<li class=" ">2.2.2</li>
<li class=" ">2.2.3</li>
</ul>
</li>
</ul>
</div>
I've been trying to do it like this:
var allLi = document.getElementById("sideNavigation").getElementsByTagName("li");
but it returns all <li> in this div not only first level <li>. Do you have any quick method to solve my problem or do I have to implement a new function to detect depth of nodes
You can use the attribute .children to get those "li"
var firstDepthLi = document.getElementById("sideNavigation").children[0].children;
If you want a generic function you can create something like:
var getElementsByDepth = function(el, tagname, depth) {
var children = el.children;
var res = new Array();
for(var i=0; i<children.length; i++) {
if (children[i].tagName == tagname) {
res.push(children[i]);
if (depth > 0)
res.concat(getElementsByDepth(children[i], tagname, depth-1));
}
}
return res;
}
Try:
var allLi = document.getElementById("sideNavigation").getElementsByTagName("li")[0];
That should return the first li element out of all li's on the page. Change the zero at the end to a different number to get a different element. You could even set a variable for the value:
var liNum = 0;
var allLi = document.getElementById("sideNavigation").getElementsByTagName("li")[liNum];
And in a function:
function getLi(depth) {
var specificLi = document.getElementById("sideNavigation").getElementsByTagName("li")[depth];
return specificLi;
}
var firstLi = getLi(0);
console.log(firstLi);
<div id="sideNavigation">
<ul>
<li>First list tag</li>
<li>Second list tag</li>
<li>Third list tag</li>
</ul>
</div>
And to make the function even shorter, you could just do:
function getLi(depth) {
return document.getElementById("sideNavigation").getElementsByTagName("li")[depth];
}
That should work. :)

Categories

Resources