简体   繁体   中英

can anyone tell me why my javascript clicks isnt working?

i am making a shopping cart, looking to change the quantities but cant work out why its not working. i have created two funtions, one to add quantities and one to take away. i want to apply this to multiple objects in my shopping cart. it works if i change the p tag to an id rather than a class but i want it to apply to multiple items

<div class="controlpic">
  <img class="img" src="jsbook1.png">
  <button onClick="onClick2()">-</button>
  <p class="clicks">0</p>
  <button onClick="onClick()">+</button>
  <button class="addBasket">Add to Basket</button>
  <div>some text about this product</div>
</div>
/* onclick function will add clicks for basket*/
var clicks1 = 0;

function onClick() {
    clicks1 += 1;
    document.getElementsByClassName("clicks").innerHTML = clicks1;
  }
  /* onclick function will take away clicks for basket*/
var clicks1 = 0;

function onClick2() {
  if (clicks1 > 0) {
    clicks1 -= 1;
    document.getElementsByClassName("clicks").innerHTML = clicks1;
  }
}

The problem

The problem in your code is that getElementsByClassName returns an HTMLCollection , which is similar to (but not the same as) an array.

Instead of changing the innerHTML of your HTMLCollection , you should change the innerHTML the element(s) in your HTMLCollection .


The solution

If you only have one element with the class "clicks", you can just replace ...

document.getElementsByClassName("clicks").innerHTML = clicks1;

... with ...

document.getElementsByClassName("clicks")[0].innerHTML = clicks1;

... and everything will work just fine.

If you need to support multiple elements, you'll have to loop over those elements :

[].forEach.call(document.getElementsByClassName('clicks'), function(clicks) {
    clicks.textContent = clicks1;
});

A demo

 var clicks1 = 0; function onClick() { clicks1 += 1; [].forEach.call(document.getElementsByClassName('clicks'), function(clicks) { clicks.textContent = clicks1; }); } function onClick2() { if (clicks1 > 0) { clicks1 -= 1; [].forEach.call(document.getElementsByClassName('clicks'), function(clicks) { clicks.textContent = clicks1; }); } } 
 <div class="controlpic"> <img class="img" src="jsbook1.png"> <button onClick="onClick2()">-</button> <p class="clicks">0</p> <button onClick="onClick()">+</button> <button class="addBasket">Add to Basket</button> <div>some text about this product</div> </div> 

Your problem

it works if i change the p tag to an id rather than a class but i want it to apply to multiple items

Your approach

It doesn't work, because you are trying to set property innerHTML on an HTMLCollection that document.getElementsByClassName("clicks") returns, instead of setting it on every of those elements.

Fix

Replace your document.getElementsByClassName("clicks").innerHTML = clicks1 with:

[].forEach.call(document.getElementsByClassName('clicks'), function(element) {
  element.textContent = clicks1;
});

Demo

Below demo contains many flaws, it only presents how to implement the above fix. Also, each quantity modifier ( + or - ) will update all counters. For solution to this, see section Rewrite .

 /* onclick function will add clicks for basket*/ var clicks1 = 0; function onClick() { clicks1 += 1; [].forEach.call(document.getElementsByClassName('clicks'), function(element) { element.textContent = clicks1; }); } /* onclick function will take away clicks for basket*/ var clicks1 = 0; function onClick2() { if (clicks1 > 0) { clicks1 -= 1; [].forEach.call(document.getElementsByClassName('clicks'), function(element) { element.textContent = clicks1; }); } } 
 <div class="controlpic"> <img class="img" src="jsbook1.png"> <button onClick="onClick2()">-</button> <p class="clicks">0</p> <button onClick="onClick()">+</button> <button class="addBasket">Add to Basket</button> <div>some text about this product</div> </div> 

Comments

Few other notes about your code:

  • Don't use inline onclick use element.addEventListener('click', someFunction)
  • Rather than innerHTML in your case, you can use textContent . It's safer and faster.
  • Defining var clicks1 = 0 second time makes no difference in your code.

Rewrite

 function setQuantityModifier(element) { 'use strict'; var quantity = element.parentNode.getElementsByClassName('clicks')[0]; element.addEventListener('click', function() { 'use strict'; if (element.value === '+') { quantity.textContent = parseInt(quantity.textContent) + 1; } else if (parseInt(quantity.textContent) > 0) { quantity.textContent = parseInt(quantity.textContent) - 1; } }); } [].forEach.call(document.querySelectorAll('.controlpic > input'), setQuantityModifier); 
 <div class="controlpic"> <img class="img" alt="ADDME" src="jsbook1.png"/> <input type="button" value="&ndash;"/> <p class="clicks">0</p> <input type="button" value="+"/> <button class="addBasket">Add to Basket</button> <div>some text about this product</div> </div> <div class="controlpic"> <img class="img" alt="ADDME" src="jsbook2.png"/> <input type="button" value="&ndash;"/> <p class="clicks">0</p> <input type="button" value="+"/> <button class="addBasket">Add to Basket</button> <div>some text about this product</div> </div> 

It doesn't work because document.getElementsByClassName returns an array (as you see getElement s , which is plural). You can either do document.getElementsByClassName('clicks')[0].innerHTML or you can use document.querySelector('.clicks').innerHTML

EDIT: for updating multiple elements with class name, you can use (based on @tymeJV's comment):

var clicks = document.getElementsByClassName('clicks');
for(var i = 0; i < clicks.length; ++i) {
    clicks[i].innerHTML = "...";
}

I personally like using document.querySelectorAll('.clicks') for any matchings (whether it is a class, id, or attribute).

This should work for you: https://jsfiddle.net/DIRTY_SMITH/7oe5kh9L/30/

Add an id to <p class="clicks" id="clicks">0</p>

And insert text with document.getElementById('clicks').innerHTML = clicks1;

Also remove the second var clicks1 = 0; because you only need to declare a variable once.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM