// ###### Helper functions ###### // get query as string from form Element function getQueryStr(queryFormElement) { // gets query let queryFormData; let queryStr; queryFormData = new FormData(queryFormElement); queryStr = queryFormData.get("query-form-query"); return queryStr } // get display options from display options form element function getDisplayOptions(displayOptionsFormElement) { // gets display options parameters let displayOptionsFormData let displayOptionsData; displayOptionsFormData = new FormData(displayOptionsFormElement); displayOptionsData = {"resultsPerPage": displayOptionsFormData.get("display-options-form-results_per_page"), "resultsContex": displayOptionsFormData.get("display-options-form-result_context"), "expertMode": displayOptionsFormData.get("display-options-form-expert_mode")}; console.log(displayOptionsData); return displayOptionsData } // ###### Download results functions ###### // TODO: Maybe write these as class functions? For this maybe create a result class // function creates a unique and safe filename for the download function createDownloadFilename() { let today; let currentDate; let currentTime; let safeFilename; let resultFilename; // get and create metadata console.log("Create Metadata!"); today = new Date(); currentDate = today.getUTCFullYear() + '-' + (today.getUTCMonth() +1) + '-' + today.getUTCDate(); currentTime = today.getUTCHours() + ":" + today.getUTCMinutes() + ":" + today.getUTCSeconds(); safeFilename = results.resultsJSON["query"].replace(/[^a-z0-9_-]/gi, "_"); resultFilename = "UTC-" + currentDate + "_" + currentTime + "_" + safeFilename; return resultFilename } // function to download the results as JSON function downloadJSONRessource(resultFilename) { let dataStr; let downloadElement; // stringify JSON object for json download dataStr = JSON.stringify(results.resultsJSON, undefined, "\t"); // use tabs to save some space // get downloadResultsElement downloadElement = document.getElementById("download-results-json"); // start actual download download(downloadElement, dataStr, resultFilename, "text/json", ".json") } // Function to download data as a Blob created from a string, should be multi purpose function download(downloadElem, dataStr, filename, type, filenameSlug) { let file; console.log("Start Download!"); filename += filenameSlug; file = new Blob([dataStr], {type: type}); if (window.navigator.msSaveOrOpenBlob) // IE10+ window.navigator.msSaveOrOpenBlob(file, filename); else { // Others var url = URL.createObjectURL(file); downloadElem.href = url; downloadElem.download = filename; } } // ###### Functions to inspect one match, to show more details ###### // activate inspect buttons if queryFinished is true function activateInspect(progress) { let inspectBtnElements; inspectBtnElements = document.getElementsByClassName("inspect"); for (let inspectBtn of inspectBtnElements) { inspectBtn.classList.remove("disabled"); } } //gets result cpos infos for one dataIndex to send back to the server function inspect(dataIndex) { // This function should be in the AnalysisClient class as a method. console.log("Inspect!"); console.log(results.resultsJSON.matches[dataIndex].c); contextResultsElement = document.getElementById("context-results"); contextResultsElement.innerHTML = ""; // clear it from old inspects contextModal.open(); nopaque.socket.emit("pj_corpus_analysis_inspect_match", {payload: { first_cpos: results.resultsJSON.matches[dataIndex].c[0], last_cpos: results.resultsJSON.matches[dataIndex].c[1] } }); } function showMatchContext(response) { let contextData = response.payload let contextResultsElement; let contextModalLoading; let contextModalReady; let expertModeSwitchElement let partElement let token; let tokenElement; console.log("###### match_context ######"); console.log("Incoming data:", contextData); expertModeSwitchElement = document.getElementById("display-options-form-expert_mode"); contextResultsElement = document.getElementById("context-results"); contextModalLoading = document.getElementById("context-modal-loading"); contextModalLoading.classList.add("hide"); contextModalReady = document.getElementById("context-modal-ready"); contextModalReady.classList.remove("hide"); if (contextData.cpos_ranges == true) { // python range like function from MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from#Sequence_generator_(range) const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step)); lc = range(contextData.match.lc[0], contextData.match.lc[1], 1) c = range(contextData.match.c[0], contextData.match.c[1], 1) rc = range(contextData.match.rc[0], contextData.match.rc[1], 1) } else { lc = contextData.match.lc; c = contextData.match.c; rc = contextData.match.rc; } partElement = document.createElement("p"); for (let cpos of lc) { token = contextData["cpos_lookup"][cpos]; partElement.insertAdjacentHTML("beforeend", `${token["word"]} `); contextResultsElement.append(partElement); } for (let cpos of c) { token = contextData["cpos_lookup"][cpos]; partElement.insertAdjacentHTML("beforeend", `${token["word"]} `); contextResultsElement.append(partElement); } for (let cpos of rc) { token = contextData["cpos_lookup"][cpos]; partElement.insertAdjacentHTML("beforeend", `${token["word"]} `); contextResultsElement.append(partElement); } if (expertModeSwitchElement.checked) { let tokenElements = partElement.getElementsByClassName("token"); expertModeOn(tokenElements, contextData); } } // ###### Display options changing live how the matches are being displayed ###### // Event function that changes the shown hits per page. // Just alters the resultsList.page property function changeHitsPerPage(event) { try { resultsList.page = event.target.value; resultsList.update(); nopaque.flash("Updated matches per page.") } catch (e) { console.log("resultsList has no results right now. Live update of items per page is useless for now."); } } // Event function triggered on context select change and also if pagination is clicked function changeContext(event) { let newContextValue; let lc; let rc; let array; try { if (event.type === "change") { nopaque.flash("Updated context per match!"); } } catch (e) { // console.log(e); // console.log("This error is expected."); } finally { newContextValue = document.getElementById("display-options-form-result_context").value; console.log("Context value is:", newContextValue); lc = document.getElementsByClassName("left-context"); rc = document.getElementsByClassName("right-context"); for (let element of lc) { array = Array.from(element.childNodes); for (let element of array.slice(newContextValue)) { element.classList.add("hide"); } for (let element of array.slice(0, newContextValue)) { element.classList.remove("hide"); } } for (let element of rc) { array = Array.from(element.childNodes); for (let element of array.slice(newContextValue)) { element.classList.add("hide"); } for (let element of array.slice(0, newContextValue)) { element.classList.remove("hide"); } } } } // ###### Expert view event functions ###### // Event function to check if pagination is used and then look if // expertModeSwitchElement is checked // if checked than expertModeOn is executed // if unchecked expertModeOff is executed function eventHandlerCheck(event) { console.log("pagination used!"); console.log(expertModeSwitchElement.checked); if (expertModeSwitchElement.checked) { expertModeOn(event.currentTarget.tokenElements, resultsJSON); } else if (!expertModeSwitchElement.checked) { event.preventDefault(); console.log("prevented! Destroy"); expertModeOff(event.currentTarget.tokenElements); } } // function to apply extra information and animation to every token function expertModeOn(tokenElements, results) { let token; console.log("expertModeOn!"); for (let tokenElement of tokenElements) { tokenElement.classList.add("chip"); tokenElement.classList.add("hoverable"); tokenElement.classList.add("expert-view"); token = results["cpos_lookup"][tokenElement.dataset.cpos]; tokenElement.addEventListener("mouseover", function(event) { console.log("Mouseover!"); console.log(event.target); token = results["cpos_lookup"][event.target.dataset.cpos]; addToolTipToTokenElement(event.target, token); }); } } // fuction that creates Tooltip for one token and extracts the corresponding // infos from the result JSON function addToolTipToTokenElement(tokenElement, token) { M.Tooltip.init(tokenElement, {"html": `
Token information | Source information |
---|---|
Word: ${token["word"]} Lemma: ${token["lemma"]} POS: ${token["pos"]} Simple POS: ${token["simple_pos"]} NER: ${token["ner"]} |
Title: ${resultsJSON["text_lookup"][token["text"]]["title"]} Author: ${resultsJSON["text_lookup"][token["text"]]["author"]} Publishing year: ${resultsJSON["text_lookup"][token["text"]]["publishing_year"]} |