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