2017-05-16 12:23:17 -07:00
|
|
|
{
|
|
|
|
|
function fixTable() {
|
|
|
|
|
const table = document.querySelector('table');
|
2014-12-09 10:13:45 -08:00
|
|
|
|
|
|
|
|
// Remove <hr>s
|
2017-05-16 12:23:17 -07:00
|
|
|
Array.from(table.querySelectorAll('hr')).forEach(({ parentNode }) => {
|
|
|
|
|
const row = parentNode.parentNode;
|
2014-12-09 10:13:45 -08:00
|
|
|
row.parentNode.removeChild(row);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Make a table head.
|
2017-05-16 12:23:17 -07:00
|
|
|
const thead = document.createElement('thead');
|
|
|
|
|
const firstRow = table.querySelector('tr');
|
2014-12-09 10:13:45 -08:00
|
|
|
firstRow.parentNode.removeChild(firstRow);
|
|
|
|
|
thead.appendChild(firstRow);
|
|
|
|
|
table.insertBefore(thead, table.firstElementChild);
|
|
|
|
|
|
2014-12-09 13:52:21 -08:00
|
|
|
// Remove the first column and put the image in the next.
|
2017-05-16 12:23:17 -07:00
|
|
|
const rows = Array.from(table.querySelectorAll('tr'));
|
|
|
|
|
rows.forEach((row) => {
|
|
|
|
|
const iconColumn = row.children[0];
|
|
|
|
|
const fileColumn = row.children[1];
|
2016-09-15 20:36:44 -07:00
|
|
|
|
|
|
|
|
// Remove icon column.
|
|
|
|
|
row.removeChild(iconColumn);
|
|
|
|
|
|
2017-05-16 12:23:17 -07:00
|
|
|
const image = iconColumn.firstElementChild;
|
2016-09-15 20:36:44 -07:00
|
|
|
|
|
|
|
|
if (!image) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Wrap icon in a div.img-wrap.
|
2017-05-16 12:23:17 -07:00
|
|
|
const div = document.createElement('div');
|
2014-12-09 13:52:21 -08:00
|
|
|
div.className = 'img-wrap';
|
2016-09-15 20:36:44 -07:00
|
|
|
div.appendChild(image);
|
|
|
|
|
|
|
|
|
|
// Insert icon before filename.
|
|
|
|
|
fileColumn.insertBefore(div, fileColumn.firstElementChild);
|
2014-12-09 10:13:45 -08:00
|
|
|
});
|
2017-05-16 12:23:17 -07:00
|
|
|
}
|
2014-12-09 10:13:45 -08:00
|
|
|
|
|
|
|
|
// Underscore string's titleize.
|
2017-05-16 12:23:17 -07:00
|
|
|
function titleize(str) {
|
2018-02-05 13:16:38 -08:00
|
|
|
return decodeURI(str).toLowerCase().replace(/(?:^|\s|-)\S/g, c => c.toUpperCase());
|
2017-05-16 12:23:17 -07:00
|
|
|
}
|
2014-12-09 10:13:45 -08:00
|
|
|
|
2017-05-16 12:23:17 -07:00
|
|
|
function addTitle() {
|
|
|
|
|
let path = window.location.pathname.replace(/\/$/g, '');
|
|
|
|
|
let titleText;
|
2014-12-09 10:13:45 -08:00
|
|
|
|
|
|
|
|
if (path) {
|
2017-05-16 12:23:17 -07:00
|
|
|
const parts = path.split('/');
|
2014-12-09 10:13:45 -08:00
|
|
|
path = parts[parts.length - 1];
|
2017-05-16 12:23:17 -07:00
|
|
|
titleText = titleize(path).replace(/-|_/g, ' ');
|
2014-12-09 10:13:45 -08:00
|
|
|
} else {
|
|
|
|
|
titleText = window.location.host;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-16 12:23:17 -07:00
|
|
|
titleText = `Index of ${titleText}`;
|
2014-12-09 10:13:45 -08:00
|
|
|
|
2017-05-16 12:23:17 -07:00
|
|
|
const container = document.createElement('div');
|
|
|
|
|
container.id = 'page-header';
|
|
|
|
|
const h1 = document.createElement('h1');
|
2014-12-09 10:13:45 -08:00
|
|
|
h1.appendChild(document.createTextNode(titleText));
|
2017-05-16 12:23:17 -07:00
|
|
|
container.appendChild(h1);
|
|
|
|
|
|
|
|
|
|
document.body.insertBefore(container, document.body.firstChild);
|
2014-12-09 10:13:45 -08:00
|
|
|
document.title = titleText;
|
2017-05-16 12:23:17 -07:00
|
|
|
}
|
2014-12-09 10:13:45 -08:00
|
|
|
|
2017-05-16 12:23:17 -07:00
|
|
|
function getTimeSince(seconds) {
|
|
|
|
|
let intervalType;
|
2014-12-09 10:13:45 -08:00
|
|
|
|
2017-05-16 12:23:17 -07:00
|
|
|
let interval = Math.floor(seconds / 31536000);
|
2014-12-09 10:13:45 -08:00
|
|
|
if (interval >= 1) {
|
|
|
|
|
intervalType = 'year';
|
|
|
|
|
} else {
|
|
|
|
|
interval = Math.floor(seconds / 2592000);
|
|
|
|
|
if (interval >= 1) {
|
|
|
|
|
intervalType = 'month';
|
|
|
|
|
} else {
|
|
|
|
|
interval = Math.floor(seconds / 86400);
|
|
|
|
|
if (interval >= 1) {
|
|
|
|
|
intervalType = 'day';
|
|
|
|
|
} else {
|
|
|
|
|
interval = Math.floor(seconds / 3600);
|
|
|
|
|
if (interval >= 1) {
|
|
|
|
|
intervalType = 'hour';
|
|
|
|
|
} else {
|
|
|
|
|
interval = Math.floor(seconds / 60);
|
|
|
|
|
if (interval >= 1) {
|
|
|
|
|
intervalType = 'minute';
|
|
|
|
|
} else {
|
|
|
|
|
interval = seconds;
|
|
|
|
|
intervalType = 'second';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (interval > 1 || interval === 0) {
|
|
|
|
|
intervalType += 's';
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-16 12:23:17 -07:00
|
|
|
return `${interval} ${intervalType}`;
|
|
|
|
|
}
|
2014-12-09 10:13:45 -08:00
|
|
|
|
2017-05-16 12:23:17 -07:00
|
|
|
function fixTime() {
|
|
|
|
|
const dates = Array.from(document.querySelectorAll('.indexcollastmod'));
|
|
|
|
|
const now = new Date();
|
|
|
|
|
dates.forEach((date, i) => {
|
|
|
|
|
const stamp = date.textContent.trim();
|
2014-12-09 10:13:45 -08:00
|
|
|
if (!stamp || i === 0) return;
|
|
|
|
|
|
2014-12-09 13:52:21 -08:00
|
|
|
// 2014-12-09 10:43 -> 2014, 11, 09, 10, 43, 0.
|
2017-05-16 12:23:17 -07:00
|
|
|
const parts = stamp.split(' ');
|
|
|
|
|
const day = parts[0].split('-');
|
|
|
|
|
const timeOfDay = parts[1].split(':');
|
|
|
|
|
const year = parseInt(day[0], 10);
|
|
|
|
|
const month = parseInt(day[1], 10) - 1;
|
|
|
|
|
const _day = parseInt(day[2], 10);
|
|
|
|
|
const hour = parseInt(timeOfDay[0], 10);
|
|
|
|
|
const minutes = parseInt(timeOfDay[1], 10);
|
|
|
|
|
|
|
|
|
|
const time = new Date(year, month, _day, hour, minutes, 0);
|
|
|
|
|
const difference = Math.round((now.getTime() - time.getTime()) / 1000);
|
|
|
|
|
date.textContent = `${getTimeSince(difference)} ago`;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function addSearch() {
|
|
|
|
|
const input = document.createElement('input');
|
|
|
|
|
input.type = 'search';
|
|
|
|
|
input.id = 'search';
|
|
|
|
|
input.setAttribute('placeholder', 'Search');
|
|
|
|
|
document.getElementById('page-header').appendChild(input);
|
|
|
|
|
|
|
|
|
|
const sortColumns = Array.from(document.querySelectorAll('thead a'));
|
|
|
|
|
const nameColumns = Array.from(document.querySelectorAll('tbody .indexcolname'));
|
|
|
|
|
const rows = nameColumns.map(({ parentNode }) => parentNode);
|
|
|
|
|
const fileNames = nameColumns.map(({ textContent }) => textContent);
|
|
|
|
|
|
|
|
|
|
function filter(value) {
|
|
|
|
|
// Allow tabbing out of the search input and skipping the sort links
|
|
|
|
|
// when there is a search value.
|
|
|
|
|
sortColumns.forEach((link) => {
|
|
|
|
|
if (value) {
|
|
|
|
|
link.tabIndex = -1;
|
|
|
|
|
} else {
|
|
|
|
|
link.removeAttribute('tabIndex');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Test the input against the file/folder name.
|
|
|
|
|
let even = false;
|
|
|
|
|
fileNames.forEach((name, i) => {
|
|
|
|
|
if (!value || name.toLowerCase().includes(value.toLowerCase())) {
|
|
|
|
|
const className = even ? 'even' : '';
|
|
|
|
|
rows[i].className = className;
|
|
|
|
|
even = !even;
|
|
|
|
|
} else {
|
|
|
|
|
rows[i].className = 'hidden';
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
document.getElementById('search').addEventListener('input', ({ target }) => {
|
|
|
|
|
filter(target.value);
|
2014-12-09 10:13:45 -08:00
|
|
|
});
|
2017-05-16 12:23:17 -07:00
|
|
|
|
|
|
|
|
filter('');
|
|
|
|
|
}
|
2014-12-09 10:13:45 -08:00
|
|
|
|
|
|
|
|
fixTable();
|
|
|
|
|
addTitle();
|
|
|
|
|
fixTime();
|
2017-05-16 12:23:17 -07:00
|
|
|
addSearch();
|
|
|
|
|
}
|