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

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

added multivalued metadata input shortcut functionality. In documentedit_scripts you can specify which metadata fields are multivalued, and what the delimiter is. For these fields, the user can put a delimiter spearated list, and the values will get split and saved to the doc.xml file individually

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