mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-03 20:02:47 +00:00 
			
		
		
		
	Push before rework part 2
This commit is contained in:
		@@ -1,8 +1,10 @@
 | 
			
		||||
/**
 | 
			
		||||
 * This class is used to create an CorpusAnalysisClient object.
 | 
			
		||||
 * This class is used to create a CorpusAnalysisClient object.
 | 
			
		||||
 * The client handels the client server communication.
 | 
			
		||||
 * It requests data (e.g. the analysis session or query results) from the
 | 
			
		||||
 * the server and recieves them.
 | 
			
		||||
 * the server and recieves them, if it dynamicMode is true.
 | 
			
		||||
 * If dynamicMode is false, the client can also handle data that is already
 | 
			
		||||
 * loaded and not coming in in chunks.
 | 
			
		||||
 */
 | 
			
		||||
class CorpusAnalysisClient {
 | 
			
		||||
  constructor({corpusId = null,
 | 
			
		||||
@@ -19,11 +21,9 @@ class CorpusAnalysisClient {
 | 
			
		||||
    this.socketEventListeners = {};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set client into imported mode if SOME THIGN IS INDICATING it
 | 
			
		||||
     *
 | 
			
		||||
     * Disable all console logging.
 | 
			
		||||
     * Credits to https://gist.github.com/kmonsoor/0244fdb4ad79a4826371e58a1a5fa984
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    // Disable all console logging. Credits to https://gist.github.com/kmonsoor/0244fdb4ad79a4826371e58a1a5fa984
 | 
			
		||||
    if (!logging) {
 | 
			
		||||
      (() => {
 | 
			
		||||
        let console = (window.console = window.console || {});
 | 
			
		||||
@@ -32,7 +32,7 @@ class CorpusAnalysisClient {
 | 
			
		||||
          'error', 'exception', 'group', 'groupCollapsed', 'groupEnd',
 | 
			
		||||
          'info', 'log', 'markTimeline', 'profile', 'profileEnd', 'table',
 | 
			
		||||
          'time', 'timeEnd', 'timeStamp', 'trace', 'warn'
 | 
			
		||||
        ].forEach(method => {
 | 
			
		||||
        ].forEach((method) => {
 | 
			
		||||
          console[method] = () => {};
 | 
			
		||||
        });
 | 
			
		||||
      })();
 | 
			
		||||
@@ -41,14 +41,18 @@ class CorpusAnalysisClient {
 | 
			
		||||
 | 
			
		||||
  // Registers one or more SocketEventListeners to the CorpusAnalysisClient.
 | 
			
		||||
  setSocketEventListeners(socketEventListeners) {
 | 
			
		||||
    for (let listener of socketEventListeners) {
 | 
			
		||||
      this.socketEventListeners[listener.type] = listener.listenerFunction;
 | 
			
		||||
    for (let socketEventListener of socketEventListeners) {
 | 
			
		||||
      this.socketEventListeners[socketEventListener.type] = socketEventListener;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Loads the SocketEventListeners so they will be triggered on their assigned
 | 
			
		||||
   * type strings because they double as the socket event event names.
 | 
			
		||||
   */
 | 
			
		||||
  loadSocketEventListeners() {
 | 
			
		||||
    for (let [type, listener] of Object.entries(this.socketEventListeners)) {
 | 
			
		||||
      listener(this);
 | 
			
		||||
      listener.listenerFunction(type, this);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -64,12 +68,14 @@ class CorpusAnalysisClient {
 | 
			
		||||
   * string as the key. The selector will be converted to a valid JavaScript
 | 
			
		||||
   * Field name i. e. #html-id-string -> this.htmlIdString
 | 
			
		||||
   * The value will be the identifed element fetched with the querySelector
 | 
			
		||||
   * method. MutlipleResults and atattchSomeCallback not yet implemented.
 | 
			
		||||
   * method.
 | 
			
		||||
   */
 | 
			
		||||
  getHTMLElements(arrayOfSelectors, multipleResults=false, atattchSomeCallback=false) {
 | 
			
		||||
  // TODO: multipleResults=false, atattchSomeCallback=false ?
 | 
			
		||||
  getHTMLElements(arrayOfSelectors) {
 | 
			
		||||
    for (let selector of arrayOfSelectors) {
 | 
			
		||||
      let element = document.querySelector(selector);
 | 
			
		||||
      let cleanKey = [];
 | 
			
		||||
      selector = selector.replace('_', '-');
 | 
			
		||||
      selector.match(/\w+/g).forEach((word) => {
 | 
			
		||||
        let tmp = word[0].toUpperCase() + word.slice(1);
 | 
			
		||||
        cleanKey.push(tmp);
 | 
			
		||||
@@ -82,7 +88,8 @@ class CorpusAnalysisClient {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Requests a corpus analysis session via socket.io.
 | 
			
		||||
   * Opens a loading modal at the start of the request
 | 
			
		||||
   * Opens a loading modal at the start of the request.
 | 
			
		||||
   * Will be closed if session has been successfully recieved.
 | 
			
		||||
   */
 | 
			
		||||
  requestSession() {
 | 
			
		||||
    console.info('corpus_analysis_init: Client requesting session via',
 | 
			
		||||
@@ -95,7 +102,7 @@ class CorpusAnalysisClient {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Sends the query string to the server.
 | 
			
		||||
   * Request query data for the query string that has been sent to the server.
 | 
			
		||||
   */
 | 
			
		||||
  requestQueryData(queryStr) {
 | 
			
		||||
    console.info('corpus_analysis_query: Client requesting query data via',
 | 
			
		||||
@@ -180,16 +187,57 @@ class CorpusAnalysisDisplay {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This class is used to create an CorpusAnalysisDisplay object.
 | 
			
		||||
 * Input is one HTMLElement that can then be hidden or shown depending on
 | 
			
		||||
 * its CSS classes.
 | 
			
		||||
 * This class is used to create an SocketEventListener.
 | 
			
		||||
 * Input are an identifying type string, the listener function and callbacks
 | 
			
		||||
 * which will be executed as part of the listener function. The identifying
 | 
			
		||||
 * type string is also used as the socket event event identifier.
 | 
			
		||||
 */
 | 
			
		||||
class SocketEventListener {
 | 
			
		||||
  constructor(type, listenerFunction) {
 | 
			
		||||
    this.listenerCallbacks = {};
 | 
			
		||||
    this.listenerFunction = listenerFunction;
 | 
			
		||||
    this.type = type;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Registers callbacks to this SocketEventListener
 | 
			
		||||
  setCallbacks(listenerCallbacks) {
 | 
			
		||||
    for (let listenerCallback of listenerCallbacks) {
 | 
			
		||||
      this.listenerCallbacks[listenerCallback.type] = listenerCallback;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Shorthand to execute all registered callbacks with same args in insertion
 | 
			
		||||
   * order.
 | 
			
		||||
   * NOTE:
 | 
			
		||||
   * Since ECMAScript 2015, objects do preserve creation order for
 | 
			
		||||
   * string and Symbol keys. In JavaScript engines that comply with the
 | 
			
		||||
   * ECMAScript 2015 spec, iterating over an object with only string keys will
 | 
			
		||||
   * yield the keys in order of insertion.
 | 
			
		||||
   * So all modern Browsers.
 | 
			
		||||
   */
 | 
			
		||||
  executeCallbacks(args) {
 | 
			
		||||
    for (let [type, listenerCallback] of Object.entries(this.listenerCallbacks)) {
 | 
			
		||||
      listenerCallback.callbackFunction(...args);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This class is used to create an ListenerCallback which will be registered
 | 
			
		||||
 * to an SocketEventListener so the Listener cann invoke the ListenerCallback
 | 
			
		||||
 * callback functions.
 | 
			
		||||
 */
 | 
			
		||||
class ListenerCallback {
 | 
			
		||||
  constructor(type, callbackFunction) {
 | 
			
		||||
    this.callbackFunction = callbackFunction;
 | 
			
		||||
    this.type = type;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// export Classes from this module
 | 
			
		||||
export {CorpusAnalysisClient, CorpusAnalysisDisplay, SocketEventListener};
 | 
			
		||||
export {
 | 
			
		||||
  CorpusAnalysisClient,
 | 
			
		||||
  CorpusAnalysisDisplay,
 | 
			
		||||
  SocketEventListener,
 | 
			
		||||
  ListenerCallback,
 | 
			
		||||
};
 | 
			
		||||
@@ -62,3 +62,6 @@ class InteractionElements {
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// export Classes
 | 
			
		||||
export { InteractionElement, InteractionElements };
 | 
			
		||||
@@ -1,10 +1,8 @@
 | 
			
		||||
// This callback is called on socket.on "query".
 | 
			
		||||
// Does some hiding, showing disabling etc.
 | 
			
		||||
/**
 | 
			
		||||
 * This call back is called when the SocketEventListener 'recieveQueryStatus'
 | 
			
		||||
 * has been triggered. It just gets the incoming status data of the issued
 | 
			
		||||
 * This callback should be registered to the SocketEventListener 'recieveQueryStatus'.
 | 
			
		||||
 * It just gets the incoming status data of the issued query
 | 
			
		||||
 * and does some preperation work like hiding or showing elements and deleting
 | 
			
		||||
 * the date from the last query.
 | 
			
		||||
 * the data from the last query.
 | 
			
		||||
 */
 | 
			
		||||
function querySetup(payload, client) {
 | 
			
		||||
  // deletes old data from query issued before this new query
 | 
			
		||||
@@ -12,23 +10,29 @@ function querySetup(payload, client) {
 | 
			
		||||
  // load necessary HTMLElements with selectory syntax and save them as fields
 | 
			
		||||
  client.getHTMLElements(['#query-progress-bar', '#query-results-user-feedback',
 | 
			
		||||
                          '#recieved-match-count', '#total-match-count',
 | 
			
		||||
                          '#text-lookup-count', '#text-lookup-titles']);
 | 
			
		||||
                          '#text-lookup-count', '#text-lookup-titles',
 | 
			
		||||
                          '#query-results-create', '#add-to-sub-results']);
 | 
			
		||||
  client.requestQueryProgress = 0;
 | 
			
		||||
  client.recievedMatchCount.textContent = 0;
 | 
			
		||||
  client.totalMatchCount.textContent = `${payload.match_count}`;
 | 
			
		||||
  client.queryResultsUserFeedback.classList.toggle('hide');
 | 
			
		||||
  client.queryProgressBar.classList.toggle('hide');
 | 
			
		||||
  client.queryProgressBar.lastElementChild.style.width = '0%'
 | 
			
		||||
  client.queryProgressBar.lastElementChild.style.width = '0%';
 | 
			
		||||
  if (client.dynamicMode) {
 | 
			
		||||
    client.addToSubResults.toggleAttribute('disabled');
 | 
			
		||||
    client.queryResultsCreate.classList.toggle('disabled');
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This callback is called when the SocketEventListener 'recieveQueryData'
 | 
			
		||||
 * has been triggered. It takes the incoming chunk and renders the results in a
 | 
			
		||||
 * the results.jsList. It can either handle live incoming data or imported
 | 
			
		||||
 * results data.
 | 
			
		||||
 * This callback should be registered to the SocketEventListener 'recieveQueryData'
 | 
			
		||||
 * It takes the incoming chunk and renders the results using the
 | 
			
		||||
 * results.jsList object. It can either handle live incoming data chunks or
 | 
			
		||||
 * already loaded/imported results data.
 | 
			
		||||
 */
 | 
			
		||||
function queryRenderResults(payload, client) {
 | 
			
		||||
  client.getHTMLElements(['#recieved-match-count', '#match-count'])
 | 
			
		||||
  client.getHTMLElements(['#recieved-match-count', '#match-count',
 | 
			
		||||
                          '#display-options-form-expert_mode']);
 | 
			
		||||
  const renderResults = (data) => {
 | 
			
		||||
    /**
 | 
			
		||||
     * resultItem saves the incoming chunk matches as objects to add those later
 | 
			
		||||
@@ -59,11 +63,10 @@ function queryRenderResults(payload, client) {
 | 
			
		||||
       * activate, hide or show elements if all reults have been recieved
 | 
			
		||||
       * also load some new elements taht have not ben loaded before
 | 
			
		||||
       */
 | 
			
		||||
      client.getHTMLElements(['#query-results-create']);
 | 
			
		||||
      client.queryProgressBar.classList.toggle('hide');
 | 
			
		||||
      client.queryResultsUserFeedback.classList.toggle('hide');
 | 
			
		||||
      client.queryResultsCreate.classList.toggle('disabled');
 | 
			
		||||
    //   resultsExportElement.classList.remove("disabled");
 | 
			
		||||
      client.addToSubResults.toggleAttribute('disabled');
 | 
			
		||||
    //   addToSubResultsElement.removeAttribute("disabled");
 | 
			
		||||
    //   // inital expert mode check and sub results activation
 | 
			
		||||
    //   client.results.jsList.activateInspect();
 | 
			
		||||
@@ -75,19 +78,21 @@ function queryRenderResults(payload, client) {
 | 
			
		||||
    //   }
 | 
			
		||||
    }
 | 
			
		||||
  } else if (!client.dynamicMode) {
 | 
			
		||||
    client.requestQueryProgress === 100;
 | 
			
		||||
    client.queryResultsUserFeedback.classList.toggle('hide');
 | 
			
		||||
    renderResults(payload);
 | 
			
		||||
    helperQueryRenderResults({'chunk': payload}, client);
 | 
			
		||||
    client.queryProgressBar.classList.toggle('hide');
 | 
			
		||||
    client.queryResultsUserFeedback.classList.toggle('hide');
 | 
			
		||||
    client.results.jsList.activateInspect();
 | 
			
		||||
    if (expertModeSwitchElement.checked) {
 | 
			
		||||
    if (client.displayOptionsFormExpertMode.checked) {
 | 
			
		||||
      client.results.jsList.expertModeOn("query-display");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Helper function that saves result data into the client.results.data object.
 | 
			
		||||
 * Also does some showing and hiding of Elements and user feedback text.
 | 
			
		||||
 */
 | 
			
		||||
function helperQueryRenderResults (payload, client) {
 | 
			
		||||
  // updating table on finished item creation callback via createResultRowElement
 | 
			
		||||
  client.results.jsList.update();
 | 
			
		||||
@@ -111,6 +116,5 @@ function helperQueryRenderResults (payload, client) {
 | 
			
		||||
  client.requestQueryProgress = payload.progress;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: Add data to data objekt using its own socket on event?
 | 
			
		||||
 | 
			
		||||
export { querySetup, queryRenderResults }
 | 
			
		||||
// export callbacks
 | 
			
		||||
export { querySetup, queryRenderResults };
 | 
			
		||||
@@ -5,10 +5,10 @@ import { querySetup, queryRenderResults } from './nopaque.listenerCallbacks.js'
 | 
			
		||||
 * Closes the loading modal that has been opend with requestSession at the
 | 
			
		||||
 * start of the request.
 | 
			
		||||
 */
 | 
			
		||||
function recieveSession(client) {
 | 
			
		||||
  client.socket.on('corpus_analysis_init', (response) => {
 | 
			
		||||
function recieveSession(type, client) {
 | 
			
		||||
  client.socket.on(type, (response) => {
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if request for session was ok.
 | 
			
		||||
     * Check if request for session was OK.
 | 
			
		||||
     * If OK execute callbacks and hide/show displays.
 | 
			
		||||
     */
 | 
			
		||||
    console.group('recieve session')
 | 
			
		||||
@@ -44,11 +44,11 @@ function recieveSession(client) {
 | 
			
		||||
 * was invalid etc.
 | 
			
		||||
 * Also prepares the result.jsList for the incoming data.
 | 
			
		||||
 */
 | 
			
		||||
function recieveQueryStatus(client) {
 | 
			
		||||
  client.socket.on('corpus_analysis_query', (response) => {
 | 
			
		||||
function recieveQueryStatus(type, client) {
 | 
			
		||||
  client.socket.on(type, (response) => {
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if issued query was ok.
 | 
			
		||||
     * If OK execute callbacks and hide/show displays.
 | 
			
		||||
     * Check if issued query was OK.
 | 
			
		||||
     * If OK execute registered callbacks and hide/show displays.
 | 
			
		||||
     */
 | 
			
		||||
    console.group('corpus_analysis_query: Client recieving query process',
 | 
			
		||||
                  'status via socket.on');
 | 
			
		||||
@@ -59,8 +59,8 @@ function recieveQueryStatus(client) {
 | 
			
		||||
      if (client.displays.query != undefined)  {
 | 
			
		||||
        client.displays.query.setVisibilityByStatus("success");
 | 
			
		||||
      }
 | 
			
		||||
      // executing the callbacks
 | 
			
		||||
      querySetup(response.payload, client);
 | 
			
		||||
      // executing the registered callbacks
 | 
			
		||||
      client.socketEventListeners[type].executeCallbacks([response.payload, client]);
 | 
			
		||||
    } else {
 | 
			
		||||
      let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
 | 
			
		||||
      if (response.payload.code == 1281) {
 | 
			
		||||
@@ -83,20 +83,22 @@ function recieveQueryStatus(client) {
 | 
			
		||||
/**
 | 
			
		||||
 * Recieves the query data from the request and handles it.
 | 
			
		||||
 */
 | 
			
		||||
function recieveQueryData(client) {
 | 
			
		||||
function recieveQueryData(type, client) {
 | 
			
		||||
  console.group('corpus_analysis_query_results: Client recieving or loading',
 | 
			
		||||
                'query data.');
 | 
			
		||||
  if (client.dynamicMode) {
 | 
			
		||||
    console.info('Client recieving query data via socket.on');
 | 
			
		||||
    client.socket.on('corpus_analysis_query_results', (response) => {
 | 
			
		||||
    client.socket.on(type, (response) => {
 | 
			
		||||
    console.info('Recieved chunk', response);
 | 
			
		||||
    queryRenderResults(response.payload, client);
 | 
			
		||||
    // executing the registered callbacks
 | 
			
		||||
    client.socketEventListeners[type].executeCallbacks([response.payload, client]);
 | 
			
		||||
    console.info('Added chunk data to results.data and rendered it with',
 | 
			
		||||
                 'results.jsList');
 | 
			
		||||
    });
 | 
			
		||||
  } else {
 | 
			
		||||
    console.info('Client loading imported query data from database.');
 | 
			
		||||
    queryRenderResults(client.results.data, client);
 | 
			
		||||
    // executing the registered callbacks
 | 
			
		||||
    client.socketEventListeners[type].executeCallbacks([client.results.data, client]);
 | 
			
		||||
  }
 | 
			
		||||
  console.groupEnd();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								web/app/static/js/modules/nopaque.scrollToTop.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								web/app/static/js/modules/nopaque.scrollToTop.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Function to show a scrol lto top button if the user has scrolled down
 | 
			
		||||
 * 250 pixels from teh headline element.
 | 
			
		||||
 */
 | 
			
		||||
function scrollToTop() {
 | 
			
		||||
  let headline = document.querySelector(".headline");
 | 
			
		||||
  let scrollToTop = document.querySelector("#menu-scroll-to-top-div");
 | 
			
		||||
  window.addEventListener("scroll", (event) => {
 | 
			
		||||
    if (pageYOffset > 250) {
 | 
			
		||||
      scrollToTop.classList.toggle("hide", false);
 | 
			
		||||
    } else {
 | 
			
		||||
      scrollToTop.classList.toggle("hide", true);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
  scrollToTop.onclick = () => {
 | 
			
		||||
    headline.scrollIntoView({behavior: "smooth", block: "end", inline: "nearest"});
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// export function
 | 
			
		||||
export { scrollToTop };
 | 
			
		||||
@@ -425,6 +425,10 @@ RessourceList.options = {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ResultsList extends List {
 | 
			
		||||
  /**
 | 
			
		||||
   * If no options are given when a new instance of this class is created
 | 
			
		||||
   * the options below are used.
 | 
			
		||||
   */
 | 
			
		||||
  static options = {
 | 
			
		||||
    page: 10,
 | 
			
		||||
    pagination: [{
 | 
			
		||||
@@ -443,12 +447,19 @@ class ResultsList extends List {
 | 
			
		||||
  constructor(idOrElement, options) {
 | 
			
		||||
    super(idOrElement, options);
 | 
			
		||||
    this.options = options;
 | 
			
		||||
    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
 | 
			
		||||
    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.
 | 
			
		||||
    /**
 | 
			
		||||
     * All span tokens which are holding events if expert
 | 
			
		||||
     * mode is on. Collected here to delete later on.
 | 
			
		||||
     */
 | 
			
		||||
    this.eventTokens = {};
 | 
			
		||||
    /**
 | 
			
		||||
    * all token elements which have added
 | 
			
		||||
    * classes like chip and hoverable for expert view. Collected
 | 
			
		||||
    * here to delete later on
 | 
			
		||||
    */
 | 
			
		||||
    this.currentExpertTokenElements = {};
 | 
			
		||||
     // 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.addToSubResultsStatus = {};
 | 
			
		||||
    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.
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -620,7 +631,7 @@ class ResultsList extends List {
 | 
			
		||||
  // ###### Functions to inspect one match, to show more details ######
 | 
			
		||||
  // activate inspect buttons if progress is 100
 | 
			
		||||
  activateInspect() {
 | 
			
		||||
    if (progress === 100) {
 | 
			
		||||
    if (this.requestQueryProgress === 100) {
 | 
			
		||||
      let inspectBtnElements;
 | 
			
		||||
      inspectBtnElements = document.getElementsByClassName("inspect");
 | 
			
		||||
      for (let inspectBtn of inspectBtnElements) {
 | 
			
		||||
@@ -958,45 +969,43 @@ class ResultsList extends List {
 | 
			
		||||
 | 
			
		||||
  // ###### Expert view event functions ######
 | 
			
		||||
  // function to create a tooltip for the current hovered token
 | 
			
		||||
  tooltipEventCreate(event) {
 | 
			
		||||
  tooltipEventCreate(event, client) {
 | 
			
		||||
    // console.log("Create Tooltip on mouseover.");
 | 
			
		||||
    let token;
 | 
			
		||||
    token = results.data.cpos_lookup[event.target.dataset.cpos];
 | 
			
		||||
    let token = client.results.data.cpos_lookup[event.target.dataset.cpos];
 | 
			
		||||
    if (!token) {
 | 
			
		||||
      token = this.contextData.cpos_lookup[event.target.dataset.cpos];
 | 
			
		||||
    }
 | 
			
		||||
    this.addToolTipToTokenElement(event.target, token);
 | 
			
		||||
    this.addToolTipToTokenElement(event.target, token, client);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Function to destroy the current Tooltip for the current hovered tooltip
 | 
			
		||||
  // on mouse leave
 | 
			
		||||
  tooltipEventDestroy(event) {
 | 
			
		||||
  tooltipEventDestroy() {
 | 
			
		||||
    // console.log("Tooltip destroy on leave.");
 | 
			
		||||
    this.currentTooltipElement.destroy();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  expertModeOn(htmlId) {
 | 
			
		||||
    // turn the expert mode on for all tokens in the DOM element identified by its htmlID
 | 
			
		||||
  // turn the expert mode on for all tokens in the DOM element identified by its htmlID
 | 
			
		||||
  expertModeOn(htmlId, client) {
 | 
			
		||||
    if (!Array.isArray(this.currentExpertTokenElements[htmlId])) {
 | 
			
		||||
      this.currentExpertTokenElements[htmlId] = [];
 | 
			
		||||
    }
 | 
			
		||||
    let container = document.getElementById(htmlId);
 | 
			
		||||
    let tokens = container.querySelectorAll("span.token");
 | 
			
		||||
    this.currentExpertTokenElements[htmlId].push(...tokens);
 | 
			
		||||
    this.tooltipEventCreateBind = this.tooltipEventCreate.bind(this);
 | 
			
		||||
    this.tooltipEventDestroyBind = this.tooltipEventDestroy.bind(this);
 | 
			
		||||
    this.eventTokens[htmlId] = [];
 | 
			
		||||
    for (let tokenElement of this.currentExpertTokenElements[htmlId]) {
 | 
			
		||||
      tokenElement.classList.add("chip", "hoverable", "expert-view");
 | 
			
		||||
      tokenElement.onmouseover = this.tooltipEventCreateBind;
 | 
			
		||||
      tokenElement.onmouseout = this.tooltipEventDestroyBind;
 | 
			
		||||
      const eventCreate = (event, arg) => this.tooltipEventCreate(event, arg);
 | 
			
		||||
      tokenElement.onmouseover = (event) => eventCreate(event, client);
 | 
			
		||||
      tokenElement.onmouseout = () => this.tooltipEventDestroy();
 | 
			
		||||
      this.eventTokens[htmlId].push(tokenElement);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // fuction that creates Tooltip for one token and extracts the corresponding
 | 
			
		||||
  // infos from the result JSON
 | 
			
		||||
  addToolTipToTokenElement(tokenElement, token) {
 | 
			
		||||
  addToolTipToTokenElement(tokenElement, token, client) {
 | 
			
		||||
    this.currentTooltipElement;
 | 
			
		||||
    this.currentTooltipElement = M.Tooltip.init(tokenElement,
 | 
			
		||||
     {"html": `<table>
 | 
			
		||||
@@ -1013,11 +1022,11 @@ class ResultsList extends List {
 | 
			
		||||
                     NER: ${token.ner}
 | 
			
		||||
                   </td>
 | 
			
		||||
                   <td class="left-align">
 | 
			
		||||
                     Title: ${results.data.text_lookup[token.text].title}
 | 
			
		||||
                     Title: ${client.results.data.text_lookup[token.text].title}
 | 
			
		||||
                     <br>
 | 
			
		||||
                     Author: ${results.data.text_lookup[token.text].author}
 | 
			
		||||
                     Author: ${client.results.data.text_lookup[token.text].author}
 | 
			
		||||
                     <br>
 | 
			
		||||
                     Publishing year: ${results.data.text_lookup[token.text].publishing_year}
 | 
			
		||||
                     Publishing year: ${client.results.data.text_lookup[token.text].publishing_year}
 | 
			
		||||
                   </td>
 | 
			
		||||
                 </tr>
 | 
			
		||||
               </table>`}
 | 
			
		||||
 
 | 
			
		||||
@@ -69,22 +69,45 @@
 | 
			
		||||
<script type="module">
 | 
			
		||||
/**
 | 
			
		||||
 * First Phase:
 | 
			
		||||
 * document content is loaded and scripts are being imported and executed
 | 
			
		||||
 * Document content is loaded and scripts are being imported and executed.
 | 
			
		||||
 */
 | 
			
		||||
import { CorpusAnalysisClient,
 | 
			
		||||
        CorpusAnalysisDisplay,
 | 
			
		||||
        SocketEventListener } from '../../static/js/modules/nopaque.CorpusAnalysisClient.js';
 | 
			
		||||
import { recieveSession, recieveQueryStatus,
 | 
			
		||||
        recieveQueryData } from '../../static/js/modules/nopaque.listenerFunctions.js';
 | 
			
		||||
import { Results, Data, MetaData } from '../../static/js/nopaque.Results.js';
 | 
			
		||||
import { ResultsList } from '../../static/js/nopaque.lists.js';
 | 
			
		||||
import {
 | 
			
		||||
  CorpusAnalysisClient,
 | 
			
		||||
  CorpusAnalysisDisplay,
 | 
			
		||||
  SocketEventListener,
 | 
			
		||||
  ListenerCallback,
 | 
			
		||||
} from '../../static/js/modules/nopaque.CorpusAnalysisClient.js';
 | 
			
		||||
import {
 | 
			
		||||
  recieveSession,
 | 
			
		||||
  recieveQueryStatus,
 | 
			
		||||
  recieveQueryData,
 | 
			
		||||
} from '../../static/js/modules/nopaque.listenerFunctions.js';
 | 
			
		||||
import {
 | 
			
		||||
  querySetup,
 | 
			
		||||
  queryRenderResults,
 | 
			
		||||
} from '../../static/js/modules/nopaque.listenerCallbacks.js'
 | 
			
		||||
import {
 | 
			
		||||
  Results,
 | 
			
		||||
  Data,
 | 
			
		||||
  MetaData,
 | 
			
		||||
} from '../../static/js/nopaque.Results.js';
 | 
			
		||||
import {
 | 
			
		||||
  ResultsList,
 | 
			
		||||
} from '../../static/js/nopaque.lists.js';
 | 
			
		||||
import {
 | 
			
		||||
  scrollToTop,
 | 
			
		||||
} from '../../static/js/modules/nopaque.scrollToTop.js';
 | 
			
		||||
import {
 | 
			
		||||
  InteractionElement,
 | 
			
		||||
  InteractionElements,
 | 
			
		||||
} from '../../static/js/modules/nopaque.InteractionElement.js';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Second Phase:
 | 
			
		||||
 * Asynchronus and event driven code
 | 
			
		||||
 */
 | 
			
		||||
document.addEventListener("DOMContentLoaded", () => {
 | 
			
		||||
  // Initialize the CorpusAnalysisClient
 | 
			
		||||
  // Initialize the CorpusAnalysisClient dynamic mode
 | 
			
		||||
  let corpusId = {{ corpus_id}}
 | 
			
		||||
  const client = new CorpusAnalysisClient({'corpusId': corpusId,
 | 
			
		||||
                                           'socket': nopaque.socket,
 | 
			
		||||
@@ -95,7 +118,7 @@ document.addEventListener("DOMContentLoaded", () => {
 | 
			
		||||
  const initLoadingElement = document.getElementById("init-display");
 | 
			
		||||
  const initLoadingModal = M.Modal.init(initLoadingElement,
 | 
			
		||||
                                        {"dismissible": false});
 | 
			
		||||
  // Set up display elements which hare show depending on the client status
 | 
			
		||||
  // Set up display elements which are shown depending on the client status
 | 
			
		||||
  const initLoadingDisplay = new CorpusAnalysisDisplay(initLoadingModal);
 | 
			
		||||
  client.getHTMLElements(['#query-display']);
 | 
			
		||||
  const queryDisplay = new CorpusAnalysisDisplay(client.queryDisplay);
 | 
			
		||||
@@ -105,27 +128,79 @@ document.addEventListener("DOMContentLoaded", () => {
 | 
			
		||||
  /**
 | 
			
		||||
   * Initializing the results object holding all the data of a query.
 | 
			
		||||
   * Also holds the metadata of one query.
 | 
			
		||||
   * resultsListOptions is set to determine how many results per page are
 | 
			
		||||
   * shown etc.
 | 
			
		||||
   * Lastly it contains the object ResultsList which is a list.js
 | 
			
		||||
   * subclass which handles the visual representation of the query data.
 | 
			
		||||
   */
 | 
			
		||||
   let displayOptionsData = ResultsList.getDisplayOptions('display-options-form');
 | 
			
		||||
   ResultsList.options.page = displayOptionsData["resultsPerPage"];
 | 
			
		||||
   let data = new Data();
 | 
			
		||||
   let resultsList = new ResultsList("result-list", ResultsList.options);
 | 
			
		||||
   let resultsMetaData = new MetaData();
 | 
			
		||||
   let results = new Results(data, resultsList, resultsMetaData);
 | 
			
		||||
   // make results part of the client
 | 
			
		||||
   client.results = results;
 | 
			
		||||
   console.info('Initialized the Results object.')
 | 
			
		||||
  // register listeners listening to socket.io events and load them
 | 
			
		||||
  let displayOptionsData = ResultsList.getDisplayOptions('display-options-form');
 | 
			
		||||
  ResultsList.options.page = displayOptionsData["resultsPerPage"];
 | 
			
		||||
  let data = new Data();
 | 
			
		||||
  let resultsList = new ResultsList("result-list", ResultsList.options);
 | 
			
		||||
  let resultsMetaData = new MetaData();
 | 
			
		||||
  let results = new Results(data, resultsList, resultsMetaData);
 | 
			
		||||
  // Make results part of the client
 | 
			
		||||
  client.results = results;
 | 
			
		||||
  console.info('Initialized the Results object.')
 | 
			
		||||
  /**
 | 
			
		||||
   * Initialization of interactionElemnts
 | 
			
		||||
   * An interactionElement is an object identifing a switch or button via
 | 
			
		||||
   * htmlID. Callbacks are set for these elements which will be triggered on
 | 
			
		||||
   * a pagination interaction by the user or if the status of the element has
 | 
			
		||||
   * been altered. (Like the switche has ben turned on or off).
 | 
			
		||||
   */
 | 
			
		||||
  let interactionElements = new InteractionElements();
 | 
			
		||||
  const expertModeInteraction = new InteractionElement("display-options-form-expert_mode");
 | 
			
		||||
  expertModeInteraction.setCallback('on',
 | 
			
		||||
                                  results.jsList.expertModeOn,
 | 
			
		||||
                                  results.jsList,
 | 
			
		||||
                                  ['query-display', client]);
 | 
			
		||||
  expertModeInteraction.setCallback('off',
 | 
			
		||||
                                    results.jsList.expertModeOff,
 | 
			
		||||
                                    results.jsList,
 | 
			
		||||
                                    ['query-display', client]);
 | 
			
		||||
  const subResultsInteraction = new InteractionElement("add-to-sub-results");
 | 
			
		||||
  subResultsInteraction.setCallback('on',
 | 
			
		||||
                                     results.jsList.activateAddToSubResults,
 | 
			
		||||
                                     results.jsList);
 | 
			
		||||
  subResultsInteraction.setCallback('off',
 | 
			
		||||
                                     results.jsList.deactivateAddToSubResults,
 | 
			
		||||
                                     results.jsList);
 | 
			
		||||
 | 
			
		||||
  const activateInspectInteraction = new InteractionElement('inspect',
 | 
			
		||||
                                                            false);
 | 
			
		||||
  activateInspectInteraction.setCallback('noCheck',
 | 
			
		||||
                                         results.jsList.activateInspect,
 | 
			
		||||
                                         results.jsList);
 | 
			
		||||
  const changeContextInteraction = new InteractionElement('display-options-form-results_per_page',
 | 
			
		||||
                                                          false);
 | 
			
		||||
  changeContextInteraction.setCallback('noCheck',
 | 
			
		||||
                                       results.jsList.changeContext,
 | 
			
		||||
                                       results.jsList)
 | 
			
		||||
  interactionElements.addInteractions([expertModeInteraction,
 | 
			
		||||
                                       subResultsInteraction,
 | 
			
		||||
                                       activateInspectInteraction,
 | 
			
		||||
                                       changeContextInteraction]);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
  * Checks if a change for every interactionElement happens and executes
 | 
			
		||||
  * the callbacks accordingly.
 | 
			
		||||
  */
 | 
			
		||||
  interactionElements.onChangeExecute();
 | 
			
		||||
  /**
 | 
			
		||||
   * Register listeners listening to socket.io events and their callbacks
 | 
			
		||||
   * Afterwards load them.
 | 
			
		||||
   */
 | 
			
		||||
  const listenForSession = new SocketEventListener('corpus_analysis_init',
 | 
			
		||||
                                                  recieveSession);
 | 
			
		||||
  const listenForQueryStatus = new SocketEventListener('corpus_analysis_query',
 | 
			
		||||
                                                     recieveQueryStatus);
 | 
			
		||||
                                                       recieveQueryStatus);
 | 
			
		||||
  const queryStatusCallback = new ListenerCallback('corpus_analysis_query',
 | 
			
		||||
                                                   querySetup);
 | 
			
		||||
  listenForQueryStatus.setCallbacks([queryStatusCallback]);
 | 
			
		||||
  const listenForQueryData = new SocketEventListener('corpus_analysis_query_results',
 | 
			
		||||
                                                  recieveQueryData);
 | 
			
		||||
  const queryDataCallback = new ListenerCallback('corpus_analysis_query_results',
 | 
			
		||||
                                                 queryRenderResults);
 | 
			
		||||
  listenForQueryData.setCallbacks([queryDataCallback]);
 | 
			
		||||
  client.setSocketEventListeners([listenForSession, listenForQueryStatus,
 | 
			
		||||
                                  listenForQueryData]);
 | 
			
		||||
  client.loadSocketEventListeners();
 | 
			
		||||
@@ -153,6 +228,9 @@ document.addEventListener("DOMContentLoaded", () => {
 | 
			
		||||
    // Get query string and send query to server
 | 
			
		||||
    results.data.getQueryStr(queryFormElement);
 | 
			
		||||
    client.requestQueryData(results.data.query);
 | 
			
		||||
 | 
			
		||||
    // Add scrollToTop functionality
 | 
			
		||||
    scrollToTop();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -10,8 +10,7 @@ results.-->
 | 
			
		||||
        Sub-Results creation:
 | 
			
		||||
        <label>
 | 
			
		||||
          Off
 | 
			
		||||
          <input disabled
 | 
			
		||||
                 type="checkbox"
 | 
			
		||||
          <input type="checkbox"
 | 
			
		||||
                 id="add-to-sub-results">
 | 
			
		||||
          <span class="lever"></span>
 | 
			
		||||
          On
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@ the selected sub results.-->
 | 
			
		||||
      <button class="waves-effect
 | 
			
		||||
              waves-light
 | 
			
		||||
              btn-flat
 | 
			
		||||
              disabled
 | 
			
		||||
              flat-interaction"
 | 
			
		||||
              type="submit"
 | 
			
		||||
              id="query-results-create">Create Results
 | 
			
		||||
@@ -30,7 +29,6 @@ the selected sub results.-->
 | 
			
		||||
              waves-light
 | 
			
		||||
              btn-flat
 | 
			
		||||
              hide
 | 
			
		||||
              disabled
 | 
			
		||||
              flat-interaction"
 | 
			
		||||
              type="submit"
 | 
			
		||||
              id="sub-results-create">Create Sub-Results
 | 
			
		||||
 
 | 
			
		||||
@@ -59,21 +59,39 @@
 | 
			
		||||
 * First Phase:
 | 
			
		||||
 * document content is loaded and scripts are being imported and executed
 | 
			
		||||
 */
 | 
			
		||||
import { CorpusAnalysisClient,
 | 
			
		||||
        CorpusAnalysisDisplay,
 | 
			
		||||
        SocketEventListener } from '../../static/js/modules/nopaque.CorpusAnalysisClient.js';
 | 
			
		||||
import { recieveSession, recieveQueryStatus,
 | 
			
		||||
        recieveQueryData } from '../../static/js/modules/nopaque.listenerFunctions.js';
 | 
			
		||||
import { Results, Data, MetaData } from '../../static/js/nopaque.Results.js';
 | 
			
		||||
import { ResultsList } from '../../static/js/nopaque.lists.js';
 | 
			
		||||
import { queryRenderResults, querySetup } from '../../static/js/modules/nopaque.listenerCallbacks.js'
 | 
			
		||||
 import {
 | 
			
		||||
   CorpusAnalysisClient,
 | 
			
		||||
   CorpusAnalysisDisplay,
 | 
			
		||||
   SocketEventListener,
 | 
			
		||||
   ListenerCallback,
 | 
			
		||||
 } from '../../static/js/modules/nopaque.CorpusAnalysisClient.js';
 | 
			
		||||
 import {
 | 
			
		||||
   recieveSession,
 | 
			
		||||
   recieveQueryStatus,
 | 
			
		||||
   recieveQueryData,
 | 
			
		||||
 } from '../../static/js/modules/nopaque.listenerFunctions.js';
 | 
			
		||||
 import {
 | 
			
		||||
   querySetup,
 | 
			
		||||
   queryRenderResults,
 | 
			
		||||
 } from '../../static/js/modules/nopaque.listenerCallbacks.js'
 | 
			
		||||
 import {
 | 
			
		||||
   Results,
 | 
			
		||||
   Data,
 | 
			
		||||
   MetaData,
 | 
			
		||||
 } from '../../static/js/nopaque.Results.js';
 | 
			
		||||
 import {
 | 
			
		||||
   ResultsList,
 | 
			
		||||
 } from '../../static/js/nopaque.lists.js';
 | 
			
		||||
 import {
 | 
			
		||||
   scrollToTop,
 | 
			
		||||
 } from '../../static/js/modules/nopaque.scrollToTop.js';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Second Phase:
 | 
			
		||||
 * Asynchronus and event driven code
 | 
			
		||||
 */
 | 
			
		||||
document.addEventListener("DOMContentLoaded", () => {
 | 
			
		||||
  // Initialize the CorpusAnalysisClient
 | 
			
		||||
  // Initialize the CorpusAnalysisClient with dynamicMode as false
 | 
			
		||||
  const client = new CorpusAnalysisClient({'logging': true,
 | 
			
		||||
                                           'dynamicMode': false});
 | 
			
		||||
  console.info("CorpusAnalysisClient created as client:", client);
 | 
			
		||||
@@ -85,8 +103,6 @@ document.addEventListener("DOMContentLoaded", () => {
 | 
			
		||||
  /**
 | 
			
		||||
   * Initializing the results object holding all the data of a query.
 | 
			
		||||
   * Also holds the metadata of one query.
 | 
			
		||||
   * resultsListOptions is set to determine how many results per page are
 | 
			
		||||
   * shown etc.
 | 
			
		||||
   * Lastly it contains the object ResultsList which is a list.js
 | 
			
		||||
   * subclass which handles the visual representation of the query data.
 | 
			
		||||
   */
 | 
			
		||||
@@ -114,7 +130,22 @@ document.addEventListener("DOMContentLoaded", () => {
 | 
			
		||||
                                 'onOpenEnd': deleteOverlay});
 | 
			
		||||
  // saving imported data into client object
 | 
			
		||||
  const payload = {{ query_result_file_content|tojson|safe }};
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Register listeners and their callbacks. Because we are using the client
 | 
			
		||||
   * not in dynamic mode we will not load the listeners. We just call the
 | 
			
		||||
   * callbacks of the listeners manually. This is done to keep the setup of
 | 
			
		||||
   * the client in dynamic or not dynamic mode similarish.
 | 
			
		||||
   */
 | 
			
		||||
   const listenForQueryStatus = new SocketEventListener('corpus_analysis_query',
 | 
			
		||||
                                                        recieveQueryStatus);
 | 
			
		||||
   const queryStatusCallback = new ListenerCallback('corpus_analysis_query',
 | 
			
		||||
                                                    querySetup);
 | 
			
		||||
   listenForQueryStatus.setCallbacks([queryStatusCallback]);
 | 
			
		||||
   const listenForQueryData = new SocketEventListener('corpus_analysis_query_results',
 | 
			
		||||
                                                   recieveQueryData);
 | 
			
		||||
   const queryDataCallback = new ListenerCallback('corpus_analysis_query_results',
 | 
			
		||||
                                                  queryRenderResults);
 | 
			
		||||
   listenForQueryData.setCallbacks([queryDataCallback]);
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//   // Initialization of interactionElemnts
 | 
			
		||||
@@ -160,9 +191,8 @@ document.addEventListener("DOMContentLoaded", () => {
 | 
			
		||||
//   }
 | 
			
		||||
//
 | 
			
		||||
  // render results directly with callbacks because we are not in dynamic mode
 | 
			
		||||
  querySetup(payload, client);
 | 
			
		||||
  queryRenderResults(payload, client);
 | 
			
		||||
 | 
			
		||||
  listenForQueryStatus.listenerCallbacks['corpus_analysis_query'].callbackFunction(payload, client);
 | 
			
		||||
  listenForQueryData.listenerCallbacks['corpus_analysis_query_results'].callbackFunction(payload, client);
 | 
			
		||||
//   // ### Show corpus Metadata
 | 
			
		||||
//   showMetaDataButton.onclick = () => {
 | 
			
		||||
//     metaDataModal.open();
 | 
			
		||||
@@ -185,19 +215,8 @@ document.addEventListener("DOMContentLoaded", () => {
 | 
			
		||||
//     }
 | 
			
		||||
//   });
 | 
			
		||||
//
 | 
			
		||||
//   // scroll to top button if user scrolled down the list
 | 
			
		||||
//   let headline = document.querySelector(".headline");
 | 
			
		||||
//   let scrollToTop = document.querySelector("#menu-scroll-to-top-div");
 | 
			
		||||
//   window.addEventListener("scroll", (event) => {
 | 
			
		||||
//     if (pageYOffset > 250) {
 | 
			
		||||
//       scrollToTop.classList.toggle("hide", false);
 | 
			
		||||
//     } else {
 | 
			
		||||
//       scrollToTop.classList.toggle("hide", true);
 | 
			
		||||
//     }
 | 
			
		||||
//   });
 | 
			
		||||
//   scrollToTop.onclick = () => {
 | 
			
		||||
//     headline.scrollIntoView({behavior: "smooth", block: "end", inline: "nearest"});
 | 
			
		||||
//   };
 | 
			
		||||
  // Add scrollToTop functionality
 | 
			
		||||
  scrollToTop();
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user