diff --git a/src/index.html b/src/index.html index 090ff55..4825341 100644 --- a/src/index.html +++ b/src/index.html @@ -200,16 +200,16 @@
- - - - @@ -264,15 +264,15 @@ 1.8.6
- - - diff --git a/src/js/contextmenu.js b/src/js/contextmenu.js index c3d75de..154bc37 100644 --- a/src/js/contextmenu.js +++ b/src/js/contextmenu.js @@ -271,13 +271,13 @@ function setupQueueContextMenu() { ui.queueList.addEventListener( "contextmenu", (e) => { - const row = getClosestRow(e.target); + const row = e.target.closest("tr"); if (!row) return; e.preventDefault(); e.stopPropagation(); - const idx = getRowIndex(row, DATA_ATTRS.INDEX); + const idx = parseInt(row.getAttribute(DATA_ATTRS.INDEX)); if (!selectionManager.isSelected(idx)) { selectionManager.select(idx); } diff --git a/src/js/draggable.js b/src/js/draggable.js index a85c1cc..140ecb4 100644 --- a/src/js/draggable.js +++ b/src/js/draggable.js @@ -8,16 +8,16 @@ function setupDragAndDrop() { let lastDragOverRow = null; ui.queueList.addEventListener("dragstart", (e) => { - const row = getClosestRow(e.target); + const row = e.target.closest("tr"); if ( !row || row.classList.contains(CLASSES.DRAGGING) || - selectionManager.isSelected(getRowIndex(row, DATA_ATTRS.INDEX)) + selectionManager.isSelected(parseInt(row.getAttribute(DATA_ATTRS.INDEX))) ) return; selectionManager.clear(); - selectionManager.select(getRowIndex(row, DATA_ATTRS.INDEX)); + selectionManager.select(parseInt(row.getAttribute(DATA_ATTRS.INDEX))); updateRowClass( ui.queueList, selectionManager.getSelected(), @@ -32,7 +32,7 @@ function setupDragAndDrop() { ui.queueList.addEventListener("dragover", (e) => { e.preventDefault(); e.dataTransfer.dropEffect = "move"; - const row = getClosestRow(e.target); + const row = e.target.closest("tr"); if (!row || row.classList.contains(CLASSES.DRAGGING)) return; const isBelow = isDropBelowCenter(e, row); @@ -65,7 +65,7 @@ function setupDragAndDrop() { // handle drop and complete the move ui.queueList.addEventListener("drop", (e) => { e.preventDefault(); - const row = getClosestRow(e.target); + const row = e.target.closest("tr"); if (!row || row.classList.contains(CLASSES.DRAGGING)) return; if (lastDragOverRow) { @@ -78,7 +78,7 @@ function setupDragAndDrop() { } clearRowClasses(ui.queueList, "tr", CLASSES.DRAGGING); - const draggedIdx = getRowIndex(row, DATA_ATTRS.INDEX); + const draggedIdx = parseInt(row.getAttribute(DATA_ATTRS.INDEX)); moveQueueItems( state.queue, selectionManager.getSelected(), diff --git a/src/js/events.js b/src/js/events.js index 0482860..bdf8258 100644 --- a/src/js/events.js +++ b/src/js/events.js @@ -79,7 +79,8 @@ document.addEventListener("DOMContentLoaded", async () => { ui.player.addEventListener("play", () => { if ( state.settings.scrobbling && - isValidQueueIndex(state.queueIndex, state.queue.length) + state.queueIndex >= 0 && + state.queueIndex < state.queue.length ) { const songId = state.queue[state.queueIndex]?.id; if (songId && songId !== lastScrobbledSongId) { @@ -125,9 +126,9 @@ document.addEventListener("DOMContentLoaded", async () => { const btn = e.target.closest("button"); if (!btn) { // handle row selection on click - const row = getClosestRow(e.target); + const row = e.target.closest("tr"); if (row) { - const idx = getRowIndex(row, DATA_ATTRS.INDEX); + const idx = parseInt(row.getAttribute(DATA_ATTRS.INDEX)); selectionManager.select(idx, { multi: e.ctrlKey || e.metaKey, shift: e.shiftKey, @@ -136,7 +137,7 @@ document.addEventListener("DOMContentLoaded", async () => { return; } - const idx = getRowIndex(getClosestRow(btn), DATA_ATTRS.INDEX); + const idx = parseInt(e.target.closest("tr").getAttribute(DATA_ATTRS.INDEX)); for (const [className, handler] of Object.entries(QUEUE_BUTTON_HANDLERS)) { if (btn.classList.contains(className)) { handler(idx); @@ -147,9 +148,9 @@ document.addEventListener("DOMContentLoaded", async () => { // double-click to play ui.queueList.addEventListener("dblclick", (e) => { - const row = getClosestRow(e.target); + const row = e.target.closest("tr"); if (row) { - const idx = getRowIndex(row, DATA_ATTRS.INDEX); + const idx = parseInt(row.getAttribute(DATA_ATTRS.INDEX)); playQueueTrack(idx); selectionManager.clear(); updateQueue(); diff --git a/src/js/player.js b/src/js/player.js index 77c8987..ee7d4e7 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -97,7 +97,7 @@ const togglePlayback = () => { // check if queue has a valid current track const hasValidTrack = () => - isValidQueueIndex(state.queueIndex, state.queue.length); + state.queueIndex >= 0 && state.queueIndex < state.queue.length; // helper to play a track at given queue index const playQueueTrack = (idx) => { @@ -161,7 +161,8 @@ function clearPlayerUI() { // move to next track when current song ends function handleTrackEnd() { if ( - isValidQueueIndex(state.queueIndex, state.queue.length) && + state.queueIndex >= 0 && + state.queueIndex < state.queue.length && state.settings.scrobbling ) { state.api.scrobble(state.queue[state.queueIndex].id).catch(() => {}); diff --git a/src/js/queue.js b/src/js/queue.js index 5013e95..0f8a491 100644 --- a/src/js/queue.js +++ b/src/js/queue.js @@ -186,7 +186,7 @@ async function loadQueue() { if (!Array.isArray(songs) || songs.length === 0) return false; state.queue = songs; - if (isValidQueueIndex(queueIndex, state.queue.length)) { + if (queueIndex >= 0 && queueIndex < state.queue.length) { state.queueIndex = queueIndex; } return true; diff --git a/src/js/ui.js b/src/js/ui.js index 346aa25..23f4cb6 100644 --- a/src/js/ui.js +++ b/src/js/ui.js @@ -25,11 +25,10 @@ function createElement(tag, config = {}) { } // create a button with icon -function createIconButton(className, ariaLabel, iconPath, onCallback) { +function createIconButton(className, alt, iconPath, onCallback) { const btn = createElement("button", { className, - attributes: { "aria-label": ariaLabel }, - children: [createElement("img", { attributes: { src: iconPath } })], + children: [createElement("img", { attributes: { src: iconPath, alt } })], }); if (onCallback) { @@ -47,11 +46,6 @@ function createIconButton(className, ariaLabel, iconPath, onCallback) { return btn; } -// find closest row element -function getClosestRow(el, rowSelector = "tr") { - return el.closest(rowSelector); -} - // format seconds as mm:ss string function formatDuration(seconds) { if (!seconds || !Number.isFinite(seconds)) return "0:00"; @@ -61,11 +55,6 @@ function formatDuration(seconds) { .padStart(2, "0")}`; } -// get row index from data attribute -function getRowIndex(rowEl, attrName = "data-index") { - return parseInt(rowEl.getAttribute(attrName)); -} - // remove classes from only elements that have them function clearRowClasses(container, rowSelector, classNames) { const classes = Array.isArray(classNames) ? classNames : [classNames]; @@ -78,12 +67,7 @@ function clearRowClasses(container, rowSelector, classNames) { function updateRowClass(container, indices, className, add = true) { const indexSet = new Set(indices); container.querySelectorAll("tr").forEach((row) => { - const idx = getRowIndex(row); + const idx = parseInt(row.getAttribute("data-index")); row.classList.toggle(className, indexSet.has(idx) === add); }); } - -// validate queue index -function isValidQueueIndex(index, queueLength) { - return index >= 0 && index < queueLength; -}