I'm experiencing an issue with my JavaScript clicks not working. Can someone help me troubleshoot

I'm currently working on a shopping cart and trying to figure out why changing quantities is not working as expected. I've created two functions, one for adding quantities and the other for subtraction. My goal is to apply these functions to multiple items in the shopping cart. It seems to work when I change the p tag to an id instead of a class, but I want it to work for 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;
  }
}

Answer №1

The issue

The main problem lies within your code where you are utilizing the getElementsByClassName method that returns an HTMLCollection. This is akin to an array, but with some differences.

To rectify this issue, rather than altering the innerHTML of your entire HTMLCollection, it is advisable to modify the innerHTML of the individual element(s) within the HTMLCollection.


The resolution

If there is only a single element with the "clicks" class, you can simply replace ...

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

... with ...

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

... and this adjustment should resolve the issue successfully.

However, if multiple elements require support, you will need to loop through these elements:

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

An example

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>

Answer №2

The issue you're facing

When I change the p tag to an id instead of a class, it works. However, my goal is to have it apply to multiple items.

Your current approach

The reason it's not working is that you are attempting to set the property innerHTML on an HTMLCollection returned by

document.getElementsByClassName("clicks")
, instead of setting it on each individual element within the collection.

Solution

To fix this issue, replace your

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

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

Live Demo

The demo below showcases the main solution, but there are some limitations. Each quantity modifier (+ or -) will update all counters. For a solution to this, refer to the section labeled Rewrite.

Additional Comments

Here are a few additional pointers regarding your code:

  • Avoid using inline onclick attributes; opt for
    element.addEventListener('click', someFunction)
    instead.
  • Instead of using innerHTML, consider utilizing textContent as it is safer and more efficient in your case.
  • Redeclaring var clicks1 = 0 has no impact on your code's functionality.

Improvements

Answer №3

I found a solution that should do the trick for you: https://jsfiddle.net/CREATIVE_JOHN/7oe5kh9L/30/

Make sure to give an id to

<p class="clicks" id="clicks">0</p>

Then, add this line of code to insert text:

document.getElementById('clicks').innerHTML = clicks1;

Lastly, don't forget to delete the extra var clicks1 = 0; as it is unnecessary to declare a variable more than once.

Answer №4

The reason it's not functioning is due to the fact that document.getElementsByClassName produces an array (as indicated by the plural form of getElements). To rectify this, you can either use

document.getElementsByClassName('clicks')[0].innerHTML
or opt for
document.querySelector('.clicks').innerHTML

