blob: a718d8ad8b09ec79e34759cca323c10505b3663a [file] [log] [blame]
Akrone51eaa32020-11-10 09:35:53 +01001"use strict";
2
Nils Diewald0e6992a2015-04-14 20:13:52 +00003define(['util'], function () {
Akronbf713fc2020-10-13 10:44:35 +02004
5 // TODO:
6 // - https://github.com/honza/140medley/blob/master/140medley.js
7 // - https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
8 // - https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
9 // - r.addEventListener("progress", updateProgress, false);
10 // - http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml
11 // - http://stackoverflow.com/questions/6112744/load-javascript-on-demand
Nils Diewald58141332015-04-07 16:18:45 +000012
Leo Reppa6aba9a2021-01-23 20:16:43 +010013 // See https://flaviocopes.com/http-request-headers/ for a list of headers
14
Akron4c33c622018-11-12 13:43:27 +010015 KorAP.URL = KorAP.URL !== undefined ? KorAP.URL : '';
Nils Diewald4347ee92015-05-04 20:32:48 +000016 KorAP.API = KorAP.API || {};
Akronb89863a2018-11-13 16:43:59 +010017
Akronbf713fc2020-10-13 10:44:35 +020018 const legacySigle = new RegExp('^([^_]+)_([^\\.]+)\\.(.+?)$');
19
Akron48b1e4d2015-06-17 18:47:01 +020020 /**
21 * Retrieve information about a match
22 */
Nils Diewald4347ee92015-05-04 20:32:48 +000023 KorAP.API.getMatchInfo = function (match, param, cb) {
Nils Diewald58141332015-04-07 16:18:45 +000024
Nils Diewald4347ee92015-05-04 20:32:48 +000025 // match is a KorAP.Match object
Akronbf713fc2020-10-13 10:44:35 +020026 let url = KorAP.URL + '/corpus';
Akron33526592026-09-02 13:27:46 +020027 const matchInfoExtended = document.body
28 ? document.body.getAttribute('data-match-info-extended')
29 : null;
Akron0b489ad2018-02-02 16:49:32 +010030 /*
31 url += '/' + match.corpusID;
32 url += '/' + match.docID;
33 url += '/' + match.textID;
34 */
Akron19d97fe2016-09-06 20:47:05 +020035
Akron19d97fe2016-09-06 20:47:05 +020036 // This is for legacy support
Akronbf713fc2020-10-13 10:44:35 +020037 const legacy = legacySigle.exec(match.textSigle);
38 let docFragment = "";
Akron7f613e02016-11-07 02:50:44 +010039 if (legacy !== null && legacy[0]) {
Akronb89863a2018-11-13 16:43:59 +010040 docFragment = legacy[1] + '/' + legacy[2] + '/' + legacy[3];
Akron19d97fe2016-09-06 20:47:05 +020041 }
42 else {
Akronb89863a2018-11-13 16:43:59 +010043 docFragment = match.textSigle;
Akron19d97fe2016-09-06 20:47:05 +020044 }
Akronb89863a2018-11-13 16:43:59 +010045
46 docFragment += '/' + match.matchID;
Akron910828a2025-06-27 15:38:48 +020047 url += '/' + docFragment + '?';
Nils Diewald58141332015-04-07 16:18:45 +000048
Nils Diewald4347ee92015-05-04 20:32:48 +000049 // { spans: true, layer:x, foundry : y}
50 if (param['spans'] == true) {
Akron910828a2025-06-27 15:38:48 +020051 url += 'spans=true';
Akronb89863a2018-11-13 16:43:59 +010052 docFragment += ' +spans ';
53 if (param['foundry'] !== undefined) {
Akron515851a2017-05-02 12:53:17 +020054 url += '&foundry=' + param['foundry'];
Akronb89863a2018-11-13 16:43:59 +010055 docFragment += param['foundry'];
56 };
57 if (param['layer'] !== undefined) {
Akron515851a2017-05-02 12:53:17 +020058 url += '&layer=' + param['layer'];
Akronb89863a2018-11-13 16:43:59 +010059 docFragment += '/'+param['layer'];
60 }
Nils Diewald58141332015-04-07 16:18:45 +000061 }
Akron33526592026-09-02 13:27:46 +020062
Nils Diewald4347ee92015-05-04 20:32:48 +000063 // { spans : false, layer: [Array of KorAP.InfoLayer] }
64 else {
65 // TODO
Akronb89863a2018-11-13 16:43:59 +010066 docFragment += ' -spans';
Akron910828a2025-06-27 15:38:48 +020067 url += 'spans=false';
68 };
69
Akron33526592026-09-02 13:27:46 +020070 if (matchInfoExtended) {
71 url += '&extended=' + encodeURIComponent(matchInfoExtended);
72 docFragment += ' +extended=' + matchInfoExtended;
73 }
74
Akron910828a2025-06-27 15:38:48 +020075 if (KorAP.ResponsePipe != null)
76 url += '&response-pipe=' + KorAP.ResponsePipe.toString();
Nils Diewald4347ee92015-05-04 20:32:48 +000077
Akronb89863a2018-11-13 16:43:59 +010078 KorAP.API.getJSON(url, cb, "MatchInfo: " + docFragment);
Nils Diewald58141332015-04-07 16:18:45 +000079 };
Nils Diewald4347ee92015-05-04 20:32:48 +000080
Akron0b489ad2018-02-02 16:49:32 +010081
Akron48b1e4d2015-06-17 18:47:01 +020082 /**
Akron0ad7cd22018-02-08 18:03:06 +010083 * Retrieve information about a document.
84 */
85 KorAP.API.getTextInfo = function (doc, param, cb) {
86
87 // doc is a KorAP.Match object
Akronbf713fc2020-10-13 10:44:35 +020088 let url = KorAP.URL + '/corpus' + '/' + doc.textSigle;
Akron0ad7cd22018-02-08 18:03:06 +010089
90 if (param['fields'] !== undefined) {
91 url += '?fields='; // TODO!
92 }
93 else {
Akron4bbd8b32018-03-06 19:19:44 +010094 url += '?fields=@all'; // TODO: Maybe '*'?
Akron910828a2025-06-27 15:38:48 +020095 };
Akronbf713fc2020-10-13 10:44:35 +020096
Akron910828a2025-06-27 15:38:48 +020097 if (KorAP.ResponsePipe != null)
98 url += '&response-pipe=' + KorAP.ResponsePipe.toString();
99
100
Akronb89863a2018-11-13 16:43:59 +0100101 KorAP.API.getJSON(url, cb, "TextInfo: " + doc.textSigle);
Akron0ad7cd22018-02-08 18:03:06 +0100102 };
103
104
105 /**
Akroncd42a142019-07-12 18:55:37 +0200106 * Retrieve information about virtual corpora
Akron48b1e4d2015-06-17 18:47:01 +0200107 */
108 KorAP.API.getCollections = function (cb) {
Akronb89863a2018-11-13 16:43:59 +0100109 KorAP.API.getJSON(KorAP.URL + '/collection', cb, "CorpusInfo");
Akron48b1e4d2015-06-17 18:47:01 +0200110 };
111
hebasta0ee50802018-06-20 10:24:45 +0200112
113 /**
114 * Retrieve information about corpus statistic
115 *
116 * Example URL: /corpus?cq=availability+%3D+%2FCC-BY.*%2F+%26+textClass+%3D+%22kultur%22
117 *
Leo Reppa6aba9a2021-01-23 20:16:43 +0100118 * @param cq corpus query (formerly collectionQuery)
hebasta0ee50802018-06-20 10:24:45 +0200119 *
120 * Adress the MOJO-Endpoint for example with
121 * http://localhost:3000/corpus?cq=availability+%3D+%2FCC-BY.*%2F+%26+textClass+%3D+%22kultur%22
122 */
123 KorAP.API.getCorpStat = function (cq, cb){
Akronbf713fc2020-10-13 10:44:35 +0200124 let url = KorAP.URL + "/corpus?cq=" + encodeURIComponent(cq);
Akronb89863a2018-11-13 16:43:59 +0100125 KorAP.API.getJSON(url, cb, "CorpusInfo: " + cq);
hebasta0ee50802018-06-20 10:24:45 +0200126 };
Akron8dda1c62021-01-20 10:27:32 +0100127
128
129 /**
130 * Retrieve a list of all plugin objects to
131 * establish in the frontend.
132 */
133 KorAP.API.getPluginList = function (url, cb) {
134 KorAP.API.getJSON(url, cb, "Plugin-List")
135 };
Akronbf713fc2020-10-13 10:44:35 +0200136
hebasta4ba496a2018-06-05 15:56:01 +0200137 /**
Leo Reppa6aba9a2021-01-23 20:16:43 +0100138 * General function to communicate JS Objects with the server
139 *
140 * @param {HTTMLRequestType} requestType Should be "GET", "PUT", "POST" or "DELETE"
141 * @param {String} url The url that specifies where the JSON file is ("GET"), will be ("PUT" and "POST") or will have been ("DELETE")
142 * @param {String} title How to store this request in the logs
143 * @param {JSObj} jsObj For "PUT" and "POST". The JS Object that is getting transfered. This function stringifies it.
144 * @param {function} returnValueCB For "GET". The callback function that receives the retrieved JS object (already parsed) as a parameter, or undefined if none is eligible
145 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
146 */
147 function _actionJSON (requestType, url, title, jsObj, returnValueCB, errorCB) {
Akronbf713fc2020-10-13 10:44:35 +0200148 const req = new XMLHttpRequest();
Leo Reppa6aba9a2021-01-23 20:16:43 +0100149 req.open(requestType, url, true);
150 // Dispatch global "window" event. See Kalamar::Plugin::Piwik
Akronbf713fc2020-10-13 10:44:35 +0200151 const reqE = new CustomEvent('korapRequest', {
Akron4c33c622018-11-12 13:43:27 +0100152 bubbles : false,
Akronb89863a2018-11-13 16:43:59 +0100153 detail: {
154 "url" : url,
155 "title" : title
156 }
Akron4c33c622018-11-12 13:43:27 +0100157 });
158 window.dispatchEvent(reqE);
159
Nils Diewald4347ee92015-05-04 20:32:48 +0000160 req.setRequestHeader("Accept", "application/json");
Leo Reppa6aba9a2021-01-23 20:16:43 +0100161 req.setRequestHeader("Content-Type", "application/json");
162 req.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
Leo Repp57997402021-08-18 16:37:52 +0200163 //req.setRequestHeader('Origin',"API");
Nils Diewald4347ee92015-05-04 20:32:48 +0000164 req.onreadystatechange = function () {
165 /*
Akron0b489ad2018-02-02 16:49:32 +0100166 States:
167 0 - unsent (prior to open)
168 1 - opened (prior to send)
169 2 - headers received
170 3 - loading (responseText has partial data)
171 4 - done
Nils Diewald4347ee92015-05-04 20:32:48 +0000172 */
173 if (this.readyState == 4) {
Akron515851a2017-05-02 12:53:17 +0200174
Leo Reppa6aba9a2021-01-23 20:16:43 +0100175 if (requestType === "GET") { //GET
176 let retJSObj;
177 try {
178 retJSObj = JSON.parse(this.responseText);
179 }
180 catch (e) {
181 KorAP.log(0, e);
182 console.log(e);
183 returnValueCB(undefined);
184 return;
185 };
186
Akrone71bd6d2024-06-11 15:47:39 +0200187 if (retJSObj !== undefined) {
188 if (retJSObj["errors"] !== undefined) {
189 retJSObj["errors"].forEach(
190 e => KorAP.log(e[0], e[1] || "Unknown")
191 );
192 } else if (retJSObj["warnings"] !== undefined) {
193 retJSObj["warnings"].forEach(
194 e => KorAP.log(e[0], e[1] || "Unknown", null, 'warn')
195 );
196 }
Leo Reppa6aba9a2021-01-23 20:16:43 +0100197 }
198
199 else if (this.status !== 200) {
200 KorAP.log(this.status, this.statusText, "Remote service error (XMLHttpRequest) under URL: " + url);
201 };
202
203 if (this.status === 200) {
204 returnValueCB(retJSObj);
205 }
206
207 else {
208 returnValueCB(undefined);
209 };
210
211 } else { // PUT, POST, DELETE
212 if (this.status >= 300 || this.status < 200) { //Error
213 KorAP.log(this.status, this.statusText, "Remote service error (XMLHttpRequest) under URL: " + url);
214 };
Akronb5d05d72018-02-12 15:09:12 +0100215 };
Leo Reppa6aba9a2021-01-23 20:16:43 +0100216 // Call the callback function (no matter requestType) if one is given.
217 if (typeof(errorCB) === "function"){
218 errorCB({
219 "status" : this.status,
220 "statusText" : this.statusText
221 });
222 };
223 };
Nils Diewald4347ee92015-05-04 20:32:48 +0000224 };
Akronbf713fc2020-10-13 10:44:35 +0200225
Leo Reppa6aba9a2021-01-23 20:16:43 +0100226 /*Set a value for .timeout to use this functionality */
227 //req.ontimeout = function () {
228 // KorAP.log(0, 'Request Timeout');
229 //};
230 if (requestType === "POST" || requestType === "PUT") {
231 req.send(JSON.stringify(jsObj));
232 } else { //GET, DELETE
233 req.send();
Nils Diewald4347ee92015-05-04 20:32:48 +0000234 };
Leo Reppa6aba9a2021-01-23 20:16:43 +0100235 };
236
237 /**
238 * General method to get JSON information.
239 *
240 * @param {String} url The url at which the JSON File will be located
241 * @param {function} returnValueCB The callback function that receives the retrieved JS object (already parsed) as a parameter, or undefined if none is eligible
242 * @param {String} title How to store this request in the logs
243 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
244 */
245 KorAP.API.getJSON = function (url, returnValueCB, title, errorCB) {
246 _actionJSON("GET", url, title, undefined, returnValueCB, errorCB);
247 };
248
249 /**
250 * General method to put JSON information.
251 *
252 * @param {String} url The url at which the JSON File will be located
253 * @param {JSObj} jsObj The JS object that is getting transfered. This will be stringified
254 * @param {String} title How to store this request in the logs
255 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
256 */
257 KorAP.API.putJSON = function (url, jsObj, title, errorCB) {
258 _actionJSON("PUT", url, title, jsObj, undefined, errorCB);
259 };
260
261 /**
262 * General method to post JSON information.
263 *
264 * @param {String} url The url at which the JSON File will be located
265 * @param {JSObj} jsObj The JS object that is getting transfered. This will be stringified
266 * @param {String} title How to store this request in the logs
267 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
268 */
269 KorAP.API.postJSON = function (url, jsObj, title, errorCB) {
270 _actionJSON("POST", url, title, jsObj, undefined, errorCB);
271 };
272
273 /**
274 * General method to delete a file at a specific URL
275 *
276 * @param {String} url The url at which the to be deleted file is located
277 * @param {String} title How to store this request in the logs
278 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
279 */
280 KorAP.API.deleteJSON = function (url, title, errorCB) {
281 _actionJSON("DELETE", url, title, undefined, undefined, errorCB);
282 };
283
284
285 // Stored query related functions
286
287 /**
288 * Retrieve saved list of queries
289 *
290 * @param {function} returnValueCB The callback function that receives the JS object Listof queries, already parsed
291 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
292 */
293 KorAP.API.getQueryList = function (returnValueCB, errorCB){
294 KorAP.API.getJSON(KorAP.URL + "/query/", returnValueCB, "getSavedQueryList", errorCB);
295 };
296
297 /**
298 * Retrieve specific saved query by query name
299 *
300 * @param {String} qn The name of the query to be retrieved. Must be a string
301 * @param {function} returnValueCB The callback function that receives the query JS object Object, already parsed
302 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
303 */
304 KorAP.API.getQuery = function (qn, returnValueCB, errorCB){
305 KorAP.API.getJSON(KorAP.URL + "/query/" + qn, returnValueCB, "getSavedQuery of name "+ qn, errorCB);
306 };
307
308 /**
309 * Put new query by query name
310 *
311 * @param {String} qn The name of the new query
312 * @param {JSObj} jsObj The query. This will be stringified
313 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
314 */
315 KorAP.API.putQuery = function (qn, jsObj, errorCB){
316 KorAP.API.putJSON(KorAP.URL + "/query/" + qn, jsObj, "putQuery of name "+ qn, errorCB);
317 };
318
319 /**
320 * Post new query by query name
321 *
322 * @param {String} qn The name of the new query
323 * @param {JSObj} jsObj The query. This will be stringified
324 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
325 */
326 KorAP.API.postQuery = function (qn, jsObj, errorCB){
327 KorAP.API.postJSON(KorAP.URL + "/query/" + qn, jsObj, "postQuery of name "+ qn, errorCB);
328 };
329
330 /**
331 * delete query by query name
332 *
333 * @param {String} qn The name of the to be deleted query
334 * @param {function} errorCB Optional. Callback function for error handling, receives JS object with status and statusText attribute
335 */
336 KorAP.API.deleteQuery = function (qn, errorCB){
337 KorAP.API.deleteJSON(KorAP.URL + "/query/" + qn, "deleteQuery of name "+ qn, errorCB);
338 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000339});