Published
Edited
May 30, 2022
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function ScrollInput(
data = d3.range(150),
{ height = `200px`, width = `100px`, type = "number" } = {}
) {
const padding_box = html`<div style="height: 50%; border: 1px dashed orange;"></div>`;
const child_style = `
font-family: monospace;
display: grid;
place-items: center;
scroll-snap-align: center;
`;
const children = data.map(
(d) => html`<div data-value=${d} style=${child_style}>${d}</div>`
);
const parent_style = `
height: 100%;
overflow: scroll;
scroll-snap-type: y mandatory;
overscroll-behavior: contain;
`;
const pad = () => html`<div style="height: 50%;"></div>`;
const scroll_box = html`<div id="scroll-box" style=${parent_style}>${pad()}${children}${pad()}</div>`;
const overlay_style = `
pointer-events: none;
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 100%;
border: 1px solid black;
`;
const overlay = html`<div style=${overlay_style}>&nbsp;</div>`;
const wrapper_style = `position: relative; height: ${height}; width: ${width}`;
const wrapper = html`<form style=${wrapper_style}>${scroll_box}${overlay}</form>`;
let value;
scroll_box.onscroll = (event) => {
event.stopPropagation();
event.preventDefault();
const rect = scroll_box.getBoundingClientRect();
const { x, y, width, height } = rect;
const middle = { x: x + width / 2, y: y + height / 2 };
const elem = document.elementFromPoint(middle.x, middle.y);
value = elem.dataset?.value;
wrapper.dispatchEvent(new CustomEvent("input"));
};
Object.defineProperty(wrapper, "value", {
get() {
return value;
},
set(v) {
value = v;
const child = scroll_box.querySelector(`div[data-value="${v}"]`);
const child_height = child.getBoundingClientRect().height;
const parent_height = scroll_box.getBoundingClientRect().height;
scroll_box.scrollTo({
behavior: `instant`,
top: child.offsetTop + child_height / 2 - parent_height / 2,
left: 0
});
}
});
return wrapper;
}
Insert cell
Insert cell
html = htl.html
Insert cell
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