source: main/trunk/greenstone3/web/interfaces/default/js/javascript-global-functions.js@ 33218

Last change on this file since 33218 was 33218, checked in by wy59, 5 years ago
  1. Added Javascript versions of new erase-metadata functions, to work with their recently introduced perl counterparts. Because this feature is now unused but still potentially useful, having been created for a scenario we no longer need, these functions are untested. Other than that they produced no obvious javascript syntax errors when the modified javascript-global-functions.js file got included. 2. Minor, improved a comment.
File size: 39.3 KB
Line 
1var SUCCESS = 1;
2var ACCEPTED = 2;
3var ERROR = 3;
4var CONTINUING = 10;
5var COMPLETED = 11;
6var HALTED = 12;
7
8gs.functions = {};
9
10gs.jqGet = function(id)
11{
12 return $("#" + id.replace(/\./g, "\\.").replace(/:/g,"\\:"));
13}
14
15// Debugging function to print a string's non-basic chars in hex. So does string2hex on all non-basic and non-printable ASCII chars
16// Dr Bainbridge said that printing anything with charCode over 128 in hex is okay, but I'd already made extra allowances for non-printable ASCII
17// Based on https://stackoverflow.com/questions/36637146/javascript-encode-string-to-hex/36637293
18// https://stackoverflow.com/questions/21647928/javascript-unicode-string-to-hex
19gs.functions.debug_unicode_string = function(str) {
20 var hex, i;
21
22 var result = "";
23 for (i=0; i<str.length; i++) {
24 charcode = str.charCodeAt(i);
25 // ASCII table: https://cdn.sparkfun.com/assets/home_page_posts/2/1/2/1/ascii_table_black.png
26 // if the unicode character code pt is less than the ASCII code for space and greater than for tilda, let's display the char in hex (x0000 format)
27 if(charcode < 20 || charcode > 126) { //doesn't work: if(str.charAt(i) < ' ' || str.charAt(i) > '~') {
28 hex = charcode.toString(16);
29 result += "x{" + ("000"+hex).slice(-4) + "}"; // looks like: x{4-char-codepoint}
30 }
31 else {
32 result += str.charAt(i);
33 }
34 }
35
36 return result;
37}
38
39gs.functions.ajaxRequest = function()
40{
41 var activexmodes=["Msxml2.XMLHTTP", "Microsoft.XMLHTTP"];
42 if(window.ActiveXObject)
43 {
44 for (var i=0; i<activexmodes.length; i++)
45 {
46 try
47 {
48 return new ActiveXObject(activexmodes[i]);
49 }
50 catch(e){}
51 }
52 }
53 else if (window.XMLHttpRequest)
54 {
55 return new XMLHttpRequest();
56 }
57 else
58 {
59 return false
60 }
61}
62
63gs.functions.hasClass = function(elem, classVal)
64{
65 if(!elem || !elem.getAttribute("class"))
66 {
67 return false;
68 }
69
70 return (elem.getAttribute("class").search(classVal) != -1)
71}
72
73gs.functions.getElementsByClassName = function(cl)
74{
75 var nodes = new Array();
76 var classRegEx = new RegExp('\\b'+cl+'\\b');
77 var allElems = document.getElementsByTagName('*');
78
79 for (var i = 0; i < allElems.length; i++)
80 {
81 var classes = allElems[i].className;
82 if (classRegEx.test(classes))
83 {
84 nodes.push(allElems[i]);
85 }
86 }
87 return nodes;
88};
89
90gs.functions.makeToggle = function(buttons, divs)
91{
92 var buttonArray = (buttons.length) ? buttons : [buttons];
93 var divArray = (divs.length) ? divs : [divs];
94
95 for(var i = 0; i < buttonArray.length; i++)
96 {
97 buttonArray[i].onclick = function()
98 {
99 for(var j = 0; j < divArray.length; j++)
100 {
101 if(divArray[j].style.display == "none")
102 {
103 divArray[j].style.display = "block";
104 }
105 else
106 {
107 divArray[j].style.display = "none";
108 }
109 }
110
111 for(var j = 0; j < buttonArray.length; j++)
112 {
113 if(buttonArray[j].getAttribute("src") == gs.imageURLs.collapse)
114 {
115 buttonArray[j].setAttribute("src", gs.imageURLs.expand);
116 }
117 else if(buttonArray[j].getAttribute("src") == gs.imageURLs.expand)
118 {
119 buttonArray[j].setAttribute("src", gs.imageURLs.collapse);
120 }
121 }
122 };
123 }
124}
125
126gs.functions.checkForErrors = function(xml)
127{
128 var errorElems = xml.getElementsByTagName("error");
129
130 if(errorElems && errorElems.length > 0)
131 {
132 var errorString = gs.text.dse.error_saving_changes + ": ";
133 for(var i = 0; i < errorElems.length; i++)
134 {
135 errorString += " " + errorElems.item(i).firstChild.nodeValue;
136 }
137 alert(errorString);
138 return true;
139 }
140 return false; //No errors
141}
142
143gs.functions.validateXML = function(txt)
144{
145 // code for IE
146 if (window.ActiveXObject)
147 {
148 var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
149 xmlDoc.async = "false";
150 xmlDoc.loadXML(document.all(txt).value);
151
152 if(xmlDoc.parseError.errorCode!=0)
153 {
154 txt = dse.error_code + ": " + xmlDoc.parseError.errorCode + "\n";
155 txt = txt + dse.error_reason + ": " + xmlDoc.parseError.reason;
156 txt = txt + dse.error_line + ": " + xmlDoc.parseError.line;
157 console.log(txt);
158 return null;
159 }
160
161 return xmlDoc;
162 }
163 // code for Mozilla, Firefox, Opera, etc.
164 else if (document.implementation.createDocument)
165 {
166 var parser = new DOMParser();
167 var xmlDoc = parser.parseFromString(txt,"text/xml");
168
169 if (xmlDoc.getElementsByTagName("parsererror").length > 0)
170 {
171 console.log(gs.text.dse.xml_error);
172 return null;
173 }
174
175 return xmlDoc;
176 }
177 else
178 {
179 console.log(gs.text.dse.browse_cannot_validate_xml);
180 }
181 return null;
182}
183
184gs.functions.buildCollections = function(collections, finalFunction)
185{
186 if(!collections || collections.length == 0)
187 {
188 console.log("List of collections to build is empty");
189 return;
190 }
191
192 var counter = 0;
193 var buildFunction = function()
194 {
195 var ajax = new gs.functions.ajaxRequest();
196 ajax.open("GET", gs.xsltParams.library_name + "?a=g&rt=r&ro=1&s=BuildCollection&s1.collection=" + collections[counter]);
197 ajax.onreadystatechange = function()
198 {
199 if(ajax.readyState == 4 && ajax.status == 200)
200 {
201 var text = ajax.responseText;
202 var xml = gs.functions.validateXML(text);
203
204 if(!xml || gs.functions.checkForErrors(xml))
205 {
206 console.log("Could not build collection -> " + collections[counter] + ", aborting");
207 return;
208 }
209
210 var status = xml.getElementsByTagName("status")[0];
211 var pid = status.getAttribute("pid");
212
213 gs.functions.startCheckLoop(pid, "BuildCollection", function()
214 {
215 var localAjax = new gs.functions.ajaxRequest();
216 localAjax.open("GET", gs.xsltParams.library_name + "?a=g&rt=r&ro=1&s=ActivateCollection&s1.collection=" + collections[counter], true);
217 localAjax.onreadystatechange = function()
218 {
219 if(localAjax.readyState == 4 && localAjax.status == 200)
220 {
221 var localText = localAjax.responseText;
222 var localXML = gs.functions.validateXML(localText);
223
224 if(!xml || gs.functions.checkForErrors(xml))
225 {
226 console.log("Could not activate collection -> " + collections[counter] + ", aborting");
227 return;
228 }
229
230 var localStatus = localXML.getElementsByTagName("status")[0];
231 if(localStatus)
232 {
233 var localPID = localStatus.getAttribute("pid");
234 gs.functions.startCheckLoop(localPID, "ActivateCollection", function()
235 {
236 if (++counter == collections.length)
237 {
238 //Run this function once we are done building all the collections
239 if(finalFunction){finalFunction();}
240 }
241 else
242 {
243 buildFunction();
244 }
245 });
246 }
247 }
248 }
249 localAjax.send();
250 });
251 }
252 }
253 ajax.send();
254 }
255 buildFunction();
256}
257
258gs.functions.startCheckLoop = function(pid, serverFunction, callbackFunction)
259{
260 var ajaxFunction = function()
261 {
262 var ajax = new gs.functions.ajaxRequest();
263 ajax.open("GET", gs.xsltParams.library_name + "?a=g&rt=s&ro=1&s=" + serverFunction + "&s1.pid=" + pid, true);
264 ajax.onreadystatechange = function()
265 {
266 if(ajax.readyState == 4 && ajax.status == 200)
267 {
268 var text = ajax.responseText;
269 var xml = gs.functions.validateXML(text);
270
271 if(!xml || gs.functions.checkForErrors(xml))
272 {
273 console.log("Could not check status of " + serverFunction + ", there was an error in the XML, aborting");
274 return;
275 }
276
277 var status = xml.getElementsByTagName("status")[0];
278 var code = status.getAttribute("code");
279
280 if (code == COMPLETED || code == SUCCESS)
281 {
282 callbackFunction();
283 }
284 else if (code == HALTED || code == ERROR)
285 {
286 console.log("Could not check status of " + serverFunction + ", there was an error on the server, aborting");
287 }
288 else
289 {
290 setTimeout(ajaxFunction, 1000);
291 }
292 }
293 }
294 ajax.send();
295 }
296 ajaxFunction();
297}
298
299function inc(a, b)
300{
301 var carry = 0;
302 var num = 0;
303 var i = 0;
304
305 while((carry || (i < a.length) || (i < b.length)) && (i < 100))
306 {
307 num = carry;
308 if(i < a.length){num += a[i];}
309 if(i < b.length){num += b[i];}
310
311 if(num >= 256)
312 {
313 num -= 256;
314 carry = 1;
315 }
316 else
317 {
318 carry = 0;
319 }
320
321 a[i] = num;
322
323 i++;
324 }
325}
326
327function ifposDec(a, b)
328{
329 var carry = 0;
330 var num = 0;
331 var i = 0;
332
333 if(b.length > a.length){return a;}
334 if(b.length == a.length)
335 {
336 i = a.length - 1;
337 while(i >= 0)
338 {
339 if(a[i] > b[i]){break;}
340 if(a[i] < b[i]){return a;}
341 i--;
342 }
343 }
344
345 i = 0;
346 var len = 0;
347 var outString = "";
348 while((i < a.length) || (i < b.length))
349 {
350 num = -carry;
351 if(i < a.length){num += a[i];}
352 if(i < b.length){num -= b[i];}
353
354 if(num < 0)
355 {
356 num += 256;
357 carry = 1;
358 }
359 else
360 {
361 carry = 0;
362 }
363
364 a[i] = num;
365 outString += num + ","
366 i++
367
368 if(num != 0){len = i}
369 }
370
371 if(len < a.length)
372 {
373 a = a.slice(0, len);
374 }
375
376 return a;
377}
378
379function convertNum(a)
380{
381 var result = new Array();
382 var i;
383 var convert = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"];
384
385 if(a.length == 0)
386 {
387 result.push("0");
388 return result;
389 }
390
391 for(i = a.length - 1; i >= 0; i--)
392 {
393 result.push(convert[Math.floor(a[i]/16)]);
394 result.push(convert[Math.floor(a[i]%16)]);
395 }
396
397 var resultString = "";
398 for(var j = 0; j < result.length; j++)
399 {
400 resultString += result[j];
401 }
402
403 return resultString;
404}
405
406gs.functions.hashString = function(str)
407{
408 var remainder = new Array();
409 var primePow = new Array();
410 var pow =
411 [
412 255, 255, 255,
413 255, 255, 255,
414 255, 255, 255,
415 255, 255, 1
416 ];
417
418 for(var i = 0; i < 8; i++)
419 {
420 primePow.push(pow.slice()); //The javascript way to do an array copy (yuck!)
421 inc(pow, pow);
422 }
423
424 for(var i = 0; i < str.length; i++)
425 {
426 var c = str.charCodeAt(i);
427
428 if(remainder.length == 99)
429 {
430 return null;
431 }
432
433 for(var j = remainder.length; j > 0; j--)
434 {
435 remainder[j] = remainder[j-1];
436 }
437 remainder[0] = c;
438
439 for(var j = 7; j >= 0; j--)
440 {
441 remainder = ifposDec(remainder, primePow[j]);
442 }
443 }
444
445 return convertNum(remainder);
446}
447
448// This method performs an AJAX call after working out, based on parameters and internal decision-making code,
449// if it's using GET or POST,
450// asynchronous or synchronous AJAX,
451// jQuery's .ajax() method or gsajaxapi.js' regular JavaScript way of calling AJAX (necessary functions
452// now ported from GS2 to GS3)
453// and whether it needs to transmit the payload in URL or data structure (Java object) form.
454// In the past, the AJAX calls to metadataserver.pl only dealt with URLs and used jQuery .ajax(). As a
455// consequence of this particular combination, the calls in the past were all GET operations.
456//
457// - payload param: contains both the URL form and the data object form of the package to transmit over
458// AJAX to metadataserver.pl. Based on the parameters and some internal variables, _callMetadataServer()
459// determines which to use.
460// - opts param: No function overloading in JavaScript. Can pass a custom object, however can pass opts,
461// see http://stackoverflow.com/questions/456177/function-overloading-in-javascript-best-practices
462//
463// BEWARE:
464// errorResponseFunction is at present only called on error if using jQuery ajax (sync/async) and not if using gsajaxapi (sync/async).
465gs.functions._callMetadataServer = function(callingFunction, payload, successResponseFunction, errorResponseFunction, opts)
466{
467
468 // async AJAX by default for get operations: because internal processing of 'read' operations (get meta)
469 // is not order dependent.
470 // Set/remove operations will switch to synchronous AJAX, unless opt["forceSync"] is set otherwise
471 var async_setting = true;
472 var method = "POST"; // GET was the default before
473
474 // Set to false if you wish to use the regular JavaScript AJAX way in gsajaxapi.js (will use payload.url)
475 // Set to true if using jQuery AJAX (will use payload.data).
476 var _use_jQuery_ajax_not_gsajaxapi = true;
477
478 // _use_payload_in_data_not_url_form is determined based on vars method and _use_jQuery_ajax_not_gsajaxapi
479 // If using AJAX with payload data (with jQuery) rather than using URLs containing data (payload in url):
480 // using data will allow us to use jQuery to POST stuff too.
481 // For gsajaxapi, payload to be transmitted over AJAX must be in URL form, whether GET or POST.
482 // For jQuery, AJAX calls ended up as GET when the payload is in URL form.
483 // Default used to be payload in url form. To get the default back,
484 // set method = "GET" (above, but also in calling functions that specify this optional parameter!)
485 // and set the default here below for _use_payload_in_data_not_url_form to false.
486 var _use_payload_in_data_not_url_form = true; // code will anyway set this to true for jQuery $.ajax() with POST
487
488 var _modifyingMeta = false;
489
490 var url = payload["url"]; // for jQuery GET, and for GET and POST using JavaScript AJAX
491 var data = payload["data"]; // for jQuery POST
492
493
494 // check for any caller overrides
495 if(opts != null) {
496 if(opts["requestMethod"] != null) {
497 method = opts["requestMethod"];
498 }
499 }
500
501 // sync or async? Generally, synchronous AJAX for set-meta operations, and asynchronous for get-meta ops
502 var metaServerCommand = (data["s1.a"] == null) ? data["a"] : data["s1.a"];
503 if(metaServerCommand.indexOf("set-") != -1 || metaServerCommand.indexOf("remove-") != -1) {
504 _modifyingMeta = true;
505 async_setting = false; // for 'write' operations (set/remove meta), we force sequential processing of the internal operation.
506
507 }
508 // check for any overrides by calling code that knows what it's doing
509 if (opts != null && opts["forceSync"] != null) {
510 async_setting = (!opts["forceSync"]);
511 }
512
513 if(_use_jQuery_ajax_not_gsajaxapi) {
514 if(method == "POST") {
515 _use_payload_in_data_not_url_form = true;
516 } // if GET, can use payload in URL form or in data form for jQuery AJAX
517 // to put it another way: can't do jQuery POST operations with payload in URL form
518
519 } else { // using gsajaxapi.js, which only accepts the payload in URL form, whether GET or POST
520 _use_payload_in_data_not_url_form = false;
521 }
522
523 // use the URL form or the data form to transmit the payload over AJAX?
524 // Payload in data form implies jQuery AJAX, not gsajaxapi calls,
525 // since we can't use gsajaxapi.js AJAX GET/POST calls without payload in URL form
526 if(_use_payload_in_data_not_url_form) { // using data payload to do AJAX (regardless of request method)
527
528 // for get-meta operations, go directly through metadata-server.pl
529 // for set-meta ops, should go via GS3 authentication, which is off the GS3 library servlet
530 url = (_modifyingMeta) ? gs.xsltParams.library_name : "cgi-bin/metadata-server.pl";
531
532 } else { // uses data encoded into URL, rather than a data structure.
533 data = null; // we're using the URL as payload, don't duplicate the payload to be transmitted into data
534
535 url = payload["url"]; // payload["url"] contains the URL + data encoded in URL form
536 // URL is already correct for get-meta vs meta-modification operations.
537 // For meta-modification ops, it will through GS3 authentication first rather than metadata-server.pl
538
539 }
540
541 // finally, can do the AJAX call
542
543 //console.log("*** Away to call: " + url);
544 var ajaxResponse = async_setting ? "*** No response received yet, async ajax request" : null;
545
546
547 if(_use_jQuery_ajax_not_gsajaxapi) {
548 // ajax calls default to using method GET, we want to do POST operations for get-meta and set-meta requests
549 // since get-meta-array and especially set-meta-array can be large, e.g. for user comments.
550 $.ajax({url: url, async: async_setting, type: method, data: data})
551 .success(function(response) {
552 ajaxResponse = response;
553// console.log("** (" + callingFunction + ") Response received from server: " + ajaxResponse);
554
555 //var xml = $.parseXML(response);
556 //console.log(xml);
557
558 if(successResponseFunction != null) {
559 //console.log("XXXX callMetaServer - Got response: " + response);
560 successResponseFunction(response);
561 }
562 })
563 .error(function(response) {
564 if(errorResponseFunction != null) {
565 errorResponseFunction(response);
566 } else {
567 console.log("(" + callingFunction + ") Failed");
568 }
569 });
570 }
571 else {
572 // USES GSAJAXAPI.JS to do AJAX. In this case, the payload must be in URL form
573
574 var splitURL = url.split("?");
575 url = splitURL[0]; // base URL
576 var params = splitURL[1]; // query-string
577
578 // Don't need to delete objects created with 'new' in JavaScript. Garbage collection will do it.
579 // http://stackoverflow.com/questions/4869712/new-without-delete-on-same-variable-in-javascript
580 var gsapi = new GSAjaxAPI(url);
581
582 // ajax calls default to using method GET, we want to do POST operations for get-meta and set-meta requests
583 // since get-meta-array and especially set-meta-array can be large, e.g. for user comments.
584
585 if(async_setting) {
586 gsapi.urlPostAsync(url, params, successResponseFunction);
587 } else {
588 ajaxResponse = gsapi.urlPostSync(url, params);
589 ajaxResponse = ajaxResponse;
590 }
591
592// console.log("*** (" + callingFunction + ") Response from server: " + ajaxResponse);
593
594 }
595
596// console.log("*** Finished ajax call to: " + url);
597// console.log("*** Got response: " + ajaxResponse);
598
599 return ajaxResponse;
600}
601
602// Prepare the payload (data package) to transmit to metadataserver.pl over AJAX.
603// These next 2 functions prepare both the URL version of the payload and the data object version of
604// of the payload. Then calling functions, and the _callMetadataServer() function they call, will control
605// and determine which of the two forms ultimately gets used.
606// (Constructing both URL and data structure, as I could not successfully convert old URL way to data structure
607// http://stackoverflow.com/questions/8648892/convert-url-parameters-to-a-javascript-object)
608gs.functions.getBasicDataForMetadataServer = function(metaServerCommand, collection, site, documentID, metadataName,
609 metamode, metadataValue, prevMetadataValue, metadataPosition)
610{
611 // if we're doing set- or remove- metadata operations,
612 // then we need change the data params that will make up the query string
613 // to make sure we go through GS3's authentication
614 // 1. prefix meta names with s1,
615 // 2. use s1.collection for collectionName since c is a special param name for GS2Construct
616 // 3. Additional parameters for rerouting through Authentication: a=g&rt=r&ro=1&s=ModifyMetadata
617
618 var modifyingMeta = false;
619 var prefix = "";
620 var colPropName = "c";
621 var baseURL = "cgi-bin/metadata-server.pl?";
622
623 // if we need authentication:
624 if(metaServerCommand.indexOf("set-") != -1 || metaServerCommand.indexOf("remove-") != -1) {
625 modifyingMeta = true;
626 prefix = "s1.";
627 colPropName = prefix+"collection"; // "s1.collection"
628 baseURL = gs.xsltParams.library_name + "?a=g&rt=r&ro=1&s=ModifyMetadata&";
629 }
630
631
632 // 1. when using jQuery to POST, need to invoke AJAX with a data structure rather than a URL
633 var data = {};
634
635 // customizable portion of ajax call
636 data[prefix+"a"] = metaServerCommand;
637 data[colPropName] = collection;
638 data[prefix+"site"] = site;
639 data[prefix+"d"] = documentID;
640 data[prefix+"metaname"] = metadataName;
641 data[prefix+"metapos"] = metadataPosition;
642 data[prefix+"metavalue"] = metadataValue;
643 data[prefix+"prevmetavalue"] = prevMetadataValue;
644 data[prefix+"metamode"] = metamode;
645
646 if(modifyingMeta) {
647 // fixed portion of url: add the a=g&rt=r&ro=1&s=ModifyMetadata part of the GS3 URL for
648 // going through authentication. Don't prefix "s1." to these!
649 data["a"] = "g";
650 data["rt"] = "r";
651 data["ro"] = "1";
652 data["s"] = "ModifyMetadata";
653 }
654
655 // 2. Construct the URL version of the metadata-server.pl operation:
656 // for GET requests, the URL can contain the data.
657 // Regular JavaScript AJAX code in gsajaxapi.js can also POST data in URL form, but not jQuery's .ajax().
658
659
660 // If doing set- or remove- (not get-) metadata, then rewrite URLs to call GS2Construct's ModfiyMetadata service instead (which will ensure this only works when authenticated).
661 // From:
662 // <gs3server>/cgi-bin/metadata-server.pl?a=set-archives-metadata&c=smallcol&site=localsite&d=HASH01454f31011f6b6b26eaf8d7&metaname=Title&metavalue=Moo&prevmetavalue=Blabla&metamode=override
663 // To:
664 // <gs3server>/library?a=g&rt=r&ro=1&s=ModifyMetadata&s1.a=set-archives-metadata&s1.collection=smallcol&s1.site=localsite&s1.d=HASH01454f31011f6b6b26eaf8d7&s1.metaname=Title&s1.metavalue=Moo&s1.prevmetavalue=Blabla&s1.metamode=override
665
666 var extraParams = "";
667
668 if(metadataValue != null) {
669 extraParams += "&"+prefix+"metavalue=" + metadataValue;
670 }
671
672 if(metadataPosition != null)
673 {
674 extraParams += "&"+prefix+"metapos=" + metadataPosition;
675 }
676
677 if(prevMetadataValue != null) {
678 extraParams += "&"+prefix+"prevmetavalue=" + prevMetadataValue;
679 }
680
681 var url = baseURL + prefix+"a=" + metaServerCommand + "&"+colPropName+"=" + collection + "&"+prefix+"site=" + site + "&"+prefix+"d=" + documentID + "&"+prefix+"metaname=" + metadataName + extraParams + "&"+prefix+"metamode=" + metamode;
682
683 // 3. Return both the constructed url & data variants of the payload to be transmitted over ajax
684 var payload = {
685 url: url,
686 data: data
687 };
688
689 return payload;
690}
691
692// See description for getBasicDataForMetadataServer()
693gs.functions.getComplexDataForMetadataServer = function(metaServerCommand, collection, site, docArray, metamode, where)
694{
695 var docArrayJSON = JSON.stringify(docArray);
696
697 // if we're doing set- or remove- metadata operations,
698 // then we need change the data params that will make up the query string
699 // to make sure we go through GS3's authentication
700 // 1. prefix meta names with s1,
701 // 2. use s1.collection for collectionName since c is a special param name for GS2Construct
702 // 3. Additional parameters for rerouting through Authentication: a=g&rt=r&ro=1&s=ModifyMetadata
703
704 var modifyingMeta = false;
705 var prefix = "";
706 var colPropName = "c";
707 var baseURL = "cgi-bin/metadata-server.pl?";
708
709 // if we need authentication:
710 if(metaServerCommand.indexOf("set-") != -1 || metaServerCommand.indexOf("remove-") != -1) {
711 modifyingMeta = true;
712 prefix = "s1.";
713 colPropName = prefix+"collection"; // "s1.collection"
714 baseURL = gs.xsltParams.library_name + "?a=g&rt=r&ro=1&s=ModifyMetadata&";
715 }
716
717 // 1. when using jQuery to POST, need to invoke AJAX with a data structure rather than a URL
718 var data = {};
719
720 // customizable portion of ajax call
721 data[prefix+"a"] = metaServerCommand;
722 data[colPropName] = collection;
723 data[prefix+"site"] = site;
724 data[prefix+"json"] = docArrayJSON;
725
726 if(where != null) {
727 data[prefix+"where"] = where;
728 }
729 if (metamode!=null) {
730 data[prefix+"metamode"] = metamode;
731 }
732
733 if(modifyingMeta) {
734 // fixed portion of url: add the a=g&rt=r&ro=1&s=ModifyMetadata part of the GS3 URL for
735 // going through authentication. Don't prefix "s1." to these!
736 data["a"] = "g";
737 data["rt"] = "r";
738 data["ro"] = "1";
739 data["s"] = "ModifyMetadata";
740 }
741
742
743 // 2. URL for when doing AJAX in URL mode. GET with jQuery allows the data to be part of the URL, but
744 // not jQuery POST. But our regular JavaScript AJAX code in gsajaxapi.js allows GET and POST with URLs
745 // containing the data.
746
747 var params = prefix+"a=" + escape(metaServerCommand); //"a=set-metadata-array";
748 if(where != null) {
749 params += "&"+prefix+"where=" + escape(where); // if where not specified, meta-server will default to setting index meta
750 //} else {
751 // params += "&"+prefix+"where=import|archives|index";
752 }
753 params += "&"+colPropName+"="+escape(collection);
754 params += "&"+prefix+"site="+escape(site);
755 params += "&"+prefix+"json="+escape(docArrayJSON);
756
757 if (metamode!=null) {
758 params += "&"+prefix+"metamode=" + escape(metamode);
759 }
760
761 // 3. Return both the constructed url & data variants of the payload to be transmitted over ajax
762 var payload = {
763 url: baseURL + params,
764 data: data
765 };
766
767 return payload;
768}
769
770/*************************
771* SET METADATA FUNCTIONS *
772*************************/
773
774gs.functions.setImportMetadata = function(collection, site, documentID, metadataName, metadataValue, prevMetadataValue, metamode, successResponseFunction, errorResponseFunction)
775{
776 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
777
778 gs.functions._callMetadataServer(
779 "setImportMetadata",
780 gs.functions.getBasicDataForMetadataServer("set-import-metadata", collection, site, documentID, metadataName, metamode, metadataValue, prevMetadataValue, null /*metapos*/),
781 successResponseFunction,
782 errorResponseFunction);
783
784}
785
786gs.functions.setArchivesMetadata = function(collection, site, documentID, metadataName, metadataPosition, metadataValue, prevMetadataValue, metamode, successResponseFunction, errorResponseFunction)
787{
788 if(metadataValue) console.log("metaval: " + metadataValue + " | " + gs.functions.debug_unicode_string(metadataValue)); //metadataValue.hexEncode()
789 if(prevMetadataValue) console.log("prevmetaval: " + prevMetadataValue + " | " + gs.functions.debug_unicode_string(prevMetadataValue));
790
791 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
792
793 if(metadataPosition != null) {
794 prevMetadataValue = null; // to force the same ultimate behaviour as in the old version of this code
795 }
796
797 gs.functions._callMetadataServer(
798 "setArchivesMetadata",
799 gs.functions.getBasicDataForMetadataServer("set-archives-metadata", collection, site, documentID, metadataName, metamode, metadataValue, prevMetadataValue, metadataPosition),
800 successResponseFunction,
801 errorResponseFunction);
802
803}
804
805gs.functions.setIndexMetadata = function(collection, site, documentID, metadataName, metadataPosition, metadataValue, prevMetadataValue, metamode, successResponseFunction, errorResponseFunction)
806{
807 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
808
809 if(metadataPosition != null) {
810 prevMetadataValue = null; // to force the same ultimate behaviour as in the old version of this code
811 }
812
813 // old version of this function would only call _callMetadataServer if either metapos
814 // or prevMetaValue had a value. So sticking to the same behaviour in rewriting this function.
815 if(metadataPosition != null || prevMetadataValue != null) {
816
817 gs.functions._callMetadataServer(
818 "setIndexMetadata",
819 gs.functions.getBasicDataForMetadataServer("set-metadata", collection, site, documentID, metadataName, metamode, metadataValue, prevMetadataValue, metadataPosition),
820 successResponseFunction,
821 errorResponseFunction);
822 }
823}
824
825gs.functions.setMetadata = function(collection, site, documentID, metadataName, metadataValue, metamode, successResponseFunction, errorResponseFunction)
826{
827 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
828
829 var nameArray = ["setImportMetadata", "setArchivesMetadata", "setIndexMetadata"];
830 var functionArray = ["set-import-metadata", "set-archives-metadata", "set-metadata"];
831
832 for(var i = 0; i < nameArray.length; i++)
833 {
834 // previous version of this function did not allow setting metapos or prevMetavalue
835 // so leaving the behaviour the same along with function signature.
836 gs.functions._callMetadataServer(
837 nameArray[i],
838 gs.functions.getBasicDataForMetadataServer(functionArray[i], collection, site, documentID, metadataName, metamode, metadataValue, null /*prevMetadataValue*/, null /*metadataPosition*/),
839 successResponseFunction,
840 errorResponseFunction);
841 }
842}
843
844// New. Modified version of the GS2 version of this method in gsajaxapi.js.
845// The where parameter can be specified as one or more of: import, archives, index, live
846// separated by |. If null, it is assumed to be index which is the original default
847// behaviour of calling set-metadata-array. E.g. where=import|archives|index
848// THIS METHOD IS SYNCHRONOUS by default. Set forceSync to false to override this default behaviour
849gs.functions.setMetadataArray = function(collection, site, docArray, metamode, where, successResponseFunction, forceSync, errorResponseFunction)
850{
851 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
852
853 var payload = gs.functions.getComplexDataForMetadataServer("set-metadata-array", collection, site, docArray, metamode, where);
854
855 // set operations are generally synchronous, but allow calling function to force ajax call
856 // to be synchronous or not. Default is synchronous, as it was for GS2
857 if(forceSync == null) {
858 forceSync = true;
859 }
860
861 //console.log("cgi-bin/metadata-server.pl?"+params);
862
863 var response = gs.functions._callMetadataServer("Setting metadata in "+where, payload, successResponseFunction, errorResponseFunction, {"forceSync": forceSync, "requestMethod": "POST"});
864
865 return response;
866}
867
868
869/*************************
870* GET METADATA FUNCTIONS *
871*************************/
872
873// New. Modified version of the GS2 version of this method in gsajaxapi.js.
874// See description for setMetadataArray above for information about the 'where' parameter.
875// THIS METHOD IS SYNCHRONOUS BY DEFAULT. Set forceSync to false to override this default behaviour
876gs.functions.getMetadataArray = function(collection, site, docArray, where, successResponseFunction, forceSync, errorResponseFunction)
877{
878 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
879
880 var payload = gs.functions.getComplexDataForMetadataServer("get-metadata-array", collection, site, docArray, null /*metamode*/, where);
881
882 // get operations are generally asynchronous, but allow calling function to force ajax call
883 // to be synchronous or not. Default for get-metadata-array is synchronous, as it was for GS2
884 if(forceSync == null) {
885 forceSync = true;
886 }
887 // Objects/maps can use identifiers or strings for property names
888 // http://stackoverflow.com/questions/456177/function-overloading-in-javascript-best-practices
889 // https://www.w3schools.com/js/js_objects.asp
890 var response = gs.functions._callMetadataServer("Getting metadata from "+where, payload, successResponseFunction, errorResponseFunction, {"forceSync":forceSync, "requestMethod": "POST"});
891
892 return response;
893}
894
895
896gs.functions.getImportMetadata = function(collection, site, documentID, metadataName, successResponseFunction, errorResponseFunction)
897{
898 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
899
900 var payload = gs.functions.getBasicDataForMetadataServer("get-import-metadata", collection, site, documentID, metadataName);
901 gs.functions._callMetadataServer("getImportMetadata", payload, function(responseText) {
902 var metadata = new GSMetadata(collection, site, documentID, metadataName, null, null, responseText);
903 if(successResponseFunction != null)
904 {
905 successResponseFunction(metadata);
906 }
907 },
908 errorResponseFunction);
909}
910
911gs.functions.getArchivesMetadata = function(collection, site, documentID, metadataName, metadataPosition, successResponseFunction, errorResponseFunction)
912{
913 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
914
915 var payload = gs.functions.getBasicDataForMetadataServer("get-archives-metadata", collection, site, documentID, metadataName, null /*metamode*/, null /*metavalue*/, null /*prevmetavalue*/, metadataPosition);
916
917 gs.functions._callMetadataServer("getArchivesMetadata", payload, function(responseText) {
918 var metadata = new GSMetadata(collection, site, documentID, metadataName, null, metadataPosition, responseText); // indexPos, archivesPos, metaval (responseText)
919 if(successResponseFunction != null)
920 {
921 successResponseFunction(metadata);
922 }
923 },
924 errorResponseFunction);
925}
926
927gs.functions.getIndexMetadata = function(collection, site, documentID, metadataName, metadataPosition, successResponseFunction, errorResponseFunction)
928{
929 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
930
931 var payload = gs.functions.getBasicDataForMetadataServer("get-metadata", collection, site, documentID, metadataName, null /*metamode*/, null /*metavalue*/, null /*prevmetavalue*/, metadataPosition);
932
933 gs.functions._callMetadataServer("getIndexMetadata", payload, function(responseText) {
934 var metadata = new GSMetadata(collection, site, documentID, metadataName, metadataPosition, null, responseText); // indexPos, archivesPos, metaval (responseText)
935 if(successResponseFunction != null)
936 {
937 successResponseFunction(metadata);
938 }
939 },
940 errorResponseFunction);
941}
942
943/****************************
944* REMOVE METADATA FUNCTIONS *
945****************************/
946
947gs.functions.removeImportMetadata = function(collection, site, documentID, metadataName, metadataValue, successResponseFunction, errorResponseFunction)
948{
949 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
950
951 gs.functions._callMetadataServer(
952 "removeImportMetadata",
953 gs.functions.getBasicDataForMetadataServer("remove-import-metadata", collection, site, documentID, metadataName, null /*metamode*/, metadataValue, null /*prevmetavalue*/, null /*metapos*/),
954 successResponseFunction,
955 errorResponseFunction);
956}
957
958gs.functions.removeArchivesMetadata = function(collection, site, documentID, metadataName, metadataPosition, metadataValue, successResponseFunction, errorResponseFunction)
959{
960 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
961
962 if(metadataPosition != null) {
963 metadataValue = null; // retaining behaviour of previous version of this function removeArchivesMetadata()
964 }
965
966 gs.functions._callMetadataServer(
967 "removeArchivesMetadata",
968 gs.functions.getBasicDataForMetadataServer("remove-archives-metadata", collection, site, documentID, metadataName, null /*metamode*/, metadataValue, null /*prevmetavalue*/, metadataPosition),
969 successResponseFunction,
970 errorResponseFunction);
971}
972
973gs.functions.removeIndexMetadata = function(collection, site, documentID, metadataName, metadataPosition, metadataValue, successResponseFunction, errorResponseFunction)
974{
975 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
976
977 if(metadataPosition != null) {
978 metadataValue = null; // retaining behaviour of previous version of this function removeIndexMetadata()
979 }
980
981 gs.functions._callMetadataServer(
982 "removeIndexMetadata",
983 gs.functions.getBasicDataForMetadataServer("remove-metadata", collection, site, documentID, metadataName, null /*metamode*/, metadataValue, null /*prevmetavalue*/, metadataPosition),
984 successResponseFunction,
985 errorResponseFunction);
986}
987
988gs.functions.removeMetadata = function(collection, site, documentID, metadataName, metadataValue, successResponseFunction, errorResponseFunction)
989{
990 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
991
992 var nameArray = ["removeImportMetadata", "removeArchivesMetadata", "removeIndexMetadata"];
993 var functionArray = ["remove-import-metadata", "remove-archives-metadata", "remove-metadata"];
994
995 for(var i = 0; i < nameArray.length; i++)
996 {
997 gs.functions._callMetadataServer(
998 nameArray[i],
999 gs.functions.getBasicDataForMetadataServer(functionArray[i], collection, site, documentID, metadataName, null /*metamode*/, metadataValue, null /*prevmetavalue*/, null /*metapos*/),
1000 successResponseFunction,
1001 errorResponseFunction);
1002 }
1003}
1004
1005
1006/***********************************************************
1007* ERASE METADATA FUNCTIONS *
1008* Erase all meta in docID (sectionID) that match metaname. *
1009***********************************************************/
1010
1011gs.functions.eraseImportMetadata = function(collection, site, documentID, metadataName, successResponseFunction, errorResponseFunction)
1012{
1013 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
1014
1015 gs.functions._callMetadataServer(
1016 "eraseImportMetadata",
1017 gs.functions.getBasicDataForMetadataServer("erase-import-metadata", collection, site, documentID, metadataName, "override" /*metamode*/, null /*metadataValue*/, null /*prevmetavalue*/, null /*metadataPosition*/),
1018 successResponseFunction,
1019 errorResponseFunction);
1020}
1021
1022gs.functions.eraseArchivesMetadata = function(collection, site, documentID, metadataName, successResponseFunction, errorResponseFunction)
1023{
1024 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
1025
1026 gs.functions._callMetadataServer(
1027 "eraseArchivesMetadata",
1028 gs.functions.getBasicDataForMetadataServer("erase-archives-metadata", collection, site, documentID, metadataName, "override" /*metamode*/, null /*metadataValue*/, null /*prevmetavalue*/, null /*metadataPosition*/),
1029 successResponseFunction,
1030 errorResponseFunction);
1031}
1032
1033gs.functions.eraseIndexMetadata = function(collection, site, documentID, metadataName, successResponseFunction, errorResponseFunction)
1034{
1035 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
1036
1037 gs.functions._callMetadataServer(
1038 "eraseIndexMetadata",
1039 gs.functions.getBasicDataForMetadataServer("erase-metadata", collection, site, documentID, metadataName, "override" /*metamode*/, null /*metadataValue*/, null /*prevmetavalue*/, null /*metadataPosition*/),
1040 successResponseFunction,
1041 errorResponseFunction);
1042}
1043
1044gs.functions.eraseMetadata = function(collection, site, documentID, metadataName, successResponseFunction, errorResponseFunction)
1045{
1046 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
1047
1048 var nameArray = ["eraseImportMetadata", "eraseArchivesMetadata", "eraseIndexMetadata"];
1049 var functionArray = ["erase-import-metadata", "erase-archives-metadata", "erase-metadata"];
1050
1051 for(var i = 0; i < nameArray.length; i++)
1052 {
1053 gs.functions._callMetadataServer(
1054 nameArray[i],
1055 gs.functions.getBasicDataForMetadataServer(functionArray[i], collection, site, documentID, metadataName, "override" /*metamode*/, null /*metadataValue*/, null /*prevmetavalue*/, null /*metadataPosition*/),
1056 successResponseFunction,
1057 errorResponseFunction);
1058 }
1059}
Note: See TracBrowser for help on using the repository browser.