diff --git a/app/static/js/nopaque.analyse_corpus.js b/app/static/js/nopaque.analyse_corpus.js deleted file mode 100644 index 4f766cba..00000000 --- a/app/static/js/nopaque.analyse_corpus.js +++ /dev/null @@ -1,453 +0,0 @@ -// ### corpus analysis client status functions - -function sendAbortSignal() { - console.log(`Sending status "abort signal" from client side.`); - message = {'status': "abort"}; - nopaque.socket.emit("send_analysis_status_cli", message); - setAnalysisStatus("abort"); -} - -function setAnalysisStatus(statusStr) { - analysisClientStatus[sessionId] = statusStr; - console.log(`Set new status "${statusStr}" for "${sessionId}" on client side.`); - console.log("Object with status is:", analysisClientStatus); -} - -function checkAnalysisStatus(sessionId) { - let status = analysisClientStatus[sessionId]; - console.log(`Check status on client side for ${sessionId}.`, analysisClientStatus); - return status; -} - -// ### Send query functions ### - -//function to get current queryData from a given queryFormElement -function getQueryData(queryFormElement) { - let formData - let queryData - formData = new FormData(queryFormElement); - queryData = {"context": formData.get("context"), // global declaration - "hits_per_page": formData.get("hits_per_page"), - "query": formData.get("query")}; - return queryData -} - -// Function to send a query to the CQP server using queryData gatherd with getQueryData -async function sendQuery(event) { - const delay = ms => new Promise(res => setTimeout(res, ms)); - result; // global declaration, holds query results as JSON - resultList; // global declaration, list.js object displaying the results - let queryData; // holds data of query form - let resultListOptions; // holding the options for the ResultList object - let analysisStatus; - - // checks if one query has been finished before - // if true, result download will be disabled again until query is finished - // also shows progress bar again - if (queryFinished) { - exportQueryResultsElement.classList.add("disabled"); - queryResultsDeterminateElement.parentNode.parentNode.classList.remove("hide"); - } - - console.log("Sending query."); - console.log("Session status are: ", analysisClientStatus); - event.preventDefault(); - analysisStatus = checkAnalysisStatus(sessionId); - queryData = getQueryData(queryFormElement); - - if (analysisStatus === "idle") { - nopaque.flash("Query has been sent!"); - nopaque.socket.emit("corpus_analysis_query", queryData.query); - helperSendQuery(queryData); - analysisStatus = checkAnalysisStatus(sessionId); - } else if (analysisStatus === "running" ) { - sendAbortSignal(); - analysisStatus = checkAnalysisStatus(sessionId); - while (analysisStatus === "abort") { - queryResultsTableElement.classList.add("hide"); - queryLoadingElement.classList.remove("hide"); - analysisStatus = checkAnalysisStatus(sessionId); - await delay(100); - } - sendQuery(event) - } -} - - -function helperSendQuery(queryData) { - // full results object declaration, global declaration! - // will always be reset if a query is sent, so that only the chunks of the - // current query will be saved in it - result = {}; // full JSON object holding match results - result["matches"] = []; // list of all amtches with lc and rc - result["cpos_lookup"] = {}; // object contains all cpos as key value pair - result["text_lookup"] = {}; // same as above for all text ids - result["loaded_match_count"] = 0; // how many matches have been recieved - result["num_matches_total"]; // how many should have been recieved/total nr - result["query"] = ""; // the query as a string - // some hiding/showing for loading animation - queryLoadingElement.classList.remove("hide"); - queryResultsTableElement.classList.add("hide"); - - resultListOptions = {page: queryData["hits_per_page"], - pagination: [{ - name: "paginationTop", - paginationClass: "paginationTop", - innerWindow: 8, - outerWindow: 1 - }, { - paginationClass: "paginationBottom", - innerWindow: 8, - outerWindow: 1 - }], - valueNames: ["titles", "lc", "c", "rc", {data: ["index"]}], - item: ``}; - resultList = new ResultsList('result-list', resultListOptions); - resultList.clear(); // empty list for new query -} - -// ### Recieve results from sent query and display them in a list etc. ### - -// Function used when CQP server sends back the query results using socketio -function recieveResults(response) { - let toolTipInfoElement; - let chunk; - let countCorpusFiles; - let queryData; - let queryResultsElement; - let resultItems; - let queryResultsMetadataElement; - let queryResultsInteractionElement; - let queryResultsHeadElement; - let queryStatus; - queryFinished = false; - - console.log(response); - - // ERROR code checking - if (response["code"] === 0) { - console.log("[SUCCESS] corpus_analysis_init"); - console.log("Code:" + response["code"]); - // further code execution of this code block starting in line 342 - } else if (response["code"] === 1) { - queryResultsTableElement.classList.add("hide"); - queryLoadingElement.classList.add("hide"); - nopaque.flash("error", "Invalid query entered!"); - console.log("[ERROR] corpus_analysis_init"); - console.log("Code:" + response["code"]); - return; // no further code execution of this code block - } else { - console.log("[ERROR] corpus_analysis_init"); - console.log("Code:" + response["code"]); - return; // no further code execution of this code block - } - // logs the current recieved chunk - chunk = response["chunk"]; - //chunk = response["chunk"]; - console.log("### corpus_analysis chunk ###"); - console.log(chunk); - // logs and extends/push/update the current recieved chunk to the - // result Object - console.log("### corpus analysis updated result json ###"); - result["matches"].push(...chunk["matches"]); - Object.assign(result["cpos_lookup"], chunk["cpos_lookup"]); - Object.assign(result["text_lookup"], chunk["text_lookup"]); - result["num_matches_total"] = response["num_matches_total"]; - //result["match_count"] = response["match_count"]; - console.log("Before Current match count", result["loaded_match_count"]); - queryData = getQueryData(queryFormElement); - result["query"] = queryData["query"]; - console.log(result); - // Some hiding and showing of loading animations - analysisStatus = checkAnalysisStatus(); - if (analysisStatus === "abort") { - queryResultsTableElement.classList.add("hide"); - queryLoadingElement.classList.remove("hide"); - } else { - queryResultsTableElement.classList.remove("hide"); - queryLoadingElement.classList.add("hide"); - queryResultsElement = document.getElementById("query-results"); - queryResultsElement.innerHTML = ""; - } - - // check if query has any results - if (chunk["matches"].length === 0) { - queryResultsTableElement.classList.add("hide"); - nopaque.flash("No results for this query!"); - return; - } - - // List building/appending the chunks when query had results - countCorpusFiles = Object.keys(result["text_lookup"]).length; - - resultItems = []; // list for holding every row item - // get infos for full match row - for (let [index, match] of chunk["matches"].entries()) { - resultItems.push({...match, ...{"index": index + result["loaded_match_count"]}}); - } - resultList.add(resultItems, items => { - for (let item of items) { - item.elm = resultList.createResultRowElement(item, chunk); - } - resultList.update(); - changeContext(); // sets lr context on first result load - }); - result["loaded_match_count"] += Object.keys(chunk["matches"]).length; - console.log("After current match count", result["loaded_match_count"]); - queryResultsMetadataElement = document.getElementById("query-results-metadata"); - queryResultsMetadataElement.innerHTML = `

