954 lines
34 KiB
JavaScript
954 lines
34 KiB
JavaScript
/*
|
|
$Revision$
|
|
$Id$
|
|
|
|
File: iface.js
|
|
Description: clientside functions for shared/iface.inc
|
|
*/
|
|
var secfilters;
|
|
// Toggle-t de zichtbaarheid van secundaire zoekvelden
|
|
// Gebruikt globale boolean secfilters om de huidige status te onthouden
|
|
// iface.inc definieert de strings
|
|
function iface_toggleSecondarySearchblock(aanuit)
|
|
{
|
|
if (typeof aanuit == 'boolean')
|
|
window.secfilters = !aanuit;
|
|
if (!window.secfilters) {
|
|
$(".secsearch").show();
|
|
window.secfilters = true; // en vervang label door L("lcl_less")
|
|
$("#btnMoreLess").text(L("lcl_shared_less"));
|
|
} else {
|
|
$(".secsearch").hide();
|
|
window.secfilters = false; // en vervang label door L("lcl_more")
|
|
$("#btnMoreLess").text(L("lcl_shared_more"));
|
|
}
|
|
}
|
|
|
|
function headertofooter()
|
|
{
|
|
$('body#editbody div.fcltframeheader').each(function () {
|
|
var footer = $("<div>").addClass("fcltframefooter");
|
|
footer.append($("div#buttons", this).clone()).css('clear','both');
|
|
$(this).parent().append(footer);
|
|
FcltMgr.resized();
|
|
});
|
|
}
|
|
|
|
var iface =
|
|
{
|
|
button:
|
|
{
|
|
click: function(evt, btn)
|
|
{
|
|
if ($(btn).is("#printhamburger"))
|
|
$(btn).find("> i.fa").toggleClass("fa-bars fa-times");
|
|
|
|
FcltMgr.stopPropagation(evt);
|
|
|
|
if (btn.getAttribute("singlepress") && btn.getAttribute("isactive")=="true")
|
|
{ // FcltMgr.alert("Heb geduld");
|
|
return;
|
|
}
|
|
if (btn.getAttribute("singlepress"))
|
|
{
|
|
iface.button.disable(btn);
|
|
}
|
|
var elem = btn.getAttribute("fcltclick");
|
|
|
|
window.fcltevent = evt;
|
|
var result = eval(elem);
|
|
// Dit lijkt erg onzinning (we zitten binnen iface) maar soms als
|
|
// een scherm/dialoog net gesloten is door de action van de button
|
|
// blijkt de code toch nog hier te komen terwijl iface weg is
|
|
if (typeof iface == "undefined")
|
|
return;
|
|
|
|
if (result === false)
|
|
{
|
|
iface.button.enable(btn);
|
|
}
|
|
|
|
},
|
|
disable: function(btn)
|
|
{
|
|
if (typeof btn == "object")
|
|
btn = btn.id;
|
|
if (!btn)
|
|
FcltMgr.alert("For button.disable it should have an id");
|
|
// Kan ondertussen dubbel aanwezig zijn doordat we knoppen onderin frame herhalen
|
|
// Een selectie via $("." + btn") werkt niet omdat jQuery dan alleen de eerste id ophaalt
|
|
var $btn = $("li[id=" + btn + "]");
|
|
$btn.attr("isactive", "true");
|
|
$btn.addClass("btn_disabled");
|
|
$btn.children().addClass("btn_disabled");
|
|
},
|
|
enable: function(btn)
|
|
{
|
|
if (typeof btn == "object")
|
|
btn = btn.id;
|
|
var $btn = $("li[id='" + btn + "']");
|
|
$btn.removeClass("btn_disabled");
|
|
$btn.children().removeClass("btn_disabled");
|
|
$btn.attr("isactive", "false");
|
|
}
|
|
},
|
|
translate: function (kolomnaam, key, lbl, deftxt, typ)
|
|
{
|
|
var url = rooturl + "/appl/fac/fac_locale_data.asp?kolomnaam="+kolomnaam+"&kolomkeyval=" + key
|
|
+ "&kolomkeydata=" +escape(deftxt)
|
|
+ "&lbl=" +escape(lbl)
|
|
+ "&typ=" +typ;
|
|
FcltMgr.openModalDetail(url, L("lcl_lcl_vertaling"), {xheight: 200, width: 600 } );
|
|
|
|
},
|
|
overrule: function (lcl_name)
|
|
{
|
|
var url = rooturl + "/appl/fac/fac_locale_edit_std.asp?module=ASP&lcl_label=" + escape(lcl_name);
|
|
FcltMgr.openModalDetail(url, L("lcl_lcl_vertaling"), {xheight: 200, width: 600 } );
|
|
|
|
},
|
|
formToString: function (stringForm, explicit)
|
|
{
|
|
// explicit: expliciet = bewust opgeslagen pagina's (tot nu toe alleen pinnen van tabs)
|
|
// !explicit: impliciet = onbewust opgeslagen pagina's (tot nu toe alleen het impliciet onthouden van rapport filters bij S(fac_usrrap_keepfilter) == 1)
|
|
var notFilter = "";
|
|
if (explicit)
|
|
notFilter = "[name^='fclt_f_colname']";
|
|
else // Bij impliciet opslaan, deze filters negeren;
|
|
notFilter = "[name='mode'], [name='columns'], [name='groupby'], "
|
|
+ "[name='scf_pivot'], [name='usrrap_key'], [name^='fclt_f_colname']";
|
|
|
|
var formObject = {};
|
|
stringForm.find("input, select").not(notFilter).each(function()
|
|
{
|
|
var nm = $(this).attr("colname") || this.id || this.name || null;
|
|
if (!nm)
|
|
return;
|
|
|
|
// Sla adhoc filters op als "veldnaam.adhoc"
|
|
var objName = $(this).hasClass("adhoc") ? nm + ".adhoc" : nm;
|
|
|
|
if ($(this).attr("type") == "checkbox" || $(this).attr("type") == "radio")
|
|
{
|
|
formObject[objName] = $(this).prop("checked");
|
|
}
|
|
else
|
|
{
|
|
var val = $(this).val();
|
|
|
|
// Sla bij opengeklapte multiSuggests met 1 geselecteerde waarde, de text op ipv de key(s)
|
|
if ($(this).prop("tagName") == "SELECT" && $(this).hasClass("multiSuggest") && $(this).find(":selected").length == 1)
|
|
val = $(this).find(":selected").text();
|
|
|
|
if (!$(this).hasClass("adhoc") && val == "" || val == null) // Save empty adhoc filters too: DJIN#41716
|
|
return;
|
|
if (val == "-1" && nm.match(/key$/))
|
|
return;
|
|
//if (val === $(this).prop( 'defaultValue' ))
|
|
// return;
|
|
formObject[objName] = val;
|
|
if ($(this).hasClass("suggest"))
|
|
{
|
|
if (!("suggestattr" in formObject))
|
|
formObject.suggestattr = {};
|
|
formObject.suggestattr[objName] =
|
|
{ // Ook deze 'hidden' suggest attributen meenemen
|
|
sgKey: $(this).attr("sgKey"),
|
|
sgCurrentValue: $(this).attr("sgCurrentValue"),
|
|
sgExtraParam: $(this).attr("sgExtraParam")
|
|
}
|
|
}
|
|
}
|
|
})
|
|
return JSON.stringify(formObject);
|
|
},
|
|
|
|
stringToForm: function (formString, stringForm)
|
|
{
|
|
var formObject = JSON.parse(formString);
|
|
stringForm.find("input, select").not("reportmulti").each(function() // negeer reportmulti, die kunnen we niet aan
|
|
{
|
|
var nm = $(this).attr("colname") || this.id || this.name || null;
|
|
|
|
// Adhoc filters zijn in het formObject opgeslagen als "veldnaam.adhoc"
|
|
var isAdhoc = $(this).hasClass("adhoc");
|
|
var objName = isAdhoc ? nm + ".adhoc" : nm;
|
|
|
|
if (!nm || !(objName in formObject))
|
|
return;
|
|
|
|
if ($(this).attr("colname"))
|
|
var input = stringForm.find("[colname=" + nm + "]")
|
|
else if (this.id)
|
|
var input = stringForm.find("#" + nm)
|
|
else
|
|
var input = stringForm.find("[name=" + nm + "]");
|
|
if (!input.length)
|
|
return;
|
|
|
|
var multiple = formObject[objName] instanceof Array && formObject[objName].length > 1;
|
|
|
|
if (input.attr("type") == "checkbox" || input.attr("type") == "radio")
|
|
{
|
|
input.prop("checked", !!formObject[objName])
|
|
}
|
|
else if (input.prop("tagName") == "SELECT")
|
|
{
|
|
// This fills out the filters as saved from a (multi)select into the input field (so we dont have to perform any FillListbox()'s)
|
|
if (input.is(":hidden") && nm.length > 2 && stringForm.find("input#" + nm.slice(0, -2)).length > 0)
|
|
{
|
|
// Not supported; Could take too long to open the list, so just take the first value
|
|
if (multiple)
|
|
formObject[objName] = formObject[objName][0];
|
|
|
|
stringForm.find("input#" + nm.slice(0, -2)).val(formObject[objName])
|
|
.prop('defaultValue', formObject[objName]);
|
|
}
|
|
else
|
|
{
|
|
if (multiple) // Maak hem multiselect
|
|
{
|
|
input.attr('multiple', 1);
|
|
input.attr('size', Math.min(input.find("option").length, 8));
|
|
input.val(formObject[objName]); // gewoon
|
|
input.prev().html('«')
|
|
}
|
|
else
|
|
input.val(formObject[objName]); // gewoon
|
|
}
|
|
}
|
|
else if (!input.hasClass("final") && // Final's niet opslaan als filter
|
|
((isAdhoc && input.hasClass("adhoc")) || // Adhoc filters alleen invullen bij adhoc filters
|
|
(!isAdhoc && !input.hasClass("adhoc")))) // Normale filters alleen invullen bij normale filters
|
|
{
|
|
// Meerdere waarden alleen supported bij multiSuggest's
|
|
if (multiple && !$(input).hasClass("multiSuggest"))
|
|
formObject[objName] = formObject[objName][0];
|
|
|
|
input.val(formObject[objName]);
|
|
input.prop('defaultValue', formObject[objName]);
|
|
|
|
// multiSuggests met meerdere waarden vast openklappen
|
|
if (input.hasClass("multiSuggest") && multiple)
|
|
$(input).prev(".multi_suggest_toggle").click();
|
|
|
|
if ("suggestattr" in formObject && nm in formObject.suggestattr)
|
|
{
|
|
for (var sg in formObject.suggestattr[nm])
|
|
input.attr(sg, formObject.suggestattr[nm][sg])
|
|
}
|
|
}
|
|
});
|
|
},
|
|
// Persoonselector functies
|
|
persoonDetails: function (fieldName, info)
|
|
{
|
|
var pkey=$('#'+fieldName)[0].value;
|
|
if (info == 'PRS')
|
|
{
|
|
FcltMgr.openDetail("appl/prs/prs_perslid.asp?prs_key=" + pkey, { reuse: true });
|
|
}
|
|
else // Standaard fac_user info aanroepen.
|
|
{
|
|
if (pkey != -1)
|
|
FcltMgr.openDetail("appl/fac/fac_user.asp?prs_key=" + pkey, { reuse: true });
|
|
else
|
|
FcltMgr.openDetail("appl/fac/fac_user.asp", { reuse: true }); // self
|
|
}
|
|
},
|
|
showCaller: function (zelf)
|
|
{
|
|
var callerinfo=FcltMgr.getCaller();
|
|
if (callerinfo)
|
|
{
|
|
zelf.title=callerinfo.prs_naam;
|
|
}
|
|
else
|
|
zelf.title="beller beschikbaar";
|
|
},
|
|
setCaller: function (suggestfield)
|
|
{
|
|
var callerinfo=FcltMgr.getCaller();
|
|
if (callerinfo)
|
|
{
|
|
suggestfield.setValue(callerinfo.prs_key, callerinfo.prs_naam, true, true); // wel checkExist doen!
|
|
}
|
|
},
|
|
tabFrames: function () // Maak van alle subframes automatisch interne tabjes
|
|
{
|
|
var $frames = $(".fcltframe");
|
|
if ($frames.length < 2)
|
|
return;
|
|
$('body').wrapInner("<div id='frametabs'></div>");
|
|
var $ul = $("<ul class='frametabs'></ul>");
|
|
$(".fcltframe").not(".notabframe").each(function ()
|
|
{
|
|
$li = $("<li></li>");
|
|
$li.append("<a href='#{0}'>{1}</a>".format(this.id, this.id));
|
|
$ul.append($li);
|
|
});
|
|
$('#frametabs').prepend($ul);
|
|
$('#frametabs').tabs({
|
|
activate: function( event, ui ) {
|
|
var div = ui.newPanel;
|
|
if (div.length)
|
|
{
|
|
$("iframe", div).each(function () {
|
|
FcltMgr.iframeLoaded(this);
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
// params: checkOnly : [] beperkt array met velden die gecontroleerd moeten worden
|
|
// (default alles met class 'required')
|
|
// checkNot : [] deze velden niet controleren (default leeg)
|
|
// relaxed : alleen controle, geen class aanpassingen of alerts
|
|
function validateForm(fName, params)
|
|
{ // TODO: Alleen binnen fName kijken?
|
|
$(".fldCflexN.required").change(); // trigger change on required flex checkboxes
|
|
params = params || {};
|
|
function _isGoodCurrency(str, checkInteger, relativeValuesAllowed)
|
|
{
|
|
if (relativeValuesAllowed && str.match("%"))
|
|
var anum = /^[-\+](\d+[.,]?\d*)[%]$/; // RegExpr for currency field with % sign and with mandatory + or -
|
|
else if (relativeValuesAllowed && str.match(/^-{2}|\+{2}/))
|
|
var anum = /^(\+{2}|-{2})\d+[.,]?\d*$/; // RegExpr for currency field with ++ (add) or -- (sub) without % sign
|
|
else
|
|
var anum = /^([-\+]?\d+[.,]?\d*)$/; // RegExpr for currency field without % sign
|
|
// original: var anum = /^([-\+]?\d+[.,]?|[-\+]?\d+[.,]\d+$)$/ [results would have been the same with /^([-\+]?\d+[.,]?\d*)$/]
|
|
return anum.test(str);
|
|
}
|
|
|
|
function _isGoodTextFormat(aObject)
|
|
{
|
|
var regexptekst = aObject.getAttribute("regexp");
|
|
var re = new RegExp(regexptekst);
|
|
var hint = '';
|
|
var vIsGood = true;
|
|
|
|
if (!re.test($(aObject).val()))
|
|
{
|
|
var spantitle = $("label[for="+ aObject.name +"] span");
|
|
if (spantitle)
|
|
{
|
|
hint = spantitle[0].getAttribute("title");
|
|
if (hint == '')
|
|
hint = L("lcl_shared_validator_format");
|
|
|
|
hint = (spantitle[0].textContent || spantitle[0].innerText) + ' ' + hint
|
|
|
|
// FSN#41130, voorkomen van dubbele hint's
|
|
// door datum-validatie wordt _isGoodTextFormat() 2x doorlopen
|
|
if ($.inArray(hint, validatorHint) == -1)
|
|
validatorHint.push(hint);
|
|
}
|
|
vIsGood = false;
|
|
}
|
|
return vIsGood;
|
|
}
|
|
|
|
try
|
|
{
|
|
if (document.activeElement && document.activeElement.tagName != 'BODY' && !params.noBlur)
|
|
document.activeElement.blur(); // trigger laatste onChanges
|
|
}
|
|
catch (e)
|
|
{
|
|
// Faalt in onthouden tabje van frontend meldingenoverzicht die autosearch doet
|
|
}
|
|
|
|
var clsName = "missing";
|
|
var anyMissing = false;
|
|
var anyBad = false;
|
|
var validatorHint = [];
|
|
|
|
var jqcheckonly="*";
|
|
if (params.checkOnly) // slechts enkele velden controleren
|
|
jqcheckonly = "#" + params.checkOnly.join(",#");
|
|
var jqchecknot="";
|
|
if (params.checkNot && params.checkNot.length) // Deze velden niet meer controleren
|
|
jqchecknot = "#" + params.checkNot.join(",#");
|
|
|
|
if (params.relaxed)
|
|
clsName = "";
|
|
|
|
// Klap labels open waaronder verplichte kenmerken hangen
|
|
$(".required").filter(jqcheckonly).not(jqchecknot).filter(':not(:visible)').each(function (i)
|
|
{
|
|
var labels = $(this).closest("tr").prevAll("tr.trlabel.flexlabel");
|
|
if (labels.length && $(labels[0]).hasClass("flexcollapsed"))
|
|
$(labels[0]).click();
|
|
});
|
|
|
|
// Onderstaand stukje klapt mobile collapsible blocks uit indien er zich een input veld met waarde in bevind.
|
|
$(".ui-body-c").each(function ()
|
|
{
|
|
var $collapsable = $(this);
|
|
$(this).find("input.required").filter(':hidden').each(function() {
|
|
|
|
if ($(this).val() && $collapsable.prev(".ui-collapsible-heading-collapsed"))
|
|
$collapsable.prev(".ui-collapsible-heading-collapsed").trigger("click");
|
|
});
|
|
});
|
|
|
|
if (hasBadFields())
|
|
{
|
|
validatorHint.push(L("lcl_shared_validator_invalid"));
|
|
anyBad = true;
|
|
}
|
|
|
|
$(".required").filter(jqcheckonly).not(jqchecknot).filter(':visible').each(function (i)
|
|
{
|
|
switch (this.tagName)
|
|
{
|
|
case "SELECT":
|
|
{
|
|
$(this).removeClass(clsName);
|
|
$("#req_"+this.name + ",#" + this.name).removeClass(clsName);
|
|
var opt = $(this).find("option:selected");
|
|
if (this.options.length == 0 || opt.length == 0|| opt.val() == "-1" || opt.val() == "") // flex 'R' heeft leeg
|
|
{
|
|
$(this).addClass(clsName);
|
|
if (this.options.length)
|
|
opt.addClass(clsName);
|
|
else
|
|
$("#" + this.name).addClass(clsName);
|
|
anyMissing = true;
|
|
}
|
|
break;
|
|
}
|
|
case "INPUT":
|
|
{
|
|
if (this.type == 'button')
|
|
{ // specifiek voor de bijlage knop, om te kijken of er bijlagen zijn indien dit vereist wordt.
|
|
$(this).removeClass(clsName);
|
|
if (this.getAttribute("isBijlage")==1)
|
|
{
|
|
if (this.getAttribute("nBijlagen") == 0) // Als het aantal op de button 0 is, dan isMissing
|
|
{
|
|
$(this).addClass(clsName);
|
|
anyMissing = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
if (this.type == 'text' && this.getAttribute("hasvalue"))
|
|
{ // de class missing moet op de div boven de input staan.
|
|
$("#req_"+this.name).removeClass(clsName);
|
|
if (this.getAttribute("hasvalue") == 0)
|
|
{
|
|
$("#req_"+this.name).addClass(clsName);
|
|
anyMissing = true;
|
|
}
|
|
break;
|
|
}
|
|
// voor andere type=text doorvallen naar textarea
|
|
}
|
|
case "TEXTAREA":
|
|
{
|
|
// bij currency zijn we extra streng: 0.0 wordt niet geaccepteerd.
|
|
// tenzij je oorspronkelijk requiredor0:true (ipv required) hebt meegegeven
|
|
$(this).removeClass(clsName);
|
|
if ($.trim($(this).val()) == "" ||
|
|
($(this).hasClass("currency") && !$(this).hasClass("required0isoke") && parseFloat($(this).val().replace(',', '.')) == 0) ||
|
|
$(this).hasClass("suggestBad") ||
|
|
($(this).hasClass("suggest") && this.getAttribute("sgKey") < 0))
|
|
{
|
|
$(this).addClass(clsName);
|
|
anyMissing = true;
|
|
}
|
|
// Ten behoeve van foute invoer/formattering datum.
|
|
// Indien geen reguliere expressie (regexp) dan bad zetten anders eerst controlen of format nu goed is.
|
|
else if ($(this).hasClass("bad") && (this.getAttribute("regexp") == null || !_isGoodTextFormat(this)))
|
|
{
|
|
$(this).addClass(clsName);
|
|
anyBad = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
)
|
|
|
|
$(".suggestBad").each(function (i)
|
|
{
|
|
if($(this).val() != "" && !$(this).hasClass("missing"))
|
|
{
|
|
anyBad = true;
|
|
}
|
|
}
|
|
)
|
|
|
|
$(".number").filter(jqcheckonly).not(jqchecknot).filter(':visible').each(function (i)
|
|
{
|
|
if ($(this).val() != "" && isNaN(parseInt($(this).val()), 10))
|
|
{
|
|
$(this).addClass("bad");
|
|
anyBad = true;
|
|
}
|
|
else
|
|
{
|
|
$(this).removeClass("bad"); // Een eventuele attention blijft er op staan!
|
|
}
|
|
}
|
|
)
|
|
$(".float").filter(jqcheckonly).not(jqchecknot).filter(':visible').each(function (i)
|
|
{
|
|
if ($(this).val() != "" && !isFinite(parseFloat($(this).val())))
|
|
{
|
|
$(this).addClass("bad");
|
|
anyBad = true;
|
|
}
|
|
else
|
|
{
|
|
$(this).removeClass("bad"); // Een eventuele attention blijft er op staan!
|
|
}
|
|
}
|
|
)
|
|
$(".currency").filter(jqcheckonly).not(jqchecknot).filter(':visible').each(function (i)
|
|
{
|
|
if ($(this).val() != "" && !_isGoodCurrency($(this).val().replace(',', '.'), undefined, $(this).hasClass('relativeValuesAllowed')))
|
|
{
|
|
$(this).addClass("bad");
|
|
anyBad = true;
|
|
}
|
|
else
|
|
{
|
|
$(this).removeClass("bad"); // Een eventuele attention blijft er op staan!
|
|
}
|
|
}
|
|
)
|
|
$("input[regexp]").filter(jqcheckonly).not(jqchecknot).filter(':visible').each(function (i)
|
|
{
|
|
if (($(this).hasClass("required") || $(this).val()) && (!_isGoodTextFormat(this)))
|
|
{
|
|
$(this).addClass("bad");
|
|
anyBad = true;
|
|
}
|
|
else
|
|
{
|
|
$(this).removeClass("bad"); // Een eventuele attention blijft er op staan!
|
|
}
|
|
}
|
|
)
|
|
$("textarea[regexp]").filter(jqcheckonly).not(jqchecknot).filter(':visible').each(function (i)
|
|
{
|
|
if (($(this).hasClass("required") || $(this).val()) && (!_isGoodTextFormat(this)))
|
|
{
|
|
$(this).addClass("bad");
|
|
anyBad = true;
|
|
}
|
|
else
|
|
{
|
|
$(this).removeClass("bad"); // Een eventuele attention blijft er op staan!
|
|
}
|
|
}
|
|
)
|
|
|
|
/* Experimenteel. Nieuwe browsers staan bij een maxlength ook in een textarea niet al
|
|
te veel karakters toe dus is dan dubbelop */
|
|
// Echter bij importeren van tekst in een input of texarea veld kunnen er wel meer tekens in komen te staan dan maxlength.
|
|
// In dat geval moeten we deze check bijvoorbeeld laten uitvoeren.
|
|
if (params.checklength)
|
|
{
|
|
// Lengte controle
|
|
$("input:enabled,textarea:enabled").filter(jqcheckonly).not(jqchecknot).filter(':visible').each(function (i)
|
|
{
|
|
var txt = $(this).val()||"";
|
|
var maxlen = parseInt($(this).attr("maxlength"), 10)||4000;
|
|
if (txt.length > maxlen)
|
|
{
|
|
var lbl = $("label[for="+ this.name +"]").text() || // Label van flexkenmerken op eigen regel. Label staat voor het veld.
|
|
$(this).closest('table').find('th').eq($(this).closest('td').index()).text() || // Label van flexkenmerken op eerste regel achter parkeerplaats. Label staat boven in de kolom boven het veld.
|
|
"";
|
|
if ($("label[for="+ this.name +"]").text() != "")
|
|
lbl = lbl.replace(/\:$/, ""); // Dubbele punt aan einde weg indien aanwezig indien flex op eigen regel
|
|
if (lbl != "")
|
|
lbl = "'" + lbl + "'";
|
|
validatorHint.push(L("lcl_shared_validator_length").format(lbl, maxlen, txt.length));
|
|
$(this).addClass("bad");
|
|
|
|
anyBad = true;
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
// Klap dichtgeklaptje flexkenmerken eventueel open
|
|
$(".missing,.bad").each(function(i)
|
|
{
|
|
var labels = $(this).closest("tr").prevAll("tr.trlabel.flexlabel");
|
|
if (labels.length && $(labels[0]).hasClass("flexcollapsed"))
|
|
{
|
|
$(labels[0]).click();
|
|
}
|
|
});
|
|
|
|
if (params.relaxed && (anyMissing || anyBad))
|
|
return false;
|
|
|
|
if (anyMissing)
|
|
{
|
|
FcltMgr.alert(L("lcl_shared_validator_missing"));
|
|
return false;
|
|
}
|
|
else if (anyBad)
|
|
{
|
|
if (!validatorHint.length)
|
|
{
|
|
validatorHint = [L("lcl_shared_validator_format")];
|
|
}
|
|
FcltMgr.alert(validatorHint.join("\n"));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// Functies t.b.v. tijd velden
|
|
// werk veld om naar h:mm syntax
|
|
// 1.5 ==> 1:30, 1:5==>1:05, 1:50==>1:50, 1.50==>1:30,
|
|
// 2==>2:00, 10==>0:10, 40==>0:40, 10:00==>10:00 etc.
|
|
function sanitizeHours(veld, minvalue)
|
|
{
|
|
var valid = true;
|
|
if (!minvalue)
|
|
{
|
|
var TIME_RE = /^(\d*)([\/\.\,\-\:])?(\d\d?)?$/;
|
|
}
|
|
else
|
|
{
|
|
var TIME_RE = /^(\-)?(\d*)([\/\.\,\-\:])?(\d\d?)?$/;
|
|
}
|
|
|
|
var tmtxt = $(veld).val();
|
|
var posstime = tmtxt.match(TIME_RE);
|
|
|
|
if (posstime && posstime.length
|
|
&& !isNaN(parseInt(posstime, 10))
|
|
) // er moet minstens iets goed zijn
|
|
{ // De indexen van posstime verschuiven 1 positie als minvalue = true
|
|
// omdat op plaats 0 nu eventueel het -teken komt te staan.
|
|
var pt_sep = (minvalue?3:2); // index van uur/minuut seperator
|
|
var pt_mm = pt_sep + 1; // index van minuten
|
|
|
|
var hh = Math.abs(parseInt(posstime, 10) || 0);
|
|
var mm = 0;
|
|
if (posstime.length > pt_sep && posstime[pt_mm] != "")
|
|
{
|
|
var mm = parseInt(posstime[pt_mm], 10) || 0;
|
|
if (posstime[pt_sep] == "." || posstime[pt_sep] == ",")
|
|
{
|
|
mm = Math.floor(0.5 + 60 * parseFloat("0." + posstime[pt_mm]));
|
|
// 2.5 moet 2:30 worden en niet 2.05, 2.25 moet 2:15 worden
|
|
}
|
|
// else // 2:5 wordt 2:05
|
|
}
|
|
else // 40 voor 0:40
|
|
if (hh >= 10)
|
|
{
|
|
mm = hh % 60;
|
|
hh = Math.floor(hh / 60);
|
|
}
|
|
hh = hh % 24;
|
|
mm = mm % 60;
|
|
var hm = hh + mm/60;
|
|
// Opgeschoonde waarde opslaan
|
|
if (minvalue && posstime[1] == '-')
|
|
{
|
|
hm = -1 * hm;
|
|
}
|
|
$(veld).val(decimalToHour(hm));
|
|
}
|
|
else
|
|
if (tmtxt != "")
|
|
{
|
|
valid = false;
|
|
}
|
|
validateField(veld, valid, L("lcl_shared_validator_format"));
|
|
return valid;
|
|
}
|
|
|
|
// Usage: "Wilt U melding {0} afmelden?".format(12345)
|
|
String.prototype.format = function()
|
|
{
|
|
var formatted = this;
|
|
for (var i = 0; i < arguments.length; i++)
|
|
{
|
|
if (typeof arguments[i] == "string")
|
|
arguments[i] = arguments[i].replace(/\$/g, '$$$$');
|
|
var regexp = new RegExp('\\{'+i+'\\}', 'gi');
|
|
formatted = formatted.replace(regexp, arguments[i]);
|
|
}
|
|
return formatted;
|
|
};
|
|
|
|
// altijd :-syntax
|
|
function hourToDecimal(val)
|
|
{
|
|
if (!val || val == "")
|
|
return 0;
|
|
var hhmm = String(val).split(":");
|
|
var mintime = hhmm[0].indexOf('-') >= 0 ; // is tijd negatief of positief
|
|
var dtime = Math.abs(parseInt(hhmm[0], 10));
|
|
if (hhmm.length != 1)
|
|
{
|
|
dtime = dtime + parseInt(hhmm[1], 10) / 60;
|
|
}
|
|
return (mintime ? -1 * dtime : dtime);
|
|
}
|
|
|
|
// altijd :-syntax
|
|
function decimalToHour(val)
|
|
{
|
|
if (!val || val == 0)
|
|
return "";
|
|
var mintime = Math.abs(val) != val; // is tijd negatief of positief
|
|
var hh = Math.floor(Math.abs(val) + 0.5 / 60); // reken met positief tijd
|
|
var mm = Math.floor((Math.abs(val) - hh) * 60 + 0.5);
|
|
|
|
var timestr = String(hh) + ":" + String((mm < 10? "0" : "") + mm);
|
|
return (mintime ? "-" + timestr : timestr); // voeg eventueel weer min-teken toe
|
|
}
|
|
|
|
// Clientside variant van de shared.inc versie
|
|
var protectRequest =
|
|
{
|
|
dataToken: function (dataName) // Voeg aan een data hash een input token toe
|
|
{
|
|
dataName["RVT_token"] = window.RVT_token;
|
|
}
|
|
}
|
|
|
|
$(function () {
|
|
// Kijk of bij de buttons de teksten niet meer passen en we dus
|
|
// terugvallen op alleen de icons
|
|
$(window).on("resize", function ()
|
|
{
|
|
$("div.buttoncontainer").each(function ()
|
|
{
|
|
var w = $(window).width();
|
|
var p = $(this).position();
|
|
var smallsize = $(this).data("smallsize");
|
|
var pheader = $(this).closest("div.fcltframeheader");
|
|
var headertop = pheader.length?pheader.position().top:0;
|
|
|
|
if (p.top > headertop + 20) // shifted to next line?
|
|
{
|
|
$(this).addClass("smallbuttons")
|
|
.data("smallsize", Math.max(w, smallsize||0))
|
|
}
|
|
else
|
|
{
|
|
if (w > smallsize) // Weer groot genoeg geworden
|
|
$(this).removeClass("smallbuttons");
|
|
}
|
|
})
|
|
});
|
|
|
|
$(document).on("focus active", "input, textarea, select", function()
|
|
{
|
|
var thisid = $(this).attr("id") || $(this).attr("name");
|
|
if (thisid)
|
|
{
|
|
$("label[for="+thisid+"]").addClass("active");
|
|
thisid = thisid.replace(/_show$/, "");
|
|
$("label[for="+thisid+"]").addClass("active");
|
|
}
|
|
});
|
|
|
|
$(document).on("blur", "input, textarea, select", function()
|
|
{
|
|
var thisid = $(this).attr("id") || $(this).attr("name");
|
|
if (thisid)
|
|
{
|
|
$("label[for="+thisid+"]").removeClass("active");
|
|
thisid = thisid.replace(/_show$/, "");
|
|
$("label[for="+thisid+"]").removeClass("active");
|
|
}
|
|
});
|
|
|
|
// Zorg dat mailto-type links niet de spinners triggeren.
|
|
$("a[href^='mailto:'], a[href^='tel:'], a[href^='callto:']").each(function()
|
|
{
|
|
// Dit is een ongedocumenteerde interne (!) jQuery eventhandler collection
|
|
var e = $._data($(this).get(0), "events");
|
|
|
|
// Alleen er op zetten als deze er nog niet op zit
|
|
if (!e || !(e.mouseover && e.mouseout))
|
|
$(this).hover(function() { FcltMgr.setData("preventBeforeUnload", true); }, // mouseOver
|
|
function() { FcltMgr.setData("preventBeforeUnload", false); }); // mouseOut
|
|
});
|
|
|
|
$("input.float, input.number, input.currency").blur(function()
|
|
{
|
|
allowInputExpression(this);
|
|
});
|
|
});
|
|
|
|
// Als de input met een '=' begint doen we een 'eval' op de rest
|
|
function allowInputExpression(thisObj)
|
|
{
|
|
var val = $(thisObj).val();
|
|
if (val.substr(0,1) == '=')
|
|
{
|
|
try {
|
|
val = val.replace(/,/g,"."); // we staan ook komma's toe
|
|
var newval = eval(val.substr(1));
|
|
if (isFinite(newval))
|
|
{
|
|
if (val.indexOf(".") > -1 || $(thisObj).hasClass("currency"))
|
|
newval = num2currEditable(newval);
|
|
$(thisObj).val(newval);
|
|
}
|
|
// else negeren
|
|
}
|
|
catch (e) { /* negeren */ }
|
|
}
|
|
}
|
|
|
|
// Afronden van geldbedragen.
|
|
// roundcurr(1.275, 2); // Returns 1.28
|
|
// roundcurr(-1.275, 2); // Returns -1.28
|
|
// roundcurr(1.27499, 2); // Returns 1.27
|
|
// roundcurr(-1.27499, 2); // Returns -1.27
|
|
// roundcurr(1.2345678e+2, 2); // Returns 123.46
|
|
// roundcurr(1234.5678, -2); // Returns 1200
|
|
// roundcurr(123.45); // Returns 123
|
|
function roundcurr(value, exp) {
|
|
if (typeof exp === 'undefined' || +exp === 0)
|
|
return Math.round(value);
|
|
|
|
value = +value;
|
|
exp = +exp;
|
|
|
|
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
|
|
return NaN;
|
|
|
|
// Negatieve getallen voor het afronden even positief maken.
|
|
var negatief = false;
|
|
if (value < 0)
|
|
{
|
|
negatief = true;
|
|
value = value * -1;
|
|
}
|
|
|
|
// Shift
|
|
value = value.toString().split('e');
|
|
value = Math.round(+(value[0] + 'e' + (value[1]? (+value[1] + exp) : exp)));
|
|
|
|
// Negatieve getallen weer negatief maken.
|
|
if (negatief)
|
|
value = value * -1;
|
|
|
|
// Shift back
|
|
value = value.toString().split('e');
|
|
value = +(value[0] + 'e' + (value[1]? (+value[1] - exp) : -exp))
|
|
return (value).toFixed(exp); // value is al afgerond. ik kan nu gerust toFixed() gebruiken om eind nullen terug te krijgen (1.5toFixed(2) => 1.50).
|
|
}
|
|
|
|
// Voorheen num2curr.js
|
|
function num2curr(s) {
|
|
if( !isNaN(s) ) {
|
|
// MARX#58496: Be careful using ".toFixed()" as it might return different rounding results for different browsers.
|
|
//
|
|
// Afronding waarde.toFixed(2) voor verschillende browsers:
|
|
// IE: 251,075 => 251,08,
|
|
// FF,Crome: 251,075 => 251,07)
|
|
//
|
|
// Therefore we use roundcurr instead.
|
|
//s = s.toFixed(2);
|
|
s = roundcurr(s, 2);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
// Met eventueel gewenste decimaalscheider (punt of komma) maar
|
|
// nooit 1000-scheiders
|
|
function num2currEditable(fnum, decimals)
|
|
{
|
|
if (fnum == null)
|
|
return "";
|
|
|
|
if (typeof decimals == "undefined")
|
|
decimals = 2;
|
|
// MARX#58496: Be careful using ".toFixed()" as it might return different rounding results for different browsers.
|
|
//
|
|
// Afronding waarde.toFixed(2) voor verschillende browsers:
|
|
// IE: 251,075 => 251,08,
|
|
// FF,Crome: 251,075 => 251,07)
|
|
//
|
|
// Therefore we use roundcurr instead.
|
|
//fnum = fnum.toFixed(decimals);
|
|
fnum = roundcurr(fnum, decimals);
|
|
|
|
var waarde2 = (1.5).toLocaleString(); // Eventueel gewenste komma.
|
|
fnum = fnum.substring(0, fnum.length - decimals - 1) + waarde2.substring(2, 1) + fnum.substring(fnum.length - decimals);
|
|
|
|
return fnum;
|
|
}
|
|
|
|
function isGoodNumber(str, intOnly, posOnly, numLen, numDec)
|
|
{
|
|
var posOnlyStr = (posOnly ? "" : "\\-?");
|
|
var numLenStr = (numLen == -1 ? "" : (numDec == -1 ? numLen : (intOnly ? numLen : numLen - numDec)));
|
|
var numDecStr = (numDec == -1 ? "" : numDec);
|
|
|
|
var intOnlyStr = "\\d{1," + numLenStr + "}[.,]?";
|
|
var dblOnlyStr = "\\d{0," + numLenStr + "}[.,]\\d{1," + numDecStr + "}" + "|"
|
|
+ "\\d{1," + numLenStr + "}[.,]\\d{0," + numDecStr + "}" ;
|
|
|
|
var anum = "^"
|
|
+ posOnlyStr + "(" + intOnlyStr
|
|
+ (intOnly ? "" : "[.,]?" + "|" + dblOnlyStr)
|
|
+ ")"
|
|
+ "$";
|
|
|
|
var patt = new RegExp(anum);
|
|
return patt.test(str);
|
|
}
|
|
|
|
function getScrollHeight(elem)
|
|
{
|
|
if ($(elem).is(":hidden"))
|
|
{ // Insert a visible clone of the element as to gather its scrollHeight
|
|
var cloneParams = { "position": "absolute", "left": "-10000px" };
|
|
if ($(elem).parent().hasClass("bubble"))
|
|
cloneParams.width = "90%";
|
|
var $elemClone = $(elem).clone().css(cloneParams);
|
|
$elemClone.appendTo($(elem).closest("body")).show();
|
|
var scrollHeight = $elemClone.prop("scrollHeight");
|
|
// And immediately remove it again
|
|
$elemClone.remove();
|
|
return scrollHeight;
|
|
}
|
|
else
|
|
return $(elem).prop("scrollHeight");
|
|
}
|
|
|
|
function validateField(thisObj, valid, errorMsg)
|
|
{
|
|
var nextIsTimeHolder = $(thisObj).next("div.time-holder").length;
|
|
var $afterThisObj = nextIsTimeHolder ? $(thisObj).next("div.time-holder") : $(thisObj);
|
|
|
|
var hasIconFollower = $afterThisObj.next('i.fa').length;
|
|
$afterThisObj = hasIconFollower ? $afterThisObj.next('i.fa') : $afterThisObj;
|
|
|
|
$(thisObj).removeClass('bad');
|
|
$afterThisObj.next('span.bad').remove();
|
|
|
|
if (!valid)
|
|
{
|
|
$(thisObj).addClass('bad');
|
|
$afterThisObj.after('<span class="bad">' + errorMsg + '</span>')
|
|
}
|
|
FcltMgr.resized();
|
|
}
|
|
|
|
function hasBadFields()
|
|
{
|
|
return $(document).has('span.bad').length;
|
|
} |