/* Copyright (c) 2012-2017 Open Lab Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ var muteAlertOnChange = false; // isRequired ---------------------------------------------------------------------------- //return true if every mandatory field is filled and highlight empty ones jQuery.fn.isFullfilled = function () { var canSubmit = true; var firstErrorElement = ""; this.each(function () { var theElement = $(this); theElement.removeClass("formElementsError"); //if (theElement.val().trim().length == 0 || theElement.attr("invalid") == "true") { //robicch 13/2/15 if (theElement.is("[required]") && theElement.val().trim().length == 0 || theElement.attr("invalid") == "true") { if (theElement.attr("type") == "hidden") { theElement = theElement.prevAll("#" + theElement.prop("id") + "_txt:first"); } else if (theElement.is("[withTinyMCE]")){ if (tinymce.activeEditor.getContent()=="") theElement=$("#"+theElement.attr("name")+"_tbl"); else return true;// in order to continue the loop } theElement.addClass("formElementsError"); canSubmit = false; if (firstErrorElement == "") firstErrorElement = theElement; } }); if (!canSubmit) { // get the tabdiv var theTabDiv = firstErrorElement.closest(".tabBox"); if (theTabDiv.length > 0) clickTab(theTabDiv.attr("tabId")); // highlight element firstErrorElement.effect("highlight", { color:"red" }, 1500); } return canSubmit; }; function canSubmitForm(formOrId) { //console.debug("canSubmitForm",formOrId); if (typeof formOrId != "object") formOrId=$("#" + formOrId); return formOrId.find(":input[required],:input[invalid=true]").isFullfilled(); } function showSavingMessage() { $("#savingMessage:hidden").fadeIn(); $("body").addClass("waiting"); $(window).resize(); } function hideSavingMessage() { $("#savingMessage:visible").fadeOut(); $("body").removeClass("waiting"); $(window).resize(); } /* Types Function */ function isValidURL(url) { var RegExp = /^(([\w]+:)?\/\/)?(([\d\w]|%[a-fA-f\d]{2,2})+(:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,4}(:[\d]+)?(\/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?$/; return RegExp.test(url); } function isValidEmail(email) { //var RegExp = /^((([a-z]|[0-9]|!|#|$|%|&|'|\*|\+|\-|\/|=|\?|\^|_|`|\{|\||\}|~)+(\.([a-z]|[0-9]|!|#|$|%|&|'|\*|\+|\-|\/|=|\?|\^|_|`|\{|\||\}|~)+)*)@((((([a-z]|[0-9])([a-z]|[0-9]|\-){0,61}([a-z]|[0-9])\.))*([a-z]|[0-9])([a-z]|[0-9]|\-){0,61}([a-z]|[0-9])\.)[\w]{2,4}|(((([0-9]){1,3}\.){3}([0-9]){1,3}))|(\[((([0-9]){1,3}\.){3}([0-9]){1,3})\])))$/; var RegExp = /^.+@\S+\.\S+$/; return RegExp.test(email); } function isValidInteger(n) { reg = new RegExp("^[-+]{0,1}[0-9]*$"); return reg.test(n) || isNumericExpression(n); } function isValidDouble(n) { var sep = Number.decimalSeparator; reg = new RegExp("^[-+]{0,1}[0-9]*[" + sep + "]{0,1}[0-9]*$"); return reg.test(n) || isNumericExpression(n); } function isValidTime(n) { return !isNaN(millisFromHourMinute(n)); } function isValidDurationDays(n) { return !isNaN(daysFromString(n)); } function isValidDurationMillis(n) { return !isNaN(millisFromString(n)); } function isNumericExpression(expr) { try { var a = eval(expr); return typeof(a) == 'number'; } catch (t) { return false; } } function getNumericExpression(expr) { var ret; try { var a = eval(expr); if (typeof(a) == 'number') ret = a; } catch (t) { } return ret; } /* supports almost all Java currency format e.g.: ###,##0.00EUR €#,###.00 #,###.00€ -$#,###.00 $-#,###.00 */ function isValidCurrency(numStr) { //first try to convert format in a regex var regex = ""; var format = Number.currencyFormat + ""; var minusFound = false; var numFound = false; var currencyString = ""; var numberRegex = "[0-9\\" + Number.groupingSeparator + "]+[\\" + Number.decimalSeparator + "]?[0-9]*"; for (var i = 0; i < format.length; i++) { var ch = format.charAt(i); if (ch == "." || ch == "," || ch == "0") { //skip it if (currencyString != "") { regex = regex + "(?:" + RegExp.quote(currencyString) + ")?"; currencyString = ""; } } else if (ch == "#") { if (currencyString != "") { regex = regex + "(?:" + RegExp.quote(currencyString) + ")?"; currencyString = ""; } if (!numFound) { numFound = true; regex = regex + numberRegex; } } else if (ch == "-") { if (currencyString != "") { regex = regex + "(?:" + RegExp.quote(currencyString) + ")?"; currencyString = ""; } if (!minusFound) { minusFound = true; regex = regex + "[-]?"; } } else { currencyString = currencyString + ch; } } if (!minusFound) regex = "[-]?" + regex; if (currencyString != "") regex = regex + "(?:" + RegExp.quote(currencyString) + ")?"; regex = "^" + regex + "$"; var rg = new RegExp(regex); return rg.test(numStr) || isNumericExpression(numStr); } function getCurrencyValue(numStr) { if (!isValidCurrency(numStr)) return NaN; var ripul = numStr.replaceAll(Number.groupingSeparator, "").replaceAll(Number.decimalSeparator, "."); return getNumericExpression(ripul) || parseFloat(ripul.replace(/[^-0123456789.]/, "")); } function formatCurrency(numberString) { return formatNumber(numberString, Number.currencyFormat); } function formatNumber(numberString, format) { if (!format) format = "##0.00"; var dec = Number.decimalSeparator; var group = Number.groupingSeparator; var neg = Number.minusSign; var round = true; var validFormat = "0#-,."; // strip all the invalid characters at the beginning and the end // of the format, and we'll stick them back on at the end // make a special case for the negative sign "-" though, so // we can have formats like -$23.32 var prefix = ""; var negativeInFront = false; for (var i = 0; i < format.length; i++) { if (validFormat.indexOf(format.charAt(i)) == -1) { prefix = prefix + format.charAt(i); } else { if (i == 0 && format.charAt(i) == '-') { negativeInFront = true; } else { break; } } } var suffix = ""; for (var i = format.length - 1; i >= 0; i--) { if (validFormat.indexOf(format.charAt(i)) == -1) suffix = format.charAt(i) + suffix; else break; } format = format.substring(prefix.length); format = format.substring(0, format.length - suffix.length); // now we need to convert it into a number //while (numberString.indexOf(group) > -1) // numberString = numberString.replace(group, ''); //var number = new Number(numberString.replace(dec, ".").replace(neg, "-")); var number = new Number(numberString); var forcedToZero = false; if (isNaN(number)) { number = 0; forcedToZero = true; } // special case for percentages if (suffix == "%") number = number * 100; var returnString = ""; if (format.indexOf(".") > -1) { var decimalPortion = dec; var decimalFormat = format.substring(format.lastIndexOf(".") + 1); // round or truncate number as needed if (round) number = new Number(number.toFixed(decimalFormat.length)); else { var numStr = number.toString(); numStr = numStr.substring(0, numStr.lastIndexOf('.') + decimalFormat.length + 1); number = new Number(numStr); } var decimalValue = number % 1; var decimalString = new String(decimalValue.toFixed(decimalFormat.length)); decimalString = decimalString.substring(decimalString.lastIndexOf(".") + 1); for (var i = 0; i < decimalFormat.length; i++) { if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) != '0') { decimalPortion += decimalString.charAt(i); } else if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) == '0') { var notParsed = decimalString.substring(i); if (notParsed.match('[1-9]')) { decimalPortion += decimalString.charAt(i); } else { break; } } else if (decimalFormat.charAt(i) == "0") { decimalPortion += decimalString.charAt(i); } } returnString += decimalPortion; } else { number = Math.round(number); } var ones = Math.floor(number); if (number < 0) ones = Math.ceil(number); var onesFormat = ""; if (format.indexOf(".") == -1) onesFormat = format; else onesFormat = format.substring(0, format.indexOf(".")); var onePortion = ""; if (!(ones == 0 && onesFormat.substr(onesFormat.length - 1) == '#') || forcedToZero) { // find how many digits are in the group var oneText = new String(Math.abs(ones)); var groupLength = 9999; if (onesFormat.lastIndexOf(",") != -1) groupLength = onesFormat.length - onesFormat.lastIndexOf(",") - 1; var groupCount = 0; for (var i = oneText.length - 1; i > -1; i--) { onePortion = oneText.charAt(i) + onePortion; groupCount++; if (groupCount == groupLength && i != 0) { onePortion = group + onePortion; groupCount = 0; } } // account for any pre-data padding if (onesFormat.length > onePortion.length) { var padStart = onesFormat.indexOf('0'); if (padStart != -1) { var padLen = onesFormat.length - padStart; // pad to left with 0's or group char var pos = onesFormat.length - onePortion.length - 1; while (onePortion.length < padLen) { var padChar = onesFormat.charAt(pos); // replace with real group char if needed if (padChar == ',') padChar = group; onePortion = padChar + onePortion; pos--; } } } } if (!onePortion && onesFormat.indexOf('0', onesFormat.length - 1) !== -1) onePortion = '0'; returnString = onePortion + returnString; // handle special case where negative is in front of the invalid characters if (number < 0 && negativeInFront && prefix.length > 0) prefix = neg + prefix; else if (number < 0) returnString = neg + returnString; if (returnString.lastIndexOf(dec) == returnString.length - 1) { returnString = returnString.substring(0, returnString.length - 1); } returnString = prefix + returnString + suffix; return returnString; } //validation functions - used by textfield and datefield jQuery.fn.validateField = function () { var isValid = true; this.each(function () { var el = $(this); el.clearErrorAlert(); var value = el.val(); if (value) { var rett = true; var type = (el.attr('entryType')+"").toUpperCase(); var errParam; if (type == "INTEGER") { rett = isValidInteger(value); } else if (type == "DOUBLE") { rett = isValidDouble(value); } else if (type == "PERCENTILE") { rett = isValidDouble(value); } else if (type == "URL") { rett = isValidURL(value); } else if (type == "EMAIL") { rett = isValidEmail(value); } else if (type == "DURATIONMILLIS") { rett = isValidDurationMillis(value); } else if (type == "DURATIONDAYS") { rett = isValidDurationDays(value); } else if (type == "DATE") { rett = Date.isValid(value, el.attr("format"), true); if (!rett) errParam = el.attr("format"); } else if (type == "TIME") { rett = isValidTime(value); } else if (type == "CURRENCY") { rett = isValidCurrency(value); } if (!rett) { el.createErrorAlert(i18n.ERROR_ON_FIELD, i18n.INVALID_DATA + (errParam ? " " + errParam : "")); isValid=false; } //check limits minValue : maxValue if (rett && (el.attr("minValue") || el.attr("maxValue"))){ var val=value; var min=el.attr("minValue"); var max=el.attr("maxValue"); if (type == "INTEGER") { val=parseInt(value); min=parseInt(min); max=parseInt(max); } else if (type == "DOUBLE" || type == "PERCENTILE") { val=parseDouble(value); min=parseDouble(min); max=parseDouble(max); } else if (type == "URL") { val=value; } else if (type == "EMAIL") { val=value; } else if (type == "DURATIONMILLIS") { val=millisFromString(value); min=millisFromString(min); max=millisFromString(max); } else if (type == "DURATIONDAYS") { val=daysFromString(value); min=daysFromString(min); max=daysFromString(max); } else if (type == "DATE") { val=Date.parseString(value, el.attr("format"),true).getTime(); min=Date.parseString(min, el.attr("format"),true).getTime(); max=Date.parseString(max, el.attr("format"),true).getTime(); } else if (type == "TIME") { val = millisFromHourMinute(value); min = millisFromHourMinute(min); max = millisFromHourMinute(max); } else if (type == "CURRENCY") { val=getCurrencyValue(value); min=getCurrencyValue(min); max=getCurrencyValue(max); } if (el.attr("minValue") && valmax){ el.createErrorAlert(i18n.ERROR_ON_FIELD, i18n.OUT_OF_BOUDARIES + " ("+(el.attr("minValue")?el.attr("minValue"):"--")+" : "+el.attr("maxValue")+")"); rett=false; isValid=false; } } } }); return isValid; }; jQuery.fn.clearErrorAlert = function () { this.each(function () { var el = $(this); el.removeAttr("invalid").removeClass("formElementsError"); $("#" + el.prop("id") + "error").remove(); }); return this; }; jQuery.fn.createErrorAlert = function (errorCode, message) { this.each(function () { var el = $(this); el.attr("invalid", "true").addClass("formElementsError"); if ($("#" + el.prop("id") + "error").length <= 0) { var errMess = (errorCode ? errorCode : "") + ": " + (message ? message : ""); var err = " "; err += "\n"; err = $(err); err.prop("title", errMess); el.after(err); } }); return this; }; // button submit support BEGIN ------------------ function saveFormValues(idForm) { var formx = obj(idForm); formx.setAttribute("savedAction", formx.action); formx.setAttribute("savedTarget", formx.target); var el = formx.elements; for (i = 0; i < el.length; i++) { if (el[i].getAttribute("savedValue") != null) { el[i].setAttribute("savedValue", el[i].value); } } } function restoreFormValues(idForm) { var formx = obj(idForm); formx.action = formx.getAttribute("savedAction"); formx.target = formx.getAttribute("savedTarget"); var el = formx.elements; for (i = 0; i < el.length; i++) { if (el[i].getAttribute("savedValue") != null) { el[i].value = el[i].getAttribute("savedValue"); } } } function changeActionAndSubmit(action,command){ var f=$("form:first"); f.prop("action",action); f.find("[name=CM]").val(command); f.submit(); } // textarea limit size ------------------------------------------------- function limitSize(ob) { if (ob.getAttribute("maxlength")) { var ml =parseInt(ob.getAttribute("maxlength")); var val = ob.value;//.replace(/\r\n/g,"\n"); if (val.length > ml) { ob.value = val.substr(0, ml); $(ob).createErrorAlert("Error",i18n.ERR_FIELD_MAX_SIZE_EXCEEDED); } else { $(ob).clearErrorAlert(); } } return true; } // verify before unload BEGIN ---------------------------------------------------------------------------- function alertOnUnload(container) { //console.debug("alertOnUnload",container,muteAlertOnChange); if (!muteAlertOnChange) { //first try to call a function eventually defined on the page if (typeof(managePageUnload) == "function") managePageUnload(); container=container||$("body"); var inps= $("[alertonchange=true]",container).find("[oldValue=1]"); for (var j = 0; j < inps.length; j++) { var anInput = inps.eq(j); //console.debug(j,anInput,anInput.isValueChanged()) var oldValue = anInput.getOldValue() + ""; if (!('true' == '' + anInput.attr('excludeFromAlert'))) { if (anInput.attr("maleficoTiny")) { if (tinymce.EditorManager.get(anInput.prop("id")).isDirty()) { return i18n.FORM_IS_CHANGED + " \"" + anInput.prop("name") + "\""; } } else if (anInput.isValueChanged()) { var inputLabel = $("label[for='" + anInput.prop("id") + "']").text(); //use label element inputLabel = inputLabel ? inputLabel : anInput.prop("name"); return i18n.FORM_IS_CHANGED + " \"" + inputLabel + "\""; } } } } return undefined; } function canILeave(){ var ret = window.onbeforeunload(); if (typeof(ret)!="undefined" && !confirm(ret+" \n"+i18n.PROCEED)) return false; else return true; } // ---------------------------------- oldvalues management // update all values selected jQuery.fn.updateOldValue = function () { this.each(function () { var el = $(this); var val=(el.is(":checkbox,:radio")?el.prop("checked"):el.val())+""; el.data("_oldvalue", val); }); return this; }; // return true if at least one element has changed jQuery.fn.isValueChanged = function () { var ret = false; this.each(function () { var el = $(this); var val=(el.is(":checkbox,:radio")?el.prop("checked"):el.val())+""; if (val != el.data("_oldvalue") + "") { //console.debug("io sono diverso "+el.prop("id")+ " :"+el.val()+" != "+el.data("_oldvalue")); ret = true; return false; } }); return ret; }; jQuery.fn.getOldValue = function () { return $(this).data("_oldvalue"); }; jQuery.fn.fillJsonWithInputValues = function (jsonObject) { var inputs = this.find(":input"); $.each(inputs.serializeArray(),function(){ if (this.name) { jsonObject[this.name] = this.value; } }); inputs.filter(":checkbox[name]").each(function () { var el = $(this); jsonObject[el.attr("name")] = el.is(":checked") ? "yes" : "no"; }) return this; }; function enlargeTextArea(immediate) { //console.debug("enlargeTextArea",immediate); var el = $(this); var delay=immediate===true?1:300; el.stopTime("taResizeApply"); el.oneTime(delay,"taResizeApply",function(){ var miH = el.is("[minHeight]") ? parseInt(el.attr("minHeight")) : 30; var maH = el.is("[maxHeight]") ? parseInt(el.attr("maxHeight")) : 400; var inc = el.is("[lineHeight]") ? parseInt(el.attr("lineHeight")) : 30; //si copiano nel css per sicurezza el.css({maxHeight:maH,minHeight:miH}); var domEl = el.get(0); var pad = el.outerHeight()-el.height(); //devo allargare if (domEl.scrollHeight>el.outerHeight() && el.outerHeight()maH-pad?maH-pad:nh; el.height(nh); } else if (el.height()>miH){ //devo stringere el.height(el.height()-inc); while(el.outerHeight()-domEl.scrollHeight > 0 && el.height()>miH){ el.height(el.height()-inc); } var newH=domEl.scrollHeight-pad +inc; //newH=newH