Published
Edited
Feb 4, 2021
Insert cell
Insert cell
Insert cell
element
Insert cell
// programmatically call undo
// viewof element.value.undo.dispatchEvent(new Event('click'))
Insert cell
// programmatically call redo
// viewof element.value.redo.dispatchEvent(new Event('click'))
Insert cell
viewof element = numberBox()
Insert cell
function numberBox() {
const wrapper = html`<div>`;
const input = html`<input type="number">`;
const undoButton = html`<button>Undo</button>`;
const redoButton = html`<button>Redo</button>`;

const state = {
history: [],
value: 0,
undo: undoButton,
redo: redoButton
};

let curIndex = -1;
const addToHistory = debounce(e => {
if (curIndex !== state.history.length - 1) {
state.history = state.history.slice(0, curIndex);
}
state.history.push(e.target.valueAsNumber);
curIndex++;
state.value = e.target.valueAsNumber;
wrapper.value = state;
wrapper.dispatchEvent(new CustomEvent("input"));
}, 250);

input.addEventListener('input', addToHistory);

undoButton.addEventListener('click', undo);

redoButton.addEventListener('click', redo);

function undo() {
if (curIndex) curIndex--;
state.value = state.history[curIndex];
input.value = state.value;
wrapper.value = state;
wrapper.dispatchEvent(new CustomEvent("input"));
}

function redo() {
if (curIndex < state.history.length - 1) curIndex++;
state.value = state.history[curIndex];
input.value = state.value;
wrapper.value = state;
wrapper.dispatchEvent(new CustomEvent("input"));
}

// from David Walsh https://davidwalsh.name/javascript-debounce-function
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this,
args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}

wrapper.appendChild(input);
wrapper.appendChild(undoButton);
wrapper.appendChild(redoButton);
wrapper.value = state;
return wrapper;
}
Insert cell
md`### Questions

- When entering a 3 digit number (like 357), it shows "3", then "35", then "357". This can be alleviated with a submit button.
- For an input like a slider, that continuously updates as we are dragging. We might just want the history of the mouseup event. I'm not sure how I would attempt to do that, except by making some custom input controls
`
Insert cell
md`# Requires and imports`
Insert cell
// import {number} from "@severo/inputs-setter"

// I copied the input2 and originalNumber from "@severo/inputs-setter" and modified them.
Insert cell
import {number} with { input3 as input } from "@jashkenas/inputs"
Insert cell
import {addSetter} from "@severo/inputs-setter"
Insert cell
d3format = require("d3-format@1")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more