The query resulted in a total of ${result["num_matches_total"]} matches.

${result["loaded_match_count"]} of ${result["num_matches_total"]} matches in ${countCorpusFiles} corpus files have been loaded.

helpThe Server is still sending your results. Functions like "Export Results" and "Match Inspect" will be available after all matches have been loaded.

`; - queryResultsInteractionElement = document.getElementById("interaction-elements"); - queryResultsInteractionElement.appendChild(exportQueryResultsElement); - queryResultsHeadElement = document.getElementById("query-results-head"); - queryResultsHeadElement.classList.remove("hide"); - queryStatus = response["progress"]; - console.log("QUERY STATUS:", queryStatus); - queryResultsDeterminateElement.style["width"] = `${queryStatus}%`; - console.log(queryResultsDeterminateElement.style["width"]); - - // enable download and inspect when query is finished - // also sets queryFinished to true - if (queryStatus === 100) { - queryFinished = true; // global declaration to set downlaod button and inspects buttons back to disabled for new queries - queryResultsDeterminateElement.parentNode.parentNode.classList.add("hide"); - exportQueryResultsElement.classList.remove("disabled"); - queryResultsMetadataElement.innerHTML = `

The query resulted in a total of ${result["num_matches_total"]} matches.

${result["loaded_match_count"]} of ${result["num_matches_total"]} matches in ${countCorpusFiles} corpus files have been loaded.check_circle

