Add logic for data export etc.

This commit is contained in:
Stephan Porada 2020-08-26 16:55:24 +02:00
parent 763183435d
commit 64f8f82fe8
10 changed files with 286 additions and 211 deletions

View File

@ -16,7 +16,7 @@ class Client {
this.logging = logging;
this.requestQueryProgress = 0;
this.socket = socket;
this.socketEventListeners = {};
this.eventListeners = {};
this.connected = false;
@ -44,9 +44,9 @@ class Client {
}
// Registers one or more SocketEventListeners to the Client.
setSocketEventListeners(socketEventListeners) {
for (let socketEventListener of socketEventListeners) {
this.socketEventListeners[socketEventListener.type] = socketEventListener;
setSocketEventListeners(eventListeners) {
for (let eventListener of eventListeners) {
this.eventListeners[eventListener.type] = eventListener;
}
}
@ -55,7 +55,7 @@ class Client {
* type strings because they double as the socket event event names.
*/
loadSocketEventListeners() {
for (let [type, listener] of Object.entries(this.socketEventListeners)) {
for (let [type, listener] of Object.entries(this.eventListeners)) {
listener.listenerFunction(type, this);
}
}
@ -66,8 +66,8 @@ class Client {
*/
notifyView(caseIdentifier, detailObject={}) {
detailObject.caseIdentifier = caseIdentifier;
const event = new CustomEvent('notify', { detail: detailObject });
console.info('Dispatching Notification:', caseIdentifier);
const event = new CustomEvent('notify-view', { detail: detailObject });
console.info('Client dispatching Notification:', caseIdentifier);
document.dispatchEvent(event);
}
@ -105,16 +105,38 @@ class Client {
'socket.emit for the query', queryStr);
this.socket.emit('corpus_analysis_query', queryStr);
}
// create results data either from all results or from all marked sub results
getResultsData(resultsType, dataIndexes, results) {
// TODO: where to put all the stuff that deactivates all the buttons because cqp server cannot handle mutliple requests?
// Triggers emit to get full match context from server for a number of
// matches identified by their data_index.
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]);
}
nopaque.socket.emit("corpus_analysis_inspect_match",
{
type: resultsType,
data_indexes: dataIndexes,
first_cpos: tmp_first_cpos,
last_cpos: tmp_last_cpos,
});
}
}
/**
* 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, args=null) {
class ClientEventListener {
constructor(type, listenerFunction) {
this.listenerCallbacks = {};
this.listenerFunction = listenerFunction;
this.type = type;
@ -127,8 +149,8 @@ class SocketEventListener {
}
}
/** Shorthand to execute all registered callbacks with same args in insertion
* order.
/** Shorthand to execute all registered callbacks with same defaultArgs
* in insertion order.
* NOTE:
* Since ECMAScript 2015, objects do preserve creation order for
* string and Symbol keys. In JavaScript engines that comply with the
@ -136,11 +158,18 @@ class SocketEventListener {
* yield the keys in order of insertion.
* So all modern Browsers.
*/
executeCallbacks(payload) {
executeCallbacks(defaultArgs) {
for (let [type, listenerCallback] of Object.entries(this.listenerCallbacks)) {
listenerCallback.callbackFunction(payload, ...listenerCallback.args);
listenerCallback.callbackFunction(...defaultArgs,
...listenerCallback.args);
}
}
// use this if you only want to execute a specific registered callback
executeCallback(defaultArgs, type) {
let listenerCallback = this.listenerCallbacks[type];
listenerCallback.callbackFunction(...defaultArgs,
...listenerCallback.args);
}
}
/**
@ -159,6 +188,6 @@ class ListenerCallback {
// export Classes from this module
export {
Client,
SocketEventListener,
ClientEventListener,
ListenerCallback,
};

View File

@ -46,116 +46,24 @@ function saveQueryData(args) {
}
}
function querySetup(payload, client) {
// deletes old data from query issued before this new query
client.results.clearAll();
// 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',
'#query-results-create', '#add-to-sub-results']);
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%';
if (client.dynamicMode) {
client.addToSubResults.toggleAttribute('disabled');
client.queryResultsCreate.classList.toggle('disabled');
}
function getResultsData(args) {
let [resultsType, dataIndexes, client, results, rest] = arguments;
client.notifyView('results-data-recieving');
client.getResultsData(resultsType, dataIndexes, results);
}
/**
* 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',
'#display-options-form-expert_mode']);
const renderResults = (data) => {
/**
* resultItem saves the incoming chunk matches as objects to add those later
* to the client.results.jsList
*/
let resultItems = [];
// get infos for full match row
for (let [index, match] of data.matches.entries()) {
resultItems.push({...match, ...{'index': index + client.results.data.matches.length}});
}
client.results.jsList.add(resultItems, (items) => {
for (let item of items) {
item.elm = client.results.jsList.createResultRowElement(item, data);
}
});
}
if (client.dynamicMode) {
if (payload.chunk.cpos_ranges == true) {
client.results.data['cpos_ranges'] = true;
} else {
client.results.data['cpos_ranges'] = false;
}
renderResults(payload.chunk);
helperQueryRenderResults(payload, client);
console.info('Result progress is:', client.requestQueryProgress);
if (client.requestQueryProgress === 100) {
/**
* activate, hide or show elements if all reults have been recieved
* also load some new elements taht have not ben loaded before
*/
client.queryProgressBar.classList.toggle('hide');
client.queryResultsUserFeedback.classList.toggle('hide');
client.queryResultsCreate.classList.toggle('disabled');
client.addToSubResults.toggleAttribute('disabled');
// addToSubResultsElement.removeAttribute("disabled");
// // inital expert mode check and sub results activation
// client.results.jsList.activateInspect();
// if (addToSubResultsElement.checked) {
// client.results.jsList.activateAddToSubResults();
// }
// if (expertModeSwitchElement.checked) {
// client.results.jsList.expertModeOn("query-display");
// }
}
} else if (!client.dynamicMode) {
renderResults(payload);
helperQueryRenderResults({'chunk': payload}, client);
client.queryProgressBar.classList.toggle('hide');
client.queryResultsUserFeedback.classList.toggle('hide');
client.results.jsList.activateInspect();
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();
client.results.jsList.changeContext(); // sets lr context on first result load
// incorporating new chunk results into full results
client.results.data.matches.push(...payload.chunk.matches);
client.results.data.addData(payload.chunk.cpos_lookup, 'cpos_lookup');
client.results.data.addData(payload.chunk.text_lookup, 'text_lookup');
// complete metaData
// client.results.metaData.add();
// show user current and total match count
client.recievedMatchCount.textContent = `${client.results.data.matches.length}`;
client.textLookupCount.textContent = `${Object.keys(client.results.data.text_lookup).length}`;
let titles = new Array();
for (let [key, value] of Object.entries(client.results.data.text_lookup)) {
titles.push(`${value.title} (${value.publishing_year})`);
};
client.textLookupTitles.textContent = `${titles.join(", ")}`;
// update progress bar and requestQueryProgress
client.queryProgressBar.lastElementChild.style.width = `${payload.progress}%`;
client.requestQueryProgress = payload.progress;
function saveResultsData(args) {
let [payload, client, results, rest] = arguments;
// code to save results data depending on type
console.info('Results data has been saved.');
client.notifyView('results-data-recieved');
}
// export callbacks
export { prepareQueryData, saveMetaData, saveQueryData };
export {
prepareQueryData,
saveMetaData,
saveQueryData,
getResultsData,
saveResultsData,
};

View File

@ -1,9 +1,14 @@
/**
* This file contains the listener functions which can be assigned to the
* coprus_analysis client. So that the incoming data/status informations will
* be handled.
* be handled. There are several listeners listening for socket .io events.
* Further below one javascript custom event listener is specified. This
* listener listens for javascript custom events which are being dispatched by
* the View (resultsList).
*/
// Listeners for socket io events
/**
* Recieves a corpus analysis connected signal via socket.io.
*/
@ -50,7 +55,7 @@ function recieveMetaData(type, client) {
console.info(`corpus_analysis_meta_data: ${response.code} - ${response.msg}`);
console.info(response);
// executing the registered callbacks
client.socketEventListeners[type].executeCallbacks(response.payload);
client.eventListeners[type].executeCallbacks([response.payload]);
console.groupEnd();
} else {
console.group('Failed to recieve meta data.');
@ -81,7 +86,7 @@ function recieveQueryStatus(type, client) {
console.info(`corpus_analysis_query: ${response.code} - ${response.msg}`);
console.info(response);
// executing the registered callbacks
client.socketEventListeners[type].executeCallbacks(response.payload);
client.eventListeners[type].executeCallbacks([response.payload]);
console.groupEnd();
} else {
console.group('corpus_analysis_query: Client failed recieving',
@ -113,7 +118,7 @@ function recieveQueryData(type, client) {
/**
* Execute registered callbacks and notify View.
*/
client.socketEventListeners[type].executeCallbacks(response.payload);
client.eventListeners[type].executeCallbacks([response.payload]);
console.info('Added chunk data to results.data.');
console.groupEnd();
} else {
@ -125,18 +130,72 @@ function recieveQueryData(type, client) {
}
});
} else {
console.group('corpus_analysis_query_results: Loading query data.')
console.group('corpus_analysis_query_results: Loading query data.');
console.info('Client loading imported query data from database.');
// executing the registered callbacks
client.socketEventListeners[type].executeCallbacks();
client.eventListeners[type].executeCallbacks();
console.groupEnd();
}
}
/**
* Recieves the data requested by the create Results or sub results button
*/
function recieveResultsData(type, client) {
client.socket.on(type, (response) => {
/**
* Check if request for session was OK.
* If OK execute registered callbacks and notify View.
*/
if (response.code === 200) {
console.group('Client recieving results data')
console.info('corpus_analysis_inspect_match: Client recieving results data',
'via socket.on');
console.info(`corpus_analysis_inspect_match: ${response.code} - ${response.msg}`);
console.info(response);
// executing the registered callbacks
client.eventListeners[type].executeCallbacks([response.payload]);
console.groupEnd();
} else {
console.group('Failed to recieve results data.');
console.error('corpus_analysis_inspect_match: Client failed to recieve',
'results data via socket.on');
let errorText = `Error ${response.payload.code} - ${response.payload.msg}`;
console.error(`corpus_analysis_inspect_match: ${errorText}`);
console.groupEnd();
}
});
}
/*
* This is the javascript custom event listener, listening for events
* dispatched by the View.
*/
function recieveViewNotification(type, client) {
document.addEventListener(type, (event) => {
let caseIdentifier = event.detail.caseIdentifier;
switch(caseIdentifier) {
case 'get-results':
console.info('Client getting full results for export.');
// execute callback or functions
client.eventListeners[type].executeCallback([event.detail.resultsType,
event.detail.dataIndexes],
caseIdentifier);
break
default:
console.error('Recieved unkown notification case identifier from View');
// do something to not crash the analysis session?
// maybe unnecessary
}
});
}
// export listeners from this module
export {
recieveConnected,
recieveMetaData,
recieveQueryStatus,
recieveQueryData
recieveQueryData,
recieveViewNotification,
recieveResultsData,
};

View File

@ -8,6 +8,7 @@ class Results {
constructor() {
this.data = new Data();
this.metaData = new MetaData();
this.fullResultsData = new Data();
this.subResultsData = new Data();
console.info('Initialized the Results object.');
}
@ -15,12 +16,12 @@ class Results {
init() {
this.data.init();
this.metaData.init();
this.fullResultsData = new Data();
this.subResultsData.init();
}
}
class Data {
// Sets empty object structure. Also usefull to delete old results.
// matchCount default is 0
@ -94,29 +95,6 @@ class Data {
this.download(downloadElement, dataStr, resultFilename, "text/json", ".json")
}
// create results data either from all results or from al lmarked sub results
createResultsData(type) {
// deactivate inspect, because cqp server cannot handle multiple requests
results.jsList.deactivateInspect();
activateInspectInteraction.setCallback("noCheck",
results.jsList.deactivateInspect,
results.jsList);
// set flag that results are being created to avoid reactivation of
// sub results creation if marked matches are changed
resultCreationRunning = true;
console.log(resultCreationRunning);
if (type === "sub-results") {
resultsCreateElement.classList.add("disabled"); // cqp server cannot handle more than one request at a time. Thus we deactivate the resultsCreateElement
let tmp = [...results.jsList.addToSubResultsIdsToShow].sort(function(a, b){return a-b});
let dataIndexes = [];
tmp.forEach((index) => dataIndexes.push(index - 1));
results.jsList.getMatchWithContext(dataIndexes, "sub-results");
} else if (type === "results") {
subResultsCreateElement.classList.add("disabled"); // cqp server cannot handle more than one request at a time. Thus we deactivate the subResultsCreateElement
let dataIndexes = [...Array(results.data.match_count).keys()];
results.jsList.getMatchWithContext(dataIndexes, "results");
}
}
}
class MetaData {

View File

@ -2,7 +2,7 @@
* This class implements a NotificationListener that is listening for the
* specified
*/
class NotificationListener {
class ViewEventListener {
constructor(type, listenerFunction) {
this.listenerFunction = listenerFunction;
this.type = type;
@ -61,7 +61,7 @@ class ResultsList extends List {
* class field in the ResultsList object with the query selector
* 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
* The value will be the identifed element or elements fetched with the querySelector
* method.
*/
// TODO: multipleResults=false, atattchSomeCallback=false ?
@ -73,6 +73,7 @@ class ResultsList extends List {
element = document.querySelector(selector);
} else {
elements = document.querySelectorAll(selector);
elements = [...elements];
}
let cleanKey = [];
selector = selector.replace(/_/g, '-');
@ -106,6 +107,17 @@ class ResultsList extends List {
}
}
/**
* This functions sends events to the Client to trigger specific functions to
* trigger new data requests from the server.
*/
notifyClient(caseIdentifier, detailObject={}) {
detailObject.caseIdentifier = caseIdentifier;
const event = new CustomEvent('notify-client', { detail: detailObject });
console.info('Client dispatching Notification:', caseIdentifier);
document.dispatchEvent(event);
}
/**
* Creates cpos either from ranges or not.
*/
@ -255,25 +267,6 @@ class ResultsList extends List {
}
}
// Triggers emit to get full match context from server for a number of
// matches identified by their data_index.
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]);
}
nopaque.socket.emit("corpus_analysis_inspect_match",
{
type: type,
data_indexes: dataIndexes,
first_cpos: tmp_first_cpos,
last_cpos: tmp_last_cpos,
}
);
}
// ###### Functions to inspect one match, to show more details ######
// activate inspect buttons if progress is 100
activateInspect() {
@ -786,7 +779,7 @@ class ResultsList extends List {
return matchRowElement
}
// creates the HTML table code for the metadata vie in the corpus analysis interface
// creates the HTML table code for the metadata view in the corpus analysis interface
createMetaDataForModal(metaDataObject) {
let html = `<div class="col s12">
<table class="highlight">
@ -838,12 +831,12 @@ class ResultsList extends List {
}
// Creates the text details for the texts shown in the corpus analysis metadata modal.
createTextDetails(metaDataObject) {
createTextDetails(metaData) {
let metadataKey = event.target.dataset.metadataKey;
let textKey = event.target.dataset.textKey;
let textData = metaDataObject[metadataKey][textKey];
let bibliographicData = document.getElementById(`bibliographic-data-${metadataKey}-${textKey}`);
bibliographicData.innerHTML = "";
let textData = metaData[metadataKey][textKey];
let bibliographicData = document.querySelector(`#bibliographic-data-${metadataKey}-${textKey}`);
bibliographicData.textContent = '';
for (let [key, value] of Object.entries(textData)) {
bibliographicData.insertAdjacentHTML("afterbegin",
`
@ -854,4 +847,4 @@ class ResultsList extends List {
};
// export classses
export { NotificationListener, ResultsList };
export { ViewEventListener, ResultsList };

View File

@ -98,8 +98,14 @@ function queryDataRecievedCallback(resultsList, detail) {
// show or enable some things for the user
resultsList.queryResultsCreate.classList.toggle('disabled');
resultsList.addToSubResults.removeAttribute("disabled");
}
function resultsDataRecievingCallback(resultsList, detail) {
// hide or disable elments taht would trigger another cqp data request
}
function resultsDataRecievedCallback(resultsList, detail) {
// hide or show the right stuff
}
// export the callbacks
@ -110,4 +116,6 @@ export {
queryDataPreparingCallback,
queryDataRecievingCallback,
queryDataRecievedCallback,
resultsDataRecievingCallback,
resultsDataRecievedCallback,
};

View File

@ -14,43 +14,55 @@ import {
queryDataPreparingCallback,
queryDataRecievingCallback,
queryDataRecievedCallback,
resultsDataRecievingCallback,
resultsDataRecievedCallback,
} from './callbacks.js';
function recieveNotification(eventType, resultsList) {
function recieveClientNotification(eventType, resultsList) {
document.addEventListener(eventType, (event) => {
let caseIdentifier = event.detail.caseIdentifier;
switch (caseIdentifier) {
case 'connecting':
console.info('Recieved notification:', caseIdentifier);
console.info('View recieved notification:', caseIdentifier);
connectingCallback(resultsList, event.detail);
// execute callback
break;
case 'connected':
console.info('Recieved notification:', caseIdentifier);
console.info('View recieved notification:', caseIdentifier);
connectedCallback(resultsList, event.detail);
break;
case 'connecting-failed':
console.info('Recieved notification:', caseIdentifier);
console.info('View recieved notification:', caseIdentifier);
// execute callback
connectingFaildeCallback(resultsList, event.detail);
break;
case 'query-data-prepareing':
console.info('Recieved notification:', caseIdentifier);
console.info('View recieved notification:', caseIdentifier);
// execute callback
queryDataPreparingCallback(resultsList, event.detail);
break;
case 'query-data-recieving':
console.info('Recieved notification:', caseIdentifier);
console.info('View recieved notification:', caseIdentifier);
// execute callback
queryDataRecievingCallback(resultsList, event.detail);
break;
case 'query-data-recieved':
console.info('Recieved notification:', caseIdentifier);
console.info('View recieved notification:', caseIdentifier);
// execute callback
queryDataRecievedCallback(resultsList, event.detail);
break;
case 'results-data-recieving':
console.info('View recieved notification:', caseIdentifier);
// execute callback
resultsDataRecievedCallback(resultsList, event.detail);
break;
case 'results-data-recieved':
console.info('View recieved notification:', caseIdentifier);
// execute callback
resultsDataRecievedCallback(resultsList, event.detail);
break;
default:
console.error('Recieved unkown notification case identifier');
console.error('Recieved unkown notification case identifier from Client');
// do something to not crash the analysis session?
// maybe unnecessary
}
@ -58,4 +70,4 @@ function recieveNotification(eventType, resultsList) {
}
// export listeners
export { recieveNotification };
export { recieveClientNotification };

View File

@ -0,0 +1,17 @@
// loading spinner animation HTML
const loadingSpinnerHTML = `
<div class="preloader-wrapper button-icon-spinner small active">
<div class="spinner-layer spinner-green-only">
<div class="circle-clipper left">
<div class="circle"></div>
</div><div class="gap-patch">
<div class="circle"></div>
</div><div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
</div>
`;
//export
export { loadingSpinnerHTML };

View File

@ -70,35 +70,45 @@
* First Phase:
* Document content is loaded and scripts are being imported and executed.
*/
// import Client classes
import {
Client,
SocketEventListener,
ClientEventListener,
ListenerCallback,
} from '../../static/js/modules/corpus_analysis/client/Client.js';
// import client listener functions
import {
recieveConnected,
recieveMetaData,
recieveQueryStatus,
recieveQueryData,
recieveViewNotification,
recieveResultsData,
} from '../../static/js/modules/corpus_analysis/client/listeners.js';
import {
Results,
} from '../../static/js/modules/corpus_analysis/model/Results.js';
// import client listener callbacks
import {
prepareQueryData,
saveQueryData,
saveMetaData,
getResultsData,
saveResultsData,
} from '../../static/js/modules/corpus_analysis/client/callbacks.js';
import {
NotificationListener,
Results,
} from '../../static/js/modules/corpus_analysis/model/Results.js';
import {
ViewEventListener,
ResultsList,
} from '../../static/js/modules/corpus_analysis/view/ResultsView.js';
import {
recieveNotification,
recieveClientNotification,
} from '../../static/js/modules/corpus_analysis/view/listeners.js';
import {
scrollToTop,
} from '../../static/js/modules/corpus_analysis/view/scrollToTop.js'
import {
loadingSpinnerHTML,
} from '../../static/js/modules/corpus_analysis/view/spinner.js'
/**
* Second Phase:
@ -120,44 +130,59 @@ document.addEventListener("DOMContentLoaded", () => {
let resultsList = new ResultsList('result-list', ResultsList.options);
/**
* Register listeners listening to socket.io events and their callbacks
* Afterwards load them.
* Afterwards load them. Also registers listeners listening for custom
* javascript events.
*/
const listenForConnected = new SocketEventListener('corpus_analysis_init',
const listenForConnected = new ClientEventListener('corpus_analysis_init',
recieveConnected);
const listenForMetaData = new SocketEventListener('corpus_analysis_meta_data',
const listenForMetaData = new ClientEventListener('corpus_analysis_meta_data',
recieveMetaData);
const metaDataCallback = new ListenerCallback('corpus_analysis_meta_data',
saveMetaData,
[client, results]);
listenForMetaData.setCallbacks([metaDataCallback]);
const listenForQueryStatus = new SocketEventListener('corpus_analysis_query',
const listenForQueryStatus = new ClientEventListener('corpus_analysis_query',
recieveQueryStatus);
const queryStatusCallback = new ListenerCallback('corpus_analysis_query',
prepareQueryData,
[client, results]);
listenForQueryStatus.setCallbacks([queryStatusCallback]);
const listenForQueryData = new SocketEventListener('corpus_analysis_query_results',
const listenForQueryData = new ClientEventListener('corpus_analysis_query_results',
recieveQueryData);
const queryDataCallback = new ListenerCallback('corpus_analysis_query_results',
saveQueryData,
[client, results]);
listenForQueryData.setCallbacks([queryDataCallback]);
const listenForResults = new ClientEventListener('corpus_analysis_inspect_match',
recieveResultsData);
const resultsDataCallback = new ListenerCallback('corpus_analysis_inspect_match',
saveResultsData,
[client, results]);
listenForResults.setCallbacks([resultsDataCallback]);
// listen for javascript custom notifications
const listenForViewNotification = new ClientEventListener('notify-client',
recieveViewNotification);
const getResultsCallback = new ListenerCallback('get-results',
getResultsData,
[client, results]);
listenForViewNotification.setCallbacks([getResultsCallback]);
client.setSocketEventListeners([listenForConnected,
listenForQueryStatus,
listenForQueryData,
listenForMetaData]);
listenForMetaData,
listenForViewNotification,
listenForResults]);
client.loadSocketEventListeners();
/**
* Register resultsList listeners listening to nitification events.
*/
const listenForNotification = new NotificationListener('notify',
recieveNotification);
resultsList.setNotificationListeners([listenForNotification]);
const listenForClientNotification = new ViewEventListener('notify-view',
recieveClientNotification);
resultsList.setNotificationListeners([listenForClientNotification]);
resultsList.loadNotificationListeners();
// Connect client to server
client.notifyView('connecting');
client.connect();
// Send a query and recieve its answer data
let queryFormElement = document.querySelector('#query-form');
queryFormElement.addEventListener('submit', (event) => {
@ -181,20 +206,66 @@ document.addEventListener("DOMContentLoaded", () => {
results.data.getQueryStr(queryFormElement);
client.query(results.data.query);
});
/**
* Display events
* 1. live update of hits per page if hits per page value is changed
*/
// Get all needed HTMLElements for the following event listeners
resultsList.getHTMLElements([
'#display-options-form-results_per_page',
'#display-options-form-result_context'
'#display-options-form-result_context',
'#show-meta-data',
'#meta-data-modal',
'#meta-data-modal-content',
'#query-results-create'
]);
/**
* Display events: Following event listeners are handleing the
* live update of hits per page if hits per page value is changed and the
* context size of every match.
*/
resultsList.displayOptionsFormResultsPerPage.onchange = () => {
resultsList.changeHitsPerPage();
};
resultsList.displayOptionsFormResultContext.onchange = () => {
resultsList.changeContext();
};
/**
* The following event listener handel the Show metadata button and its
* functionality. Before the needed modal is initialized.
*/
let deleteOverlay = () => {
let overlay = document.querySelector(".modal-overlay");
overlay.remove();
};
resultsList.metaDataModal= M.Modal.init(resultsList.metaDataModal, {
'preventScrolling': false,
'opacity': 0.0,
'dismissible': false,
'onOpenEnd': deleteOverlay
});
resultsList.showMetaData.onclick = () => {
resultsList.metaDataModalContent.textContent = '';
let table = resultsList.createMetaDataForModal(results.metaData);
resultsList.metaDataModalContent.insertAdjacentHTML('afterbegin', table);
resultsList.metaDataModal.open();
let collapsibles = resultsList.metaDataModalContent.querySelectorAll(".text-metadata");
for (let collapsible of collapsibles) {
collapsible.onclick = () => {
let elems = resultsList.metaDataModalContent.querySelectorAll('.collapsible');
let instances = M.Collapsible.init(elems, {accordion: false});
resultsList.createTextDetails(results.metaData);
}
}
};
/**
* The following event listeners are handeling the data export.
*/
resultsList.queryResultsCreate.onclick = () => {
resultsList.queryResultsCreate.querySelector('i').classList.toggle('hide');
resultsList.queryResultsCreate.innerText = 'Creating...';
resultsList.queryResultsCreate.insertAdjacentHTML('afterbegin',
loadingSpinnerHTML);
resultsList.notifyClient('get-results', { resultsType: 'full-results',
dataIndexes: [...Array(results.data.match_count).keys()]});
}

View File

@ -7,7 +7,7 @@ result.-->
<div class="divider" style="margin-bottom: 10px;"></div>
<div class="row">
<div class="col s12">
<button id="show-metadata"
<button id="show-meta-data"
class="waves-effect
waves-light
btn-flat