HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers10/shop.komma.nl/resources/js/components/quantityController.js
/**
 * @see Numeric attribute for KMS. This code is a stripped down version of it.
 */
class QuantityController {
    constructor(attributeWrapper)
    {
        if(!attributeWrapper) {
            console.error('Please give the quantity controller an attribute wrapper "{HTMLElement}". You did not.')
        }

        this.attributeWrapper = attributeWrapper;
        this.wholeInput = this.attributeWrapper.querySelector('.js-whole');
        this.wholeUpButton = this.attributeWrapper.querySelector('.js-whole-up');
        this.wholeDownButton = this.attributeWrapper.querySelector('.js-whole-down');


        this.wholeMin = (this.wholeInput.dataset.min) ? parseInt(this.wholeInput.dataset.min, 10) : 0;
        this.wholeMax = (this.wholeInput.dataset.max) ? parseInt(this.wholeInput.dataset.max, 10) : null;
        this.wholeStep = (this.wholeInput.dataset.step) ? parseInt(this.wholeInput.dataset.step, 10) : 1;

        this.wholeInputChanged = this.wholeInputChanged.bind(this);
        this.wholeUpButtonClicked = this.wholeUpButtonClicked.bind(this);
        this.wholeDownButtonClicked = this.wholeDownButtonClicked.bind(this);
        this.wholeInputKeyDown = this.wholeInputKeyDown.bind(this);
        this.controlListeners(true);

        this.eventMap = {};
    }

    controlListeners(enabled) {
        if(enabled) {
            this.wholeInput.addEventListener('change', this.wholeInputChanged);
            this.wholeInput.addEventListener('keydown', this.wholeInputKeyDown);
            this.wholeUpButton.addEventListener('click', this.wholeUpButtonClicked);
            this.wholeDownButton.addEventListener('click', this.wholeDownButtonClicked);
        } else {
            this.wholeInput.removeEventListener('change', this.wholeInputChanged);
            this.wholeInput.addEventListener('keydown', this.wholeInputKeyDown);
            this.wholeUpButton.removeEventListener('click', this.wholeUpButtonClicked);
            this.wholeDownButton.removeEventListener('click', this.wholeDownButtonClicked);
        }
    }

    /**
     * @param {KeyboardEvent} Event
     */
    wholeInputKeyDown(Event)
    {
        this.onlyAllowEventWhenNumericKey(Event);
        if(Event.key === 'ArrowDown') this.wholeDownButtonClicked(Event);
        else if(Event.key === 'ArrowUp') this.wholeUpButtonClicked(Event);
    }

    /**
     * @param {Event} Event
     */
    wholeInputChanged(Event) {
        this.onlyAllowEventWhenNumericKey(Event);
        this.mustBeBetween(this.wholeInput, this.wholeMin, this.wholeMax);

        let self = this;
        if(this.eventMap.hasOwnProperty('update')) {
            this.eventMap.update.forEach(function (callback) {
                callback.call(self.wholeInput, self.wholeInput.value);
            })
        }
    }

    /**
     * @param {MouseEvent} event
     */
    wholeUpButtonClicked(event) {
        let current = parseInt(this.wholeInput.value ? this.wholeInput.value : 0);
        if(this.wholeMax && current + this.wholeStep > this.wholeMax) return;
        this.wholeInput.value = current + this.wholeStep;
        this.wholeInputChanged(event);
    }

    /**
     * @param {MouseEvent} event
     */
    wholeDownButtonClicked(event) {
        let current = parseInt(this.wholeInput.value ? this.wholeInput.value : 0);
        if(current - this.wholeStep < this.wholeMin) return;
        this.wholeInput.value = current - this.wholeStep;
        this.wholeInputChanged(event);
    }

    /**
     *
     * @param {Event} event
     * @param {int} maxLength
     */
    onlyAllowMaxLength(event, maxLength)
    {
        if(this.eventCausedByAllowedModifier(event)) return;
        if(event.target.value.length >= maxLength) {
            if(event.cancelable) event.preventDefault();
        }
    }

    /**
     * @param {Event} event
     */
    onlyAllowEventWhenNumericKey(event)
    {
        if(!event.key) return;
        if(!this.isNumber(event.key) && !this.eventCausedByAllowedModifier(event)) {
            if(event.cancelable) event.preventDefault();
        }
    }

    /**
     * @param {Event} event
     */
    eventCausedByAllowedModifier(event)
    {
        if(!event.key) return;
        return event.key.toLowerCase() === 'backspace' || event.key.toLowerCase() === 'delete' || event.key.toLowerCase() === 'arrowleft' || event.key.toLowerCase() === 'arrowright';
    }

    /**
     * @param {HTMLInputElement} inputElement
     * @param {int} min
     * @param {int} max
     */
    mustBeBetween(inputElement, min, max) {
        let number = parseInt(inputElement.value, 10);
        if(number) {
            if((min || min === 0) && number < min) inputElement.value = min;
            if(max && number > max) inputElement.value = max;
        } else if(isNaN(number)) {
            inputElement.value = (0).toString();
        }
    }

    /**
     * @param number
     * @return {boolean}
     */
    isNumber(number) {
        return !isNaN(parseFloat(number)) && isFinite(number);
    }

    /**
     * Registers a callback to an "event".
     *
     * @param {string} event
     * @param {function} callback
     * @param {int|undefined} debounceWaitTime
     */
    on(event, callback, debounceWaitTime) {
        if(!this.eventMap.hasOwnProperty(event)) this.eventMap[event] = [];
        if(debounceWaitTime) callback = this.debounce(callback, parseInt(debounceWaitTime));
        this.eventMap[event].push(callback);
    }

    /**
     * Makes the function you pass run only after it wasn't called again
     * within the wait time you specify in milliseconds.
     *
     * @param func
     * @param wait
     * @param immediate
     * @return {function(...[*]=)} The debounced function
     */
    debounce(func, wait, immediate) {
        let timeout;
        return function() {
            let context = this, args = arguments;
            let later = function() {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            let callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    };
}

export { QuantityController }