Javascript - Access multiple nested elements with Chrome Extension - javascript

I am attempting to get some values of a website using a Chrome Function i am working on. I am able to fetch the first listing-name using document.querySelector(".listing-name").textContent, however how would i go about fetching all listing-name into an Array?
DOM Structure
<div class="container">
<div class="active-listings">
<section class="listing">
<div class="listing-info">
<h3 class="listing-name">Listing 1</h3>
</div>
</section>
<section class="listing">
<div class="listing-info">
<h3 class="listing-name">Listing 2</h3>
</div>
</section>
</div>
</div>
I am new to Javascript so not entirely familiar with the correct syntax. However am i right in assuming i'd need to loop all the sections within the active-listings div and then obtain the listing-name that way?

As stated in the comments, the method you are looking for, which is available on all elements having querySelector as an available method, is querySelectorAll. Whereas querySelector returns the first element that matches, querySelectorAll matches any and returns them as an array.
As a result, in your example, if you were to get all the active-listings to get a sub-element's inner text, you'd simply do it this way (ES6):
window.onload = () => {
document.querySelectorAll(".active-listings .listing-name").forEach((element) => {
console.log(element.innerText);
});
};
<ul>
<li class="active-listings">
<h3 class="listing-name">Test</h3>
</li>
<li class="active-listings">
<h3 class="listing-name">Test</h3>
</li>
<li class="active-listings">
<h3 class="listing-name">Test</h3>
</li>
<li class="active-listings">
<h3 class="listing-name">Test</h3>
</li>
</ul>
If your nesting is more complex, or if you need to do additional processing, merely selecting active-listings is also a possibility.

You can simply use querySelectorAll : querySelectorAll
The querySelectorAll() method returns all elements in the document that matches a specified CSS selector(s), as a static NodeList object.
The NodeList object represents a collection of nodes. The nodes can be accessed by index numbers. The index starts at 0.
var matches = document.querySelectorAll("some_selector");
//then you can access the matched selector with `matches`

Related

Querying complex html document

I'm trying to query a complex web app for some data...
A very simplified example is the below
<section class="Test newTest testTest active">
<div>
</div>
<a class="classLink1 classlink2 classlink3" data-render="test">Link</a>
</div>
</div>
</section>
<section class="Test newTest testTest">
<div>
</div>
<a class="classLink1 classlink2 classlink3" data-render="test">Link</a>
</div>
</div>
</section>
Problem
There are a few <a> tags with very similasr class names and some dataset with unique values which I don't want to query
I'm trying to only target the <a> tag where the parent <section> has an .active class. But it may not be the immediate parent if that makes sense
I am trying something like this
document.querySelectorAll('section.Test.newTest.testTest.active a.classLink1.classlink2.classlink3 [data-render="test"]')
But it seems to return an empty nodelist.
You must not have the space between classlink3 and [data-render="test"], as the elements you are searching for have both classes and attribute, and aren't nested inside the "classes" element.
The right selector should be
'section.Test.newTest.testTest.active a.classLink1.classlink2.classlink3[data-render="test"]'
Which will select the following
Instead of

How can I get a Node's only direct children with a specific class name?

