mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-10-04 12:01:35 +02:00
much better sketch resetting using DOM rebuild
This commit is contained in:
172
docs/js/custom-element/api/impart-slider-logic.js
Normal file
172
docs/js/custom-element/api/impart-slider-logic.js
Normal file
@@ -0,0 +1,172 @@
|
||||
import { create } from "../lib/create.js";
|
||||
|
||||
export default function impartSliderLogic(GraphicsAPI) {
|
||||
/**
|
||||
* Dynamically add a slider
|
||||
*/
|
||||
GraphicsAPI.prototype.addSlider = function addSlider(
|
||||
classes,
|
||||
propname,
|
||||
min,
|
||||
max,
|
||||
step,
|
||||
value,
|
||||
transform
|
||||
) {
|
||||
if (this.element) {
|
||||
let slider = create(`input`);
|
||||
slider.type = `range`;
|
||||
slider.min = min;
|
||||
slider.max = max;
|
||||
slider.step = step;
|
||||
slider.setAttribute(`value`, value);
|
||||
slider.setAttribute(`class`, classes);
|
||||
this.element.append(slider);
|
||||
this.setSlider(slider, propname, value, transform);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Update a slider with new min/max/step parameters, and value.
|
||||
*
|
||||
* @param {*} propname
|
||||
* @param {*} min
|
||||
* @param {*} max
|
||||
* @param {*} step
|
||||
* @param {*} value
|
||||
*/
|
||||
GraphicsAPI.prototype.updateSlider = function updateSlider(
|
||||
propname,
|
||||
min,
|
||||
max,
|
||||
step,
|
||||
value
|
||||
) {
|
||||
let slider = this._sliders[propname];
|
||||
|
||||
if (!slider) {
|
||||
throw new Error(`this.${propname} has no associated slider.`);
|
||||
}
|
||||
|
||||
slider.setAttribute(`min`, min);
|
||||
slider.setAttribute(`max`, max);
|
||||
slider.setAttribute(`step`, step);
|
||||
slider.setAttribute(`value`, value);
|
||||
slider.updateProperty(value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set up a slider to control a named, numerical property in the sketch.
|
||||
*
|
||||
* @param {String} local query selector for the type=range element.
|
||||
* @param {String} propname the name of the property to control.
|
||||
* @param {float} initial the initial value for this property.
|
||||
* @param {boolean} redraw whether or not to redraw after updating the value from the slider.
|
||||
*/
|
||||
GraphicsAPI.prototype.setSlider = function setSlider(
|
||||
qs,
|
||||
propname,
|
||||
initial,
|
||||
transform
|
||||
) {
|
||||
if (propname !== false && typeof this[propname] !== `undefined`) {
|
||||
throw new Error(`this.${propname} already exists: cannot bind slider.`);
|
||||
}
|
||||
|
||||
this._sliders = this._sliders || {};
|
||||
|
||||
let propLabel = propname.replace(`!`, ``);
|
||||
propname = propLabel === propname ? propname : false;
|
||||
|
||||
let slider = typeof qs === `string` ? this.find(qs) : qs;
|
||||
|
||||
// create a slider row in the table of sliders
|
||||
let ui = (() => {
|
||||
if (!this.element) {
|
||||
return { update: (v) => {} };
|
||||
}
|
||||
|
||||
let table = find(`table.slider-wrapper`);
|
||||
|
||||
if (!table) {
|
||||
table = slider.parentNode.querySelector(`table.slider-wrapper`);
|
||||
if (!table) {
|
||||
table = create(`table`);
|
||||
table.classList.add(`slider-wrapper`);
|
||||
slider.parentNode.replaceChild(table, slider);
|
||||
}
|
||||
}
|
||||
|
||||
let tr = create(`tr`);
|
||||
|
||||
let td = create(`td`);
|
||||
let label = create(`label`);
|
||||
label.classList.add(`slider-label`);
|
||||
label.innerHTML = propLabel;
|
||||
td.append(label);
|
||||
tr.append(td);
|
||||
|
||||
td = create(`td`);
|
||||
slider.classList.add(`slider`);
|
||||
this._sliders[propname] = slider;
|
||||
td.append(slider);
|
||||
tr.append(td);
|
||||
|
||||
td = create(`td`);
|
||||
let valueField = create(`label`);
|
||||
valueField.classList.add(`slider-value`);
|
||||
valueField.textContent;
|
||||
td.append(valueField);
|
||||
tr.append(td);
|
||||
|
||||
table.append(tr);
|
||||
return { update: (v) => (valueField.textContent = v) };
|
||||
})();
|
||||
|
||||
if (!slider) {
|
||||
console.warn(`Warning: no slider found for query selector "${qs}"`);
|
||||
if (propname) this[propname] = initial;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let step = slider.getAttribute(`step`) || "1";
|
||||
let res = !step.includes(`.`)
|
||||
? 0
|
||||
: step.substring(step.indexOf(`.`) + 1).length;
|
||||
|
||||
slider.updateProperty = (evt) => {
|
||||
let value = parseFloat(slider.value);
|
||||
ui.update(value.toFixed(res));
|
||||
try {
|
||||
let checked = transform ? transform(value) ?? value : value;
|
||||
if (propname) this[propname] = checked;
|
||||
} catch (e) {
|
||||
if (evt instanceof Event) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
}
|
||||
ui.update(e.value.toFixed(res));
|
||||
slider.value = e.value;
|
||||
slider.setAttribute(`value`, e.value);
|
||||
}
|
||||
if (!this.redrawing) this.redraw();
|
||||
};
|
||||
|
||||
slider.value = initial;
|
||||
slider.updateProperty({ target: { value: initial } });
|
||||
slider.listen(`input`, (evt) => slider.updateProperty(evt));
|
||||
|
||||
return slider;
|
||||
};
|
||||
|
||||
/**
|
||||
* remove all sliders from this element
|
||||
*/
|
||||
GraphicsAPI.prototype.removeSliders = function removeSliders() {
|
||||
this.findAll(`.slider-wrapper`).forEach((s) => {
|
||||
s.parentNode.removeChild(s);
|
||||
});
|
||||
};
|
||||
|
||||
return GraphicsAPI;
|
||||
}
|
Reference in New Issue
Block a user