I'm trying to get the index of an element in a class. For example if I have a class called myClass with 5 elements, and the fourth element has an id of fourth, I want to get the index number of #fourth from the class.
I tried using indexOf like this:
var myClass = document.getElementsByClassName('myClass');
var fourth = document.getElementById('fourth');
console.log(myClass.indexOf(fourth));
But I get an error saying:
Uncaught TypeError: myClass.indexOf is not a function
JSFiddle
Code Snippet
var myClass = document.getElementsByClassName('myClass');
var fourth = document.getElementById('fourth');
console.log(myClass.indexOf(fourth));
<div class="myClass"></div>
<div class="myClass"></div>
<div class="myClass"></div>
<div class="myClass" id="fourth"></div>
<div class="myClass"></div>
I then tried creating my own function that gets the index from the class:
function indexInClass(node) {
var className = node.className;
var num = 0;
for (var i = 0; i < className.length; i++) {
if (className[i] === node) {
return num;
}
num++;
}
return -1;
}
But I get undefined when I use it.
How can I get the index of the class?
JSFiddle
Code Snippet
var myClass = document.getElementsByClassName('myClass');
var fourth = document.getElementById('fourth');
function indexInClass(node) {
var className = node.className;
var num = 0;
for (var i = 0; i < className.length; i++) {
if (className[i] === node) {
return num;
}
num++;
}
return -1;
}
console.log(myClass[indexInClass(fourth)]);
<div class="myClass"></div>
<div class="myClass"></div>
<div class="myClass"></div>
<div class="myClass" id="fourth"></div>
<div class="myClass"></div>
getElementsByClassName returns an HTML collection, not an array, thus you cannon use indexOf on it.
Iterating over the elements is the way to go, but the problem with your custom function was this:
for (var i = 0; i < className.length; i++) {
You were iterating over className, which is a string containing your node's class name, while instead you should be iterating over your element collection myClass.
Here's your custom function fixed:
var myClass = document.getElementsByClassName('myClass');
var fourth = document.getElementById('fourth');
function indexInClass(node) {
var className = node.className;
var num = 0;
for (var i = 0; i < myClass.length; i++) {
if (myClass[i] === node) {
return num;
}
num++;
}
return -1;
}
console.log(myClass[indexInClass(fourth)]);
<div class="myClass"></div>
<div class="myClass"></div>
<div class="myClass"></div>
<div class="myClass" id="fourth"></div>
<div class="myClass"></div>
UPDATE
Thanks for the answer! I want to create a function that I can use anywhere, meaning, not specific to myClass. How can I achieve that?
Here's a sligthly optimized version of your function:
function indexInClass(collection, node) {
for (var i = 0; i < collection.length; i++) {
if (collection[i] === node)
return i;
}
return -1;
}
var myClass = document.getElementsByClassName('myClass');
var fourth = document.getElementById('fourth');
alert("The ID is: " + indexInClass(myClass, fourth));
<div class="myClass"></div>
<div class="myClass"></div>
<div class="myClass"></div>
<div class="myClass" id="fourth"></div>
<div class="myClass"></div>
UPDATE 2
Is there a way to do it without the collection argument? For example, is there a way to get the class from the id?
function indexInClass(node) {
var collection = document.getElementsByClassName(node.className);
for (var i = 0; i < collection.length; i++) {
if (collection[i] === node)
return i;
}
return -1;
}
var fourth = document.getElementById('fourth');
alert("The ID is: " + indexInClass(fourth));
<div class="myClass"></div>
<div class="myClass"></div>
<div class="myClass"></div>
<div class="myClass" id="fourth"></div>
<div class="myClass"></div>
Be careful with .className because it will work properly if the node has one class. If you expect more, you'd need to extract the common one, either from className or classList.
getElementsByClassName returns an HTMLCollection, which does not have the indexOf array methods.
If you have access to Array.from, then the simple solution is to use it to convert the collection to an array and call indexOf:
Array.from(document.getElementsByClassName('myClass'))
.indexOf(fourth); //3
If you can't use Array.from, then Array.prototype.slice.call should work:
Array.prototype.slice.call(document.getElementsByClassName('myClass'))
.indexOf(fourth); //3
Your custom function has the right idea, you're just iterating over the wrong variable. Fiddle
var myClass = document.getElementsByClassName('myClass');
var fourth = document.getElementById('fourth');
function indexInClass(node) {
var className = node.className;
var num = 0;
for (var i = 0; i < myClass.length; i++) {
if (myClass[i] === node) {
return num;
}
num++;
}
return -1;
}
console.log(indexInClass(fourth));
Related
I have an HTML like this
How add ID to HTML href with javascript
<div class="tab">
exp
</div>
<div class="tab">
exp
</div>
<div class="tab">
exp
</div>
<script>
var els = document.getElementsByClassName("tab");
// loops els
for(var i = 0, x = els.length; i < x; i++) {
els[i].onclick = function(){
x = document.querySelector(".tab> a")
// do something
x.id = "expid";
}
}
</script>
I want to add the id to each tag when I click this. Pls help me. Thks so much
<div class="tabs">
... your html code.
</div>
const tabs = document.querySelector('.tabs')
tabs.addEventListener('click', event => {
const aTag = event.target
if (aTag.tagName !== 'A') return
aTag.id = `EXPID#${getIndexIn(aTag, tabs)}`
})
function getIndexIn(element, parent): number
What's the meaning to be it?
Your call to document.querySelector() always returns the first .tab > a link in the document. You can this.querySelector() to return the link in the DIV that you clicked on instead.
I've changed the code to use a class rather than ID, since you shouldn't have duplicate IDs.
Loop through all the DIVs. If it's the DIV that the user clicked on, add the class, otherwise remove it.
var els = document.getElementsByClassName("tab");
// loops els
for (var i = 0, x = els.length; i < x; i++) {
els[i].onclick = function() {
for (var j = 0; j < els.length; j++) {
x = els[j].querySelector("a");
if (els[j] == this) {
x.classList.add("expid");
} else {
x.classList.remove("expid");
}
}
}
}
.expid {
background-color: yellow;
}
<div class="tab">
exp
</div>
<div class="tab">
exp
</div>
<div class="tab">
exp
</div>
const anchors = document.getElementsByTagName('a');
const ids= [1,2,3,4,5];
let index =0 ;
for(let a of anchors ){
a.href=ids[index++]
}
you can try this way it's a cool and easiest what I do with pure js
I am trying to only replace the content of the div with the "replace this".
The content of each div is dynamically created, so i have to check which class needs to be changed. I tried it with a for-loop and so far I am getting the right div but having trouble changing its content. The main problem is that they all have the same class. How can I put the new text into the correct div without changing the others?
var x = document.getElementsByClassName("class_name");
var teststring = "rep";
for (i = 0; i < x.length; i++) {
if (x[i].toString().indexOf(teststring) > 0) {
this.innerHTML = "text3";
}
}
<div class="class_name">
text1
</div>
<div class="class_name">
text2
</div>
<div class="class_name">
replace this
</div>
Declare the variable with let in the for loop which will create it's own scope within curly braces ({...}). Instead of using this, use the current element with x[i]. x[i] refers to the element itself, you have to take the content from it.
I will prefer textcontent instead of innerHTML
var x = document.getElementsByClassName("class_name");
var teststring = "rep";
for (let i = 0; i < x.length; i++) {
if (x[i].textContent.indexOf(teststring) > 0) {
x[i].textContent = "text3";
}
}
<div class="class_name">
text1
</div>
<div class="class_name">
text2
</div>
<div class="class_name">
replace this
</div>
Use x[i].innerHTML not this.innerHTML
var x = document.getElementsByClassName("class_name");
var teststring = "rep";
for (i = 0; i < x.length; i++) {
if(x[i].innerHTML.indexOf(teststring) !== -1) {
x[i].innerHTML = "text3";
}
}
DEMO
https://jsfiddle.net/0cmz4pvk/5/
I have a problem for getting children using getElementsByClassName method.
I'm using OOP way just like Jquery Does.
"use strict";
var $, i;
(function() {
$ = function(el) {
return new obj$(el);
};
var obj$ = function(el) {
var firstChar = el.charAt(0),
cl = document.getElementsByClassName(el.slice(1));
switch (firstChar) {
case ".":
for (i = 0; i < this.length; i++) {
this[i] = cl[i];
}
break;
}
};
obj$.prototype = {
find : function(child) {
for (i = 0; i < this.length; i++) {
this[i].getElementsByClassName(child)[0];
}
return this;
},
html : function(data) {
for (i = 0; i < this.length; i++) {
this[i].innerHTML = data;
}
return this;
}
};
})();
var x = $(".parent").find("child").html("replace!");
console.log(x);
<div class="parent">
this is parent 1
<p class="child">test 1</p>
</div>
<div class="parent">
this is parent 2
<p class="child">test 2</p>
</div>
<div class="parent">
this is parent 3
<p class="child">test 3</p>
</div>
jsFiddle : https://jsfiddle.net/Lng5mn3o/
It doesn't work.
I have updated fiddle for you - https://jsfiddle.net/Lng5mn3o/3/
The main thing what i changed in your jsfiddle example, i created this['elements'] to store matched elements and used it length in loop rest was ok in your code
// define blank array
this['elements'] = new Array();
// store elements
this['elements'][i] = cl[i];
// loop over that elements
for (i = 0; i < this['elements'].length; i++) {
function storeid(){
var className = document.getElementsByClassName('Jicon');
var classnameCount = className.length;
var IdStore = new Array();
for(var j = 0; j < classnameCount; j++){
IdStore = classnameCount.id[j];
}
}
My intention is to get the id of all elements with a specific class name and store them in array.
Demo
You will get all the ids in IdStore array.
function storeid(){
var className = document.getElementsByClassName('Jicon');
var classnameCount = className.length;
var IdStore = new Array();
for(var j = 0; j < classnameCount; j++){
debugger;
IdStore.push(className[j].id);
}
alert(IdStore.length);
}
storeid();
<div class="Jicon" id="displayImage1">image1</div>
<div class="Jicon" id="displayImage2">image2</div>
<div class="Jicon" id="displayImage3">image3</div>
<div class="Jicon" id="displayImage4">image4</div>
I prefer querySelectorAll for this kind of things, since getElementsByClassName returns a live list, which could mess up other logic if you add/remove elements with that class.
var ids = Array.prototype.slice.call(document.querySelectorAll('.Jicon')).map(function ( element ) {
return element.id;
});
You need few changes like following:
You must use className as it's actual array of elements which is returned by your query getElementsByClassName()
You must use .push() to add item into the array
for(var j = 0; j < classnameCount; j++){
IdStore.push(className[j].id); // use className instead of classnameCount
}
Demo
function storeid(){
var className = document.getElementsByClassName('Jicon');
return className.map(function(cur){
return cur.id
});
}
document.write( JSON.stringify(storeid()) )
<div class="Jicon" id="displayImage1">image1</div>
<div class="Jicon" id="displayImage2">image2</div>
<div class="Jicon" id="displayImage3">image3</div>
<div class="Jicon" id="displayImage4">image4</div>
function storeid(){
var className = document.getElementsByClassName('Jicon');
var classnameCount = className.length;
var IdStore = new Array();
for(var j = 0; j < classnameCount; j++){
IdStore[j] = className[j].id;
}
alert(IdStore.length);
}
here goes your code. Voila!!
NOTE: remove the alert in code.
I Have created a NodeList by obtaining HTML elements with a shared className by:
> var btn = document.getElementsbyClassName("btn")
This is the HTML code:
<div id="main">
<div class="btn">
</div>
<div class="btn">
</div>
<div class="btn">
</div>
<div class="btn">
</div>
</div>
Thus this particular NodeList object has a length of 4.
Now I want to invoke a function when one of this elements is being clicked. I accomplish that by using a for loop:
for(var i = 0; i < btn.length ; i++) {
btn[i].onclick = doSomething;
};
function doSomething() {
// here come some code.
};
But how can I obtain the index of the NodeList on which te event was fired? And how can I assign unique names for each of the elements of the array?
Here's what I'd do:
var btn = document.getElementById('main').getElementsByTagName('div');
for(var i = 0; i < btn.length ; i++) {
btn[i].id = "btn"+i;
if(btn[i].className=="btn")
btn[i].onclick = doSomething;
};
function doSomething() {
var num = this.id.substr(3);
alert("Div " + num + " clicked");
};
(I took out getElementsByClassName() to make it cross browser. That is of course assuming you haven't implemented your own override for the method to make it cross browser).
Edit: For your innerHTML question, check out the attached fiddle to see it working fine:
http://jsfiddle.net/TdCD8/
You can include it in the function signature :
for(var i = 0; i < btn.length ; i++) {
btn[i].onclick = doSomething(i);
};
function doSomething(i) {
return function() {
btn[1].innerHTML = i;
}
};