Source: search/Search.js

import { EventObject } from "../events/EventObject.js";

export { Search }

/**
 * Full-text search base class. Listen on events "prepare", "process", "finished" or "failed"
 * for processing UI preparations and search results. The finished() method is fired
 * even in case of errors.
 *
 * @author rkoppe <roland.koppe@awi.de>
 * @author rhess <robin.hess@awi.de>
 * 
 * @memberof vef.search
 */
class Search extends EventObject {

	// initialize properties
	baseUrl = "";
	searchRequest = null;
	searchResult = null;
	page = 0;
	pages = 0;

	/**
	 * Initializes the search aganist the given base URL.
	 * 
	 * @param {string} baseUrl 
	 */
	constructor(baseUrl) {

		if (!baseUrl) throw new Error("baseUrl is not set");
		if (!baseUrl.endsWith('/')) baseUrl += '/';

		// Initialize EventObject
		super({
			"prepare": [],   // pre-processes the given data. Example: create a table header,
			"process": [],   // Processes the given object record of the search result.
			"finished": [],  // Fired when the search request finished
			"failed": []     // Fired if there was an error during the search request.
		});

		// Initialize baseUrl
		this.baseUrl = baseUrl;
	}

	/**
	 * Processes the responseText from the ajax request and
	 * fires the necessary events for processing
	 * 
	 * @private
	 */
	processResult_(responseText) {
		try {
			// parse respons
			const data = JSON.parse(responseText);
			this.searchResult = data;

			// prepare pages
			this.page = Math.ceil(data.offset / this.searchRequest.hits) + 1;
			this.pages = Math.ceil(data.totalHits / this.searchRequest.hits);

			this.fire("prepare", data);

			// process
			const objects = data.records;
			for (let i = 0; i < objects.length; ++i) {
				this.fire("process", objects[i]);
			}

			this.fire("finished", data);
		} catch (e) {
			this.fire("failed", e);
		}
	}

	/**
	 * Performs the given searchRequest
	 * 
	 * @param {SearchRequest} request
	 * @returns {XMLHttpRequest}
	 */
	request(request) {
		// reset properties
		this.searchRequest = request;
		this.searchResult = null;
		this.page = 0;
		this.pages = 0;

		// create request
		const http = new XMLHttpRequest();
		http.open("POST", this.baseUrl, true);
		http.setRequestHeader("Content-Type", 'application/json');

		http.onreadystatechange = (e) => {
			if (http.readyState == 4) {
				if (http.status === 200) {
					this.processResult_(http.responseText);
				} else {
					this.fire("failed", e);
				}
			}
		}

		http.onerror = (e) => this.fire("failed", e);
		http.send(JSON.stringify(request));

		return http;
	}

	/**
	 * Returns the current page number.
	 * 
	 * @returns {number} page number
	 */
	getPage() {
		return this.page;
	}

	/**
	 * Returns the previous page number.
	 * 
	 * @returns {number} page number
	 */
	getPreviousPage() {
		return this.page == 1 ? 1 : this.page - 1;
	}

	/**
	 * Returns the next page number lower or equals pages.
	 * 
	 * @returns {number} page number
	 */
	getNextPage() {
		return this.page >= this.pages ? this.pages : this.page + 1;
	}

}