2020-01-31 13:14:08 +00:00
class RessourceList extends List {
2020-07-30 12:17:51 +00:00
constructor ( idOrElement , subscriberList , type , options ) {
if ( ! type || ! [ "Corpus" , "CorpusFile" , "Job" , "JobInput" , "QueryResult" , "User" ] . includes ( type ) ) {
throw "Unknown Type!" ;
2020-07-07 13:08:15 +00:00
}
2020-07-30 12:17:51 +00:00
super ( idOrElement , { ... RessourceList . options [ 'common' ] ,
... RessourceList . options [ type ] ,
... ( options ? options : { } ) } ) ;
if ( subscriberList ) { subscriberList . push ( this ) ; }
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-07-30 12:17:51 +00:00
this . _add ( 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-07-30 12:17:51 +00:00
this . _add ( [ 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-07-30 12:17:51 +00:00
_add ( values , callback ) {
this . add ( values . map ( x => RessourceList . dataMappers [ this . type ] ( x ) ) , callback ) ;
// Initialize modal and tooltipped elements in list
M . AutoInit ( this . listContainer ) ;
2020-07-10 09:39:16 +00:00
}
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-07-30 12:17:51 +00:00
RessourceList . dataMappers = {
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-30 12:17:51 +00:00
/* ### Corpus mapper ### */
Corpus : corpus => ( {
creation _date : corpus . creation _date ,
description : corpus . description ,
id : corpus . id ,
link : ` /corpora/ ${ corpus . id } ` ,
status : corpus . status ,
title : corpus . title ,
title1 : corpus . title ,
"analyse-link" : [ "analysing" , "prepared" , "start analysis" ] . includes ( corpus . status ) ? ` /corpora/ ${ corpus . id } /analyse ` : "" ,
"delete-link" : ` /corpora/ ${ corpus . id } /delete ` ,
"delete-modal" : ` delete-corpus- ${ corpus . id } -modal ` ,
"delete-modal-trigger" : ` delete-corpus- ${ corpus . id } -modal ` ,
} ) ,
/* ### CorpusFile mapper ### TODO: replace delete-modal with delete-onclick */
CorpusFile : corpus _file => ( {
author : corpus _file . author ,
filename : corpus _file . filename ,
link : ` ${ corpus _file . corpus _id } /files/ ${ corpus _file . id } ` ,
publishing _year : corpus _file . publishing _year ,
title : corpus _file . title ,
title1 : corpus _file . title ,
"delete-link" : ` /corpora/ ${ corpus _file . corpus _id } /files/ ${ corpus _file . id } /delete ` ,
"delete-modal" : ` delete-corpus-file- ${ corpus _file . id } -modal ` ,
"delete-modal-trigger" : ` delete-corpus-file- ${ corpus _file . id } -modal ` ,
"download-link" : ` ${ corpus _file . corpus _id } /files/ ${ corpus _file . id } /download ` ,
} ) ,
/* ### Job mapper ### */
Job : job => ( {
creation _date : job . creation _date ,
description : job . description ,
id : job . id ,
link : ` /jobs/ ${ job . id } ` ,
service : job . service ,
status : job . status ,
title : job . title ,
title1 : job . title ,
"delete-link" : ` /jobs/ ${ job . id } /delete ` ,
"delete-modal" : ` delete-job- ${ job . id } -modal ` ,
"delete-modal-trigger" : ` delete-job- ${ job . id } -modal ` ,
} ) ,
/* ### JobInput mapper ### */
JobInput : job _input => ( {
filename : job _input . filename ,
id : job _input . job _id ,
"download-link" : ` ${ job _input . job _id } /inputs/ ${ job _input . id } /download `
} ) ,
/* ### QueryResult mapper ### */
QueryResult : query _result => ( {
corpus _name : query _result . query _metadata . corpus _name ,
description : query _result . description ,
id : query _result . id ,
link : ` /query_results/ ${ query _result . id } ` ,
query : query _result . query _metadata . query ,
title : query _result . title ,
"delete-link" : ` /query_results/ ${ query _result . id } /delete ` ,
"delete-modal" : ` delete-query-result- ${ query _result . id } -modal ` ,
"delete-modal-trigger" : ` delete-query-result- ${ query _result . id } -modal ` ,
"inspect-link" : ` /query_results/ ${ query _result . id } /inspect ` ,
} ) ,
/* ### User mapper ### */
User : user => ( {
confirmed : user . confirmed ,
email : user . email ,
id : user . id ,
link : ` user/ ${ user . id } ` ,
role _id : user . role _id ,
username : user . username ,
username2 : user . username ,
"delete-link" : ` /admin/user/ ${ user . id } /delete ` ,
"delete-modal" : ` delete-user- ${ user . id } -modal ` ,
"delete-modal-trigger" : ` delete-user- ${ user . id } -modal ` ,
} ) ,
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-07-30 12:17:51 +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-30 12:17:51 +00:00
extended : {
page : 10 ,
pagination : [
{
name : "paginationTop" ,
paginationClass : "paginationTop" ,
innerWindow : 8 ,
outerWindow : 1
} ,
{
paginationClass : "paginationBottom" ,
innerWindow : 8 ,
outerWindow : 1 ,
} ,
] ,
} ,
2020-07-15 06:57:39 +00:00
/ * 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
* /
2020-07-30 12:17:51 +00:00
Corpus : {
item : ` <tr>
< 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 >
< span class = "badge new status" data - badge - caption = "" > < / s p a n >
< / t d >
< td >
< div class = "right-align" >
< a class = "btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data - position = "top" data - tooltip = "Delete" >
< i class = "material-icons" > delete < / i >
< / a >
< a class = "btn-floating tooltipped waves-effect waves-light link" data - position = "top" data - tooltip = "Edit" >
< i class = "material-icons" > edit < / i >
< / a >
< a class = "btn-floating tooltipped waves-effect waves-light analyse-link" data - position = "top" data - tooltip = "Analyse" >
< i class = "material-icons" > search < / i >
< / a >
< / d i v >
< div class = "modal delete-modal" >
< div class = "modal-content" >
< h4 > Confirm corpus deletion < / h 4 >
< p > Do you really want to delete the corpus < b class = "title1" > < / b > ? A l l f i l e s w i l l b e p e r m a n e n t l y d e l e t e d ! < / p >
< / d i v >
< div class = "modal-footer" >
< a href = "#!" class = "btn modal-close waves-effect waves-light" > Cancel < / a >
< a class = "btn modal-close red waves-effect waves-light delete-link" > < i class = "material-icons left" > delete < / i > D e l e t e < / a >
< / d i v >
< / d i v >
< / t d >
< / t r > ` ,
valueNames : [
"creation_date" ,
"description" ,
"title" ,
"title1" ,
{ data : [ "id" ] } ,
{ name : "analyse-link" , attr : "href" } ,
{ name : "delete-link" , attr : "href" } ,
{ name : "delete-modal-trigger" , attr : "data-target" } ,
{ name : "delete-modal" , attr : "id" } ,
{ name : "link" , attr : "href" } ,
{ name : "status" , attr : "data-status" } ,
]
} ,
CorpusFile : {
item : ` <tr>
< 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 >
< td >
< div class = "right-align" >
< a class = "btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data - position = "top" data - tooltip = "Delete" >
< i class = "material-icons" > delete < / i >
< / a >
< 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 >
< a class = "btn-floating tooltipped waves-effect waves-light link" data - position = "top" data - tooltip = "Edit" >
< i class = "material-icons" > edit < / i >
< / a >
< / d i v >
< div class = "modal delete-modal" >
< div class = "modal-content" >
< h4 > Confirm corpus file deletion < / h 4 >
< p > Do you really want to delete the corpus file < b class = "title1" > < / b > ? I t b e p e r m a n e n t l y d e l e t e d ! < / p >
< / d i v >
< div class = "modal-footer" >
< a href = "#!" class = "btn modal-close waves-effect waves-light" > Cancel < / a >
< a class = "btn modal-close red waves-effect waves-light delete-link" > < i class = "material-icons left" > delete < / i > D e l e t e < / a >
< / d i v >
< / d i v >
< / t d >
< / t r > ` ,
valueNames : [
"author" ,
"filename" ,
"publishing_year" ,
"title" ,
"title1" ,
{ name : "delete-link" , attr : "href" } ,
{ name : "delete-modal-trigger" , attr : "data-target" } ,
{ name : "delete-modal" , attr : "id" } ,
{ name : "download-link" , attr : "href" } ,
{ name : "link" , attr : "href" } ,
] ,
} ,
Job : {
item : ` <tr>
< 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 >
< td >
< div class = "right-align" >
< a class = "btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data - position = "top" data - tooltip = "Delete" >
< i class = "material-icons" > delete < / i >
< / a >
< a class = "btn-floating tooltipped waves-effect waves-light link" data - position = "top" data - tooltip = "Go to job" >
< i class = "material-icons" > send < / i >
< / a >
< / d i v >
< div class = "modal delete-modal" >
< div class = "modal-content" >
< h4 > Confirm job deletion < / h 4 >
< p > Do you really want to delete the job < b class = "title1" > < / b > ? A l l f i l e s w i l l b e p e r m a n e n t l y d e l e t e d ! < / p >
< / d i v >
< div class = "modal-footer" >
< a href = "#!" class = "btn modal-close waves-effect waves-light" > Cancel < / a >
< a class = "btn modal-close red waves-effect waves-light delete-link" > < i class = "material-icons left" > delete < / i > D e l e t e < / a >
< / d i v >
< / d i v >
< / t d >
< / t r > ` ,
valueNames : [
"creation_date" ,
"description" ,
"title" ,
"title1" ,
{ data : [ "id" ] } ,
{ name : "delete-link" , attr : "href" } ,
{ name : "delete-modal-trigger" , attr : "data-target" } ,
{ name : "delete-modal" , attr : "id" } ,
{ name : "link" , attr : "href" } ,
{ name : "service" , attr : "data-service" } ,
{ name : "status" , attr : "data-status" } ,
] ,
} ,
JobInput : {
item : ` <tr>
< td class = "filename" > < / t d >
< td class = "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 > ` ,
valueNames : [
"filename" ,
"id" ,
{ name : "download-link" , attr : "href" } ,
] ,
} ,
QueryResult : {
item : ` <tr>
< td >
< 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 >
< div class = "right-align" >
< a class = "btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data - position = "top" data - tooltip = "Delete" >
< i class = "material-icons" > delete < / i >
< / a >
< a class = "btn-floating tooltipped waves-effect waves-light link" 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 >
< / a >
< / d i v >
< div class = "modal delete-modal" >
< div class = "modal-content" >
< h4 > Confirm query result deletion < / h 4 >
< p > Do you really want to delete the query result < b class = "title1" > < / b > ? I t w i l l b e p e r m a n e n t l y d e l e t e d ! < / p >
< / d i v >
< div class = "modal-footer" >
< a href = "#!" class = "btn modal-close waves-effect waves-light" > Cancel < / a >
< a class = "btn modal-close red waves-effect waves-light delete-link" > < i class = "material-icons left" > delete < / i > D e l e t e < / a >
< / d i v >
< / d i v >
< / t d >
< / t r > ` ,
valueNames : [
"corpus_name" ,
"description" ,
"query" ,
"title" ,
"title2" ,
{ data : [ "id" ] } ,
{ name : "delete-link" , attr : "href" } ,
{ name : "delete-modal-trigger" , attr : "data-target" } ,
{ name : "delete-modal" , attr : "id" } ,
{ name : "inspect-link" , attr : "href" } ,
{ name : "link" , attr : "href" } ,
] ,
} ,
User : {
item : ` <tr>
< 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 >
< td >
< div class = "right-align" >
< a class = "btn-floating modal-trigger red tooltipped waves-effect waves-light delete-modal-trigger" data - position = "top" data - tooltip = "Delete" >
< i class = "material-icons" > delete < / i >
< / a >
< a class = "btn-floating tooltipped waves-effect waves-light link" data - position = "top" data - tooltip = "Go to user" >
< i class = "material-icons" > send < / i >
< / a >
< / d i v >
< div class = "modal delete-modal" >
< div class = "modal-content" >
< h4 > Confirm corpus deletion < / h 4 >
< p > Do you really want to delete the job < b class = "title1" > < / b > ? A l l f i l e s w i l l b e p e r m a n e n t l y d e l e t e d ! < / p >
< / d i v >
< div class = "modal-footer" >
< a href = "#!" class = "btn modal-close waves-effect waves-light" > Cancel < / a >
< a class = "btn modal-close red waves-effect waves-light delete-link" > < i class = "material-icons left" > delete < / i > D e l e t e < / a >
< / d i v >
< / d i v >
< / t d >
< / t r > ` ,
valueNames : [
"username" ,
"username2" ,
"email" ,
"role_id" ,
"confirmed" ,
"id" ,
{ name : "link" , attr : "href" } ,
{ name : "delete-link" , attr : "href" } ,
{ name : "delete-modal-trigger" , attr : "data-target" } ,
{ name : "delete-modal" , attr : "id" } ,
] ,
} ,
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
2020-07-20 07:31:27 +00:00
for ( let interaction of interactionElements . interactions ) {
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" ) ;
2020-08-06 08:42:35 +00:00
btn . textContent = "check" ;
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
helperDeactivateBtn ( btn ) {
btn . classList . remove ( "green" ) ;
btn . classList . add ( "grey" ) ;
2020-08-06 08:42:35 +00:00
btn . textContent = "add" ;
2020-06-25 15:44:55 +00:00
}
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
2020-08-06 08:42:35 +00:00
textarea . textContent = [ ... this . addToSubResultsIdsToShow ] . sort ( function ( a , b ) { return a - b } ) . join ( ", " ) ; // automaticalle sorts ids into the textarea in ascending order
2020-06-26 07:51:10 +00:00
M . textareaAutoResize ( textarea ) ; // after an insert textarea has to be resized manually
2020-08-06 08:42:35 +00:00
nrMarkedMatches . textContent = [ ... 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
2020-08-06 08:42:35 +00:00
textarea . textContent = [ ... this . addToSubResultsIdsToShow ] . sort ( function ( a , b ) { return a - b } ) . join ( ", " ) ; // automaticalle sorts ids into the textarea in ascending order
nrMarkedMatches . textContent = [ ... 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-07-20 07:31:27 +00:00
// Toggles the create button according 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-07-20 07:31:27 +00:00
if ( resultCreationRunning ) {
subResultsCreateElement . classList . add ( "disabled" ) ;
}
2020-06-26 07:51:10 +00:00
// After a match as been added or removed the export button will be
2020-07-20 07:31:27 +00:00
// hidden because the sub-results have been altered and have to be built
// again. Thus subResultsCreateElement has to be shown again.
2020-07-16 12:00:52 +00:00
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-20 07:31:27 +00:00
// deactivate inspect buttons
deactivateInspect ( ) {
let inspectBtnElements ;
inspectBtnElements = document . getElementsByClassName ( "inspect" ) ;
for ( let inspectBtn of inspectBtnElements ) {
inspectBtn . classList . add ( "disabled" ) ;
}
}
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 ( ) ;
2020-08-06 08:42:35 +00:00
// match nr for user to display derived from data_index
let contextMatchNrElement = document . getElementById ( "context-match-nr" ) ;
contextMatchNrElement . textContent = this . contextId + 1 ;
2020-07-14 07:24:04 +00:00
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 ;
2020-08-06 08:42:35 +00:00
this . contextId = dataIndex ;
2020-07-14 07:24:04 +00:00
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-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 ] ;
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-08-06 08:42:35 +00:00
// match nr for user to display derived from data_index
let contextMatchNrElement = document . getElementById ( "context-match-nr" ) ;
contextMatchNrElement . textContent = this . contextId + 1 ;
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 )
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 `
) ;
2020-08-06 08:42:35 +00:00
inspectBtn . innerHTML = '<i class="material-icons inspect-btn">search</i>' ;
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-08-06 08:42:35 +00:00
addToSubResultsBtn . innerHTML = '<i class="material-icons add-btn">add</i>' ;
2020-06-25 15:44:55 +00:00
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-08-06 08:42:35 +00:00
textTitlesCellElement . textContent = [ ... textTitles ] . join ( ", " ) ;
2020-02-03 11:58:40 +00:00
matchRowElement . insertAdjacentHTML ( "afterbegin" , textTitlesCellElement . outerHTML ) ;
2020-08-06 08:42:35 +00:00
matchNrElement . textContent = 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
}
2020-07-21 11:40:17 +00:00
// creates the HTML table code for the metadata vie in the corpus analysis interface
createMetaDataForModal ( metaDataObject ) {
2020-07-22 11:15:55 +00:00
let html = ` <div class="col s12">
2020-07-21 11:40:17 +00:00
< table class = "highlight" >
< thead >
< tr >
< th > Metadata Description < / t h >
< th > Value < / t h >
< / t r >
< / t h e a d >
< tbody > `
for ( let [ outerKey , outerValue ] of Object . entries ( metaDataObject ) ) {
2020-07-22 11:15:55 +00:00
html += ` <tr>
< td style = "text-transform: uppercase;" > $ { outerKey . replace ( /_/g , " " ) } < / t d > `
2020-07-21 11:40:17 +00:00
if ( outerKey === "corpus_all_texts" || outerKey === "text_lookup" ) {
2020-07-22 11:15:55 +00:00
html += ` <td>
< ul class = "collapsible" > `
2020-07-21 11:40:17 +00:00
for ( let [ innerKey , innerValue ] of Object . entries ( outerValue ) ) {
2020-07-22 11:15:55 +00:00
html += ` <li class="text-metadata"
data - metadata - key = "${outerKey}"
data - text - key = "${innerKey}" >
< div class = "collapsible-header"
2020-07-21 11:40:17 +00:00
data - metadata - key = "${outerKey}"
2020-07-22 11:15:55 +00:00
data - text - key = "${innerKey}" >
< i class = "material-icons"
data - metadata - key = "${outerKey}"
data - text - key = "${innerKey}" > info _outline < / i >
$ { innerValue [ 'author' ] } - $ { innerValue [ 'publishing_year' ] } -
$ { innerValue [ 'title' ] }
< / d i v >
< div class = "collapsible-body" >
< span >
< ul id = "bibliographic-data-${outerKey}-${innerKey}"
style = "column-count: 2;" >
< / u l >
< / s p a n >
< / d i v >
< / l i > `
2020-07-21 11:40:17 +00:00
}
2020-07-22 11:15:55 +00:00
html += ` </ul>
< / t d > `
2020-07-21 11:40:17 +00:00
} else {
2020-07-22 11:15:55 +00:00
html += ` <td> ${ outerValue } </td> `
2020-07-21 11:40:17 +00:00
}
2020-07-22 11:15:55 +00:00
html += ` </tr> `
2020-07-21 11:40:17 +00:00
}
2020-07-22 11:15:55 +00:00
html += ` </tbody>
2020-07-21 11:40:17 +00:00
< / t a b l e > `
2020-07-22 11:15:55 +00:00
return html
2020-07-21 11:40:17 +00:00
}
// Creates the text details for the texts shown in the corpus analysis metadata modal.
createTextDetails ( metaDataObject ) {
let metadataKey = event . target . dataset . metadataKey ;
let textKey = event . target . dataset . textKey ;
let textData = metaDataObject [ metadataKey ] [ textKey ] ;
2020-07-22 11:15:55 +00:00
let bibliographicData = document . getElementById ( ` bibliographic-data- ${ metadataKey } - ${ textKey } ` ) ;
2020-07-21 11:40:17 +00:00
bibliographicData . innerHTML = "" ;
for ( let [ key , value ] of Object . entries ( textData ) ) {
2020-07-22 11:15:55 +00:00
bibliographicData . insertAdjacentHTML ( "afterbegin" ,
2020-07-21 11:40:17 +00:00
`
2020-07-22 11:15:55 +00:00
< li > < span style = "text-transform: capitalize;" > $ { key } : < / s p a n > $ { v a l u e } < / l i >
2020-07-21 11:40:17 +00:00
` );
}
}
2020-01-29 15:12:57 +00:00
}