I've the following code snippet. The issue is onclick event doesn't fire for the second label, which has the same class as the first one. Why is that?
I searched online and found multiple solutions but all of them are in jQuery. But I want it in pure JavaScript. Does anyone know what am I doing wrong here?
var label = document.getElementsByClassName('text');
label[0].onclick = function() {
console.log(true);
};
<label class="text">Hello</label>
<label class="text">World!</label>
PS: I know this question has been asked here multiple times (but the solutions are for jQuery). So please don't mark this question as duplicate :/
You could use event delegation :
document.body.onclick = function (ev) {
if (ev.target.getAttribute("class") == "text") {
console.log(true);
}
};
<label class="text">Hello</label>
<label class="text">World!</label>
Thanks to event delegation new labels are also clickable :
var nLabels = 2;
document.body.onclick = function (ev) {
var newLabel;
if (ev.target.getAttribute("class") == "text") {
console.log(ev.target.textContent);
} else if (ev.target.id == "btn-add-label") {
newLabel = document.createElement("label");
newLabel.setAttribute("class", "text");
newLabel.textContent = " new label #" + (nLabels++);
document.body.appendChild(newLabel);
}
};
<button type="button" id="btn-add-label">Add label</button>
<label class="text">Hello</label>
<label class="text">World!</label>
label is an array of all the elements with class text, so label[0] will only apply to the first element in the document. Simplest way to do it would probably be with a loop such as
for (var i = 0; i<label.length; i++){
label[i].onclick = function() {
console.log(true);
};
var label = document.getElementsByClassName('text');
for (var i = 0; i<label.length; i++) {
label[i].oncllick = function () { console.log(true); };
}
try this
var label = document.getElementsByClassName('text');
for (var i = 0; i < label.length; i++) {
label[i].onclick = function() {
console.log(true);
};
}
Related
This question already has answers here:
How can I change an element's class with JavaScript?
(33 answers)
Closed 5 years ago.
I am working on a simple example, if a user clicks on element then all the elements above it should have a class and all elements below it should not have any class applied to them.
Here is my code:
<script>
function test(object) {
var pid = object.id;
var id = parseInt(pid.split("")[1]);
console.log(id);
for (var i = 1; i <= id; i++) {
var element = document.getElementById("p"+i);
console.log(element);
element.className = "active";
}
console.log(id+1);
for(var i = id+1; i <= 4; i++) {
var element = document.getElementById("p"+i);
element.className.replace(new RegExp('(?:^|\\s)'+ 'active' + '(?:\\s|$)'), ' ');
console.log(element);
}
}
</script>
<div id="divid">
<p id="p1" onclick="test(this)">one</p>
<p id="p2" onclick="test(this)">two</p>
<p id="p3" onclick="test(this)">three</p>
<p id="p4" onclick="test(this)">four</p>
</div>
So here if I click on three then the elements for one, two, three should have the class active and element four should not have any class. This is working fine.
Now if I click on one, I am expecting that two, three, four should have any css class but it is not working like that.
Can you please help me where is the issue. I want to use plain Javascript.
It might be wise to consider an alternative to using the onclick attribute due to separation of concerns. The following allows you to alter the HTML without having to consider JavaScript while you work.
https://jsfiddle.net/gseh0wxc/2/
var getList = (selector) => [].slice.call(document.querySelectorAll(selector));
var paragraphs = getList("#divid p[id ^= 'p']");
paragraphs.forEach((paragraph, index) => {
paragraph.addEventListener('click', (e) => {
for (let i = 0; i < index; i++) {
paragraphs[i].classList.remove('active');
}
for (let i = index; i < paragraphs.length; i++) {
paragraphs[i].classList.add('active');
}
});
})
Please try this code
function test(object) {
var pid = object.id;
var id = parseInt(pid.split("")[1]);
console.log(id);
for (var i = 1; i <= id; i++) {
var element = document.getElementById("p"+i);
element.classList.add("active");
}
console.log(id+1);
for(var i = id+1; i <= 4; i++) {
var element = document.getElementById("p"+i);
element.classList.remove("active");
}
}
Hope this helps.
try this simple approach instead, don't need to extract id number and all, and with a single simple loop.
function test(option) {
//this will select all p tags id starts with "p" inside div having id "divid" and return a array
var targetPTags = document.querySelectorAll("div#divid p[id^=p]")
var idx, flag=false;
//we are iterating over that array and taking each dom element in el
for(idx=0;idx<targetPTags.length;idx++) {
var el = targetPTags[idx];
if(flag) {
//do operation you want for after elements in el
} else if(option===el) {
flag=true; // we are making flag true when its the element that clicked and doing no operation
//do the operation you want for the element, may be the same as below operation in else
} else {
//do operation you want for before element in el
}
}
}
Kind of similar to "Chatterjee"'s solution, but here you go:
function test(object)
{
var parentElem = null;
var childElems = null;
var currElemSet = false;
var i=-1;
try
{
parentElem = object.parentElement;
if(parentElem!=null)
{
childElems=parentElem.getElementsByTagName(object.nodeName); // could refine to accommodate sibling nodes only
if(childElems!=null)
{
for(i=0;i<childElems.length; i++)
{
if(currElemSet) childElems[i].className = "";
else childElems[i].className = "active";
if(childElems[i]==object) currElemSet = true;
}
}
}
}
catch(e)
{
alert("Error: " + e.Message);
}
finally
{
}
}
I'm creating a tool which generates a bunch of divs based on data I input into an array, however they all have the same class. The idea is that when one link is clicked it shows one of the ".catbox" divs and hides the rest.
All of these divs have the same class so I need to iterate through them, but I'm not quite sure how this is done with jQuery. Currently clicking on the last ".list" class triggers the on click event instead of all of them, and currently it shows all of the divs with the class ".catbox" instead of the corresponding one.
Here is the code:
var HTMLcatName = '<h1>%data%</h1>';
var HTMLcatImage = '<img id="cat" src="%data%">';
var HTMLcatCounter = '<p class="counter">Number of clicks: %data%</p>';
var HTMLcatList = '<p>%data%</p>'
var noCats = 'No cats selected m8';
var getCounterClass = document.getElementsByClassName("counter");
$(document).ready(function() {
cats.display();
$('.catbox').hide();
for (u = 0; u < cats.name.length; u++) {
formattedCatList = HTMLcatList.replace("%data%", cats.name[u]);
var listDiv = document.createElement('div');
listDiv.innerHTML = formattedCatList;
listDiv.className = "list";
$(".list").click(function() {
$(".catbox").toggle("slow");
});
$("body").prepend(listDiv);
}
});
var update = function() {
for (j = 0; j < getCounterClass.length; j++) {
getCounterClass[j].innerHTML = 'Number of clicks: ' + cats.clicks[j];
}
}
var cats = {
"name": ["Monte", "Jib"],
"image": ["images/monte.jpg", "images/jib.jpg"],
"clicks": [0, 0],
display: function () {
for (i = 0; i < cats.image.length; i++) {
formattedCatNames = HTMLcatName.replace("%data%", cats.name[i]);
formattedCatImages = HTMLcatImage.replace("%data%", cats.image[i]);
formattedCatCounter = HTMLcatCounter.replace("%data%", cats.clicks[i]);
var catDiv = document.createElement('div');
catDiv.className = "catbox";
catDiv.innerHTML = formattedCatNames + formattedCatImages + formattedCatCounter;
catDiv.querySelector('img').addEventListener('click', (function(catCountUp) {
return function() {
cats.clicks[catCountUp]++;
update();
};
})(i));
document.body.appendChild(catDiv);
}
},
}
The function I need help with is found within $(document).ready(function() {
Any help would be greatly appreciated.
The following can do it:
$(".list").on("click", function(){
$(this).find(".catbox").toggle("slow");
});
With $('.list') you get a group of elements of class list, so if you use $('.list').click(); you will bind the click event to just one element. You should use:
$(".list").each(function(){
$(this).click(function() {
$(".catbox").toggle("slow");
});
});
The on click event that I add to an input in javascript isn't working in the proper manner.
My code so far looks like so:
function order(option) {
if(option.checked) {
document.getElementId("col_order").value = document.getElementById("col_order").value + " " + option.value;
}
}
...//somewhere further down
for(var i = 0; i < options.length; i++) {
var check = document.createElement("input");
var label = document.createElement("label");
var description = document.createTextNode(options[i]);
check.type = "checkbox";
check.name = "order_list[]";
check.value = options[i];
check.onclick = "order(check)"; //Problem here
label.appendChild(check);
label.appendChild(description);
element.appendChild(label);
}
I have also tried:
check.onclick = (function() { var option = check; return function() {order(option);}})();
The problem that I am having is the check.onlick line of code. When I add this with normal HTML:
<input type = "checkbox" name = "order_list[]" onclick = "order(this)" value = "randVal">randVal</input>
I don't have any problem whatsoever; the method executes with the intended results. Any thoughts?
Let me clarify: I make it to the order function just fine, but I never get into the if statement, even though the checkbox was just clicked
Use addEventListener instead, and even if it looks like it should work, you're overwriting the same variables on each iteration as there is no closure in for loops, so I would probably add a closure to avoid issues.
For a checkbox you would listen for the change event, not click
for(var j = 0; j < options.length; j++) {
(function(i) {
var check = document.createElement("input");
var label = document.createElement("label");
var description = document.createTextNode(options[i]);
check.type = "checkbox";
check.name = "order_list[]";
check.value = options[i];
check.addEventListener('change', function() {
if (this.checked) {
var col_order = document.getElementById("col_order");
col_order.value = col_order.value + " " + this.value;
}
}, false);
label.appendChild(check);
label.appendChild(description);
element.appendChild(label);
})(j);
}
FIDDLE
check.onclick = "order(check)"; assigns a String as an on-click handler. That doesn't work; the browser expects a function there:
check.onclick = function() {
order(check);
}
I'm looking for a JQuery code which creates input fields dynamically.. I found this code and it's kind of the thing I want
$(function() {
var input = $('<input type="text" />');
var newFields = $('');
$('#qty').bind('blur keyup change', function() {
var n = this.value || 0;
if (n + 1) {
if (n > newFields.length) {
addFields(n);
} else {
removeFields(n);
}
}
});
function addFields(n) {
for (i = newFields.length; i < n; i++) {
var newInput = input.clone();
newFields = newFields.add(newInput);
newInput.appendTo('#newFields');
}
}
function removeFields(n) {
var removeField = newFields.slice(n).remove();
newFields = newFields.not(removeField);
}
});
DEMO
But I would like to have the fields numerated, like this:
#1 FIELD
#2 FIELD
#3 FIELD
I've already tried my best and I've really searched for a long time but I haven't found anything that helps me. I hope someone can help me here.
Try this:
function addFields(n) {
for (i = newFields.length; i < n; i++) {
var newInput = $("<div>#"+(i+1)+"</div>").append(input.clone());
newFields = newFields.add(newInput);
newInput.appendTo('#newFields');
}
}
DEMO
I need to create 2 arrays in JS from an input value. The first should contain all my inputs values and the second one should contain all my inputs values but for the last one.
I tried this but it doesn't work.
<body>
<input type="text"></input>
<button>click</button>
<script>
var input = document.querySelector("input");
var button = document.querySelector("button");
button.addEventListener("click" , clickHandler , false);
var valori = [];
var comp = [];
function clickHandler()
{
n = input.value;
for (var i =0; i < 10; i++)
{
valori.push(parseInt(n));
comp = valori.pop();
console.log(valori);
console.log(comp);
break;
}
}
</script>
</body>
The ideea is that I want to check if an input value has been entered before. I thought of doing that by creating 2 arrays like I mentioned before and then compare "n" to the "comp" array
if you are just to check element exist or not.. why dont u why indexOf(n)??
no need to create two array and for loop etc etc.. just indexOf will work for you..
check the below code..
<html>
<body>
<input type="text"></input>
<button>click</button>
<script>
var input = document.querySelector("input");
var button = document.querySelector("button");
button.addEventListener("click" , clickHandler , false);
var valori = [];
function clickHandler()
{
if(isNaN(input.value))
{
alert('value is not a Number');
}
else
{
var nbr = parseInt(input.value);
if(valori.indexOf(nbr) < 0)
{
valori.push(nbr);
input.value="";
}
else
{
alert('element already exists.');
}
}
}
</script>
</body>
</html>
U are setting value on comp which is array u need to set value at index .
function clickHandler()
{
var is = true;
var n = parseInt(document.getElementById("inp").value);
if(!isNaN(n))
{
for (var i =0; i < valori.length; i++)
{
if(n === valori[i])
{
console.log("duplicate");
is = false;
break;
}
}
if(is)
valori.push(n);
}
console.log(valori);
}
DEMO