2020-01-31 13:14:08 +00:00
class RessourceList extends List {
2020-02-12 11:19:54 +00:00
constructor ( idOrElement , subscriberList , type , options = { } ) {
2020-07-15 12:52:41 +00:00
if ( ! [ "Corpus" , "CorpusFile" , "Job" , "JobInput" , "QueryResult" , "User" ] . includes ( type ) ) {
2020-02-12 11:19:54 +00:00
console . error ( "Unknown Type!" ) ;
return ;
}
2020-07-07 13:08:15 +00:00
if ( subscriberList ) {
2020-07-13 13:33:00 +00:00
super ( idOrElement , { ... RessourceList . options [ 'common' ] ,
... RessourceList . options [ type ] ,
... options } ) ;
this . type = type ;
subscriberList . push ( this ) ;
2020-07-07 13:08:15 +00:00
} else {
super ( idOrElement , { ... RessourceList . options [ 'extended' ] ,
... RessourceList . options [ type ] ,
... options } ) ;
this . type = type ;
}
2020-01-29 09:50:31 +00:00
}
2020-01-31 13:14:08 +00:00
_init ( ressources ) {
2020-04-30 09:28:55 +00:00
this . clear ( ) ;
2020-02-07 15:00:48 +00:00
this . addRessources ( Object . values ( ressources ) ) ;
2020-02-07 14:21:59 +00:00
this . sort ( "creation_date" , { order : "desc" } ) ;
2020-01-29 09:50:31 +00:00
}
_update ( patch ) {
2020-01-31 13:14:08 +00:00
let item , pathArray ;
2020-01-29 09:50:31 +00:00
2020-01-31 13:14:08 +00:00
for ( let operation of patch ) {
2020-04-30 09:28:55 +00:00
/* "/{ressourceName}/{ressourceId}/..." -> ["{ressourceId}", "..."] */
pathArray = operation . path . split ( "/" ) . slice ( 2 ) ;
2020-01-29 09:50:31 +00:00
switch ( operation . op ) {
case "add" :
2020-02-03 15:04:47 +00:00
if ( pathArray . includes ( "results" ) ) { break ; }
2020-02-07 15:00:48 +00:00
this . addRessources ( [ operation . value ] ) ;
2020-01-29 09:50:31 +00:00
break ;
case "remove" :
this . remove ( "id" , pathArray [ 0 ] ) ;
break ;
case "replace" :
item = this . get ( "id" , pathArray [ 0 ] ) [ 0 ] ;
switch ( pathArray [ 1 ] ) {
case "status" :
2020-04-16 11:28:09 +00:00
item . values ( { status : operation . value ,
"analyse-link" : [ "analysing" , "prepared" , "start analysis" ] . includes ( operation . value ) ? ` /corpora/ ${ pathArray [ 0 ] } /analyse ` : "" } ) ;
2020-01-29 09:50:31 +00:00
break ;
default :
break ;
}
default :
break ;
}
}
}
2020-02-07 15:00:48 +00:00
addRessources ( ressources ) {
2020-02-12 11:19:54 +00:00
this . add ( ressources . map ( x => RessourceList . dataMapper [ this . type ] ( x ) ) ) ;
2020-01-29 09:50:31 +00:00
}
2020-07-10 09:39:16 +00:00
// Use this to modify tooltips to show after 750ms. If loaded is set to
// true (default) tooltips will only be initialized if DOMContentLoaded event
// triggered. If you do not want to wait for this event set pass false.
static modifyTooltips ( waitForDOMContentLoaded = true ) {
if ( waitForDOMContentLoaded ) {
document . addEventListener ( 'DOMContentLoaded' , function ( ) {
var elems = document . querySelectorAll ( '.tooltipped' ) ;
var instances = M . Tooltip . init ( elems , { enterDelay : 750 } ) ;
} ) ;
} else {
var elems = document . querySelectorAll ( '.tooltipped' ) ;
var instances = M . Tooltip . init ( elems , { enterDelay : 750 } ) ;
}
}
2020-01-29 09:50:31 +00:00
}
2020-07-07 13:08:15 +00:00
2020-07-10 09:39:16 +00:00
2020-01-31 13:14:08 +00:00
RessourceList . dataMapper = {
2020-07-13 13:33:00 +00:00
// A data mapper describes entitys rendered per row. One key value pair holds
2020-07-08 09:35:47 +00:00
// the data to be rendered in the list.js table. Key has to correspond
// with the ValueNames defined below in RessourceList.options ValueNames.
// Links are declared with double ticks(") around them. The key for links
// have to correspond with the class of an <a> element in the
// RessourceList.options item blueprint.
2020-07-15 06:57:39 +00:00
// Mapping for Corpus entities shown in the dashboard table.
Corpus : corpus => ( { creation _date : corpus . creation _date ,
2020-07-17 06:43:02 +00:00
"delete-onclick" : ` prepareDeleteCorpusModal( ${ corpus . id } ) ` ,
2020-02-07 14:21:59 +00:00
description : corpus . description ,
id : corpus . id ,
2020-04-15 08:32:21 +00:00
"analyse-link" : [ "analysing" , "prepared" , "start analysis" ] . includes ( corpus . status ) ? ` /corpora/ ${ corpus . id } /analyse ` : "" ,
2020-02-12 11:19:54 +00:00
"edit-link" : ` /corpora/ ${ corpus . id } ` ,
2020-02-07 14:21:59 +00:00
status : corpus . status ,
2020-07-13 13:33:00 +00:00
title : corpus . title } ) ,
2020-07-08 13:24:18 +00:00
// Mapping for corpus file entities shown in the corpus overview
2020-07-15 06:57:39 +00:00
CorpusFile : corpus _file => ( { filename : corpus _file . filename ,
author : corpus _file . author ,
title : corpus _file . title ,
publishing _year : corpus _file . publishing _year ,
"edit-link" : ` ${ corpus _file . corpus _id } /files/ ${ corpus _file . id } /edit ` ,
"download-link" : ` ${ corpus _file . corpus _id } /files/ ${ corpus _file . id } /download ` ,
"delete-modal" : ` delete-corpus-file- ${ corpus _file . id } -modal ` } ) ,
2020-07-08 09:35:47 +00:00
// Mapping for job entities shown in the dashboard table.
2020-07-15 06:57:39 +00:00
Job : job => ( { creation _date : job . creation _date ,
2020-07-17 06:43:02 +00:00
"delete-onclick" : ` prepareDeleteJobModal( ${ job . id } ) ` ,
2020-02-07 14:21:59 +00:00
description : job . description ,
id : job . id ,
link : ` /jobs/ ${ job . id } ` ,
service : job . service ,
status : job . status ,
2020-07-13 13:33:00 +00:00
title : job . title } ) ,
2020-07-08 09:35:47 +00:00
// Mapping for job input files shown in table on every job page
2020-07-15 06:57:39 +00:00
JobInput : job _input => ( { filename : job _input . filename ,
id : job _input . job _id ,
"download-link" : ` ${ job _input . job _id } /inputs/ ${ job _input . id } /download ` } ) ,
2020-07-08 09:35:47 +00:00
// Mapping for imported result entities from corpus analysis.
// Shown in imported results table
2020-07-15 09:07:03 +00:00
QueryResult : query _result => ( { corpus _name : query _result . query _metadata . corpus _name ,
2020-07-17 06:43:02 +00:00
"delete-onclick" : ` prepareDeleteQueryResultModal( ${ query _result . id } ) ` ,
2020-07-15 09:07:03 +00:00
description : query _result . description ,
2020-07-15 06:57:39 +00:00
id : query _result . id ,
2020-07-15 11:16:31 +00:00
"inspect-link" : ` /query_results/ ${ query _result . id } /inspect ` ,
2020-07-15 06:57:39 +00:00
link : ` /query_results/ ${ query _result . id } ` ,
2020-07-15 09:07:03 +00:00
query : query _result . query _metadata . query ,
2020-07-15 06:57:39 +00:00
title : query _result . title } ) ,
2020-07-08 09:35:47 +00:00
// Mapping for user entities shown in admin table
2020-07-15 06:57:39 +00:00
User : user => ( { username : user . username ,
2020-07-07 14:06:09 +00:00
email : user . email ,
role _id : user . role _id ,
confirmed : user . confirmed ,
id : user . id ,
2020-07-13 13:33:00 +00:00
"profile-link" : ` user/ ${ user . id } ` } )
2020-01-31 13:14:08 +00:00
} ;
2020-07-07 13:08:15 +00:00
2020-01-31 13:14:08 +00:00
RessourceList . options = {
2020-07-08 09:35:47 +00:00
// common list.js options for 4 rows per page etc.
2020-02-12 11:19:54 +00:00
common : { page : 4 , pagination : { innerWindow : 8 , outerWindow : 1 } } ,
2020-07-08 09:35:47 +00:00
// extended list.js options for 10 rows per page etc.
2020-07-07 13:08:15 +00:00
extended : { page : 10 ,
2020-07-15 06:57:39 +00:00
pagination : [ { name : "paginationTop" ,
paginationClass : "paginationTop" ,
innerWindow : 8 ,
outerWindow : 1 } ,
{ paginationClass : "paginationBottom" ,
innerWindow : 8 ,
outerWindow : 1 } ] } ,
/ * T y p e s p e c i f i c L i s t . j s o p t i o n s . U s u a l l y o n l y " i t e m " a n d " v a l u e N a m e s " g e t s
* defined here but it is possible to define other List . js options .
* item : https : //listjs.com/api/#item
* valueNames : https : //listjs.com/api/#valueNames
* /
Corpus : { item : ` <tr>
2020-02-12 11:19:54 +00:00
< td >
< a class = "btn-floating disabled" >
< i class = "material-icons service" > book < / i >
< / a >
< / t d >
< td >
< b class = "title" > < / b > < b r >
< i class = "description" > < / i >
< / t d >
< td >
2020-04-08 09:37:34 +00:00
< span class = "badge new status" data - badge - caption = "" >
< / s p a n >
2020-02-12 11:19:54 +00:00
< / t d >
2020-07-10 07:32:16 +00:00
< td class = "actions right-align" >
2020-07-17 06:43:02 +00:00
< a class = "btn-floating modal-trigger red tooltipped waves-effect waves-light delete-onclick" data - position = "top" data - tooltip = "Delete" >
< i class = "material-icons" > delete < / i >
< / a >
2020-07-15 06:57:39 +00:00
< a class = "btn-floating tooltipped waves-effect waves-light edit-link" data - position = "top" data - tooltip = "Edit" >
2020-04-08 09:37:34 +00:00
< i class = "material-icons" > edit < / i >
< / a >
2020-07-15 06:57:39 +00:00
< a class = "btn-floating tooltipped waves-effect waves-light analyse-link" data - position = "top" data - tooltip = "Analyse" >
2020-07-08 13:24:18 +00:00
< i class = "material-icons" > search < / i >
2020-04-08 09:37:34 +00:00
< / a >
2020-02-12 11:19:54 +00:00
< / t d >
< / t r > ` ,
2020-07-08 09:35:47 +00:00
valueNames : [ "creation_date" ,
"description" ,
"title" ,
2020-02-12 11:19:54 +00:00
{ data : [ "id" ] } ,
{ name : "analyse-link" , attr : "href" } ,
2020-07-17 06:43:02 +00:00
{ name : "delete-onclick" , attr : "onclick" } ,
2020-02-12 11:19:54 +00:00
{ name : "edit-link" , attr : "href" } ,
2020-07-15 06:57:39 +00:00
{ name : "status" , attr : "data-status" } ] } ,
CorpusFile : { item : ` <tr>
2020-07-08 13:24:18 +00:00
< td class = "filename" style = "word-break: break-word;" > < / t d >
< td class = "author" style = "word-break: break-word;" > < / t d >
< td class = "title" style = "word-break: break-word;" > < / t d >
< td class = "publishing_year" style = "word-break: break-word;" > < / t d >
2020-07-10 07:32:16 +00:00
< td class = "actions right-align" >
2020-07-15 06:57:39 +00:00
< a class = "btn-floating tooltipped waves-effect waves-light edit-link" data - position = "top" data - tooltip = "Edit" >
2020-07-08 13:24:18 +00:00
< i class = "material-icons" > edit < / i >
< / a >
2020-07-15 06:57:39 +00:00
< a class = "btn-floating tooltipped waves-effect waves-light download-link" data - position = "top" data - tooltip = "Download" >
2020-07-08 13:24:18 +00:00
< i class = "material-icons" > file _download < / i >
< / a >
2020-07-15 06:57:39 +00:00
< a class = "btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal" data - position = "top" data - tooltip = "Delete" >
2020-07-08 13:24:18 +00:00
< i class = "material-icons" > delete < / i >
< / a >
< / t d >
< / t r > ` ,
2020-07-15 06:57:39 +00:00
valueNames : [ "filename" ,
2020-07-08 13:24:18 +00:00
"author" ,
"title" ,
"publishing_year" ,
{ name : "edit-link" , attr : "href" } ,
{ name : "download-link" , attr : "href" } ,
2020-07-15 06:57:39 +00:00
{ name : "delete-modal" , attr : "data-target" } ] } ,
Job : { item : ` <tr>
2020-02-12 11:19:54 +00:00
< td >
< a class = "btn-floating disabled" >
< i class = "material-icons service" > < / i >
< / a >
< / t d >
< td >
< b class = "title" > < / b > < b r >
< i class = "description" > < / i >
< / t d >
< td >
< span class = "badge new status" data - badge - caption = "" > < / s p a n >
< / t d >
2020-07-10 07:32:16 +00:00
< td class = "actions right-align" >
2020-07-17 06:43:02 +00:00
< a class = "btn-floating modal-trigger red tooltipped waves-effect waves-light delete-onclick" data - position = "top" data - tooltip = "Delete" >
< i class = "material-icons" > delete < / i >
< / a >
2020-07-15 06:57:39 +00:00
< a class = "btn-floating tooltipped waves-effect waves-light link" data - position = "top" data - tooltip = "Go to Job" >
< i class = "material-icons" > send < / i >
2020-04-08 09:37:34 +00:00
< / a >
2020-02-12 11:19:54 +00:00
< / t d >
< / t r > ` ,
2020-07-08 09:35:47 +00:00
valueNames : [ "creation_date" ,
"description" ,
"title" ,
2020-02-12 11:19:54 +00:00
{ data : [ "id" ] } ,
2020-07-17 06:43:02 +00:00
{ name : "delete-onclick" , attr : "onclick" } ,
2020-02-12 11:19:54 +00:00
{ name : "link" , attr : "href" } ,
{ name : "service" , attr : "data-service" } ,
2020-07-15 06:57:39 +00:00
{ name : "status" , attr : "data-status" } ] } ,
JobInput : { item : ` <tr>
< td class = "filename" > < / t d >
2020-07-17 06:43:02 +00:00
< td class = "actions right-align" >
< a class = "btn-floating tooltipped waves-effect waves-light download-link" data - position = "top" data - tooltip = "Download" >
< i class = "material-icons" > file _download < / i >
< / a >
< / t d >
< / t r > ` ,
2020-07-15 06:57:39 +00:00
valueNames : [ "filename" ,
"id" ,
{ name : "download-link" , attr : "href" } ] } ,
QueryResult : { item : ` <tr>
< td >
2020-07-15 09:07:03 +00:00
< b class = "title" > < / b > < b r >
< i class = "description" > < / i > < b r >
< / t d >
< td >
< span class = "corpus_name" > < / s p a n > < b r >
< span class = "query" > < / s p a n >
< / t d >
< td class = "actions right-align" >
2020-07-17 06:43:02 +00:00
< a class = "btn-floating modal-trigger red tooltipped waves-effect waves-light delete-onclick" data - position = "top" data - tooltip = "Delete" >
2020-07-16 12:40:57 +00:00
< i class = "material-icons" > delete < / i >
< / a >
2020-07-17 06:43:02 +00:00
< a class = "btn-floating tooltipped link waves-effect waves-light" data - position = "top" data - tooltip = "Info" >
< i class = "material-icons" > info < / i >
< / a >
< a class = "btn-floating tooltipped waves-effect waves-light inspect-link" data - position = "top" data - tooltip = "Analyse" >
< i class = "material-icons" > search < / i >
2020-07-15 06:57:39 +00:00
< / a >
2020-07-15 09:07:03 +00:00
< / t d >
< / t r > ` ,
valueNames : [ "corpus_name" ,
"description" ,
"query" ,
2020-07-15 06:57:39 +00:00
"title" ,
{ data : [ "id" ] } ,
2020-07-17 06:43:02 +00:00
{ name : "delete-onclick" , attr : "onclick" } ,
2020-07-15 11:16:31 +00:00
{ name : "inspect-link" , attr : "href" } ,
2020-07-15 06:57:39 +00:00
{ name : "link" , attr : "href" } ] } ,
2020-07-08 09:35:47 +00:00
// User entity blueprint setting html strucuture per entity per row
// Link classes have to correspond with Links defined in the Mapping process
2020-07-15 06:57:39 +00:00
User : { item : ` <tr>
2020-07-07 14:06:09 +00:00
< td class = "username" > < / t d >
< td class = "email" > < / t d >
< td class = "role_id" > < / t d >
< td class = "confirmed" > < / t d >
< td class = "id" > < / t d >
2020-07-10 07:32:16 +00:00
< td class = "actions right-align" >
2020-07-15 06:57:39 +00:00
< a class = "btn-floating tooltipped profile-link waves-effect waves-light" data - position = "top" data - tooltip = "Edit User" >
< i class = "material-icons" > edit < / i >
< / a >
2020-07-07 14:06:09 +00:00
< / t d >
< / t r > ` ,
valueNames : [ "username" ,
"email" ,
"role_id" ,
"confirmed" ,
"id" ,
2020-07-15 06:57:39 +00:00
{ name : "profile-link" , attr : "href" } ] }
2020-02-12 11:19:54 +00:00
} ;
2020-01-29 15:12:57 +00:00
2020-04-02 12:22:03 +00:00
class ResultsList extends List {
2020-04-09 12:49:17 +00:00
constructor ( idOrElement , options = { } ) {
2020-04-14 09:31:57 +00:00
super ( idOrElement , options ) ;
2020-04-23 10:07:08 +00:00
this . eventTokens = { } ; // all span tokens which are holdeing events if expert
// mode is on. Collected here to delete later on
this . currentExpertTokenElements = { } ; // all token elements which have added
// classes like chip and hoverable for expert view. Collected
//here to delete later on
2020-06-26 07:51:10 +00:00
this . addToSubResultsStatus = { } ; // holds True/false for check buttons used to add matches tu sub-results. If checked, it is True. If unchecked, it is false. Buttons for this have the class add. Those little round check buttons.
this . addToSubResultsIdsToShow = new Set ( ) ; // If check button is pressed its corresponding data_index is saved in this set. The set is shown to the user.
2020-04-09 12:49:17 +00:00
}
2020-01-29 15:12:57 +00:00
2020-07-14 08:59:02 +00:00
helperCreateCpos ( cpos _ranges , cpos _values ) {
let lc ;
let c ;
let rc ;
if ( cpos _ranges ) {
// 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 ( cpos _values . lc [ 0 ] , cpos _values . lc [ 1 ] , 1 )
c = range ( cpos _values . c [ 0 ] , cpos _values . c [ 1 ] , 1 )
rc = range ( cpos _values . rc [ 0 ] , cpos _values . rc [ 1 ] , 1 )
} else {
lc = cpos _values . lc ;
c = cpos _values . c ;
rc = cpos _values . rc ;
}
return { lc : lc , c : c , rc : rc } ;
}
2020-06-19 10:30:05 +00:00
// handels interactionElements during a pagination navigation
2020-06-26 07:51:10 +00:00
// loops over interactionElements and executes callback functions accordingly
2020-06-19 10:30:05 +00:00
pageChangeEventInteractionHandler ( interactionElements ) {
// get elements to check thier status
for ( let interaction of interactionElements ) {
2020-06-19 13:49:11 +00:00
if ( interaction . checkStatus ) {
2020-06-25 15:44:55 +00:00
if ( interaction . element . checked ) {
2020-06-19 13:49:11 +00:00
let f _on = interaction . bindThisToCallback ( "on" ) ;
let args _on = interaction . callbacks . on . args ;
f _on ( ... args _on ) ;
} else {
let f _off = interaction . bindThisToCallback ( "off" ) ;
let args _off = interaction . callbacks . off . args ;
f _off ( ... args _off ) ;
}
2020-06-19 10:30:05 +00:00
} else {
2020-06-19 13:49:11 +00:00
let f = interaction . bindThisToCallback ( "noCheck" ) ;
let args = interaction . callbacks . noCheck . args ;
f ( ... args ) ;
2020-06-19 10:30:05 +00:00
}
}
}
2020-04-14 09:31:57 +00:00
2020-04-07 11:13:48 +00:00
// get display options from display options form element
static getDisplayOptions ( displayOptionsFormElement ) {
// gets display options parameters
let displayOptionsFormData
let displayOptionsData ;
displayOptionsFormData = new FormData ( displayOptionsFormElement ) ;
2020-04-08 09:37:34 +00:00
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" )
} ;
2020-04-07 11:13:48 +00:00
return displayOptionsData
}
2020-06-25 08:51:51 +00:00
// ###### Functions to add one match to a sub-results ######
2020-06-26 07:51:10 +00:00
// activate the add buttons
2020-06-25 08:51:51 +00:00
activateAddToSubResults ( ) {
subResultsIdListElement . classList . remove ( "hide" ) ;
2020-07-16 12:00:52 +00:00
if ( subResultsExportElement . classList . contains ( "hide" ) ) {
subResultsCreateElement . classList . remove ( "hide" ) ;
}
2020-06-25 08:51:51 +00:00
let addToSubResultsBtnElements = document . getElementsByClassName ( "add" ) ;
for ( let addToSubResultsBtn of addToSubResultsBtnElements ) {
addToSubResultsBtn . classList . remove ( "hide" ) ;
2020-06-19 10:30:05 +00:00
}
}
2020-06-26 07:51:10 +00:00
// deactivate the add buttons
2020-06-25 08:51:51 +00:00
deactivateAddToSubResults ( ) {
subResultsIdListElement . classList . add ( "hide" ) ;
subResultsCreateElement . classList . add ( "hide" ) ;
let addToSubResultsBtnElements = document . getElementsByClassName ( "add" ) ;
for ( let addToSubResultsBtn of addToSubResultsBtnElements ) {
addToSubResultsBtn . classList . add ( "hide" ) ;
2020-06-19 10:30:05 +00:00
}
}
2020-06-25 15:44:55 +00:00
2020-06-26 07:51:10 +00:00
// Used in addToSubResults and inspect to toggle the design of the check
// buttons according to its checked unchecked status.
2020-06-25 15:44:55 +00:00
helperActivateBtn ( btn ) {
btn . classList . remove ( "grey" ) ;
btn . classList . add ( "green" ) ;
btn . innerText = "check" ;
}
2020-06-26 07:51:10 +00:00
// Used in addToSubResults and inspect to toggle the design of the check
// buttons according to its checked unchecked status.
2020-06-25 15:44:55 +00:00
helperDeactivateBtn ( btn ) {
btn . classList . remove ( "green" ) ;
btn . classList . add ( "grey" ) ;
btn . innerText = "add" ;
}
2020-06-26 07:51:10 +00:00
// Either adds or removes a match to the sub-results. For this it checks
// onclick if the current button has been checked or not. For this the
// function checks if its status in addToSubResultsStatus is either flase or
// true. Adds match to sub-results if status is false if status is true it
// removes it.
2020-06-25 15:44:55 +00:00
addToSubResults ( dataIndex , tableCall = true ) {
2020-06-26 07:51:10 +00:00
let textarea = subResultsIdListElement . getElementsByTagName ( "textarea" ) [ 0 ] ;
2020-06-25 08:51:51 +00:00
if ( ! this . addToSubResultsStatus [ dataIndex ]
|| this . addToSubResultsStatus === undefined ) {
2020-06-26 07:51:10 +00:00
// add button is activated because status is either false or undefined
2020-06-25 15:44:55 +00:00
this . helperActivateBtn ( event . target ) ;
2020-06-26 07:51:10 +00:00
this . addToSubResultsStatus [ dataIndex ] = true ; // sets status to true
this . addToSubResultsIdsToShow . add ( dataIndex + 1 ) ; // + 1 because user does not see zero indexd data indexes
textarea . innerText = [ ... this . addToSubResultsIdsToShow ] . sort ( function ( a , b ) { return a - b } ) . join ( ", " ) ; // automaticalle sorts ids into the textarea in ascending order
M . textareaAutoResize ( textarea ) ; // after an insert textarea has to be resized manually
2020-06-29 09:09:12 +00:00
nrMarkedMatches . innerText = [ ... this . addToSubResultsIdsToShow ] . length ;
2020-06-25 08:51:51 +00:00
} else if ( this . addToSubResultsStatus [ dataIndex ] ) {
2020-06-26 07:51:10 +00:00
// add button is deactivated because status is true
2020-06-25 15:44:55 +00:00
this . helperDeactivateBtn ( event . target ) ;
2020-06-26 07:51:10 +00:00
this . addToSubResultsStatus [ dataIndex ] = false ; // sets status to false
this . addToSubResultsIdsToShow . delete ( dataIndex + 1 ) ; // + 1 because user does not see zero indexd data indexes
textarea . innerText = [ ... this . addToSubResultsIdsToShow ] . sort ( function ( a , b ) { return a - b } ) . join ( ", " ) ; // automaticalle sorts ids into the textarea in ascending order
2020-06-29 09:09:12 +00:00
nrMarkedMatches . innerText = [ ... this . addToSubResultsIdsToShow ] . length ;
2020-06-26 07:51:10 +00:00
M . textareaAutoResize ( textarea ) ; // after an insert textarea has to be resized manually
2020-06-19 10:30:05 +00:00
}
2020-06-26 07:51:10 +00:00
// Toggles the create button accoring to the number of ids in addToSubResultsIdsToShow
2020-06-25 08:51:51 +00:00
if ( [ ... this . addToSubResultsIdsToShow ] . length > 0 ) {
2020-07-16 12:00:52 +00:00
subResultsCreateElement . classList . remove ( "disabled" ) ;
2020-06-25 08:51:51 +00:00
} else if ( [ ... this . addToSubResultsIdsToShow ] . length === 0 ) {
2020-07-16 12:00:52 +00:00
subResultsCreateElement . classList . add ( "disabled" ) ;
2020-06-25 08:51:51 +00:00
}
2020-06-26 07:51:10 +00:00
// After a match as been added or removed the export button will be
2020-07-16 12:00:52 +00:00
// hidden because the sub-results have been alterd and have to be built //// again. Thus subResultsCreateElement has to be shown again.
subResultsExportElement . classList . add ( "hide" ) ;
subResultsCreateElement . classList . remove ( "hide" ) ;
2020-06-26 07:51:10 +00:00
// Also activate/deactivate buttons in the table/jsList results accordingly
//if button in inspect was activated/deactivated.
// This part only runs if tableCall is false.
2020-06-25 15:44:55 +00:00
if ( ! tableCall ) {
2020-06-26 07:51:10 +00:00
let tableAddBtn = document . getElementById ( "query-results" ) . querySelectorAll ( ` [data-index=" ${ dataIndex } "] ` ) [ 0 ] . getElementsByClassName ( 'add' ) [ 0 ] . firstElementChild ; // gets the add button from the list view
2020-06-25 15:44:55 +00:00
if ( this . addToSubResultsStatus [ dataIndex ] ) {
this . helperActivateBtn ( tableAddBtn ) ;
} else {
this . helperDeactivateBtn ( tableAddBtn ) ;
}
}
2020-06-19 10:30:05 +00:00
}
2020-06-26 07:51:10 +00:00
// Triggers emit to get full match context from server for a number of
// matches identified by their data_index.
2020-06-25 08:51:51 +00:00
getMatchWithContext ( dataIndexes , type ) {
let tmp _first _cpos = [ ] ;
let tmp _last _cpos = [ ] ;
for ( let dataIndex of dataIndexes ) {
tmp _first _cpos . push ( results . data . matches [ dataIndex ] . c [ 0 ] ) ;
tmp _last _cpos . push ( results . data . matches [ dataIndex ] . c [ 1 ] ) ;
}
2020-06-19 13:49:11 +00:00
nopaque . socket . emit ( "corpus_analysis_inspect_match" ,
{
type : type ,
2020-06-25 08:51:51 +00:00
data _indexes : dataIndexes ,
first _cpos : tmp _first _cpos ,
last _cpos : tmp _last _cpos ,
2020-06-19 13:49:11 +00:00
}
) ;
}
2020-04-07 11:13:48 +00:00
// ###### Functions to inspect one match, to show more details ######
2020-04-08 09:37:34 +00:00
// activate inspect buttons if progress is 100
activateInspect ( ) {
2020-04-07 11:13:48 +00:00
if ( progress === 100 ) {
2020-06-19 13:49:11 +00:00
let inspectBtnElements ;
2020-04-07 11:13:48 +00:00
inspectBtnElements = document . getElementsByClassName ( "inspect" ) ;
for ( let inspectBtn of inspectBtnElements ) {
inspectBtn . classList . remove ( "disabled" ) ;
}
} else {
return
}
}
2020-07-14 07:24:04 +00:00
// ### functions to inspect imported Matches
// This function creates an object that is similar to the object that is
// being recieved as an answere to the getMatchWithContext Method, which is
// triggering an socket.io event.
// It is used as an input for show match context in the context of imported
// results to be able to inspect matches.
createFakeResponse ( ) {
contextModal . open ( ) ;
let cpos _lookup ;
let fake _response = { } ;
let contextResultsElement ;
// function to create one match object from entire imported results
// that is passed into the results.jsList.showMatchContext() function
fake _response [ "payload" ] = { } ;
let dataIndex = event . target . closest ( "tr" ) . dataset . index ;
fake _response . payload [ "matches" ] = [ results . data . matches [ dataIndex ] ] ;
contextResultsElement = document . getElementById ( "context-results" ) ;
contextResultsElement . innerHTML = "" ;
2020-07-14 08:59:02 +00:00
let { lc , c , rc } = this . helperCreateCpos ( results . data . cpos _ranges ,
fake _response . payload . matches [ 0 ] ) ;
2020-07-14 07:24:04 +00:00
cpos _lookup = { } ;
for ( let cpos of lc ) {
cpos _lookup [ cpos ] = results . data . cpos _lookup [ cpos ] ;
}
for ( let cpos of c ) {
cpos _lookup [ cpos ] = results . data . cpos _lookup [ cpos ] ;
}
for ( let cpos of rc ) {
cpos _lookup [ cpos ] = results . data . cpos _lookup [ cpos ] ;
}
fake _response . payload [ "cpos_lookup" ] = cpos _lookup
fake _response . payload [ "cpos_ranges" ] = results . data . cpos _ranges ;
fake _response . payload [ "query" ] = results . data . query ;
fake _response . payload [ "context_id" ] = dataIndex + 1 ;
fake _response . payload [ "match_count" ] = fake _response . payload . matches . length
fake _response . payload [ "corpus_type" ] = "inspect-result"
return fake _response
}
2020-06-25 08:51:51 +00:00
// gets result cpos infos for one dataIndex (list of length 1) to send back to
// the server
2020-06-19 10:30:05 +00:00
inspect ( dataIndex , type ) {
2020-06-29 09:09:12 +00:00
let contextMatchNrElement ;
2020-07-14 07:24:04 +00:00
let contextResultsElement ;
2020-06-26 07:51:10 +00:00
// get result infos from server and show them in context modal
2020-06-25 08:51:51 +00:00
this . contextId = dataIndex [ 0 ] ;
2020-06-29 09:09:12 +00:00
// match nr for user to display derived from data_index
contextMatchNrElement = document . getElementById ( "context-match-nr" ) ;
contextMatchNrElement . innerText = this . contextId + 1 ;
2020-06-25 08:51:51 +00:00
contextResultsElement = document . getElementById ( "context-results" ) ;
contextResultsElement . innerHTML = "" ; // clear it from old inspects
2020-06-19 13:49:11 +00:00
this . getMatchWithContext ( dataIndex , type ) ;
2020-04-07 11:13:48 +00:00
contextModal . open ( ) ;
2020-06-26 07:51:10 +00:00
// add a button to add this match to sub results with onclick event
2020-06-25 08:51:51 +00:00
let classes = ` btn-floating btn waves-effect ` +
` waves-light grey right `
2020-06-25 15:44:55 +00:00
let addToSubResultsIdsBtn = document . createElement ( "a" ) ;
addToSubResultsIdsBtn . setAttribute ( "class" , classes + ` add ` ) ;
addToSubResultsIdsBtn . innerHTML = '<i class="material-icons">add</i>' ;
2020-06-26 07:51:10 +00:00
addToSubResultsIdsBtn . onclick = ( ) => { this . addToSubResults ( dataIndex [ 0 ] , false ) } ;
// checks if a button has already been added to the inspect modal and removes it
2020-06-25 15:44:55 +00:00
if ( addToSubResultsFromInspectElement . children . length > 0 ) {
addToSubResultsFromInspectElement . firstElementChild . remove ( ) ;
}
2020-06-26 07:51:10 +00:00
// Changes the design of the add button according to its checked status
// upon opening the inspect modal.
2020-06-25 15:44:55 +00:00
if ( this . addToSubResultsStatus [ dataIndex [ 0 ] ] ) {
2020-06-26 07:51:10 +00:00
this . helperActivateBtn ( addToSubResultsIdsBtn . firstElementChild ) ;
2020-06-25 15:44:55 +00:00
} else if ( ! this . addToSubResultsStatus [ dataIndex [ 0 ] ] ) {
2020-06-26 07:51:10 +00:00
this . helperDeactivateBtn ( addToSubResultsIdsBtn . firstElementChild ) ;
2020-06-25 15:44:55 +00:00
}
addToSubResultsFromInspectElement . appendChild ( addToSubResultsIdsBtn ) ;
2020-04-07 11:13:48 +00:00
}
2020-06-19 10:30:05 +00:00
// create Element from HTML String helper function
2020-04-15 13:11:25 +00:00
HTMLTStrToElement ( htmlStr ) {
2020-04-15 12:55:29 +00:00
// https://stackoverflow.com/questions/494143/creating-a-new-dom-element-from-an-html-string-using-built-in-dom-methods-or-pro/35385518#35385518
let template = document . createElement ( "template" ) ;
htmlStr = htmlStr . trim ( ) ;
template . innerHTML = htmlStr ;
return template . content . firstChild ;
}
2020-06-26 07:51:10 +00:00
// Used as a callback to handle incoming match context results when inspect
// has been used.
2020-04-07 11:13:48 +00:00
showMatchContext ( response ) {
2020-04-15 12:55:29 +00:00
this . contextData ;
2020-04-07 11:13:48 +00:00
let contextModalLoading ;
let contextModalReady ;
2020-04-08 09:37:34 +00:00
let contextResultsElement ;
2020-04-16 13:06:03 +00:00
let highlightSentencesSwitchElement ;
2020-04-20 11:48:40 +00:00
let htmlTokenStr ;
let modalExpertModeSwitchElement ;
2020-04-15 12:55:29 +00:00
let modalTokenElements ;
2020-04-20 11:48:40 +00:00
let nrOfContextSentences ;
2020-04-08 09:37:34 +00:00
let partElement ;
2020-04-07 11:13:48 +00:00
let token ;
2020-04-15 12:55:29 +00:00
let tokenHTMLArray ;
let tokenHTMlElement ;
2020-05-04 09:05:17 +00:00
let uniqueContextS ;
2020-04-20 11:48:40 +00:00
let uniqueS ;
2020-04-15 12:55:29 +00:00
this . contextData = response . payload ;
2020-06-29 09:09:12 +00:00
console . log ( this . contextData ) ;
2020-06-25 08:51:51 +00:00
this . contextData [ "cpos_ranges" ] = response . payload . cpos _ranges ;
2020-04-30 13:21:55 +00:00
this . contextData [ "query" ] = results . data . query ;
2020-05-04 09:05:17 +00:00
this . contextData [ "context_id" ] = this . contextId ;
2020-06-16 12:05:58 +00:00
this . contextData [ "match_count" ] = this . contextData . matches . length
2020-06-25 08:51:51 +00:00
this . contextData [ "corpus_type" ] = "inspect-result"
2020-04-30 13:21:55 +00:00
Object . assign ( this . contextData , results . metaData ) ;
2020-04-07 11:13:48 +00:00
contextResultsElement = document . getElementById ( "context-results" ) ;
2020-04-20 11:48:40 +00:00
modalExpertModeSwitchElement = document . getElementById ( "inspect-display-options-form-expert_mode_inspect" ) ;
highlightSentencesSwitchElement = document . getElementById ( "inspect-display-options-form-highlight_sentences" ) ;
nrOfContextSentences = document . getElementById ( "context-sentences" ) ;
2020-04-15 12:55:29 +00:00
uniqueS = new Set ( ) ;
2020-05-04 09:05:17 +00:00
uniqueContextS = new Set ( ) ;
2020-07-14 08:59:02 +00:00
let { lc , c , rc } = this . helperCreateCpos ( this . contextData . cpos _ranges ,
this . contextData . matches [ 0 ] )
2020-04-08 09:37:34 +00:00
// create sentence strings as tokens
2020-04-15 12:55:29 +00:00
tokenHTMLArray = [ ] ;
2020-04-07 11:13:48 +00:00
for ( let cpos of lc ) {
2020-04-15 12:55:29 +00:00
token = this . contextData . cpos _lookup [ cpos ] ;
uniqueS . add ( token . s )
htmlTokenStr = ` <span class="token" ` +
` data-sid=" ${ token . s } " ` +
` data-cpos=" ${ cpos } "> ` +
` ${ token . word } ` +
` </span> ` ;
2020-04-15 13:11:25 +00:00
tokenHTMlElement = this . HTMLTStrToElement ( htmlTokenStr )
2020-04-15 12:55:29 +00:00
tokenHTMLArray . push ( tokenHTMlElement ) ;
2020-04-07 11:13:48 +00:00
}
for ( let cpos of c ) {
2020-04-15 12:55:29 +00:00
token = this . contextData . cpos _lookup [ cpos ] ;
2020-05-04 09:05:17 +00:00
uniqueContextS . add ( token . s ) ;
uniqueS . add ( token . s ) ;
2020-04-15 12:55:29 +00:00
htmlTokenStr = ` <span class="token bold light-green" ` +
` data-sid=" ${ token . s } " ` +
` data-cpos=" ${ cpos } " ` +
` style="text-decoration-line: underline;"> ` +
` ${ token . word } ` +
` </span> ` ;
2020-04-15 13:11:25 +00:00
tokenHTMlElement = this . HTMLTStrToElement ( htmlTokenStr )
2020-04-15 12:55:29 +00:00
tokenHTMLArray . push ( tokenHTMlElement ) ;
2020-04-07 11:13:48 +00:00
}
2020-05-04 09:05:17 +00:00
this . contextData [ "context_s_ids" ] = Array . from ( uniqueContextS ) ;
2020-04-07 11:13:48 +00:00
for ( let cpos of rc ) {
2020-04-15 12:55:29 +00:00
token = this . contextData . cpos _lookup [ cpos ] ;
uniqueS . add ( token . s )
htmlTokenStr = ` <span class="token" ` +
` data-sid=" ${ token . s } " ` +
` data-cpos=" ${ cpos } "> ` +
` ${ token . word } ` +
` </span> ` ;
2020-04-15 13:11:25 +00:00
tokenHTMlElement = this . HTMLTStrToElement ( htmlTokenStr )
2020-04-15 12:55:29 +00:00
tokenHTMLArray . push ( tokenHTMlElement ) ;
}
for ( let sId of uniqueS ) {
2020-04-16 11:49:21 +00:00
let htmlSentence = ` <span class="sentence" data-sid=" ${ sId } "></span> ` ;
2020-04-15 13:11:25 +00:00
let sentenceElement = this . HTMLTStrToElement ( htmlSentence ) ;
2020-04-15 12:55:29 +00:00
for ( let tokenElement of tokenHTMLArray ) {
if ( tokenElement . dataset . sid == sId ) {
sentenceElement . appendChild ( tokenElement ) ;
2020-04-23 11:28:13 +00:00
sentenceElement . insertAdjacentHTML ( "beforeend" , ` ` ) ;
2020-04-15 12:55:29 +00:00
} else {
continue ;
}
}
2020-04-16 11:49:21 +00:00
contextResultsElement . appendChild ( sentenceElement ) ;
2020-04-07 11:13:48 +00:00
}
2020-04-15 12:55:29 +00:00
2020-04-20 11:48:40 +00:00
// add inspect display options events
modalExpertModeSwitchElement . onchange = ( event ) => {
2020-04-16 13:06:03 +00:00
if ( event . target . checked ) {
this . expertModeOn ( "context-results" ) ;
} else {
this . expertModeOff ( "context-results" )
}
2020-04-20 11:48:40 +00:00
} ;
2020-04-16 13:06:03 +00:00
2020-04-20 11:48:40 +00:00
highlightSentencesSwitchElement . onchange = ( event ) => {
2020-04-16 13:06:03 +00:00
if ( event . target . checked ) {
this . higlightContextSentences ( ) ;
} else {
this . unhighlightContextSentences ( ) ;
}
2020-04-20 11:48:40 +00:00
} ;
nrOfContextSentences . onchange = ( event ) => {
2020-04-23 10:10:36 +00:00
// console.log(event.target.value);
2020-04-20 11:48:40 +00:00
this . changeSentenceContext ( event . target . value ) ;
}
// checks on new modal opening if switches are checked
// if switches are checked functions are executed
if ( modalExpertModeSwitchElement . checked ) {
this . expertModeOn ( "context-results" ) ;
}
2020-04-16 13:06:03 +00:00
if ( highlightSentencesSwitchElement . checked ) {
this . higlightContextSentences ( ) ;
2020-04-07 11:13:48 +00:00
}
2020-04-20 11:48:40 +00:00
// checks the value of the number of sentences to show on modal opening
// sets context sentences accordingly
this . changeSentenceContext ( nrOfContextSentences . value )
2020-04-07 11:13:48 +00:00
}
2020-06-26 07:51:10 +00:00
// splits context text into sentences based on spacy sentence split
2020-04-16 13:06:03 +00:00
higlightContextSentences ( ) {
let sentences ;
sentences = document . getElementById ( "context-results" ) . getElementsByClassName ( "sentence" ) ;
for ( let s of sentences ) {
2020-04-20 11:48:40 +00:00
s . insertAdjacentHTML ( "beforeend" , ` <span><br><br></span> ` )
2020-04-16 13:06:03 +00:00
}
}
unhighlightContextSentences ( ) {
let sentences ;
2020-04-20 11:48:40 +00:00
let br ;
2020-04-16 13:06:03 +00:00
sentences = document . getElementById ( "context-results" ) . getElementsByClassName ( "sentence" ) ;
for ( let s of sentences ) {
2020-04-20 11:48:40 +00:00
br = s . lastChild ;
br . remove ( ) ;
2020-04-16 13:06:03 +00:00
}
}
2020-06-26 07:51:10 +00:00
// changes how many context sentences in inspect view are shown
2020-04-20 11:48:40 +00:00
changeSentenceContext ( sValue , maxSValue = 10 ) {
let array ;
let sentences ;
let toHideArray ;
let toShowArray ;
sValue = maxSValue - sValue ;
2020-04-23 10:10:36 +00:00
// console.log(sValue);
2020-04-20 11:48:40 +00:00
sentences = document . getElementById ( "context-results" ) . getElementsByClassName ( "sentence" ) ;
array = Array . from ( sentences ) ;
if ( sValue != 0 ) {
toHideArray = array . slice ( 0 , sValue ) . concat ( array . slice ( - ( sValue ) ) ) ;
toShowArray = array . slice ( sValue , 9 ) . concat ( array . slice ( 9 , - ( sValue ) ) )
} else {
toHideArray = [ ] ;
toShowArray = array ;
}
2020-04-23 10:10:36 +00:00
// console.log(array);
// console.log("#######");
// console.log(toHideArray);
2020-04-20 11:48:40 +00:00
for ( let s of toHideArray ) {
s . classList . add ( "hide" ) ;
}
for ( let s of toShowArray ) {
s . classList . remove ( "hide" ) ;
}
2020-04-15 12:55:29 +00:00
}
2020-04-07 11:13:48 +00:00
// ###### Display options changing live how the matches are being displayed ######
// Event function that changes the shown hits per page.
// Just alters the resultsList.page property
changeHitsPerPage ( event ) {
try {
2020-04-14 09:31:57 +00:00
// console.log(this);
this . page = event . target . value ;
this . update ( ) ;
2020-04-20 11:59:28 +00:00
this . activateInspect ( ) ;
2020-06-30 13:15:06 +00:00
this . pageChangeEventInteractionHandler ( interactionElements ) ;
2020-04-14 09:31:57 +00:00
if ( expertModeSwitchElement . checked ) {
2020-04-20 11:55:11 +00:00
this . expertModeOn ( "query-display" ) ; // page holds new result rows, so add new tooltips
2020-04-14 09:31:57 +00:00
}
2020-04-27 13:22:20 +00:00
nopaque . flash ( "Updated matches per page." , "corpus" )
2020-04-07 11:13:48 +00:00
} catch ( e ) {
2020-04-14 09:31:57 +00:00
// console.log(e);
// console.log("resultsList has no results right now.");
2020-04-07 11:13:48 +00:00
}
}
2020-04-08 09:37:34 +00:00
// Event function triggered on context select change
// also if pagination is clicked
2020-04-07 11:13:48 +00:00
changeContext ( event ) {
2020-04-08 09:37:34 +00:00
let array ;
2020-04-07 11:13:48 +00:00
let lc ;
2020-04-08 09:37:34 +00:00
let newContextValue ;
2020-04-07 11:13:48 +00:00
let rc ;
try {
if ( event . type === "change" ) {
2020-04-27 13:22:20 +00:00
nopaque . flash ( "Updated context per match!" , "corpus" ) ;
2020-04-07 11:13:48 +00:00
}
} catch ( e ) {
} finally {
newContextValue = document . getElementById ( "display-options-form-result_context" ) . value ;
lc = document . getElementsByClassName ( "left-context" ) ;
rc = document . getElementsByClassName ( "right-context" ) ;
for ( let element of lc ) {
array = Array . from ( element . childNodes ) ;
2020-04-08 07:46:37 +00:00
for ( let element of array . reverse ( ) . slice ( newContextValue ) ) {
2020-04-07 11:13:48 +00:00
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 ######
2020-04-14 09:31:57 +00:00
// function to create a tooltip for the current hovered token
tooltipEventCreate ( event ) {
// console.log("Create Tooltip on mouseover.");
2020-04-07 11:13:48 +00:00
let token ;
2020-04-30 13:21:55 +00:00
token = results . data . cpos _lookup [ event . target . dataset . cpos ] ;
2020-04-15 12:55:29 +00:00
if ( ! token ) {
token = this . contextData . cpos _lookup [ event . target . dataset . cpos ] ;
}
2020-04-09 12:49:17 +00:00
this . addToolTipToTokenElement ( event . target , token ) ;
}
2020-04-14 09:31:57 +00:00
// Function to destroy the current Tooltip for the current hovered tooltip
// on mouse leave
tooltipEventDestroy ( event ) {
// console.log("Tooltip destroy on leave.");
this . currentTooltipElement . destroy ( ) ;
}
2020-04-16 13:06:03 +00:00
expertModeOn ( htmlId ) {
2020-06-19 10:30:05 +00:00
// turn the expert mode on for all tokens in the DOM element identified by its htmlID
if ( ! Array . isArray ( this . currentExpertTokenElements [ htmlId ] ) ) {
this . currentExpertTokenElements [ htmlId ] = [ ] ;
}
2020-07-14 07:24:04 +00:00
let container = document . getElementById ( htmlId ) ;
let tokens = container . querySelectorAll ( "span.token" ) ;
this . currentExpertTokenElements [ htmlId ] . push ( ... tokens ) ;
2020-04-14 09:31:57 +00:00
this . tooltipEventCreateBind = this . tooltipEventCreate . bind ( this ) ;
this . tooltipEventDestroyBind = this . tooltipEventDestroy . bind ( this ) ;
2020-04-20 11:48:40 +00:00
this . eventTokens [ htmlId ] = [ ] ;
2020-04-16 13:06:03 +00:00
for ( let tokenElement of this . currentExpertTokenElements [ htmlId ] ) {
2020-04-09 12:49:17 +00:00
tokenElement . classList . add ( "chip" , "hoverable" , "expert-view" ) ;
2020-04-14 09:31:57 +00:00
tokenElement . onmouseover = this . tooltipEventCreateBind ;
tokenElement . onmouseout = this . tooltipEventDestroyBind ;
2020-04-16 13:06:03 +00:00
this . eventTokens [ htmlId ] . push ( tokenElement ) ;
2020-04-07 11:13:48 +00:00
}
}
// fuction that creates Tooltip for one token and extracts the corresponding
// infos from the result JSON
addToolTipToTokenElement ( tokenElement , token ) {
2020-04-14 09:31:57 +00:00
this . currentTooltipElement ;
this . currentTooltipElement = M . Tooltip . init ( tokenElement ,
2020-04-08 09:37:34 +00:00
{ "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-30 13:21:55 +00:00
Title : $ { results . data . text _lookup [ token . text ] . title }
2020-04-08 09:37:34 +00:00
< br >
2020-04-30 13:21:55 +00:00
Author : $ { results . data . text _lookup [ token . text ] . author }
2020-04-08 09:37:34 +00:00
< br >
2020-04-30 13:21:55 +00:00
Publishing year : $ { results . data . text _lookup [ token . text ] . publishing _year }
2020-04-08 09:37:34 +00:00
< / t d >
< / t r >
< / t a b l e > ` }
2020-04-14 09:31:57 +00:00
) ;
2020-04-07 11:13:48 +00:00
}
// function to remove extra informations and animations from tokens
2020-04-16 13:06:03 +00:00
expertModeOff ( htmlId ) {
2020-04-14 09:31:57 +00:00
// console.log("Expert mode is off.");
2020-06-19 10:30:05 +00:00
if ( ! Array . isArray ( this . currentExpertTokenElements [ htmlId ] ) ) {
this . currentExpertTokenElements [ htmlId ] = [ ] ;
}
if ( ! Array . isArray ( this . eventTokens [ htmlId ] ) ) {
this . eventTokens [ htmlId ] = [ ] ;
}
2020-04-16 13:06:03 +00:00
for ( let tokenElement of this . currentExpertTokenElements [ htmlId ] ) {
2020-04-09 12:49:17 +00:00
tokenElement . classList . remove ( "chip" , "hoverable" , "expert-view" ) ;
}
2020-04-16 13:06:03 +00:00
this . currentExpertTokenElements [ htmlId ] = [ ] ;
2020-04-20 11:48:40 +00:00
2020-04-16 13:06:03 +00:00
for ( let eventToken of this . eventTokens [ htmlId ] ) {
2020-04-14 09:31:57 +00:00
eventToken . onmouseover = "" ;
eventToken . onmouseout = "" ;
2020-04-07 11:13:48 +00:00
}
2020-04-16 13:06:03 +00:00
this . eventTokens [ htmlId ] = [ ] ;
2020-04-07 11:13:48 +00:00
}
2020-07-14 07:24:04 +00:00
createResultRowElement ( item , chunk , imported = false ) {
2020-06-25 15:44:55 +00:00
let aCellElement ;
2020-06-25 08:51:51 +00:00
let addToSubResultsBtn ;
2020-04-08 09:37:34 +00:00
let cCellElement ;
let cpos ;
2020-07-14 07:24:04 +00:00
let fakeResponse ; // used if imported results are being created;
2020-04-08 09:37:34 +00:00
let inspectBtn
let lcCellElement ;
let matchNrElement ;
let matchRowElement ;
let rcCellElement ;
let textTitles ;
let textTitlesCellElement ;
let token ;
let values ;
2020-01-29 15:12:57 +00:00
// gather values from item
values = item . values ( ) ;
2020-07-14 08:59:02 +00:00
let { lc , c , rc } = this . helperCreateCpos ( chunk . cpos _ranges ,
values )
// 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)
// 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)
// c = range(values.c[0], values.c[1], 1)
// rc = range(values.rc[0], values.rc[1], 1)
// } else {
// lc = values.lc;
// c = values.c;
// rc = values.rc;
// }
2020-01-29 15:12:57 +00:00
// get infos for full match row
matchRowElement = document . createElement ( "tr" ) ;
2020-04-09 08:17:04 +00:00
matchRowElement . setAttribute ( "data-index" , values . index )
2020-02-03 11:58:40 +00:00
lcCellElement = document . createElement ( "td" ) ;
lcCellElement . classList . add ( "left-context" ) ;
matchRowElement . appendChild ( lcCellElement ) ;
2020-04-02 09:37:45 +00:00
for ( cpos of lc ) {
2020-04-08 09:37:34 +00:00
token = chunk . cpos _lookup [ cpos ] ;
lcCellElement . insertAdjacentHTML ( "beforeend" ,
` <span class="token" data-cpos=" ${ cpos } "> ${ token . word } </span> ` ) ;
2020-01-29 15:12:57 +00:00
}
2020-02-03 11:58:40 +00:00
2020-06-25 15:44:55 +00:00
// get infos for hit of match and set actions
2020-04-08 09:37:34 +00:00
textTitles = new Set ( ) ;
2020-06-25 15:44:55 +00:00
aCellElement = document . createElement ( "td" ) ;
aCellElement . classList . add ( "actions" ) ;
2020-04-08 09:37:34 +00:00
cCellElement = document . createElement ( "td" ) ;
cCellElement . classList . add ( "match-hit" ) ;
2020-02-03 11:58:40 +00:00
textTitlesCellElement = document . createElement ( "td" ) ;
textTitlesCellElement . classList . add ( "titles" ) ;
2020-02-03 12:59:37 +00:00
matchNrElement = document . createElement ( "td" ) ;
matchNrElement . classList . add ( "match-nr" ) ;
2020-04-08 09:37:34 +00:00
matchRowElement . appendChild ( cCellElement ) ;
2020-06-25 15:44:55 +00:00
matchRowElement . appendChild ( aCellElement ) ;
2020-04-02 09:37:45 +00:00
for ( cpos of c ) {
2020-04-08 09:37:34 +00:00
token = chunk . cpos _lookup [ cpos ] ;
cCellElement . insertAdjacentHTML ( "beforeend" ,
` <span class="token" data-cpos=" ${ cpos } "> ${ token . word } </span> ` ) ;
2020-02-03 11:58:40 +00:00
// get text titles of every hit cpos token
2020-04-08 09:37:34 +00:00
textTitles . add ( chunk . text _lookup [ token . text ] . title ) ;
2020-02-03 11:58:40 +00:00
}
2020-06-19 10:30:05 +00:00
// add some interaction buttons
// # some btn css rules and classes
2020-06-25 15:44:55 +00:00
let css = ` margin-right: 5px; margin-bottom: 5px; `
2020-06-19 13:49:11 +00:00
let classes = ` btn-floating btn waves-effect ` +
2020-06-25 15:44:55 +00:00
` waves-light grey `
2020-06-19 10:30:05 +00:00
// # add button to trigger more context to every match td
inspectBtn = document . createElement ( "a" ) ;
2020-06-25 15:44:55 +00:00
inspectBtn . setAttribute ( "style" , css ) ;
2020-06-19 10:30:05 +00:00
inspectBtn . setAttribute ( "class" , classes + ` disabled inspect `
) ;
inspectBtn . innerHTML = '<i class="material-icons">search</i>' ;
2020-07-14 07:24:04 +00:00
if ( imported ) {
inspectBtn . onclick = ( ) => {
fakeResponse = this . createFakeResponse ( ) ;
this . showMatchContext ( fakeResponse ) ;
} ;
} else {
inspectBtn . onclick = ( ) => { this . inspect ( [ values . index ] , "inspect" ) } ;
}
2020-06-25 08:51:51 +00:00
// # add btn to add matches to sub-results. hidden per default
addToSubResultsBtn = document . createElement ( "a" ) ;
2020-06-25 15:44:55 +00:00
addToSubResultsBtn . setAttribute ( "style" , css ) ;
2020-06-25 08:51:51 +00:00
addToSubResultsBtn . setAttribute ( "class" , classes + ` hide add `
2020-06-19 10:30:05 +00:00
) ;
2020-06-25 08:51:51 +00:00
addToSubResultsBtn . innerHTML = '<i class="material-icons">add</i>' ;
2020-06-25 15:44:55 +00:00
addToSubResultsBtn . onclick = ( event ) => { this . addToSubResults ( values . index ) }
aCellElement . appendChild ( inspectBtn ) ;
2020-06-26 11:13:18 +00:00
aCellElement . appendChild ( addToSubResultsBtn ) ;
2020-06-19 10:30:05 +00:00
// add text titles at front as first td of one row
2020-02-03 11:58:40 +00:00
textTitlesCellElement . innerText = [ ... textTitles ] . join ( ", " ) ;
matchRowElement . insertAdjacentHTML ( "afterbegin" , textTitlesCellElement . outerHTML ) ;
2020-04-08 09:37:34 +00:00
matchNrElement . innerText = values . index + 1 ;
2020-02-03 12:59:37 +00:00
matchRowElement . insertAdjacentHTML ( "afterbegin" , matchNrElement . outerHTML ) ;
2020-02-03 11:58:40 +00:00
// get infos for right context of match
rcCellElement = document . createElement ( "td" ) ;
rcCellElement . classList . add ( "right-context" ) ;
matchRowElement . appendChild ( rcCellElement ) ;
2020-04-02 09:37:45 +00:00
for ( cpos of rc ) {
2020-04-09 08:17:04 +00:00
token = chunk . cpos _lookup [ cpos ] ;
2020-04-08 09:37:34 +00:00
rcCellElement . insertAdjacentHTML ( "beforeend" ,
` <span class="token" data-cpos=" ${ cpos } "> ${ token . word } </span> ` ) ;
2020-02-03 11:58:40 +00:00
}
2020-01-30 13:23:19 +00:00
return matchRowElement
2020-01-29 15:12:57 +00:00
}
}