javascriptcountdown

Show the stock counter in more than one place on the same page


This script works great as a stock countdown, but I couldn't show it in more than 1 place on the same page.

For example, on the same page there are 4 or 5 products/plans and each product shows a different stock quantity and changing the quantity at different times from each other. Only shows on 1 product.

<span class="qty" id="qty"></span>

<script>
    const setQty = (qty) => {
        qtySpan.innerHTML = qty;

        if (qty == 0) return;

        let parts = Math.floor((Math.random() * 3) + 1);
        if (parts > qty) parts = qty;

        const msec =  Math.floor(((Math.random() * 15) + 15) * 1000);
        qty -= parts;

        // Save the updated quantity in localStorage
        localStorage.setItem('saved_countdown', qty);

        setTimeout(() => setQty(qty), msec);
    }

    // Get the saved countdown value from localStorage, or use default value of 57 if not found
    const defaultQty = localStorage.getItem('saved_countdown') ?? 57;
    
    const qtySpan = document.getElementById('qty');

    // Set the initial value of the quantity
    setQty(defaultQty);
</script>

I duplicated the script 4x changing the ID "qty" by qty1, qty2, qty3 and qty4, but it didn't work, it keeps showing only in 1 product... :/

Would anyone here be able to help me out? Thank you!


Solution

  • I've modified your script into a Custom Element. This means that you can now create an element called <stock-counter>.

    This element has 2 attributes, quantity and storage-key.

    1. quantity is the amount to start counting from.
    2. storage-key is the name of the Local Storage key that is used to store the last quantity of this specific counter. If a storage key is set and a stored value has been found, then this value will supersede the quanitity value, unless the stored value is 0.

    So the element would look like this:

    <stock-counter quantity="40" storage-key="countdown-one">40</stock-counter>
    

    You can place as many of these elements on your page and modify the quantity and storage-key for each one.

    customElements.define('stock-counter', class extends HTMLElement {
      get quantity() {
        // Check if value has been stored.
        if (this.storageKey !== null) {
          const value = Number(localStorage.getItem(this.storageKey));
    
          // Use that value if it is a valid number and not 0.
          if (!Number.isNaN(value) && value !== 0) {
            return value;
          }
        }
    
        // Otherwise get the value from the quantity attribute.
        const value = Number(this.getAttribute('quantity'));
    
        if (Number.isNaN(value)) {
          return 0;
        }
    
        return value;
      }
    
      set quantity(value) {
        if (!isNaN(value)) {
        
          // Store the new value if it's possible.
          if (this.storageKey !== null) {
            localStorage.setItem(this.storageKey, value);
          }
    
          // Set the new attribute value.
          this.setAttribute('quantity', value);
        }
      }
    
      get storageKey() {
        return this.getAttribute('storage-key');
      }
    
      connectedCallback() {
        this.count();
      }
    
      count = () => {
        const qty = this.quantity;
        this.textContent = qty;
    
        if (qty === 0) {
          return;
        }
    
        let parts = Math.floor((Math.random() * 3) + 1);
    
        if (parts > qty) {
          parts = qty;
        }
    
        this.quantity -= parts;
    
        const msec = Math.floor(((Math.random() * 15) + 15) * 1000);
        setTimeout(this.count, msec);
      };
    });
    <stock-counter quantity="40" storage-key="countdown-one">40</stock-counter>
    <stock-counter quantity="50">50</stock-counter>
    <stock-counter quantity="80" storage-key="countdown-three">80</stock-counter>