I can't access HTMLCollection - javascript

I can't access HTMLCollection Type When I use getElementsByClassName.
I wanna get the length but I can't get that
var documentHeader = parent.document.all['header'];
var motionClass = documentHeader.getElementsByClassName('motion');
this is a result of motionClass
HTMLCollection []
0: div.motion
length: 1
__proto__ : HTMLColletion
If I access length result is 0
How can I result This Issue?

NOTE: Here we execute the code safely when the DOM is ready. Ensure you are doing that.
document.addEventListener('DOMContentLoaded', function() {
let motionArray = document.getElementsByClassName('motion');
console.log(motionArray.length);
});
<div class='motion'>test</div>
<div class='motion'>test</div>
<div class='motion'>test</div>
<div class='motion'>test</div>
<div class='motion'>test</div>
<div class='motion'>test</div>
<div class='motion'>test</div>

To give a more modern approach - use documentQuerySelectorAll() to get the collection - this can then be iterated over to give each item - or can give the length of the collection.
let motions = document.querySelectorAll('.motion');
console.log(motions.length); // gives 5
console.log(motions[2].textContent); // gives "3" - the text content of that element
<div class='motion'>1</div>
<div class='motion'>2</div>
<div class='motion'>3</div>
<div class='motion'>4</div>
<div class='motion'>5</div>

Related

jQuery remove duplicate but keep last occurance

