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

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

javascript-global-functions' local function callMetadataServer() now renamed to _callMetadataServer() and takes and extra parameter BEFORE existing last parameter opts. The extra parameter is errorResponseFunction, which if not null is called on an ajax error if using jQuery mode to do ajax (errorResponseFunction is not used by gsajaxapi yet). All functions that call _callMetadataServer() now also take an extra last param, errorResponseFunction, and force it to null if undefined. It is always the last param for these public functions, so that the existing method calls from outside the file will continue to work. Tested getting and setting regular meta with the doceditor and mapeditor: saving and reloading saved data still works. Not tested set/getMetaArrays used by usercomments, but the changes haven't been drastic or complicated, so shouldn't have broken anything in those 2 functions either.

File size: 34.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
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
438//
439// BEWARE:
440// errorResponseFunction is at present only called on error if using jQuery ajax (sync/async) and not if using gsajaxapi (sync/async).
441gs.functions._callMetadataServer = function(callingFunction, payload, successResponseFunction, errorResponseFunction, opts)
442{
443
444 // async AJAX by default for get operations: because internal processing of 'read' operations (get meta)
445 // is not order dependent.
446 // Set/remove operations will switch to synchronous AJAX, unless opt["forceSync"] is set otherwise
447 var async_setting = true;
448 var method = "POST"; // GET was the default before
449
450 // Set to false if you wish to use the regular JavaScript AJAX way in gsajaxapi.js (will use payload.url)
451 // Set to true if using jQuery AJAX (will use payload.data).
452 var _use_jQuery_ajax_not_gsajaxapi = true;
453
454 // _use_payload_in_data_not_url_form is determined based on vars method and _use_jQuery_ajax_not_gsajaxapi
455 // If using AJAX with payload data (with jQuery) rather than using URLs containing data (payload in url):
456 // using data will allow us to use jQuery to POST stuff too.
457 // For gsajaxapi, payload to be transmitted over AJAX must be in URL form, whether GET or POST.
458 // For jQuery, AJAX calls ended up as GET when the payload is in URL form.
459 // Default used to be payload in url form. To get the default back,
460 // set method = "GET" (above, but also in calling functions that specify this optional parameter!)
461 // and set the default here below for _use_payload_in_data_not_url_form to false.
462 var _use_payload_in_data_not_url_form = true; // code will anyway set this to true for jQuery $.ajax() with POST
463
464 var _modifyingMeta = false;
465
466 var url = payload["url"]; // for jQuery GET, and for GET and POST using JavaScript AJAX
467 var data = payload["data"]; // for jQuery POST
468
469
470 // check for any caller overrides
471 if(opts != null) {
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 // for get-meta operations, go directly through metadata-server.pl
505 // for set-meta ops, should go via GS3 authentication, which is off the GS3 library servlet
506 url = (_modifyingMeta) ? gs.xsltParams.library_name : "cgi-bin/metadata-server.pl";
507
508 } else { // uses data encoded into URL, rather than a data structure.
509 data = null; // we're using the URL as payload, don't duplicate the payload to be transmitted into data
510
511 url = payload["url"]; // payload["url"] contains the URL + data encoded in URL form
512 // URL is already correct for get-meta vs meta-modification operations.
513 // For meta-modification ops, it will through GS3 authentication first rather than metadata-server.pl
514
515 }
516
517 // finally, can do the AJAX call
518
519 //console.log("*** Away to call: " + url);
520 var ajaxResponse = async_setting ? "*** No response received yet, async ajax request" : null;
521
522
523 if(_use_jQuery_ajax_not_gsajaxapi) {
524 // ajax calls default to using method GET, we want to do POST operations for get-meta and set-meta requests
525 // since get-meta-array and especially set-meta-array can be large, e.g. for user comments.
526 $.ajax({url: url, async: async_setting, type: method, data: data})
527 .success(function(response) {
528 ajaxResponse = response;
529// console.log("** (" + callingFunction + ") Response received from server: " + ajaxResponse);
530
531 //var xml = $.parseXML(response);
532 //console.log(xml);
533
534 if(successResponseFunction != null) {
535
536 successResponseFunction(response);
537 }
538 })
539 .error(function() {
540 if(errorResponseFunction != null) {
541 errorResponseFunction(response);
542 } else {
543 console.log("(" + callingFunction + ") Failed");
544 }
545 });
546 }
547 else {
548 // USES GSAJAXAPI.JS to do AJAX. In this case, the payload must be in URL form
549
550 var splitURL = url.split("?");
551 url = splitURL[0]; // base URL
552 var params = splitURL[1]; // query-string
553
554 // Don't need to delete objects created with 'new' in JavaScript. Garbage collection will do it.
555 // http://stackoverflow.com/questions/4869712/new-without-delete-on-same-variable-in-javascript
556 var gsapi = new GSAjaxAPI(url);
557
558 // ajax calls default to using method GET, we want to do POST operations for get-meta and set-meta requests
559 // since get-meta-array and especially set-meta-array can be large, e.g. for user comments.
560
561 if(async_setting) {
562 gsapi.urlPostAsync(url, params, successResponseFunction);
563 } else {
564 ajaxResponse = gsapi.urlPostSync(url, params);
565 ajaxResponse = ajaxResponse;
566 }
567
568// console.log("*** (" + callingFunction + ") Response from server: " + ajaxResponse);
569
570 }
571
572// console.log("*** Finished ajax call to: " + url);
573// console.log("*** Got response: " + ajaxResponse);
574
575 return ajaxResponse;
576}
577
578// Prepare the payload (data package) to transmit to metadataserver.pl over AJAX.
579// These next 2 functions prepare both the URL version of the payload and the data object version of
580// of the payload. Then calling functions, and the _callMetadataServer() function they call, will control
581// and determine which of the two forms ultimately gets used.
582// (Constructing both URL and data structure, as I could not successfully convert old URL way to data structure
583// http://stackoverflow.com/questions/8648892/convert-url-parameters-to-a-javascript-object)
584gs.functions.getBasicDataForMetadataServer = function(metaServerCommand, collection, site, documentID, metadataName,
585 metamode, metadataValue, prevMetadataValue, metadataPosition)
586{
587 // if we're doing set- or remove- metadata operations,
588 // then we need change the data params that will make up the query string
589 // to make sure we go through GS3's authentication
590 // 1. prefix meta names with s1,
591 // 2. use s1.collection for collectionName since c is a special param name for GS2Construct
592 // 3. Additional parameters for rerouting through Authentication: a=g&rt=r&ro=1&s=ModifyMetadata
593
594 var modifyingMeta = false;
595 var prefix = "";
596 var colPropName = "c";
597 var baseURL = "cgi-bin/metadata-server.pl?";
598
599 // if we need authentication:
600 if(metaServerCommand.indexOf("set-") != -1 || metaServerCommand.indexOf("remove-") != -1) {
601 modifyingMeta = true;
602 prefix = "s1.";
603 colPropName = prefix+"collection"; // "s1.collection"
604 baseURL = gs.xsltParams.library_name + "?a=g&rt=r&ro=1&s=ModifyMetadata&";
605 }
606
607
608 // 1. when using jQuery to POST, need to invoke AJAX with a data structure rather than a URL
609 var data = {};
610
611 // customizable portion of ajax call
612 data[prefix+"a"] = metaServerCommand;
613 data[colPropName] = collection;
614 data[prefix+"site"] = site;
615 data[prefix+"d"] = documentID;
616 data[prefix+"metaname"] = metadataName;
617 data[prefix+"metapos"] = metadataPosition;
618 data[prefix+"metavalue"] = metadataValue;
619 data[prefix+"prevmetavalue"] = prevMetadataValue;
620 data[prefix+"metamode"] = metamode;
621
622 if(modifyingMeta) {
623 // fixed portion of url: add the a=g&rt=r&ro=1&s=ModifyMetadata part of the GS3 URL for
624 // going through authentication. Don't prefix "s1." to these!
625 data["a"] = "g";
626 data["rt"] = "r";
627 data["ro"] = "1";
628 data["s"] = "ModifyMetadata";
629 }
630
631 // 2. Construct the URL version of the metadata-server.pl operation:
632 // for GET requests, the URL can contain the data.
633 // Regular JavaScript AJAX code in gsajaxapi.js can also POST data in URL form, but not jQuery's .ajax().
634
635
636 // 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).
637 // From:
638 // <gs3server>/cgi-bin/metadata-server.pl?a=set-archives-metadata&c=smallcol&site=localsite&d=HASH01454f31011f6b6b26eaf8d7&metaname=Title&metavalue=Moo&prevmetavalue=Blabla&metamode=override
639 // To:
640 // <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
641
642 var extraParams = "";
643
644 if(metadataValue != null) {
645 extraParams += "&"+prefix+"metavalue=" + metadataValue;
646 }
647
648 if(metadataPosition != null)
649 {
650 extraParams += "&"+prefix+"metapos=" + metadataPosition;
651 }
652
653 if(prevMetadataValue != null) {
654 extraParams += "&"+prefix+"prevmetavalue=" + prevMetadataValue;
655 }
656
657 var url = baseURL + prefix+"a=" + metaServerCommand + "&"+colPropName+"=" + collection + "&"+prefix+"site=" + site + "&"+prefix+"d=" + documentID + "&"+prefix+"metaname=" + metadataName + extraParams + "&"+prefix+"metamode=" + metamode;
658
659 // 3. Return both the constructed url & data variants of the payload to be transmitted over ajax
660 var payload = {
661 url: url,
662 data: data
663 };
664
665 return payload;
666}
667
668// See description for getBasicDataForMetadataServer()
669gs.functions.getComplexDataForMetadataServer = function(metaServerCommand, collection, site, docArray, metamode, where)
670{
671 var docArrayJSON = JSON.stringify(docArray);
672
673 // if we're doing set- or remove- metadata operations,
674 // then we need change the data params that will make up the query string
675 // to make sure we go through GS3's authentication
676 // 1. prefix meta names with s1,
677 // 2. use s1.collection for collectionName since c is a special param name for GS2Construct
678 // 3. Additional parameters for rerouting through Authentication: a=g&rt=r&ro=1&s=ModifyMetadata
679
680 var modifyingMeta = false;
681 var prefix = "";
682 var colPropName = "c";
683 var baseURL = "cgi-bin/metadata-server.pl?";
684
685 // if we need authentication:
686 if(metaServerCommand.indexOf("set-") != -1 || metaServerCommand.indexOf("remove-") != -1) {
687 modifyingMeta = true;
688 prefix = "s1.";
689 colPropName = prefix+"collection"; // "s1.collection"
690 baseURL = gs.xsltParams.library_name + "?a=g&rt=r&ro=1&s=ModifyMetadata&";
691 }
692
693 // 1. when using jQuery to POST, need to invoke AJAX with a data structure rather than a URL
694 var data = {};
695
696 // customizable portion of ajax call
697 data[prefix+"a"] = metaServerCommand;
698 data[colPropName] = collection;
699 data[prefix+"site"] = site;
700 data[prefix+"json"] = docArrayJSON;
701
702 if(where != null) {
703 data[prefix+"where"] = where;
704 }
705 if (metamode!=null) {
706 data[prefix+"metamode"] = metamode;
707 }
708
709 if(modifyingMeta) {
710 // fixed portion of url: add the a=g&rt=r&ro=1&s=ModifyMetadata part of the GS3 URL for
711 // going through authentication. Don't prefix "s1." to these!
712 data["a"] = "g";
713 data["rt"] = "r";
714 data["ro"] = "1";
715 data["s"] = "ModifyMetadata";
716 }
717
718
719 // 2. URL for when doing AJAX in URL mode. GET with jQuery allows the data to be part of the URL, but
720 // not jQuery POST. But our regular JavaScript AJAX code in gsajaxapi.js allows GET and POST with URLs
721 // containing the data.
722
723 var params = prefix+"a=" + escape(metaServerCommand); //"a=set-metadata-array";
724 if(where != null) {
725 params += "&"+prefix+"where=" + escape(where); // if where not specified, meta-server will default to setting index meta
726 //} else {
727 // params += "&"+prefix+"where=import|archives|index";
728 }
729 params += "&"+colPropName+"="+escape(collection);
730 params += "&"+prefix+"site="+escape(site);
731 params += "&"+prefix+"json="+escape(docArrayJSON);
732
733 if (metamode!=null) {
734 params += "&"+prefix+"metamode=" + escape(metamode);
735 }
736
737 // 3. Return both the constructed url & data variants of the payload to be transmitted over ajax
738 var payload = {
739 url: baseURL + params,
740 data: data
741 };
742
743 return payload;
744}
745
746/*************************
747* SET METADATA FUNCTIONS *
748*************************/
749
750gs.functions.setImportMetadata = function(collection, site, documentID, metadataName, metadataValue, prevMetadataValue, metamode, successResponseFunction, errorResponseFunction)
751{
752 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
753
754 gs.functions._callMetadataServer(
755 "setImportMetadata",
756 gs.functions.getBasicDataForMetadataServer("set-import-metadata", collection, site, documentID, metadataName, metamode, metadataValue, prevMetadataValue, null /*metapos*/),
757 successResponseFunction,
758 errorResponseFunction);
759
760}
761
762gs.functions.setArchivesMetadata = function(collection, site, documentID, metadataName, metadataPosition, metadataValue, prevMetadataValue, metamode, successResponseFunction, errorResponseFunction)
763{
764 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
765
766 if(metadataPosition != null) {
767 prevMetadataValue = null; // to force the same ultimate behaviour as in the old version of this code
768 }
769
770 gs.functions._callMetadataServer(
771 "setArchivesMetadata",
772 gs.functions.getBasicDataForMetadataServer("set-archives-metadata", collection, site, documentID, metadataName, metamode, metadataValue, prevMetadataValue, metadataPosition),
773 successResponseFunction,
774 errorResponseFunction);
775
776}
777
778gs.functions.setIndexMetadata = function(collection, site, documentID, metadataName, metadataPosition, metadataValue, prevMetadataValue, metamode, successResponseFunction, errorResponseFunction)
779{
780 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
781
782 if(metadataPosition != null) {
783 prevMetadataValue = null; // to force the same ultimate behaviour as in the old version of this code
784 }
785
786 // old version of this function would only call _callMetadataServer if either metapos
787 // or prevMetaValue had a value. So sticking to the same behaviour in rewriting this function.
788 if(metadataPosition != null || prevMetadataValue != null) {
789
790 gs.functions._callMetadataServer(
791 "setIndexMetadata",
792 gs.functions.getBasicDataForMetadataServer("set-metadata", collection, site, documentID, metadataName, metamode, metadataValue, prevMetadataValue, metadataPosition),
793 successResponseFunction,
794 errorResponseFunction);
795 }
796}
797
798gs.functions.setMetadata = function(collection, site, documentID, metadataName, metadataValue, metamode, successResponseFunction, errorResponseFunction)
799{
800 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
801
802 var nameArray = ["setImportMetadata", "setArchivesMetadata", "setIndexMetadata"];
803 var functionArray = ["set-import-metadata", "set-archives-metadata", "set-metadata"];
804
805 for(var i = 0; i < nameArray.length; i++)
806 {
807 // previous version of this function did not allow setting metapos or prevMetavalue
808 // so leaving the behaviour the same along with function signature.
809 gs.functions._callMetadataServer(
810 nameArray[i],
811 gs.functions.getBasicDataForMetadataServer(functionArray[i], collection, site, documentID, metadataName, metamode, metadataValue, null /*prevMetadataValue*/, null /*metadataPosition*/),
812 successResponseFunction,
813 errorResponseFunction);
814 }
815}
816
817// New. Modified version of the GS2 version of this method in gsajaxapi.js.
818// The where parameter can be specified as one or more of: import, archives, index, live
819// separated by |. If null, it is assumed to be index which is the original default
820// behaviour of calling set-metadata-array. E.g. where=import|archives|index
821// THIS METHOD IS SYNCHRONOUS by default. Set forceSync to false to override this default behaviour
822gs.functions.setMetadataArray = function(collection, site, docArray, metamode, where, successResponseFunction, forceSync, errorResponseFunction)
823{
824 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
825
826 var payload = gs.functions.getComplexDataForMetadataServer("set-metadata-array", collection, site, docArray, metamode, where);
827
828 // set operations are generally synchronous, but allow calling function to force ajax call
829 // to be synchronous or not. Default is synchronous, as it was for GS2
830 if(forceSync == null) {
831 forceSync = true;
832 }
833
834 //console.log("cgi-bin/metadata-server.pl?"+params);
835
836 var response = gs.functions._callMetadataServer("Setting metadata in "+where, payload, successResponseFunction, errorResponseFunction, {"forceSync": forceSync, "requestMethod": "POST"});
837
838 return response;
839}
840
841
842/*************************
843* GET METADATA FUNCTIONS *
844*************************/
845
846// New. Modified version of the GS2 version of this method in gsajaxapi.js.
847// See description for setMetadataArray above for information about the 'where' parameter.
848// THIS METHOD IS SYNCHRONOUS BY DEFAULT. Set forceSync to false to override this default behaviour
849gs.functions.getMetadataArray = function(collection, site, docArray, 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("get-metadata-array", collection, site, docArray, null /*metamode*/, where);
854
855 // get operations are generally asynchronous, but allow calling function to force ajax call
856 // to be synchronous or not. Default for get-metadata-array is synchronous, as it was for GS2
857 if(forceSync == null) {
858 forceSync = true;
859 }
860 // Objects/maps can use identifiers or strings for property names
861 // http://stackoverflow.com/questions/456177/function-overloading-in-javascript-best-practices
862 // https://www.w3schools.com/js/js_objects.asp
863 var response = gs.functions._callMetadataServer("Getting metadata from "+where, payload, successResponseFunction, errorResponseFunction, {"forceSync":forceSync, "requestMethod": "POST"});
864
865 return response;
866}
867
868
869gs.functions.getImportMetadata = function(collection, site, documentID, metadataName, successResponseFunction, errorResponseFunction)
870{
871 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
872
873 var payload = gs.functions.getBasicDataForMetadataServer("get-import-metadata", collection, site, documentID, metadataName);
874 gs.functions._callMetadataServer("getImportMetadata", payload, function(responseText) {
875 var metadata = new GSMetadata(collection, site, documentID, metadataName, null, null, responseText);
876 if(successResponseFunction != null)
877 {
878 successResponseFunction(metadata);
879 }
880 },
881 errorResponseFunction);
882}
883
884gs.functions.getArchivesMetadata = function(collection, site, documentID, metadataName, metadataPosition, successResponseFunction, errorResponseFunction)
885{
886 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
887
888 var payload = gs.functions.getBasicDataForMetadataServer("get-archives-metadata", collection, site, documentID, metadataName, null /*metamode*/, null /*metavalue*/, null /*prevmetavalue*/, metadataPosition);
889
890 gs.functions._callMetadataServer("getArchivesMetadata", payload, function(responseText) {
891 var metadata = new GSMetadata(collection, site, documentID, metadataName, null, metadataPosition, responseText); // indexPos, archivesPos, metaval (responseText)
892 if(successResponseFunction != null)
893 {
894 successResponseFunction(metadata);
895 }
896 },
897 errorResponseFunction);
898}
899
900gs.functions.getIndexMetadata = function(collection, site, documentID, metadataName, metadataPosition, successResponseFunction, errorResponseFunction)
901{
902 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
903
904 var payload = gs.functions.getBasicDataForMetadataServer("get-metadata", collection, site, documentID, metadataName, null /*metamode*/, null /*metavalue*/, null /*prevmetavalue*/, metadataPosition);
905
906 gs.functions._callMetadataServer("getIndexMetadata", payload, function(responseText) {
907 var metadata = new GSMetadata(collection, site, documentID, metadataName, metadataPosition, null, responseText); // indexPos, archivesPos, metaval (responseText)
908 if(successResponseFunction != null)
909 {
910 successResponseFunction(metadata);
911 }
912 },
913 errorResponseFunction);
914}
915
916/****************************
917* REMOVE METADATA FUNCTIONS *
918****************************/
919
920gs.functions.removeImportMetadata = function(collection, site, documentID, metadataName, metadataValue, successResponseFunction, errorResponseFunction)
921{
922 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
923
924 gs.functions._callMetadataServer(
925 "removeImportMetadata",
926 gs.functions.getBasicDataForMetadataServer("remove-import-metadata", collection, site, documentID, metadataName, null /*metamode*/, metadataValue, null /*prevmetavalue*/, null /*metapos*/),
927 successResponseFunction,
928 errorResponseFunction);
929}
930
931gs.functions.removeArchivesMetadata = function(collection, site, documentID, metadataName, metadataPosition, metadataValue, successResponseFunction, errorResponseFunction)
932{
933 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
934
935 if(metadataPosition != null) {
936 metadataValue = null; // retaining behaviour of previous version of this function removeArchivesMetadata()
937 }
938
939 gs.functions._callMetadataServer(
940 "removeArchiveMetadata",
941 gs.functions.getBasicDataForMetadataServer("remove-archives-metadata", collection, site, documentID, metadataName, null /*metamode*/, metadataValue, null /*prevmetavalue*/, metadataPosition),
942 successResponseFunction,
943 errorResponseFunction);
944}
945
946gs.functions.removeIndexMetadata = function(collection, site, documentID, metadataName, metadataPosition, metadataValue, successResponseFunction, errorResponseFunction)
947{
948 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
949
950 if(metadataPosition != null) {
951 metadataValue = null; // retaining behaviour of previous version of this function removeIndexMetadata()
952 }
953
954 gs.functions._callMetadataServer(
955 "removeIndexMetadata",
956 gs.functions.getBasicDataForMetadataServer("remove-metadata", collection, site, documentID, metadataName, null /*metamode*/, metadataValue, null /*prevmetavalue*/, metadataPosition),
957 successResponseFunction,
958 errorResponseFunction);
959}
960
961gs.functions.removeMetadata = function(collection, site, documentID, metadataName, metadataValue, successResponseFunction, errorResponseFunction)
962{
963 if( typeof errorResponseFunction === 'undefined' ) { errorResponseFunction = null; } // force error callback to be defined: either null or has value
964
965 var nameArray = ["removeImportMetadata", "removeArchivesMetadata", "removeIndexMetadata"];
966 var functionArray = ["remove-import-metadata", "remove-archives-metadata", "remove-metadata"];
967
968 for(var i = 0; i < nameArray.length; i++)
969 {
970 gs.functions._callMetadataServer(
971 nameArray[i],
972 gs.functions.getBasicDataForMetadataServer(functionArray[i], collection, site, documentID, metadataName, null /*metamode*/, metadataValue, null /*prevmetavalue*/, null /*metapos*/),
973 successResponseFunction,
974 errorResponseFunction);
975 }
976}
977
Note: See TracBrowser for help on using the repository browser.