I have a simple set of buttons that may be clicked in any order. When clicked[,] the button should fill the next available [empty] text box.
I would choose kind of a custom component based approach, thus one implements code as generic as possible just once. Code-reuse will be possible pretty easy for same (even similar) tasks but with e.g. a different markup. One also can use/run more than just one component at each document.
The approach is build around the usage of data-*
global attributes, attribute selectors and HTMLElement.dataset
.
A component (source) root gets identified by its [data-prefill-values-for]
attribute where its related dataset.prefillValuesFor
value holds such a component's ID. The latter will be used for querying the component's related target root via `[data-prefill-targets-for="${ componentId }"]`
.
The initialization of a component is done by subscribing a single handler which bind
s the component's target root to any 'click'
event from within the root element (see ... event-delegation).
The handler itself retrieves from its bound target root the first available empty prefill-target which is done by querying for [data-prefill-target]
and filtering the related elements each by its empty value
. In addition, but only if an empty prefill-target exists, the handler retrieves from its event-target the to be set prefill-value which gets achieved by reading the event-target's dataset.prefillValue
. In case all assignment criteria was fulfilled the assignment finally takes place.
function handlePrefillForBoundTarget(evt) {
const targetRoot = this;
const emptyPrefillTarget = Array
.from(
targetRoot
.querySelectorAll('[data-prefill-target]')
)
.filter(elmNode =>
(elmNode.value?.trim?.() ?? elmNode.value) === ''
)[0];
if (emptyPrefillTarget) {
const prefillSource = evt
.target
.closest('[data-prefill-value]');
const { prefillValue } = prefillSource.dataset;
emptyPrefillTarget.value = prefillValue;
}
}
function initPrefillComponent(sourceRoot) {
const componentId = sourceRoot
.dataset
.prefillValuesFor ?? '';
const targetRoot = document
.querySelector(`[data-prefill-targets-for="${ componentId }"]`);
if (targetRoot) {
sourceRoot
.addEventListener(
'click',
handlePrefillForBoundTarget
.bind(targetRoot)
);
}
}
function main() {
document
.querySelectorAll('[data-prefill-values-for]')
.forEach(initPrefillComponent);
}
main();
body { margin: 0; }
.textBoxes { margin: 8px 0 24px 0; }
<div class="buttons" data-prefill-values-for="1">
<button data-prefill-value="foo bar">foo bar</button>
<button data-prefill-value="baz biz">baz biz</button>
<button data-prefill-value="the quick brown fox">the quick brown fox</button>
<button data-prefill-value="jumps over">jumps over</button>
<button data-prefill-value="the lazy dog">the lazy dog</button>
</div>
<div class="textBoxes" data-prefill-targets-for="1">
<input type="text" placeholder="WPT 1" data-prefill-target autofocus />
<input type="text" placeholder="WPT 2" data-prefill-target />
<input type="text" placeholder="WPT 3" data-prefill-target />
<input type="text" placeholder="WPT 4" data-prefill-target />
<input type="text" placeholder="WPT 5" data-prefill-target />
</div>
<div class="buttons" data-prefill-values-for="2">
<button data-prefill-value="Lorem ipsum">
Lorem ipsum
</button>
<button data-prefill-value="dolor sit amet">
dolor sit amet
</button>
<button data-prefill-value="consectetur adipiscing elit">
consectetur adipiscing elit
</button>
<button data-prefill-value="sed do eiusmod tempor incididunt">
sed do eiusmod tempor incididunt
</button>
<button data-prefill-value="ut labore et dolore magna aliqua">
ut labore et dolore magna aliqua
</button>
</div>
<div class="textBoxes" data-prefill-targets-for="2">
<input type="text" placeholder="WPT 11" data-prefill-target value="foo" autofocus />
<input type="text" placeholder="WPT 12" data-prefill-target value="bar" />
<input type="text" placeholder="WPT 13" data-prefill-target />
<input type="text" placeholder="WPT 14" data-prefill-target value="baz" />
<input type="text" placeholder="WPT 15" data-prefill-target />
</div>