SO is full of these questions, I know, but after going through 20+ pages and numerous google searches I end up asking because I can't find the answer.
I want to filter through data attributes and keep the last occurrence. So for instance with this code:
<div data-id="001">Hello</div>
<div data-id="001">World</div>
<div data-id="002">Keep</div>
<div data-id="002">Only</div>
<div data-id="002">Unique</div>
<div data-id="003">Last</div>
<div data-id="003">Word</div>
<div data-id="004">Please</div>
<br><br>
<p>Result should be: World Unique Word Please</p>
I tried numerous ideas from the SO pages and google searches but I have no luck in keeping the last items. First items though work perfectly with this code.
var found = {};
$('[data-id]').each(function(){
var $this = $(this);
if(found[$this.data('id')]){
$this.remove();
}
else{
found[$this.data('id')] = true;
}
});
Here is a fiddle, hopefully that makes things easier http://jsfiddle.net/hx9Lzqf6/
We can find the last index with same id,store them into an array,then call $.each() again to remove elements with index not in the array
let result = {}
$('[data-id]').each(function(i,e){
let id = $(e).attr("data-id")
result[id] = i
});
result = Object.values(result)
$('[data-id]').each(function(i,e){
let id = $(e).attr("data-id")
if(!result.includes(i)){
$(e).remove()
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div data-id="001">Hello</div>
<div data-id="001">World</div>
<div data-id="002">Keep</div>
<div data-id="002">Only</div>
<div data-id="002">Unique</div>
<div data-id="003">Last</div>
<div data-id="003">Word</div>
<div data-id="004">Please</div>
<br><br>
<p>Result should be: World Unique Word Please</p>

how to find out each index of a div

For example, I have
<div class="stick active"></div>
<div class="stick"></div>
<div class="stick"></div>
<div class="stick"></div>
<div class="stick"></div>
I need to find out all the indexes from the stick classes so that I can refer to each of them further [0],[1],[2]...
I tried to convert them to an array via [...] and via Array.prototype.slice.call
but when I try to interact with them, I get "undefined"
use this I think it will help you:
for first index:
var x = document.querySelectorAll(".stick");
console.log(x[0])
for all:
var x = document.querySelectorAll(".stick");
console.log(x)
Use Document.querySelectorAll() to create a NodeList.
querySelectorAll():
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
NodeList:
https://developer.mozilla.org/en-US/docs/Web/API/NodeList
const highlightedItems = document.querySelectorAll(".stick");
// access the second node:
console.log(highlightedItems[2].textContent);
// loop through all nodes
for (let i = 0; i < highlightedItems.length; i++) {
let item = highlightedItems[i];
console.log( item.id );
}
<div class="stick active"></div>
<div class="stick" id="1">A</div>
<div class="stick" id="2">B</div>
<div class="stick" id="3">C</div>
<div class="stick" id="4">D</div>
I think you want to hanle it via getElementsByClassName. This returns an HTML collection, not an array, thus you cannot use indexOf on it.
Iterating over the elements is the way to go, iterating over className, which is a string containing your node's class name, like this:
let stick = document.getElementsByClassName('stick');
for(let i=0; i < stick.length; i++){
console.log(stick[i]);
}

JQuery: Loop through elements and set as variable for outside scope

I am trying to retrieve a DOM element from an array, and I want to set it as a variable to use outside its scope. Right now, my variable future_devices returns one object as expected. But my other variable future_device returns the object when the current DOM should have returned [] due to my last if statement. I originally tried to declare my variables as var due to scope but that did not help. Here is my code:
var future_devices = $('.hardware .future-hardware')
if (future_devices.length) {
let future_device = $(future_devices)
.each(function() {
let device = this
let device_work_order = $(device)
.data(
'work-order'
)
if (device_work_order == data['new_host']['work_order']) {
return device
}
})
I can tell you on the said DOM, the two variables I am using to compare have the following values:
device_work_order = 3MOD0
data['new_host']['work_order'] = 3MOD9
So since future_devices returns only one object and my last if statement is not true, I should get [], right?
$(...) is returning the jQuery collection and always will regardless. So an assignment statement using .each() is the wrong approach.
Solution: Assign the return of .filter() instead. Filter is designed to accomplish your goal. Reference
NOTE: You should realize that if there is more than one match, it will return the entire collection of matches. In the code below I show only the first match, but since there are two matches (for demonstration), you'll see that both matches are returned.
const future_devices = $('.hardware .future-hardware');
const data = {new_host: {work_order: 333}};
const future_device = $(future_devices)
.filter(function(idx, el) {
let device_work_order = $(el).data('work-order');
if (device_work_order == data['new_host']['work_order']) {
return true;
} else {
return false;
}
})
console.log("First match only: ", future_device[0]); // First match
console.log("Collection: ",future_device); // All matches
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="hardware">
<div class="future-hardware" data-work-order="111">111</div>
</div>
<div class="hardware">
<div class="future-hardware" data-work-order="333">First Match</div>
</div>
<div class="hardware">
<div class="future-hardware" data-work-order="111">111</div>
</div>
<div class="hardware">
<div class="future-hardware" data-work-order="333">Second Match</div>
</div>
<div class="hardware">
<div class="future-hardware" data-work-order="111">111</div>
</div>
<div class="hardware">
<div class="future-hardware" data-work-order="111">111</div>
</div>

How to addEventListener and function with element as a parameter to multiple elements?

My goal is to have a bunch of div with clickable words to pass their ids to a Javascript function when one of them is clicked by the user. It works flawlessly for
<div id="wordbox">
<div id="pd"><h4>pdf</h4><br></div>
<div id="an"><h3>analysis</h3></div>
<div id="ai"><h2>artificial intelligence</h2></div>
<div id="tr"><h4>trends</h4><br><br></div>
<div id="dm"><h3>data mining</a></div>
</div>
var word = document.getElementById("pd");
word.addEventListener("click", function(){ showSlide(word.id) });
but I don't manage to get it working for all elements. This fails:
var wb = document.getElementById("wordbox").children;
wb.forEach(function (element, index){
element.addEventListener("click", function(){
showSlide(element.id);
});
});
Any ideas?
When you select the children from a node, it actually returns an array-like collection which is similar but not quite an array. In order to use forEach you first need to convert it into an array, and in the case below, I used the spread syntax to convert it into an array that allows me to use forEach.
const wb = document.querySelector('#wordbox')
const children = [...wb.children]
children.forEach(child => {
child.addEventListener('click', () => {
console.log(child.id)
})
})
<div id="wordbox">
<div id="pd"><h4>pdf</h4><br></div>
<div id="an"><h3>analysis</h3></div>
<div id="ai"><h2>artificial intelligence</h2></div>
<div id="tr"><h4>trends</h4><br><br></div>
<div id="dm"><h3>data mining</a></div>
</div>
wb is not a real array, it is an array-like object called live HTMLCollection. You can get an array using Array.from(). You can also use document.querySelectorAll() to select the elements
var wb = document.querySelectorAll("#wordbox > div");
// new browsers - https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach#bcd:api.NodeList.forEach
// wb
// To support older browsers
Array.from(wb)
.forEach(function(element, index) {
element.addEventListener("click", function() {
console.log(element.id);
});
});
<div id="wordbox">
<div id="pd">
<h4>pdf</h4><br></div>
<div id="an">
<h3>analysis</h3>
</div>
<div id="ai">
<h2>artificial intelligence</h2>
</div>
<div id="tr">
<h4>trends</h4><br><br></div>
<div id="dm">
<h3>data mining</a>
</div>
</div>

How do I convert a HTMLCollection into an array, without emptying it?

I am trying to convert an HTMLCollection of 4 divs into an array, but every method I try seems to result in the array being emptied.
<div class="container">
<div class="shape" id="one"></div>
<div class="shape" id="two"></div>
<div class="shape" id="three"></div>
<div class="shape" id="four"></div>
</div>
Methods I've attempted - as per this previous question:
var shapesHC = document.getElementsByClassName('shape');
//gives HTMLCollection
var shapesArrCall = [].slice.call(shapesHC);
// returns empty array
var shapesArrHC = Array.from(shapesHC);
// returns empty array
var shapesArrHCSpread = [...shapesHC];
// returns empty array
I'd really appreciate if anyone can point out where I'm going wrong here.
Thanks.
Try using this:
setTimeout(() => {
this.convertToArray();
});
convertToArray() {
const shapesHC = document.getElementsByClassName('shape');
const shapesArrHCSpread = [...(shapesHC as any)];
console.log(shapesArrHCSpread);
}

Categories