Theseus: drag-to-reorder search engines (replaces up/down arrows)
Each engine row in Settings has a drag handle (⠿) and is draggable; dropping onto another row reorders and persists via setEngineOrder, driving the toolbar dropdown order. Visual drag/over states included.
This commit is contained in:
parent
e284864d3c
commit
9c5c6c12c9
1 changed files with 24 additions and 15 deletions
|
|
@ -43,9 +43,11 @@
|
||||||
.eng .eic .ei{width:16px;height:16px;border-radius:3px} .eng .eic .es{font-size:14px}
|
.eng .eic .ei{width:16px;height:16px;border-radius:3px} .eng .eic .es{font-size:14px}
|
||||||
.eng .enm{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
.eng .enm{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||||
.eng .cx{cursor:pointer;color:var(--dim);border:none;background:transparent;font-size:13px} .eng .cx:hover{color:#f6768a}
|
.eng .cx{cursor:pointer;color:var(--dim);border:none;background:transparent;font-size:13px} .eng .cx:hover{color:#f6768a}
|
||||||
.eng .mv{display:flex;flex-direction:column;flex:none;gap:1px}
|
.eng{cursor:default}
|
||||||
.eng .mv button{border:none;background:transparent;color:var(--dim);cursor:pointer;font-size:8px;line-height:1;padding:1px 2px;border-radius:3px}
|
.eng .grip{flex:none;color:var(--dim);cursor:grab;font-size:14px;line-height:1;padding:0 2px;user-select:none}
|
||||||
.eng .mv button:hover{background:var(--line);color:var(--ink)}
|
.eng .grip:active{cursor:grabbing}
|
||||||
|
.eng.dragging{opacity:.45}
|
||||||
|
.eng.over{border-color:var(--acid);box-shadow:0 -2px 0 var(--acid) inset}
|
||||||
.sw.sm{width:38px;height:22px} .sw.sm .knob{width:15px;height:15px} .sw.sm input:checked + .track .knob{transform:translateX(16px)}
|
.sw.sm{width:38px;height:22px} .sw.sm .knob{width:15px;height:15px} .sw.sm input:checked + .track .knob{transform:translateX(16px)}
|
||||||
.ceng .cn{font-weight:600} .ceng .cu{color:var(--dim);font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}
|
.ceng .cn{font-weight:600} .ceng .cu{color:var(--dim);font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}
|
||||||
.ceng .cx{cursor:pointer;color:#8b98a9;border:none;background:transparent;font-size:13px} .ceng .cx:hover{color:#f6768a}
|
.ceng .cx{cursor:pointer;color:#8b98a9;border:none;background:transparent;font-size:13px} .ceng .cx:hover{color:#f6768a}
|
||||||
|
|
@ -233,26 +235,33 @@
|
||||||
const enabled = d.engines.filter((e) => e.enabled);
|
const enabled = d.engines.filter((e) => e.enabled);
|
||||||
sel.innerHTML = enabled.map((e) => `<option value="${e.id}">${(e.sym ? e.sym + " " : "")}${esc(e.name)}</option>`).join("");
|
sel.innerHTML = enabled.map((e) => `<option value="${e.id}">${(e.sym ? e.sym + " " : "")}${esc(e.name)}</option>`).join("");
|
||||||
sel.value = d.current;
|
sel.value = d.current;
|
||||||
// unified checklist: drag handle / up-down to reorder; built-in get an
|
// unified checklist: drag a row by its handle to reorder; built-in get an
|
||||||
// enable toggle, custom get a remove ✕.
|
// enable toggle, custom get a remove ✕.
|
||||||
const list = document.getElementById("engineList");
|
const list = document.getElementById("engineList");
|
||||||
list.innerHTML = d.engines.map((e) => `<div class="eng" data-id="${e.id}">` +
|
list.innerHTML = d.engines.map((e) => `<div class="eng" data-id="${e.id}" draggable="true">` +
|
||||||
`<span class="mv"><button class="up" title="Move up">▲</button><button class="dn" title="Move down">▼</button></span>` +
|
`<span class="grip" title="Drag to reorder">⠿</span>` +
|
||||||
`<span class="eic">${engIcon(e)}</span><span class="enm">${esc(e.name)}</span>` +
|
`<span class="eic">${engIcon(e)}</span><span class="enm">${esc(e.name)}</span>` +
|
||||||
(e.builtin
|
(e.builtin
|
||||||
? `<label class="sw sm"><input type="checkbox" data-id="${e.id}" ${e.enabled ? "checked" : ""}><span class="track"><span class="knob"></span></span></label>`
|
? `<label class="sw sm"><input type="checkbox" data-id="${e.id}" ${e.enabled ? "checked" : ""}><span class="track"><span class="knob"></span></span></label>`
|
||||||
: `<button class="cx" data-id="${e.id}" title="Remove">✕</button>`) + `</div>`).join("");
|
: `<button class="cx" data-id="${e.id}" title="Remove">✕</button>`) + `</div>`).join("");
|
||||||
list.querySelectorAll('input[type="checkbox"]').forEach((cb) => cb.onchange = () => C.setEngineEnabled(cb.dataset.id, cb.checked).then(renderEngines));
|
list.querySelectorAll('input[type="checkbox"]').forEach((cb) => cb.onchange = () => C.setEngineEnabled(cb.dataset.id, cb.checked).then(renderEngines));
|
||||||
list.querySelectorAll(".cx").forEach((b) => b.onclick = () => C.removeEngine(b.dataset.id).then(renderEngines));
|
list.querySelectorAll(".cx").forEach((b) => b.onclick = () => C.removeEngine(b.dataset.id).then(renderEngines));
|
||||||
const move = (id, dir) => {
|
// drag-and-drop reorder
|
||||||
const ids = [...list.querySelectorAll(".eng")].map((el) => el.dataset.id);
|
let dragId = null;
|
||||||
const i = ids.indexOf(id), j = dir === "up" ? i - 1 : i + 1;
|
list.querySelectorAll(".eng").forEach((row) => {
|
||||||
if (j < 0 || j >= ids.length) return;
|
row.addEventListener("dragstart", (e) => { dragId = row.dataset.id; e.dataTransfer.effectAllowed = "move"; row.classList.add("dragging"); });
|
||||||
[ids[i], ids[j]] = [ids[j], ids[i]];
|
row.addEventListener("dragend", () => { row.classList.remove("dragging"); list.querySelectorAll(".eng").forEach((r) => r.classList.remove("over")); });
|
||||||
C.setEngineOrder(ids).then(renderEngines);
|
row.addEventListener("dragover", (e) => { e.preventDefault(); e.dataTransfer.dropEffect = "move"; if (row.dataset.id !== dragId) row.classList.add("over"); });
|
||||||
};
|
row.addEventListener("dragleave", () => row.classList.remove("over"));
|
||||||
list.querySelectorAll(".up").forEach((b) => b.onclick = () => move(b.closest(".eng").dataset.id, "up"));
|
row.addEventListener("drop", (e) => {
|
||||||
list.querySelectorAll(".dn").forEach((b) => b.onclick = () => move(b.closest(".eng").dataset.id, "down"));
|
e.preventDefault(); row.classList.remove("over");
|
||||||
|
if (!dragId || dragId === row.dataset.id) return;
|
||||||
|
const ids = [...list.querySelectorAll(".eng")].map((el) => el.dataset.id);
|
||||||
|
const from = ids.indexOf(dragId), to = ids.indexOf(row.dataset.id);
|
||||||
|
ids.splice(from, 1); ids.splice(to, 0, dragId);
|
||||||
|
C.setEngineOrder(ids).then(renderEngines);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
sel.onchange = () => C.set("searchEngine", sel.value);
|
sel.onchange = () => C.set("searchEngine", sel.value);
|
||||||
// appearance (theme)
|
// appearance (theme)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue