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>
Related
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>
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'));
I have an array in javascript called menuElm that has <ul> elements in it:
<ul id="1"></ul>
<ul id="2"></ul>
<ul id="3"></ul>
I have a page in HTML that has the following:
<ul id="menu">
<li class="menu-item"></li>
<li class="menu-item"></li>
<li class="menu-item"></li>
</ul>
I want to add the elements of menuElm to the HTML page so it would look like this:
<ul id="menu">
<li class="menu-item">
<ul id="1"></ul>
</li>
<li class="menu-item">
<ul id="2"></ul>
</li>
<li class="menu-item">
<ul id="3"></ul>
</li>
</ul>
I have tried the following, but the <ul> elements just wont show up in the page nor in the code:
function CreateMenu() {
var menuElm;
var k = 0;
menuElm = createElm("ul");
menuElm.id = ++k;
for (var i = 0; i < menuElm.length; ++i) {
document.getElementsByClassName("menu-item")[i].appendChild(menuElm[i]);
}
}
I am new with JavaScript, what am I doing wrong?
menuElm.length
The ul element doesn't have a length, so you are looping from 0 to 0, which is 0 iterations.
menuElm = createElm("ul");
This function isn't defined. You need document.createElement('ul');
menuElm = createElm("ul");
menuElm.id = ++k;
You appear to be creating one list item, and then changing its ID and appending it multiple times.
You need a new list item each time you go around the loop.
appendChild(menuElm[i]);
You've been treating menuElm as an element previously. It isn't an array, [i] makes no sense here.
$("#menu").find('li').each(function(i){
$(this).append(menuElm[i]);
});
/* if you want to use jquery here is the code to append */
I am having issues on sorting based on array. Let's say I have something like this:
HTML:
<button onClick="sortfunc();">Sort</button>
<ul id="sortable">
<li id="a">is </li>
<li id="b">awesome</li>
<li id="c">very </li>
<li id="d">javascript </li>
<li id="e">hard </li>
<li id="f">but </li>
</ul>
Now I want to use an external button to sort it out and sort final value equal to d a c e f b order.
Javascript:
$(function() {
$( "#sortable" ).sortable();
});
function sortfunc() {
var idsInOrder = $("#sortable").sortable("toArray");
console.log(idsInOrder);
//Print: ["a", "b", "c", "d", "e", "f"]
var sorttoarray = ["d","a","c","e","f","b"];
//Do something here to sort the ul li to match sorttoarray
}
I print out the array but it is not in the order as expected.
Is it possible to use external button to sort out the above sortable to the id as indicated?
EDIT so id starts with letter.
Here's how you can accomplish this (I've altered the HTML a bit, as you don't need the jQuery UI sortable functionality):
<button id="doSomething">Sort</button>
<ul id="sortable">
<li id="1">is </li>
<li id="2">awesome</li>
<li id="3">very </li>
<li id="4">javascript </li>
<li id="5">hard </li>
<li id="6">but </li>
</ul>
And here's my JavaScript:
function sortfunc() {
var liItems = $("#sortable li");
var sorttoarray = ["4","1","3","5","6","2"];
$("#sortable").empty();
for (var i = 0; i < sorttoarray.length; i++) {
$("#sortable").append(liItems.filter("#" + sorttoarray[i]));
}
}
$("#doSomething").click(function () {
sortfunc();
});
Here's the working jsfiddle: http://jsfiddle.net/odmrxwxr/
Ultimately all I do here is save off the li elements, empty the parent ul, and then loop through the array for the order, and when I reach the next desired element that should be in the order, I just append() it back.
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. :)