609 lines
19 KiB
JavaScript

let searchBar = document.getElementById("searchBar");
let pathBar = document.getElementById("pathBar");
let scroll_id = null;
let docCount = 0;
let searchQueued = false;
let coolingDown = false;
let selectedDirs = [];
function toggleSearchBar() {
searchQueued = true;
}
let tree = new InspireTree({
selection: {
mode: 'checkbox'
},
data: mimeMap
});
new InspireTreeDOM(tree, {
target: '.tree'
});
//Select all
tree.select();
tree.node("any").deselect();
tree.on("node.click", function (event, node, handler) {
event.preventTreeDefault();
if (node.id === "any") {
if (!node.itree.state.checked) {
tree.deselect();
}
} else {
tree.node("any").deselect();
}
handler();
searchQueued = true;
});
new autoComplete({
selector: '#pathBar',
minChars: 1,
delay: 75,
renderItem: function (item) {
return '<div class="autocomplete-suggestion" data-val="' + item + '">' + item + '</div>';
},
source: async function (term, suggest) {
term = term.toLowerCase();
const choices = await getPathChoices();
let matches = [];
for (let i = 0; i < choices.length; i++) {
if (~choices[i].toLowerCase().indexOf(term)) {
matches.push(choices[i]);
}
}
suggest(matches);
},
onSelect: function () {
searchQueued = true;
}
});
function makeStatsCard(searchResult) {
let statsCard = document.createElement("div");
statsCard.setAttribute("class", "card");
let statsCardBody = document.createElement("div");
statsCardBody.setAttribute("class", "card-body");
let stat = document.createElement("p");
const totalHits = searchResult["hits"]["total"].hasOwnProperty("value")
? searchResult["hits"]["total"]["value"] : searchResult["hits"]["total"];
stat.appendChild(document.createTextNode(totalHits + " results in " + searchResult["took"] + "ms"));
let sizeStat = document.createElement("span");
sizeStat.appendChild(document.createTextNode(humanFileSize(searchResult["aggregations"]["total_size"]["value"])));
statsCardBody.appendChild(stat);
statsCardBody.appendChild(sizeStat);
statsCard.appendChild(statsCardBody);
return statsCard;
}
function makeResultContainer() {
let resultContainer = document.createElement("div");
resultContainer.setAttribute("class", "card-columns");
return resultContainer;
}
/**
* https://stackoverflow.com/questions/10420352
*/
function humanFileSize(bytes) {
if (bytes === 0) {
return "? B"
}
let thresh = 1000;
if (Math.abs(bytes) < thresh) {
return bytes + ' B';
}
let units = ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
let u = -1;
do {
bytes /= thresh;
++u;
} while (Math.abs(bytes) >= thresh && u < units.length - 1);
return bytes.toFixed(1) + ' ' + units[u];
}
/**
* https://stackoverflow.com/questions/6312993
*/
function humanTime(sec_num) {
sec_num = Math.floor(sec_num);
let hours = Math.floor(sec_num / 3600);
let minutes = Math.floor((sec_num - (hours * 3600)) / 60);
let seconds = sec_num - (hours * 3600) - (minutes * 60);
if (hours < 10) {
hours = "0" + hours;
}
if (minutes < 10) {
minutes = "0" + minutes;
}
if (seconds < 10) {
seconds = "0" + seconds;
}
return hours + ":" + minutes + ":" + seconds;
}
function initPopover() {
$('[data-toggle="popover"]').popover({
trigger: "focus",
delay: {"show": 0, "hide": 100},
placement: "bottom",
html: true
});
}
/**
* Enable gif loading on hover
* @param thumbnail
* @param documentId
*/
function gifOver(thumbnail, documentId) {
let callee = arguments.callee;
thumbnail.addEventListener("mouseover", function () {
thumbnail.mouseStayedOver = true;
window.setTimeout(function () {
if (thumbnail.mouseStayedOver) {
thumbnail.removeEventListener('mouseover', callee, false);
//Load gif
thumbnail.setAttribute("src", "/file/" + documentId);
}
}, 750);
});
thumbnail.addEventListener("mouseout", function () {
//Reset timer
thumbnail.mouseStayedOver = false;
thumbnail.setAttribute("src", "/thumb/" + documentId);
})
}
function downloadPopover(element, documentId) {
element.setAttribute("data-content",
'<a class="btn btn-sm btn-primary" href="/dl/' + documentId + '"><i class="fas fa-download"></i> Download</a>' +
'<a class="btn btn-sm btn-success" style="margin-left:3px;" href="/file/' + documentId + '" target="_blank"><i class="fas fa-eye"></i> View</a>');
element.setAttribute("data-toggle", "popover");
element.addEventListener("mouseover", function () {
element.focus();
});
}
/**
*
* @param hit
* @returns {Element}
*/
function createDocCard(hit) {
let docCard = document.createElement("div");
docCard.setAttribute("class", "card");
docCard.setAttribute("tabindex", "-1");
let docCardBody = document.createElement("div");
docCardBody.setAttribute("class", "card-body document");
let link = document.createElement("a");
link.setAttribute("href", "/document/" + hit["_id"]);
link.setAttribute("target", "_blank");
//Title
let title = document.createElement("p");
title.setAttribute("class", "file-title");
let extension = hit["_source"].hasOwnProperty("extension") && hit["_source"]["extension"] !== "" ? "." + hit["_source"]["extension"] : "";
if (hit.hasOwnProperty("highlight") && hit["highlight"].hasOwnProperty("name")) {
title.insertAdjacentHTML('afterbegin', hit["highlight"]["name"] + extension);
} else if (hit.hasOwnProperty("highlight") && hit["highlight"].hasOwnProperty("name.nGram")) {
title.insertAdjacentHTML('afterbegin', hit["highlight"]["name.nGram"] + extension);
} else {
title.appendChild(document.createTextNode(hit["_source"]["name"] + extension));
}
title.setAttribute("title", hit["_source"]["path"] + "/" + hit["_source"]["name"] + extension);
docCard.appendChild(title);
let tagContainer = document.createElement("div");
tagContainer.setAttribute("class", "card-text");
if (hit["_source"].hasOwnProperty("mime") && hit["_source"]["mime"] !== null) {
let tags = [];
let thumbnail = null;
let thumbnailOverlay = null;
let imgWrapper = document.createElement("div");
imgWrapper.setAttribute("style", "position: relative");
let mimeCategory = hit["_source"]["mime"].split("/")[0];
//Thumbnail
switch (mimeCategory) {
case "video":
thumbnail = document.createElement("video");
let vidSource = document.createElement("source");
vidSource.setAttribute("src", "/file/" + hit["_id"]);
vidSource.setAttribute("type", "video/webm");
thumbnail.appendChild(vidSource);
thumbnail.setAttribute("class", "fit");
thumbnail.setAttribute("loop", "");
thumbnail.setAttribute("controls", "");
thumbnail.setAttribute("preload", "none");
thumbnail.setAttribute("poster", "/thumb/" + hit["_id"]);
thumbnail.addEventListener("dblclick", function () {
thumbnail.webkitRequestFullScreen();
});
break;
case "image":
thumbnail = document.createElement("img");
thumbnail.setAttribute("class", "card-img-top fit");
thumbnail.setAttribute("src", "/thumb/" + hit["_id"]);
break;
}
//Thumbnail overlay
switch (mimeCategory) {
case "image":
thumbnailOverlay = document.createElement("div");
thumbnailOverlay.setAttribute("class", "card-img-overlay");
//Resolution
let resolutionBadge = document.createElement("span");
resolutionBadge.setAttribute("class", "badge badge-resolution");
if (hit["_source"].hasOwnProperty("width")) {
resolutionBadge.appendChild(document.createTextNode(hit["_source"]["width"] + "x" + hit["_source"]["height"]));
}
thumbnailOverlay.appendChild(resolutionBadge);
var format = hit["_source"]["format_name"];
//Hover
if (format === "GIF") {
gifOver(thumbnail, hit["_id"]);
}
break;
case "video":
//Duration
if (hit["_source"].hasOwnProperty("duration")) {
thumbnailOverlay = document.createElement("div");
thumbnailOverlay.setAttribute("class", "card-img-overlay");
let durationBadge = document.createElement("span");
durationBadge.setAttribute("class", "badge badge-resolution");
durationBadge.appendChild(document.createTextNode(humanTime(hit["_source"]["duration"])));
thumbnailOverlay.appendChild(durationBadge);
}
}
//Tags
switch (mimeCategory) {
case "video":
if (hit["_source"].hasOwnProperty("format_long_name")) {
let formatTag = document.createElement("span");
formatTag.setAttribute("class", "badge badge-pill badge-video");
formatTag.appendChild(document.createTextNode(hit["_source"]["format_long_name"].replace(" ", "")));
tags.push(formatTag);
}
break;
case "image": {
if (format !== undefined) {
let formatTag = document.createElement("span");
formatTag.setAttribute("class", "badge badge-pill badge-image");
formatTag.appendChild(document.createTextNode(format));
tags.push(formatTag);
}
}
break;
case "audio": {
if (hit["_source"].hasOwnProperty("format_long_name")) {
let formatTag = document.createElement("span");
formatTag.setAttribute("class", "badge badge-pill badge-audio");
formatTag.appendChild(document.createTextNode(hit["_source"]["format_long_name"]));
tags.push(formatTag);
}
}
break;
case "text": {
let formatTag = document.createElement("span");
formatTag.setAttribute("class", "badge badge-pill badge-text");
formatTag.appendChild(document.createTextNode(hit["_source"]["encoding"]));
tags.push(formatTag);
}
break;
}
//Content
if (hit.hasOwnProperty("highlight") && hit["highlight"].hasOwnProperty("content")) {
let contentDiv = document.createElement("div");
contentDiv.setAttribute("class", "content-div bg-light");
contentDiv.insertAdjacentHTML('afterbegin', hit["highlight"]["content"][0]);
docCard.appendChild(contentDiv);
}
//Audio
if (mimeCategory === "audio" && hit["_source"].hasOwnProperty("format_long_name")) {
let audio = document.createElement("audio");
audio.setAttribute("preload", "none");
audio.setAttribute("class", "audio-fit fit");
audio.setAttribute("controls", "");
audio.setAttribute("type", hit["_source"]["mime"]);
audio.setAttribute("src", "file/" + hit["_id"]);
docCard.appendChild(audio)
}
if (thumbnail !== null) {
imgWrapper.appendChild(thumbnail);
docCard.appendChild(imgWrapper);
}
if (thumbnailOverlay !== null) {
imgWrapper.appendChild(thumbnailOverlay);
}
for (let i = 0; i < tags.length; i++) {
tagContainer.appendChild(tags[i]);
}
}
//Size tag
let sizeTag = document.createElement("small");
sizeTag.appendChild(document.createTextNode(humanFileSize(hit["_source"]["size"])));
sizeTag.setAttribute("class", "text-muted");
tagContainer.appendChild(sizeTag);
//Download button
downloadPopover(docCard, hit["_id"]);
docCardBody.appendChild(link);
docCard.appendChild(docCardBody);
link.appendChild(title);
docCardBody.appendChild(tagContainer);
return docCard;
}
function makePageIndicator(searchResult) {
let pageIndicator = document.createElement("div");
const totalHits = searchResult["hits"]["total"].hasOwnProperty("value")
? searchResult["hits"]["total"]["value"] : searchResult["hits"]["total"];
pageIndicator.appendChild(document.createTextNode(docCount + " / " + totalHits));
return pageIndicator;
}
function insertHits(resultContainer, hits) {
for (let i = 0; i < hits.length; i++) {
resultContainer.appendChild(createDocCard(hits[i]));
docCount++;
}
}
window.addEventListener("scroll", function () {
if (!coolingDown) {
let threshold = 350;
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight - threshold) {
//load next page
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
let searchResult = JSON.parse(this.responseText);
let searchResults = document.getElementById("searchResults");
let hits = searchResult["hits"]["hits"];
//Page indicator
let pageIndicator = makePageIndicator(searchResult);
searchResults.appendChild(pageIndicator);
//Result container
let resultContainer = makeResultContainer();
searchResults.appendChild(resultContainer);
insertHits(resultContainer, hits);
initPopover();
if (hits.length !== 0) {
coolingDown = false;
}
} else if (this.status === 500) {
window.location.reload()
}
};
xhttp.open("GET", "/scroll?scroll_id=" + scroll_id, true);
xhttp.send();
coolingDown = true;
}
}
});
function getSelectedMimeTypes() {
let mimeTypes = [];
let selected = tree.selected();
for (let i = 0; i < selected.length; i++) {
if (selected[i].id === "any") {
return "any"
}
//Only get children
if (selected[i].text.indexOf("(") !== -1) {
mimeTypes.push(selected[i].id);
}
}
return mimeTypes
}
function search() {
if (searchQueued === true) {
searchQueued = false;
//Clear old search results
let searchResults = document.getElementById("searchResults");
while (searchResults.firstChild) {
searchResults.removeChild(searchResults.firstChild);
}
let query = searchBar.value;
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
let searchResult = JSON.parse(this.responseText);
scroll_id = searchResult["_scroll_id"];
//Search stats
searchResults.appendChild(makeStatsCard(searchResult));
//Autocomplete
if (searchResult.hasOwnProperty("suggest") && searchResult["suggest"].hasOwnProperty("path")) {
pathAutoComplete = [];
for (let i = 0; i < searchResult["suggest"]["path"][0]["options"].length; i++) {
pathAutoComplete.push(searchResult["suggest"]["path"][0]["options"][i].text)
}
}
//Setup page
let resultContainer = makeResultContainer();
searchResults.appendChild(resultContainer);
//Insert search results (hits)
docCount = 0;
insertHits(resultContainer, searchResult["hits"]["hits"]);
//Initialise download/view button popover
initPopover();
}
};
xhttp.open("POST", "/search", true);
let postBody = {};
postBody.q = query;
postBody.size_min = size_min;
postBody.size_max = size_max;
postBody.mime_types = getSelectedMimeTypes();
postBody.must_match = document.getElementById("barToggle").checked;
postBody.directories = selectedDirs;
postBody.path = pathBar.value.replace(/\/$/, "").toLowerCase(); //remove trailing slashes
xhttp.setRequestHeader('content-type', 'application/json');
xhttp.send(JSON.stringify(postBody));
}
}
let pathAutoComplete = [];
let size_min = 0;
let size_max = 10000000000000;
searchBar.addEventListener("keyup", function () {
searchQueued = true;
});
//Size slider
$("#sizeSlider").ionRangeSlider({
type: "double",
grid: false,
force_edges: true,
min: 0,
max: 3684.03149864,
from: 0,
to: 3684.03149864,
min_interval: 5,
drag_interval: true,
prettify: function (num) {
if (num === 0) {
return "0 B"
} else if (num >= 3684) {
return humanFileSize(num * num * num) + "+";
}
return humanFileSize(num * num * num)
},
onChange: function (e) {
size_min = (e.from * e.from * e.from);
size_max = (e.to * e.to * e.to);
if (e.to >= 3684) {
size_max = 10000000000000;
}
searchQueued = true;
}
});
//Directories select
function updateDirectories() {
let selected = $('#directories').find('option:selected');
selectedDirs = [];
$(selected).each(function () {
selectedDirs.push(parseInt($(this).val()));
});
searchQueued = true;
}
document.getElementById("directories").addEventListener("change", updateDirectories);
updateDirectories();
searchQueued = false;
//Suggest
function getPathChoices() {
return new Promise(getPaths => {
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
getPaths(JSON.parse(xhttp.responseText))
}
};
xhttp.open("GET", "/suggest?prefix=" + pathBar.value, true);
xhttp.send();
});
}
document.getElementById("pathBar").addEventListener("keyup", function () {
searchQueued = true;
});
window.setInterval(search, 300);