infusion
Version:
Infusion is an application framework for developing flexible stuff with JavaScript
140 lines (130 loc) • 4.97 kB
JavaScript
/*
Copyright The Infusion copyright holders
See the AUTHORS.md file at the top-level directory of this distribution and at
https://github.com/fluid-project/infusion/raw/main/AUTHORS.md.
Licensed under the Educational Community License (ECL), Version 2.0 or the New
BSD license. You may not use this file except in compliance with one these
Licenses.
You may obtain a copy of the ECL 2.0 License and BSD License at
https://github.com/fluid-project/infusion/raw/main/Infusion-LICENSE.txt
*/
"use strict";
/*************
* Textfield *
*************/
/*
* A component for controlling a textfield and handling data binding.
* Typically this will be used in conjunction with a UI control widget such as
* button steppers or slider.
*/
fluid.defaults("fluid.textfield", {
gradeNames: ["fluid.viewComponent"],
attrs: {
// Specified by implementor
// ID of an external label to refer to with aria-labelledby
// attribute
// "aria-labelledby": "",
// Should specify either "aria-label" or "aria-labelledby"
// aria-label: "{that}.options.strings.label",
// ID of an element that is controlled by the textfield.
// "aria-controls": ""
},
strings: {
// Specified by implementor
// text of label to apply to both textfield and slider input
// via aria-label attribute
// "label": ""
},
modelListeners: {
value: {
"this": "{that}.container",
"method": "val",
args: ["{change}.value"]
}
},
listeners: {
"onCreate.bindChangeEvt": {
"this": "{that}.container",
"method": "on",
"args": ["change", "{that}.setModel"]
},
"onCreate.initTextfieldAttributes": {
"this": "{that}.container",
method: "attr",
args: ["{that}.options.attrs"]
}
},
invokers: {
setModel: {
changePath: "value",
value: "{arguments}.0.target.value"
}
}
});
/**
* Sets the model value only if the new value is a valid number, and will reset the textfield to the current model
* value otherwise.
*
* @param {Object} that - The component.
* @param {Number} value - The new numerical entry.
* @param {String} path - The path into the model for which the value should be set.
*/
fluid.textfield.setModelRestrictToNumbers = function (that, value, path) {
var isNumber = !isNaN(Number(value));
if (isNumber) {
that.applier.change(path, value);
}
// Set the textfield to the latest valid entry.
// This handles both the cases where an invalid entry was provided, as well as cases where a valid number is
// rounded. In the case of rounded numbers this ensures that entering a number that rounds to the current
// set value, doesn't leave the textfield with the unrounded number present.
that.container.val(that.model.value);
};
/******************************
* TextField Range Controller *
******************************/
/*
* Range Controller is intended to be used as a grade on a fluid.textfield component. It will limit the input
* to be constrained within a given numerical range. This should be paired with configuring the textfield.setModel
* invoker to use fluid.textfield.setModelRestrictToNumbers.
* The Range Controller is useful when combining the textfield with a UI control element such as stepper buttons
* or a slider to enter numerical values.
*/
fluid.defaults("fluid.textfield.rangeController", {
gradeNames: ["fluid.textfield"],
components: {
controller: {
type: "fluid.modelComponent",
options: {
model: {
value: null
},
modelRelay: [{
source: "value",
target: "{fluid.textfield}.model.value",
singleTransform: {
type: "fluid.transforms.numberToString",
// The scale option sets the number of decimal places to round
// the number to. If no scale is specified, the number will not be rounded.
// Scaling is useful to avoid long decimal places due to floating point imprecision.
scale: "{that}.options.scale"
}
}, {
target: "value",
singleTransform: {
type: "fluid.transforms.limitRange",
input: "{that}.model.value",
min: "{that}.model.range.min",
max: "{that}.model.range.max"
}
}]
}
}
},
invokers: {
setModel: {
funcName: "fluid.textfield.setModelRestrictToNumbers",
args: ["{that}", "{arguments}.0.target.value", "value"]
}
}
});