How can I get a Node's only direct children with a specific class name?
Example
<div class="list-group">
<div class="list-group-item">
<div class="list-group"> <!--I have this-->
<div class="list-group-item"> <!--And I want to reach this-->
<div class="list-group">
<div class="list-group-item"></div> <!--Not this-->
<div class="list-group-item"></div>
</div>
</div>
<div class="list-group-item"></div> <!--And get this-->
</div>
</div>
</div>
I have a list-group that contains items and groups and I want to keep that hierarchy and get a list-group's only direct list-group-items.
How can I do so?
You haven't mentioned if you use any JS frameworks, but with JQuery it is fairly simple... just use children()
In example $("#haveThis").children()
You can also filter children like: $("#haveThis").children("list-group-item")
docs: https://api.jquery.com/children/
For vanilla JS I'd do this:
[].slice.call(document.getElementById("havethis").children).filter(el=>el.className==='list-group-item')
In vanilla JS (if you're not using jQuery) element.children (where element is the parent you wish to query) will return a list of all direct child nodes, you would then itterate over the list list, looking for node.className = "list-group-item";
I've not found a way to do this with standard CSS selectors, so a coded solution seems to be the only option.
Get all elements with the specified class name:
var x = document.getElementsByClassName("list-group-item");
Link https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName

Cannot detect element by classname

I am a beginner and I am using pure javascript for DOM manipulation. I am not able to get all the divs in my section element. I get undefined. Please tell me what is the error and how I can fix it.
HTML
<section class="main-content">
<aside>
<p>
<span class="sidebartext">Watch this space for breaking news items.</span>
</p>
</aside>
<section class="notes">
<div id="Services" class="nav-pages active">Services</div>
<div id="Resources" class="nav-pages">Resources</div>
<div id="Contact-Us" class="nav-pages">Contact Us</div>
<div id="Company" class="nav-pages">Company</div>
</section>
</section>
JS
var navTabs = document.getElementsByClassName('notes').children;
console.log(navTabs);//undefined
No jQuery answers please !!!
getElementsByClassName returns an array of elements (actually, array-like - see #Hamms comment below), so children is undefined on it. If there's only one notes section, you can choose to use id="notes" instead (with getElementById) or iterate through the above array and access children from that.
That happens because getElementsByClassName returns an HTMLCollection or NodeList. If you console log just that element, "notes" you will see why you are getting an undefined.
Replace your JS code by:
var navTabs = document.getElementsByClassName('notes');
console.log(navTabs);
That will output an array which once expanded, it will show the content of the position [0]. If you expand that one you will get your NodeList labeled as childNodes. Expand it and you will get your divs.
Try this to get directly your divs:
console.log('Items: ',navTabs[0].childNodes);

How to traverse the DOM to get to specific element

I'm having a brain freeze trying to remember what the best way is to access the data attribute on an anchor tag when clicking a button that's not inside the tags container, could someone assist me on how I would do this, so if I click .js-watchlist-add I want to get the data-id of .js-film-entry:
JS
<div class="ctn">
<a href="/movie/{{id}}" class="film-entry js-film-entry" data-id="{{id}}">
<img src="{{poster}}" class="film-img">
<div class="result-film-details">
<h2 class="film-title">{{title}}</h2>
<p class="film-release-date">Released {{releaseYear}}</p>
<ul class="result-stats-tabs clearfix">
<li>{{vote_average}} <span>Vote Average</span></li>
<li>{{vote_count}} <span>Vote Count</span></li>
</ul>
</div>
</a>
<div class="cta-ctn">
<button class="watchlist-add js-watchlist-add">Add to watchlist</button>
<button class="watchlist-remove js-watchlist-remove">Remove from watchlist</button>
</div>
</div>
You can use closest() to get the parent element and find() to get the descendant within parent.
Live Demo
$(this).closest('.ctn').find('.js-film-entry').data('id');
You can use jQuery's has and find methods.
$('.ctn').has(this).find('.js-film-entry')
Adil's answer is great,
Though it may be more efficient to use children versus find, to avoid traversing descendants.
$(this).closest('.ctn').children('.js-film-entry').data('id');
Just to give another DOM traversal example, you could also use:
$(this).parent().siblings('.js-film-entry').data('id');

Selecting an element created using document.createElement jquery/javascript

I am creating a number of div and ul elements using document.createElement. In a case, when I am creating these elements I need to take reference of one of those elements that I created above and assign it as the parent to element that's next in line to be created.
I have the id (e.g "idoftheelement") of the created element but when I do
$('#idoftheelement')
I don't get the element.
Is there a possibility to get the element. If yes how ?
Edit:
Below is html structure I am trying to generate based on a JSON input data. Every element in the JSON array could have a child array of elements. All the elements will have the same markup and the difference is only in where they are getting placed. I have to construct this in a recursive way i.e for every JSON element check if child elements(and the child elements could also contain child elements) are present, if yes then i should append these child elements to corresponding parent thread block. This is why I need to know if there is a direct way to get the reference of parent element that is in context to the current element so that It can be appended.
<div id="comment-12345">
<div id="threads-block-12345"
<ul id="thread-12345">
<li id="thread-item-12346">
<div id="comment-12346">
<div id="threads-block-12346"
<ul id="thread-12346">
<li id="thread-item-12347">
<!--keeps growing if there till all the children are processed-->
</li>
</ul>
</div>
</div>
</li>
<li>
<div id="comment-xyz">
<div id="threads-block-xyz"
<ul id="thread-xyz">
<li id="thread-item-xyz">
<!--keeps growing if there till all the children are processed-->
</li>
</ul>
</div>
</div>
</li>
</ul>
</div>
The code $('#idoftheelement') tells me you are using jQuery, so you shouldn't be using document.createElement. What you need to do is create the element using jQuery and reference it by that variable. For example:
var $node = $("<div id='" + id + "'>")
$node.append( ... new elements ... )

Categories

Resources