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 }