How to add ID to <a href> on click using JavaScript - javascript

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

Related

Getting Random Nulls on .querySelector() in for Loop

<div id="agg-filter-buttons">
<button class="btn filter-btn" onclick="filterSelection(event)"><span data-
value="freespins">Free Spins <div class="num-brands"></div> </span></button>
<button class="btn filter-btn" onclick="filterSelection(event)"> <span data-value="bigbonus">Big Bonus <div class="num-brands"></div> </span></button> </div>
enter code here
</div>
<div class="brand-row the-table-row all row-1 filterDiv bigbonus newPlay show">
Row 1
</div>
<div class="brand-row the-table-row all row-2 filterDiv freespins newPlay show">
Row 2
</div>
filterSelection();
function filterSelection(e) {
var x, i, c;
x = document.getElementsByClassName("filterDiv");
var allBtns = document.getElementsByClassName("filter-btn")
for(i = 0; i<allBtns.length; i++){
let rowsAffected = allBtns[i].querySelector('.num-brands');
rowsAffected.innerText = '';
}
c = "all";
if(e && e.target.dataset){
c = e.target.dataset.value ? e.target.dataset.value : "all";
}
const numBrands = [];
for (i = 0; i < x.length; i++) {
x[i].classList.remove('show');
void x[i].offsetWidth;
if (x[i].classList.contains(c)) {
x[i].classList.add('show');
numBrands.push(i);
}
}
if(e && e.target){
e.srcElement.children[0].innerText = ` (${numBrands.length})`;
}
}
// Add active class to the current control button (highlight it)
var btnContainer = document.getElementById("agg-filter-buttons");
var btns = btnContainer.getElementsByClassName("filter-btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function($this) {
var current = document.querySelectorAll(".active-btn");
current[0].className = current[0].className.replace(" active-btn", "");
this.className += " active-btn";
});
}
var filter = document.getElementById('agg-filter-buttons');
filter.addEventListener('click', function(){
document.getElementsByClassName('section--btable')[0].classList.add('flash');
});
filterSelection();
function filterSelection(e) {
var x, i, c;
x = document.getElementsByClassName("filterDiv");
var allBtns = document.getElementsByClassName("filter-btn")
for (i = 0; i < allBtns.length; i++) {
let rowsAffected = allBtns[i].querySelector('.num-brands');
rowsAffected.innerText = '';
}
c = "all";
if (e && e.target.dataset) {
c = e.target.dataset.value ? e.target.dataset.value : "all";
}
const numBrands = [];
for (i = 0; i < x.length; i++) {
x[i].classList.remove('show');
void x[i].offsetWidth;
if (x[i].classList.contains(c)) {
x[i].classList.add('show');
numBrands.push(i);
}
}
if (e && e.target) {
e.srcElement.children[0].innerText = ` (${numBrands.length})`;
}
}
// Add active class to the current control button (highlight it)
var btnContainer = document.getElementById("agg-filter-buttons");
var btns = btnContainer.getElementsByClassName("filter-btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function($this) {
var current = document.querySelectorAll(".active-btn");
current[0].className = current[0].className.replace(" active-btn", "");
this.className += " active-btn";
});
}
var filter = document.getElementById('agg-filter-buttons');
filter.addEventListener('click', function() {
document.getElementsByClassName('section--btable')[0].classList.add('flash');
});
<div id="agg-filter-buttons">
<button class="btn filter-btn" onclick="filterSelection(event)"><span data-
value="freespins">Free Spins <div class="num-brands"></div> </span></button>
<button class="btn filter-btn" onclick="filterSelection(event)"> <span data-value="bigbonus">Big Bonus <div class="num-brands"></div> </span></button> </div>
enter code here
</div>
>
<div class="brand-row the-table-row all row-1 filterDiv bigbonus newPlay show">
Row 1
</div>
<div class="brand-row the-table-row all row-2 filterDiv freespins newPlay show">
Row 2
</div>
So I have a table with rows. These are filtered with the filter buttons. When you click a filter button it shows only the rows with the same name in its class. This works and populates the button with how many rows are affected.
However this breaks occasionally and I have no idea why.
the Variable rowsAffected works until it becomes null for some unknown reason.
My guess is that the dom eventually doesnt load fast enough for the querySelector to be able to read it. But im not sure.. Any advice very welcome!
I have also added a fiddle
https://jsfiddle.net/8z56sxby/
Since you only care about the first .active-btn (because there is at most one), you can just use querySelector.
Make sure there is a current before you do anything with its classes.
Use element.classList.add and element.classList.remove to add or remove classes.
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.querySelector(".active-btn");
if (current) current.classList.remove("active-btn");
this.classList.add("active-btn");
});
}
Thankyou
The answer to this question was that clicks on my button were sometimes clicking child elements which were not setup to handle the click.
A silly mistake - that someone may find useful in the future.

Replace innerHTML of divs with same class based on content

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/

Javascript OOP get Children with getElementsByClassName method

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++) {

Get index of class

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

JavaScript - Detect index of Element being clicked in NodeLIst

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

Categories