diff --git a/autoindex.css b/autoindex.css index 5e9c20b..6075c5a 100644 --- a/autoindex.css +++ b/autoindex.css @@ -24,6 +24,9 @@ table { border-spacing: 0; font-size: 1.2rem; } +table th { + cursor: pointer; +} table th, table td { padding: 0.5rem; } diff --git a/autoindex.js b/autoindex.js index 843db41..5bb86bf 100644 --- a/autoindex.js +++ b/autoindex.js @@ -2,6 +2,8 @@ const allLinks = [...document.getElementsByTagName('a')]; const bodyInner = document.querySelector('.inner'); const tableElem = document.querySelector('table'); const infoRegex = /(-thumb)?\.(jpg|nfo|srt)$/; +let infoFiles = 0; +let infoFilesAccounted = 0; const arrow = ` { const element = findByHref(infoFile.replace(infoRegex, '.' + current))[0]; return element ? element : last; @@ -100,6 +101,7 @@ function createOrImproveMovieMeta(original, thumbnail, nfo) { if (nfo) { createXMLRequest(reencodeURI(getHref(nfo))) .then((content) => { + infoFilesAccounted += 1; if (!content) { return; } @@ -127,6 +129,7 @@ function createOrImproveMovieMeta(original, thumbnail, nfo) { let title = titleEl.textContent if (episode && season) { title = `(S${season.textContent} E${episode.textContent}) ` + title; + original.parentElement.setAttribute('data-episode', episode.textContent); } movieTitle.innerText = title; @@ -164,10 +167,46 @@ function createOrImproveMovieMeta(original, thumbnail, nfo) { }); } }) - .catch((e) => console.error(e)); + .catch((e) => { + infoFilesAccounted += 1; + console.error(e); + }); } } +function waitUntilInfoComplete() { + return new Promise((resolve, reject) => { + if (infoFilesAccounted >= infoFiles) { + resolve(true); + return; + } + + let seconds = 0; + const accountWait = setInterval(() => { + if (infoFilesAccounted >= infoFiles || seconds > 5000) { + clearInterval(accountWait); + resolve(true); + return; + } + seconds += 500; + }, 500); + }); +} + +const getCellValue = (tr, idx) => + tr.children[idx].getAttribute('data-episode') + || tr.children[idx].innerText + || tr.children[idx].textContent; + +const comparer = (idx, asc) => (a, b) => ((v1, v2) => + v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v2) ? v1 - v2 : v1.toString().localeCompare(v2) + )(getCellValue(asc ? a : b, idx), getCellValue(asc ? b : a, idx)); + +const sortTableValues = (index) => + Array.from(tableElem.querySelectorAll('tr:nth-child(n+2):not(.btn-back)')) + .sort(comparer(index, this.asc = !this.asc)) + .forEach((tr) => tableElem.appendChild(tr)); + let tvShow; function accountForMetadata() { allLinks.forEach((link) => { @@ -202,6 +241,9 @@ function accountForMetadata() { findOriginal = findByInfoFile(url); } if (findOriginal) { + if (url.match(/.nfo$/)) { + infoFiles += 1; + } createOrImproveMovieMeta(findOriginal, url.match(/.jpg$/) ? link : undefined, url.match(/.nfo$/) ? link : undefined, @@ -213,6 +255,7 @@ function accountForMetadata() { link.innerHTML = arrow + 'Back (..)'; } }); + waitUntilInfoComplete().then(() => sortTableValues(0)); } function createToggleCheckbox(field, value, description) { @@ -248,3 +291,7 @@ if ('localStorage' in window) { } else { accountForMetadata(); } + +document.querySelectorAll('th').forEach((th) => th.addEventListener('click', (() => { + sortTableValues(Array.from(th.parentNode.children).indexOf(th)); +})));