/** Javascript file containing useful functions used by both documentedit_scripts.js and documentmaker_scripts.js */ //Some "constants" to match the server constants var SUCCESS = 1; var ACCEPTED = 2; var ERROR = 3; var CONTINUING = 10; var COMPLETED = 11; var HALTED = 12; var _transactions = new Array(); var _collectionsToBuild = new Array(); var _allContents = new Array(); var _deletedSections = new Array(); var _deletedMetadata = new Array(); var _undoOperations = new Array(); var _baseURL; var _statusBar; var _metadataSetList = new Array(); // We need to wait for all editable elements (metadataTable and sectionText) to be finished with initialising // before we try to store their current states in the editableInitStates array // To do this, we need to keep track of how many elements still require initialising. var editableElementsInitialisationProgress = 0; function encodeDelimiters(meta_value) { var new_value = meta_value.replace(/;/g, "%253B"); return new_value.replace(/&/g, "%2526"); } function getElementsByClassName(cl, parent) { var elemArray = []; var classRegEx = new RegExp("\\b" + cl + "\\b"); var elems; if(parent) { elems = parent.getElementsByTagName("*"); } else { elems = document.getElementsByTagName("*"); } for (var i = 0; i < elems.length; i++) { var classeName = elems[i].className; if (classRegEx.test(classeName)) elemArray.push(elems[i]); } return elemArray; }; function getNextSiblingOfType(elem, type) { if(elem == null) { return null; } var current = elem.nextSibling; while(current != null) { if(current.nodeName.toLowerCase() == type) { return current; } current = current.nextSibling; } return null; } function getPrevSiblingOfType(elem, type) { if(elem == null) { return null; } var current = elem.previousSibling; while(current != null) { if(current.nodeName.toLowerCase() == type) { return current; } current = current.previousSibling; } return null; } function saveTransaction(transaction) { console.log(transaction); _transactions.push(transaction); } function undo() { if(_undoOperations.length == 0) { return; } var undoOp = _undoOperations.pop(); //Create/Duplicate undo if(undoOp.op == "del") { if(undoOp.srcElem.childList) { removeFromParent(undoOp.srcElem.childList); } if(undoOp.srcElem.parentItem) { undoOp.srcElem.parentItem.menu.newSectionLink.style.display = "inline"; undoOp.srcElem.parentItem.childList = null; } removeFromParent(undoOp.srcElem); } if(undoOp.op == "delMeta") { if(undoOp.srcElem.childList) { removeFromParent(undoOp.srcElem.childList); } if(undoOp.srcElem.parentItem) { undoOp.srcElem.parentItem.menu.newSectionLink.style.display = "inline"; undoOp.srcElem.parentItem.childList = null; } de.doc.unregisterEditSection(undoOp.srcElem); removeFromParent(undoOp.srcElem); } //Move undo (mva is move after, mvb is move before, mvi is move into) else if(undoOp.op == "mva" || undoOp.op == "mvb" || undoOp.op == "mvi") { if(undoOp.op == "mvb") { undoOp.refElem.parentNode.insertBefore(undoOp.srcElem, undoOp.refElem); } else if(undoOp.op == "mva") { insertAfter(undoOp.srcElem, undoOp.refElem); } else { undoOp.refElem.removeChild(undoOp.refElem.firstChild); undoOp.refElem.appendChild(undoOp.srcElem); } if(undoOp.srcElem.textDiv) { insertAfter(undoOp.srcElem.textDiv, undoOp.srcElem); } if(undoOp.srcElem.childList) { insertAfter(undoOp.srcElem.childList, undoOp.srcElem.textDiv); } if(undoOp.srcElem.onmouseout) { //Uncolour the section if it coloured undoOp.srcElem.onmouseout(); } updateFromTop(); } else if(undoOp.op == "display") { undoOp.srcElem.style.display = undoOp.subOp; } if(undoOp.removeDeletedMetadata) { _deletedMetadata.pop(); } if(undoOp.removeTransaction) { _transactions.pop(); } } function enableSaveButtons(enabled) { if (enabled) { $("#saveButton, #quickSaveButton").html(gs.text.de.save_changes); $("#saveButton, #quickSaveButton").prop("disabled", false); } else { $("#saveButton, #quickSaveButton").html(gs.text.de.saving + "..."); $("#saveButton, #quickSaveButton").prop("disabled", true); } } function addCollectionToBuild(collection) { for(var i = 0; i < _collectionsToBuild.length; i++) { if(collection == _collectionsToBuild[i]) { return; } } _collectionsToBuild.push(collection); } function save() { saveAndRebuild(false); } function rebuildCurrentCollection() { console.log(gs.text.de.rebuilding_collection); enableSaveButtons(false); var collection = gs.cgiParams.c; var collectionsArray = new Array(); collectionsArray.push(collection); buildCollections(collectionsArray, null, reloadUponRebuild); // passing in callback to reload the page after build, as requested by Kathy } function reloadUponRebuild() { // finished rebuilding - reload the page after rebuild, but first // clear transactions array of saved changes, now that we're done processing these changes during rebuild, // since we don't want the "are you sure to leave page" popup which appears on _transactions array being non-empty _transactions = null; location.reload(true); // force reload, not from cache, https://www.w3schools.com/jsref/met_loc_reload.asp } /************************************ * TEXT EDIT (CKEDITOR) SCRIPTS * **************************************/ // not using this anymore as the instanceready never seems to get called function addCKEEditableState(evt,stateArray) { // Event->Editor->CKE DOM Inline Element that editor was for->underlying jquery element element = evt.editor.element.$; nodeText = element.innerHTML; stateArray.push({ editableNode : element, initHTML : nodeText }); } function addEditableState(editable,stateArray) { if(editable.tagName == 'TEXTAREA') { nodeText = editable.value; } else { nodeText = editable.innerHTML; } stateArray.push({ editableNode : editable, initHTML : nodeText }); } function getLastEditableStates() { editableLastStates = []; $(".sectionText").each(function(){addEditableState(this,editableLastStates);}); $(".metaTableCellArea").each(function(){addEditableState(this,editableLastStates);}); } function changesToUpdate() { var resultArray = new Array(); //console.log("**** changesToUpdate::editableElementsInitialisationProgress = " + editableElementsInitialisationProgress); // Only want to check for valid edited states if the editableInitStates has been fully set up: // We don't bother if editableInitStates is not ready: // if editableInitStates array has nothing in it (which means CKEditor is not ready) // OR if some of the editable elements (metadataTable OR ckeditor editable values) still need to be initialised/initialising is only partway through if ((editableInitStates.length > 0) && (editableElementsInitialisationProgress == 0)) { getLastEditableStates(); for (var j in editableLastStates) { if (isNodeChanged(editableLastStates[j])) { resultArray.push(editableLastStates[j].editableNode); } } } return resultArray; } function isNodeChanged(StateToCheck){ for (var i in editableInitStates) { if ((StateToCheck.editableNode === editableInitStates[i].editableNode)) { if ( StateToCheck.initHTML === editableInitStates[i].initHTML ) { return false; } //console.log("current="+StateToCheck.initHTML); //console.log("init="+editableInitStates[i].initHTML); return true; } } // if get here, this must be a new node, as wasn't in init states // make sure its not empty - we won't add empty nodes. if (StateToCheck.initHTML == "") { return false; } console.log("**** isNodeChanged() editableInitStates = ", editableInitStates); return true; } function changesSaved() { console.log("Replacing init states with current states"); // Clean changes. We're here because setting meta for all meta changes was successful, so // - update doc's metadata initial states to current: editableInitStates = editableLastStates; if (gs.variables.isMapGPSEditingAllowed === '1') { // - update doc's map editors' initial states to current: var map_editors_array = Object.values(gsmap_store); for(var i = 0; i < map_editors_array.length; i++) { var map_editor = map_editors_array[i]; map_editor.savedOverlays = JSON.stringify(ShapesUtil.overlayToJSON(map_editor.overlays)); } } } function fillUserCommentTableColumnNames(elem, userCommentsMetaFields) { var currentElem = elem; if(currentElem.tagName != "TABLE") { while((currentElem = currentElem.parentNode).tagName != "TABLE"); } var headerRow = currentElem.firstElementChild; // tr var headerCells = headerRow.querySelectorAll("th"); for(var th = 1; th < headerCells.length; th++) { // skip th index=0, which is metapos userCommentsMetaFields.push(headerCells[th].textContent); //console.log("userCommentsMetaFields:" + userCommentsMetaFields[th-1]); } } function saveAndRebuild(rebuild) { //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 var collection; if(gs.cgiParams.c && gs.cgiParams.c != "") { collection = gs.cgiParams.c; } else { collection = gs.cgiParams.p_c; } var sendBuildRequest = function() { var request = "["; for(var i = 0; i < _transactions.length; i++) { request += _transactions[i]; if(i != _transactions.length - 1) { request += ","; } } request += "]"; var statusID; var ajax = new gs.functions.ajaxRequest(); ajax.open("POST", gs.xsltParams.library_name, true); ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8"); ajax.onreadystatechange = function() { if(ajax.readyState == 4 && ajax.status == 200) { var text = ajax.responseText; var xml = validateXML(text); var errorElems; if(!xml || checkForErrors(xml)) { alert(gs.text.dse.error_saving); enableSaveButtons(true); if(_statusBar) { _statusBar.removeStatus(statusID); } return; } if(_statusBar) { _statusBar.removeStatus(statusID); } if (rebuild) { buildCollections(_collectionsToBuild, null, reloadUponRebuild); } else { // no rebuilding // We're past possible errors at this point. So changes have by now been definitely saved to archives. // and as there is no rebuilding of the collection, we're now ready to set init states to current states changesSaved(); // reset the save button here enableSaveButtons(true); // saving to archives is now done, clear the transactions // that were keeping track of the full text changes that have now // been performed to archives (no member var keeps track of meta changes, only a local var) _transactions = new Array(); } } } if(_collectionsToBuild.length > 0) { enableSaveButtons(false); if(_statusBar) { statusID = _statusBar.addStatus(gs.text.dse.modifying_archives + "..."); } ajax.send("a=g&rt=r&s=DocumentExecuteTransaction&s1.transactions=" + request); } } // end sendBuildRequest definition var metadataChanges = new Array(); var docids_to_delCommentsMetapositions = {}; //var delCommentsMetapositions = []; var userCommentsMetaFields = []; var _docid; if (_deletedMetadata.length > 0) { //addCollectionToBuild(collection); var i; for(i = 0; i < _deletedMetadata.length; i++) { var currentRow = _deletedMetadata[i]; //Get document ID var currentElem = currentRow; //console.log("metapos: " + currentElem.firstElementChild.textContent); while((currentElem = currentElem.parentNode).tagName != "TABLE"); var docID; if(currentElem.getAttribute("id").startsWith("usercomments-")) { docID = currentElem.getAttribute("id").substring("usercomments-".length); _docid = docID; if(userCommentsMetaFields.length == 0) { fillUserCommentTableColumnNames(currentElem, userCommentsMetaFields); } // get metapos; collumn names in first row are metanames var metapos = currentRow.firstElementChild.textContent; if(docids_to_delCommentsMetapositions[docID] === undefined) { docids_to_delCommentsMetapositions[docID] = []; } //delCommentsMetapositions.push(metapos); docids_to_delCommentsMetapositions[docID].push(metapos); //console.log("docID : " + docID + " - metapos: " + metapos); } else { docID = currentElem.getAttribute("id").substring(4); // with id ="meta" //Get metadata name var cells = currentRow.getElementsByTagName("TD"); var nameCell = cells[0]; // metadata name cell might have the multivalue indicator in it, so just want the first word var name = nameCell.innerHTML.split(" ")[0]; var valueCell = cells[1]; var value = valueCell.getElementsByTagName("TEXTAREA")[0].value; if (value.length) { // check for non empty value, in case all they have done is add a field then deleted it. metadataChanges.push({type:'delete', docID:docID, name:name, value:value}); addCollectionToBuild(collection); } } removeFromParent(currentRow); } } var changes = changesToUpdate(); // expect user comment edits to be processed async from deletes var forcesync_userCommentsEdits = false; //Clean changes ////editableInitStates = editableLastStates; // moved into processChangesLoop(): when all changes have successfully been processed. // Alternative is to set initState per metadata in changes array: after each setArchiveMetadata call for each individual meta change. // But since our setMeta calls are always synchronous, happening in sequence, if one setArchivesMeta() call fails // we'll not attempt subsequent ones or coll building at the end. var userCommentsRowsChanged = []; for(var i = 0; i < changes.length; i++) { var changedElem = changes[i]; //Save metadata if(gs.functions.hasClass(changedElem, "metaTableCellArea")) { //Get document ID var currentElem = changedElem; while((currentElem = currentElem.parentNode).tagName != "TABLE"); if(currentElem.getAttribute("id").startsWith("usercomments-")) { userCommentsRowsChanged.push(changedElem); continue; // we'll process edited user comments separately } var docID = currentElem.getAttribute("id").substring(4); //Get metadata name var row = changedElem.parentNode.parentNode; var cells = row.getElementsByTagName("TD"); var nameCell = cells[0]; // metadata name cell might have the multivalue indicator in it, so just want the first word var name = nameCell.innerHTML.split(" ")[0]; var value = changedElem.value; value = value.replace(/ /g, " "); var orig = changedElem.originalValue; if (orig) { orig = orig.replace(/ /g, " "); } if (jQuery.inArray(name, multiValuedMetadata) != -1) { // split the values var values_list = value.split(mvm_delimiter); var orig_list; var num_orig; if (orig) { orig_list = orig.split(mvm_delimiter); num_orig = orig_list.length; } for(var i = 0; i < values_list.length; i++) { var val = values_list[i]; var ori =null; if (orig && i 0) { if(userCommentsMetaFields.length == 0) { fillUserCommentTableColumnNames(userCommentsRowsChanged[0], userCommentsMetaFields); } //alert("Usercomments colnames: " + userCommentsMetaFields); var docArray = getUserCommentsEditDataForSaving( userCommentsMetaFields, userCommentsRowsChanged, docids_to_delCommentsMetapositions); // passing in docids_to_delCommentsMetapositions to cancel any edits in user comment // rows that have also been marked for deletion. metadataChanges.push({type:'editUserComments',collection:collection,docArray:docArray}); addCollectionToBuild(collection); forcesync_userCommentsEdits = forceSyncUserCommentsEdits(docArray, docids_to_delCommentsMetapositions); docArray = []; // clear it } // process user comment edits *before* user comment deletes, // since deletes change usercomments' metapos values which would affect // edits if edits were to happen after deletes // we can now process the deleted user comments, by organizing them into a single JSON // so that a single call to removeMetadataArray can delete them all more efficiently var docArray = getUserCommentsDeletions( userCommentsMetaFields, docids_to_delCommentsMetapositions); if(docArray.length > 0) { metadataChanges.push({type:'deleteUserComments', docArray:docArray}); addCollectionToBuild(collection); } // clear used up vars https://bobbyhadz.com/blog/javascript-clear-object-delete-all-properties docArray = []; docids_to_delCommentsMetapositions = {}; // Check for changes to any map editors in the document // NOTE: At present, we don't maintain a list of deletions for the map editor: // GPS.mapOverlay data that has been removed is recorded as a change not a deletion, // with the metadata's new value being the string of an empty JSON array, [], // and entered as such into doc.xml. if (gs.variables.isMapGPSEditingAllowed === '1') { var modified_map_editors_data = getDocMapsEditDataForSaving(gs.cgiParams.c); // collection for(var i = 0; i < modified_map_editors_data.length; i++) { metadataChanges.push(modified_map_editors_data[i]); // of the form { collection: gs.cgiParams.c, docID: nodeID, name:"GSP.mapOverlay", metapos: 0, value: } addCollectionToBuild(gs.cgiParams.c); // collection } } var errorCallback = function() { 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." return true; } // called on success callback, to check for errors in response. Returns true if response contains the error status code 3 var hadErrorResponseOnSave = function(response) { // check response for error status code 3 // 0) { var status_code = xmlDoc.getElementsByTagName("status")[0].getAttribute("code"); if(status_code === "3") { // status code 3 means error (see GSStatus.java::ERROR) 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." console.log("@@@ Error on setting archive metadata. Got error message: " + response); return true; } } return false; } var processChangesLoop = function(index) { var change = metadataChanges[index]; var callbackFunction; if(index + 1 == metadataChanges.length) { callbackFunction = sendBuildRequest; } else { callbackFunction = function(){processChangesLoop(index + 1)}; } if (change.type == "delete") { gs.functions.removeArchivesMetadata(collection, gs.xsltParams.site_name, change.docID, change.name, null, encodeDelimiters(change.value), function(){callbackFunction();}); } else if (change.type === "editUserComments") { var edit_locations = "import|archives|index"; //alert("editUserComments: " + JSON.stringify(change.docArray)); gs.functions.setMetadataArray( collection, gs.xsltParams.site_name, change.docArray, "override", //metamode edit_locations, function(ajaxResult) { console.log("Edited comments in "+edit_locations); //callbackFunction(); if(!hadErrorResponseOnSave(ajaxResult)) { callbackFunction(); // move on to processing next & eventually rebuild } }, // if necessary, forcesync AJAX call to make sure user comments edits are // all processed before deletes, as deletes can alter metapositions forcesync_userCommentsEdits, // false for asynchronous, see comment in gs.usercomments.addUserComment() function(ajaxError) { console.log("Set usercomments meta FAILED!"); var errData = (ajaxError.responseText) ? ajaxError.responseText : ajaxError; //alert(gs.text.dse.setmeta_server_error + ". Set meta failed. Got: " + errData); console.log("A server side error occurred during setMetadataArray. (Is the server running?)\nNot proceeding further with saving and rebuilding. Got error: " + JSON.stringify(errData)); alert("A server side error occurred during setMetadataArray. (Is the server running?)\nNot proceeding further with saving and rebuilding. Got error: " + JSON.stringify(errData)); } ); } else if (change.type === "deleteUserComments") { //alert("deleteUserComments" + JSON.stringify(change.docArray)); gs.functions.removeMetadataArray( collection, gs.xsltParams.site_name, change.docArray, null, //metamode "import|archives|index", function(ajaxResult) { console.log("Comments deleted from import/archives/index"); callbackFunction(); // move on to processing next & eventually rebuild }, false, // false for asynchronous, see comment in gs.usercomments.addUserComment() function(ajaxError) { var errData = (ajaxError.responseText) ? ajaxError.responseText : ajaxError; alert("Remove failed. Got: " + errData); } ); } else { // 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. // https://ultimatecourses.com/blog/methods-to-determine-if-an-object-has-a-given-property if('metapos' in change && change.metapos === 0) {// && change.metapos === 0) { // for maps // collection, site, documentID, metadataName, metadataPosition, metadataValue, prevMetadataValue, metamode, responseFunction //console.log("@@@ metapos! change: ", change); gs.functions.setArchivesMetadata(change.collection, gs.xsltParams.site_name, change.docID, change.name, change.metapos, encodeDelimiters(change.value), null, "override", function(response){ if(!hadErrorResponseOnSave(response)) callbackFunction(); }, errorCallback); } else if(change.orig) { gs.functions.setArchivesMetadata(change.collection, gs.xsltParams.site_name, change.docID, change.name, null, encodeDelimiters(change.value), encodeDelimiters(change.orig), "override", function(response){ if(!hadErrorResponseOnSave(response)) callbackFunction(); }, errorCallback); } else { gs.functions.setArchivesMetadata(change.collection, gs.xsltParams.site_name, change.docID, change.name, null, encodeDelimiters(change.value), null, "accumulate", function(response){ if(!hadErrorResponseOnSave(response)) callbackFunction(); }, errorCallback); } } } if (metadataChanges.length>0) { // this will process each change one by one, and then send the build request processChangesLoop(0); } else if(_collectionsToBuild.length > 0) { // if there are no metadata changes, but some other changes eg text have happened, then we need to send the build request. sendBuildRequest(); } /* need to clear the changes from the page so that we don't process them again next time */ while (_deletedMetadata.length>0) { _deletedMetadata.pop(); } } function buildCollections(collections, documents, callback) { if(!collections || collections.length == 0) { console.log(gs.text.dse.empty_collection_list); enableSaveButtons(true); return; } var docs = ""; var buildOperation = ""; if(documents) { buildOperation = "ImportCollection"; docs += "&s1.documents="; for(var i = 0; i < documents.length; i++) { docs += documents[i]; if(i < documents.length - 1) { docs += ","; } } } else { buildOperation = "BuildAndActivateCollection"; } var counter = 0; var statusID = 0; var buildFunction = function() { var ajax = new gs.functions.ajaxRequest(); ajax.open("GET", gs.xsltParams.library_name + "?a=g&rt=r&ro=1&s=" + buildOperation + "&s1.incremental=true&s1.collection=" + collections[counter] + docs); ajax.onreadystatechange = function() { if(ajax.readyState == 4 && ajax.status == 200) { var text = ajax.responseText; var xml = validateXML(text); if(!xml || checkForErrors(xml)) { alert(gs.text.dse.could_not_build_p1 + " " + collections[counter] + gs.text.dse.could_not_build_p2); if(_statusBar) { _statusBar.removeStatus(statusID); } enableSaveButtons(true); return; } var status = xml.getElementsByTagName("status")[0]; var pid = status.getAttribute("pid"); startCheckLoop(pid, buildOperation, statusID, function() { /* var localAjax = new gs.functions.ajaxRequest(); localAjax.open("GET", gs.xsltParams.library_name + "?a=g&rt=r&ro=1&s=ActivateCollection&s1.collection=" + collections[counter], true); localAjax.onreadystatechange = function() { if(localAjax.readyState == 4 && localAjax.status == 200) { var localText = localAjax.responseText; var localXML = validateXML(localText); if(!xml || checkForErrors(xml)) { alert(gs.text.dse.could_not_activate_p1 + " " + collections[counter] + gs.text.dse.could_not_activate_p2); if(_statusBar) { _statusBar.removeStatus(statusID); } enableSaveButtons(true); return; } var localStatus = localXML.getElementsByTagName("status")[0]; if(localStatus) { var localPID = localStatus.getAttribute("pid"); startCheckLoop(localPID, "ActivateCollection", statusID, function() { */ if(counter == collections.length - 1) { // We're here because rebuilding has now completed with no errors. // This means changes were definitely successfully saved to archives AND have been rebuilt with NO errors, // so set init states to current states: changesSaved(); removeCollectionsFromBuildList(collections); if(callback) { callback(); } } else { counter++; buildFunction(); } _transactions = new Array(); if(_statusBar) { _statusBar.removeStatus(statusID); } enableSaveButtons(true); /* }); } } } if(_statusBar) { _statusBar.changeStatus(statusID, gs.text.dse.activating + " " + collections[counter] + "..."); } localAjax.send(); */ }); } } if(_statusBar) { statusID = _statusBar.addStatus(gs.text.dse.building + " " + collections[counter] + "..."); } ajax.send(); } buildFunction(); } function startCheckLoop(pid, serverFunction, statusID, callbackFunction) { var ajaxFunction = function() { var ajax = new gs.functions.ajaxRequest(); ajax.open("GET", gs.xsltParams.library_name + "?a=g&rt=s&ro=1&s=" + serverFunction + "&s1.pid=" + pid, true); ajax.onreadystatechange = function() { if(ajax.readyState == 4 && ajax.status == 200) { var text = ajax.responseText; var xml = validateXML(text); if(!xml || checkForErrors(xml)) { alert(gs.text.dse.could_not_check_status_p1 + " " + serverFunction + gs.text.dse.could_not_check_status_p2a); if(_statusBar) { _statusBar.removeStatus(statusID); } enableSaveButtons(true); return; } var status = xml.getElementsByTagName("status")[0]; var code = status.getAttribute("code"); if (code == COMPLETED || code == SUCCESS) { callbackFunction(); } else if (code == HALTED || code == ERROR) { alert(gs.text.dse.could_not_check_status_p1 + " " + serverFunction + gs.text.dse.could_not_check_status_p2b); if(_statusBar) { _statusBar.removeStatus(statusID); } enableSaveButtons(true); } else { setTimeout(ajaxFunction, 1000); } } } ajax.send(); } ajaxFunction(); } function removeCollectionsFromBuildList(collections) { var tempArray = new Array(); for(var i = 0; i < _collectionsToBuild.length; i++) { var found = false; for(var j = 0; j < collections.length; j++) { if(collections[j] == _collectionsToBuild[i]) { found = true; break; } } if(!found) { tempArray.push(_collectionsToBuild[i]); } } _collectionsToBuild = tempArray; } function checkForErrors(xml) { var errorElems = xml.getElementsByTagName("error"); if(errorElems && errorElems.length > 0) { var errorString = gs.text.dse.error_saving_changes + ": "; for(var i = 0; i < errorElems.length; i++) { errorString += " " + errorElems.item(i).firstChild.nodeValue; } alert(errorString); return true; } return false; //No errors } function validateXML(txt) { // code for IE if (window.ActiveXObject) { var xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); xmlDoc.async = "false"; xmlDoc.loadXML(document.all(txt).value); if(xmlDoc.parseError.errorCode!=0) { txt = dse.error_code + ": " + xmlDoc.parseError.errorCode + "\n"; txt = txt + dse.error_reason + ": " + xmlDoc.parseError.reason; txt = txt + dse.error_line + ": " + xmlDoc.parseError.line; console.log(txt); return null; } return xmlDoc; } // code for Mozilla, Firefox, Opera, etc. else if (document.implementation.createDocument) { var parser = new DOMParser(); var xmlDoc = parser.parseFromString(txt,"text/xml"); if (xmlDoc.getElementsByTagName("parsererror").length > 0) { console.log(gs.text.dse.xml_error); return null; } return xmlDoc; } else { console.log(gs.text.dse.browse_cannot_validate_xml); } return null; } function onVisibleMetadataSetChange() { var metadataList = document.getElementById("metadataSetList"); var index = metadataList.selectedIndex; var options = metadataList.getElementsByTagName("OPTION"); var selectedOption = options[index]; var selectedSet = selectedOption.value; changeVisibleMetadata(selectedSet); } function changeVisibleMetadata(metadataSetName) { var metaSetList = metadataSetName.split(","); var tables = document.getElementsByTagName("TABLE"); for(var i = 0; i < tables.length; i++) { var id = tables[i].getAttribute("id"); if(id && id.search(/^meta/) != -1) { var rows = tables[i].getElementsByTagName("TR"); for(var j = 0; j < rows.length; j++) { if(metadataSetName == "All") { rows[j].style.display = "table-row"; } else { var cells = rows[j].getElementsByTagName("TD"); // metadata name cell might have the multivalue indicator in it, so just want the first word var cellName = cells[0].innerHTML.split(" ")[0]; if(cellName.indexOf(".") == -1) { rows[j].style.display = "none"; } else { var setName = cellName.substring(0, cellName.lastIndexOf(".")); if (metaSetList.indexOf(setName)!= -1) { rows[j].style.display = "table-row"; } else { rows[j].style.display = "none"; } } } } } } } function asyncRegisterEditSection(cell) { //This registering can cause a sizeable delay so we'll thread it (effectively) so the browser is not paused cell.originalValue = cell.value; setTimeout(function(){ addEditableState(cell, editableInitStates); // finished initialising one more editable element, // so decrement the counter keeping track of how many elements still need initialising editableElementsInitialisationProgress--; },0); } function addOptionToList(list, optionvalue, optiontext, selected) { var newOption = $(""); } else { nameCell = $(""); } nameCell.attr("class", "metaTableCellName"); var valueCell = $("
" + name + " "+mvm_delimiter+"" + name + "", {"class": "metaTableCell"}); var textValue = $("