Move vanilla javascript event listeners into view listeners.

This commit is contained in:
Stephan Porada 2020-10-07 15:52:43 +02:00
parent 4241c13e13
commit 20074ebeae
5 changed files with 386 additions and 328 deletions

View File

@ -2,6 +2,7 @@
* This callback is called on a socket.on "corpus_analysis_send_meta_data".
* Handels incoming corpus metadata
*/
// TODO: rework arguments to ...args
function saveMetaData() {
let [payload, client, results, rest] = arguments;
client.notifyView('meta-data-recieving');

View File

@ -3,9 +3,10 @@
* specified
*/
class ViewEventListener {
constructor(type, listenerFunction) {
constructor(type, listenerFunction, args=[]) {
this.listenerFunction = listenerFunction;
this.type = type;
this.args = args;
}
}
@ -139,7 +140,11 @@ class ResultsList extends List {
*/
loadViewEventListeners() {
for (let [type, listener] of Object.entries(this.notificationListeners)) {
listener.listenerFunction(type, this);
if (listener.args.length > 0) {
listener.listenerFunction(...listener.args);
} else {
listener.listenerFunction(type, this);
}
}
}

View File

@ -1,273 +0,0 @@
/**
* This module contains vanilla javascript Event listeners which are listening
* for button clicks etc. the user is doing to interact with the page.
*/
// Import the script that implements a spinner animation for buttons.
import {
loadingSpinnerHTML,
} from './spinner.js';
/**
* The following listener handles what functions are called when the user
* does use the page navigation to navigate to a new page.
*/
function pageNavigation(resultsList, results, client) {
for (let element of resultsList.pagination) {
element.addEventListener("click", (event) => {
// Shows match context according to the user picked value on a new page.
resultsList.changeContext();
// De- or activates expertMode on new page depending on switch value.
if (resultsList.displayOptionsFormExpertMode.checked) {
resultsList.expertModeOn('query-display', results);
} else {
resultsList.expertModeOff('query-display');
}
// Activates inspect buttons on new page if client is not busy.
resultsList.toggleInspectButtons(client);
});
}
}
/**
* The following event Listener handles the expert mode switch for the list.
*/
function expertModeSwitch(resultsList, results) {
resultsList.displayOptionsFormExpertMode.onchange = (event) => {
if (event.target.checked) {
resultsList.expertModeOn('query-display', results);
} else {
resultsList.expertModeOff('query-display');
}
};
}
/**
* The following event Listener handles the add-btn and the inspect-btn
* onclick events via bubbleing.
*/
function actionButtons(resultsList, results, client) {
resultsList.queryResultsTable.addEventListener('click', (event) => {
let dataIndex;
if (event.target.classList.contains('inspect-btn')) {
dataIndex = parseInt(event.target.closest('tr').dataset.index);
resultsList.inspect(client, results, [dataIndex], 'inspect');
} else if (event.target.classList.contains('add-btn')) {
dataIndex = parseInt(event.target.closest('tr').dataset.index);
resultsList.addToSubResults(dataIndex, client);
}
})
}
/**
* Following event listeners handle the change of Context size per match and
* the number of matches shown per page.
*/
function displayOptions(resultsList, results, client) {
resultsList.displayOptionsFormResultsPerPage.onchange = (event) => {
resultsList.changeHitsPerPage(client, results);
};
resultsList.displayOptionsFormResultContext.onchange = (event) => {
resultsList.changeContext();
};
}
/**
* The following event listener handles the show metadata button and its
* functionality.
*/
function showMetaData(resultsList, results) {
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 listener handles the button showing infos about matches
* and their corresponding corpus files
*/
function showCorpusFiles(resultsList, results) {
resultsList.showCorpusFiles.onclick = () => {
resultsList.showCorpusFilesModalContent.innerHTML = '';
let htmlString = `
<div id="corpus-file-table">
<ul class="pagination paginationTop"></ul>
<table class="responsive-table highlight">
<thead>
<tr>
<th class="sort" data-sort="title">Title</th>
<th class="sort" data-sort="year">Year</th>
<th class="sort" data-sort="match-count">Match count in this text</th>
</tr>
</thead>
<tbody class="list">
`
for (let [key, value] of Object.entries(results.data.text_lookup)) {
htmlString += `
<tr>
<td class="title">${value.title}</td>
<td class="year">${value.publishing_year}</td>
<td class="match-count">${value.match_count}</td>
</tr>
`
}
htmlString += `
</tbody>
</table>
<ul class="pagination paginationBottom"></ul>
</div>
`
resultsList.showCorpusFilesModalContent.insertAdjacentHTML('afterbegin', htmlString);
resultsList.showCorpusFilesModal.open();
let options = {
page: 10,
pagination: [{
name: "paginationTop",
paginationClass: "paginationTop",
innerWindow: 8,
outerWindow: 1
}, {
paginationClass: "paginationBottom",
innerWindow: 8,
outerWindow: 1
}],
valueNames: ["title", "year", "match-count"],
};
let corpusFileTable = new List('corpus-file-table', options);
console.log(corpusFileTable);
}
}
/**
* Checks if resultsList.exportFullInspectContext switch is changed.
* If it has been changed reset all Download buttons.
*/
function exportFullContextSwitch(resultsList) {
resultsList.exportFullInspectContext.onchange = (event) => {
// Hide all download buttons.
resultsList.fullResultsExport.classList.toggle('hide', true);
resultsList.subResultsExport.classList.toggle('hide', true);
// Show result create buttons.
resultsList.fullResultsCreate.classList.toggle('hide', false);
resultsList.subResultsCreate.classList.toggle('hide', false);
}
}
/**
* The following event listeners are handeling the data export.
* 1. Create full-results
* 2. Create sub-results
* 3. Download full-results
* 4. Download sub-results
* 5. Download single inspect-results
*/
// 1. Add events for full-results create
function createFullResults(resultsList, results) {
resultsList.fullResultsCreate.onclick = (event) => {
resultsList.fullResultsCreate.querySelector('i').classList.toggle('hide');
resultsList.fullResultsCreate.innerText = 'Creating...';
resultsList.fullResultsCreate.insertAdjacentHTML('afterbegin',
loadingSpinnerHTML);
// .keys() is for a zero based array. I think...
let dataIndexes = [...Array(results.data.match_count).keys()];
// Empty fullResultsData so that no previous data is used.
results.fullResultsData.init();
resultsList.notifyClient('get-results', {resultsType: 'full-results',
dataIndexes: dataIndexes,
resultsList: resultsList,});
}
}
// 2. Add events for sub-results create
function createSubResults(resultsList, results) {
resultsList.subResultsCreate.onclick = (event) => {
let dataIndexes = [];
Object.keys(resultsList.subResultsIndexes).forEach((id) => {
dataIndexes.push(id);
});
resultsList.subResultsCreate.querySelector('i').classList.toggle('hide');
resultsList.subResultsCreate.innerText = 'Creating...';
resultsList.subResultsCreate.insertAdjacentHTML('afterbegin',
loadingSpinnerHTML);
// Empty subResultsData so that no previous data is used.
results.subResultsData.init();
resultsList.notifyClient('get-results', {resultsType: 'sub-results',
dataIndexes: dataIndexes,
resultsList: resultsList,});
}
}
// 3. Open download modal when full results export button is pressed
function exportFullResults(resultsList, results) {
resultsList.fullResultsExport.onclick = (event) => {
resultsList.queryResultsDownloadModal.open();
// add onclick to download JSON button and download the file
resultsList.downloadResultsJson.onclick = (event) => {
let suffix = 'full-results'
if (resultsList.exportFullInspectContext.checked) {
suffix += '_full-context';
}
let filename = results.fullResultsData.createDownloadFilename(suffix);
results.fullResultsData.addData(results.metaData);
results.fullResultsData.downloadJSONRessource(filename,
results.fullResultsData,
resultsList.downloadResultsJson)};
}
}
// 4. Open download modal when sub results export button is pressed
function exportSubResults(resultsList, results) {
resultsList.subResultsExport.onclick = (event) => {
resultsList.queryResultsDownloadModal.open();
// add onclick to download JSON button and download the file
resultsList.downloadResultsJson.onclick = (event) => {
let suffix = 'sub-results'
if (resultsList.exportFullInspectContext.checked) {
suffix += '_full-context';
}
let filename = results.subResultsData.createDownloadFilename(suffix);
results.subResultsData.addData(results.metaData);
results.subResultsData.downloadJSONRessource(filename,
results.subResultsData,
resultsList.downloadResultsJson)};
}
}
// 5. Open download modal when inspect-results-export button is pressed
function exportSingleMatch(resultsList, results) {
resultsList.inspectResultsExport.onclick = (event) => {
resultsList.queryResultsDownloadModal.open();
// add onclick to download JSON button and download the file
resultsList.downloadResultsJson.onclick = (event) => {
let filename = results.subResultsData.createDownloadFilename('inspect-results_full-context');
results.subResultsData.addData(results.metaData);
results.subResultsData.downloadJSONRessource(filename,
results.inspectResultsData,
resultsList.downloadResultsJson)};
}
}
export {
pageNavigation,
expertModeSwitch,
actionButtons,
displayOptions,
showMetaData,
showCorpusFiles,
exportFullContextSwitch,
createFullResults,
createSubResults,
exportFullResults,
exportSubResults,
exportSingleMatch,
}

View File

@ -1,10 +1,15 @@
/**
* 1.)
* This file contains the listener function that will be assigned to the
* corpus_analysis ResultsView. The listener is listening for the notification
* event which is being dispatched by the corpus_analysis Client. The
* notification Event triggers the listener which will call different
* callback functions depending on the detail information of the notification
* event.
* 2.)
* This file also contains vanilla javascript Event listeners which are
* listening for button clicks etc. the user is doing for page interaction.
* They will be registered the same way as teh listeners above.
*/
import {
@ -20,7 +25,16 @@ import {
disableElementsGeneralCallback,
enableElementsGeneralCallback,
} from './callbacks.js';
// Import the script that implements a spinner animation for buttons.
import {
loadingSpinnerHTML,
} from './spinner.js';
/**
* The Listener listening for the notification event 'notify-view' dispatched
* by the client and execeutes callbacks accordingly.
*/
function recieveClientNotification(eventType, resultsList) {
document.addEventListener(eventType, (event) => {
let caseIdentifier = event.detail.caseIdentifier;
@ -92,5 +106,274 @@ function recieveClientNotification(eventType, resultsList) {
});
}
/**
* This are some vanilla javascript Event listeners which are listening
* for button clicks etc. the user is doing to interact with the page.
* They will be registered the same way as the listeners above.
*/
/**
* The following listener handles what functions are called when the user
* does use the page navigation to navigate to a new page.
*/
function pageNavigation(resultsList, results, client) {
for (let element of resultsList.pagination) {
element.addEventListener("click", (event) => {
// Shows match context according to the user picked value on a new page.
resultsList.changeContext();
// De- or activates expertMode on new page depending on switch value.
if (resultsList.displayOptionsFormExpertMode.checked) {
resultsList.expertModeOn('query-display', results);
} else {
resultsList.expertModeOff('query-display');
}
// Activates inspect buttons on new page if client is not busy.
resultsList.toggleInspectButtons(client);
});
}
}
/**
* The following event Listener handles the expert mode switch for the list.
*/
function expertModeSwitch(resultsList, results) {
resultsList.displayOptionsFormExpertMode.onchange = (event) => {
if (event.target.checked) {
resultsList.expertModeOn('query-display', results);
} else {
resultsList.expertModeOff('query-display');
}
};
}
/**
* The following event Listener handles the add-btn and the inspect-btn
* onclick events via bubbleing.
*/
function actionButtons(resultsList, results, client) {
resultsList.queryResultsTable.addEventListener('click', (event) => {
let dataIndex;
if (event.target.classList.contains('inspect-btn')) {
dataIndex = parseInt(event.target.closest('tr').dataset.index);
resultsList.inspect(client, results, [dataIndex], 'inspect');
} else if (event.target.classList.contains('add-btn')) {
dataIndex = parseInt(event.target.closest('tr').dataset.index);
resultsList.addToSubResults(dataIndex, client);
}
})
}
/**
* Following event listeners handle the change of Context size per match and
* the number of matches shown per page.
*/
function displayOptions(resultsList, results, client) {
resultsList.displayOptionsFormResultsPerPage.onchange = (event) => {
resultsList.changeHitsPerPage(client, results);
};
resultsList.displayOptionsFormResultContext.onchange = (event) => {
resultsList.changeContext();
};
}
/**
* The following event listener handles the show metadata button and its
* functionality.
*/
function showMetaData(resultsList, results) {
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 listener handles the button showing infos about matches
* and their corresponding corpus files
*/
function showCorpusFiles(resultsList, results) {
resultsList.showCorpusFiles.onclick = () => {
resultsList.showCorpusFilesModalContent.innerHTML = '';
let htmlString = `
<div id="corpus-file-table">
<ul class="pagination paginationTop"></ul>
<table class="responsive-table highlight">
<thead>
<tr>
<th class="sort" data-sort="title">Title</th>
<th class="sort" data-sort="year">Year</th>
<th class="sort" data-sort="match-count">Match count in this text</th>
</tr>
</thead>
<tbody class="list">
`
for (let [key, value] of Object.entries(results.data.text_lookup)) {
htmlString += `
<tr>
<td class="title">${value.title}</td>
<td class="year">${value.publishing_year}</td>
<td class="match-count">${value.match_count}</td>
</tr>
`
}
htmlString += `
</tbody>
</table>
<ul class="pagination paginationBottom"></ul>
</div>
`
resultsList.showCorpusFilesModalContent.insertAdjacentHTML('afterbegin', htmlString);
resultsList.showCorpusFilesModal.open();
let options = {
page: 10,
pagination: [{
name: "paginationTop",
paginationClass: "paginationTop",
innerWindow: 8,
outerWindow: 1
}, {
paginationClass: "paginationBottom",
innerWindow: 8,
outerWindow: 1
}],
valueNames: ["title", "year", "match-count"],
};
let corpusFileTable = new List('corpus-file-table', options);
console.log(corpusFileTable);
}
}
/**
* Checks if resultsList.exportFullInspectContext switch is changed.
* If it has been changed reset all Download buttons.
*/
function exportFullContextSwitch(resultsList) {
resultsList.exportFullInspectContext.onchange = (event) => {
// Hide all download buttons.
resultsList.fullResultsExport.classList.toggle('hide', true);
resultsList.subResultsExport.classList.toggle('hide', true);
// Show result create buttons.
resultsList.fullResultsCreate.classList.toggle('hide', false);
resultsList.subResultsCreate.classList.toggle('hide', false);
}
}
/**
* The following event listeners are handeling the data export.
* 1. Create full-results
* 2. Create sub-results
* 3. Download full-results
* 4. Download sub-results
* 5. Download single inspect-results
*/
// 1. Add events for full-results create
function createFullResults(resultsList, results) {
resultsList.fullResultsCreate.onclick = (event) => {
resultsList.fullResultsCreate.querySelector('i').classList.toggle('hide');
resultsList.fullResultsCreate.innerText = 'Creating...';
resultsList.fullResultsCreate.insertAdjacentHTML('afterbegin',
loadingSpinnerHTML);
// .keys() is for a zero based array. I think...
let dataIndexes = [...Array(results.data.match_count).keys()];
// Empty fullResultsData so that no previous data is used.
results.fullResultsData.init();
resultsList.notifyClient('get-results', {resultsType: 'full-results',
dataIndexes: dataIndexes,
resultsList: resultsList,});
}
}
// 2. Add events for sub-results create
function createSubResults(resultsList, results) {
resultsList.subResultsCreate.onclick = (event) => {
let dataIndexes = [];
Object.keys(resultsList.subResultsIndexes).forEach((id) => {
dataIndexes.push(id);
});
resultsList.subResultsCreate.querySelector('i').classList.toggle('hide');
resultsList.subResultsCreate.innerText = 'Creating...';
resultsList.subResultsCreate.insertAdjacentHTML('afterbegin',
loadingSpinnerHTML);
// Empty subResultsData so that no previous data is used.
results.subResultsData.init();
resultsList.notifyClient('get-results', {resultsType: 'sub-results',
dataIndexes: dataIndexes,
resultsList: resultsList,});
}
}
// 3. Open download modal when full results export button is pressed
function exportFullResults(resultsList, results) {
resultsList.fullResultsExport.onclick = (event) => {
resultsList.queryResultsDownloadModal.open();
// add onclick to download JSON button and download the file
resultsList.downloadResultsJson.onclick = (event) => {
let suffix = 'full-results'
if (resultsList.exportFullInspectContext.checked) {
suffix += '_full-context';
}
let filename = results.fullResultsData.createDownloadFilename(suffix);
results.fullResultsData.addData(results.metaData);
results.fullResultsData.downloadJSONRessource(filename,
results.fullResultsData,
resultsList.downloadResultsJson)};
}
}
// 4. Open download modal when sub results export button is pressed
function exportSubResults(resultsList, results) {
resultsList.subResultsExport.onclick = (event) => {
resultsList.queryResultsDownloadModal.open();
// add onclick to download JSON button and download the file
resultsList.downloadResultsJson.onclick = (event) => {
let suffix = 'sub-results'
if (resultsList.exportFullInspectContext.checked) {
suffix += '_full-context';
}
let filename = results.subResultsData.createDownloadFilename(suffix);
results.subResultsData.addData(results.metaData);
results.subResultsData.downloadJSONRessource(filename,
results.subResultsData,
resultsList.downloadResultsJson)};
}
}
// 5. Open download modal when inspect-results-export button is pressed
function exportSingleMatch(resultsList, results) {
resultsList.inspectResultsExport.onclick = (event) => {
resultsList.queryResultsDownloadModal.open();
// add onclick to download JSON button and download the file
resultsList.downloadResultsJson.onclick = (event) => {
let filename = results.subResultsData.createDownloadFilename('inspect-results_full-context');
results.subResultsData.addData(results.metaData);
results.subResultsData.downloadJSONRessource(filename,
results.inspectResultsData,
resultsList.downloadResultsJson)};
}
}
// export listeners
export { recieveClientNotification };
export {
recieveClientNotification,
pageNavigation,
expertModeSwitch,
actionButtons,
displayOptions,
showMetaData,
showCorpusFiles,
exportFullContextSwitch,
createFullResults,
createSubResults,
exportFullResults,
exportSubResults,
exportSingleMatch,
};

View File

@ -115,14 +115,9 @@ import {
} from '../../static/js/modules/corpus_analysis/view/ResultsView.js';
// Import listener which will be registered to the ViewEventListener class.
import {
// listener listening for client dispatched 'notify-vie' custom event.
recieveClientNotification,
} from '../../static/js/modules/corpus_analysis/view/listeners.js';
// Import script that implements the scroll to top button.
import {
scrollToTop,
} from '../../static/js/modules/corpus_analysis/view/scrollToTop.js';
// vanilla javascript Event listeners which are listening for button clicks etc
import {
// vanilla javascript Event listeners which are listening for button clicks.
pageNavigation,
expertModeSwitch,
actionButtons,
@ -135,7 +130,13 @@ import {
exportFullResults,
exportSubResults,
exportSingleMatch,
} from '../../static/js/modules/corpus_analysis/view/eventListeners.js';
} from '../../static/js/modules/corpus_analysis/view/listeners.js';
// Import script that implements the scroll to top button.
import {
scrollToTop,
} from '../../static/js/modules/corpus_analysis/view/scrollToTop.js';
// vanilla javascript Event listeners which are listening for button clicks etc
/**
* Second Phase:
@ -208,35 +209,11 @@ document.addEventListener("DOMContentLoaded", () => {
*/
const listenForClientNotification = new ViewEventListener('notify-view',
recieveClientNotification);
resultsList.setViewEventListeners([listenForClientNotification]);
resultsList.loadViewEventListeners();
// 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) => {
try {
/**
* Selects first page of result list if pagination is already available
* from an query submitted before.
* This avoids confusion for the user e.g.: The user was on page 24
* reviewing the results and issues a new query. He would not see any
* results until the new results reach page 24 or he clicks on another
* valid result page element from the new pagination.
*/
let firstPageElement = document.querySelector('a.page');
firstPageElement.click();
} catch (e) {
// No page element is present if first query is submitted.
}
// Prevent page from reloading on submit.
event.preventDefault();
// Get query string and send query to server.
results.data.getQueryStr(queryFormElement);
client.query(results.data.query);
});
// Get all needed HTMLElements for the following event listeners.
/**
* Register vanilla Javascript events to the resultList listening for button
* clicks etc. done by the user.
* Get all needed HTMLElements for those event listeners before.
*/
resultsList.getHTMLElements([
'.pagination',
'#display-options-form-expert_mode',
@ -270,21 +247,86 @@ document.addEventListener("DOMContentLoaded", () => {
'#sub-results-export',
'#export-full-inspect-context',
]);
// Call the vanilla event listeners listening for clicks etc. from the user.
pageNavigation(resultsList, results, client);
expertModeSwitch(resultsList, results);
actionButtons(resultsList, results, client);
displayOptions(resultsList, results, client);
showMetaData(resultsList, results);
showCorpusFiles(resultsList, results);
// Still vanilla event listeners, but focused on result download and export
exportFullContextSwitch(resultsList);
createFullResults(resultsList, results);
createSubResults(resultsList, results);
exportFullResults(resultsList, results);
exportSubResults(resultsList, results);
exportSingleMatch(resultsList, results);
let args = [resultsList, results, client]
const listenForPageNavigation = new ViewEventListener('page-navigation',
pageNavigation,
args);
const listenForExpertModeSwitch = new ViewEventListener('expert-mode',
expertModeSwitch,
args);
const listenForActionButtons = new ViewEventListener('action-buttons',
actionButtons,
args);
const listenForDisplayOptions = new ViewEventListener('display-otions',
displayOptions,
args);
const listenForShowMetaData = new ViewEventListener('show-meta-data',
showMetaData,
args);
const listenForShowCorpusFiles = new ViewEventListener('show-corpus-files',
showCorpusFiles,
args);
const listenForExportFullContextSwitch = new ViewEventListener('export-full-context-switch',
exportFullContextSwitch,
args);
const listenForCreateFullResults = new ViewEventListener('create-full-results',
createFullResults,
args);
const listenForCreateSubResults = new ViewEventListener('create-sub-results',
createSubResults,
args);
const listenForExportFullResults = new ViewEventListener('export-full-results',
exportFullResults,
args);
const listenForExportSubResults = new ViewEventListener('export-sub-results',
exportSubResults,
args);
const listenForExportSingleMatch = new ViewEventListener('export-single-match',
exportSingleMatch,
args);
// Set and load define listeners
resultsList.setViewEventListeners([
listenForClientNotification,
listenForPageNavigation,
listenForExpertModeSwitch,
listenForActionButtons,
listenForDisplayOptions,
listenForShowMetaData,
listenForShowCorpusFiles,
listenForExportFullContextSwitch,
listenForCreateFullResults,
listenForCreateSubResults,
listenForExportFullResults,
listenForExportSubResults,
listenForExportSingleMatch,
]);
resultsList.loadViewEventListeners();
// 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) => {
try {
/**
* Selects first page of result list if pagination is already available
* from an query submitted before.
* This avoids confusion for the user e.g.: The user was on page 24
* reviewing the results and issues a new query. He would not see any
* results until the new results reach page 24 or he clicks on another
* valid result page element from the new pagination.
*/
let firstPageElement = document.querySelector('a.page');
firstPageElement.click();
} catch (e) {
// No page element is present if first query is submitted.
}
// Prevent page from reloading on submit.
event.preventDefault();
// Get query string and send query to server.
results.data.getQueryStr(queryFormElement);
client.query(results.data.query);
});
// Enable scroll to Top functionality.
scrollToTop('#headline', '#menu-scroll-to-top-div');
});