From 9827c5f7315c4d25a2f909d1e53b7ffe13763435 Mon Sep 17 00:00:00 2001 From: "Alexander \"Arav\" Andreev" Date: Tue, 20 Sep 2022 03:39:42 +0400 Subject: [PATCH] Overlay was reworked from ground up. Now you can use prev and next buttons to go through media. Or use left and right arrow keys. Also ESC to close an overlay. --- web/assets/js/main.js | 244 ++++++++++++++++++++++++++---------------- 1 file changed, 149 insertions(+), 95 deletions(-) diff --git a/web/assets/js/main.js b/web/assets/js/main.js index 5c434b4..cc06519 100644 --- a/web/assets/js/main.js +++ b/web/assets/js/main.js @@ -5,143 +5,197 @@ const audio_formats = ["mp3", "flac", "opus", "ogg", "m4a"]; const image_formats = ["jpg", "jpeg", "gif", "png", "bmp", "webp"]; const overlay = document.getElementById("overlay"); -let g_scale = 1; +const overlay_content = overlay.children[1].firstChild; +const overlay_label = overlay.children[1].lastChild; + +let g_scale = 1; + +let g_current_row = null; +const g_first_row = document.getElementsByTagName("tbody")[0].firstChild; +const g_last_row = document.getElementsByTagName("tbody")[0].lastChild; + + +const file_links = Array.from(document.getElementsByTagName("tbody")[0].children) + .filter(e => e.lastChild.innerHTML != "DIR").map(l => l.firstChild.firstChild); + if (localStorage.getItem('audio_volume') == null) - localStorage['audio_volume'] = 0.5; + localStorage['audio_volume'] = 0.5; -function mousescroll(e) { - e.preventDefault(); - g_scale = Math.min(Math.max(0.25, g_scale + (e.deltaY * -0.001)), 4); - e.target.style.transform = `scale(${g_scale})`; +overlay.addEventListener("mouseup", e => { + if (e.target.tagName !== "DIV") return; + if (e.button === 0) { + overlay_content.children[0].remove(); + overlay.style.visibility = "hidden"; + g_scale = 1; } }); + + +function determine_media_element(path) { + path = path.toLowerCase(); + if (video_formats.some(ext => path.endsWith(ext))) + return "video"; + else if (audio_formats.some(ext => path.endsWith(ext))) + return "audio"; + else if (image_formats.some(ext => path.endsWith(ext))) + return "img"; + return undefined; } -function onvolumechange(e) { - localStorage['audio_volume'] = e.target.volume; +function send_to_overlay(pathname, media_type_element) { + if (media_type_element === undefined) + return false; + if (overlay_content.children.length != 0) + overlay_content.children[0].remove(); + + const media_element = document.createElement(media_type_element); + media_element.src = pathname; + + overlay_label.textContent = decodeURI(pathname.substr(pathname.lastIndexOf("/") + 1)); + + if (media_type_element !== "audio") { + media_element.addEventListener("wheel", e => { + e.preventDefault(); + g_scale = Math.min(Math.max(0.25, g_scale + (e.deltaY * -0.001)), 4); + e.target.style.transform = `scale(${g_scale})`; }); + } + if (media_type_element !== "img") { + media_element.autoplay = media_element.controls = true; + media_element.addEventListener("volumechange", e => { + localStorage['audio_volume'] = e.target.volume; }); + media_element.volume = localStorage["audio_volume"]; + } + + overlay_content.appendChild(media_element); + overlay.style.visibility = "visible"; + + return true; } -const ext_filter = (ext, pathname) => pathname.toLowerCase().endsWith(ext); -function to_overlay(eltyp, pathname) { - const el = document.createElement(eltyp); - const el_label = document.createElement("span"); - el_label.textContent = decodeURI(pathname.substr(pathname.lastIndexOf("/") + 1)); - if (eltyp !== "audio") el.addEventListener('wheel', mousescroll); - if (eltyp !== "img") { - el.autoplay = el.controls = true; - el.addEventListener("volumechange", onvolumechange); - el.volume = localStorage['audio_volume']; - } - el.src = pathname; - overlay.appendChild(el); - overlay.appendChild(el_label); - overlay.style.visibility = "visible"; -} +const [b_prev, b_next] = overlay.getElementsByTagName("button"); -document.getElementById("overlay").addEventListener("click", e => { - e.target.firstChild.remove(); - e.target.firstChild.remove(); - e.target.style.visibility = "hidden"; - g_scale = 1; +b_prev.addEventListener("click", e => { + do { + if (g_current_row.previousSibling === null) + g_current_row = g_last_row; + else + g_current_row = g_current_row.previousSibling; + } while (!send_to_overlay(g_current_row.firstChild.firstChild.pathname, + determine_media_element(g_current_row.firstChild.firstChild.pathname))); + e.preventDefault(); }); -const file_links = Array.from(document.getElementsByTagName('tr')).slice(2) - .filter(e => e.lastChild.innerHTML != "DIR").map(l => l.firstChild.firstChild); +b_next.addEventListener("click", () => { + do { + if (g_current_row.nextSibling === null) + g_current_row = g_first_row; + else + g_current_row = g_current_row.nextSibling; + } while (!send_to_overlay(g_current_row.firstChild.firstChild.pathname, + determine_media_element(g_current_row.firstChild.firstChild.pathname))); +}); -file_links.forEach(f => f.addEventListener('click', e => { - const pathname = e.target.pathname; - if (video_formats.some(ext => ext_filter(ext, pathname))) - to_overlay("video", pathname); - else if (audio_formats.some(ext => ext_filter(ext, pathname))) - to_overlay("audio", pathname); - else if (image_formats.some(ext => ext_filter(ext, pathname))) - to_overlay("img", pathname); - if (overlay.firstChild != null) - e.preventDefault(); -})); +window.addEventListener("keydown", e => { + if (overlay.style.visibility === "hidden" || e.isComposing) + return; + if (e.code === "ArrowLeft") + b_prev.click(); + else if (e.code === "ArrowRight") + b_next.click(); + else if (e.code === "Escape") + overlay_close(); +}); + + +for (let i = 0; i < file_links.length; ++i) + file_links[i].addEventListener("click", e => { + g_current_row = e.target.parentNode.parentNode; + if (send_to_overlay(e.target.pathname, determine_media_element(e.target.pathname))) + e.preventDefault(); + }); //// SORT BY COLUMN const [thead_name, thead_date, thead_size] = document.getElementsByTagName('thead')[0] - .children[0].children; + .children[0].children; const tbody = document.getElementsByTagName('tbody')[0]; let g_sort_reverse = false; thead_name.classList.toggle("clickable"); thead_name.addEventListener('click', e => { - e.preventDefault(); - sortTable((a,b) => { - const a_name = a.children[0].textContent.toLowerCase(); - const b_name = b.children[0].textContent.toLowerCase(); - return a_name < b_name ? -1 : a_name > b_name ? 1 : 0; - }, null, null, thead_name, [thead_date, thead_size]); + e.preventDefault(); + sortTable((a,b) => { + const a_name = a.children[0].textContent.toLowerCase(); + const b_name = b.children[0].textContent.toLowerCase(); + return a_name < b_name ? -1 : a_name > b_name ? 1 : 0; + }, null, null, thead_name, [thead_date, thead_size]); }); thead_date.classList.toggle("clickable"); thead_date.addEventListener('click', e => { - e.preventDefault(); - sortTable((a,b) => { - const a_date = new Date(a.children[1].textContent.slice(0, -4)); - const b_date = new Date(b.children[1].textContent.slice(0, -4)); - return a_date - b_date; - }, null, null, thead_date, [thead_name, thead_size]); + e.preventDefault(); + sortTable((a,b) => { + const a_date = new Date(a.children[1].textContent.slice(0, -4)); + const b_date = new Date(b.children[1].textContent.slice(0, -4)); + return a_date - b_date; + }, null, null, thead_date, [thead_name, thead_size]); }); const units = {"B": 0, "KiB": 1, "MiB": 2, "GiB": 3, "TiB": 4}; function sizeToBytes(size, unit) { - if (units[unit] == 0) return size; - for (let i = 0; i <= units[unit]; ++i) size *= 1024; - return size; + if (units[unit] == 0) return size; + for (let i = 0; i <= units[unit]; ++i) size *= 1024; + return size; } thead_size.classList.toggle("clickable"); thead_size.addEventListener('click', e => { - e.preventDefault(); - sortTable( - (a,b) => { - if (a.textContent == "DIR") - return 1; - let [a_size, a_unit] = a.children[2].textContent.split(" "); - let [b_size, b_unit] = b.children[2].textContent.split(" "); - return sizeToBytes(+a_size, a_unit) - sizeToBytes(+b_size, b_unit); - }, - e => e.children[2].textContent == "DIR", - e => e.children[2].textContent != "DIR", - thead_size, [thead_name, thead_date]); + e.preventDefault(); + sortTable( + (a,b) => { + if (a.textContent == "DIR") + return 1; + let [a_size, a_unit] = a.children[2].textContent.split(" "); + let [b_size, b_unit] = b.children[2].textContent.split(" "); + return sizeToBytes(+a_size, a_unit) - sizeToBytes(+b_size, b_unit); + }, + e => e.children[2].textContent == "DIR", + e => e.children[2].textContent != "DIR", + thead_size, [thead_name, thead_date]); }); function sortTable(compareFn, filterFn, filterNegFn, target, other) { - let records = Array.from(document.getElementsByTagName('tbody')[0].children); + let records = Array.from(document.getElementsByTagName('tbody')[0].children); - let dirs = []; - if (filterFn != null) { - dirs = records.filter(filterFn); - records = records.filter(filterNegFn); - } + let dirs = []; + if (filterFn != null) { + dirs = records.filter(filterFn); + records = records.filter(filterNegFn); + } - records.sort(compareFn); + records.sort(compareFn); - tbody.textContent = ""; + tbody.textContent = ""; - other.forEach(v => { - v.classList.remove("sort-up"); - v.classList.remove("sort-down"); - }); + other.forEach(v => { + v.classList.remove("sort-up"); + v.classList.remove("sort-down"); + }); - if (filterFn != null) - tbody.append(...dirs); + if (filterFn != null) + tbody.append(...dirs); - if (g_sort_reverse) { - tbody.append(...records.reverse()); - target.classList.add("sort-up"); - target.classList.remove("sort-down"); - } else { - tbody.append(...records); - target.classList.add("sort-down"); - target.classList.remove("sort-up"); - } - - g_sort_reverse = !g_sort_reverse; + if (g_sort_reverse) { + tbody.append(...records.reverse()); + target.classList.add("sort-up"); + target.classList.remove("sort-down"); + } else { + tbody.append(...records); + target.classList.add("sort-down"); + target.classList.remove("sort-up"); + } + + g_sort_reverse = !g_sort_reverse; } \ No newline at end of file