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

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

Replacing alerts with fixed language strings with 2 new properties in interface_default2.properties. Not sure how to do newlines in there that won't break the Javascript.

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