/*
* sol.common.forms.Utils.initializeForm function will be executed when the page is loaded as long this script file is included.
*/
window.$initFrame = window.initFrame;
window.initFrame = function () {
window.$initFrame && window.$initFrame();
window.setTimeout(function () {
sol.common.forms.Utils.initializeForm();
}, 100);
};
/**
* Helper functions for ELOwf forms
*
* @author MW, ELO Digital Office GmbH
* @version 1.03.006
*
* @requires sol.common.ObjectUtils
*/
sol.define("sol.common.forms.Utils", {
singleton: true,
unitSuffix: "_UNIT",
wfMapSavedFlag: "WF_MAP_FORM_SAVED",
roundingFunctions: {
CHF: function (decimal) {
var roundedDecimal;
roundedDecimal = decimal.times(20).toDecimalPlaces(0).dividedBy(20);
return roundedDecimal;
}
},
/**
* Hides the tab bar if only one tab was added to the form.
*/
hideTabBarIfOnlyOneTab: function () {
var me = this,
i, tabs, firstTabContainer = document.querySelector(".tabs");
if (firstTabContainer) {
tabs = firstTabContainer.querySelectorAll(".tabs > ul > li");
if (tabs.length <= 1) {
document.getElementById("elotable").className += " hideTabBar";
} else {
for (i in tabs) {
tabs[i].onclick = me.scrollToTop;
}
}
}
},
/**
* Reset form layout if page content changes.
*/
resetFormLayout: function () {
var d = document.getElementById("elo_wf_form");
if (d) {
d.classList.add("hidden");
setTimeout(function () {
document.getElementById("elo_wf_form").classList.remove("hidden");
sol.common.forms.Utils.updateHeaderHeight();
sol.common.forms.Utils.updateFooterHeight();
}, 10);
}
},
/**
* Scroll to top of the page.
*/
scrollToTop: function () {
document.body.scrollTop = 0;
sol.common.forms.Utils.resetFormLayout();
},
/**
* Set main header if class is set.
*/
setMainHeader: function () {
if (document.querySelector(".mainheader")) {
var headTables = document.querySelectorAll("#elotable .edittable"),
i, contentContainer, topNotification;
if (headTables.length >= 1) {
for (i in headTables) {
if (headTables[i].querySelector(".mainheader")) {
// Set identifier for main header
headTables[i].className += " mainheadertable";
// Set identifier for content container
contentContainer = headTables[i].nextElementSibling;
if (contentContainer) {
contentContainer.className += " maincontent";
}
// Hide header or calculate top margin
if (document.querySelector("body.version-gt-20 .mainheader.hide-header-gt-20")) {
document.body.className += " hideMainHeader";
} else if (contentContainer) {
contentContainer.style.marginTop = (headTables[i].offsetHeight || 0) + "px";
}
// Check for top notification
topNotification = document.querySelector("#topnotification");
if (topNotification) {
document.body.className += " disabledform";
if (!topNotification.textContent.length) {
document.body.className += " hideNotificationHeader";
}
}
break;
}
}
}
}
},
/**
* Set footer settings and calculate height.
*/
setMainFooter: function () {
if (document.querySelector("#elotable .sysarea")) {
var me = this;
// Calculate footer margin
me.updateFooterHeight();
}
},
* Update top margin because of main header height.
*/
updateHeaderHeight: function () {
var hideHeader = document.querySelector(".hideMainHeader"),
mainheader = document.querySelector(".mainheadertable"),
maincontent = document.querySelector(".maincontent");
if (!hideHeader && mainheader && maincontent) {
maincontent.style.marginTop = (mainheader.offsetHeight || 0) + "px";
}
},
* Update bottom margin because of footer height.
*/
updateFooterHeight: function () {
var sysarea = document.querySelector("#elotable .sysarea"),
footercontent = sysarea.querySelector("#FlowNext");
if (sysarea && footercontent) {
sysarea.style.marginTop = ((footercontent.offsetHeight || 0) + 17) + "px";
}
},
* Mapping list for supported background colors in mainheader table
*/
headerColors: {
white: "whiteheader",
light: "lightheader",
info: "infoheader",
success: "successheader",
warning: "warningheader",
danger: "dangerheader"
},
* Set background color in mainheader table
*/
setHeaderColor: function (color) {
var i, me = this;
if (color && color in me.headerColors) {
for (i in me.headerColors) {
document.body.classList.remove(me.headerColors[i]);
}
document.body.classList.add(me.headerColors[color]);
}
},
* Clear background color in mainheader table
*/
clearHeaderColor: function () {
var i, me = this;
for (i in me.headerColors) {
document.body.classList.remove(me.headerColors[i]);
}
},
* Show single header description line
*/
showHeaderDescription: function (identifier, color) {
var me = this,
message;
if (message = document.getElementById(identifier)) {
message.parentElement.classList.remove("hidden");
} else if (message = document.querySelector("." + identifier)) {
message.classList.remove("hidden");
} else {
return false;
}
me.setHeaderColor(color);
if (document.querySelector(".hide-header-gt-20")) {
document.querySelector(".hide-header-gt-20").classList.add("show-temporary");
document.querySelector(".hide-header-gt-20").classList.remove("hide-header-gt-20");
if (!document.body.classList.contains("actionMode")) {
document.body.classList.remove("hideMainHeader");
}
me.updateHeaderHeight();
}
},
* Hide specific header description line
*/
hideHeaderDescription: function (identifier) {
var me = this,
message;
if (message = document.getElementById(identifier)) {
message.parentElement.classList.add("hidden");
} else if (message = document.querySelector("." + identifier)) {
message.classList.add("hidden");
} else {
return false;
}
me.clearHeaderColor();
if (document.querySelector(".show-temporary")) {
document.querySelector(".show-temporary").classList.add("hide-header-gt-20");
document.querySelector(".show-temporary").classList.remove("show-temporary");
if (!document.body.classList.contains("actionMode")) {
document.body.classList.add("hideMainHeader");
}
me.updateHeaderHeight();
}
},
/**
* Set full-width flag if class is set.
*/
setFullWidth: function () {
var me = this, i, formElements, formTable;
// Add class .elo-full-width to all relevant edittables
formElements = document.querySelectorAll("#elotable .edittable .full-width");
if (formElements.length >= 1) {
for (i in formElements) {
formTable = me.getTable(formElements[i]);
if (formTable) {
formTable.classList.add("elo-full-width");
}
}
}
},
/**
* Set responsive flag if class is set.
*/
setResponsive: function () {
var me = this,
i, viewport, formElements, formElement;
if (document.querySelector(".responsive")) {
// Set mobile viewport meta info
viewport = document.querySelector("meta[name=viewport]");
if (viewport) {
viewport.setAttribute("content", "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0");
} else {
viewport = document.createElement("meta");
viewport.name = "viewport";
viewport.content = "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0";
document.getElementsByTagName("head")[0].appendChild(viewport);
}
// Add class .elo-responsive to all relevant edittables
formElements = document.querySelectorAll("#elotable .edittable");
if (formElements.length >= 1) {
for (i in formElements) {
formElement = formElements[i];
if (formElement.tagName && formElement.querySelector(".responsive")) {
formElement.className += " elo-responsive";
}
}
}
// Add class .formlistheader to all relevant tr elements
formElements = document.querySelectorAll("#elotable tr td.formlistheader:first-child");
if (formElements.length >= 1) {
for (i in formElements) {
formElement = formElements[i];
if (formElement.tagName) {
formElement.parentNode.className += " formlistheader";
}
}
}
// Reset layout when resizing the browser window
window.onresize = me.resetFormLayout;
}
},
/**
* Register table navigation
*/
registerTableNavigation: function () {
var me = this;
document.addEventListener("keydown", me.navigateTable.bind(me), false);
},
keyCodeArrowLeft: 37,
keyCodeArrowUp: 38,
keyCodeArrowRight: 39,
keyCodeArrowDown: 40,
navigateTable: function (event) {
var me = this,
isArrowKey, field, fieldName, baseFieldName, fieldNameIndex, nextField,
dynKwlCmp = document.getElementById("keywordlist");
isArrowKey = me.isArrowKey(event.keyCode);
if (!isArrowKey ||
(dynKwlCmp && dynKwlCmp.offsetLeft >= 0)) {
// disable if dynKwl is opened
return;
}
field = event.target;
fieldName = field.name;
fieldNameIndex = me.getFieldNameIndex(fieldName);
if (fieldNameIndex == "") {
return;
}
switch (event.keyCode) {
case me.keyCodeArrowLeft:
if ((typeof field.selectionStart != "number") || (field.selectionStart == 0)) {
nextField = me.getNextWriteableHorizontalField(field, -1);
}
break;
case me.keyCodeArrowUp:
baseFieldName = me.getFieldNamePrefix(fieldName);
nextField = me.getNextWriteableVerticalField(baseFieldName, fieldNameIndex, -1);
break;
case me.keyCodeArrowRight:
if ((typeof field.selectionStart != "number") || (field.selectionStart == field.value.length)) {
nextField = me.getNextWriteableHorizontalField(field, 1);
}
break;
case me.keyCodeArrowDown:
baseFieldName = me.getFieldNamePrefix(fieldName);
nextField = me.getNextWriteableVerticalField(baseFieldName, fieldNameIndex, 1);
break;
default:
break;
}
if (nextField) {
nextField.focus();
if (typeof nextField.selectionStart == "number") {
nextField.selectionStart = nextField.value.length;
}
event.preventDefault();
}
},
/**
* @private
* Returns the next writeable horizontal field
* @param {HTMLElement} field Field
* @param {HTMLElement} columnCount Column count
* @return {HTMLElement} Next horizontal input field
*/
getNextWriteableHorizontalField: function (field, columnCount) {
var me = this;
do {
field = me.getNextHorizontalField(field, columnCount);
if (!field) {
return;
}
} while (field.readOnly);
return field;
},
/**
* @private
* Returns the next horizontal field
* @param {HTMLElement} field Field
* @param {HTMLElement} columnCount Column count
* @return {HTMLElement} Next horizontal input field
*/
getNextHorizontalField: function (field, columnCount) {
var me = this,
fieldName, nextField, nodeList, i, nextNodeIndex;
fieldName = field.name;
nodeList = me.getInputsInRow(field);
for (i = 0; i < nodeList.length; i++) {
field = nodeList[i];
if (field.name == fieldName) {
nextNodeIndex = i + columnCount;
if ((nextNodeIndex > -1) && (nextNodeIndex < nodeList.length)) {
nextField = nodeList[nextNodeIndex];
return nextField;
}
}
}
},
/**
* @private
* Return the next writeable vertical input field
* @param {String} baseFieldName Base field name
* @param {String} fieldNameIndex Field name index
* @param {String} rowCount Row count
* @return {HTMLElement} Next vertical input field
*/
getNextWriteableVerticalField: function (baseFieldName, fieldNameIndex, rowCount) {
var me = this,
field;
do {
field = me.getNextVerticalField(baseFieldName, fieldNameIndex, rowCount);
if (!field) {
return;
}
if (rowCount < 0) {
rowCount--;
} else {
rowCount++;
}
} while (field.readOnly);
return field;
},
/**
* @private
* Return the next vertical input field
* @param {String} baseFieldName Base field name
* @param {String} fieldNameIndex Field name index
* @param {String} rowCount Row count
* @return {HTMLElement} Next vertical input field
*/
getNextVerticalField: function (baseFieldName, fieldNameIndex, rowCount) {
var nextIndex, nextFieldName, nextField;
nextIndex = fieldNameIndex + rowCount;
if (nextIndex < 0) {
return;
}
nextFieldName = baseFieldName + nextIndex;
nextField = $var(nextFieldName);
return nextField;
},
/**
* Checks whether the pressed key is an arrow key
* @param {Number} keyCode Key code;
* @return {Boolean}
*/
isArrowKey: function (keyCode) {
var me = this,
arrowKeyCodes, isArrowKey;
arrowKeyCodes = [me.keyCodeArrowLeft, me.keyCodeArrowUp, me.keyCodeArrowRight, me.keyCodeArrowDown];
isArrowKey = (arrowKeyCodes.indexOf(keyCode) > -1);
return isArrowKey;
},
/**
* Returns the parent table
* @param {HTMLElement} element Element
* @return {HTMLElement} Table
*/
getParentTable: function (element) {
element = element.parentNode;
while (element) {
if (element.id == "elotable") {
return element;
}
element = element.parentNode;
}
},
/**
* Set CSS Classes .
*/
setActionMode: function () {
var mode = "",
i, query, vars, pair;
query = window.location.search.substring(1);
vars = query.split("&");
if (vars) {
for (i = 0; i < vars.length; i++) {
if (vars[i]) {
pair = vars[i].split("=");
if (pair[0] == "mode") {
mode = pair[1];
break;
}
}
}
}
if (mode == "launchpad") {
document.body.className += " actionMode hideMainHeader";
}
},
/**
* Initializing actions after loading the form.
*/
initializeForm: function () {
var me = this,
$saveClicked,
$onDynListItemSelected,
$sendDirty;
if (me.formIsInitialized === true) {
return;
}
me.formIsInitialized = true;
me.hideTabBarIfOnlyOneTab();
me.setActionMode();
me.setMainHeader();
me.setMainFooter();
me.setFullWidth();
me.setResponsive();
me.registerTableNavigation();
$saveClicked = window.saveClicked;
window.saveClicked = function () {
$update(me.wfMapSavedFlag, "1", true);
return $saveClicked();
};
if (window.onDynListItemSelected) {
$onDynListItemSelected = window.onDynListItemSelected;
window.onDynListItemSelected = function (item, name) {
me.dynListItemSelected = true;
$onDynListItemSelected.apply(this, arguments);
};
}
$sendDirty = elo.elowf.CommUtils.sendDirty;
elo.elowf.CommUtils.sendDirty = function () {
me.pageIsDirty = true;
$sendDirty.apply(this, arguments);
};
},
/**
* Initializes an index server connection and sets both elo.IX and elo.CONST.
*
* By default the relative url is used. If this url is not accesible for some reason the internal absolute url is tried instead.
*
* @param {Function} successCallback
* @param {Function} failureCallback
* @param {boolean} absoluteUrl defines wheather to use an absolute url or not. Defaults to false.
*/
initializeIxSession: function (successCallback, failureCallback, absoluteUrl) {
var me = this,
ixUrl, ixLib, ixUtils, ixUtilsUrl, ixServiceUrl,
onload = function () {
elo = elo || {};
try {
ixServiceUrl = ixUrl + "/ix";
console.info("establishing IX connection: " + ixServiceUrl);
elo.connFact = new de.elo.ix.client.IXConnFactory(ixServiceUrl, "ELO WF", "Business Solution");
elo.connFact.sessOpts = elo.connFact.sessOpts || {};
elo.connFact.sessOpts["ix.translateTerms"] = "true";
elo.connFact.sessOpts["ix.startDocMaskWorkflows"] = "true";
elo.connFact.connProps = elo.connFact.connProps || {};
elo.connFact.connProps[elo.connFact.NB_OF_REVERSE_CNNS] = 0;
elo.IX = elo.connFact.createFromTicket(ELO_PARAMS.ELO_TICKET);
elo.IX.getLoginResult().clientInfo.language = me.getFormLanguage();
elo.CONST = elo.IX.getCONST();
elo.data = elo.data || {};
elo.data.user = {};
elo.data.user.id = elo.IX.getUserId();
elo.data.user.name = elo.IX.getUserName();
} catch (ex) {
me.initializedIxSession = false;
alert("error initializing ix connection: " + (ex && ex.msg ? ex.msg : ex));
return;
}
if (successCallback) {
successCallback();
}
};
// define IX Url
ixUrl = ELO_PARAMS.ELOIX_PATH.substring(0, ELO_PARAMS.ELOIX_PATH.lastIndexOf("/"));
if (!absoluteUrl) {
ixUrl = ixUrl.substring(ixUrl.indexOf("/ix"));
}
if (me.initializedIxSession && elo && elo.IX) {
if (successCallback) {
successCallback();
}
return;
} else if (me.initializedIxSession && (typeof de !== "undefined") && de.elo && de.elo.ix && de.elo.ix.client) {
onload();
} else if (me.initializedIxSession) {
window.setTimeout(function () {
me.initializeIxSession(successCallback);
}, 50);
return;
}
me.initializedIxSession = true;
ixLib = document.createElement("script");
ixLib.type = "text/javascript";
ixUtilsUrl = ixUrl + "/EloixClient-min.js";
console.info("loading ix utils: " + ixUtilsUrl);
ixLib.src = ixUtilsUrl;
ixLib.onerror = function (event) {
var src, message;
src = (event && event.srcElement && event.srcElement.src) ? event.srcElement.src : "";
message = "Error while loading IX library: " + src;
if (!absoluteUrl) {
console.info("Initializing session with absolute url failed. Using relative url instad.");
me.initializedIxSession = false;
me.initializeIxSession(successCallback, failureCallback, true);
} else if (failureCallback) {
failureCallback(message);
} else {
eloAlert(message, "Error");
}
};
ixLib.onload = onload;
if (!document.getElementById("sol_common_IxUtils")) {
ixUtils = document.createElement("script");
ixUtils.id = "sol_common_IxUtils";
ixUtils.type = "text/javascript";
ixUtils.src = "lib_sol.common.IxUtils";
document.body.appendChild(ixUtils);
}
document.body.appendChild(ixLib);
},
/**
* Registers an element for update.
*
* To do so, it calls the rule defined by `ruleName` with the wf objects objId (as `param1`).
*
* @since 1.05.000 this can be called without a `ruleName` to register the element for direct update (without using the job queue). The common_monitoring package hast to be installed.
*
* Update will only be registered, if the page has changed.
* This only applies if the form was initialized using {@link #initializeForm}.
* If not, the update will always be executed.
*
* @param {String} ruleName
*/
registerUpdate: function (ruleName) {
var me = this,
req, url, rfName, rfParams, rfErrorMsg;
if ((me.formIsInitialized !== true) || (me.pageIsDirty === true) || (me.dynListItemSelected === true)) {
if (ELO_PARAMS.WF_MAP_COMMON_SKIP_UPDATE_REGISTRATION === "true") {
console.info("Skip update registration: 'WF_MAP_COMMON_SKIP_UPDATE_REGISTRATION' is set to 'true'");
return;
}
if (me.checkVersion(ELOWF_VERSION, "10.01.000")) {
if (ruleName) {
rfName = "RF_sol_common_service_ExecuteAsAction";
rfParams = {
action: ruleName,
objId: ELO_PARAMS.ELO_OBJID,
config: {}
};
rfErrorMsg = "Failed to call ELOas rule '" + ruleName + "' via '" + rfName + "'";
} else {
rfName = "RF_sol_common_monitoring_function_RegisterUpdate";
rfParams = {
objId: ELO_PARAMS.ELO_OBJID,
registerFlowId: ELO_PARAMS.ELO_FLOWID,
registerNodeId: ELO_PARAMS.ELO_NODEID
};
rfErrorMsg = "Failed to register update using '" + rfName + "'";
}
me.callRegisteredFunction(
rfName,
rfParams,
function (succObj) {
console.info("Registered update for '" + rfParams.objId + "'");
},
function (errObj) {
console.error(rfErrorMsg + " : " + JSON.stringify(errObj));
}
);
} else {
req = new XMLHttpRequest();
url = me.getAsBaseUrl() + "?cmd=get&name=" + ruleName + "¶m1=" + ELO_PARAMS.ELO_OBJID + "&ticket=" + ELO_PARAMS.ELO_TICKET;
req.open("GET", url, true);
req.onreadystatechange = function () {
if (req.readyState !== 4) {
return;
}
if (req.status !== 200) {
console.error("Failed to call ELOas rule '" + ruleName + "' via XMLHttpRequest: statusCode=" + req.status);
}
};
req.send(null);
}
}
},
/**
* Returns the ELOas base URL
* @return {String} ELOas base URL
*/
getAsBaseUrl: function () {
var me = this,
asUrl, formLocation, asLocation, asProxyUrl;
asUrl = ELO_PARAMS.ELOAS_PATH;
formLocation = window.location;
if (!formLocation.port) {
asLocation = me.getLocation(asUrl);
if (asLocation.port) {
asProxyUrl = formLocation.protocol + "//" + formLocation.host + asLocation.path;
return asProxyUrl;
}
}
return asUrl;
},
/**
* Gets the location info from a given URL
* @param {String} url URL
* @return {Object} urlParts
* @return {String} location.url Complete URL
* @return {String} location.protocol Protocol
* @return {String} location.hostName Host name
* @return {String} location.port Port
* @return {String} location.path Path
*/
getLocation: function (url) {
var location,
parts, hostParts;
location = {
url: url
};
if (url) {
parts = url.split("/");
if ((parts.length > 2) && (parts[0].toLowerCase().indexOf("http") == 0) && !parts[1]) {
location.protocol = parts[0];
hostParts = parts[2].split(":");
location.hostName = hostParts[0];
if (hostParts.length > 1) {
location.port = hostParts[1];
}
if (parts.length > 3) {
parts.shift();
parts.shift();
parts.shift();
location.path = "/" + parts.join("/");
}
}
}
return location;
},
/**
* Returns the language of the form
* @returns {String} Language
*/
getFormLanguage: function () {
return document.querySelector("input[name=lang]").getAttribute("value");
},
/**
* Check wether mandatory fields exist
* @param {Array} fieldNames
*/
checkMandatoryFields: function (fieldNames) {
var me = this,
missingFields = [],
i, fieldName, content;
if (!fieldNames || (fieldNames.length == 0)) {
return;
}
for (i = 0; i < fieldNames.length; i++) {
fieldName = fieldNames[i];
if (!me.fieldExists(fieldName)) {
missingFields.push(fieldName);
}
}
if (missingFields.length > 0) {
content = "Missing fields:\r\n" + missingFields.join("\r\n");
eloAlert(content, "Missing fields");
}
},
/**
* Checks wether a field exists
* @param {String} fieldName
* @return {Boolean}
*/
fieldExists: function (fieldName) {
if (!fieldName) {
throw "Field name is empty";
}
return !!$var(fieldName);
},
/**
* Disables the validation if cancel button is pressed
*
* ### Example:
* function nextClicked(id) {
* sol.common.forms.Utils.disableCancelButtonValidation(id, ["sol.common.wf.node.cancel"]);
* return true;
* }
*
* @param {String} successorNodeId Node ID of the successor node
* @param {Array} cancelButtonTranslationKeys Cancel button translation key
* @param {Object} params Parameters
* @param {String} [params.mode=REMOVE_TABLE] Mode: `REMOVE_VALIDATION_ATTRIBUTES` deletes only the validation attributes
* @return {Boolean}
*/
disableCancelButtonValidation: function (successorNodeId, cancelButtonTranslationKeys, params) {
var me = this,
i, nextButtonIndex, pressedNextButtonTranslationKey, cancelButtonTranslationKey;
params = params || {};
if (!successorNodeId) {
console.warn("Successor node ID is empty");
}
if (!cancelButtonTranslationKeys) {
console.warn("Cancel button translation keys are empty");
return;
}
if (!sol.common.ObjectUtils.isArray(cancelButtonTranslationKeys)) {
console.warn("Cancel button translation keys must be an array");
return;
}
nextButtonIndex = me.getNextButtonIndex(successorNodeId);
if (!nextButtonIndex) {
console.warn("Next button not found");
return;
}
pressedNextButtonTranslationKey = ELO_PARAMS["KEY_NEXT_" + nextButtonIndex];
for (i = 0; i < cancelButtonTranslationKeys.length; i++) {
cancelButtonTranslationKey = cancelButtonTranslationKeys[i];
if (pressedNextButtonTranslationKey == cancelButtonTranslationKey) {
if (params && params.mode && (params.mode.indexOf("REMOVE_VALIDATION_ATT") == 0)) {
me.removeValidationAttributes();
} else {
me.removeTables();
}
me.removeHiddenCheckboxes();
me.setSuccessor(successorNodeId);
return true;
}
}
return false;
},
/**
* @private
* Deletes the validation attributes
*/
removeValidationAttributes: function () {
var inputs, i, input, eloverify;
inputs = document.querySelectorAll("input, textarea");
for (i = 0; i < inputs.length; i++) {
input = inputs[i];
eloverify = input.getAttribute("eloverify");
if (eloverify) {
eloverify = eloverify.replace("notemptyforward");
eloverify = eloverify.replace(/min\:\d+/, "");
eloverify = eloverify.replace(/max\:\d+/, "");
input.setAttribute("eloverify", eloverify);
}
}
},
/**
* Remove all tables within the form to avoid validation
*/
removeTables: function () {
var tables, table, i;
tables = document.querySelectorAll("#elotable table");
for (i = 0; i < tables.length; i++) {
table = tables[i];
table.parentNode.removeChild(table);
}
},
/**
* Remove all checkboxes within the form to avoid validation
*/
removeHiddenCheckboxes: function () {
var checkboxes, checkbox, i;
checkboxes = document.querySelectorAll("input[name^='HIDDEN_'][value='CHECKBOX']");
for (i = 0; i < checkboxes.length; i++) {
checkbox = checkboxes[i];
checkbox.parentNode.removeChild(checkbox);
}
},
/**
* Set successor node
* @param {String} successorNodeId Successor node id
*/
setSuccessor: function (successorNodeId) {
var nextNodeElem;
nextNodeElem = document.querySelector("input[name='NEXTNODE']");
if (nextNodeElem) {
nextNodeElem.setAttribute("value", successorNodeId);
}
},
/**
* Returns the translation key of the next button by a given nodeId
* @param {String} nodeId
* @return {String} Translation key
*/
getNextButtonTranslationKey: function (nodeId) {
var me = this,
nextButtonIndex, nextButtonTranslationKey;
nextButtonIndex = me.getNextButtonIndex(nodeId);
if (!nextButtonIndex) {
console.warn("Next button not found");
return;
}
nextButtonTranslationKey = ELO_PARAMS["KEY_NEXT_" + nextButtonIndex];
return nextButtonTranslationKey;
},
/**
* Returns the index of the next button
* @param {String} successorNodeId Node ID of the successor node
* @return {Number} Index of the next button
*/
getNextButtonIndex: function (successorNodeId) {
var nextProp, nextPropParts, i, nodeId,
maxButtonId = 100;
for (i = 1; i < maxButtonId; i++) {
nextProp = ELO_PARAMS["NEXT_" + i];
if (!nextProp) {
break;
}
nextPropParts = nextProp.split("\t");
if (nextPropParts && (nextPropParts.length > 0)) {
nodeId = nextPropParts[0].trim();
if (nodeId == successorNodeId) {
return i;
}
}
}
},
/**
* generates a user image url relative to the current form.
* @param {String} username ELO Username
* @param {String} userid ELO User id
* @return {String}
*/
getUserImageUrl: function (username, userid) {
return "../social/api/feed/img/users/" + userid + "/" + username + "/" + new Date().getTime();
},
/**
* Renders images for a given user set. Internally calls applyUserImage on each entry of the map.
* If imageTargetField is not set, userNameMap will be used as imageTargetField.
* @param {String} userNameMap Name of the map field that contains the username
* @param {String} userIdMap Name of the field that contains the user id
* @param {String} imageTargetField Name of the field in which to show the userimage
*/
applyUserImages: function (userNameMap, userIdMap, imageTargetField) {
var i = 1;
imageTargetField = imageTargetField || userNameMap;
while ($var(userNameMap + i)) {
this.applyUserImage(userNameMap + i, userIdMap + i, imageTargetField + i);
i += 1;
}
},
/**
* Renders a user image
* If imageTargetField is not set, userNameMap will be used as imageTargetField.
* @param {String} userNameMap Name of the map field that contains the username
* @param {String} userIdMap Name of the field that contains the user id
* @param {String} imageTargetField Name of the field in which to show the userimage
*/
applyUserImage: function (userNameMap, userIdMap, imageTargetField) {
var img, cont;
imageTargetField = imageTargetField || userNameMap;
if ($val(userNameMap) && $val(userIdMap)) {
img = img = sol.common.forms.Utils.getUserImageUrl($val(userNameMap), $val(userIdMap));
} else {
img = "";
}
cont = document.querySelector('[name="' + imageTargetField + '"]');
if (cont) {
cont = cont.parentElement;
cont.style.backgroundImage = img ? "url('" + img + "')" : "";
}
},
/**
* Returns the surrounding table
* @param {HTMLElement} element HTML element
* @return {HTMLElement}
*/
getTable: function (element) {
var me = this;
if (!element) {
throw "Element is empty";
}
return me.getParentByTagName(element, "TABLE");
},
/**
* Returns the surrounding row
* @param {HTMLElement} element HTML element
* @return {HTMLElement}
*/
getRow: function (element) {
var me = this;
if (!element) {
throw "Element is empty";
}
return me.getParentByTagName(element, "TR");
},
/**
* Returns the surrounding cell
* @param {HTMLElement} element HTML element
* @return {HTMLElement}
*/
getCell: function (element) {
var me = this;
if (!element) {
throw "Element is empty";
}
return me.getParentByTagName(element, "TD");
},
/**
* Returns the template
* @param {HTMLElement} element HTML element
* @return {HTMLElement}
*/
getTemplate: function (element) {
var me = this;
if (!element) {
throw "Element is empty";
}
return me.getParentByTagName(element, "tbody");
},
/**
* Returns a parent element by a given tag name
* e.g. to find the surrounding table of an element
* @param {HTMLElement} element HTML element.
* @param {String} tagName Tag name of the wanted element
* @return {HTMLElement}
*/
getParentByTagName: function (element, tagName) {
if (!element) {
throw "Start element is empty";
}
if (!tagName) {
throw "Tag name is empty";
}
do {
element = element.parentElement;
if (!element) {
return;
}
if (element.nodeName.toLowerCase() == tagName.toLowerCase()) {
return element;
}
} while (element);
},
/**
* Returns the "JS add line" button
* @param {String|HTMLElement} field Field
* @return {HTMLElement}
*/
getJsAddLineButton: function (field) {
var me = this,
element, editTable, jsAddLineButton;
if (!field) {
throw "Field is empty";
}
element = (typeof field == "string") ? $var(field) : field;
if (!element) {
return;
}
editTable = me.getTable(element);
if (!editTable) {
return;
}
jsAddLineButton = editTable.querySelector("input[name='JS_ADDLINE']");
if (!jsAddLineButton) {
throw "'JS add line button' not found";
}
return jsAddLineButton;
},
/**
* Returns the "JS add line" button
* @param {String} addLineId Add line ID
* @return {HTMLElement}
*/
getJsAddLineButtonById: function (addLineId) {
var jsAddLineButton;
if (!addLineId) {
return;
}
jsAddLineButton = document.querySelector("input[name='JS_ADDLINE'][addlineid='" + addLineId + "']");
if (!jsAddLineButton) {
throw "'JS add line button' not found";
}
return jsAddLineButton;
},
/**
* Adds a listener to an JsAddLineButton
* @param {String} fieldName Field name within the JS add line table
* @param {Function} func Function
*/
addJsAddLineButtonListener: function (fieldName, func) {
var me = this,
jsAddLineButton;
if (!fieldName) {
throw "Field name is empty";
}
if (!func) {
throw "Function is empty";
}
jsAddLineButton = me.getJsAddLineButton(fieldName);
if (jsAddLineButton) {
jsAddLineButton.addEventListener("click", func);
}
},
/**
* Registers an click handler to clear a new line
* @param {String} columnName Column name
* @param {String} notEmpty Previous line must not be empty
*/
registerResetNewLineFunction: function (columnName, notEmpty) {
var me = this;
if (!columnName) {
throw "The column name is empty";
}
if (!me.columnExists(columnName)) {
return;
}
me.addJsAddLineButtonListener(columnName + "1", function () {
me.resetNewLine(columnName, notEmpty);
});
},
/**
* Resets all input fields of a new line
* @param {String} columnName Column name
* @param {String} notEmpty Previous line must not be empty
*/
resetNewLine: function (columnName, notEmpty) {
var me = this,
jsAddLineButton, lastInput, index;
if (!columnName) {
throw "The column name is empty";
}
if (!me.columnExists(columnName)) {
return;
}
lastInput = me.getLastInput(columnName);
if (notEmpty) {
index = me.getFieldNameIndex(lastInput.name);
if (!$val(columnName + (index - 1))) {
jsAddLineButton = me.getJsAddLineButton(lastInput.name);
$removeLine(jsAddLineButton, index);
return;
}
}
me.enableRow(lastInput, true);
},
/**
* Adds a callback function to the event listener of an input field.
* @param {string} event Name of the event.
* @param {string} fieldKey Field key of the input field.
* @param {object} ctx Exteution context.
* @param {function} func Callback function.
*/
addListener: function (event, fieldKey, ctx, func) {
var field = $var(ctx.field(fieldKey)),
handlerFct;
if (!field) {
return;
}
handlerFct = function () {
func.apply(ctx, arguments);
};
if (field.addEventListener) { // Modern
field.addEventListener(event, handlerFct, false);
} else if (field.attachEvent) { // Internet Explorer
field.attachEvent("on" + event, handlerFct);
}
},
/**
* Returns true, if the fieldname is a table field, otherwise false
* @param {String} s the fieldname
* @return {Boolean}
*/
isTableField: function (s) {
return (typeof s == "string") &&
!!s[1] &&
((s = +(s[s.length - 1])) === s);
},
/**
* Returns the field index
* @param {String} fieldName Field name
* @returns {String}
*/
getFieldNameIndex: function (fieldName) {
if (!fieldName) {
return "";
}
var pos = fieldName.search(/\d+$/);
if (pos > 0) {
return parseInt(fieldName.substring(pos), 10);
}
return "";
},
/**
* Returns the index number of the row
* @param {HTMLElement} field Field
* @return {String} Row index
*/
getRowIndex: function (field) {
var me = this,
row, inputs, i, input, fieldName, index;
if (!field) {
throw "Field is empty";
}
row = me.getRow(field);
if (!row) {
throw "Row not found";
}
inputs = row.querySelectorAll("input");
for (i = 0; i < inputs.length; i++) {
input = inputs[i];
fieldName = input.name;
index = me.getFieldNameIndex(fieldName);
if (index) {
return index;
}
}
},
/**
* Returns the field name without trailing numbers
* @param {Object|String} source Source element or field name
* @param {Object} params Parameters
* @param {String} [params.replaceNumberBy=""] Replace the number by this string
* @returns {String}
*/
getFieldNamePrefix: function (source, params) {
var me = this,
fieldName;
if (me.checkSource(source)) {
fieldName = source.name;
} else {
fieldName = source;
}
params = params || {};
params.replaceNumberBy = params.replaceNumberBy || "";
if (!fieldName) {
return "";
}
fieldName = fieldName.replace(/\d*$/, params.replaceNumberBy);
return fieldName;
},
/**
* Checks whether a column exists
* @param {String} columnName Column name
* @return {Boolean}
*/
columnExists: function (columnName) {
if (!columnName) {
throw "The column name is empty";
}
return !!$var(columnName + "1");
},
/**
* Return the last input field in the table
* @param {String} columnName
* @return {HTMLElement}
*/
getLastInput: function (columnName) {
var currentInput, lastInput,
i = 1;
if (!columnName) {
throw "The column name is empty";
}
while (true) {
currentInput = $var(columnName + i++);
if (currentInput) {
lastInput = currentInput;
} else {
return lastInput;
}
}
},
/**
* Sets rows read-only
* @param {String} indicatorColumnName Read-only indicator field
* @param {Function} func Function that must return a boolean to determinate whether the row should be disabled
*/
disableRowsByIndicatorField: function (indicatorColumnName, func) {
var me = this;
if (!indicatorColumnName) {
throw "The indicator column name is empty";
}
if (!$var(indicatorColumnName + "1")) {
return;
}
me.forEachRow(indicatorColumnName, function (rowIndex) {
var indicatorElement, disable;
disable = func.call(me, rowIndex);
indicatorElement = $var(indicatorColumnName + rowIndex);
me.enableRow(indicatorElement, !disable);
});
},
/**
* Enables/disables a row
* @param {type} indicatorElement
* @param {type} enable
*/
enableRow: function (indicatorElement, enable) {
var me = this,
nodeList, j, row, removeLineButton;
nodeList = me.getElementsInRow(indicatorElement);
for (j = 0; j < nodeList.length; j++) {
nodeList[j].disabled = !enable;
}
if (!enable) {
row = me.getRow(indicatorElement);
removeLineButton = row.querySelector(".jsRemoveLine");
if (removeLineButton) {
removeLineButton.parentNode.removeChild(removeLineButton);
}
}
},
/**
* Returns the input fields and buttons in the row
* @param {HTMLElement} element
* @return {NodeList}
*/
getElementsInRow: function (element) {
var me = this,
row, nodeList;
if (!element) {
throw "Element is empty";
}
row = me.getRow(element);
if (!row) {
throw "Row not found";
}
nodeList = row.querySelectorAll("input,button");
return nodeList;
},
/**
* Returns the input fields in the row
* @param {HTMLElement} element
* @return {NodeList}
*/
getInputsInRow: function (element) {
var me = this,
row, nodeList;
if (!element) {
throw "Element is empty";
}
row = me.getRow(element);
if (!row) {
throw "Row not found";
}
nodeList = row.querySelectorAll("input");
return nodeList;
},
/**
* Returns the JS add line row by ID
* @param {String} addLineId Add line ID
* @param {String} lineNo Line number
* @return {HTMLElement} row
*/
getJsAddLineRowById: function (addLineId, lineNo) {
var me = this,
jsAddLineButton, inputs, index, row;
jsAddLineButton = me.getJsAddLineButtonById(addLineId);
if (!jsAddLineButton) {
throw "Can't find JS add line button";
}
row = me.getParentByTagName(jsAddLineButton, "tr");
while (true) {
row = row.previousElementSibling;
if (!row) {
return;
}
inputs = row.querySelectorAll("input");
if (inputs.length == 0) {
continue;
}
index = me.getFieldNameIndex(inputs[0].name);
if (index == lineNo) {
return row;
} else if (index < lineNo) {
return;
}
}
},
/**
* Iterates over a table.
* @param {String} endOfTableIndicatorColumnName Name of a column to check if the line exists.
* @param {Function} func Callback function for the iteration.
* @param {Object} ctx Execution context.
*/
forEachRow: function (endOfTableIndicatorColumnName, func, ctx) {
var me = this,
i, lines;
if (!endOfTableIndicatorColumnName) {
throw "The end of table indicator column name is empty.";
}
if (!func) {
throw "The function parameter is emtpy.";
}
lines = me.getLines(endOfTableIndicatorColumnName);
for (i = 0; i < lines.length; i++) {
func.call(ctx, i + 1, lines[i]);
}
},
/**
* Calls the function `inputChanged` for fields changed by a dynamic keyword list
* @param {Object} dynListItem Dynamic keyword list item
*/
callInputChangedForDynKwlChanges: function (dynListItem) {
var fieldName, fieldNameParts, prefix, field;
for (fieldName in dynListItem) {
fieldNameParts = fieldName.split("_");
if (fieldNameParts && (fieldNameParts.length > 0)) {
prefix = fieldNameParts[0];
if (!prefix || (prefix.substr(0, 1) == "$")) {
continue;
}
if ((prefix != "IX") && (prefix != "WF")) {
fieldName = "IX_GRP_" + fieldName;
}
}
field = $var(fieldName);
if (field) {
inputChanged($var(fieldName));
}
}
},
/**
* Enables or disables forward buttons
* @param {Boolean} [disable=true] Disable button
*/
disableForwardButtons: function (disable) {
var me = this,
forwardButtons, i, forwardButton;
forwardButtons = me.getForwardButtons();
for (i = 0; i < forwardButtons.length; i++) {
forwardButton = forwardButtons[i];
forwardButton.disabled = (disable == false) ? false : true;
}
},
/**
* Returns forward buttons
* @returns {NodeList}
*/
getForwardButtons: function () {
var forwardButtons;
forwardButtons = document.querySelectorAll("button[name='NEXTNODE']");
return forwardButtons;
},
/**
* Returns a next button
* @param {Object} params Parameters
* @param {String} params.nextNodeTranslationKey Translation key of the next node
* @return {HTMLElement} Forward button
*/
getForwardButton: function (params) {
var me = this,
buttonIndex, forwardButtons, i, translationKey, forwardButton;
params = params || {};
if (params.nextNodeTranslationKey) {
for (i = 1; i < 1000; i++) {
translationKey = ELO_PARAMS["KEY_NEXT_" + i];
if (!translationKey) {
return;
}
if (translationKey == params.nextNodeTranslationKey) {
buttonIndex = i - 1;
break;
}
}
}
if (buttonIndex != undefined) {
forwardButtons = me.getForwardButtons();
if (forwardButtons && (buttonIndex < forwardButtons.length)) {
forwardButton = forwardButtons[buttonIndex];
}
}
return forwardButton;
},
/**
* Adds a class to the ´body´ tag
* @param {String} className
*/
addBodyClass: function (className) {
document.body.className += " " + className;
},
/**
* Removes a class from the ´body´ tag
* @param {String} className
*/
removeBodyClass: function (className) {
document.body.classList.remove(className);
},
/**
* Returns an ISO formatted date
* @param {String} fieldName Field name
* @param {Object} params Parameters
* @param {Boolean} params.startOfDay Start of day
* @returns {String}
*/
getIsoDate: function (fieldName, params) {
var field, isoDate;
params = params || {};
if (!$val(fieldName)) {
return "";
}
field = $var(fieldName);
if (!field) {
return;
}
isoDate = field.getAttribute("isodate") || "";
if (params.startOfDay || (isoDate.length > 8)) {
isoDate = isoDate.substr(0, 8) + "000000";
}
return isoDate;
},
/**
* Sets an ISO date
* @param {String} fieldName Field name
* @param {String} isoDate in ISO format
* @param {Object} params Parameters
* @param {Boolean} params.callInputChanged If true the function ´inputChanged´ will be called
*/
setIsoDate: function (fieldName, isoDate, params) {
var localizedDate, field;
params = params || {};
params.callInputChanged = (typeof params.callInputChanged == "undefined") ? true : params.callInputChanged;
field = $var(fieldName);
if (!field) {
return;
}
localizedDate = elo.wf.date.format(isoDate) || "";
field.setAttribute("autovalidval", localizedDate);
$update(fieldName, localizedDate);
if (params.callInputChanged) {
inputChanged($var(fieldName));
}
},
/**
* Copies an ISO date
* @param {String} srcFieldName Source field name
* @param {String} dstFieldName Destination field name
* @param {Object} params Parameters
* @param {Boolean} params.callInputChanged If true the function ´inputChanged´ will be called
*/
copyIsoDate: function (srcFieldName, dstFieldName, params) {
var me = this,
value, isoDate;
if (!$var(srcFieldName) || !$var(dstFieldName)) {
return;
}
value = $val(srcFieldName);
if (!value) {
$update(dstFieldName, "");
return;
}
isoDate = me.getIsoDate(srcFieldName);
me.setIsoDate(dstFieldName, isoDate, params);
},
/**
* Sets a default value if it's empty
* @param {String} fieldName Field name
* @param {String} defaultValue Default value
*/
setDefaultValue: function (fieldName, defaultValue) {
var value;
value = $val(fieldName);
if (!value) {
$update(fieldName, defaultValue);
}
},
/**
* Checks if the specific field has been changed or the form is loaded
* @param {Object} source Changed HTML element.
* @param {Array} fieldNames Array of field names.
* @return {undefined}
*/
isFieldChangedOrFormLoaded: function (source, fieldNames) {
var me = this;
if (!me.checkSource(source)) {
return true;
}
return me.isFieldChanged(source, fieldNames);
},
/**
* Checks if the specific field has been changed
* @param {Object} source Changed HTML element.
* @param {Array} fieldNames Array of field names.
* @return {undefined}
*/
isFieldChanged: function (source, fieldNames) {
var me = this;
if (!source) {
return false;
}
return fieldNames.some(function (fieldName) {
var fieldBaseName = me.getBaseFieldName(source.name);
return ((fieldBaseName == fieldName) || (fieldBaseName + me.unitSuffix == fieldName));
});
},
/**
* Checks if the changed input field es set
* @param {Object} source Changed input field
* @return {Boolean}
*/
checkSource: function (source) {
return (source && source.name);
},
/**
* Returns the field name without unit suffix and trailing numbers
* @param {Object|String} source Source element or field name
* @returns {String}
*/
getBaseFieldName: function (source) {
var me = this,
fieldName, unitSuffixRegExp;
if (me.checkSource(source)) {
fieldName = source.name;
} else {
fieldName = source;
}
if (!fieldName) {
return "";
}
fieldName = fieldName.replace(/\d*$/g, "");
unitSuffixRegExp = new RegExp(me.unitSuffix + "$");
fieldName = fieldName.replace(unitSuffixRegExp, "");
return fieldName;
},
/**
* Sums all values of a given column
* @param {string} columnName Name of the column
* @return {Number}
*/
sumItems: function (columnName) {
var me = this,
sum;
sum = new Decimal(0);
me.forEachRow(columnName, function (i, field) {
var decimal;
decimal = me.toDecimal(field);
sum = sum.plus(decimal);
});
return sum;
},
/**
* Returns a Decimal data type
* @param {String|HTMLElement} field Field
* @param {Object} params Parameters
* @param {Boolean} params.silent Silent
* @return {Decimal} Decimal
*/
toDecimal: function (field, params) {
var decimal, value;
if (!field) {
throw "Field is empty";
}
params = params || {};
if (!(field instanceof Element)) {
field = $var(field);
}
if (!field) {
if (params.silent) {
return;
}
throw "Field '" + field + "' not found.";
}
if (field.hasAttribute("decimal")) {
value = field.getAttribute("decimal");
} else {
value = field.value;
params.thousandsSeparator = ELO.Configuration.Amount.ThousandSep;
params.decimalSeparator = ELO.Configuration.Amount.DecimalSep;
}
value = (!!value) ? value : "0";
decimal = sol.common.DecimalUtils.toDecimal(value, params);
return decimal;
},
/**
* Write a Decimal into an input field
* @param {String} fieldName Field name
* @param {Decimal} decimal Decimal
* @param {Object} params Parameters
* @param {Boolean} params.silent Silent
* @param {Boolean} params.callInputChanged If true the function ´inputChanged´ will be called
* @param {Function} params.roundingCurrencyCode Rounding currency code
*/
updateDecimal: function (fieldName, decimal, params) {
var me = this,
field, decimalPlaces;
params = params || {};
if (!decimal) {
if (params.silent) {
return;
}
throw "Decimal is emtpy";
}
if (!fieldName) {
throw "Field name is empty";
}
if (!(fieldName instanceof Element)) {
field = $var(fieldName);
} else {
field = fieldName;
}
if (!field) {
if (params.silent) {
return;
}
throw "Field '" + fieldName + "' not found.";
}
decimalPlaces = me.getDisplayDecimalPlaces(field);
me.writeDecimalField(field, decimal, decimalPlaces, params);
},
/**
* Parse to Decimal
* @param {String} str Number as String
* @return {Decimal} Decimal
*/
parseDecimal: function (str) {
var decimal;
str = str || "";
str = str.split(" ").join("");
if (str == "null") {
str = "0";
}
str = str.split(ELO.Configuration.Amount.ThousandSep).join("");
str = str.replace(ELO.Configuration.Amount.DecimalSep, ".");
decimal = new Decimal(str);
return decimal;
},
/**
* Normalize decimals
* @param {HTMLElement} field Field
* @param {Object} params Params
*/
normalizeDecimal: function (field, params) {
var me = this,
decimalPlaces, decimal, fieldName, inputs, i, input;
if (!field) {
return;
}
if (!me.isNumeric(field)) {
return;
}
fieldName = field.name;
inputs = document.querySelectorAll("input[name='" + fieldName + "']");
for (i = 0; i < inputs.length; i++) {
input = inputs[i];
input.removeAttribute("decimal");
}
if (field.value == "") {
return;
}
decimal = me.toDecimal(field);
me.writeDecimalField(field, decimal, decimalPlaces, params);
},
/**
* Writes a Decimal
* @private
* @param {HTMLElement} field Field
* @param {Decimal} decimal Decimal
* @param {Number} decimalPlaces Decimal places
* @param {Object} params Parameters
* @param {Boolean} params.callInputChanged If true the function ´inputChanged´ will be called
* @param {Function} params.roundingCurrencyCode Rounding currency code
* @param {Function} params.roundingFunction Rounding function
*/
writeDecimalField: function (field, decimal, decimalPlaces, params) {
var me = this,
value, inputs, i, input;
params = params || {};
inputs = document.querySelectorAll("input[name='" + field.name + "']");
if (params.roundingCurrencyCode) {
params.roundingFunction = me.roundingFunctions[params.roundingCurrencyCode.toUpperCase()];
}
if (params.roundingFunction) {
decimal = params.roundingFunction.call(me, decimal);
}
for (i = 0; i < inputs.length; i++) {
input = inputs[i];
input.setAttribute("decimal", decimal.toString());
}
decimalPlaces = (typeof decimalPlaces != "undefined") ? decimalPlaces : me.getDisplayDecimalPlaces(field);
value = decimal.toDecimalPlaces(decimalPlaces).toFixed(decimalPlaces);
value = value.replace(".", ELO.Configuration.Amount.DecimalSep);
if (value == "Infinity") {
value = "";
}
$update(field.name, value);
if (params.callInputChanged) {
inputChanged(field);
}
},
/**
* Return display decimal decimalPlaces
* @param {HTMLElement} field Field
* @return {String}
*/
getDisplayDecimalPlaces: function (field) {
var eloverifyString, match, result;
if (!field) {
throw "Field is emtpy";
}
eloverifyString = field.getAttribute("eloverify");
if (eloverifyString) {
match = eloverifyString.match(/nk:(\d+)/);
if (match && (match.length == 2)) {
result = parseInt(match[1], 10);
return result;
}
}
},
/**
* Shows or hides columns
* @param {Array} columnNames Column names
* @param {Boolean} show Show columns
* @param {Object} params Parameters
*/
showColumns: function (columnNames, show, params) {
var me = this,
i, columnName;
for (i = 0; i < columnNames.length; i++) {
columnName = columnNames[i];
me.showColumn(columnName, show, params);
}
},
/**
* Show or hides a column
* @param {String} columnName Column name
* @param {Boolean} show Show column
* @param {Object} params Parameters
* @param {Boolean} [params.clear=false] Clear fields
* @param {Boolean} [params.numberOfHeaderLines=1] Number of header lines
*/
showColumn: function (columnName, show, params) {
var me = this,
field, columnIndex, addButton, tr, td, input, i;
if (!columnName) {
throw "Column name is empty";
}
params = params || {};
params.clear = (typeof params.clear == "undefined") ? false : true;
params.numberOfHeaderLines = params.numberOfHeaderLines || 1;
field = $var(columnName + "1");
if (!field) {
return;
}
field = $var(columnName + "1");
columnIndex = me.getColumnIndex(field);
if (columnIndex > -1) {
tr = me.getParentByTagName(field, "tr");
for (i = 0; i < params.numberOfHeaderLines; i++) {
tr = tr.previousElementSibling;
}
while (tr) {
addButton = tr.querySelector("input[type='button'][name='JS_ADDLINE']");
if (addButton) {
return;
}
td = tr.querySelector("*:nth-child(" + (columnIndex + 1) + ")");
if (show) {
td.style.display = "";
} else {
if (params.clear) {
input = td.querySelector("input[type='text']");
if (input) {
$update(input.name, "");
}
}
td.style.display = "none";
}
tr = tr.nextElementSibling;
}
}
},
/**
* Returns the column index
* @param {HTMLElement} field Field
* @return {Number} Column index
*/
getColumnIndex: function (field) {
var me = this,
index = 0,
td;
if (field) {
td = me.getParentByTagName(field, "TD");
while (true) {
td = td.previousElementSibling;
if (td) {
index++;
} else {
return index;
}
}
}
return -1;
},
/**
* Disables dependent fields
* @param {Object} disableDependentFieldsConfig Configuration to disable dependent fields
* @param {Object} changedInput Changed input field
*/
disableDependentFields: function (disableDependentFieldsConfig, changedInput) {
var me = this,
i, disableFieldNames, srcFieldName, key, fieldName, index, disable, lines, line;
if (!disableDependentFieldsConfig) {
return;
}
if (changedInput) {
srcFieldName = me.getFieldNamePrefix(changedInput, {
replaceNumberBy: "{i}"
});
disableFieldNames = disableDependentFieldsConfig[srcFieldName];
if (!disableFieldNames) {
return;
}
disable = !!$val(changedInput.name);
index = me.getFieldNameIndex(changedInput.name);
me.disableFields(disableFieldNames, index, disable);
} else {
for (key in disableDependentFieldsConfig) {
fieldName = key.replace("{i}", "");
lines = me.getLines(fieldName);
for (i = 0; i < lines.length; i++) {
line = lines[i];
if (line.value) {
disableFieldNames = disableDependentFieldsConfig[key];
//to get the index of the line we use our field and replace the name with an empty string
me.disableFields(disableFieldNames, line.name.replace(fieldName, ""), true);
}
}
}
}
},
/**
* Disable fields
* @param {Array} fieldNames Field names
* @param {Number} index Index
* @param {Boolean} disable
* @param {Object} params
*/
disableFields: function (fieldNames, index, disable, params) {
var me = this,
i, fieldName;
for (i = 0; i < fieldNames.length; i++) {
fieldName = fieldNames[i];
fieldName = fieldName.replace("{i}", index);
me.disableField(fieldName, disable);
}
},
/**
* Disables a field
* @param {String} fieldName Field name
* @param {Boolean} disable If true then the field will be disabled
* @param {Object} params Parameters
* @return {Boolean} Field is changed
*/
disableField: function (fieldName, disable, params) {
var field, clear;
params = params || {};
clear = (typeof params.clear == "undefined") ? true : false;
if (!fieldName) {
throw "Field name is empty";
}
field = $var(fieldName);
if (!field) {
return false;
}
if (disable) {
if (clear) {
$update(fieldName, "");
}
field.setAttribute("readonly", "readonly");
field.style.backgroundImage = "none";
} else {
field.removeAttribute("readonly");
field.style.backgroundImage = "";
}
return true;
},
/**
* Disable column
* @param {String} columnName Column name
* @param {Boolean} disable If true then the field will be disabled
* @param {Object} params Parameters
* @param {Boolean} params.clear Clear value
*/
disableColumn: function (columnName, disable, params) {
var me = this,
i = 0,
fieldName, result;
do {
i++;
fieldName = columnName + i;
result = me.disableField(fieldName, disable, params);
} while (result);
},
/**
* Ensures that a specific table row exists
* @param {String} fieldName Field name
*/
ensureRowExists: function (fieldName) {
var me = this,
field, firstFieldName, firstField, addButton;
if (!fieldName) {
throw "Field name is empty";
}
firstFieldName = me.getFieldNamePrefix(fieldName) + "1";
firstField = $var(firstFieldName);
if (!firstField) {
console.warn("First field doesn't exist. fieldName=" + firstFieldName);
return;
}
addButton = addButton || me.getJsAddLineButton(firstFieldName);
if (!addButton) {
console.warn("Addbutton not found. fieldName=" + firstFieldName);
return;
}
field = $var(fieldName);
while (!field) {
$addLine(addButton, 1);
field = $var(fieldName);
}
},
/**
* Finds a JS_ADDLINE button by a given field name
* @param {String} fieldName Field name
* @return {HTMLElement}
*/
getAddLineButton: function (fieldName) {
var me = this,
tr, field, button;
if (!fieldName) {
throw "Field name is empty";
}
field = $var(fieldName);
if (!field) {
throw "Can't find field '" + fieldName + "'";
}
tr = me.getParentByTagName(field, "tr");
while (true) {
tr = tr.nextElementSibling;
if (!tr) {
return;
}
button = tr.querySelector("input[type='button'][name='JS_ADDLINE']");
if (button) {
return button;
}
}
},
/**
* Clears remaining lines
* @param {String} fieldName Field name
*/
clearRemainingLines: function (fieldName) {
var me = this,
field, tr, inputs, i, button, input;
if (!fieldName) {
throw "Field name is empty";
}
field = $var(fieldName);
if (!field) {
return;
}
tr = me.getParentByTagName(field, "tr");
while (true) {
if (!tr) {
return;
}
button = tr.querySelector("input[type='button'][name='JS_ADDLINE']");
if (button) {
return;
}
inputs = tr.querySelectorAll("input[type='text']");
for (i = 0; i < inputs.length; i++) {
input = inputs[i];
$update(input.name, "");
}
tr = tr.nextElementSibling;
}
},
/**
* Returns true if the column is empty
* @param {String} columnName Column name
* @param {Object} params Parameters
* @param {Array} params.entriesEqualToEmpty Entries that also count as empty, e.g. `?`
* @return {Boolean}
*/
isColumnEmpty: function (columnName, params) {
var i = 1,
field, val;
params = params || {};
params.entriesEqualToEmpty = params.entriesEqualToEmpty || [];
do {
field = $var(columnName + i);
val = $val(columnName + i);
if (field && !!val && (params.entriesEqualToEmpty.indexOf(val) < 0)) {
return false;
}
i++;
} while (field);
return true;
},
/**
* Returns true if the row is empty
* @param {String} columnName Column name
* @return {Boolean}
*/
isRowEmpty: function (columnName) {
var me = this,
field, tr, inputs, i, input;
field = $var(columnName);
if (!field) {
return false;
}
tr = me.getParentByTagName(field, "tr");
if (!tr) {
return false;
}
inputs = tr.querySelectorAll("input");
for (i = 0; i < inputs.length; i++) {
input = inputs[i];
if (input.value) {
return false;
}
}
return true;
},
/**
* Shows or hides a row
* @param {String} columnName Column name
* @param {Function} callback Callback
*/
showRows: function (columnName, callback) {
var me = this,
i = 1,
field, result, tr;
if (!columnName) {
throw "Column name is empty";
}
do {
field = $var(columnName + i);
if (field) {
result = (callback) ? callback(i) : true;
tr = me.getParentByTagName(field, "tr");
if (tr) {
tr.setAttribute("style", result ? "" : "display:none;");
}
}
i++;
} while (field);
},
/**
* Registers a click handler
* @param {Object} params Parameters
* @param {String} params.name Button name
* @param {String} params.prefix Button name prefix
* @param {Object} params.ctx Context
* @param {Function} params.func Function
*/
addClickListener: function (params) {
var elements, i, element, handlerFunc;
params = params || {};
if (!params.name && !params.prefix) {
throw "Name or prefix must be set";
}
if (!params.ctx) {
throw "Context must be set";
}
if (!params.func) {
throw "Function must be set";
}
handlerFunc = function () {
params.func.apply(params.ctx, arguments);
};
if (params.prefix) {
elements = document.querySelectorAll("input[name^='" + params.prefix + "']");
} else {
elements = document.querySelectorAll("input[name='" + params.name + "']");
}
for (i = 0; i < elements.length; i++) {
element = elements[i];
element.addEventListener("click", handlerFunc, false);
}
},
/**
* Returns the number of lines
* @param {String} indicatorColumnName Indicator column name
* @return {Number} Number of lines
*/
countLines: function (indicatorColumnName) {
var me = this;
return me.getLines(indicatorColumnName).length;
},
/**
* Returns the lines
* @param {String} indicatorColumnName Indicator column name
* @return {Object} lines
*/
getLines: function (indicatorColumnName) {
var nodeList, fields;
nodeList = document.querySelectorAll('[name^="' + indicatorColumnName + '"]');
fields = Array.prototype.slice.call(nodeList).filter(function (elem) {
//Columns could start with the same prefix, e.g. IX_MAP_INVI_QUANTITY and IX_MAP_INVI_QUANTITY_UNIT.
//The querySelectorAll returns both columns so we have to filter the result.
return !isNaN(elem.name.replace(indicatorColumnName, ""));
});
return fields;
},
/**
* Calls the registered function of the given name.
* As parameter a JSON object can be given.
*
* @param {String} fctName The name of the registered function to call.
* @param {Object} paramObj The input data for the function, sent as Serialized String value of the Any object.
*
* @param {Function} success Success callback function. The argument value
* is the deserialized JSON object from the String value of the Any
* object that was returned from the registered function.
* @param {Function} failure Failure callback function the error object will be given as parameter.
*/
callRegisteredFunction: function (fctName, paramObj, success, failure) {
var me = this,
standardAppName, url, rfParams;
if (!fctName) {
throw "Function name is missing";
}
standardAppName = "sol.common.apps.BusinessSolution";
url = me.getAppApiUrl(standardAppName) + "exec_registered_fct/" + encodeURIComponent(fctName);
rfParams = {
any: JSON.stringify(paramObj)
};
me.sendPost(url, rfParams, function (resp) {
var respObj;
try {
respObj = JSON.parse(resp);
} catch (e) {
console.info("Could not parse JSON in responseText: " + resp);
failure(e);
}
success(respObj);
},
failure, {
addTicket: true,
addCookieTicket: true
});
},
/**
* Sends a post request
* @param {String} url URL
* @param {Object} dataObj Data object
* @param {Function} success Success callback function.
* @param {Function} failure Failure callback function the error object will be given as parameter.
* @param {Object} params Parameters
* @param {Object} params.reqParamsObj Request params object
* @param {Boolean} params.addTicket Add ticket
*/
sendPost: function (url, dataObj, success, failure, params) {
var me = this,
xhr, data, reqParamsString;
dataObj = dataObj || {};
params = params || {};
params.reqParamsObj = params.reqParamsObj || {};
params.contentType = params.contentType || "application/x-www-form-urlencoded";
if (params.addTicket) {
params.reqParamsObj.ticket = ELO_PARAMS.ELO_TICKET;
}
reqParamsString = me.encodeParams(params.reqParamsObj);
if (reqParamsString) {
url += "?" + reqParamsString;
}
xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
if (params.contentType) {
xhr.setRequestHeader("Content-type", params.contentType);
}
data = me.encodeParams(dataObj);
xhr.onload = function () {
var resp;
resp = xhr.responseText;
if (xhr.status == 200) {
success(resp);
} else {
failure(resp);
}
};
xhr.send(data);
},
/**
* Encodes parameters
* @param {Object} params Parameters
* @param {String} separator Separator
* @return {String}
*/
encodeParams: function (params, separator) {
var parts = [],
prop, paramsString;
params = params || {};
separator = separator || "&";
for (prop in params) {
if (params.hasOwnProperty(prop)) {
parts.push(encodeURIComponent(prop) + "=" + encodeURIComponent(params[prop]));
}
}
if (parts.length == 0) {
return "";
}
paramsString = parts.join(separator);
return paramsString;
},
/**
* Returns the ELOwf URL
* @return {String} ELOwf URL
*/
getWfUrl: function () {
var currentUrl, wfUrl;
currentUrl = window.location.href;
wfUrl = currentUrl.substr(0, currentUrl.lastIndexOf("/wf/"));
return wfUrl;
},
/**
* Returns the URL for a specific app
* @param {String} appName App name
* @return {String} ELOapp URL
*/
getAppUrl: function (appName) {
var me = this,
wfUrl, appUrl;
wfUrl = me.getWfUrl();
appUrl = wfUrl + "/apps/app/" + appName + "/";
return appUrl;
},
/**
* Returns the URL for an app API
* @param {String} appName App name
* @return {String} ELOapp API URL
*/
getAppApiUrl: function (appName) {
var me = this,
appUrl, appApiUrl;
if (!appName) {
throw "AppName is missing";
}
appUrl = me.getAppUrl(appName);
appApiUrl = appUrl + "api/";
return appApiUrl;
},
/**
* Insert list
* @param {String}labelName Label name
* @param {Array} entries Entries
* @param {String} entries[].text Text
* @param {Object} entries[].params Parameters
*/
showTemplateListWarning: function (labelName, entries) {
var me = this,
label, listElements, listElement, list, i, entry, listEntry, listEntryLink, entryTextElement,
span, spanTextNode;
label = $var(labelName);
if (!label) {
return;
}
listElements = label.getElementsByTagName("ul");
for (i = 0; i < listElements.length; i++) {
listElement = listElements[i];
label.removeChild(listElement);
}
if (!entries || (entries.length == 0)) {
me.hideTemplate(label);
return;
}
list = document.createElement("ul");
for (i = 0; i < entries.length; i++) {
entry = entries[i];
listEntry = document.createElement("li");
if (entry.style) {
listEntry.setAttribute("style", entry.style);
}
listEntryLink = document.createElement("a");
if (entry.params) {
if (entry.params.guid) {
listEntryLink.setAttribute("sordGuid", entry.params.guid);
listEntryLink.onclick = function () { // eslint-disable-line no-loop-func
var sordGuid;
sordGuid = this.getAttribute("sordGuid");
me.gotoSord(sordGuid);
};
}
}
entryTextElement = document.createTextNode(entry.text);
listEntryLink.appendChild(entryTextElement);
listEntry.appendChild(listEntryLink);
if (entry.span) {
span = document.createElement("span");
if (entry.span.style) {
span.setAttribute("style", entry.span.style);
}
spanTextNode = document.createTextNode(entry.span.text);
span.appendChild(spanTextNode);
listEntry.appendChild(span);
}
list.appendChild(listEntry);
}
label.appendChild(list);
me.showTemplate(label);
},
/**
* Goto a sord
* @param {String} guid GUID
*/
gotoSord: function (guid) {
if (!guid) {
return;
}
var data = {};
console.info("sendGoto: " + guid);
data[api.constants.communication.DATA_GUID] = guid;
api.communication.Parent.sendGoto(data);
},
/**
* Hides a template
* @param {HTMLElement} field Field
*/
hideTemplate: function (field) {
var me = this,
template;
if (!field) {
return;
}
template = me.getTemplate(field);
if (!template) {
return;
}
template.style.display = "none";
},
/**
* Shows/hides a template
* @param {HTMLElement} field Field
* @param {Boolean} [enabled=true]
*/
showTemplate: function (field, enabled) {
var me = this,
template;
enabled = (typeof enabled == "undefined") ? true : enabled;
if (!field) {
return;
}
template = me.getTemplate(field);
if (!template) {
return;
}
if (enabled) {
template.style.display = "";
} else {
template.style.display = "none";
}
},
/**
* Checks the version of ELO components
* @param {String} currentVersionString
* @param {String} requiredVersionString
* @param {Boolean} checkSubVersion (optional) Checks also the sub version.
* e.g. there is an fix in all versions in wf *.09. So if you want to check the major and sub version you have to set this boolean to true.
* Otherwise the function will return true for this example because 20.03 is greater than 12.09.
* @return {Boolean} Return true if the current version is equal or higher then the required version
*/
checkVersion: function (currentVersionString, requiredVersionString, checkSubVersion) {
var result = true,
currentRegex, requiredRegex, currentVersionMatch, requiredVersionMatch, currentPart, requiredPart, partIndex = 0;
currentRegex = /([0-9]+(\\.[0-9]+)*)/g;
requiredRegex = /([0-9]+(\\.[0-9]+)*)/g;
currentVersionMatch = currentRegex.exec(currentVersionString);
requiredVersionMatch = requiredRegex.exec(requiredVersionString);
while (requiredVersionMatch !== null) {
currentPart = (currentVersionMatch) ? parseInt(currentVersionMatch[0], 10) : 0;
requiredPart = parseInt(requiredVersionMatch[0], 10);
if (requiredPart > currentPart) {
result = false;
break;
} else if (requiredPart < currentPart) {
if (partIndex == 0 && checkSubVersion) {
result = false;
break;
}
result = true;
break;
}
currentVersionMatch = currentRegex.exec(currentVersionString);
requiredVersionMatch = requiredRegex.exec(requiredVersionString);
partIndex++;
}
return result;
},
/**
* This creates a hidden field to write values to the sord.
* If a field already exists the existing field will be updated.
* @param {Object} cfg
* @param {String} [cfg.type=GRP] GRP|MAP|WFMAP
* @param {String} cfg.key
* @param {String} value
*/
setHiddenValue: function (cfg, value) {
var field, input, form;
switch (cfg.type) {
case "MAP":
field = "IX_MAP_" + cfg.key;
break;
case "WFMAP":
field = "WF_MAP_" + cfg.key;
break;
default:
field = "IX_GRP_" + cfg.key;
break;
}
input = $var(field);
if (!input) {
form = document.getElementById("elo_wf_form");
input = document.createElement("input");
input.type = "hidden";
input.name = field;
form.append(input);
}
$update(field, value);
},
/**
* Removes the field name prefix
* @param {String} fieldName Field name
* @return {String} Field name without prefix
*/
removeFieldNamePrefix: function (fieldName) {
if (!fieldName) {
return "";
}
fieldName = fieldName.replace(/^(IX|WF)_(GRP|MAP|BLOB)_/, "");
return fieldName;
},
/**
* Returns a template Sord
* @return {Object} Template sord
*/
getTemplateSord: function () {
var me = this,
tplSord, value, name, shortName, inputs, i, input, dataType;
tplSord = {
objKeys: {},
mapKeys: {},
wfMapKeys: {}
};
inputs = document.querySelectorAll("input");
for (i = 0; i < inputs.length; i++) {
input = inputs[i];
name = input.name;
dataType = me.getInputDataType(input);
if (dataType == "isodate") {
value = me.getIsoDate(name);
} else {
value = $val(name);
}
if (name.indexOf("IX_GRP_") == 0) {
shortName = name.substr(7);
tplSord.objKeys[shortName] = value;
} else if (name.indexOf("IX_MAP_") == 0) {
shortName = name.substr(7);
tplSord.mapKeys[shortName] = value;
} else if (name.indexOf("WF_MAP_") == 0) {
shortName = name.substr(7);
tplSord.wfMapKeys[shortName] = value;
}
}
return tplSord;
},
/**
* Updates values
* @param {Object} updates Updates
* {
* objKeys: {
* },
* mapKeys: {
* "MYKEY": "myvalue"
* }
* }
*/
updateValues: function (updates) {
var me = this;
if (!updates) {
return;
}
me.writeUpdates(updates.objKeys, "IX_GRP_");
me.writeUpdates(updates.mapKeys, "IX_MAP_");
},
/**
* @private
* @param {Object} entries Entries
* {
* "MYKEY": "myvalue"
* }
* @param {String} prefix Prefix
*/
writeUpdates: function (entries, prefix) {
var me = this,
value, dataType, key, fieldName, field;
for (key in entries) {
fieldName = prefix + key;
value = entries[key];
field = $var(fieldName);
dataType = me.getInputDataType(field);
if (dataType == "isodate") {
me.setIsoDate(fieldName, value, {
callInputChanged: false
});
} else {
$update(fieldName, value);
}
}
},
/**
* Returns the input type
* @param {HTMLElement} input Input
* @return {String} Data type
*/
getInputDataType: function (input) {
var inputDataType, eloVerify, eloVerifyElements;
inputDataType = "text";
if (!input) {
throw "Input field is missing";
}
eloVerify = input.getAttribute("eloverify");
if (eloVerify) {
eloVerifyElements = eloVerify.split(" ");
}
if (eloVerifyElements && (eloVerifyElements.indexOf("date") > -1)) {
inputDataType = "isodate";
}
return inputDataType;
},
/**
* Sets a `changed` Flag
* @param {HTMLElement} field Field
*/
setFieldChanged: function (field) {
if (!field) {
return;
}
field.setAttribute("changed", "");
},
/**
* Creates an easily editable field from a multiindex field value.
* e.g. mi = MultiIndex("abc¶def¶xyz");
* mi.values() => ["abc", "def", "xyz"]
* mi.add("test") => ["abc", "def", "xyz", "test"]
* mi.remove("def") => ["abc", "xyz", "test"]
* mi.contains("abc") => true
* String(mi) => "abc¶xyz¶test"
* mi.save("IX_GRP_MYFIELD") => $updates MYFIELD with current String representation
*
* e.g. mi = MultiIndex("abc¶def¶xyz¶xyz")
* mi.removeAll("xyz") => ["abc", "def"]
*
* Hint: remove() only removes the first matching value
*
* @param {String|FormWrapper Field} f
* @param {Object} options different options
* @param {Boolean} options.unique Determine whether multiIndex field has the possibility to store same values (set to true by default).
* @returns MultiIndex field
*/
MultiIndex: function (f, options) {
var a, iA;
f || (f = "");
options = options || {};
options.unique = options.hasOwnProperty("unique") ? options.unique : true;
try {
a = (typeof f === "string" ? f : ((f || {}).value() || "")).split("¶");
} catch (_e) {
console.log("MultiIndex requires a string or FormWrapper field as constructor parameter.");
}
((a.length === 1) && (a[0] === "") && (a = []));
iA = {
values: a.slice.bind(a),
toString: function () {
return a.reduce(function (s, val, i) {
s += val;
(i + 1 < a.length) && (s += "¶");
return s;
}, "");
},
valueOf: NaN,
add: function (val) {
if (!options.unique || !this.contains(val)) {
a.push(String(val));
}
return a;
},
remove: function (val) {
var i = a.indexOf(val),
valExists = ~i;
return (valExists && a.splice(i, 1)), a;
},
removeAll: function (val) {
do {
var i = a.indexOf(val),
valExists = ~i;
valExists && a.splice(i, 1);
} while (valExists);
return a;
},
contains: function (val) {
return !!~a.indexOf(val);
},
save: function (fieldName) {
var val = String(this);
fieldName
?
(f.form ? f.form.fields[fieldName].set(val) : $update(fieldName, val)) :
((f && f.set) ? f.set(val) : console.log("could not save. no field specified"));
}
};
iA.toJSON = iA.toString;
return iA;
},
/**
* Returns the time zone from the URL
* @return {String} Time zone
*/
getTimeZoneFromUrl: function () {
var me = this,
urlParams, timeZone;
urlParams = me.getUrlParams();
timeZone = urlParams["timezone"];
return timeZone;
},
/**
* Returns the URL params
* @return {Object} URL parameters
*/
getUrlParams: function () {
var params = {};
window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) {
params[decodeURIComponent(key)] = decodeURIComponent(value);
});
return params;
},
/**
* Checks whether a field is missing
* @param {Array} fieldNames Field names
*/
fieldIsMissing: function (fieldNames) {
var i;
if (!fieldNames) {
return true;
}
for (i = 0; i < fieldNames.length; i++) {
if (!$var(fieldNames[i])) {
return true;
}
}
return false;
},
/**
* Moves a row after another row
*
* @param {String} rowToMoveFieldName Row to move field name
* @param {String} dstRowFieldName Destination row field name
* @param {Object} params Parameters
* @param {String} params.identifyTemplateByFieldName Identify the template by a specific field name
*/
moveRowAfter: function (rowToMoveFieldName, dstRowFieldName, params) {
var me = this,
rowToMoveField, dstRowField, rowToMove, dstRow, tbody, templateField, template;
params = params || {};
if (!rowToMoveFieldName) {
throw "Row to move field name is empty";
}
if (!dstRowFieldName) {
throw "Destination row field name is empty";
}
if (params.identifyTemplateByFieldName) {
templateField = $var(params.identifyTemplateByFieldName);
template = me.getTemplate(templateField);
rowToMoveField = me.getFieldInTemplate(template, rowToMoveFieldName);
} else {
rowToMoveField = $var(rowToMoveFieldName);
}
if (!rowToMoveField) {
throw "Can't find row to move field '" + rowToMoveFieldName + "'";
}
dstRowField = $var(dstRowFieldName);
if (!dstRowField) {
throw "Can't find destination row field '" + dstRowFieldName + "'";
}
rowToMove = me.getRow(rowToMoveField);
dstRow = me.getRow(dstRowField);
tbody = me.getParentByTagName(dstRow, "tbody");
tbody.insertBefore(rowToMove, dstRow.nextSibling);
},
/**
* Returns a field within a specific template
* @param {HTMLElement} template Template
* @param {HTMLElement} fieldName Field name
*/
getFieldInTemplate: function (template, fieldName) {
var field;
if (!template) {
throw "Template is empty";
}
if (!fieldName) {
throw "Field name is empty";
}
field = template.querySelector("input[name='" + fieldName + "']");
return field;
},
/**
* Sets a label
* @param {String} lblName Label name
* @param {String} translationKey Translation key
*/
setLabel: function (lblName, translationKey) {
var me = this,
label, text;
if (!lblName) {
throw "Field name is emtpy";
}
label = $var(lblName);
if (!label) {
throw "Label '" + lblName + "' not found";
}
text = me.getTranslation(translationKey);
$update(lblName, text);
},
/**
* Replaces translation keys on a form
* Usually you'd add a string like "{{package}}" within the translation keys of your form
* to avoid the automatic translation of those keys. With this function you can now replace
* {{package}} with the real package name, get the translated term and replace the text on the form
*
* This works only well when the first part of your new translateKey (sol.meeting_enterprise) is the same
* as the prefix of the current form (sol.meeting). Otherwise the new key wouldn't be loaded
* @param {String} search Search for this string (e.g. {{package}})
* @param {String} replace Replace with this string (e.g. meeting_enterprise)
* @param {String} fallback (optional) Fallback string in case a translateTerm is not found for the replaced translateKey
*/
replaceTranslations: function (search, replace, fallback) {
var me = this, texts, text, i, placeholders, placeholder, buttons, tooltips, tooltip;
// this is looking for all text elements in the form
// elowf keeps them always between <acronym>-tags
texts = document.querySelectorAll("acronym");
for (i = 0; i < texts.length; i++) {
text = texts[i].innerText;
if (text.indexOf(search) > -1) {
try {
texts[i].innerText = me.getTranslation(text.replace(search, replace));
} catch (e) {
if (fallback) {
texts[i].innerText = me.getTranslation(text.replace(search, fallback));
}
}
}
}
placeholders = document.querySelectorAll("[placeholder*='" + search + "']");
for (i = 0; i < placeholders.length; i++) {
placeholder = placeholders[i].attributes["placeholder"];
try {
placeholder.textContent = me.getTranslation(placeholder.textContent.replace(search, replace));
} catch (e) {
if (fallback) {
placeholder.textContent = me.getTranslation(placeholder.textContent.replace(search, fallback));
}
}
}
buttons = document.querySelectorAll("input[type=button][value*='" + search + "'");
for (i = 0; i < buttons.length; i++) {
try {
buttons[i].value = me.getTranslation(buttons[i].value.replace(search, replace));
} catch (e) {
if (fallback) {
buttons[i].value = me.getTranslation(buttons[i].value.replace(search, fallback));
}
}
}
tooltips = document.querySelectorAll("input[savedtitle*='" + search + "']");
for (i = 0; i < tooltips.length; i++) {
tooltip = tooltips[i].attributes["savedtitle"];
try {
tooltip.value = me.getTranslation(tooltip.value.replace(search, replace));
} catch (e) {
if (fallback) {
tooltip.value = me.getTranslation(tooltip.value.replace(search, fallback));
}
}
}
// since some parts like header texts could have been replaced, a layout reset is required
sol.common.forms.Utils.resetFormLayout();
},
/**
* Returns a translation
* @param {String} translationKey Translation key
* @return Translation
*/
getTranslation: function (translationKey) {
var translation = "";
if (!translationKey) {
throw "Translation key is empty";
}
if (elo && elo.locale && elo.locale.store) {
translation = elo.locale.store[translationKey];
}
if (!translation) {
console.info("Translation key '" + translationKey + "' not found");
return translationKey;
}
return translation;
},
/**
* Adds a validation attibute
* @param {String} fieldName
* @param {String} [validationAttribute=notemptyforward]
*/
addValidation: function (fieldName, validationAttribute) {
var field, eloverify;
if (!fieldName) {
throw "Field name is missing";
}
validationAttribute = validationAttribute || "notemptyforward";
field = $var(fieldName);
if (!field) {
return;
}
eloverify = field.getAttribute("eloverify");
if (eloverify.indexOf(validationAttribute) == -1) {
eloverify += " " + validationAttribute;
field.setAttribute("eloverify", eloverify);
}
},
/**
* Removes a validation attibute
* @param {String} fieldName
* @param {String} [validationAttribute=notemptyforward]
*/
removeValidation: function (fieldName, validationAttribute) {
var field, eloverify;
if (!fieldName) {
throw "Field name is missing";
}
validationAttribute = validationAttribute || "notemptyforward";
field = $var(fieldName);
if (!field) {
return;
}
eloverify = field.getAttribute("eloverify");
eloverify = eloverify.replace(validationAttribute, "");
field.setAttribute("eloverify", eloverify);
},
/**
* Checks wether a field is numeric
* @param {HTMLElement} field
*/
isNumeric: function (field) {
var types, i, type, eloverify;
types = ["num", "amount"];
if (!field) {
throw "Field is missing";
}
eloverify = field.getAttribute("eloverify");
if (!eloverify) {
return false;
}
for (i = 0; i < types.length; i++) {
type = types[i];
if (eloverify.indexOf(type) > -1) {
return true;
}
}
return false;
},
/**
* Removes a class from a specified field
* @param {String} fieldName Field name
* @param {String} className Class name
*/
removeFieldClass: function (fieldName, className) {
var me = this,
field, td;
if (!fieldName) {
throw "Field name is empty";
}
field = $var(fieldName);
if (!field || !className) {
return;
}
td = me.getParentByTagName(field, "td");
td.classList.remove(className);
}
});