TP_JO2024/home/dist/component/range/range.module.js

589 lines
15 KiB
JavaScript
Raw Permalink Normal View History

2024-03-27 17:19:37 +01:00
/*! DSFR v1.11.2 | SPDX-License-Identifier: MIT | License-Filename: LICENSE.md | restricted use (see terms and conditions) */
const config = {
prefix: 'fr',
namespace: 'dsfr',
organisation: '@gouvfr',
version: '1.11.2'
};
const api = window[config.namespace];
const RangeSelector = {
RANGE: api.internals.ns.selector('range'),
RANGE_SM: api.internals.ns.selector('range--sm'),
RANGE_STEP: api.internals.ns.selector('range--step'),
RANGE_DOUBLE: api.internals.ns.selector('range--double'),
RANGE_DOUBLE_STEP: api.internals.ns.selector('range--double') + api.internals.ns.selector('range--step'),
RANGE_INPUT: api.internals.ns.selector('range input[type=range]:nth-of-type(1)'),
RANGE_INPUT2: `${api.internals.ns.selector('range--double')} input[type=range]:nth-of-type(2)`,
RANGE_OUTPUT: api.internals.ns.selector('range__output'),
RANGE_MIN: api.internals.ns.selector('range__min'),
RANGE_MAX: api.internals.ns.selector('range__max'),
RANGE_PREFIX: api.internals.ns.attr('prefix'),
RANGE_SUFFIX: api.internals.ns.attr('suffix')
};
const RangeEmission = {
VALUE: api.internals.ns.emission('range', 'value'),
VALUE2: api.internals.ns.emission('range', 'value2'),
OUTPUT: api.internals.ns.emission('range', 'output'),
CONSTRAINTS: api.internals.ns.emission('range', 'constraints'),
MIN: api.internals.ns.emission('range', 'min'),
MAX: api.internals.ns.emission('range', 'max'),
STEP: api.internals.ns.emission('range', 'step'),
PREFIX: api.internals.ns.emission('range', 'prefix'),
SUFFIX: api.internals.ns.emission('range', 'suffix'),
DISABLED: api.internals.ns.emission('range', 'disabled'),
ENABLE_POINTER: api.internals.ns.emission('range', 'enable_pointer')
};
class RangeModel {
constructor () {
this._width = 0;
this._min = 0;
this._max = 0;
this._value = 0;
this._thumbSize = 24;
this._innerWidth = 0;
this._prefix = '';
this._suffix = '';
this._background = {};
}
configure (model) {
if (!model) return;
this._prefix = model._prefix;
this._suffix = model._suffix;
this._width = model.width;
this.setConstraints(model._constraints);
this.value = model.value;
this.update();
}
setPrefix (value) {
this._prefix = value !== null ? value : '';
}
setSuffix (value) {
this._suffix = value !== null ? value : '';
}
_decorate (value) {
return `${this._prefix}${value}${this._suffix}`;
}
get width () {
return this._width;
}
set width (value) {
this._width = value;
}
get isSm () {
return this._isSm;
}
set isSm (value) {
if (this._isSm === value) return;
this._isSm = value;
this.setThumbSize(value ? 16 : 24);
this.update();
}
setThumbSize (value, mult = 1) {
this._thumbSize = value;
this._innerPadding = value * mult;
}
get textValue () {
return this._decorate(this._value);
}
get value () {
return this._value;
}
set value (value) {
this._value = value;
}
get outputX () {
return this._outputX;
}
setConstraints (constraints) {
this._constraints = constraints;
this._min = constraints.min;
this._max = constraints.max;
this._step = constraints.step;
this._rangeWidth = constraints.rangeWidth;
}
get min () {
return this._min;
}
get textMin () {
return this._decorate(this._min);
}
get max () {
return this._max;
}
get textMax () {
return this._decorate(this._max);
}
get step () {
return this._step;
}
get output () {
return {
text: this.textValue,
transform: `translateX(${this._translateX}px) translateX(-${this._centerPercent}%)`
};
}
_getRatio (value) {
return (value - this._min) / this._rangeWidth;
}
get progress () {
return this._progress;
}
update () {
this._update();
}
_update () {
this._innerWidth = this._width - this._innerPadding;
const ratio = this._getRatio(this._value);
this._translateX = ratio * this._width;
this._centerPercent = ratio * 100;
this._progress = {
right: `${(this._innerWidth * ratio + this._innerPadding * 0.5).toFixed(2)}px`
};
}
}
class RangeModelStep extends RangeModel {
get stepWidth () {
return `${this._stepWidth.toFixed(3)}px`;
}
_update () {
super._update();
const steps = this._rangeWidth / this._step;
this._stepWidth = this._innerWidth / steps;
while (this._stepWidth < 4) this._stepWidth *= 2;
}
}
class RangeModelDouble extends RangeModel {
get value2 () {
return this._value;
}
set value2 (value) {
if (this._value2 === value) return;
this._value2 = value;
this.update();
}
get textValue () {
return `${this._decorate(this._value)} - ${this._decorate(this._value2)}`;
}
setThumbSize (value) {
super.setThumbSize(value, 2);
}
_update () {
super._update();
const ratio = this._getRatio((this._value + this._value2) * 0.5);
this._translateX = ratio * this._width;
this._centerPercent = ratio * 100;
const ratio1 = this._getRatio(this._value);
const ratio2 = this._getRatio(this._value2);
this._progress = {
left: `${(this._innerWidth * ratio1 + this._innerPadding * 0.25).toFixed(2)}px`,
right: `${(this._innerWidth * ratio2 + this._innerPadding * 0.75).toFixed(2)}px`
};
}
}
class RangeModelDoubleStep extends RangeModelDouble {
get stepWidth () {
return `${this._stepWidth.toFixed(3)}px`;
}
_update () {
super._update();
const steps = this._rangeWidth / this._step;
this._stepWidth = this._innerWidth / steps;
if (this._stepWidth < 4) this._stepWidth *= Math.ceil(4 / this._stepWidth);
}
}
const RangeTypes = {
STEP: 'step',
DOUBLE: 'double',
DOUBLE_STEP: 'double-step',
DEFAULT: 'default'
};
class Range extends api.core.Instance {
static get instanceClassName () {
return 'Range';
}
init () {
this._retrieveType();
this._retrieveSize();
if (this.isLegacy) {
this.isResizing = true;
this.isMouseMoving = true;
} else {
this._observer = new ResizeObserver(this.resize.bind(this));
this._observer.observe(this.node);
}
this.addAscent(RangeEmission.CONSTRAINTS, this.setConstraints.bind(this));
this.addAscent(RangeEmission.VALUE, this.setValue.bind(this));
this.addAscent(RangeEmission.VALUE2, this.setValue2.bind(this));
if (this.getAttribute(RangeSelector.RANGE_PREFIX)) this.setPrefix(this.getAttribute(RangeSelector.RANGE_PREFIX));
if (this.getAttribute(RangeSelector.RANGE_SUFFIX)) this.setSuffix(this.getAttribute(RangeSelector.RANGE_SUFFIX));
this.update();
}
_retrieveType () {
switch (true) {
case this.matches(RangeSelector.RANGE_DOUBLE_STEP):
this.type = RangeTypes.DOUBLE;
break;
case this.matches(RangeSelector.RANGE_DOUBLE):
this.type = RangeTypes.DOUBLE;
break;
case this.matches(RangeSelector.RANGE_STEP):
this.type = RangeTypes.STEP;
break;
default:
this.type = RangeTypes.DEFAULT;
}
}
set type (value) {
if (this._type === value) return;
this._type = value;
const oldModel = this._model;
switch (this._type) {
case RangeTypes.DOUBLE_STEP:
this._model = new RangeModelDoubleStep();
break;
case RangeTypes.DOUBLE:
this._model = new RangeModelDouble();
break;
case RangeTypes.STEP:
this._model = new RangeModelStep();
break;
default:
this._model = new RangeModel();
}
this._model.configure(oldModel);
}
get type () {
return this._type;
}
_retrieveSize () {
this._model.isSm = this.matches(RangeSelector.RANGE_SM);
}
resize () {
this._retrieveWidth();
this.update();
}
_retrieveWidth () {
this._model.width = this.getRect().width;
}
setValue (value) {
this._model.value = value;
switch (this._type) {
case RangeTypes.DOUBLE_STEP:
case RangeTypes.DOUBLE:
this.descend(RangeEmission.VALUE, value);
break;
}
this.update();
}
setValue2 (value) {
this._model.value2 = value;
this.descend(RangeEmission.VALUE2, value);
this.update();
}
setConstraints (constraints) {
this._model.setConstraints(constraints);
this.update();
this.descend(RangeEmission.CONSTRAINTS, constraints);
}
setPrefix (value) {
this._model.setPrefix(value);
this.update();
}
setSuffix (value) {
this._model.setSuffix(value);
this.update();
}
mutate (attributesNames) {
switch (true) {
case attributesNames.includes('class'):
this._retrieveType();
this._retrieveSize();
break;
case attributesNames.includes(RangeSelector.RANGE_PREFIX):
case attributesNames.includes(RangeSelector.RANGE_SUFFIX):
this._model.setPrefix(this.getAttribute(RangeSelector.RANGE_PREFIX));
this._model.setSuffix(this.getAttribute(RangeSelector.RANGE_SUFFIX));
this.update();
break;
}
}
update () {
this._model.update();
this.descend(RangeEmission.OUTPUT, this._model.output);
this.descend(RangeEmission.MIN, this._model.textMin);
this.descend(RangeEmission.MAX, this._model.textMax);
const progress = this._model.progress;
if (progress.left) {
this.style.setProperty('--progress-left', progress.left);
} else {
this.style.removeProperty('--progress-left');
}
if (progress.right) {
this.style.setProperty('--progress-right', progress.right);
if (this.isLegacy) {
if (progress.left) {
this.style.setProperty('background-position-x', progress.left);
this.style.setProperty('background-size', `${parseFloat(progress.right) - parseFloat(progress.left)}px ${this._model.isSm ? '8px' : '12px'}`);
}
}
} else {
this.style.removeProperty('--progress-right');
if (this.isLegacy) {
this.style.removeProperty('background-size');
this.style.removeProperty('background-position-x');
}
}
if (this._model.stepWidth) this.style.setProperty('--step-width', this._model.stepWidth);
else this.style.removeProperty('--step-width');
}
mouseMove (point) {
if (this._type !== RangeTypes.DOUBLE && this._type !== RangeTypes.DOUBLE_STEP) return;
const x = point.x - this.getRect().left;
this.descend(RangeEmission.ENABLE_POINTER, (parseFloat(this._model.progress.right) - parseFloat(this._model.progress.left)) / 2 + parseFloat(this._model.progress.left) < x ? 2 : 1);
}
dispose () {
this._observer.disconnect();
}
}
class RangeConstraints {
constructor (node) {
this._min = isNaN(node.min) ? 0 : node.min;
this._max = isNaN(node.max) ? 100 : node.max;
this._step = isNaN(node.step) ? 1 : node.step;
this._rangeWidth = this._max - this._min;
}
get min () {
return this._min;
}
get max () {
return this._max;
}
get step () {
return this._step;
}
get rangeWidth () {
return this._rangeWidth;
}
test (min, max, step) {
return this._min === min && this._max === max && this._step === step;
}
}
class RangeInput extends api.core.Instance {
static get instanceClassName () {
return 'RangeInput';
}
init () {
this._init();
this.node.value = this.getAttribute('value');
this._changing = this.change.bind(this);
this._listenerType = this.isLegacy ? 'change' : 'input';
this.listen(this._listenerType, this._changing);
if (this.isLegacy) this.addDescent(RangeEmission.ENABLE_POINTER, this._enablePointer.bind(this));
this.change();
}
_init () {
this._pointerId = 1;
this.request(() => {
if (!this.hasAttribute('min')) this.setAttribute('min', 0);
this.ascend(RangeEmission.CONSTRAINTS, new RangeConstraints(this.node));
this.ascend(RangeEmission.DISABLED, this.node.disabled);
});
this.addDescent(RangeEmission.VALUE2, this.setValue.bind(this));
}
_enablePointer (pointerId) {
const isEnabled = pointerId === this._pointerId;
if (this._isPointerEnabled === isEnabled) return;
this._isPointerEnabled = isEnabled;
if (isEnabled) this.style.removeProperty('pointer-events');
else this.style.setProperty('pointer-events', 'none');
}
setValue (value) {
if (parseFloat(this.node.value) > value) {
this.node.value = value;
this.change();
}
}
change () {
this.ascend(RangeEmission.VALUE, parseFloat(this.node.value));
}
mutate (attributesNames) {
if (attributesNames.includes('disabled')) this.ascend(RangeEmission.DISABLED, this.node.disabled);
if (attributesNames.includes('min') || attributesNames.includes('max') || attributesNames.includes('step')) {
this.ascend(RangeEmission.CONSTRAINTS, new RangeConstraints(this.node));
this.change();
}
}
dispose () {
if (this._listenerType) this.unlisten(this._listenerType, this._changing);
}
}
class RangeInput2 extends RangeInput {
static get instanceClassName () {
return 'RangeInput2';
}
_init () {
this._pointerId = 2;
this.addDescent(RangeEmission.CONSTRAINTS, this.setConstraints.bind(this));
this.addDescent(RangeEmission.VALUE, this.setValue.bind(this));
}
setValue (value) {
if (parseFloat(this.node.value) < value) {
this.node.value = value;
this.change();
}
}
change () {
this.ascend(RangeEmission.VALUE2, parseFloat(this.node.value));
}
setConstraints (constraints) {
this.node.min = constraints.min;
this.node.max = constraints.max;
this.node.step = constraints.step;
this.change();
}
mutate (attributesNames) {}
}
class RangeOutput extends api.core.Instance {
static get instanceClassName () {
return 'RangeOutput';
}
init () {
this.addDescent(RangeEmission.OUTPUT, this.change.bind(this));
}
change (data) {
this.node.innerText = data.text;
this.node.style.transform = data.transform;
}
}
class RangeLimit extends api.core.Instance {
static get instanceClassName () {
return 'RangeLimit';
}
init () {
switch (true) {
case this.matches(RangeSelector.RANGE_MIN):
this.addDescent(RangeEmission.MIN, this.change.bind(this));
break;
case this.matches(RangeSelector.RANGE_MAX):
this.addDescent(RangeEmission.MAX, this.change.bind(this));
break;
}
}
change (text) {
this.node.innerText = text;
}
}
api.range = {
Range: Range,
RangeInput: RangeInput,
RangeInput2: RangeInput2,
RangeOutput: RangeOutput,
RangeLimit: RangeLimit,
RangeEmission: RangeEmission,
RangeSelector: RangeSelector
};
api.internals.register(api.range.RangeSelector.RANGE, api.range.Range);
api.internals.register(api.range.RangeSelector.RANGE_INPUT, api.range.RangeInput);
api.internals.register(api.range.RangeSelector.RANGE_INPUT2, api.range.RangeInput2);
api.internals.register(api.range.RangeSelector.RANGE_OUTPUT, api.range.RangeOutput);
api.internals.register(api.range.RangeSelector.RANGE_MIN, api.range.RangeLimit);
api.internals.register(api.range.RangeSelector.RANGE_MAX, api.range.RangeLimit);
//# sourceMappingURL=range.module.js.map