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

Last change on this file since 32127 was 32078, checked in by kjdon, 6 years ago

only record deleted metadata changes if the field value was non empty. Otherwise if the user adds a field then deletes it, it will send off a delete meta request with an empty value, and something else will get deleted.

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