Looking for elements with specific depth in JavaScript - 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. :)

Related

Javascript foreach loop on list items

I have a basic HTML list like below...
<ul class="test_ul">
<li class="item" id="item1">
Item 1
</li>
<li class="item" id="item2">
Item 2
</li>
<li class="item" id="item3">
Item 3
</li>
<li class="item" id="item4">
Item 4
</li>
</ul>
I am using javascript to try and grab the id of each list item and then use a loop to check each one against a string. I have this so far..
var myvariable
myvariable = "item2"
items = document.getElementsByClassName("item");
for (i = 0; i < items.length; i++) {
console.log(i);
console.log(item[i]);
}
This isn't working for me, is it because it is not really an array?
You're logging the index i, instead, use items[i].id to get the id of the matched element. Something like this
var items = document.getElementsByClassName("item");
for (i = 0; i < items.length; i++) {
console.log(items[i].id);
}
<ul class="test_ul">
<li class="item" id="item1">
Item 1
</li>
<li class="item" id="item2">
Item 2
</li>
<li class="item" id="item3">
Item 3
</li>
<li class="item" id="item4">
Item 4
</li>
</ul>
You could borrow Array#map for an array like object and return just the id property of the objects.
var result = [].map.call(document.getElementsByClassName("item"), function(o) {
return o.id;
});
console.log(result);
<ul class="test_ul">
<li class="item" id="item1">Item 1</li>
<li class="item" id="item2">Item 2</li>
<li class="item" id="item3">Item 3</li>
<li class="item" id="item4">Item 4</li>
</ul>
My understanding is, you want to loop through this list of items and find a match of the item based on a specified string.
What you've done so far with the classes is good. This will allow you to reference all the list items, but there isn't really a need for the IDs based on what I think it is that you're trying to do.
If I were you, I would utilize a querySelectorAll, which returns an iterable array of HTML nodes that we can do whatever we want with.
Here's my code.
let listItemArray = document.querySelectorAll('.item');
console.log(listItemArray);
const SEARCH_STRING = 'Item 1'
for(let i=0; i<listItemArray.length; i++) {
if(listItemArray[i].innerText === SEARCH_STRING) {
console.log(`The item was found! ${listItemArray[i]}`); // This syntax is called a query string. Powerful stuff. Look them up.
}
}
<ul class="test_ul">
<li class="item" id="item1">
Item 1
</li>
<li class="item" id="item2">
Item 2
</li>
<li class="item" id="item3">
Item 3
</li>
<li class="item" id="item4">
Item 4
</li>
</ul>
Add ID ="lstUsers" to ul element < you're registered with DOM now
for (var i = 0; i < lstUsers.children.length; i++) {
alert( lstUsers.children[i].innerText);
}
#lstUsers <--css with your id you shrink your HTML down this way...
While all of the answers here are equally good, and this qs is old(2017)
I am posting this for knowledge sharing
We can use:
items = document.querySelectorAll(".item");//Get items
items.forEach(function(item) {
console.log(item);/*Use variable item for any need*/
});
If you need the index of item as well then use
items = document.querySelectorAll(".item");//Get items
items.forEach(function(item,index) {
console.log(item, index);/*Use variable item & index for any need*/
});
The best of this is that it doesn't need any loop or extra variable like i. Also, it do not make use of a loop like for or while, but a function like forEach(), where forEach is a human-readable word
Note: forEach() cannot be used with getElementsByClassName() ,it supports only querySelectorAll()
Working snippet:
items = document.querySelectorAll(".item");//Get items
items.forEach(function(item) {
console.log(item);/*Use variable item for any need*/
});
console.log("The below log is with index");
items = document.querySelectorAll(".item");//Get items
items.forEach(function(item,n) {
console.log(n,item);/*Use variable item for any need*/
});
<ul class="test_ul">
<li class="item" id="item1">Item 1</li>
<li class="item" id="item2">Item 2</li>
<li class="item" id="item3">Item 3</li>
<li class="item" id="item4">Item 4</li>
</ul>
Using ES6 (might need to transpile or add polyfills for older browsers):
// Get the DOMCollection of node corresponding to the item class
var items = document.getElementsByClassName("item")
// Transform the DOMCollection to an array and map item.id
, ids = Array.from(items).map(item => item.id);
;
console.log(ids);
<ul class="test_ul">
<li class="item" id="item1">
Item 1
</li>
<li class="item" id="item2">
Item 2
</li>
<li class="item" id="item3">
Item 3
</li>
<li class="item" id="item4">
Item 4
</li>
</ul>
Using ES5 only:
var items = document.getElementsByClassName("item")
, ids = []
;
for(var i = 0, c = items.length; i<c; i++) {
ids.push(items[i].id);
}
console.log(ids);
<ul class="test_ul">
<li class="item" id="item1">
Item 1
</li>
<li class="item" id="item2">
Item 2
</li>
<li class="item" id="item3">
Item 3
</li>
<li class="item" id="item4">
Item 4
</li>
</ul>

