Files
Facilitor/APPL/Localscripts/iface.js
2017-06-15 14:23:17 +00:00

788 lines
26 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)
{
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)
{
var formObject = { };
stringForm.find("input, select").each(function(){
var nm = this.id || this.name || null;
if (!nm)
return;
if ($(this).attr("type") == 'checkbox' || $(this).attr("type") == 'radio')
{
formObject[nm] = $(this).prop("checked");
}
else
{
var val = $(this).val();
if (val == "" || val == null)
return;
if (val == "-1" && nm.match(/key$/))
return;
//if (val === $(this).prop( 'defaultValue' ))
// return;
formObject[nm] = val;
if ($(this).hasClass("suggest"))
{
if (!("suggestattr" in formObject))
formObject.suggestattr = {};
formObject.suggestattr[nm] =
{ // 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.id || this.name || null;
if (!nm)
return;
if (!(nm in formObject))
return;
if (this.id)
var input = stringForm.find("#" + nm)
else
input = stringForm.find("[name=" + nm + "]");
if (!input.length)
return;
if (input.attr("type")=="checkbox" || input.attr("type")=="radio" )
{
input.prop("checked", !!formObject[nm])
}
else if (input.prop("tagName") == "SELECT")
{
if (formObject[nm] instanceof Array && formObject[nm].length > 1) // Maak hem multiselect
{
input.attr('multiple', 1);
input.attr('size', Math.min(input.find("option").length, 8));
input.val(formObject[nm]); // gewoon
input.prev().html('&laquo;')
}
else
input.val(formObject[nm]); // gewoon
}
else
{
input.val(formObject[nm]);
input.prop('defaultValue', formObject[nm]);
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?
params = params || {};
function _isGoodCurrency(str, checkInteger)
{
var anum = /^([-\+]?\d+[.,]?|[-\+]?\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");
}
validatorHint.push((spantitle[0].textContent || spantitle[0].innerText) + ' ' + hint);
}
vIsGood = false;
}
return vIsGood;
}
try
{
if (document.activeElement && document.activeElement.tagName != 'BODY')
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 = "";
// 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(',', '.')))
{
$(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(("Veld {0} is te lang. Maximum is {1} karakters, huidig is {2}.".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++)
{
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["__RequestVerificationToken"] = 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');
}
});
$("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 */ }
}
}
// Voorheen num2curr.js
function num2curr(s) {
// debugger;
if( !isNaN(s) ) {
s = s.toFixed(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;
fnum = fnum.toFixed(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 validateField(thisObj, valid, errorMsg)
{
var hasIconFollower = $(thisObj).next('i.fa').length;
var $afterThisObj = hasIconFollower ? $(thisObj).next('i.fa') : $(thisObj);
$(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;
}