Simon Bruder
ccc0d60d71
This shows stripes correctly even after a filter has been entered. Previously the absolute position (before filtering) has been used to determine the row colour, which looked weird.
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('tr:not(:first-child)'))
|
|
|
|
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)
|
|
})
|
|
})
|