Append array to a class in javascript

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 */

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>

Javascript: Issue when using .click method

Firsty here is the html which corresponds with the code
<div class="grid_12">
<ul id="categories">
<li class="filter">Categories:</li>
<li id="ny"> New York</li>
<li id="sc">Spanish Cities</li>
<li id="gv">A Glasgow Viewpoint</li>
<li id="sch">Some Churches</li>
<li id="bh">Barcelona Highlights</li>
<li id="mp">Martin’s Pictures</li>
</ul>
</div>
<!-- end .grid_12 - CATEGORIES -->
The idea here is that when each of these links are pressed a var id is changed to the correct number depending on which is clicked
Here is the code i have used to do this
if (nyView.click) {
id = 1;
} else if (scView.click) {
id = 2;
} else if (gvView.click) {
id = 3;
} else if (schView.click) {
id = 4;
} else if (bhView.click) {
id = 5;
} else if (mpView.click) {
id = 6;
}
the view vars are simply locators to find the correct div element so they are done like this
nyView = document.getElementById('ny');
scView = document.getElementById('sc');
gvView = document.getElementById('gv');
schView = document.getElementById('sch');
bhView = document.getElementById('bh');
mpView = document.getElementById('mp');
My issue is that no matter the element i clicked i only get the orginal... for me it seems like the code groups it all together so when u click the ny link it takes this as all other divs are clicked. This was tested as when i clicked the ny link innerHTML in all divs was executed... i am completely stuck as to why this is so would greatly appreciate the help
You don't need inline event handlers
You can use event delegation
Use index to get the clicked element index in ul
HTML
<div class="grid_12">
<ul id="categories">
<li class="filter">Categories:</li>
<li id="ny"> New York
</li>
<li id="sc">Spanish Cities
</li>
<li id="gv">A Glasgow Viewpoint
</li>
<li id="sch">Some Churches
</li>
<li id="bh">Barcelona Highlights
</li>
<li id="mp">Martin’s Pictures
</li>
</ul>
</div>
Javascript
var id;
$('#categories').on('click', 'li>a', function () {
id = $(this).closest('li').index();
});
Demo: http://jsfiddle.net/tusharj/q9xbqck0/3/
When you say nyView.click you are referring to the function definition and that would always be treated as true value, so you would get first condition always.
var id;
$('#categories').on('click', 'li', function(){
id = this.id; // id = $(this).index();
});
My approach is very different, maybe someone else can work with your logic. I can't. My approach:
<div class="grid_12">
<ul id="categories">
<li class="filter">Categories:</li>
<li class="licategory" data-val="ny" data-id="1"> New York</li>
<li class="licategory" data-val="sc" data-id="1">Spanish Cities</li>
<li class="licategory" data-val="gv" data-id="1">A Glasgow Viewpoint</li>
<li class="licategory" data-val="sch data-id="1"">Some Churches</li>
<li class="licategory" data-val="bh" data-id="1">Barcelona Highlights</li>
<li class="licategory" data-val="mp" data-id="1">Martin’s Pictures</li>
</ul>
$("li").on("click",function(){
$("this").data("val");
$("this").data("id");
})
Add one common class like .categoryin all li and get the index()
$(".category").click(function(){
// console.log(this.id);
alert($(this).index())
});
Fiddle
nyView.click returns a function that's why value of id =1 always no matter which link you clicked.....try this code
<!doctype html>
<html>
<head>
<script>
function getImageCategories(element) {
var nyView = document.getElementById('ny');
var scView = document.getElementById('sc');
var gvView = document.getElementById('gv');
var schView = document.getElementById('sch');
var bhView = document.getElementById('bh');
var mpView = document.getElementById('mp');
var id=0;
if (element.parentNode === (nyView)) {
id = 1;
} else if (element.parentNode===scView) {
id = 2;
} else if (element.parentNode===gvView) {
id = 3;
} else if (element.parentNode===schView) {
id = 4;
} else if (element.parentNode===bhView) {
id = 5;
} else if (element.parentNode===mpView) {
id = 6;
}
alert(id);
}
</script>
</head>
<body>
<div class="grid_12">
<ul id="categories">
<li class="filter">Categories:</li>
<li id="ny"> New York</li>
<li id="sc">Spanish Cities</li>
<li id="gv">A Glasgow Viewpoint</li>
<li id="sch">Some Churches</li>
<li id="bh">Barcelona Highlights</li>
<li id="mp">Martin’s Pictures</li>
</ul>
</div>
</body>
</html>

