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

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);
}

Related

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>

I can't access HTMLCollection

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>

modify the data-donut attribute of the divs from javascript

My javascript
var currentMonth= new Date().getMonth();
if (demo.length >= currentMonth){
var d3data = demo[currentMonth];
// output will be ["23", "19"]
now i need to update output values to #donut and #donut1 (data-donut="")
values are coming from json it may change according to month
for reference i have added FIDDLE
http://jsfiddle.net/Qh9X5/3166/
<div class="zipper">
<div class="current">
<div class="title_text">current</div>
<div id="donut" data-donut="42"></div>///here in the data-donut value
</div>
<div class="target">
<div class="title_text">Target</div>
<div id="donut1" data-donut="62"></div>
</div>
</div>
Any help is Appreciated
You can use this to assign the values from the array (assuming the array is the result after parsing it from json)
var d3data = demo[currentMonth];
// assuming that this results in d3data = ["23", "19"];
$(document).ready(function() {
$("div[data-donut]").each(function(i) {
$(this).attr('data-donut', d3data[i]);
});
});
The first value of the array will be assigned to the first div and the second value to the second one.
See JSFiddle
Looks like you want to modify the data-donut attribute of the divs. Hope this will help
document.getElementsById("donut").setAttribute("data-donut","<your value>");
document.getElementsById("donut1").setAttribute("data-donut","<your value>");
This will work
obj = ["23", "19"];
var keys = Object.keys(obj);
for (var i = 0,j=1; i < keys.length; i++,j++) {
var val = obj[keys[i]];
document.getElementById("donut"+j).setAttribute("data-donut", val);
}
<div class="zipper">
<div class="current">
<div class="title_text">current</div>
<div id="donut1" data-donut="42"></div>///here in the data-donut value
</div>
<div class="target">
<div class="title_text">Target</div>
<div id="donut2" data-donut="62"></div>
</div>
</div>
This is not json format ["23", "19"]
e.g this is an array
var d3data = ["23", "19"];
$('#donut').data('donut', d3data[0]);
$('#donut1').data('donut',d3data[1]);

Categories