Merge branch 'development' of gitlab.ub.uni-bielefeld.de:sfb1288inf/opaque into development

This commit is contained in:
Patrick Jentsch 2020-04-08 17:21:49 +02:00
commit 6bbe0129b4
4 changed files with 193 additions and 142 deletions

View File

@ -14,6 +14,7 @@ class Results {
class ResultsJSON { class ResultsJSON {
// Sets empty object structure. Also usefull to delete old results. // Sets empty object structure. Also usefull to delete old results.
// matchCount default is 0
init(matchCount = 0) { init(matchCount = 0) {
this["matches"] = []; // list of all c with lc and rc this["matches"] = []; // list of all c with lc and rc
this["cpos_lookup"] = {}; // object contains all this key value pair this["cpos_lookup"] = {}; // object contains all this key value pair
@ -40,14 +41,19 @@ class ResultsJSON {
let resultFilename; let resultFilename;
// get and create metadata // get and create metadata
today = new Date(); today = new Date();
currentDate = today.getUTCFullYear() + '-' + (today.getUTCMonth() +1) + '-' + today.getUTCDate(); currentDate = `${today.getUTCFullYear()}` +
currentTime = today.getUTCHours() + ":" + today.getUTCMinutes() + ":" + today.getUTCSeconds(); `-${(today.getUTCMonth() + 1)}` +
`-${today.getUTCDate()}`;
currentTime = `${today.getUTCHours()}h` +
`${today.getUTCMinutes()}m` +
`${today.getUTCSeconds()}s`;
safeFilename = this.query.replace(/[^a-z0-9_-]/gi, "_"); safeFilename = this.query.replace(/[^a-z0-9_-]/gi, "_");
resultFilename = "UTC-" + currentDate + "_" + currentTime + "_" + safeFilename; resultFilename = `UTC-${currentDate}_${currentTime}_${safeFilename}`;
return resultFilename return resultFilename
} }
// Function to download data as a Blob created from a string, should be multi purpose // Function to download data as Blob created from string
// should be private but that is not yet a feature of javascript 08.04.2020
download(downloadElem, dataStr, filename, type, filenameSlug) { download(downloadElem, dataStr, filename, type, filenameSlug) {
let file; let file;
console.log("Start Download!"); console.log("Start Download!");
@ -68,7 +74,8 @@ class ResultsJSON {
let dataStr; let dataStr;
let downloadElement; let downloadElement;
// stringify JSON object for json download // stringify JSON object for json download
dataStr = JSON.stringify(results.resultsJSON, undefined, "\t"); // use tabs to save some space // use tabs to save some space
dataStr = JSON.stringify(results.resultsJSON, undefined, "\t");
// get downloadResultsElement // get downloadResultsElement
downloadElement = document.getElementById("download-results-json"); downloadElement = document.getElementById("download-results-json");
// start actual download // start actual download

View File

@ -2,22 +2,22 @@ function querySetup(payload) {
// This is called when a query was successfull // This is called when a query was successfull
// some hiding // some hiding
queryResultsExportElement.classList.add("disabled"); queryResultsExportElement.classList.add("disabled");
console.log("Query initial setup seccessfull.");
queryResultsDeterminateElement.style.width = "0%"; queryResultsDeterminateElement.style.width = "0%";
queryResultsProgressElement.classList.remove("hide"); queryResultsProgressElement.classList.remove("hide");
queryResultsUserFeedbackElement.classList.remove("hide"); queryResultsUserFeedbackElement.classList.remove("hide");
// some initial values
receivedMatchCountElement.innerText = "0"; receivedMatchCountElement.innerText = "0";
textLookupCountElement.innerText = "0"; textLookupCountElement.innerText = "0";
matchCountElement.innerText = payload.match_count; matchCountElement.innerText = payload.match_count;
// always re initializes results to delete old results from it // always re initializes results to delete old results from it
// this has to be done here again because teh last chunk from old results was still being recieved // this has to be done here again because the last chunk from old results was still being recieved
results.clear_all() results.clear_all()
// Get query string again // Get query string again
results.resultsJSON.getQueryStr(queryFormElement); results.resultsJSON.getQueryStr(queryFormElement);
} }
function queryRenderResults(payload) { function queryRenderResults(payload) {
let resultItems; // array of built html result items row element
// This is called when results are transmitted and being recieved // This is called when results are transmitted and being recieved
console.log("Current recieved chunk:", payload.chunk); console.log("Current recieved chunk:", payload.chunk);
if (payload.chunk.cpos_ranges == true) { if (payload.chunk.cpos_ranges == true) {
@ -54,7 +54,7 @@ function queryRenderResults(payload) {
queryResultsProgressElement.classList.add("hide"); queryResultsProgressElement.classList.add("hide");
queryResultsUserFeedbackElement.classList.add("hide"); queryResultsUserFeedbackElement.classList.add("hide");
queryResultsExportElement.classList.remove("disabled"); queryResultsExportElement.classList.remove("disabled");
ResultsList.activateInspect(); results.resultsList.activateInspect();
} }
// inital expert mode check and activation // inital expert mode check and activation
if (expertModeSwitchElement.checked) { if (expertModeSwitchElement.checked) {

View File

@ -81,11 +81,16 @@ RessourceList.options = {
<i class="description"></i> <i class="description"></i>
</td> </td>
<td> <td>
<span class="badge new status" data-badge-caption=""></span> <span class="badge new status" data-badge-caption="">
</span>
</td> </td>
<td class="right-align"> <td class="right-align">
<a class="btn-small edit-link waves-effect waves-light"><i class="material-icons">edit</i></a> <a class="btn-small edit-link waves-effect waves-light">
<a class="btn-small analyse-link waves-effect waves-light">Analyse<i class="material-icons right">search</i></a> <i class="material-icons">edit</i>
</a>
<a class="btn-small analyse-link waves-effect waves-light">
Analyse<i class="material-icons right">search</i>
</a>
</td> </td>
</tr>`, </tr>`,
valueNames: ["creation_date", "description", "title", valueNames: ["creation_date", "description", "title",
@ -107,7 +112,9 @@ RessourceList.options = {
<span class="badge new status" data-badge-caption=""></span> <span class="badge new status" data-badge-caption=""></span>
</td> </td>
<td class="right-align"> <td class="right-align">
<a class="btn-small link waves-effect waves-light">View<i class="material-icons right">send</i></a> <a class="btn-small link waves-effect waves-light">
View<i class="material-icons right">send</i>
</a>
</td> </td>
</tr>`, </tr>`,
valueNames: ["creation_date", "description", "title", valueNames: ["creation_date", "description", "title",
@ -126,17 +133,20 @@ class ResultsList extends List {
let displayOptionsFormData let displayOptionsFormData
let displayOptionsData; let displayOptionsData;
displayOptionsFormData = new FormData(displayOptionsFormElement); displayOptionsFormData = new FormData(displayOptionsFormElement);
displayOptionsData = {"resultsPerPage": displayOptionsFormData.get("display-options-form-results_per_page"), displayOptionsData =
{
"resultsPerPage": displayOptionsFormData.get("display-options-form-results_per_page"),
"resultsContex": displayOptionsFormData.get("display-options-form-result_context"), "resultsContex": displayOptionsFormData.get("display-options-form-result_context"),
"expertMode": displayOptionsFormData.get("display-options-form-expert_mode")}; "expertMode": displayOptionsFormData.get("display-options-form-expert_mode")
};
return displayOptionsData return displayOptionsData
} }
// ###### Functions to inspect one match, to show more details ###### // ###### Functions to inspect one match, to show more details ######
// activate inspect buttons if queryFinished is true // activate inspect buttons if progress is 100
static activateInspect() { activateInspect() {
if (progress === 100) {
let inspectBtnElements; let inspectBtnElements;
if (progress === 100) {
inspectBtnElements = document.getElementsByClassName("inspect"); inspectBtnElements = document.getElementsByClassName("inspect");
for (let inspectBtn of inspectBtnElements) { for (let inspectBtn of inspectBtnElements) {
inspectBtn.classList.remove("disabled"); inspectBtn.classList.remove("disabled");
@ -148,10 +158,8 @@ class ResultsList extends List {
//gets result cpos infos for one dataIndex to send back to the server //gets result cpos infos for one dataIndex to send back to the server
inspect(dataIndex) { inspect(dataIndex) {
// This function should be in the AnalysisClient class as a method. let contextResultsElement;
console.log("Inspect!"); contextResultsElement = document.getElementById("context-results");
console.log(results.resultsJSON.matches[dataIndex].c);
let contextResultsElement = document.getElementById("context-results");
contextResultsElement.innerHTML = ""; // clear it from old inspects contextResultsElement.innerHTML = ""; // clear it from old inspects
contextModal.open(); contextModal.open();
nopaque.socket.emit("corpus_analysis_inspect_match", nopaque.socket.emit("corpus_analysis_inspect_match",
@ -159,29 +167,30 @@ class ResultsList extends List {
first_cpos: results.resultsJSON.matches[dataIndex].c[0], first_cpos: results.resultsJSON.matches[dataIndex].c[0],
last_cpos: results.resultsJSON.matches[dataIndex].c[1] last_cpos: results.resultsJSON.matches[dataIndex].c[1]
} }
}); }
);
} }
showMatchContext(response) { showMatchContext(response) {
let contextData = response.payload let c;
let contextResultsElement; let contextData;
let contextModalLoading; let contextModalLoading;
let contextModalReady; let contextModalReady;
let expertModeSwitchElement let contextResultsElement;
let partElement let expertModeSwitchElement;
let lc;
let partElement;
let rc;
let token; let token;
let tokenElement; let tokenElement;
let tokenElements; let tokenElements;
let lc; contextData = response.payload;
let c;
let rc;
console.log("###### match_context ######");
console.log("Incoming data:", contextData);
expertModeSwitchElement = document.getElementById("display-options-form-expert_mode");
contextResultsElement = document.getElementById("context-results"); contextResultsElement = document.getElementById("context-results");
expertModeSwitchElement = document.getElementById("display-options-form-expert_mode");
// check if cpos ranges are used or not
if (contextData.cpos_ranges == true) { 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) // 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)); 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) lc = range(contextData.match.lc[0], contextData.match.lc[1], 1)
c = range(contextData.match.c[0], contextData.match.c[1], 1) c = range(contextData.match.c[0], contextData.match.c[1], 1)
@ -191,26 +200,29 @@ class ResultsList extends List {
c = contextData.match.c; c = contextData.match.c;
rc = contextData.match.rc; rc = contextData.match.rc;
} }
// create sentence strings as tokens
partElement = document.createElement("p"); partElement = document.createElement("p");
for (let cpos of lc) { for (let cpos of lc) {
token = contextData["cpos_lookup"][cpos]; token = contextData["cpos_lookup"][cpos];
partElement.insertAdjacentHTML("beforeend", `<span class="token" data-cpos="${cpos}">${token["word"]} </span>`); partElement.insertAdjacentHTML("beforeend",
`<span class="token" data-cpos="${cpos}">${token["word"]} </span>`);
contextResultsElement.append(partElement); contextResultsElement.append(partElement);
} }
for (let cpos of c) { for (let cpos of c) {
token = contextData["cpos_lookup"][cpos]; token = contextData["cpos_lookup"][cpos];
partElement.insertAdjacentHTML("beforeend", `<span class="token bold light-green" data-cpos="${cpos}" style="text-decoration-line: underline;">${token["word"]} </span>`); partElement.insertAdjacentHTML("beforeend",
`<span class="token bold light-green" data-cpos="${cpos}"` +
`style="text-decoration-line: underline;">${token["word"]} </span>`);
contextResultsElement.append(partElement); contextResultsElement.append(partElement);
} }
for (let cpos of rc) { for (let cpos of rc) {
token = contextData["cpos_lookup"][cpos]; token = contextData["cpos_lookup"][cpos];
partElement.insertAdjacentHTML("beforeend", `<span class="token" data-cpos="${cpos}">${token["word"]} </span>`); partElement.insertAdjacentHTML("beforeend",
`<span class="token" data-cpos="${cpos}">${token["word"]} </span>`);
contextResultsElement.append(partElement); contextResultsElement.append(partElement);
} }
if (expertModeSwitchElement.checked) { if (expertModeSwitchElement.checked) {
tokenElements = partElement.getElementsByClassName("token"); tokenElements = partElement.getElementsByClassName("token");
console.log(this);
this.expertModeOn(tokenElements, contextData); this.expertModeOn(tokenElements, contextData);
} }
} }
@ -225,31 +237,29 @@ class ResultsList extends List {
resultsList.update(); resultsList.update();
nopaque.flash("Updated matches per page.") nopaque.flash("Updated matches per page.")
} catch (e) { } catch (e) {
console.log("resultsList has no results right now. Live update of items per page is useless for now."); console.log("resultsList has no results right now.");
} }
} }
// Event function triggered on context select change and also if pagination is clicked // Event function triggered on context select change
// also if pagination is clicked
changeContext(event) { changeContext(event) {
let newContextValue;
let lc;
let rc;
let array; let array;
let lc;
let newContextValue;
let rc;
try { try {
if (event.type === "change") { if (event.type === "change") {
nopaque.flash("Updated context per match!"); nopaque.flash("Updated context per match!");
} }
} catch (e) { } catch (e) {
// console.log(e);
// console.log("This error is expected.");
} finally { } finally {
newContextValue = document.getElementById("display-options-form-result_context").value; newContextValue = document.getElementById("display-options-form-result_context").value;
console.log("Context value is:", newContextValue);
lc = document.getElementsByClassName("left-context"); lc = document.getElementsByClassName("left-context");
rc = document.getElementsByClassName("right-context"); rc = document.getElementsByClassName("right-context");
for (let element of lc) { for (let element of lc) {
array = Array.from(element.childNodes); array = Array.from(element.childNodes);
for (let element of array.slice(newContextValue)) { for (let element of array.reverse().slice(newContextValue)) {
element.classList.add("hide"); element.classList.add("hide");
} }
for (let element of array.slice(0, newContextValue)) { for (let element of array.slice(0, newContextValue)) {
@ -275,13 +285,10 @@ class ResultsList extends List {
// if checked than expertModeOn is executed // if checked than expertModeOn is executed
// if unchecked expertModeOff is executed // if unchecked expertModeOff is executed
eventHandlerCheck(event) { eventHandlerCheck(event) {
console.log("pagination used!");
console.log(expertModeSwitchElement.checked);
if (expertModeSwitchElement.checked) { if (expertModeSwitchElement.checked) {
this.expertModeOn(event.currentTarget.tokenElements, resultsJSON); this.expertModeOn(event.currentTarget.tokenElements, resultsJSON);
} else if (!expertModeSwitchElement.checked) { } else if (!expertModeSwitchElement.checked) {
event.preventDefault(); event.preventDefault();
console.log("prevented! Destroy");
this.expertModeOff(event.currentTarget.tokenElements); this.expertModeOff(event.currentTarget.tokenElements);
} }
} }
@ -289,17 +296,13 @@ class ResultsList extends List {
// function to apply extra information and animation to every token // function to apply extra information and animation to every token
expertModeOn(tokenElements, results) { expertModeOn(tokenElements, results) {
let token; let token;
console.log("expertModeOn!");
for (let tokenElement of tokenElements) { for (let tokenElement of tokenElements) {
tokenElement.classList.add("chip"); tokenElement.classList.add("chip");
tokenElement.classList.add("hoverable"); tokenElement.classList.add("hoverable");
tokenElement.classList.add("expert-view"); tokenElement.classList.add("expert-view");
token = results["cpos_lookup"][tokenElement.dataset.cpos]; token = results.cpos_lookup[tokenElement.dataset.cpos];
tokenElement.addEventListener("mouseover", (event) => { tokenElement.addEventListener("mouseover", (event) => {
console.log("Mouseover!"); token = results.cpos_lookup[event.target.dataset.cpos];
console.log(event.target);
token = results["cpos_lookup"][event.target.dataset.cpos];
this.addToolTipToTokenElement(event.target, token); this.addToolTipToTokenElement(event.target, token);
}); });
} }
@ -316,19 +319,22 @@ class ResultsList extends List {
</tr> </tr>
<tr> <tr>
<td class="left-align"> <td class="left-align">
Word: ${token["word"]}<br> Word: ${token.word}<br>
Lemma: ${token["lemma"]}<br> Lemma: ${token.lemma}<br>
POS: ${token["pos"]}<br> POS: ${token.pos}<br>
Simple POS: ${token["simple_pos"]}<br> Simple POS: ${token.simple_pos}<br>
NER: ${token["ner"]} NER: ${token.ner}
</td> </td>
<td class="left-align"> <td class="left-align">
Title: ${resultsJSON["text_lookup"][token["text"]]["title"]}<br> Title: ${resultsJSON.text_lookup[token.text].title}
Author: ${resultsJSON["text_lookup"][token["text"]]["author"]}<br> <br>
Publishing year: ${resultsJSON["text_lookup"][token["text"]]["publishing_year"]} Author: ${resultsJSON.text_lookup[token.text].author}
<br>
Publishing year: ${resultsJSON.text_lookup[token.text].publishing_year}
</td> </td>
</tr> </tr>
</table>`}); </table>`}
);
} }
// function to remove extra informations and animations from tokens // function to remove extra informations and animations from tokens
@ -343,11 +349,25 @@ class ResultsList extends List {
} }
createResultRowElement(item, chunk) { createResultRowElement(item, chunk) {
let values, cpos, token, matchRowElement, lcCellElement, hitCellElement, rcCellElement, textTitlesCellElement, matchNrElement, lc, c, rc; let c;
let cCellElement;
let cpos;
let inspectBtn
let lc;
let lcCellElement;
let matchNrElement;
let matchRowElement;
let rc;
let rcCellElement;
let textTitles;
let textTitlesCellElement;
let token;
let values;
// gather values from item // gather values from item
values = item.values(); values = item.values();
if (chunk.cpos_ranges == true) { if (chunk.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) // 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)); const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));
lc = range(values.lc[0], values.lc[1], 1) lc = range(values.lc[0], values.lc[1], 1)
c = range(values.c[0], values.c[1], 1) c = range(values.c[0], values.c[1], 1)
@ -364,35 +384,39 @@ class ResultsList extends List {
lcCellElement.classList.add("left-context"); lcCellElement.classList.add("left-context");
matchRowElement.appendChild(lcCellElement); matchRowElement.appendChild(lcCellElement);
for (cpos of lc) { for (cpos of lc) {
token = chunk["cpos_lookup"][cpos]; token = chunk.cpos_lookup[cpos];
lcCellElement.insertAdjacentHTML("beforeend", `<span class="token" data-cpos="${cpos}">${token["word"]} </span>`); lcCellElement.insertAdjacentHTML("beforeend",
`<span class="token" data-cpos="${cpos}">${token.word} </span>`);
} }
// get infos for hit of match // get infos for hit of match
let textTitles = new Set(); textTitles = new Set();
hitCellElement = document.createElement("td"); cCellElement = document.createElement("td");
hitCellElement.classList.add("match-hit"); cCellElement.classList.add("match-hit");
textTitlesCellElement = document.createElement("td"); textTitlesCellElement = document.createElement("td");
textTitlesCellElement.classList.add("titles"); textTitlesCellElement.classList.add("titles");
matchNrElement = document.createElement("td"); matchNrElement = document.createElement("td");
matchNrElement.classList.add("match-nr"); matchNrElement.classList.add("match-nr");
matchRowElement.appendChild(hitCellElement); matchRowElement.appendChild(cCellElement);
for (cpos of c) { for (cpos of c) {
token = chunk["cpos_lookup"][cpos]; token = chunk.cpos_lookup[cpos];
hitCellElement.insertAdjacentHTML("beforeend", `<span class="token" data-cpos="${cpos}">${token["word"]} </span>`); cCellElement.insertAdjacentHTML("beforeend",
`<span class="token" data-cpos="${cpos}">${token.word} </span>`);
// get text titles of every hit cpos token // get text titles of every hit cpos token
textTitles.add(chunk["text_lookup"][token["text"]]["title"]); textTitles.add(chunk.text_lookup[token.text].title);
// add button to trigger more context to every match td // add button to trigger more context to every match td
var inspectBtn = document.createElement("a"); inspectBtn = document.createElement("a");
inspectBtn.setAttribute("class", "btn-floating btn-flat waves-effect waves-light grey right inspect disabled"); inspectBtn.setAttribute("class", `btn-floating btn-flat waves-effect` +
`waves-light grey right inspect disabled`
);
inspectBtn.innerHTML = '<i class="material-icons">search</i>'; inspectBtn.innerHTML = '<i class="material-icons">search</i>';
inspectBtn.onclick = () => {this.inspect(values["index"])}; inspectBtn.onclick = () => {this.inspect(values.index)};
} }
// add text titles at front as first td of one row // add text titles at front as first td of one row
hitCellElement.appendChild(inspectBtn); cCellElement.appendChild(inspectBtn);
textTitlesCellElement.innerText = [...textTitles].join(", "); textTitlesCellElement.innerText = [...textTitles].join(", ");
matchRowElement.insertAdjacentHTML("afterbegin", textTitlesCellElement.outerHTML); matchRowElement.insertAdjacentHTML("afterbegin", textTitlesCellElement.outerHTML);
matchNrElement.innerText = values["index"] + 1; matchNrElement.innerText = values.index + 1;
matchRowElement.insertAdjacentHTML("afterbegin", matchNrElement.outerHTML); matchRowElement.insertAdjacentHTML("afterbegin", matchNrElement.outerHTML);
// get infos for right context of match // get infos for right context of match
@ -401,7 +425,8 @@ class ResultsList extends List {
matchRowElement.appendChild(rcCellElement); matchRowElement.appendChild(rcCellElement);
for (cpos of rc) { for (cpos of rc) {
token = chunk["cpos_lookup"][cpos]; token = chunk["cpos_lookup"][cpos];
rcCellElement.insertAdjacentHTML("beforeend", `<span class="token" data-cpos="${cpos}">${token["word"]} </span>`); rcCellElement.insertAdjacentHTML("beforeend",
`<span class="token" data-cpos="${cpos}">${token.word} </span>`);
} }
return matchRowElement return matchRowElement
} }

View File

@ -217,36 +217,60 @@
<script src="{{ url_for('static', filename='js/nopaque.callbacks.js') }}"> <script src="{{ url_for('static', filename='js/nopaque.callbacks.js') }}">
</script> </script>
<script> <script>
// ###### Defining global variables used in other functions ###### // ###### Defining global variables used in other functions ######
var client; // CorpusAnalysisClient first undefined on DOMContentLoaded defined
var collapsibleElements; // All collapsibleElements on this page
var collapsibleElements; // all collapsibles on site
var contextModal; // Modal to open on inspect for further match context
var displayOptionsData; // Getting form data from display options
var displayOptionsFormElement; // Form holding the display informations
var downloadResultsJSONElement; // button for downloading results as JSON
var expertModeSwitchElement; // Expert mode switch Element
var exportModal; // Download options modal
var firstPageElement; // first page element of resultsList pagination
var initDisplay; // CorpusAnalysisDisplay object first undfined on DOMContentLoaded defined
var initDisplayElement; // Element for initialization using initDisplay
var initModal;
var matchCountElement; // Total nr. of matches will be displayed in this element
var progress; // global progress value
var queryDisplay; // CorpusAnalysisDisplay object first undfined on DOMContentLoaded defined
var queryDisplayElement; // Element for initialization using queryDisplay
var queryFormElement; // the query form
var queryResultsDeterminateElement; // The progress bar for recieved results
var queryResultsExportElement; // Download button opens download modal
var queryResultsProgressElement; // Div element holding the progress bar
var queryResultsUserFeedbackElement; // Element showing match count|total etc
var receivedMatchCountElement; // Nr. of loaded matches will be displayed in this element
var results; // results object var results; // results object
var resultsJSON; // full JSON object holding match results var resultsJSON; // full JSON object holding match results
var resultsList; // resultsList object var resultsList; // resultsList object
var queryFormElement; // the query form var resultsListOptions; // specifies ResultsList options
var collapsibleElements; // all collapsibles on site var textLookupCountElement // Nr of texts the matches occured in will be shown in this element
var progress; // global progress value var xpath; // xpath to grab first resultsList page pagination element
var queryResultsProgressElement; // Div element holding the progress bar
var queryResultsDeterminateElement; // The progress bar for recieved results
var queryResultsUserFeedbackElement; // Element showing match count|total etc
var queryResultsExportElement; // Download button opens download modal
var exportModal; // Download options modal
var contextModal; // Modal to open on inspect for further match context
var initModal;
var downloadResultsJSONElement; // button for downloading results as JSON
var displayOptionsFormElement;
// ###### Initialize variables ###### // ###### Initialize variables ######
client = undefined;
collapsibleElements = document.querySelector('.collapsible.expandable');
contextModal = document.getElementById("context-modal"); contextModal = document.getElementById("context-modal");
exportModal = document.getElementById("query-results-download-modal");
queryFormElement = document.getElementById("query-form");
queryResultsProgressElement = document.getElementById("query-results-progress");
queryResultsDeterminateElement = document.getElementById("query-results-determinate");
queryResultsUserFeedbackElement = document.getElementById("query-results-user-feedback");
queryResultsExportElement = document.getElementById("query-results-export");
displayOptionsFormElement = document.getElementById("display-options-form"); displayOptionsFormElement = document.getElementById("display-options-form");
expertModeSwitchElement = document.getElementById("display-options-form-expert_mode");
exportModal = document.getElementById("query-results-download-modal");
initDisplay = undefined;
initDisplayElement = document.getElementById("init-display");
matchCountElement = document.getElementById("match-count");
queryDisplay = undefined;
queryDisplayElement = document.getElementById("query-display");
queryFormElement = document.getElementById("query-form");
queryResultsDeterminateElement = document.getElementById("query-results-determinate");
queryResultsExportElement = document.getElementById("query-results-export");
queryResultsProgressElement = document.getElementById("query-results-progress");
queryResultsUserFeedbackElement = document.getElementById("query-results-user-feedback");
receivedMatchCountElement = document.getElementById("received-match-count");
textLookupCountElement = document.getElementById("text-lookup-count");
// js list options and intialization // ###### js list options and intialization ######
let displayOptionsData = ResultsList.getDisplayOptions(displayOptionsFormElement); displayOptionsData = ResultsList.getDisplayOptions(displayOptionsFormElement);
let resultsListOptions = {page: displayOptionsData["resultsPerPage"], resultsListOptions = {page: displayOptionsData["resultsPerPage"],
pagination: [{ pagination: [{
name: "paginationTop", name: "paginationTop",
paginationClass: "paginationTop", paginationClass: "paginationTop",
@ -260,23 +284,8 @@
valueNames: ["titles", "lc", "c", "rc", {data: ["index"]}], valueNames: ["titles", "lc", "c", "rc", {data: ["index"]}],
item: `<span></span>`}; item: `<span></span>`};
// ###### Set some css options ######
// get collapsibles to alter options of those
var collapsibleElements = document.querySelector('.collapsible.expandable');
var client = undefined;
var initDisplay = undefined;
var queryDisplay = undefined;
var initDisplayElement = document.getElementById("init-display");
var queryDisplayElement = document.getElementById("query-display");
receivedMatchCountElement = document.getElementById("received-match-count");
matchCountElement = document.getElementById("match-count");
textLookupCountElement = document.getElementById("text-lookup-count");
var expertModeSwitchElement = document.getElementById("display-options-form-expert_mode");
// ###### event on DOMContentLoaded ######
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
//set accordion of collapsibles to false //set accordion of collapsibles to false
M.Collapsible.init(collapsibleElements, {accordion: false}); M.Collapsible.init(collapsibleElements, {accordion: false});
@ -311,6 +320,19 @@
client.init(); client.init();
// start a query request on submit // start a query request on submit
queryFormElement.addEventListener("submit", (event) => { queryFormElement.addEventListener("submit", (event) => {
try {
// Selects first page of result list if pagination is already available
// from an query submitted before.
// This avoids confusion for the user eg: The user was on page 24
// reviewing the results and issues a new query. He would not see any
// results until the new results reach page 24 or he clicks on another
// valid result page element from the new pagination.
firstPageElement;
xpath = '//a[@class="page" and text()=1]';
firstPageElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
firstPageElement.click();
} catch (e) {
}
// Prevent page from reloading on submit // Prevent page from reloading on submit
event.preventDefault(); event.preventDefault();
// empty ResultsList and ResultsJSON for new query // empty ResultsList and ResultsJSON for new query
@ -336,7 +358,7 @@
paginationElements = document.getElementsByClassName("pagination"); paginationElements = document.getElementsByClassName("pagination");
for (element of paginationElements) { for (element of paginationElements) {
element.addEventListener("click", results.resultsList.changeContext); element.addEventListener("click", results.resultsList.changeContext);
element.addEventListener("click", ResultsList.activateInspect); element.addEventListener("click", results.resultsList.activateInspect);
} }
// epxert mode table view // epxert mode table view
@ -344,16 +366,13 @@
let currentTokenElements = document.getElementsByClassName("token"); let currentTokenElements = document.getElementsByClassName("token");
let paginationElements = document.getElementsByClassName("pagination"); let paginationElements = document.getElementsByClassName("pagination");
if (event.target.checked) { if (event.target.checked) {
console.log("Checked!");
results.resultsList.expertModeOn(currentTokenElements, resultsJSON); results.resultsList.expertModeOn(currentTokenElements, resultsJSON);
for (element of paginationElements) { for (element of paginationElements) {
element.tokenElements = currentTokenElements; element.tokenElements = currentTokenElements;
element.addEventListener("click", (event) => { results.resultsList.eventHandlerCheck(event)}); element.addEventListener("click", (event) => { results.resultsList.eventHandlerCheck(event)});
} }
} else { } else {
console.log("Unchecked!");
results.resultsList.expertModeOff(currentTokenElements); results.resultsList.expertModeOff(currentTokenElements);
console.log("unchecked! Destroy");
} }
}); });
}); });