/** 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 = $("