UPDATE: To update multiple elements with the same class name, you can utilize the following approach (suggested by @tymeJV's comment):

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

Personally, I prefer utilizing

document.querySelectorAll('.clicks')
for various matches (whether it be a class, id, or attribute).

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When the mouse is clicked, the character fails to reach the intended destination or moves in the wrong direction on the HTML canvas

UPDATE: RESOLVED I am currently working on a game where the character moves by right-clicking. The character is meant to walk slowly, not teleport, towards the destination set by right-clicking on the canvas. However, I have encountered an issue where the ...

Tips for properly indenting checkbox and radio button elements in HTML code

Check out my live code demo here This is a simple html code where I am attempting to indent radio buttons and checkboxes, but it's proving to be difficult. <tr> <td> <table> <tr& ...

Focus on React MUI Formik Input is lost when typing

I'm currently working on a form using React, MUI, and Formik, but I'm facing an issue where the input field loses focus after typing a character. I have wrapped each input field in a component for reusability and cleaner code, but it seems that t ...

How to make your divs stand out using Bootstrap

Can anyone assist me in aligning my divs based on the example below? https://i.sstatic.net/OAyCj.jpg Here is what I have achieved so far: https://i.sstatic.net/KkOWg.jpg I am struggling to apply spacing between the two divs, and they are not of equal h ...

Title Divider Right

I am looking to add a divider to the right of a section title on my webpage. Here is what I have tried: I attempted this code, but here is the result: Here is the code snippet: <h4 class="section-title">Lastest From Blog</h4> .section-title ...

Angular - the ngFor directive causing function to be executed repeatedly

I need help with a template: <mat-card *ngFor="let cargo of cargos" class="cont-mat"> ... <mat-checkbox *ngFor="let truck of (retrievingTrucksByUserIdAndRules(cargo.id) | async)" formControlName="truckId" ...

Retrieve the value of a JSON array containing only a single object using jQuery

In my project, I have a jQuery file and a PHP file. If the PHP file successfully completes the process, it returns the value 2 using `echo json_encode(2)`. I am able to catch this value in the jQuery file and display a string on an HTML div without any iss ...

The characteristics and functions of the THREE.TransformControls

I've been attempting to utilize transformControl in my program, but due to the lack of documentation on controls at threejs.org, I find it challenging to tap into its full potential. I'm seeking information on all the properties and methods provi ...

Using npm webpack-mix to execute a JavaScript function stored in a separate file

Currently, I am facing a challenge with accessing a function that is defined in the table.js file from within my index.html. Here is a snippet of the code: table.js let table; function set_table(table) { this.table = table; consol ...

Sending JavaScript objects from React.js to Node.js

I send the object to the backend (Node js) when making an API call, but I am logging the objects for verification. Initially, I used POSTMAN to check and it worked perfectly. However, when attempting to pass an object in the frontend (Reactjs), it appear ...

Give a jQuery Mobile flipswitch a new look

Currently, I am using jQuery Mobile and recently attempted to refresh a flipswitch. However, upon executing the code $("#flipEnabled").slider("refresh");, I encountered an error in the console: Uncaught Error: cannot call methods on slider prior to initial ...

Ways to determine the success of $wpdb->query and retrieve the outcome

Currently, I am in the process of developing a WordPress website, I have implemented a form that allows users to make modifications and update the database: Below is the HTML/PHP code snippet: echo '<form class="form-verifdoc" target=&q ...

Simulate a keyboard key being pressed and held for 5 seconds upon loading the page

Is it possible to create a script that automatically triggers an event to press and hold down the Space key for 5 seconds upon page load, without any user interaction? After the 5 seconds, the key should be released. It is important to emphasize that abso ...

Encountered an Angular 1.6 Error: The requested URL at http://127.0.0.1:56035/[url] could not be found (404

I've hit a roadblock in my project and can't seem to figure out the issue. The file I'm working on is supposed to display an iframe video player with a YouTube embed. I tried using interpolation to construct the correct URL: <div class= ...

CSS problem: alignment issue between text and checkbox

I'm experiencing a CSS style issue where the text box and text are not aligned properly. Can someone assist me in fixing this problem? Below is the code I am using: Thank you for your help. <div> <input type="checkbox" ...

Using AJAX to inject JSON data from PHP into Edge Animate

For a school assignment, I am currently working on a project using edge animate. My objective is to import data from a database hosted on my school's webspace and incorporate it into the edge animate project. Despite researching online for a solution ...

How to convert an array of keys and an array of values into an array of objects using JavaScript

My question is similar to the one found here: Merging keys array and values array into an object using JavaScript However, I am unable to find a solution for my specific scenario. If I have these two arrays: const keys = ['x', 'y', &ap ...

I attempted to use the Stripe API, but it seems to be non

I seem to be encountering an issue with the stripe.customers.create. My goal is to create a new Stripe customer using the email address of the current user, and then update my user with the generated customer.id. Despite the fact that stripe.customers.cre ...

Challenges with differentiating between addition and concatenation in Vue computed properties

Recently diving into Vue and came across an intriguing issue, I am curious to know the reason behind it and how to prevent it. <template> <div> <input type="number" v-model="a" style="color: white" /> <input type="number" v- ...

Tips on how to retrieve the value of a number-type input within a custom attribute directive

I have successfully implemented this code in IE 11, but now we are looking to transition away from IE11 and address some of the issues that have arisen. <input type="number" evaluate-input="model.personalNumber" ng-model="model ...