sercrod

List reordering (click to insert)

This example shows a click-based way to reorder items in a long list. You first mark one row as “moving”, then click a slot to insert it before or after another row.

This pattern works better than simple Up / Down buttons when you have dozens of items, and it is easier to reason about than free-form drag and drop for some users.

Example: click-to-reorder list

The list is driven by an items array. A small helper function nab_move rebuilds the array with one item moved from index from to index to.

Code

<script>
// Move a single element from index "from" to index "to"
function nab_move(list, from, to){
	if(from===to) return list;
	if(from<0 || to<0) return list;
	if(from>=list.length || to>list.length) return list;

	var copy = list.slice();
	var item = copy.splice(from, 1)[0];

	// When moving to a later position, adjust index after removal
	if(from < to) to = to - 1;

	copy.splice(to, 0, item);
	return copy;
}

// Build demo data: 100 items
var items = [];
for(var i=1; i<=100; i++){
	var n = String(i).padStart(3, "0"); // 001, 002, ...
	items.push({ id: i, label: "Item " + n });
}

// Data passed to Sercrod
var json = {
	items: items,
	move_index: null,
	is_reordering: false
};
</script>

<serc-rod id="reorder-list" data="__reorder_demo_data">
	<h2>Reorder (click to insert)</h2>

	<p>
		Click “Start move” on a row, then click “Insert here”
		to move it.
	</p>

	<p *if="is_reordering">
		Moving:
		<span *print="
			(move_index!=null && move_index>=0 && move_index<items.length)
			? items[move_index].label
			: ''
		"></span>
		<span
			@click="
				is_reordering = false;
				move_index = null;
			"
		>[Cancel move]</span>
	</p>
	<p *else>No active move.</p>

	<ul>
		<li>
			<span
				*if="is_reordering"
				@click="
					if(move_index===null) return;
					items = nab_move(items, move_index, 0);
					is_reordering = false;
					move_index = null;
				"
			>Insert at top</span>
			<span *else>--------</span>
		</li>

		<li *for="i, item of items">
			<div>
				<span>%i%: %item.label%</span>
				<button type="button"
					@click="
						if(is_reordering && move_index===i){
							is_reordering = false;
							move_index = null;
						}else{
							is_reordering = true;
							move_index = i;
						}
					"
				>Start move</button>
				<em *if="is_reordering && move_index===i">Selected</em>
			</div>

			<div>
				<span
					*if="is_reordering"
					@click="
						if(move_index===null) return;
						var to = i + 1;
						items = nab_move(items, move_index, to);
						is_reordering = false;
						move_index = null;
					"
				>Insert here</span>
				<span *else>--------</span>
			</div>
		</li>
	</ul>
</serc-rod>

Sample

In the live sample below you can reorder up to 100 items. Sercrod keeps the items array and the rendered list in sync.

Reorder (click to insert)

Click “Start move” on a row, then click “Insert here” to move it.

Moving: [Cancel move]

No active move.

  • Insert at top --------
  • %i%: %item.label% Selected
    Insert here --------

When this pattern helps

For a more direct, visual interaction on smaller tables, see Sortable list (drag and drop).