How to get the prev and next elements of a particular class which are not siblings

Here is my code :
<ul>
<li class="active">
<div class="course_video_heading"><span class="minus"></span> Introduction <div class="course_duration" align="right">1m 21s</div></div>
<ul>
<li class="course_video viewed">
Welcome <div class="course_duration" align="right">1m 21s</div>
</li>
<li class="course_video viewed">
I need to select this <div class="course_duration" align="right">1m 21s</div>
</li>
</ul>
</li>
<li>
<div class="course_video_heading"><span class="plus"></span> Warm up <div class="course_duration" align="right">1h 15m</div></div>
<ul>
<li class="course_video viewed current">
Roll down <div class="course_duration" align="right">57s</div>
</li>
<li class="course_video">
Roll down with demi pointe variation <div class="course_duration" align="right">57s</div>
</li>
<li class="course_video" data-file="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" data-image="http://content.bitsontherun.com/thumbs/nPripu9l-480.jpg">
Side roll down <div class="course_duration" align="right">57s</div>
</li>
<li class="course_video">
Side roll down variation with contraction <div class="course_duration" align="right">57s</div>
</li>
<li class="course_video">
Class exercise <div class="course_duration" align="right">57s</div>
</li>
</ul>
</li>
<li>
<div class="course_video_heading"><span class="plus"></span> Brushes <div class="course_duration" align="right">1h 5m</div></div>
<ul>
<li class="course_video">
Welcome <div class="course_duration" align="right">1m 21s</div>
</li>
</ul>
</li>
</ul>
My requirement : There is a element, <li class="course_video viewed current">, I need the previous li which has course_video class. In this case it would be :
<li class="course_video viewed">
I need to select this <div class="course_duration" align="right">1m 21s</div>
</li>
What have I tried :
$(".current").prev(".course_video")
This is not working as it is in different li
Note : It is not the duplicate of following questions :)
jQuery to find nearest Div of Parent
Getting next closest select element with jquery
jquery find closest previous sibling with class
Try this : read the index of current li and if it is 0 then find the previous li of its parent li and then find the course_video. And if index is not 0, then find previous li using prev()
var index = $(".current").index();
if(index==0)
{
var previousLi = $(".current").closest('li').prev('li').find("li.course_video:last");
}
else
{
var previousLi = $(".current").prev(".course_video");
}
var vindex;
$().ready(function () {
$("li .course_video").each(function (index) {
if ($(this).hasClass('current')) {
vindex = index;
}
});
$("li .course_video").each(function (index) {
if (index == vindex - 1) {
alert($(this)[0].outerHTML);
}
});
});
this code will help you.
$('.current').parents('li').prev().find('li:last')
Here's the jsFiddle
You can do it easily with a function that checks the index of the item: if the index is 0 then you'll select the last li in the previous ul.
Element.prototype.previousLi = function() {
var i = $(this).index(),
n = this.parentElement.previousSibling.children.length;
if (i) return this.parentElement.children[i-1];
else return this.parentElement.previousSibling.children[n-1];
}
Then you can do:
var el = $(".course_video.viewed.current")[0];
var previous = el.previousLi();
Try this code , it will give you the desired result :
<script>
var currentLI = $("li.current");
prevLi=$(currentLI).parent('ul').parent('li').prev('li').find('li.viewed:last');
alert($(prevLi).html());
</script>

Categories

Resources