forEach only uses first element - javascript

I got some sort of HTML Code as a List with links in each list item. I want to get those with JavaScript and only log them first for later usage. It's a List of jobs wich have a title, link and location.
The code looks kinda like this:
var jobs = document.getElementsByClassName("offerlist-item");
var jobList = [].slice.call(jobs);
var jobAnchor;
var jobName;
var jobUrl;
var jobLocation;
jobList.forEach(function(job) {
jobAnchor = $('h3.styleh3').html();
jobUrl = $(jobAnchor).attr('href');
jobName = $(jobAnchor).text();
jobLocation = $("li.noBorder").text();
console.log(this.jobUrl);
console.log(jobName);
console.log(jobLocation);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="offerlist-item">
<h3 class="styleh3">
<a href="someUrl1">
SomeTitle1
</a>
</h3>
<ul>
<li><li class="noBorder">someLocation1</li>
</ul>
</li>
<li class="offerlist-item">
<h3 class="styleh3">
<a href="someUrl2">
SomeTitle2
</a>
</h3>
<ul>
<li><li class="noBorder">someLocation2</li>
</ul>
</li>
<li class="offerlist-item">
<h3 class="styleh3">
<a href="someUrl3">
SomeTitle3
</a>
</h3>
<ul>
<li><li class="noBorder">someLocation3</li>
</ul>
</li>
</ul>
My problem is that only the first item is used in the forEach loop. Why is that so?

Firstly, your HTML is invalid. You've got an open li with no closing tag.
Secondly, the issue is because you're looking up every h3.styleh3 within each iteration of the loop. You should instead look at the ones inside the current job. You can do that using find(), like this:
var jobs = document.getElementsByClassName("offerlist-item");
var jobList = [].slice.call(jobs);
var jobAnchor;
var jobName;
var jobUrl;
var jobLocation;
jobList.forEach(function(job) {
jobAnchor = $(job).find('h3.styleh3').html();
jobUrl = $(jobAnchor).attr('href');
jobName = $(jobAnchor).text();
jobLocation = $(job).find("li.noBorder").text();
console.log(this.jobUrl);
console.log(jobName);
console.log(jobLocation);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="offerlist-item">
<h3 class="styleh3">
SomeTitle1
</h3>
<ul>
<li class="noBorder">someLocation1</li>
</ul>
</li>
<li class="offerlist-item">
<h3 class="styleh3">
SomeTitle2
</h3>
<ul>
<li class="noBorder">someLocation2</li>
</ul>
</li>
<li class="offerlist-item">
<h3 class="styleh3">
SomeTitle3
</h3>
<ul>
<li class="noBorder">someLocation3</li>
</ul>
</li>
</ul>
However it's worth noting that you're using an odd mix of native JS methods and jQuery. It's best to use either one or the other. Here's a pure jQuery implementation:
$('.offerlist-item').each(function() {
var $job = $(this);
var $jobAnchor = $job.find('h3.styleh3 a');
var jobUrl = $jobAnchor.attr('href');
var jobName = $jobAnchor.text();
var jobLocation = $job.find("li.noBorder").text();
console.log(jobUrl);
console.log(jobName);
console.log(jobLocation);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="offerlist-item">
<h3 class="styleh3">
SomeTitle1
</h3>
<ul>
<li class="noBorder">someLocation1</li>
</ul>
</li>
<li class="offerlist-item">
<h3 class="styleh3">
SomeTitle2
</h3>
<ul>
<li class="noBorder">someLocation2</li>
</ul>
</li>
<li class="offerlist-item">
<h3 class="styleh3">
SomeTitle3
</h3>
<ul>
<li class="noBorder">someLocation3</li>
</ul>
</li>
</ul>

There where a few problems:
Not necessarily a problem, but I replaces document.getElementsByClassName("offerlist-item") with the simple jQuery selector $('.offerlist-item'), which also reners [].slice.call(jobs) unnecessary
You always used the selector $('h3.styleh3') no matter what the currently looped job was. You can change that now, by using $a.find(sel). This will find all elements with the given selector "sel" that are children of "a".
var jobList = $('.offerlist-item');
var jobAnchor;
var jobName;
var jobUrl;
var jobLocation;
jobList.each(function() {
jobAnchor = $(this).find('h3.styleh3').html();
jobUrl = $(jobAnchor).attr('href');
jobName = $(jobAnchor).text();
jobLocation = $("li.noBorder").text();
console.log(this.jobUrl);
console.log(jobName);
console.log(jobLocation);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="offerlist-item">
<h3 class="styleh3">
<a href="someUrl1">
SomeTitle1
</a>
</h3>
<ul>
<li><li class="noBorder">someLocation1</li>
</ul>
</li>
<li class="offerlist-item">
<h3 class="styleh3">
<a href="someUrl2">
SomeTitle2
</a>
</h3>
<ul>
<li><li class="noBorder">someLocation2</li>
</ul>
</li>
<li class="offerlist-item">
<h3 class="styleh3">
<a href="someUrl3">
SomeTitle3
</a>
</h3>
<ul>
<li><li class="noBorder">someLocation3</li>
</ul>
</li>
</ul>

Related

Is there any way to apply javascript function on current open page url

<div><li class="item-list1"></li>
<ul>
<li class="item"><a href='/link1'>link1</a></li>
<li class="item"><a href='/link2'>link2</a></li>
<li class="item"><a href='/link3'>link3</a></li>
</ul>
</div>
<div><li class="item-list2"></li>
<ul>
<li class="item"><a href='/link4'>link4</a></li>
<li class="item"><a href='/link5'>link5</a></li>
<li class="item"><a href='/link6'>link6</a></li>
</ul>
</div>
Basically I want to apply JavaScript property on the grandparent of the current URL.
Like if the current open link is link4 then I want to find grandparent of the open link that is item-list2
I am doing window.location.href().parent().parent() but it not helps.
Edit:
Thanks, everyone for helping me out,
solution I got is given below:
const pathname = window.location.pathname
var li_attr = $(`a[href='${pathname}']`).closed("ul").prev("li")
as suggested by #bad_kotya and #freedomn-m
const pathname = window.location.pathname
$(`a[href='${pathname}']`).parent().parent()
Your HTML is not valid.
Once it is valid you can do this:
const pathname= new URL("https://www.yoursite.com/link4").pathname; // location.pathname; // on your server
console.log(pathname);
// must be quoted due to the / in the pathname
const $link = $("[href='" + pathname + "']"); // you can use a template literal too
const $parentUl = $link.closest("ul")
const $ulContainer = $parentUl.closest("li");
console.log($ulContainer.attr("class"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<ul>
<li class="item-list1">
<ul>
<li class="item">
<a href='/link1'>link1</a></li>
<li class="item">
<a href='/link2'>link2</a></li>
<li class="item">
<a href='/link3'>link3</a></li>
</ul>
</li>
</ul>
</div>
<div>
<ul>
<li class="item-list2">
<ul>
<li class="item">
<a href='/link4'>link4</a></li>
<li class="item">
<a href='/link5'>link5</a></li>
<li class="item">
<a href='/link6'>link6</a></li>
</ul>
</li>
</ul>
</div>

What part of this jQuery .replace is not working?

I've read at least, ten different similar topics but haven't been able to figure out, what the problem is.
I am trying to change, part the url's in my header menu. Those url's, which contains "onepage" should be replaced with a hashtag.
<ul>
<li class="menu-item">
<a class="level2" href="//test.com/products/iphone/iphone-onepage-32gb"><span>iPhone 32GB</span></a>
</li>
<li class="menu-item">
<a class="level2" href="//test.com/products/iphone/iphone-onepage-64gb"><span>iPhone 64GB</span></a>
</li>
</ul>
$('$('a[href*="onepage"]')').each(function() {
var text = $(this).text();
$(this).text(text.replace(new RegExp("onepage","g"), "#");
});
JSFiddle
$('$('a[href *= "onepage"] ')').each(function() {
var text = $(this).text();
$(this).text(text.replace(new RegExp("onepage", "g"), "#");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="menu-item">
<a class="level2" href="//test.com/products/iphone/iphone-onepage-32gb"><span>iPhone 32GB</span></a>
</li>
<li class="menu-item">
<a class="level2" href="//test.com/products/iphone/iphone-onepage-64gb"><span>iPhone 64GB</span></a>
</li>
</ul>
You should change the href instead of the text. Also, you have your css selector wrong.
$('a[href*="onepage"]').each(function() {
var href = $(this).prop("href");
// change the property href to new url
$(this).prop("href", href.replace(new RegExp("onepage", "g"), "#"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="menu-item">
<a class="level2" href="//test.com/products/iphone/iphone-onepage-32gb"><span>iPhone 32GB</span></a>
</li>
<li class="menu-item">
<a class="level2" href="//test.com/products/iphone/iphone-onepage-64gb"><span>iPhone 64GB</span></a>
</li>
</ul>
You could use plain javascript to change the href property, see following please:
$('a[href*="onepage"]').each(function() {
this.href = this.href.replace(/onepage/, "#");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li class="menu-item">
<a class="level2" href="//test.com/products/iphone/iphone-onepage-32gb"><span>iPhone 32GB</span></a>
</li>
<li class="menu-item">
<a class="level2" href="//test.com/products/iphone/iphone-onepage-64gb"><span>iPhone 64GB</span></a>
</li>
</ul>
$('a[href*="onepage"]').each(function() {
var str = $(this).attr('href').replace(/onepage/, "#");
$(this).attr('href',str);
});
or
$('a[href*="onepage"]').attr( "href", function( i, val ) {
return val.replace(/onepage/, "#");
});

How can I select a box which has specific text?

I have this HTML:
<h5>something</h5>
<ul>
<li class="name">John</li>
<li class="age">21</li>
</ul>
<h5>specific text</h5>
<ul>
<li class="name">Peter</li>
<li class="age">19</li>
</ul>
<h5>something else</h5>
<ul>
<li class="name">Ali</li>
<li class="age">62</li>
</ul>
I want to select this part:
<h5>specific text</h5>
<ul>
<li class="name">Peter</li>
<li class="age">19</li>
</ul>
The logic is the content of <h5> tag. I want the one which is specific text. Actually expected result is an array of both that name and that age. Some thing like this: var res = ['Peter', 19];.
But my code selects all those <ul>s:
$('ul').map(function (){
var res = [$(this).find('li.name').text(), $(this).find('li.age').text()];
});
How can I fix it?
You can use :contains() to find the H5 that contains the specific string you want. Then use .next() to get that ul associated with the h5
$("h5:contains('specific text')").next('ul').map(function (){
var res = [$(this).find('li.name').text(), $(this).find('li.age').text()];
console.log(res)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h5>something</h5>
<ul>
<li class="name">John</li>
<li class="age">21</li>
</ul>
<h5>specific text</h5>
<ul>
<li class="name">Peter</li>
<li class="age">19</li>
</ul>
<h5>something else</h5>
<ul>
<li class="name">Ali</li>
<li class="age">62</li>
</ul>
Jquery script for getting data from ul list :
$('ul').map(function (){
var res = [$(this).find('li.name').text(), $(this).find('li.age').text()];
// console.log(res);
});
var htmVal = '';
$('h5').each(function(index){
htmVal = $(this).html();
if(htmVal == 'something else'){
var detail ={name:$(this).next().find('li.name').html(),age:$(this).next().find('li.age').html()};
console.log(detail);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h5>something</h5>
<ul>
<li class="name">John</li>
<li class="age">21</li>
</ul>
<h5>specific text</h5>
<ul>
<li class="name">Peter</li>
<li class="age">19</li>
</ul>
<h5>something else</h5>
<ul>
<li class="name">Ali</li>
<li class="age">62</li>
</ul>

Convert dynamic DOM structure to JSON

How can convert below DOM to JSON array which will have many more leafs in thefuture . I have tried a lot but didn't got any solution. I found this but it is not possible in my case.
HTML Code
<ul id="org1">
<li>
Main
<ul data-self="1">
<li data-self="2" data-parent="1">A
<ul data-self="2">
<li data-self="5" data-parent="2">A1</li>
<li data-self="6" data-parent="2">A2</li>
<li data-self="7" data-parent="2">A3</li>
<li data-self="8" data-parent="2">A4</li>
<li data-self="9" data-parent="2">A5</li>
<li data-self="10" data-parent="2">A6</li>
</ul>
</li>
<li data-self="3" data-parent="1">B
<ul data-self="3">
<li data-self="11" data-parent="3">B1</li>
<li data-self="12" data-parent="3">B2</li>
<li data-self="13" data-parent="3">B3</li>
<li data-self="14" data-parent="3">B4</li>
</ul>
</li>
</ul>
</li>
</ul>
JSON Required is
{
1:{
2:{5,6,7,8,9,10},
3:{11,12,13,14}
}
}
Script
function recursive(dis)
{
$(this).find(' > ul ').each(function(){
params[$(this).attr('data-self')]=[];
var i=0;
$(this).find('li').each(function(){
if($(this).has('ul'))
{
params[$(this).attr('data-parent')][i++]=rec(this);
}else
{
params[$(this).attr('data-parent')][i++]=$(this).attr('data-self');
}
});
});
}
recursive('#org1');
console.log(params);
I would prefer something like the following. The 2 changes in the HTML you need to make are:
1) Add a class to your ul such as <ul data-self="2" class="nodes">. 2) Add a class to the wrapper ul such as <ul data-self="1" class="parent">.
var json = {};
$("#org1").find("ul.parent").each(function() {
var $this = $(this);
json[$this.data("self")] = {};
var $nodes = $this.find("ul.nodes");
$nodes.each(function() {
var children = $(this).find("li").map(function() {
return $(this).data("self")
}).get();
json[$this.data("self")][$(this).data("self")] = children;
});
});
alert (JSON.stringify(json));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="org1">
<li>
Main
<ul data-self="1" class="parent">
<li data-self="2" data-parent="1">A
<ul data-self="2" class="nodes">
<li data-self="5" data-parent="2">A1</li>
<li data-self="6" data-parent="2">A2</li>
<li data-self="7" data-parent="2">A3</li>
<li data-self="8" data-parent="2">A4</li>
<li data-self="9" data-parent="2">A5</li>
<li data-self="10" data-parent="2">A6</li>
</ul>
</li>
<li data-self="3" data-parent="1">B
<ul data-self="3" class="nodes">
<li data-self="11" data-parent="3">B1</li>
<li data-self="12" data-parent="3">B2</li>
<li data-self="13" data-parent="3">B3</li>
<li data-self="14" data-parent="3">B4</li>
</ul>
</li>
</ul>
</li>
</ul>

Count the number of displayed elements in a HTML list

I have a list of list items which are display: none by default. I programmatically change a certain number of them to list-items.
I've been trying to use querySelectorAll but when I try:
document.querySelectorAll("#ulname style[display*='list-item']")
it returns an empty array (I know it is at least one).
Ideas on how to modify my selectors or another approach? I would like to know after the fact how many items are displayed.
var liList = document.getElementById("myul").getElementsByTagName("li");
var largo = liList.length
alert(largo);
WHERE "myul" is the id of the list and largo is number of li items
<ul id="myul">
<li>hello</li>
<li>world</li>
</ul>
the alert would be 2
<ul id="myul">
<li>hello</li>
<li>world
<ul>
<li>here we are</li>
<ul>
</li>
</ul>
the alert would be 3
var ul = document.getElementById("myul");
var liNodes = [];
for (var i = 0; i < ul.childNodes.length; i++) {
if (ul.childNodes[i].nodeName == "LI") {
liNodes.push(ul.childNodes[i]);
}
}
totalLis = liNodes.length;
Adding text to your ul tag
var txt = document.createTextNode("gsdgds");
ul.appendChild(txt);
Adding li tag to your ul tag
var txt = "<li>dsgdsgs</li>";
ul.innerHTML(txt);
<!DOCTYPE html>
<html>
<body onload="myFunction()">
<p>Maybe this answer can help. I improvise for this after a few days of testing. This is what I got. Hope it helps you.</p>
<li class="sidenav-item open active">
<a href="#" class="sidenav-link sidenav-toggle" ></i>
<div class="text-white">Hi, There!
<div class="badge badge-primary" id="ul-me"></div></div>
</a>
<ul class="sidenav-menu" id="ul1">
<li class="sidenav-item active">
<a href="#" class="sidenav-link" >
<div class="text-white" >Home</div>
</a>
</li>
<li class="sidenav-item" id="ul2">
<a href="#" class="sidenav-link" >
<div class="text-white" >Blog</div>
</a>
</li>
<li class="sidenav-item" id="ul3">
<a href="#" class="sidenav-link" >
<div class="text-white" >Downloads</div>
</a>
</li>
<li class="sidenav-item" id="ul4">
<a href="#" class="sidenav-link" >
<div class="text-white" >Contact</div>
</a>
</li>
<li class="sidenav-item" id="ul5">
<a href="#" class="sidenav-link" >
<div class="text-white" >About</div>
</a>
</li>
</ul>
</li>
'''
<!-- Count Item (li) in <ul> -->
<script>
function myFunction() {
var mylist = [document.getElementById("ul1"), ("ul2"), ("ul3"), ("ul4"), ("ul5")];
document.getElementById("ul-me").innerHTML = mylist.length;
}
</script>
</body>
</html>

Categories

Resources