Simon Bruder
0d9ec3383e
This fixes a regression introduced in
77eab2497a
, which moved the heading into a
thead and the file listing into a tbody. Therefore, the .. entry is now
the first entry and has been excluded by the rule that previously
excluded the header.
92 lines
2.9 KiB
JavaScript
92 lines
2.9 KiB
JavaScript
document.addEventListener('DOMContentLoaded', () => {
|
|
function humanFileSize(bytes) {
|
|
const thresh = 1024
|
|
if(Math.abs(bytes) < thresh) {
|
|
return bytes + ' B'
|
|
}
|
|
const units = ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB']
|
|
var u = -1
|
|
do {
|
|
bytes /= thresh
|
|
++u
|
|
} while(Math.abs(bytes) >= thresh && u < units.length - 1)
|
|
return bytes.toFixed(1)+' '+units[u]
|
|
}
|
|
|
|
|
|
function textToA(line) {
|
|
let outerElement = document.createElement('div')
|
|
outerElement.innerHTML = line
|
|
return outerElement.getElementsByTagName('a')[0]
|
|
}
|
|
|
|
function parseLine(line) {
|
|
const href = textToA(line).href
|
|
const filename = href.substr(-1) === '/' ? decodeURIComponent(href.split('/').slice(-2, -1)[0]) : decodeURIComponent(href.split('/').pop())
|
|
const size = line.split(' ').pop()
|
|
return {
|
|
href: href,
|
|
filename: filename,
|
|
size: size
|
|
}
|
|
}
|
|
|
|
function processLine(line) {
|
|
meta = parseLine(line)
|
|
return `<tr><td><a href="${meta.href}">${meta.filename}</a></td><td>${meta.size === '-' ? '-' : humanFileSize(meta.size)}</td></tr>`
|
|
}
|
|
|
|
function addZebraStripes(rows) {
|
|
// this should be done in CSS, but AFAIU it does not support limiting
|
|
// :nth-child to elements matching a previous :not selector
|
|
rows.forEach((row, idx) => {
|
|
if (idx % 2 === 0) {
|
|
row.classList.add("zebra-stripe")
|
|
} else {
|
|
row.classList.remove("zebra-stripe")
|
|
}
|
|
})
|
|
}
|
|
|
|
const collator = new Intl.Collator('kn', {numeric: true})
|
|
|
|
// transform plain text to table
|
|
document.querySelector('pre').outerHTML = '<table><thead><tr><th>Name</th><th>Size</th></tr></thead><tbody><tr><td><a href="..">..</a></td><td>-</td></tr>' + document.querySelector('pre').innerHTML
|
|
.split('\n')
|
|
.filter(line => line !== '')
|
|
.filter(line => line !== '<a href="../">../</a>')
|
|
.map(processLine)
|
|
.sort(collator.compare)
|
|
.join('\n') + '</tbody></table>'
|
|
|
|
let searchField = document.createElement('input')
|
|
searchField.id = 'search-field'
|
|
searchField.autofocus = true
|
|
document.querySelector('body').insertBefore(searchField, document.querySelector('table'))
|
|
|
|
const rows = Array.from(document.querySelectorAll('tbody tr'))
|
|
|
|
addZebraStripes(rows)
|
|
|
|
document.querySelector('#search-field').addEventListener("input", e => {
|
|
const searchValue = e.target.value.toLowerCase()
|
|
rows.forEach(row => {
|
|
const file = row.querySelector('td:nth-child(1) a').innerText
|
|
if (!file.toLowerCase().includes(searchValue)) {
|
|
row.classList.add("hidden")
|
|
} else {
|
|
row.classList.remove("hidden")
|
|
}
|
|
})
|
|
|
|
const visibleRows = rows.filter(row => !row.classList.contains("hidden"))
|
|
if (visibleRows.length === 1) {
|
|
const target = visibleRows[0].querySelector('td a').href
|
|
if (target.substr(-1) === '/') {
|
|
window.location = target
|
|
}
|
|
}
|
|
addZebraStripes(visibleRows)
|
|
})
|
|
})
|