/* $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 = $("
").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('«') } 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("
"); var $ul = $(""); $(".fcltframe").not(".notabframe").each(function () { $li = $("
  • "); $li.append("{1}".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) // Deze velden niet meer controleren jqchecknot = "#" + params.checkNot.join(",#"); if (params.relaxed) clsName = ""; $(".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) { 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 != "") { FcltMgr.alert(L("lcl_shared_validator_format")); return false; } return true; } // 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'); } }); });