source: main/trunk/greenstone3/web/interfaces/default/js/documentedit_scripts_util.js@ 32770

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

Edit Map GPS and Hide Map GPS buttons

  • Property svn:executable set to *
File size: 38.2 KB
Line 
1/** Javascript file containing useful functions used by both documentedit_scripts.js and documentmaker_scripts.js */
2
3
4//Some "constants" to match the server constants
5var SUCCESS = 1;
6var ACCEPTED = 2;
7var ERROR = 3;
8var CONTINUING = 10;
9var COMPLETED = 11;
10var HALTED = 12;
11
12var _transactions = new Array();
13var _collectionsToBuild = new Array();
14var _allContents = new Array();
15var _deletedSections = new Array();
16var _deletedMetadata = new Array();
17var _undoOperations = new Array();
18var _baseURL;
19var _statusBar;
20var _metadataSetList = new Array();
21
22
23// If the user is attempting to leave the page, check if there are unsaved changes
24// and if so, display an "Are you sure you want to leave" message.
25// https://stackoverflow.com/questions/7080269/javascript-before-leaving-the-page
26// Newer versions of Firefox/Chrome don't display custom message (security feature):
27// https://stackoverflow.com/questions/22776544/why-is-jquery-onbeforeunload-not-working-in-chrome-and-firefox
28// and http://jsfiddle.net/XZAWS/
29// jquery bind() is deprecated: https://stackoverflow.com/questions/33654716/is-jquery-bind-deprecated
30$(window).on("beforeunload", function(event) {
31
32 if(gs.cgiParams.docEdit == "1") { // like document.xsl, which checks the same var upon onload
33 // shouldn't check for whether changes are saved unless on Doc Editing page (DocEdit=1)
34 // else the following pop up always ends up appearing when attempting
35 // to leave a doc view page in Doc Editing Mode (when not yet actually Doc Editing)
36 var changes = changesToUpdate();
37
38 if(changes.length > 0) {
39 console.log("The collection hasn't yet been saved after editing. Are you sure you want to leave?");
40 return "The collection hasn't yet been saved after editing. Are you sure you want to leave?";
41 }
42 }
43
44});
45
46
47function encodeDelimiters(meta_value) {
48
49 var new_value = meta_value.replace(/;/g, "%253B");
50 return new_value.replace(/&/g, "%2526");
51}
52
53function getElementsByClassName(cl, parent)
54{
55 var elemArray = [];
56 var classRegEx = new RegExp("\\b" + cl + "\\b");
57 var elems;
58 if(parent)
59 {
60 elems = parent.getElementsByTagName("*");
61 }
62 else
63 {
64 elems = document.getElementsByTagName("*");
65 }
66
67 for (var i = 0; i < elems.length; i++)
68 {
69 var classeName = elems[i].className;
70 if (classRegEx.test(classeName)) elemArray.push(elems[i]);
71 }
72
73 return elemArray;
74};
75
76function getNextSiblingOfType(elem, type)
77{
78 if(elem == null)
79 {
80 return null;
81 }
82
83 var current = elem.nextSibling;
84 while(current != null)
85 {
86 if(current.nodeName.toLowerCase() == type)
87 {
88 return current;
89 }
90
91 current = current.nextSibling;
92 }
93 return null;
94}
95
96function getPrevSiblingOfType(elem, type)
97{
98 if(elem == null)
99 {
100 return null;
101 }
102
103 var current = elem.previousSibling;
104 while(current != null)
105 {
106 if(current.nodeName.toLowerCase() == type)
107 {
108 return current;
109 }
110
111 current = current.previousSibling;
112 }
113 return null;
114}
115
116function saveTransaction(transaction)
117{
118 console.log(transaction);
119 _transactions.push(transaction);
120}
121
122function undo()
123{
124 if(_undoOperations.length == 0)
125 {
126 return;
127 }
128
129 var undoOp = _undoOperations.pop();
130
131 //Create/Duplicate undo
132 if(undoOp.op == "del")
133 {
134 if(undoOp.srcElem.childList)
135 {
136 removeFromParent(undoOp.srcElem.childList);
137 }
138 if(undoOp.srcElem.parentItem)
139 {
140 undoOp.srcElem.parentItem.menu.newSectionLink.style.display = "inline";
141 undoOp.srcElem.parentItem.childList = null;
142 }
143 removeFromParent(undoOp.srcElem);
144 }
145
146 if(undoOp.op == "delMeta")
147 {
148 if(undoOp.srcElem.childList)
149 {
150 removeFromParent(undoOp.srcElem.childList);
151 }
152 if(undoOp.srcElem.parentItem)
153 {
154 undoOp.srcElem.parentItem.menu.newSectionLink.style.display = "inline";
155 undoOp.srcElem.parentItem.childList = null;
156 }
157 de.doc.unregisterEditSection(undoOp.srcElem);
158 removeFromParent(undoOp.srcElem);
159 }
160
161 //Move undo (mva is move after, mvb is move before, mvi is move into)
162 else if(undoOp.op == "mva" || undoOp.op == "mvb" || undoOp.op == "mvi")
163 {
164 if(undoOp.op == "mvb")
165 {
166 undoOp.refElem.parentNode.insertBefore(undoOp.srcElem, undoOp.refElem);
167 }
168 else if(undoOp.op == "mva")
169 {
170 insertAfter(undoOp.srcElem, undoOp.refElem);
171 }
172 else
173 {
174 undoOp.refElem.removeChild(undoOp.refElem.firstChild);
175 undoOp.refElem.appendChild(undoOp.srcElem);
176 }
177
178 if(undoOp.srcElem.textDiv)
179 {
180 insertAfter(undoOp.srcElem.textDiv, undoOp.srcElem);
181 }
182 if(undoOp.srcElem.childList)
183 {
184 insertAfter(undoOp.srcElem.childList, undoOp.srcElem.textDiv);
185 }
186
187 if(undoOp.srcElem.onmouseout)
188 {
189 //Uncolour the section if it coloured
190 undoOp.srcElem.onmouseout();
191 }
192 updateFromTop();
193 }
194 else if(undoOp.op == "display")
195 {
196 undoOp.srcElem.style.display = undoOp.subOp;
197 }
198
199 if(undoOp.removeDeletedMetadata)
200 {
201 _deletedMetadata.pop();
202 }
203
204 if(undoOp.removeTransaction)
205 {
206 _transactions.pop();
207 }
208}
209
210function enableSaveButtons(enabled) {
211 if (enabled) {
212 $("#saveButton, #quickSaveButton").html(gs.text.de.save_changes);
213 $("#saveButton, #quickSaveButton").removeAttr("disabled");
214
215 } else {
216 $("#saveButton, #quickSaveButton").html(gs.text.de.saving + "...");
217 $("#saveButton, #quickSaveButton").attr("disabled", "disabled");
218
219 }
220}
221function addCollectionToBuild(collection)
222{
223 for(var i = 0; i < _collectionsToBuild.length; i++)
224 {
225 if(collection == _collectionsToBuild[i])
226 {
227 return;
228 }
229 }
230 _collectionsToBuild.push(collection);
231}
232
233function save() {
234 saveAndRebuild(false);
235}
236
237function rebuildCurrentCollection() {
238
239 console.log(gs.text.de.rebuilding_collection);
240 enableSaveButtons(false);
241 var collection = gs.cgiParams.c;
242
243 var collectionsArray = new Array();
244 collectionsArray.push(collection);
245 buildCollections(collectionsArray, null, reloadUponRebuild); // passing in callback to reload the page after build, as requested by Kathy
246}
247
248
249function reloadUponRebuild() {
250 // finished rebuilding - reload the page after rebuild, but first
251 // clear transactions array of saved changes, now that we're done processing these changes during rebuild,
252 // since we don't want the "are you sure to leave page" popup which appears on _transactions array being non-empty
253 _transactions = null;
254 location.reload(true); // force reload, not from cache, https://www.w3schools.com/jsref/met_loc_reload.asp
255}
256
257/************************************
258* TEXT EDIT (CKEDITOR) SCRIPTS *
259**************************************/
260
261// not using this anymore as the instanceready never seems to get called
262function addCKEEditableState(evt,stateArray)
263{
264 // Event->Editor->CKE DOM Inline Element that editor was for->underlying jquery element
265 element = evt.editor.element.$;
266 nodeText = element.innerHTML;
267 stateArray.push({
268 editableNode : element,
269 initHTML : nodeText
270 });
271}
272
273function addEditableState(editable,stateArray)
274{
275
276 if(editable.tagName == 'TEXTAREA')
277 {
278 nodeText = editable.value;
279 }
280 else
281 {
282 nodeText = editable.innerHTML;
283 }
284
285 stateArray.push({
286 editableNode : editable,
287 initHTML : nodeText
288 });
289
290}
291
292function getLastEditableStates()
293{
294 editableLastStates = [];
295 $(".sectionText").each(function(){addEditableState(this,editableLastStates);});
296 $(".metaTableCellArea").each(function(){addEditableState(this,editableLastStates);});
297
298}
299
300function changesToUpdate()
301{
302 var resultArray = new Array();
303 getLastEditableStates();
304 for (var j in editableLastStates)
305 {
306 if (isNodeChanged(editableLastStates[j]))
307 {
308 resultArray.push(editableLastStates[j].editableNode);
309 }
310 }
311 return resultArray;
312}
313
314
315function isNodeChanged(StateToCheck){
316 for (var i in editableInitStates)
317 {
318 if ((StateToCheck.editableNode === editableInitStates[i].editableNode)) {
319 if ( StateToCheck.initHTML === editableInitStates[i].initHTML )
320 {
321 return false;
322 }
323 //console.log("current="+StateToCheck.initHTML);
324 //console.log("init="+editableInitStates[i].initHTML);
325 return true;
326 }
327
328 }
329 // if get here, this must be a new node, as wasn't in init states
330 // make sure its not empty - we won't add empty nodes.
331 if (StateToCheck.initHTML == "") {
332 return false;
333 }
334
335 return true;
336
337}
338
339
340function saveAndRebuild(rebuild)
341{
342//This works in most cases but will not work when taking a doc from one collection to another, will need to be fixed at some point
343 var collection;
344 if(gs.cgiParams.c && gs.cgiParams.c != "") {
345
346 collection = gs.cgiParams.c;
347 }
348 else {
349 collection = gs.cgiParams.p_c;
350 }
351
352 var sendBuildRequest = function()
353 {
354 var request = "[";
355 for(var i = 0; i < _transactions.length; i++)
356 {
357 request += _transactions[i];
358 if(i != _transactions.length - 1)
359 {
360 request += ",";
361 }
362 }
363 request += "]";
364
365 var statusID;
366 var ajax = new gs.functions.ajaxRequest();
367 ajax.open("POST", gs.xsltParams.library_name, true);
368 ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
369 ajax.onreadystatechange = function()
370 {
371 if(ajax.readyState == 4 && ajax.status == 200)
372 {
373 var text = ajax.responseText;
374 var xml = validateXML(text);
375
376 var errorElems;
377 if(!xml || checkForErrors(xml))
378 {
379 alert(gs.text.dse.error_saving);
380
381 enableSaveButtons(true);
382
383 if(_statusBar)
384 {
385 _statusBar.removeStatus(statusID);
386 }
387 return;
388 }
389
390 if(_statusBar)
391 {
392 _statusBar.removeStatus(statusID);
393 }
394 if (rebuild) {
395 buildCollections(_collectionsToBuild, null, reloadUponRebuild);
396 } else {
397 // reset the save button here
398 enableSaveButtons(true);
399 // saving to archives is now done, clear the transactions
400 // that were keeping track of the full text changes that have now
401 // been performed to archives (no member var keeps track of meta changes, only a local var)
402 _transactions = new Array();
403 }
404 }
405 }
406
407 if(_collectionsToBuild.length > 0)
408 {
409 enableSaveButtons(false);
410
411 if(_statusBar)
412 {
413 statusID = _statusBar.addStatus(gs.text.dse.modifying_archives + "...");
414 }
415 ajax.send("a=g&rt=r&s=DocumentExecuteTransaction&s1.transactions=" + request);
416 }
417 } // end sendBuildRequest definition
418
419 var metadataChanges = new Array();
420 if (_deletedMetadata.length > 0) {
421 //addCollectionToBuild(collection);
422
423 for(var i = 0; i < _deletedMetadata.length; i++) {
424
425 var currentRow = _deletedMetadata[i];
426
427 //Get document ID
428 var currentElem = currentRow;
429 while((currentElem = currentElem.parentNode).tagName != "TABLE");
430 var docID = currentElem.getAttribute("id").substring(4);
431
432 //Get metadata name
433 var cells = currentRow.getElementsByTagName("TD");
434 var nameCell = cells[0];
435 // metadata name cell might have the multivalue indicator in it, so just want the first word
436 var name = nameCell.innerHTML.split(" ")[0];
437 var valueCell = cells[1];
438 var value = valueCell.getElementsByTagName("TEXTAREA")[0].value;
439 if (value.length) {
440 // check for non empty value, in case all they have done is add a field then deleted it.
441 metadataChanges.push({type:'delete', docID:docID, name:name, value:value});
442 addCollectionToBuild(collection);
443 }
444 removeFromParent(currentRow);
445 }
446 }
447
448 var changes = changesToUpdate();
449 //Clean changes
450 editableInitStates = editableLastStates;
451 for(var i = 0; i < changes.length; i++)
452 {
453 var changedElem = changes[i];
454 //Save metadata
455 if(gs.functions.hasClass(changedElem, "metaTableCellArea"))
456 {
457 //Get document ID
458 var currentElem = changedElem;
459 while((currentElem = currentElem.parentNode).tagName != "TABLE");
460 var docID = currentElem.getAttribute("id").substring(4);
461
462 //Get metadata name
463 var row = changedElem.parentNode.parentNode;
464 var cells = row.getElementsByTagName("TD");
465 var nameCell = cells[0];
466 // metadata name cell might have the multivalue indicator in it, so just want the first word
467 var name = nameCell.innerHTML.split(" ")[0];
468 var value = changedElem.value;
469 value = value.replace(/&nbsp;/g, " ");
470
471 var orig = changedElem.originalValue;
472 if (orig) {
473 orig = orig.replace(/&nbsp;/g, " ");
474 }
475 if (jQuery.inArray(name, multiValuedMetadata) != -1) {
476
477 // split the values
478 var values_list = value.split(mvm_delimiter);
479 var orig_list;
480 var num_orig;
481 if (orig) {
482 orig_list = orig.split(mvm_delimiter);
483 num_orig = orig_list.length;
484 }
485
486 for(var i = 0; i < values_list.length; i++) {
487 var val = values_list[i];
488 var ori =null;
489 if (orig && i<num_orig) {
490 ori = orig_list[i];
491 }
492 metadataChanges.push({collection:collection, docID:docID, name:name, value:val, orig:ori});
493 }
494 } else {
495 metadataChanges.push({collection:collection, docID:docID, name:name, value:value, orig:orig});
496 }
497 changedElem.originalValue = changedElem.value;
498 addCollectionToBuild(collection);
499 }
500 //Save content
501 else if(gs.functions.hasClass(changedElem, "renderedText"))
502 {
503 var section = changedElem.parentDiv.parentItem;
504 saveTransaction('{"operation":"setText", "text":"' + CKEDITOR.instances[changedElem.getAttribute("id")].getData().replace(/%/g, "%25").replace(/"/g, "\\\"").replace(/&/g, "%26") + '", "collection":"' + section.collection + '", "oid":"' + section.nodeID + '"}'); //'
505 addCollectionToBuild(section.collection);
506 }
507 else if(gs.functions.hasClass(changedElem, "sectionText"))
508 {
509 var id = changedElem.getAttribute("id");
510 var sectionID = id.substring(4);
511 saveTransaction('{"operation":"setText", "text":"' + CKEDITOR.instances[changedElem.getAttribute("id")].getData().replace(/%/g, "%25").replace(/"/g, "\\\"").replace(/&/g, "%26") + '", "collection":"' + gs.cgiParams.c + '", "oid":"' + sectionID + '"}'); //'
512 addCollectionToBuild(gs.cgiParams.c);
513 }
514 }
515
516
517 var processChangesLoop = function(index)
518 {
519
520 var change = metadataChanges[index];
521
522 var callbackFunction;
523 if(index + 1 == metadataChanges.length)
524 {
525 callbackFunction = sendBuildRequest;
526 }
527 else
528 {
529 callbackFunction = function(){processChangesLoop(index + 1)};
530 }
531 if (change.type == "delete") {
532 gs.functions.removeArchivesMetadata(collection, gs.xsltParams.site_name, change.docID, change.name, null, encodeDelimiters(change.value), function(){callbackFunction();});
533 } else {
534 if(change.orig)
535 {
536 gs.functions.setArchivesMetadata(change.collection, gs.xsltParams.site_name, change.docID, change.name, null, encodeDelimiters(change.value), encodeDelimiters(change.orig), "override", function(){callbackFunction();});
537 }
538 else
539 {
540 gs.functions.setArchivesMetadata(change.collection, gs.xsltParams.site_name, change.docID, change.name, null, encodeDelimiters(change.value), null, "accumulate", function(){callbackFunction();});
541 }
542 }
543 }
544 if (metadataChanges.length>0) {
545 // this will process each change one by one, and then send the build request
546 processChangesLoop(0);
547 }
548 else if(_collectionsToBuild.length > 0) {
549 // if there are no metadata changes, but some other changes eg text have happened, then we need to send the build request.
550 sendBuildRequest();
551 }
552
553 /* need to clear the changes from the page so that we don't process them again next time */
554 while (_deletedMetadata.length>0) {
555 _deletedMetadata.pop();
556 }
557
558}
559
560
561function buildCollections(collections, documents, callback)
562{
563 if(!collections || collections.length == 0)
564 {
565 console.log(gs.text.dse.empty_collection_list);
566 enableSaveButtons(true);
567 return;
568 }
569
570 var docs = "";
571 var buildOperation = "";
572 if(documents)
573 {
574 buildOperation = "ImportCollection";
575 docs += "&s1.documents=";
576 for(var i = 0; i < documents.length; i++)
577 {
578 docs += documents[i];
579 if(i < documents.length - 1)
580 {
581 docs += ",";
582 }
583 }
584 }
585 else
586 {
587 buildOperation = "BuildAndActivateCollection";
588 }
589
590 var counter = 0;
591 var statusID = 0;
592 var buildFunction = function()
593 {
594 var ajax = new gs.functions.ajaxRequest();
595 ajax.open("GET", gs.xsltParams.library_name + "?a=g&rt=r&ro=1&s=" + buildOperation + "&s1.incremental=true&s1.collection=" + collections[counter] + docs);
596 ajax.onreadystatechange = function()
597 {
598 if(ajax.readyState == 4 && ajax.status == 200)
599 {
600 var text = ajax.responseText;
601 var xml = validateXML(text);
602
603 if(!xml || checkForErrors(xml))
604 {
605 alert(gs.text.dse.could_not_build_p1 + " " + collections[counter] + gs.text.dse.could_not_build_p2);
606
607 if(_statusBar)
608 {
609 _statusBar.removeStatus(statusID);
610 }
611 enableSaveButtons(true);
612
613 return;
614 }
615
616 var status = xml.getElementsByTagName("status")[0];
617 var pid = status.getAttribute("pid");
618
619 startCheckLoop(pid, buildOperation, statusID, function()
620 {
621 /*
622 var localAjax = new gs.functions.ajaxRequest();
623 localAjax.open("GET", gs.xsltParams.library_name + "?a=g&rt=r&ro=1&s=ActivateCollection&s1.collection=" + collections[counter], true);
624 localAjax.onreadystatechange = function()
625 {
626 if(localAjax.readyState == 4 && localAjax.status == 200)
627 {
628 var localText = localAjax.responseText;
629 var localXML = validateXML(localText);
630
631 if(!xml || checkForErrors(xml))
632 {
633 alert(gs.text.dse.could_not_activate_p1 + " " + collections[counter] + gs.text.dse.could_not_activate_p2);
634
635 if(_statusBar)
636 {
637 _statusBar.removeStatus(statusID);
638 }
639 enableSaveButtons(true);
640
641 return;
642 }
643
644 var localStatus = localXML.getElementsByTagName("status")[0];
645 if(localStatus)
646 {
647 var localPID = localStatus.getAttribute("pid");
648 startCheckLoop(localPID, "ActivateCollection", statusID, function()
649 {
650 */
651 if(counter == collections.length - 1)
652 {
653 removeCollectionsFromBuildList(collections);
654 if(callback)
655 {
656 callback();
657 }
658 }
659 else
660 {
661 counter++;
662 buildFunction();
663 }
664
665 _transactions = new Array();
666
667 if(_statusBar)
668 {
669 _statusBar.removeStatus(statusID);
670 }
671 enableSaveButtons(true);
672 /*
673 });
674 }
675 }
676 }
677 if(_statusBar)
678 {
679 _statusBar.changeStatus(statusID, gs.text.dse.activating + " " + collections[counter] + "...");
680 }
681 localAjax.send();
682 */
683 });
684 }
685 }
686 if(_statusBar)
687 {
688 statusID = _statusBar.addStatus(gs.text.dse.building + " " + collections[counter] + "...");
689 }
690 ajax.send();
691 }
692 buildFunction();
693}
694
695function startCheckLoop(pid, serverFunction, statusID, callbackFunction)
696{
697 var ajaxFunction = function()
698 {
699 var ajax = new gs.functions.ajaxRequest();
700 ajax.open("GET", gs.xsltParams.library_name + "?a=g&rt=s&ro=1&s=" + serverFunction + "&s1.pid=" + pid, true);
701 ajax.onreadystatechange = function()
702 {
703 if(ajax.readyState == 4 && ajax.status == 200)
704 {
705 var text = ajax.responseText;
706 var xml = validateXML(text);
707
708 if(!xml || checkForErrors(xml))
709 {
710 alert(gs.text.dse.could_not_check_status_p1 + " " + serverFunction + gs.text.dse.could_not_check_status_p2a);
711
712 if(_statusBar)
713 {
714 _statusBar.removeStatus(statusID);
715 }
716 enableSaveButtons(true);
717
718 return;
719 }
720
721 var status = xml.getElementsByTagName("status")[0];
722 var code = status.getAttribute("code");
723
724 if (code == COMPLETED || code == SUCCESS)
725 {
726 callbackFunction();
727 }
728 else if (code == HALTED || code == ERROR)
729 {
730 alert(gs.text.dse.could_not_check_status_p1 + " " + serverFunction + gs.text.dse.could_not_check_status_p2b);
731
732 if(_statusBar)
733 {
734 _statusBar.removeStatus(statusID);
735 }
736 enableSaveButtons(true);
737 }
738 else
739 {
740 setTimeout(ajaxFunction, 1000);
741 }
742 }
743 }
744 ajax.send();
745 }
746 ajaxFunction();
747}
748
749function removeCollectionsFromBuildList(collections)
750{
751 var tempArray = new Array();
752 for(var i = 0; i < _collectionsToBuild.length; i++)
753 {
754 var found = false;
755 for(var j = 0; j < collections.length; j++)
756 {
757 if(collections[j] == _collectionsToBuild[i])
758 {
759 found = true;
760 break;
761 }
762 }
763
764 if(!found)
765 {
766 tempArray.push(_collectionsToBuild[i]);
767 }
768 }
769 _collectionsToBuild = tempArray;
770}
771
772function checkForErrors(xml)
773{
774 var errorElems = xml.getElementsByTagName("error");
775
776 if(errorElems && errorElems.length > 0)
777 {
778 var errorString = gs.text.dse.error_saving_changes + ": ";
779 for(var i = 0; i < errorElems.length; i++)
780 {
781 errorString += " " + errorElems.item(i).firstChild.nodeValue;
782 }
783 alert(errorString);
784 return true;
785 }
786 return false; //No errors
787}
788
789function validateXML(txt)
790{
791 // code for IE
792 if (window.ActiveXObject)
793 {
794 var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
795 xmlDoc.async = "false";
796 xmlDoc.loadXML(document.all(txt).value);
797
798 if(xmlDoc.parseError.errorCode!=0)
799 {
800 txt = dse.error_code + ": " + xmlDoc.parseError.errorCode + "\n";
801 txt = txt + dse.error_reason + ": " + xmlDoc.parseError.reason;
802 txt = txt + dse.error_line + ": " + xmlDoc.parseError.line;
803 console.log(txt);
804 return null;
805 }
806
807 return xmlDoc;
808 }
809 // code for Mozilla, Firefox, Opera, etc.
810 else if (document.implementation.createDocument)
811 {
812 var parser = new DOMParser();
813 var xmlDoc = parser.parseFromString(txt,"text/xml");
814
815 if (xmlDoc.getElementsByTagName("parsererror").length > 0)
816 {
817 console.log(gs.text.dse.xml_error);
818 return null;
819 }
820
821 return xmlDoc;
822 }
823 else
824 {
825 console.log(gs.text.dse.browse_cannot_validate_xml);
826 }
827 return null;
828}
829
830function onVisibleMetadataSetChange()
831{
832 var metadataList = document.getElementById("metadataSetList");
833 var index = metadataList.selectedIndex;
834 var options = metadataList.getElementsByTagName("OPTION");
835 var selectedOption = options[index];
836
837 var selectedSet = selectedOption.value;
838 changeVisibleMetadata(selectedSet);
839}
840
841function changeVisibleMetadata(metadataSetName)
842{
843 var metaSetList = metadataSetName.split(",");
844 var tables = document.getElementsByTagName("TABLE");
845 for(var i = 0; i < tables.length; i++)
846 {
847 var id = tables[i].getAttribute("id");
848 if(id && id.search(/^meta/) != -1)
849 {
850 var rows = tables[i].getElementsByTagName("TR");
851 for(var j = 0; j < rows.length; j++)
852 {
853 if(metadataSetName == "All")
854 {
855 rows[j].style.display = "table-row";
856 }
857 else
858 {
859 var cells = rows[j].getElementsByTagName("TD");
860 // metadata name cell might have the multivalue indicator in it, so just want the first word
861 var cellName = cells[0].innerHTML.split(" ")[0];
862
863 if(cellName.indexOf(".") == -1)
864 {
865 rows[j].style.display = "none";
866 }
867 else
868 {
869 var setName = cellName.substring(0, cellName.lastIndexOf("."));
870 if (metaSetList.indexOf(setName)!= -1)
871 {
872 rows[j].style.display = "table-row";
873 }
874 else
875 {
876 rows[j].style.display = "none";
877 }
878 }
879 }
880 }
881 }
882 }
883}
884
885function asyncRegisterEditSection(cell)
886{
887 //This registering can cause a sizeable delay so we'll thread it (effectively) so the browser is not paused
888 cell.originalValue = cell.value;
889 setTimeout(function(){addEditableState(cell, editableInitStates)}, 0);
890}
891
892function addOptionToList(list, optionvalue, optiontext, selected) {
893 var newOption = $("<option>");
894 if (optiontext) {
895 newOption.html(optiontext);
896 newOption.attr("value", optionvalue);
897 } else {
898 newOption.html(optionvalue);
899 }
900 if (selected) {
901 newOption.attr("selected", true);
902 }
903 list.append(newOption);
904}
905
906/* returns either an input or a select element. Data based on
907 availableMetadataElements var. */
908function createMetadataElementSelector() {
909 var metaNameField;
910 if (new_metadata_field_input_type == "fixedlist") {
911 metaNameField = $("<select>", {"class": "ui-state-default"});
912 for(var i=0; i<availableMetadataElements.length; i++) {
913 addOptionToList(metaNameField, availableMetadataElements[i]);
914 }
915 return metaNameField;
916 }
917 metaNameField = $("<input>", {"type": "text","style":"margin: 5px; border: 1px solid #000;"});
918 if (new_metadata_field_input_type == "autocomplete") {
919 metaNameField.autocomplete({
920 minLength: 0,
921 source: availableMetadataElements
922 });
923 metaNameField.attr("title", gs.text.de.enter_meta_dropdwon); //"Enter a metadata name, or use the down arrow to select one, then click 'Add New Metadata'");
924 } else {
925 metaNameField.attr("title", gs.text.de.enter_meta_name); //"Enter a metadata name, then click 'Add New Metadata'");
926 }
927
928 return metaNameField;
929}
930
931function addFunctionalityToMapGPS(mapGPScontainer)
932{
933
934}
935
936function addFunctionalityToTable(table)
937{
938 table.find("tr").each(function()
939 {
940 var cells = $(this).find("td");
941 var metadataName = $(cells[0]).html();
942
943 if(dynamic_metadata_set_list == true && metadataName.indexOf(".") != -1)
944 {
945 var metadataSetName = metadataName.substring(0, metadataName.lastIndexOf("."));
946
947 var found = false;
948 for(var j = 0; j < _metadataSetList.length; j++)
949 {
950 if(metadataSetName == _metadataSetList[j])
951 {
952 found = true;
953 break;
954 }
955 }
956
957 if(!found)
958 {
959 _metadataSetList.push(metadataSetName);
960 addOptionToList( $("#metadataSetList"), metadataSetName);
961 }
962 }
963
964 asyncRegisterEditSection(cells[1].getElementsByTagName("textarea")[0]);
965 addRemoveLinkToRow(this);
966
967 // add multivalued indicator if needed
968 if (jQuery.inArray(metadataName, multiValuedMetadata) != -1) {
969 //if (multiValuedMetadata.includes(metadataName)){
970 $(cells[0]).html(metadataName + " <span title='"+gs.text.de.multi_valued_tooltip + "' style='float:right;'>"+mvm_delimiter+"</span>"); //Multi-valued metadata. Separate values with semi-colon ;
971 }
972
973 });
974
975 // set up autocomplete values
976 var value_cells = $(".metaTableCellArea");
977 for (var k=0; k<autocompleteMetadata.length; k++) {
978 var source_name = autocompleteMetadata[k].replace(/[\.-]/g, "");
979 var source_obj = window[source_name+"_values"];
980 if (source_obj) {
981 value_cells.filter("."+source_name).autocomplete({
982 minLength: 0,
983 source: source_obj
984 });
985 }
986 }
987
988 // add metadata field selector
989 var metaNameField = createMetadataElementSelector();
990 table.after(metaNameField);
991 table.metaNameField = metaNameField;
992
993 /* add the buttons */
994 // check enable_add_all_button - only valid for fixedlist and autocomplete
995 if (enable_add_all_metadata_button == true) {
996 if (new_metadata_field_input_type != "fixedlist" && new_metadata_field_input_type != "autocomplete") {
997 enable_add_all_metadata_button = false;
998 }
999 }
1000
1001 // add single metadata button
1002 var addRowButton = $("<button>",{"class": "ui-state-default ui-corner-all", "style": "margin: 5px;"});
1003
1004 addRowButton.html(gs.text.de.add_new_metadata);
1005 addRowButton.click(function()
1006 {
1007 var name = metaNameField.val();
1008 if(!name || name == "")
1009 {
1010 console.log(gs.text.de.no_meta_name_given);
1011 return;
1012 }
1013 addNewMetadataRow(table, name);
1014
1015
1016 });
1017 table.addRowButton = addRowButton;
1018 metaNameField.after(addRowButton);
1019
1020 // add all metadata button
1021 if (enable_add_all_metadata_button == true) {
1022 var addAllButton = $("<button>",{"class": "ui-state-default ui-corner-all", "style": "margin: 5px;"});
1023 addAllButton.html(gs.text.de.add_all_metadata);
1024 addAllButton.click(function()
1025 {
1026 for(var i=0; i<availableMetadataElements.length; i++) {
1027
1028 addNewMetadataRow(table, availableMetadataElements[i])
1029 }
1030
1031 });
1032 table.addAllButton = addAllButton;
1033 addRowButton.after(addAllButton);
1034
1035 }
1036
1037}
1038
1039function addNewMetadataRow(table, name) {
1040
1041 var clean_name = name.replace(/[\.-]/g, "");
1042 var newRow = $("<tr>", {"style": "display: table-row;"});
1043 var nameCell;
1044 if (jQuery.inArray(name, multiValuedMetadata) != -1) {
1045 nameCell = $("<td>" + name + " <span title='"+gs.text.de.multi_valued_tooltip + "' style='float:right;'>"+mvm_delimiter+"</span></td>");
1046 } else {
1047 nameCell = $("<td>" + name + "</td>");
1048 }
1049 nameCell.attr("class", "metaTableCellName");
1050 var valueCell = $("<td>", {"class": "metaTableCell"});
1051 var textValue = $("<textarea>", {"class": "metaTableCellArea "+ clean_name});
1052
1053 if (jQuery.inArray(name, autocompleteMetadata) != -1) {
1054 var source_obje = window[clean_name +"_values"];
1055 if (source_obje) {
1056 textValue.autocomplete({
1057 minLength: 0,
1058 source: source_obje
1059 });
1060 }
1061 }
1062 valueCell.append(textValue);
1063 newRow.append(nameCell);
1064 newRow.append(valueCell);
1065 addRemoveLinkToRow(newRow.get(0));
1066 table.append(newRow);
1067
1068 var undo = new Array();
1069 undo.op = "delMeta";
1070 undo.srcElem = newRow;
1071 undo.removeTransaction = false;
1072 _undoOperations.push(undo);
1073 if ( hierarchyStorage && hierarchyStorage[name])
1074 {
1075 setHierarchyEventsWrappers(name);
1076 }
1077}
1078
1079function addRemoveLinkToRow(row)
1080{
1081 var newCell = $("<td>");
1082 var removeLink = $("<a>"+gs.text.de.remove+"</a>", {"href": "javascript:;"});
1083 removeLink.click(function()
1084 {
1085 var undo = new Array();
1086 undo.srcElem = row;
1087 undo.op = "display";
1088 undo.subOp = "table-row";
1089 undo.removeDeletedMetadata = true;
1090 _undoOperations.push(undo);
1091 _deletedMetadata.push(row);
1092 //row.css("display", "none");
1093 $(row).hide();
1094 });
1095 newCell.append(removeLink);
1096 newCell.attr({"class": "metaTableCellRemove", "style": "font-size:0.6em; padding-left: 3px; padding-right: 3px;"});
1097 $(row).append(newCell);
1098}
1099
1100/* This is for 'edit structure' menu bar */
1101function createTopMenuBar()
1102{
1103 //Create the top menu bar
1104 var headerTable = document.createElement("TABLE");
1105 var tableBody = document.createElement("TBODY");
1106 var row = document.createElement("TR");
1107 var newDocCell = document.createElement("TD");
1108 var newSecCell = document.createElement("TD");
1109 var saveCell = document.createElement("TD");
1110 var undoCell = document.createElement("TD");
1111 var metadataListCell = document.createElement("TD");
1112
1113 var metadataListLabel = document.createElement("SPAN");
1114 metadataListLabel.innerHTML = gs.text.de.visible_metadata;
1115 var metadataList = document.createElement("SELECT");
1116 metadataList.setAttribute("id", "metadataSetList");
1117 metadataList.onchange = onVisibleMetadataSetChange;
1118 var allMetadataOption = document.createElement("OPTION");
1119 metadataList.appendChild(allMetadataOption);
1120 allMetadataOption.innerHTML = gs.text.de.all_metadata;
1121 metadataListCell.appendChild(metadataListLabel);
1122 metadataListCell.appendChild(metadataList);
1123
1124 metadataListCell.setAttribute("class", "headerTableTD");
1125 newDocCell.setAttribute("class", "headerTableTD");
1126 newSecCell.setAttribute("class", "headerTableTD");
1127 undoCell.setAttribute("class", "headerTableTD");
1128 saveCell.setAttribute("class", "headerTableTD");
1129
1130 headerTable.appendChild(tableBody);
1131 tableBody.appendChild(row);
1132 row.appendChild(saveCell);
1133 row.appendChild(undoCell);
1134 row.appendChild(newDocCell);
1135 row.appendChild(newSecCell);
1136 row.appendChild(metadataListCell);
1137
1138 //The "Save changes" button
1139 var saveButton = document.createElement("BUTTON");
1140 saveButton.innerHTML = gs.text.de.save_changes;
1141 saveButton.setAttribute("onclick", "saveAndRebuild();");
1142 saveButton.setAttribute("id", "saveButton");
1143 saveCell.appendChild(saveButton);
1144
1145 //The "Undo" button
1146 var undoButton = document.createElement("BUTTON");
1147 undoButton.innerHTML = gs.text.dse.undo;
1148 undoButton.setAttribute("onclick", "undo();");
1149 undoCell.appendChild(undoButton);
1150
1151 //The "Create new document" button
1152 var newDocButton = document.createElement("BUTTON");
1153 newDocButton.innerHTML = gs.text.dse.create_new_document;
1154 newDocButton.setAttribute("onclick", "createNewDocumentArea();");
1155 newDocButton.setAttribute("id", "createNewDocumentButton");
1156 newDocCell.appendChild(newDocButton);
1157
1158 //The "Insert new section" LI
1159 var newSecLI = createDraggableNewSection(newSecCell);
1160
1161 return headerTable;
1162}
1163
1164function getMetadataFromNode(node, name)
1165{
1166 var currentNode = node.firstChild;
1167 while(currentNode != null)
1168 {
1169 if(currentNode.nodeName == "metadataList")
1170 {
1171 currentNode = currentNode.firstChild;
1172 break;
1173 }
1174
1175 currentNode = currentNode.nextSibling;
1176 }
1177
1178 while(currentNode != null)
1179 {
1180 if(currentNode.nodeName == "metadata" && currentNode.getAttribute("name") == name)
1181 {
1182 return currentNode.firstChild.nodeValue;
1183 }
1184
1185 currentNode = currentNode.nextSibling;
1186 }
1187 return "";
1188}
1189
1190function storeMetadata(node, listItem)
1191{
1192 listItem.metadata = new Array();
1193
1194 var currentNode = node.firstChild;
1195 while(currentNode != null)
1196 {
1197 if(currentNode.nodeName == "metadataList")
1198 {
1199 currentNode = currentNode.firstChild;
1200 break;
1201 }
1202
1203 currentNode = currentNode.nextSibling;
1204 }
1205
1206 while(currentNode != null)
1207 {
1208 if(currentNode.nodeName == "metadata")
1209 {
1210 listItem.metadata[currentNode.getAttribute("name")] = currentNode.firstChild.nodeValue;
1211 }
1212
1213 currentNode = currentNode.nextSibling;
1214 }
1215}
1216
1217function getNodeContent(node)
1218{
1219 var currentNode = node.firstChild;
1220 while(currentNode != null)
1221 {
1222 if(currentNode.nodeName == "nodeContent")
1223 {
1224 return currentNode.firstChild;
1225 }
1226
1227 currentNode = currentNode.nextSibling;
1228 }
1229 return null;
1230}
1231
1232function containsDocumentNode(node)
1233{
1234 var currentNode = node.firstChild;
1235 while(currentNode != null)
1236 {
1237 if(currentNode.nodeName == "documentNode")
1238 {
1239 return true;
1240 }
1241
1242 currentNode = currentNode.nextSibling;
1243 }
1244 return false;
1245}
1246
1247function isExpanded(textDiv)
1248{
1249 if(typeof textDiv.style == "undefined" || typeof textDiv.style.display == "undefined" || textDiv.style.display == "block")
1250 {
1251 return true;
1252 }
1253 return false;
1254}
1255
1256function toggleTextDiv(section)
1257{
1258 var textDiv = section.textDiv;
1259 if(textDiv)
1260 {
1261 if(isExpanded(textDiv))
1262 {
1263 textDiv.style.display = "none";
1264 section.menu.editTextLink.innerHTML = gs.text.dse.edit;
1265 }
1266 else
1267 {
1268 textDiv.style.display = "block";
1269 section.menu.editTextLink.innerHTML = gs.text.dse.hide;
1270 }
1271 }
1272}
1273
1274function updateFromTop()
1275{
1276 updateRecursive(document.getElementById("dbDiv"), null, null, 0);
1277}
1278
1279function insertAfter(elem, refElem)
1280{
1281 if(refElem.nextSibling)
1282 {
1283 refElem.parentNode.insertBefore(elem, refElem.nextSibling);
1284 }
1285 else
1286 {
1287 refElem.parentNode.appendChild(elem);
1288 }
1289}
1290
1291function removeFromParent(elem)
1292{
1293 elem.parentNode.removeChild(elem);
1294}
1295
1296function createSectionTitle(text)
1297{
1298 var textSpan = document.createElement("SPAN");
1299 if(text)
1300 {
1301 textSpan.appendChild(document.createTextNode(" " + text + " "));
1302 }
1303 else
1304 {
1305 textSpan.appendChild(document.createTextNode(" [" + gs.text.dse.untitled_section + "] "));
1306 }
1307 return textSpan;
1308}
1309
1310function setMouseOverAndOutFunctions(section)
1311{
1312 //Colour the list item and display the menu on mouse over
1313 section.onmouseover = function(e)
1314 {
1315 if(this.menu){this.menu.style.display = "inline";}
1316 this.style.background = "rgb(255, 200, 0)";
1317 };
1318 //Uncolour the list item and hide the menu on mouse out
1319 section.onmouseout = function(e)
1320 {
1321 if(this.menu){this.menu.style.display = "none";}
1322 this.style.background = "none";
1323 };
1324}
1325
1326function createDraggableNewSection(parent)
1327{
1328 var newSecLI = document.createElement("LI");
1329 var newSpan = document.createElement("SPAN");
1330 newSpan.innerHTML = gs.text.dse.insert_new_section + " ";
1331
1332 newSecLI.sectionTitle = newSpan;
1333 newSecLI.appendChild(newSpan);
1334 newSecLI.setAttribute("class", "dragItem newSection");
1335 newSecLI.newSection = true;
1336 newSecLI.parent = parent;
1337 newSecLI.index = -1;
1338 new YAHOO.example.DDList(newSecLI);
1339 parent.appendChild(newSecLI);
1340}
1341
1342function closeAllOpenContents()
1343{
1344 for(var i = 0; i < _allContents.length; i++)
1345 {
1346 if(isExpanded(_allContents[i].textDiv))
1347 {
1348 toggleTextDiv(_allContents[i]);
1349 }
1350 }
1351 DDM.refreshCache();
1352}
1353
1354//Status Bar class (initialised with new StatusBar(elem);)
1355function StatusBar(mainElem)
1356{
1357 var _statusMap = new Array();
1358 var _statusIDCounter = 0;
1359 var _mainElem = mainElem;
1360 var _activeMessages = 0;
1361
1362 _mainElem.style.display = "none";
1363
1364 this.addStatus = function(newStatus)
1365 {
1366 _mainElem.style.display = "block";
1367 var newStatusDiv = document.createElement("DIV");
1368 var newStatusSpan = document.createElement("SPAN");
1369
1370 var workingImage = document.createElement("IMG");
1371 workingImage.setAttribute("src", gs.imageURLs.loading);
1372 workingImage.setAttribute("height", "16px");
1373 workingImage.setAttribute("width", "16px");
1374 newStatusDiv.appendChild(workingImage);
1375
1376 newStatusDiv.appendChild(newStatusSpan);
1377 newStatusSpan.innerHTML = " " + newStatus;
1378 newStatusDiv.setAttribute("class", "statusMessage");
1379 newStatusDiv.span = newStatusSpan;
1380
1381 _mainElem.appendChild(newStatusDiv);
1382 _statusMap["status" + _statusIDCounter] = newStatusDiv;
1383 _activeMessages++;
1384 return _statusIDCounter++;
1385 }
1386
1387 this.changeStatus = function(id, newStatus)
1388 {
1389 if(_statusMap["status" + id])
1390 {
1391 _statusMap["status" + id].span.innerHTML = " " + newStatus;
1392 }
1393 }
1394
1395 this.removeStatus = function(id)
1396 {
1397 if(_statusMap["status" + id])
1398 {
1399 removeFromParent(_statusMap["status" + id]);
1400
1401 if(--_activeMessages == 0)
1402 {
1403 _mainElem.style.display = "none";
1404 }
1405 }
1406 }
1407
1408 this.clear = function()
1409 {
1410 for(var p in _statusMap)
1411 {
1412 if(_statusMap.hasOwnProperty(p))
1413 {
1414 if(_statusMap[p] && _statusMap[p].parentNode)
1415 {
1416 removeFromParent(_statusMap[p]);
1417 }
1418
1419 if(--_activeMessages == 0)
1420 {
1421 _mainElem.style.display = "none";
1422 }
1423 }
1424 }
1425 }
1426}
1427
1428/*
1429function toggleEdit(e)
1430{
1431 var mousePos = de.events.getXYInWindowFromEvent(e);
1432 var cDesc = de.cursor.getCursorDescAtXY(mousePos.x, mousePos.y, de.events.getEventTarget(e));
1433 de.cursor.setCursor(cDesc);
1434}
1435*/
Note: See TracBrowser for help on using the repository browser.