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

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

Save and rebuild works with map, but as with save shortcut key on map editor, the metamode ends up as accumulate still in doc.xml. Some other issues (not related to saveandrebuild) need fixing up like a popup about unsaved changes appearing even after save and rebuild has finished and possibly more things).

  • Property svn:executable set to *
File size: 39.5 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
450 //Clean changes
451 editableInitStates = editableLastStates;
452
453 for(var i = 0; i < changes.length; i++)
454 {
455 var changedElem = changes[i];
456 //Save metadata
457
458 if(gs.functions.hasClass(changedElem, "metaTableCellArea"))
459 {
460 //Get document ID
461 var currentElem = changedElem;
462 while((currentElem = currentElem.parentNode).tagName != "TABLE");
463 var docID = currentElem.getAttribute("id").substring(4);
464
465 //Get metadata name
466 var row = changedElem.parentNode.parentNode;
467 var cells = row.getElementsByTagName("TD");
468 var nameCell = cells[0];
469 // metadata name cell might have the multivalue indicator in it, so just want the first word
470 var name = nameCell.innerHTML.split(" ")[0];
471 var value = changedElem.value;
472 value = value.replace(/&nbsp;/g, " ");
473
474 var orig = changedElem.originalValue;
475 if (orig) {
476 orig = orig.replace(/&nbsp;/g, " ");
477 }
478 if (jQuery.inArray(name, multiValuedMetadata) != -1) {
479
480 // split the values
481 var values_list = value.split(mvm_delimiter);
482 var orig_list;
483 var num_orig;
484 if (orig) {
485 orig_list = orig.split(mvm_delimiter);
486 num_orig = orig_list.length;
487 }
488
489 for(var i = 0; i < values_list.length; i++) {
490 var val = values_list[i];
491 var ori =null;
492 if (orig && i<num_orig) {
493 ori = orig_list[i];
494 }
495 metadataChanges.push({collection:collection, docID:docID, name:name, value:val, orig:ori});
496 }
497 } else {
498 metadataChanges.push({collection:collection, docID:docID, name:name, value:value, orig:orig});
499 }
500 changedElem.originalValue = changedElem.value;
501 addCollectionToBuild(collection);
502 }
503 //Save content
504 else if(gs.functions.hasClass(changedElem, "renderedText"))
505 {
506 var section = changedElem.parentDiv.parentItem;
507 saveTransaction('{"operation":"setText", "text":"' + CKEDITOR.instances[changedElem.getAttribute("id")].getData().replace(/%/g, "%25").replace(/"/g, "\\\"").replace(/&/g, "%26") + '", "collection":"' + section.collection + '", "oid":"' + section.nodeID + '"}'); //'
508 addCollectionToBuild(section.collection);
509 }
510 else if(gs.functions.hasClass(changedElem, "sectionText"))
511 {
512 var id = changedElem.getAttribute("id");
513 var sectionID = id.substring(4);
514 saveTransaction('{"operation":"setText", "text":"' + CKEDITOR.instances[changedElem.getAttribute("id")].getData().replace(/%/g, "%25").replace(/"/g, "\\\"").replace(/&/g, "%26") + '", "collection":"' + gs.cgiParams.c + '", "oid":"' + sectionID + '"}'); //'
515 addCollectionToBuild(gs.cgiParams.c);
516 }
517 }
518
519 // Check for changes to any map editors in the document
520 var modified_map_editors_data = getDocMapsEditDataForSaving(gs.cgiParams.c); // collection
521 for(var i = 0; i < modified_map_editors_data.length; i++) {
522 metadataChanges.push(modified_map_editors_data[i]); // of the form { collection: gs.cgiParams.c, docID: nodeID, name:"GSP.mapOverlay", metapos: 0, value: <stringifiedJSON> }
523 addCollectionToBuild(gs.cgiParams.c); // collection
524 }
525
526
527
528 var processChangesLoop = function(index)
529 {
530 var change = metadataChanges[index];
531
532 var callbackFunction;
533 if(index + 1 == metadataChanges.length)
534 {
535 callbackFunction = sendBuildRequest;
536 }
537 else
538 {
539 callbackFunction = function(){processChangesLoop(index + 1)};
540 }
541 if (change.type == "delete") {
542 gs.functions.removeArchivesMetadata(collection, gs.xsltParams.site_name, change.docID, change.name, null, encodeDelimiters(change.value), function(){callbackFunction();});
543 } else {
544 // Checking "if(change.metapos)" doesn't work for us as it becomes false when the property doesn't exist AND when the property is 0. But metapos IS 0 for us.
545 // https://ultimatecourses.com/blog/methods-to-determine-if-an-object-has-a-given-property
546 if('metapos' in change && change.metapos === 0) {// && change.metapos === 0) { // for maps
547
548 // collection, site, documentID, metadataName, metadataPosition, metadataValue, prevMetadataValue, metamode, responseFunction
549 //console.log("@@@ metapos! change: ", change);
550 gs.functions.setArchivesMetadata(change.collection, gs.xsltParams.site_name, change.docID, change.name, change.metapos, change.value /*TODO: encodeDelimiters(change.value)*/, null, "override", function(){callbackFunction();});
551 }
552 else if(change.orig)
553 {
554 gs.functions.setArchivesMetadata(change.collection, gs.xsltParams.site_name, change.docID, change.name, null, encodeDelimiters(change.value), encodeDelimiters(change.orig), "override", function(){callbackFunction();});
555 }
556 else
557 {
558 gs.functions.setArchivesMetadata(change.collection, gs.xsltParams.site_name, change.docID, change.name, null, encodeDelimiters(change.value), null, "accumulate", function(){callbackFunction();});
559 }
560 }
561 }
562 if (metadataChanges.length>0) {
563 // this will process each change one by one, and then send the build request
564 processChangesLoop(0);
565 }
566 else if(_collectionsToBuild.length > 0) {
567 // if there are no metadata changes, but some other changes eg text have happened, then we need to send the build request.
568 sendBuildRequest();
569 }
570
571 /* need to clear the changes from the page so that we don't process them again next time */
572 while (_deletedMetadata.length>0) {
573 _deletedMetadata.pop();
574 }
575
576}
577
578
579function buildCollections(collections, documents, callback)
580{
581 if(!collections || collections.length == 0)
582 {
583 console.log(gs.text.dse.empty_collection_list);
584 enableSaveButtons(true);
585 return;
586 }
587
588 var docs = "";
589 var buildOperation = "";
590 if(documents)
591 {
592 buildOperation = "ImportCollection";
593 docs += "&s1.documents=";
594 for(var i = 0; i < documents.length; i++)
595 {
596 docs += documents[i];
597 if(i < documents.length - 1)
598 {
599 docs += ",";
600 }
601 }
602 }
603 else
604 {
605 buildOperation = "BuildAndActivateCollection";
606 }
607
608 var counter = 0;
609 var statusID = 0;
610 var buildFunction = function()
611 {
612 var ajax = new gs.functions.ajaxRequest();
613 ajax.open("GET", gs.xsltParams.library_name + "?a=g&rt=r&ro=1&s=" + buildOperation + "&s1.incremental=true&s1.collection=" + collections[counter] + docs);
614 ajax.onreadystatechange = function()
615 {
616 if(ajax.readyState == 4 && ajax.status == 200)
617 {
618 var text = ajax.responseText;
619 var xml = validateXML(text);
620
621 if(!xml || checkForErrors(xml))
622 {
623 alert(gs.text.dse.could_not_build_p1 + " " + collections[counter] + gs.text.dse.could_not_build_p2);
624
625 if(_statusBar)
626 {
627 _statusBar.removeStatus(statusID);
628 }
629 enableSaveButtons(true);
630
631 return;
632 }
633
634 var status = xml.getElementsByTagName("status")[0];
635 var pid = status.getAttribute("pid");
636
637 startCheckLoop(pid, buildOperation, statusID, function()
638 {
639 /*
640 var localAjax = new gs.functions.ajaxRequest();
641 localAjax.open("GET", gs.xsltParams.library_name + "?a=g&rt=r&ro=1&s=ActivateCollection&s1.collection=" + collections[counter], true);
642 localAjax.onreadystatechange = function()
643 {
644 if(localAjax.readyState == 4 && localAjax.status == 200)
645 {
646 var localText = localAjax.responseText;
647 var localXML = validateXML(localText);
648
649 if(!xml || checkForErrors(xml))
650 {
651 alert(gs.text.dse.could_not_activate_p1 + " " + collections[counter] + gs.text.dse.could_not_activate_p2);
652
653 if(_statusBar)
654 {
655 _statusBar.removeStatus(statusID);
656 }
657 enableSaveButtons(true);
658
659 return;
660 }
661
662 var localStatus = localXML.getElementsByTagName("status")[0];
663 if(localStatus)
664 {
665 var localPID = localStatus.getAttribute("pid");
666 startCheckLoop(localPID, "ActivateCollection", statusID, function()
667 {
668 */
669 if(counter == collections.length - 1)
670 {
671 removeCollectionsFromBuildList(collections);
672 if(callback)
673 {
674 callback();
675 }
676 }
677 else
678 {
679 counter++;
680 buildFunction();
681 }
682
683 _transactions = new Array();
684
685 if(_statusBar)
686 {
687 _statusBar.removeStatus(statusID);
688 }
689 enableSaveButtons(true);
690 /*
691 });
692 }
693 }
694 }
695 if(_statusBar)
696 {
697 _statusBar.changeStatus(statusID, gs.text.dse.activating + " " + collections[counter] + "...");
698 }
699 localAjax.send();
700 */
701 });
702 }
703 }
704 if(_statusBar)
705 {
706 statusID = _statusBar.addStatus(gs.text.dse.building + " " + collections[counter] + "...");
707 }
708 ajax.send();
709 }
710 buildFunction();
711}
712
713function startCheckLoop(pid, serverFunction, statusID, callbackFunction)
714{
715 var ajaxFunction = function()
716 {
717 var ajax = new gs.functions.ajaxRequest();
718 ajax.open("GET", gs.xsltParams.library_name + "?a=g&rt=s&ro=1&s=" + serverFunction + "&s1.pid=" + pid, true);
719 ajax.onreadystatechange = function()
720 {
721 if(ajax.readyState == 4 && ajax.status == 200)
722 {
723 var text = ajax.responseText;
724 var xml = validateXML(text);
725
726 if(!xml || checkForErrors(xml))
727 {
728 alert(gs.text.dse.could_not_check_status_p1 + " " + serverFunction + gs.text.dse.could_not_check_status_p2a);
729
730 if(_statusBar)
731 {
732 _statusBar.removeStatus(statusID);
733 }
734 enableSaveButtons(true);
735
736 return;
737 }
738
739 var status = xml.getElementsByTagName("status")[0];
740 var code = status.getAttribute("code");
741
742 if (code == COMPLETED || code == SUCCESS)
743 {
744 callbackFunction();
745 }
746 else if (code == HALTED || code == ERROR)
747 {
748 alert(gs.text.dse.could_not_check_status_p1 + " " + serverFunction + gs.text.dse.could_not_check_status_p2b);
749
750 if(_statusBar)
751 {
752 _statusBar.removeStatus(statusID);
753 }
754 enableSaveButtons(true);
755 }
756 else
757 {
758 setTimeout(ajaxFunction, 1000);
759 }
760 }
761 }
762 ajax.send();
763 }
764 ajaxFunction();
765}
766
767function removeCollectionsFromBuildList(collections)
768{
769 var tempArray = new Array();
770 for(var i = 0; i < _collectionsToBuild.length; i++)
771 {
772 var found = false;
773 for(var j = 0; j < collections.length; j++)
774 {
775 if(collections[j] == _collectionsToBuild[i])
776 {
777 found = true;
778 break;
779 }
780 }
781
782 if(!found)
783 {
784 tempArray.push(_collectionsToBuild[i]);
785 }
786 }
787 _collectionsToBuild = tempArray;
788}
789
790function checkForErrors(xml)
791{
792 var errorElems = xml.getElementsByTagName("error");
793
794 if(errorElems && errorElems.length > 0)
795 {
796 var errorString = gs.text.dse.error_saving_changes + ": ";
797 for(var i = 0; i < errorElems.length; i++)
798 {
799 errorString += " " + errorElems.item(i).firstChild.nodeValue;
800 }
801 alert(errorString);
802 return true;
803 }
804 return false; //No errors
805}
806
807function validateXML(txt)
808{
809 // code for IE
810 if (window.ActiveXObject)
811 {
812 var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
813 xmlDoc.async = "false";
814 xmlDoc.loadXML(document.all(txt).value);
815
816 if(xmlDoc.parseError.errorCode!=0)
817 {
818 txt = dse.error_code + ": " + xmlDoc.parseError.errorCode + "\n";
819 txt = txt + dse.error_reason + ": " + xmlDoc.parseError.reason;
820 txt = txt + dse.error_line + ": " + xmlDoc.parseError.line;
821 console.log(txt);
822 return null;
823 }
824
825 return xmlDoc;
826 }
827 // code for Mozilla, Firefox, Opera, etc.
828 else if (document.implementation.createDocument)
829 {
830 var parser = new DOMParser();
831 var xmlDoc = parser.parseFromString(txt,"text/xml");
832
833 if (xmlDoc.getElementsByTagName("parsererror").length > 0)
834 {
835 console.log(gs.text.dse.xml_error);
836 return null;
837 }
838
839 return xmlDoc;
840 }
841 else
842 {
843 console.log(gs.text.dse.browse_cannot_validate_xml);
844 }
845 return null;
846}
847
848function onVisibleMetadataSetChange()
849{
850 var metadataList = document.getElementById("metadataSetList");
851 var index = metadataList.selectedIndex;
852 var options = metadataList.getElementsByTagName("OPTION");
853 var selectedOption = options[index];
854
855 var selectedSet = selectedOption.value;
856 changeVisibleMetadata(selectedSet);
857}
858
859function changeVisibleMetadata(metadataSetName)
860{
861 var metaSetList = metadataSetName.split(",");
862 var tables = document.getElementsByTagName("TABLE");
863 for(var i = 0; i < tables.length; i++)
864 {
865 var id = tables[i].getAttribute("id");
866 if(id && id.search(/^meta/) != -1)
867 {
868 var rows = tables[i].getElementsByTagName("TR");
869 for(var j = 0; j < rows.length; j++)
870 {
871 if(metadataSetName == "All")
872 {
873 rows[j].style.display = "table-row";
874 }
875 else
876 {
877 var cells = rows[j].getElementsByTagName("TD");
878 // metadata name cell might have the multivalue indicator in it, so just want the first word
879 var cellName = cells[0].innerHTML.split(" ")[0];
880
881 if(cellName.indexOf(".") == -1)
882 {
883 rows[j].style.display = "none";
884 }
885 else
886 {
887 var setName = cellName.substring(0, cellName.lastIndexOf("."));
888 if (metaSetList.indexOf(setName)!= -1)
889 {
890 rows[j].style.display = "table-row";
891 }
892 else
893 {
894 rows[j].style.display = "none";
895 }
896 }
897 }
898 }
899 }
900 }
901}
902
903function asyncRegisterEditSection(cell)
904{
905 //This registering can cause a sizeable delay so we'll thread it (effectively) so the browser is not paused
906 cell.originalValue = cell.value;
907 setTimeout(function(){addEditableState(cell, editableInitStates)}, 0);
908}
909
910function addOptionToList(list, optionvalue, optiontext, selected) {
911 var newOption = $("<option>");
912 if (optiontext) {
913 newOption.html(optiontext);
914 newOption.attr("value", optionvalue);
915 } else {
916 newOption.html(optionvalue);
917 }
918 if (selected) {
919 newOption.attr("selected", true);
920 }
921 list.append(newOption);
922}
923
924/* returns either an input or a select element. Data based on
925 availableMetadataElements var. */
926function createMetadataElementSelector() {
927 var metaNameField;
928 if (new_metadata_field_input_type == "fixedlist") {
929 metaNameField = $("<select>", {"class": "ui-state-default"});
930 for(var i=0; i<availableMetadataElements.length; i++) {
931 addOptionToList(metaNameField, availableMetadataElements[i]);
932 }
933 return metaNameField;
934 }
935 metaNameField = $("<input>", {"type": "text","style":"margin: 5px; border: 1px solid #000;"});
936 if (new_metadata_field_input_type == "autocomplete") {
937 metaNameField.autocomplete({
938 minLength: 0,
939 source: availableMetadataElements
940 });
941 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'");
942 } else {
943 metaNameField.attr("title", gs.text.de.enter_meta_name); //"Enter a metadata name, then click 'Add New Metadata'");
944 }
945
946 return metaNameField;
947}
948
949function addFunctionalityToMapGPS(mapGPScontainer)
950{
951
952}
953
954function addFunctionalityToTable(table)
955{
956 table.find("tr").each(function()
957 {
958 var cells = $(this).find("td");
959 var metadataName = $(cells[0]).html();
960
961 if(dynamic_metadata_set_list == true && metadataName.indexOf(".") != -1)
962 {
963 var metadataSetName = metadataName.substring(0, metadataName.lastIndexOf("."));
964
965 var found = false;
966 for(var j = 0; j < _metadataSetList.length; j++)
967 {
968 if(metadataSetName == _metadataSetList[j])
969 {
970 found = true;
971 break;
972 }
973 }
974
975 if(!found)
976 {
977 _metadataSetList.push(metadataSetName);
978 addOptionToList( $("#metadataSetList"), metadataSetName);
979 }
980 }
981
982 asyncRegisterEditSection(cells[1].getElementsByTagName("textarea")[0]);
983 addRemoveLinkToRow(this);
984
985 // add multivalued indicator if needed
986 if (jQuery.inArray(metadataName, multiValuedMetadata) != -1) {
987 //if (multiValuedMetadata.includes(metadataName)){
988 $(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 ;
989 }
990
991 });
992
993 // set up autocomplete values
994 var value_cells = $(".metaTableCellArea");
995 for (var k=0; k<autocompleteMetadata.length; k++) {
996 var source_name = autocompleteMetadata[k].replace(/[\.-]/g, "");
997 var source_obj = window[source_name+"_values"];
998 if (source_obj) {
999 value_cells.filter("."+source_name).autocomplete({
1000 minLength: 0,
1001 source: source_obj
1002 });
1003 }
1004 }
1005
1006 // add metadata field selector
1007 var metaNameField = createMetadataElementSelector();
1008 table.after(metaNameField);
1009 table.metaNameField = metaNameField;
1010
1011 /* add the buttons */
1012 // check enable_add_all_button - only valid for fixedlist and autocomplete
1013 if (enable_add_all_metadata_button == true) {
1014 if (new_metadata_field_input_type != "fixedlist" && new_metadata_field_input_type != "autocomplete") {
1015 enable_add_all_metadata_button = false;
1016 }
1017 }
1018
1019 // add single metadata button
1020 var addRowButton = $("<button>",{"class": "ui-state-default ui-corner-all", "style": "margin: 5px;"});
1021
1022 addRowButton.html(gs.text.de.add_new_metadata);
1023 addRowButton.click(function()
1024 {
1025 var name = metaNameField.val();
1026 if(!name || name == "")
1027 {
1028 console.log(gs.text.de.no_meta_name_given);
1029 return;
1030 }
1031 addNewMetadataRow(table, name);
1032
1033
1034 });
1035 table.addRowButton = addRowButton;
1036 metaNameField.after(addRowButton);
1037
1038 // add all metadata button
1039 if (enable_add_all_metadata_button == true) {
1040 var addAllButton = $("<button>",{"class": "ui-state-default ui-corner-all", "style": "margin: 5px;"});
1041 addAllButton.html(gs.text.de.add_all_metadata);
1042 addAllButton.click(function()
1043 {
1044 for(var i=0; i<availableMetadataElements.length; i++) {
1045
1046 addNewMetadataRow(table, availableMetadataElements[i])
1047 }
1048
1049 });
1050 table.addAllButton = addAllButton;
1051 addRowButton.after(addAllButton);
1052
1053 }
1054
1055}
1056
1057function addNewMetadataRow(table, name) {
1058
1059 var clean_name = name.replace(/[\.-]/g, "");
1060 var newRow = $("<tr>", {"style": "display: table-row;"});
1061 var nameCell;
1062 if (jQuery.inArray(name, multiValuedMetadata) != -1) {
1063 nameCell = $("<td>" + name + " <span title='"+gs.text.de.multi_valued_tooltip + "' style='float:right;'>"+mvm_delimiter+"</span></td>");
1064 } else {
1065 nameCell = $("<td>" + name + "</td>");
1066 }
1067 nameCell.attr("class", "metaTableCellName");
1068 var valueCell = $("<td>", {"class": "metaTableCell"});
1069 var textValue = $("<textarea>", {"class": "metaTableCellArea "+ clean_name});
1070
1071 if (jQuery.inArray(name, autocompleteMetadata) != -1) {
1072 var source_obje = window[clean_name +"_values"];
1073 if (source_obje) {
1074 textValue.autocomplete({
1075 minLength: 0,
1076 source: source_obje
1077 });
1078 }
1079 }
1080 valueCell.append(textValue);
1081 newRow.append(nameCell);
1082 newRow.append(valueCell);
1083 addRemoveLinkToRow(newRow.get(0));
1084 table.append(newRow);
1085
1086 var undo = new Array();
1087 undo.op = "delMeta";
1088 undo.srcElem = newRow;
1089 undo.removeTransaction = false;
1090 _undoOperations.push(undo);
1091 if ( hierarchyStorage && hierarchyStorage[name])
1092 {
1093 setHierarchyEventsWrappers(name);
1094 }
1095}
1096
1097function addRemoveLinkToRow(row)
1098{
1099 var newCell = $("<td>");
1100 var removeLink = $("<a>"+gs.text.de.remove+"</a>", {"href": "javascript:;"});
1101 removeLink.click(function()
1102 {
1103 var undo = new Array();
1104 undo.srcElem = row;
1105 undo.op = "display";
1106 undo.subOp = "table-row";
1107 undo.removeDeletedMetadata = true;
1108 _undoOperations.push(undo);
1109 _deletedMetadata.push(row);
1110 //row.css("display", "none");
1111 $(row).hide();
1112 });
1113 newCell.append(removeLink);
1114 newCell.attr({"class": "metaTableCellRemove", "style": "font-size:0.6em; padding-left: 3px; padding-right: 3px;"});
1115 $(row).append(newCell);
1116}
1117
1118/* This is for 'edit structure' menu bar */
1119function createTopMenuBar()
1120{
1121 //Create the top menu bar
1122 var headerTable = document.createElement("TABLE");
1123 var tableBody = document.createElement("TBODY");
1124 var row = document.createElement("TR");
1125 var newDocCell = document.createElement("TD");
1126 var newSecCell = document.createElement("TD");
1127 var saveCell = document.createElement("TD");
1128 var undoCell = document.createElement("TD");
1129 var metadataListCell = document.createElement("TD");
1130
1131 var metadataListLabel = document.createElement("SPAN");
1132 metadataListLabel.innerHTML = gs.text.de.visible_metadata;
1133 var metadataList = document.createElement("SELECT");
1134 metadataList.setAttribute("id", "metadataSetList");
1135 metadataList.onchange = onVisibleMetadataSetChange;
1136 var allMetadataOption = document.createElement("OPTION");
1137 metadataList.appendChild(allMetadataOption);
1138 allMetadataOption.innerHTML = gs.text.de.all_metadata;
1139 metadataListCell.appendChild(metadataListLabel);
1140 metadataListCell.appendChild(metadataList);
1141
1142 metadataListCell.setAttribute("class", "headerTableTD");
1143 newDocCell.setAttribute("class", "headerTableTD");
1144 newSecCell.setAttribute("class", "headerTableTD");
1145 undoCell.setAttribute("class", "headerTableTD");
1146 saveCell.setAttribute("class", "headerTableTD");
1147
1148 headerTable.appendChild(tableBody);
1149 tableBody.appendChild(row);
1150 row.appendChild(saveCell);
1151 row.appendChild(undoCell);
1152 row.appendChild(newDocCell);
1153 row.appendChild(newSecCell);
1154 row.appendChild(metadataListCell);
1155
1156 //The "Save changes" button
1157 var saveButton = document.createElement("BUTTON");
1158 saveButton.innerHTML = gs.text.de.save_changes;
1159 saveButton.setAttribute("onclick", "saveAndRebuild();");
1160 saveButton.setAttribute("id", "saveButton");
1161 saveCell.appendChild(saveButton);
1162
1163 //The "Undo" button
1164 var undoButton = document.createElement("BUTTON");
1165 undoButton.innerHTML = gs.text.dse.undo;
1166 undoButton.setAttribute("onclick", "undo();");
1167 undoCell.appendChild(undoButton);
1168
1169 //The "Create new document" button
1170 var newDocButton = document.createElement("BUTTON");
1171 newDocButton.innerHTML = gs.text.dse.create_new_document;
1172 newDocButton.setAttribute("onclick", "createNewDocumentArea();");
1173 newDocButton.setAttribute("id", "createNewDocumentButton");
1174 newDocCell.appendChild(newDocButton);
1175
1176 //The "Insert new section" LI
1177 var newSecLI = createDraggableNewSection(newSecCell);
1178
1179 return headerTable;
1180}
1181
1182function getMetadataFromNode(node, name)
1183{
1184 var currentNode = node.firstChild;
1185 while(currentNode != null)
1186 {
1187 if(currentNode.nodeName == "metadataList")
1188 {
1189 currentNode = currentNode.firstChild;
1190 break;
1191 }
1192
1193 currentNode = currentNode.nextSibling;
1194 }
1195
1196 while(currentNode != null)
1197 {
1198 if(currentNode.nodeName == "metadata" && currentNode.getAttribute("name") == name)
1199 {
1200 return currentNode.firstChild.nodeValue;
1201 }
1202
1203 currentNode = currentNode.nextSibling;
1204 }
1205 return "";
1206}
1207
1208function storeMetadata(node, listItem)
1209{
1210 listItem.metadata = new Array();
1211
1212 var currentNode = node.firstChild;
1213 while(currentNode != null)
1214 {
1215 if(currentNode.nodeName == "metadataList")
1216 {
1217 currentNode = currentNode.firstChild;
1218 break;
1219 }
1220
1221 currentNode = currentNode.nextSibling;
1222 }
1223
1224 while(currentNode != null)
1225 {
1226 if(currentNode.nodeName == "metadata")
1227 {
1228 listItem.metadata[currentNode.getAttribute("name")] = currentNode.firstChild.nodeValue;
1229 }
1230
1231 currentNode = currentNode.nextSibling;
1232 }
1233}
1234
1235function getNodeContent(node)
1236{
1237 var currentNode = node.firstChild;
1238 while(currentNode != null)
1239 {
1240 if(currentNode.nodeName == "nodeContent")
1241 {
1242 return currentNode.firstChild;
1243 }
1244
1245 currentNode = currentNode.nextSibling;
1246 }
1247 return null;
1248}
1249
1250function containsDocumentNode(node)
1251{
1252 var currentNode = node.firstChild;
1253 while(currentNode != null)
1254 {
1255 if(currentNode.nodeName == "documentNode")
1256 {
1257 return true;
1258 }
1259
1260 currentNode = currentNode.nextSibling;
1261 }
1262 return false;
1263}
1264
1265function isExpanded(textDiv)
1266{
1267 if(typeof textDiv.style == "undefined" || typeof textDiv.style.display == "undefined" || textDiv.style.display == "block")
1268 {
1269 return true;
1270 }
1271 return false;
1272}
1273
1274function toggleTextDiv(section)
1275{
1276 var textDiv = section.textDiv;
1277 if(textDiv)
1278 {
1279 if(isExpanded(textDiv))
1280 {
1281 textDiv.style.display = "none";
1282 section.menu.editTextLink.innerHTML = gs.text.dse.edit;
1283 }
1284 else
1285 {
1286 textDiv.style.display = "block";
1287 section.menu.editTextLink.innerHTML = gs.text.dse.hide;
1288 }
1289 }
1290}
1291
1292function updateFromTop()
1293{
1294 updateRecursive(document.getElementById("dbDiv"), null, null, 0);
1295}
1296
1297function insertAfter(elem, refElem)
1298{
1299 if(refElem.nextSibling)
1300 {
1301 refElem.parentNode.insertBefore(elem, refElem.nextSibling);
1302 }
1303 else
1304 {
1305 refElem.parentNode.appendChild(elem);
1306 }
1307}
1308
1309function removeFromParent(elem)
1310{
1311 elem.parentNode.removeChild(elem);
1312}
1313
1314function createSectionTitle(text)
1315{
1316 var textSpan = document.createElement("SPAN");
1317 if(text)
1318 {
1319 textSpan.appendChild(document.createTextNode(" " + text + " "));
1320 }
1321 else
1322 {
1323 textSpan.appendChild(document.createTextNode(" [" + gs.text.dse.untitled_section + "] "));
1324 }
1325 return textSpan;
1326}
1327
1328function setMouseOverAndOutFunctions(section)
1329{
1330 //Colour the list item and display the menu on mouse over
1331 section.onmouseover = function(e)
1332 {
1333 if(this.menu){this.menu.style.display = "inline";}
1334 this.style.background = "rgb(255, 200, 0)";
1335 };
1336 //Uncolour the list item and hide the menu on mouse out
1337 section.onmouseout = function(e)
1338 {
1339 if(this.menu){this.menu.style.display = "none";}
1340 this.style.background = "none";
1341 };
1342}
1343
1344function createDraggableNewSection(parent)
1345{
1346 var newSecLI = document.createElement("LI");
1347 var newSpan = document.createElement("SPAN");
1348 newSpan.innerHTML = gs.text.dse.insert_new_section + " ";
1349
1350 newSecLI.sectionTitle = newSpan;
1351 newSecLI.appendChild(newSpan);
1352 newSecLI.setAttribute("class", "dragItem newSection");
1353 newSecLI.newSection = true;
1354 newSecLI.parent = parent;
1355 newSecLI.index = -1;
1356 new YAHOO.example.DDList(newSecLI);
1357 parent.appendChild(newSecLI);
1358}
1359
1360function closeAllOpenContents()
1361{
1362 for(var i = 0; i < _allContents.length; i++)
1363 {
1364 if(isExpanded(_allContents[i].textDiv))
1365 {
1366 toggleTextDiv(_allContents[i]);
1367 }
1368 }
1369 DDM.refreshCache();
1370}
1371
1372//Status Bar class (initialised with new StatusBar(elem);)
1373function StatusBar(mainElem)
1374{
1375 var _statusMap = new Array();
1376 var _statusIDCounter = 0;
1377 var _mainElem = mainElem;
1378 var _activeMessages = 0;
1379
1380 _mainElem.style.display = "none";
1381
1382 this.addStatus = function(newStatus)
1383 {
1384 _mainElem.style.display = "block";
1385 var newStatusDiv = document.createElement("DIV");
1386 var newStatusSpan = document.createElement("SPAN");
1387
1388 var workingImage = document.createElement("IMG");
1389 workingImage.setAttribute("src", gs.imageURLs.loading);
1390 workingImage.setAttribute("height", "16px");
1391 workingImage.setAttribute("width", "16px");
1392 newStatusDiv.appendChild(workingImage);
1393
1394 newStatusDiv.appendChild(newStatusSpan);
1395 newStatusSpan.innerHTML = " " + newStatus;
1396 newStatusDiv.setAttribute("class", "statusMessage");
1397 newStatusDiv.span = newStatusSpan;
1398
1399 _mainElem.appendChild(newStatusDiv);
1400 _statusMap["status" + _statusIDCounter] = newStatusDiv;
1401 _activeMessages++;
1402 return _statusIDCounter++;
1403 }
1404
1405 this.changeStatus = function(id, newStatus)
1406 {
1407 if(_statusMap["status" + id])
1408 {
1409 _statusMap["status" + id].span.innerHTML = " " + newStatus;
1410 }
1411 }
1412
1413 this.removeStatus = function(id)
1414 {
1415 if(_statusMap["status" + id])
1416 {
1417 removeFromParent(_statusMap["status" + id]);
1418
1419 if(--_activeMessages == 0)
1420 {
1421 _mainElem.style.display = "none";
1422 }
1423 }
1424 }
1425
1426 this.clear = function()
1427 {
1428 for(var p in _statusMap)
1429 {
1430 if(_statusMap.hasOwnProperty(p))
1431 {
1432 if(_statusMap[p] && _statusMap[p].parentNode)
1433 {
1434 removeFromParent(_statusMap[p]);
1435 }
1436
1437 if(--_activeMessages == 0)
1438 {
1439 _mainElem.style.display = "none";
1440 }
1441 }
1442 }
1443 }
1444}
1445
1446/*
1447function toggleEdit(e)
1448{
1449 var mousePos = de.events.getXYInWindowFromEvent(e);
1450 var cDesc = de.cursor.getCursorDescAtXY(mousePos.x, mousePos.y, de.events.getEventTarget(e));
1451 de.cursor.setCursor(cDesc);
1452}
1453*/
Note: See TracBrowser for help on using the repository browser.