META-INF.resources.primefaces.inputnumber.1-inputnumber.js Maven / Gradle / Ivy
/**
* __PrimeFaces InputNumber Widget__
*
* InputNumber formats input fields with numeric strings. It supports currency symbols, minimum and maximum value,
* negative numbers, and a lot of round methods.
*
* @typedef {import("autonumeric").Options} PrimeFaces.widget.InputNumber.AutoNumericOptions Alias for the AutoNumeric
* options, required for technical reasons.
*
* @prop {import("autonumeric")} autonumeric The current AutoNumeric instance.
* @prop {boolean} disabled Whether this widget is currently disabled, i.e. whether the user can enter a number.
* @prop {JQuery} hiddenInput The DOM element for the hidden input field with the current value of this widget.
* @prop {JQuery} input The DOM element for the visible input field with autoNumeric.
* @prop {undefined} plugOptArray Always `undefined`.
* @prop {string} initialValue The initial, numerical value that is displayed, such as `0.0` or `5.3`.
*
* @interface {PrimeFaces.widget.InputNumberCfg} cfg The configuration for the {@link InputNumber| InputNumber widget}.
* You can access this configuration via {@link PrimeFaces.widget.BaseWidget.cfg|BaseWidget.cfg}. Please note that this
* configuration is usually meant to be read-only and should not be modified.
* @extends {PrimeFaces.widget.BaseWidgetCfg} cfg
* @extends {PrimeFaces.widget.InputNumber.AutoNumericOptions} cfg
*
* @prop {boolean} cfg.disabled Whether this widget is initially disabled.
* @prop {undefined} cfg.pluginOptions Always undefined.
* @prop {string} cfg.valueToRender The initial, numerical value that is displayed, such as `0.0` or `5.3`.
*/
PrimeFaces.widget.InputNumber = PrimeFaces.widget.BaseWidget.extend({
/**
* @override
* @inheritdoc
* @param {PrimeFaces.PartialWidgetCfg} cfg
*/
init: function(cfg) {
this._super(cfg);
this.input = $(this.jqId + '_input');
this.hiddenInput = $(this.jqId + '_hinput');
this.plugOptArray = cfg.pluginOptions;
this.initialValue = cfg.valueToRender;
this.disabled = cfg.disabled;
// GitHub #8125 minValue>0 shows js warning and quirky behavior
if (this.cfg.minimumValue > 0.0000001 || this.cfg.maximumValue < 0) {
this.cfg.overrideMinMaxLimits = 'invalid';
}
//bind events if not disabled
if (this.disabled) {
this.input.attr("disabled", "disabled");
this.input.addClass("ui-state-disabled");
this.hiddenInput.attr("disabled", "disabled");
}
//Visual effects
PrimeFaces.skinInput(this.input);
this.autonumeric = new AutoNumeric(this.jqId + '_input', this.cfg);
if (this.initialValue !== "") {
//set the value to the input the plugin will format it.
this.autonumeric.set(this.initialValue);
// GitHub #6940 blur firing too many change events
this.autonumeric.rawValueOnFocus = this.initialValue;
}
this.setValueToHiddenInput(this.getValue());
//pfs metadata
this.input.data(PrimeFaces.CLIENT_ID_DATA, this.id);
this.hiddenInput.data(PrimeFaces.CLIENT_ID_DATA, this.id);
// GitHub #10046 delay registering events until CSP has registered
var $this = this;
setTimeout(function () {$this.wrapEvents();}, 0);
},
/**
* @override
* @inheritdoc
* @param {PrimeFaces.PartialWidgetCfg} cfg
*/
refresh: function(cfg) {
this._cleanup();
this._super(cfg);
},
/**
* @override
* @inheritdoc
*/
destroy: function() {
this._super();
this._cleanup();
},
/**
* Clean up this widget and remove events from the DOM.
* @private
*/
_cleanup: function() {
if (this.autonumeric) {
this.autonumeric.remove();
}
},
/**
* Wraps the events on the external (visible) input to copy the value to the hidden input, before calling the
* callback.
* @private
*/
wrapEvents: function() {
var $this = this;
// get the current attached events if using CSP
var events = this.input[0] ? $._data(this.input[0], "events") : null;
// use DOM if non-CSP and JQ event if CSP
var originalOnkeyup = this.input.prop('onkeyup');
if (!originalOnkeyup && events && events.keyup) {
originalOnkeyup = events.keyup[0].handler;
}
this.input.prop('onkeyup', null).off('keyup').on('keyup.inputnumber', function(e) {
var oldValue;
var key = e.key;
if (key === 'Backspace' || key === 'Enter' || key === 'Delete' || PrimeFaces.utils.isPrintableKey(e)) {
oldValue = $this.copyValueToHiddenInput();
}
if (originalOnkeyup && originalOnkeyup.call(this, e) === false) {
if (oldValue) {
$this.setValueToHiddenInput(oldValue);
}
return false;
}
});
// use DOM if non-CSP and JQ event if CSP
var originalOnchange = this.input.prop('onchange');
if (!originalOnchange && events && events.change) {
originalOnchange = events.change[0].handler;
}
this.input.prop('onchange', null).off('change').on('change.inputnumber', function(e) {
var newValue = $this.copyValueToHiddenInput();
// #10046 do not call on Change if the value has not changed
if (newValue === $this.initialValue ||
($this.initialValue !== '' && newValue !== '' && Number(newValue) === Number($this.initialValue))) {
return false;
}
if (originalOnchange && originalOnchange.call(this, e) === false) {
$this.setValueToHiddenInput(newValue);
return false;
}
$this.initialValue = newValue;
});
// use DOM if non-CSP and JQ event if CSP
var originalOnkeydown = this.input.prop('onkeydown');
if (!originalOnkeydown && events && events.keydown) {
originalOnkeydown = events.keydown[0].handler;
}
this.input.prop('onkeydown', null).off('keydown').on('keydown.inputnumber', function(e) {
var oldValue = $this.copyValueToHiddenInput();
if (originalOnkeydown && originalOnkeydown.call(this, e) === false) {
$this.setValueToHiddenInput(oldValue);
return false;
}
});
this.bindInputEvents();
},
/**
* Binds input listener which fixes a browser autofill issue.
* See: https://github.com/autoNumeric/autoNumeric/issues/536
* @private
*/
bindInputEvents: function() {
var $this = this;
// GitHub #6447: browser auto fill fix
this.input.off('blur.inputnumber').on('blur.inputnumber', function(e) {
var element = AutoNumeric.getAutoNumericElement(this);
if (element && this.value && this.value.length > 0) {
var newValue = this.value.trim();
if ($this.cfg.digitGroupSeparator) {
newValue = newValue.replaceAll($this.cfg.digitGroupSeparator, '');
}
element.set(newValue, null, true);
// GitHub #8610: reset the raw values so we don't fire change event if 1.0 == 1.00
if (element.rawValueOnFocus !== '' && Number(element.rawValue) === Number(element.rawValueOnFocus)) {
element.rawValueOnFocus = element.rawValue;
}
}
$this.copyValueToHiddenInput();
});
},
/**
* Wraps the events on the external (visible) input to copy the value to the hidden input.
* @private
* @return {number} The original value of the hidden input.
*/
copyValueToHiddenInput: function() {
var oldVal = this.hiddenInput.val();
var newVal = this.getValue();
if (((oldVal === '') ^ (newVal === '')) || Number(oldVal) !== Number(newVal)) {
this.setValueToHiddenInput(newVal);
}
return oldVal;
},
/**
* Writes the given value to the hidden input field that stores the actual value of this widget.
* @private
* @param {string} value A value to set on the hidden input.
*/
setValueToHiddenInput: function(value) {
this.hiddenInput.val(value).trigger('input.slider');
},
/**
* Enables this input field, so that the user can enter data.
*/
enable: function() {
PrimeFaces.utils.enableInputWidget(this.input);
PrimeFaces.utils.enableInputWidget(this.hiddenInput);
this.disabled = false;
},
/**
* Enables this input field, so that the user cannot enter data.
*/
disable: function() {
PrimeFaces.utils.disableInputWidget(this.input);
PrimeFaces.utils.disableInputWidget(this.hiddenInput);
this.disabled = true;
},
/**
* Sets the value of this input number widget to the given value. Makes sure that the number is formatted correctly.
* @param {number | string} value The new value to set. If a number, it will be formatted appropriately. If the
* empty string, resets the value. Any other string is parsed into a number and then the number is set.
*/
setValue: function(value) {
this.autonumeric.set(value);
var cleanVal = this.getValue();
this.hiddenInput.attr('value', cleanVal);
},
/**
* Finds the current value, which is the raw numerical value without any formatting applied.
* @return {string} The current value of this input number widget, in its string representation according to the
* configured format.
*/
getValue: function() {
var val = this.autonumeric.getNumericString();
if (this.autonumeric.getSettings().allowDecimalPadding && val && parseInt(this.cfg.decimalPlaces, 10) > 0) {
var decimalPlacesToPad;
if (val.indexOf('.') === -1) {
decimalPlacesToPad = this.cfg.decimalPlaces;
val += '.';
} else {
var decimalPlacesAlreadyRendered = val.length - val.indexOf('.') - 1;
decimalPlacesToPad = this.cfg.decimalPlaces - decimalPlacesAlreadyRendered;
}
while (decimalPlacesToPad-- > 0) {
val += '0';
}
}
// GitHub #7911 Autonumeric bug workaround.
// Remove when issue fixed: https://github.com/autoNumeric/autoNumeric/issues/670
if (val && val.endsWith(this.cfg.decimalCharacter)) {
val = val.substring(0, val.length - 1);
}
return val;
}
});
© 2015 - 2024 Weber Informatics LLC | Privacy Policy