PageSourceSearch

http://prochoicesafetygear.com/assets/controllers/add_to_cart_grid_controller-JlXWwWu.js

js prochoicesafetygear.com collected 2026-10-09 17:52:12 UTC 3,325 bytes, 92 lines download raw bytes

1/* stimulusFetch: 'lazy' */
2import { Controller } from '@hotwired/stimulus';
3
4// noinspection JSUnusedGlobalSymbols loaded via stimulus
5export default class extends Controller {
6    subtotal = 0;
7    accumulatedQty = 0;
8    unitPrice = 0;
9    /** @type {NodeListOf<HTMLElement>|null} */
10    priceRows = null;
11    /** @type {NodeListOf<HTMLElementTagNameMap[string]>|null} */
12    inputs= null;
13    /** @type {Intl.NumberFormat|null} */
14    formatter = null;
15
16    active(inputs) {
17        inputs.forEach(input => {
18            input.labels[0]?.classList[input.checked ? 'add' : 'remove']('active');
19        });
20    }
21
22    setCurrent(elm) {
23        Array.prototype.find.call(this.priceRows, row => row.classList.contains('current'))?.classList.remove('current');
24        elm.classList.add('current');
25    }
26
27    /**
28     * @param {number} qty
29     * @returns {number}
30     */
31    getPriceRowForQty(qty) {
32        for (let i = 0, n = this.priceRows.length; i < n; i++) {
33            if (i > 0 && parseFloat(this.priceRows[i].dataset.qty || '0') > qty) {
34                return i - 1;
35            }
36        }
37        return this.priceRows.length - 1;
38    }
39
40    /**
41     * @returns {number}
42     */
43    getAccumulatedQty() {
44        return Array.prototype.reduce.call(this.inputs,
45            (carry, input) => {
46                const qty = parseInt(input.value || '0');
47                if (qty > 0) {
48                    carry += qty;
49                }
50                return carry;
51            },
52            0
53        );
54    }
55
56    updatePricing() {
57        const qty = this.getAccumulatedQty();
58        const priceRowIndex = this.getPriceRowForQty(qty);
59        const priceRow = this.priceRows[priceRowIndex];
60        this.accumulatedQty = qty;
61        this.setCurrent(priceRow);
62        this.unitPrice = parseFloat(priceRow.dataset.price);
63        this.subtotal = this.accumulatedQty * this.unitPrice;
64        /** @type {HTMLElement} */
65        const element = this.element;
66        element.querySelector('[data-subtotal]').textContent = this.formatter.format(this.subtotal);
67        element.querySelector('[data-qtytotal]').textContent = this.accumulatedQty.toFixed(0);
68        if (priceRowIndex < this.priceRows.length - 1) {
69            const nextRow = this.priceRows[priceRowIndex + 1];
70            element.querySelector('[data-next-qty]').textContent = (parseFloat(nextRow.dataset.qty) - qty).toFixed(0);
71            element.querySelector('[data-next-price]').textContent = this.formatter.format(parseFloat(priceRow.dataset.price) - parseFloat(nextRow.dataset.price));
72            element.querySelector('.save-tier').classList.remove('hidden');
73        }
74    }
75
76    connect() {
77        /** @type {HTMLElement} */
78        const element = this.element;
79        this.formatter = new Intl.NumberFormat(document.documentElement.lang, { style: 'currency', currency: 'AUD' });
80        this.inputs = element.querySelectorAll('input');
81        this.priceRows = element.querySelectorAll('[data-price]');
82        this.unitPrice = parseFloat(this.priceRows[0].dataset.price);
83        this.subtotal = 0;
84        this.accumulatedQty = 0;
85        this.inputs.forEach(input => {
86            input.addEventListener('change', () => {
87                this.updatePricing();
88            });
89        });
90        this.updatePricing();
91    }
92}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.