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

Last change on this file since 33043 was 33043, checked in by ak19, 5 years ago

Not a bugfix, but to help with encoding issues, including to help with current, still unresolved encoding issue. 1. Introduction of string2hex functions in JavaScript and Java. 2. Overriding GSXML.elemtToString() with introduction of additional debugEncoding parameter that will turn on string2hex use when printing request and response XMLs. Now non-basic ASCII characters in the XML will be printed in hex if debugEncoding parameter passed in is true. 3. The inactive Connector elements in server8.xml.svn now also have the attribute URIEncoding set to UTF-8. Some of these inactive Connectors get turned on at times, such as for https. In which case we will need tomcact to also interpret get/post data coming in through those connectors to be sent on as utf-8.

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