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

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

Part 2 of 2 commits to do with getting errorCallBack working on documentEditing for determining when changes have been saved or not to decided whether editableInitStates can finally be overwritten with current (saved) values. Tested with editing doc meta and doc map meta. Also tested special cases for both: with an meta edit followed by a tomcat restart, which then already warned you it requires a relogin for building to work, until which time editableInitStates is still not overwritten, so that it can warn you of unsaved changes if you attempt to leave the page at any point. The only time these changes don't work as expected (but still works better than original code which just loses your local changes) is when editing doc meta instead of map meta and there's the server restart in the middle and the new value ends up accumulating instead of replacing/overriding the previous value. In the old version of the code, new values were lost and the collection rebuilt, all silently without telling you of data loss.

  • 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("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("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.