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/reiskick.komma.nl/vendor/komma/kms/resources/js/attributes/numeric.js
export class Numeric {
    constructor(attributeWrapper)
    {
        if(!attributeWrapper) {
            console.log(attributeWrapper);
            console.error('Please give the Numeric attdsadsdribute an attribute wrapper "{HTMLElement}"')
        }

        this.attributeWrapper = attributeWrapper;
        this.realInput = this.attributeWrapper.querySelector('.js-real-input');
        this.wholeInput = this.attributeWrapper.querySelector('.js-whole');
        this.wholeUpButton = this.attributeWrapper.querySelector('.js-whole-up');
        this.wholeDownButton = this.attributeWrapper.querySelector('.js-whole-down');
        this.fractionInput = this.attributeWrapper.querySelector('.js-fraction'); //Can be falsy when no decimals
        this.fractionUpButton = this.attributeWrapper.querySelector('.js-fraction-up'); //Can be falsy when no decimals
        this.fractionDownButton = this.attributeWrapper.querySelector('.js-fraction-down'); //Can be falsy when no decimals

        this.wholeMin = (this.wholeInput.dataset.min) ? parseInt(this.wholeInput.dataset.min, 10) : null;
        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) : null;
        this.fractionMin = (this.fractionInput && this.fractionInput.dataset.min) ? parseInt(this.fractionInput.dataset.min, 10) : null;
        this.fractionMax = (this.fractionInput && this.fractionInput.dataset.max) ? parseInt(this.fractionInput.dataset.max, 10) : null;
        this.fractionStep = (this.fractionInput && this.fractionInput.dataset.step) ? parseInt(this.fractionInput.dataset.step, 10) : null;
        this.fractionLength = (this.attributeWrapper.dataset.fractionLength) ? parseInt(this.attributeWrapper.dataset.fractionLength, 10) : null;
        this.zeroPadFraction = (this.attributeWrapper.dataset.zeroPadFraction) ? this.attributeWrapper.dataset.zeroPadFraction : false;


        this.wholeInputChanged = this.wholeInputChanged.bind(this);
        this.wholeUpButtonClicked = this.wholeUpButtonClicked.bind(this);
        this.wholeDownButtonClicked = this.wholeDownButtonClicked.bind(this);
        this.fractionInputChanged = this.fractionInputChanged.bind(this);
        this.fractionUpButtonClicked = this.fractionUpButtonClicked.bind(this);
        this.fractionDownButtonClicked = this.fractionDownButtonClicked.bind(this);
        this.wholeInputKeyDown = this.wholeInputKeyDown.bind(this);
        this.fractionInputKeyDown = this.fractionInputKeyDown.bind(this);
        this.doZeroPadFraction = this.doZeroPadFraction.bind(this);

        this.init();
        this.controlListeners(true);
    }

    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);
            if(this.fractionInput) this.fractionInput.addEventListener('change', this.fractionInputChanged);
            if(this.fractionInput) this.fractionInput.addEventListener('keydown', this.fractionInputKeyDown);
            if(this.fractionInput) this.fractionUpButton.addEventListener('click', this.fractionUpButtonClicked);
            if(this.fractionInput) this.fractionDownButton.addEventListener('click', this.fractionDownButtonClicked)
        } 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);
            if(this.fractionInput) this.fractionInput.removeEventListener('change', this.fractionInputChanged);
            if(this.fractionInput) this.fractionInput.addEventListener('keydown', this.fractionInputKeyDown);
            if(this.fractionInput) this.fractionUpButton.removeEventListener('click', this.fractionUpButtonClicked);
            if(this.fractionInput) this.fractionDownButton.removeEventListener('click', this.fractionDownButtonClicked)
        }
    }

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

    /**
     * @param {KeyboardEvent} Event
     */
    fractionInputKeyDown(Event)
    {
        if(Event.key === 'ArrowDown') this.fractionDownButtonClicked(Event);
        else if(Event.key === 'ArrowUp') this.fractionUpButtonClicked(Event);
    }

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

    /**
     * @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
     */
    fractionInputChanged(Event) {
        console.log('fraction changed');
        this.onlyAllowEventWhenNumericKey(Event);
        this.onlyAllowMaxLength(Event, this.fractionLength);
        this.mustBeBetween(this.fractionInput, this.fractionMin, this.fractionMax);
        if(this.zeroPadFraction) this.doZeroPadFraction();
        this.processInput();
    }

    /**
     * Prepends zeros to the fraction till it matches the fraction length
     */
    doZeroPadFraction()
    {
        while(this.fractionInput.value.length < this.fractionLength)
            this.fractionInput.value = '0'+this.fractionInput.value;
    }

    /**
     * @param {MouseEvent} event
     */
    fractionUpButtonClicked(event) {
        let current = parseInt(this.fractionInput.value ? this.fractionInput.value : 0);
        let newResult = current + this.fractionStep;
        if(this.fractionMax && newResult > this.fractionMax) return;
        if(newResult.toString().length > this.fractionLength) return;
        this.fractionInput.value = newResult;
        this.fractionInputChanged(event);
    }

    /**
     * @param {MouseEvent} event
     */
    fractionDownButtonClicked(event) {
        let current = parseInt(this.fractionInput.value ? this.fractionInput.value : 0);
        let newResult = current - this.fractionStep;
        if(newResult < this.fractionMin) return;
        this.fractionInput.value = newResult;
        this.fractionInputChanged(event);
    }

    init() {
        let fraction = '';
        let whole = '';

        //Dissect the realinput value into the whole and fraction.
        if(this.realInput.value.length > this.fractionLength) fraction = this.realInput.value.slice(-this.fractionLength);
        whole = this.realInput.value.substring(0, this.realInput.value.length - this.fractionLength);

        //Set the whole and fraction inputs with the dissected values
        this.wholeInput.value = parseInt(whole, 10);
        if(this.fractionInput) this.fractionInput.value = parseInt(fraction, 10);

        // Force the inputs to be between the min and max values
        this.mustBeBetween(this.wholeInput, this.wholeMin, this.wholeMax);
        if(this.fractionInput) this.mustBeBetween(this.fractionInput, this.fractionMin, this.fractionMax);
        if(this.zeroPadFraction) this.doZeroPadFraction();
    }

    /**
     *
     * @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';
    }

    /**
     * Save the rendered values to the real input so it can be saved.
     */
    processInput()
    {
        this.realInput.value = this.wholeInput.value;
        if(this.fractionLength > 0) {
            this.realInput.value += this.padEnd(this.fractionInput.value, this.fractionLength, '0');
        }
    }

    /**
     * @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);
    }

    /**
     * @param targetLength
     * @param input
     * @param padString
     * @return {string}
     */
    padEnd(input, targetLength, padString) {
        targetLength = Math.floor(targetLength) || 0;
        if(targetLength < input.length) return String(input);

        padString = padString ? String(padString) : " ";

        let pad = "";
        let len = targetLength - input.length;
        let i = 0;
        while(pad.length < len) {
            if(!padString[i]) {
                i = 0;
            }
            pad += padString[i];
            i++;
        }

        return String(input).slice(0) + pad;
    };
}