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

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