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