mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-04 12:22:47 +00:00 
			
		
		
		
	First analys_corpus clean up
This commit is contained in:
		
							
								
								
									
										294
									
								
								app/static/js/nopaque.analyse_corpus.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										294
									
								
								app/static/js/nopaque.analyse_corpus.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,294 @@
 | 
				
			|||||||
 | 
					// ### Send query functions ###
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//function to get current queryData from a given queryFormElement
 | 
				
			||||||
 | 
					function getQueryData(queryFormElement) {
 | 
				
			||||||
 | 
					  // Get query form element and save its data on submit and send this data via
 | 
				
			||||||
 | 
					  formData = new FormData(queryFormElement);
 | 
				
			||||||
 | 
					  queryData = {"context": formData.get("context"), // global declaration
 | 
				
			||||||
 | 
					               "hits_per_page": formData.get("hits_per_page"),
 | 
				
			||||||
 | 
					               "query": formData.get("query")};
 | 
				
			||||||
 | 
					  console.log("Query data:", queryData);
 | 
				
			||||||
 | 
					  return queryData
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Function to send a query to the CQP server using queryData gatherd with getQueryData
 | 
				
			||||||
 | 
					function sendQuery(event) {
 | 
				
			||||||
 | 
					  event.preventDefault();
 | 
				
			||||||
 | 
					  queryData = getQueryData(queryFormElement);
 | 
				
			||||||
 | 
					  nopaque.socket.emit("corpus_analysis_query", queryData.query);
 | 
				
			||||||
 | 
					  // 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 = {};
 | 
				
			||||||
 | 
					  result["matches"] = [];
 | 
				
			||||||
 | 
					  result["cpos_lookup"] = {};
 | 
				
			||||||
 | 
					  result["text_lookup"] = {};
 | 
				
			||||||
 | 
					  result["loaded_match_count"] = 0;
 | 
				
			||||||
 | 
					  result["match_count"] = 0;
 | 
				
			||||||
 | 
					  result["query"] = "";
 | 
				
			||||||
 | 
					  // some hiding/showing for loading animation
 | 
				
			||||||
 | 
					  queryLoadingElement.classList.remove("hide");
 | 
				
			||||||
 | 
					  queryResultsTableElement.classList.add("hide");
 | 
				
			||||||
 | 
					  nopaque.toast("Query has been sent!");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  resultListOptions = {page: queryData["hits_per_page"],
 | 
				
			||||||
 | 
					    pagination: [{
 | 
				
			||||||
 | 
					      name: "paginationTop",
 | 
				
			||||||
 | 
					      paginationClass: "paginationTop",
 | 
				
			||||||
 | 
					      innerWindow: 8,
 | 
				
			||||||
 | 
					      outerWindow: 1
 | 
				
			||||||
 | 
					    }, {
 | 
				
			||||||
 | 
					      paginationClass: "paginationBottom",
 | 
				
			||||||
 | 
					      innerWindow: 8,
 | 
				
			||||||
 | 
					      outerWindow: 1
 | 
				
			||||||
 | 
					    }],
 | 
				
			||||||
 | 
					    valueNames: ["titles", "lc", "hit", "rc", {data: ["index"]}],
 | 
				
			||||||
 | 
					    item: `<span class="hidden"></span>`};
 | 
				
			||||||
 | 
					    resultList = new ResultList('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) {
 | 
				
			||||||
 | 
					  // 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.toast("Invalid query entered!", "red");
 | 
				
			||||||
 | 
					    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 = {};
 | 
				
			||||||
 | 
					  chunk = response["result"];
 | 
				
			||||||
 | 
					  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["match_count"] = chunk["match_count"];
 | 
				
			||||||
 | 
					  console.log("Before Current match count", result["loaded_match_count"]);
 | 
				
			||||||
 | 
					  result["query"] = queryData["query"];
 | 
				
			||||||
 | 
					  console.log(result);
 | 
				
			||||||
 | 
					  // Some hiding and showing of loading animations
 | 
				
			||||||
 | 
					  queryLoadingElement.classList.add("hide");
 | 
				
			||||||
 | 
					  queryResultsTableElement.classList.remove("hide");
 | 
				
			||||||
 | 
					  queryResultsElement.innerHTML = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // check if query has any results
 | 
				
			||||||
 | 
					  if (chunk["matches"].length === 0) {
 | 
				
			||||||
 | 
					    queryResultsTableElement.classList.add("hide");
 | 
				
			||||||
 | 
					    nopaque.toast("No results for this query!");
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // List building/appending the chunks when query had results
 | 
				
			||||||
 | 
					  match_count = chunk["match_count"];
 | 
				
			||||||
 | 
					  let count_corpus_files = Object.keys(result["text_lookup"]).length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var 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.innerHTML = `<p>The query resulted in a total of ${chunk["match_count"]} matches. </p> <p> ${result["loaded_match_count"]} of ${result["match_count"]} matches in ${count_corpus_files} corpus files have been loaded.</p>`;
 | 
				
			||||||
 | 
					  queryResultsMetadataElement.appendChild(exportQueryResults);
 | 
				
			||||||
 | 
					  exportQueryResults.classList.remove("hide");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Function to inspect one match, to show more details
 | 
				
			||||||
 | 
					function inspect(dataIndex) {
 | 
				
			||||||
 | 
					  console.log("Inspect!");
 | 
				
			||||||
 | 
					  console.log(result["matches"][dataIndex]["hit"]);
 | 
				
			||||||
 | 
					  contextModal.open();
 | 
				
			||||||
 | 
					  nopaque.socket.emit("inspect_match", {"cpos": result["matches"][dataIndex]["hit"]});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ### 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.toast("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) {
 | 
				
			||||||
 | 
					  // newValue = event.target.value;  // cannot use this anymore due to reuse of this function in the above paginationElements eventListener
 | 
				
			||||||
 | 
					  console.log("Event", event);
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					      if (event.type === "change") {
 | 
				
			||||||
 | 
					          nopaque.toast("Updated context per match!");
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					  } catch (e) {
 | 
				
			||||||
 | 
					      console.log(e);
 | 
				
			||||||
 | 
					  } finally {
 | 
				
			||||||
 | 
					      var contextPerItemElement = document.getElementById("context");
 | 
				
			||||||
 | 
					      newValue = contextPerItemElement.value;
 | 
				
			||||||
 | 
					      console.log(newValue);
 | 
				
			||||||
 | 
					      var lc = document.getElementsByClassName("left-context");
 | 
				
			||||||
 | 
					      var rc = document.getElementsByClassName("right-context");
 | 
				
			||||||
 | 
					      for (let element of lc) {
 | 
				
			||||||
 | 
					        array = Array.from(element.childNodes);
 | 
				
			||||||
 | 
					        for (let element of array.slice(newValue)) {
 | 
				
			||||||
 | 
					          element.classList.add("hide");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (let element of array.slice(0, newValue)) {
 | 
				
			||||||
 | 
					          element.classList.remove("hide");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      for (let element of rc) {
 | 
				
			||||||
 | 
					        array = Array.from(element.childNodes);
 | 
				
			||||||
 | 
					        for (let element of array.slice(newValue)) {
 | 
				
			||||||
 | 
					          element.classList.add("hide");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (let element of array.slice(0, newValue)) {
 | 
				
			||||||
 | 
					          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) {
 | 
				
			||||||
 | 
					  console.log("expertModeOn!");
 | 
				
			||||||
 | 
					  for (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": `<table>
 | 
				
			||||||
 | 
					                             <tr>
 | 
				
			||||||
 | 
					                               <th>Token information</th>
 | 
				
			||||||
 | 
					                               <th>Source information</th>
 | 
				
			||||||
 | 
					                             </tr>
 | 
				
			||||||
 | 
					                             <tr>
 | 
				
			||||||
 | 
					                               <td class="left-align">
 | 
				
			||||||
 | 
					                                 Word: ${token["word"]}<br>
 | 
				
			||||||
 | 
					                                 Lemma: ${token["lemma"]}<br>
 | 
				
			||||||
 | 
					                                 POS: ${token["pos"]}<br>
 | 
				
			||||||
 | 
					                                 Simple POS: ${token["simple_pos"]}<br>
 | 
				
			||||||
 | 
					                                 NER: ${token["ner"]}
 | 
				
			||||||
 | 
					                               </td>
 | 
				
			||||||
 | 
					                               <td class="left-align">
 | 
				
			||||||
 | 
					                                 Title: ${result["text_lookup"][token["text"]]["title"]}<br>
 | 
				
			||||||
 | 
					                                 Author: ${result["text_lookup"][token["text"]]["author"]}<br>
 | 
				
			||||||
 | 
					                                 Publishing year: ${result["text_lookup"][token["text"]]["publishing_year"]}
 | 
				
			||||||
 | 
					                               </td>
 | 
				
			||||||
 | 
					                             </tr>
 | 
				
			||||||
 | 
					                           </table>`,
 | 
				
			||||||
 | 
					                 "inDuration": 1500,
 | 
				
			||||||
 | 
					                 "margin": 15,
 | 
				
			||||||
 | 
					                 "position": "top",
 | 
				
			||||||
 | 
					                 "transitionMovement": 0});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// function to remove extra informations and animations from tokens
 | 
				
			||||||
 | 
					function expertModeOff(tokenElements) {
 | 
				
			||||||
 | 
					  console.log("expertModeOff!");
 | 
				
			||||||
 | 
					  for (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() {
 | 
				
			||||||
 | 
					  // get and create metadata
 | 
				
			||||||
 | 
					  console.log("Create Metadata!");
 | 
				
			||||||
 | 
					  var today = new Date();
 | 
				
			||||||
 | 
					  var currentDate = today.getUTCFullYear() + '-' + (today.getUTCMonth() +1) + '-' + today.getUTCDate();
 | 
				
			||||||
 | 
					  var currentTime = today.getUTCHours() + ":" + today.getUTCMinutes() + ":" + today.getUTCSeconds();
 | 
				
			||||||
 | 
					  var safeFilename = result['query'].replace(/[^a-z0-9_-]/gi, "_");
 | 
				
			||||||
 | 
					  var resultFilename = "UTC-" + currentDate + "_" + currentTime + "_" + safeFilename;
 | 
				
			||||||
 | 
					  return resultFilename
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// function to download the results as JSON
 | 
				
			||||||
 | 
					function downloadJSONRessource(resultFilename) {
 | 
				
			||||||
 | 
					  // stringify JSON object for json download
 | 
				
			||||||
 | 
					  var 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) {
 | 
				
			||||||
 | 
					  console.log("Start Download!");
 | 
				
			||||||
 | 
					  filename += filenameSlug;
 | 
				
			||||||
 | 
					  var 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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -218,7 +218,9 @@ server side -->
 | 
				
			|||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script src="{{ url_for('static', filename='js/nopaque.analyse_corpus.js') }}">
 | 
					<!-- Loading external script -->
 | 
				
			||||||
 | 
					<script src="{{ url_for('static', filename='js/nopaque.analyse_corpus.js') }}"></script>
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 // Initialising some modals for later usage
 | 
					 // Initialising some modals for later usage
 | 
				
			||||||
  var contextModal;
 | 
					  var contextModal;
 | 
				
			||||||
@@ -264,70 +266,14 @@ server side -->
 | 
				
			|||||||
  var result;
 | 
					  var result;
 | 
				
			||||||
  var resultList;
 | 
					  var resultList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //function to get queryData
 | 
					 | 
				
			||||||
  function getQueryData(queryFormElement) {
 | 
					 | 
				
			||||||
    // Get query form element and save its data on submit and send this data via
 | 
					 | 
				
			||||||
    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
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // socket.io analysis submit to the CQP server
 | 
					  // socket.io analysis submit to the CQP server
 | 
				
			||||||
  let queryFormElement = document.getElementById("query-form");
 | 
					  let queryFormElement = document.getElementById("query-form");
 | 
				
			||||||
  queryFormElement.addEventListener("submit", sendQuery);
 | 
					  queryFormElement.addEventListener("submit", sendQuery);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function sendQuery(event) {
 | 
					 | 
				
			||||||
    event.preventDefault();
 | 
					 | 
				
			||||||
    queryData = getQueryData(queryFormElement);
 | 
					 | 
				
			||||||
    nopaque.socket.emit("corpus_analysis_query", queryData.query);
 | 
					 | 
				
			||||||
    // full results object declaration, kind of global maybe store it later?
 | 
					 | 
				
			||||||
    // will always be reset if a query is sent, so that only the chunks of the
 | 
					 | 
				
			||||||
    // current query will be saved in it
 | 
					 | 
				
			||||||
    result = {};
 | 
					 | 
				
			||||||
    result["matches"] = [];
 | 
					 | 
				
			||||||
    result["cpos_lookup"] = {};
 | 
					 | 
				
			||||||
    result["text_lookup"] = {};
 | 
					 | 
				
			||||||
    result["loaded_match_count"] = 0;
 | 
					 | 
				
			||||||
    result["match_count"] = 0;
 | 
					 | 
				
			||||||
    result["query"] = "";
 | 
					 | 
				
			||||||
    // some hiding/showing for loading animation
 | 
					 | 
				
			||||||
    queryLoadingElement.classList.remove("hide");
 | 
					 | 
				
			||||||
    queryResultsTableElement.classList.add("hide");
 | 
					 | 
				
			||||||
    nopaque.toast("Query has been sent!");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    resultListOptions = {page: queryData["hits_per_page"],
 | 
					 | 
				
			||||||
      pagination: [{
 | 
					 | 
				
			||||||
        name: "paginationTop",
 | 
					 | 
				
			||||||
        paginationClass: "paginationTop",
 | 
					 | 
				
			||||||
        innerWindow: 8,
 | 
					 | 
				
			||||||
        outerWindow: 1
 | 
					 | 
				
			||||||
      }, {
 | 
					 | 
				
			||||||
        paginationClass: "paginationBottom",
 | 
					 | 
				
			||||||
        innerWindow: 8,
 | 
					 | 
				
			||||||
        outerWindow: 1
 | 
					 | 
				
			||||||
      }],
 | 
					 | 
				
			||||||
      valueNames: ["titles", "lc", "hit", "rc", {data: ["index"]}],
 | 
					 | 
				
			||||||
      item: `<span class="hidden"></span>`};
 | 
					 | 
				
			||||||
      resultList = new ResultList('result-list', resultListOptions);
 | 
					 | 
				
			||||||
      resultList.clear(); // empty list for new query
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // live update of hits per page
 | 
					  // live update of hits per page
 | 
				
			||||||
  var hitsPerPageInputElement = document.getElementById("hits-per-page");
 | 
					  var hitsPerPageInputElement = document.getElementById("hits-per-page");
 | 
				
			||||||
  hitsPerPageInputElement.onchange = changeHitsPerPage;
 | 
					  hitsPerPageInputElement.onchange = changeHitsPerPage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function changeHitsPerPage(event) {
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      resultList.page = event.target.value;
 | 
					 | 
				
			||||||
      resultList.update();
 | 
					 | 
				
			||||||
      nopaque.toast("Updated matches per page.")
 | 
					 | 
				
			||||||
    } catch (e) {
 | 
					 | 
				
			||||||
      console.log("resultList has no results right now. Live update of items per page is useless for now.");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // live update of lr context per item if context value is changed
 | 
					  // live update of lr context per item if context value is changed
 | 
				
			||||||
  var contextPerItemElement = document.getElementById("context-per-item");
 | 
					  var contextPerItemElement = document.getElementById("context-per-item");
 | 
				
			||||||
  contextPerItemElement.onchange = changeContext;
 | 
					  contextPerItemElement.onchange = changeContext;
 | 
				
			||||||
@@ -338,154 +284,14 @@ server side -->
 | 
				
			|||||||
    element.addEventListener("click", changeContext);
 | 
					    element.addEventListener("click", changeContext);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // event triggered on context select change and also if pagination is clicked
 | 
					 | 
				
			||||||
  function changeContext(event) {
 | 
					 | 
				
			||||||
    // newValue = event.target.value;  // cannot use this anymore due to reuse of this function in the above paginationElements eventListener
 | 
					 | 
				
			||||||
    console.log("Event", event);
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
        if (event.type === "change") {
 | 
					 | 
				
			||||||
            nopaque.toast("Updated context per match!");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } catch (e) {
 | 
					 | 
				
			||||||
        console.log(e);
 | 
					 | 
				
			||||||
    } finally {
 | 
					 | 
				
			||||||
        var contextPerItemElement = document.getElementById("context");
 | 
					 | 
				
			||||||
        newValue = contextPerItemElement.value;
 | 
					 | 
				
			||||||
        console.log(newValue);
 | 
					 | 
				
			||||||
        var lc = document.getElementsByClassName("left-context");
 | 
					 | 
				
			||||||
        var rc = document.getElementsByClassName("right-context");
 | 
					 | 
				
			||||||
        for (let element of lc) {
 | 
					 | 
				
			||||||
          array = Array.from(element.childNodes);
 | 
					 | 
				
			||||||
          for (let element of array.slice(newValue)) {
 | 
					 | 
				
			||||||
            element.classList.add("hide");
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          for (let element of array.slice(0, newValue)) {
 | 
					 | 
				
			||||||
            element.classList.remove("hide");
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        for (let element of rc) {
 | 
					 | 
				
			||||||
          array = Array.from(element.childNodes);
 | 
					 | 
				
			||||||
          for (let element of array.slice(newValue)) {
 | 
					 | 
				
			||||||
            element.classList.add("hide");
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          for (let element of array.slice(0, newValue)) {
 | 
					 | 
				
			||||||
            element.classList.remove("hide");
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // socket.on triggered when result chunks are recieved
 | 
					  // socket.on triggered when result chunks are recieved
 | 
				
			||||||
  nopaque.socket.on("corpus_analysis_query", function(response) {
 | 
					  nopaque.socket.on("corpus_analysis_query", recieveResults);
 | 
				
			||||||
    // 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.toast("Invalid query entered!", "red");
 | 
					 | 
				
			||||||
      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 = {};
 | 
					 | 
				
			||||||
    chunk = response["result"];
 | 
					 | 
				
			||||||
    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["match_count"] = chunk["match_count"];
 | 
					 | 
				
			||||||
    console.log("Before Current match count", result["loaded_match_count"]);
 | 
					 | 
				
			||||||
    result["query"] = queryData["query"];
 | 
					 | 
				
			||||||
    console.log(result);
 | 
					 | 
				
			||||||
    // Some hiding and showing of loading animations
 | 
					 | 
				
			||||||
    queryLoadingElement.classList.add("hide");
 | 
					 | 
				
			||||||
    queryResultsTableElement.classList.remove("hide");
 | 
					 | 
				
			||||||
    queryResultsElement.innerHTML = "";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // check if query has any results
 | 
					  // add onclick to download JSON button and download the file
 | 
				
			||||||
    if (chunk["matches"].length === 0) {
 | 
					  var downloadResultsJSONElement = document.getElementById("download-results-json")
 | 
				
			||||||
      queryResultsTableElement.classList.add("hide");
 | 
					  downloadResultsJSONElement.onclick = function() {
 | 
				
			||||||
      nopaque.toast("No results for this query!");
 | 
					    var filename = createDownloadFilename();
 | 
				
			||||||
      return;
 | 
					    downloadJSONRessource(filename)};
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // List building/appending the chunks when query had results
 | 
					 | 
				
			||||||
    match_count = chunk["match_count"];
 | 
					 | 
				
			||||||
    let count_corpus_files = Object.keys(result["text_lookup"]).length;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    var 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.innerHTML = `<p>The query resulted in a total of ${chunk["match_count"]} matches. </p> <p> ${result["loaded_match_count"]} of ${result["match_count"]} matches in ${count_corpus_files} corpus files have been loaded.</p>`;
 | 
					 | 
				
			||||||
    queryResultsMetadataElement.appendChild(exportQueryResults);
 | 
					 | 
				
			||||||
    exportQueryResults.classList.remove("hide");
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // inspect match functions
 | 
					 | 
				
			||||||
    function inspect(dataIndex) {
 | 
					 | 
				
			||||||
      console.log("Inspect!");
 | 
					 | 
				
			||||||
      console.log(result["matches"][dataIndex]["hit"]);
 | 
					 | 
				
			||||||
      contextModal.open();
 | 
					 | 
				
			||||||
      nopaque.socket.emit("inspect_match", {"cpos": result["matches"][dataIndex]["hit"]});
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    function downloadRessource(downloadElement, mimeTypeString, filenameSlug) {
 | 
					 | 
				
			||||||
      // get and create metadata
 | 
					 | 
				
			||||||
      console.log("Create Metadata!");
 | 
					 | 
				
			||||||
      var today = new Date();
 | 
					 | 
				
			||||||
      var currentDate = today.getUTCFullYear() + '-' + (today.getUTCMonth() +1) + '-' + today.getUTCDate();
 | 
					 | 
				
			||||||
      var currentTime = today.getUTCHours() + ":" + today.getUTCMinutes() + ":" + today.getUTCSeconds();
 | 
					 | 
				
			||||||
      var safeFilename = result['query'].replace(/[^a-z0-9_-]/gi, "_");
 | 
					 | 
				
			||||||
      var resultFilename = "UTC-" + currentDate + "_" + currentTime + "_" + safeFilename;
 | 
					 | 
				
			||||||
      // stringify JSON object for json download
 | 
					 | 
				
			||||||
      var dataStr = JSON.stringify(result, undefined, 2);
 | 
					 | 
				
			||||||
      // get downloadResultsElement
 | 
					 | 
				
			||||||
      downloadElement = document.getElementById("download-results-json");
 | 
					 | 
				
			||||||
      // start actual download
 | 
					 | 
				
			||||||
      download(downloadElement, dataStr, resultFilename, mimeTypeString, filenameSlug)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    // add onclick to download buttons
 | 
					 | 
				
			||||||
    var downloadResultsJSONElement = document.getElementById("download-results-json");
 | 
					 | 
				
			||||||
    downloadResultsJSONElement.onclick = function() {downloadRessource(downloadResultsJSONElement, "text/json", ".json")};
 | 
					 | 
				
			||||||
    var downloadResultsCSVElement = document.getElementById("download-results-csv");
 | 
					 | 
				
			||||||
    downloadResultsCSVElement.onclick = function() {downloadRessource(downloadResultsCSVElement, "text/plain", ".txt")};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Function to download data to a file
 | 
					 | 
				
			||||||
    function download(downloadElem, data, filename, type, filenameSlug) {
 | 
					 | 
				
			||||||
      console.log("Start Download!");
 | 
					 | 
				
			||||||
      filename += filenameSlug;
 | 
					 | 
				
			||||||
      var file = new Blob([data], {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;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // epxert mode table view
 | 
					  // epxert mode table view
 | 
				
			||||||
  var expertModeSwitchElement = document.getElementById("expert-mode-switch");
 | 
					  var expertModeSwitchElement = document.getElementById("expert-mode-switch");
 | 
				
			||||||
@@ -506,75 +312,6 @@ server side -->
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  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 expertModeOff(tokenElements) {
 | 
					 | 
				
			||||||
    console.log("expertModeOff!");
 | 
					 | 
				
			||||||
    for (tokenElement of tokenElements) {
 | 
					 | 
				
			||||||
      tokenElement.classList.remove("chip");
 | 
					 | 
				
			||||||
      tokenElement.classList.remove("hoverable");
 | 
					 | 
				
			||||||
      tokenElement.classList.remove("expert-view");
 | 
					 | 
				
			||||||
      tokenElement.outerHTML = tokenElement.outerHTML; // TODO fix this in a proper way
 | 
					 | 
				
			||||||
      // console.log("Token", tokenElement);
 | 
					 | 
				
			||||||
      // console.log("Tooltip property:", tokenElement.M_Tooltip);
 | 
					 | 
				
			||||||
      // tokenElement.M_Tooltip.destroy();
 | 
					 | 
				
			||||||
      // console.log("Destroy!");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  function expertModeOn(tokenElements, result_lookup) {
 | 
					 | 
				
			||||||
    console.log("expertModeOn!");
 | 
					 | 
				
			||||||
    for (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);
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  function addToolTipToTokenElement(tokenElement, token) {
 | 
					 | 
				
			||||||
    M.Tooltip.init(tokenElement,
 | 
					 | 
				
			||||||
                   {"html": `<table>
 | 
					 | 
				
			||||||
                               <tr>
 | 
					 | 
				
			||||||
                                 <th>Token information</th>
 | 
					 | 
				
			||||||
                                 <th>Source information</th>
 | 
					 | 
				
			||||||
                               </tr>
 | 
					 | 
				
			||||||
                               <tr>
 | 
					 | 
				
			||||||
                                 <td class="left-align">
 | 
					 | 
				
			||||||
                                   Word: ${token["word"]}<br>
 | 
					 | 
				
			||||||
                                   Lemma: ${token["lemma"]}<br>
 | 
					 | 
				
			||||||
                                   POS: ${token["pos"]}<br>
 | 
					 | 
				
			||||||
                                   Simple POS: ${token["simple_pos"]}<br>
 | 
					 | 
				
			||||||
                                   NER: ${token["ner"]}
 | 
					 | 
				
			||||||
                                 </td>
 | 
					 | 
				
			||||||
                                 <td class="left-align">
 | 
					 | 
				
			||||||
                                   Title: ${result["text_lookup"][token["text"]]["title"]}<br>
 | 
					 | 
				
			||||||
                                   Author: ${result["text_lookup"][token["text"]]["author"]}<br>
 | 
					 | 
				
			||||||
                                   Publishing year: ${result["text_lookup"][token["text"]]["publishing_year"]}
 | 
					 | 
				
			||||||
                                 </td>
 | 
					 | 
				
			||||||
                               </tr>
 | 
					 | 
				
			||||||
                             </table>`,
 | 
					 | 
				
			||||||
                   "inDuration": 1500,
 | 
					 | 
				
			||||||
                   "margin": 15,
 | 
					 | 
				
			||||||
                   "position": "top",
 | 
					 | 
				
			||||||
                   "transitionMovement": 0});
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  // collapsible display options
 | 
					  // collapsible display options
 | 
				
			||||||
  var elem = document.querySelector('.collapsible.expandable');
 | 
					  var elem = document.querySelector('.collapsible.expandable');
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user