`; - activateInspect(); - } -} - - -// ### Functions to inspect one match, to show more details ### - -// activate inspect buttons if queryFinished is true -function activateInspect() { - let inspectBtnElements; - - if (queryFinished) { - 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) { - console.log("Inspect!"); - console.log(result["matches"][dataIndex]["c"]); - contextModal.open(); - nopaque.socket.emit("inspect_match", {"cpos": result["matches"][dataIndex]["c"]}); -} - -function showMatchContext(message) { - let contextResultsElement; - let sentenceElement - let token; - let tokenElement; - console.log("### match_context ###"); - console.log("Incoming data:", message); - contextResultsElement = document.getElementById("context-results"); - contextResultsElement.innerHTML = "

 

"; - document.getElementById("context-modal-loading").classList.add("hide"); - document.getElementById("context-modal-ready").classList.remove("hide"); - - for (let [key, value] of Object.entries(message['context_s_cpos'])) { - sentenceElement = document.createElement("p"); - for (let cpos of value) { - token = message["cpos_lookup"][cpos]; - tokenElement = document.createElement("span"); - tokenElement.classList.add("token"); - if (message["match_cpos_list"].includes(cpos)) { - tokenElement.classList.add("bold"); - tokenElement.classList.add("light-green"); - } - tokenElement.dataset.cpos = cpos; - tokenElement.innerText = token["word"]; - var expertModeSwitchElement = document.getElementById("expert-mode-switch"); - if (expertModeSwitchElement.checked) { - expertModeOn([tokenElement], message); - } - sentenceElement.append(tokenElement); - sentenceElement.append(document.createTextNode(" ")); - } - contextResultsElement.append(sentenceElement); - } -} - -// ### Display options changing live how the matches are being displayed ### - -// Event function that changes the shown hits per page. -// Just alters the resultList.page property -function changeHitsPerPage(event) { - try { - resultList.page = event.target.value; - resultList.update(); - nopaque.flash("Updated matches per page.") - } catch (e) { - console.log("resultList 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("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, result); - } 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, result_lookup) { - let token; - - console.log("expertModeOn!"); - for (let tokenElement of tokenElements) { - tokenElement.classList.add("chip"); - tokenElement.classList.add("hoverable"); - tokenElement.classList.add("expert-view"); - token = result_lookup["cpos_lookup"][tokenElement.dataset.cpos]; - tokenElement.addEventListener("mouseover", function(event) { - console.log("Mouseover!"); - console.log(event.target); - token = result_lookup["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 informationSource information
- Word: ${token["word"]}
- Lemma: ${token["lemma"]}
- POS: ${token["pos"]}
- Simple POS: ${token["simple_pos"]}
- NER: ${token["ner"]} -
- Title: ${result["text_lookup"][token["text"]]["title"]}
- Author: ${result["text_lookup"][token["text"]]["author"]}
- Publishing year: ${result["text_lookup"][token["text"]]["publishing_year"]} -
`, - "inDuration": 1500, - "margin": 15, - "position": "top", - "transitionMovement": 0}); -} - -// function to remove extra informations and animations from tokens -function expertModeOff(tokenElements) { - console.log("expertModeOff!"); - for (let tokenElement of tokenElements) { - tokenElement.classList.remove("chip"); - tokenElement.classList.remove("hoverable"); - tokenElement.classList.remove("expert-view"); - tokenElement.outerHTML = tokenElement.outerHTML; // this is actually a workaround, but it works pretty fast - } -} - - -// ### Download results functions ### - -// 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 = result['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(result, 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; - } -}