/* The following errors were found when attempting to minify this file: - Line 54: Parse error. missing : after property id - Line 54: Parse error. illegal character - Line 54: Parse error. missing ; before statement - Line 54: Parse error. illegal character - Line 54: Parse error. syntax error - Line 55: Parse error. syntax error - Line 56: Parse error. syntax error - Line 57: Parse error. syntax error - Line 59: Parse error. syntax error - Line 60: Parse error. illegal character - Line 60: Parse error. missing ) after argument list - Line 60: Parse error. illegal character - Line 60: Parse error. syntax error - Line 61: Parse error. syntax error - Line 62: Parse error. syntax error - Line 63: Parse error. syntax error - Line 64: Parse error. syntax error - Line 66: Parse error. syntax error - Line 68: Parse error. missing ; before statement - Line 76: Parse error. syntax error - Line 78: Parse error. syntax error - Line 83: Parse error. invalid return - Line 84: Parse error. syntax error - Line 86: Parse error. missing ; before statement - Line 90: Parse error. syntax error - Line 91: Parse error. syntax error - Line 92: Parse error. syntax error - Line 94: Parse error. syntax error - Line 96: Parse error. missing ; before statement - Line 102: Parse error. illegal character - Line 102: Parse error. missing ; before statement - Line 102: Parse error. illegal character - Line 103: Parse error. syntax error - Line 104: Parse error. syntax error - Line 107: Parse error. syntax error - Line 110: Parse error. illegal character - Line 110: Parse error. missing ; before statement - Line 110: Parse error. illegal character - Line 114: Parse error. invalid return - Line 115: Parse error. syntax error - Line 117: Parse error. missing ; before statement - Line 118: Parse error. syntax error - Line 119: Parse error. syntax error - Line 120: Parse error. syntax error - Line 125: Parse error. invalid return - Line 130: Parse error. missing ; after for-loop initializer - Line 130: Parse error. missing ; before statement - Line 137: Parse error. syntax error - Line 144: Parse error. syntax error - Line 146: Parse error. syntax error - Line 148: Parse error. syntax error - Line 149: Parse error. syntax error - Line 150: Parse error. syntax error - Line 440: Parse error. missing ; before statement - Line 4762: Parse error. IE8 (and below) will parse trailing commas in array and object literals incorrectly. If you are targeting newer versions of JS, set the appropriate language_in option. - Line 5035: Parse error. IE8 (and below) will parse trailing commas in array and object literals incorrectly. If you are targeting newer versions of JS, set the appropriate language_in option. - Line 5145: Parse error. syntax error - Line 5150: Parse error. illegal character - Line 5150: Parse error. missing } in compound statement - Line 5150: Parse error. missing ; before statement - Line 5150: Parse error. illegal character - Line 5151: Parse error. syntax error - Line 5153: Parse error. missing ) in parenthetical - Line 5154: Parse error. syntax error - Line 5159: Parse error. illegal character - Line 5159: Parse error. missing } in compound statement - Line 5159: Parse error. missing ; before statement - Line 5159: Parse error. illegal character - Line 5161: Parse error. syntax error - Line 5163: Parse error. invalid return - Line 5163: Parse error. syntax error - Line 5168: Parse error. invalid return - Line 5168: Parse error. illegal character - Line 5168: Parse error. missing } in compound statement - Line 5168: Parse error. missing ; before statement - Line 5168: Parse error. illegal character - Line 5169: Parse error. syntax error - Line 5170: Parse error. syntax error - Line 5172: Parse error. invalid return - Line 5174: Parse error. syntax error - Line 5175: Parse error. syntax error - Line 5176: Parse error. syntax error */ /*! * pickadate.js v3.6.4, 2019/05/25 * By Amsul, http://amsul.ca * Hosted on http://amsul.github.io/pickadate.js * Licensed under MIT */ (function(n){typeof define=="function"&&define.amd?define("picker",["jquery"],n):typeof exports=="object"?module.exports=n(require("jquery")):typeof window=="object"?window.Picker=n(jQuery):this.Picker=n(jQuery)})(function(n){function t(e,s,h,a){function g(){return t._.node("div",t._.node("div",t._.node("div",t._.node("div",v.component.nodes(y.open),w.box),w.wrap),w.frame),w.holder,'tabindex="-1"')}function rt(){b.data(s,v).addClass(w.input).val(b.data("value")?v.get("select",p.format):e.value).on("focus."+y.id+" click."+y.id,function(n){n.preventDefault();v.open()}).on("mousedown",function(){y.handlingOpen=!0;var t=function(){setTimeout(function(){n(document).off("mouseup",t);y.handlingOpen=!1},0)};n(document).on("mouseup",t)});if(!p.editable)b.on("keydown."+y.id,it);i(e,{haspopup:!0,readonly:!1,owns:e.id+"_root"})}function ut(){i(v.$root[0],"hidden",!0)}function nt(){v.$holder.on({keydown:it,"focus.toOpen":tt,blur:function(){b.removeClass(w.target)},focusin:function(n){v.$root.removeClass(w.focused);n.stopPropagation()},"mousedown click":function(t){var i=r(t,e);i!=v.$holder[0]&&(t.stopPropagation(),t.type!="mousedown"||n(i).is("input, select, textarea, button, option")||(t.preventDefault(),v.$holder.eq(0).focus()))}}).on("click","[data-pick], [data-nav], [data-clear], [data-close]",function(){var r=n(this),i=r.data(),u=r.hasClass(w.navDisabled)||r.hasClass(w.disabled),t=o();t=t&&(t.type||t.href?t:null);(u||t&&!n.contains(v.$root[0],t))&&v.$holder.eq(0).focus();!u&&i.nav?v.set("highlight",v.component.item.highlight,{nav:i.nav}):!u&&"pick"in i?(v.set("select",i.pick),p.closeOnSelect&&v.close(!0)):i.clear?(v.clear(),p.closeOnClear&&v.close(!0)):i.close&&v.close(!0)})}function ft(){var t;p.hiddenName===!0?(t=e.name,e.name=""):(t=[typeof p.hiddenPrefix=="string"?p.hiddenPrefix:"",typeof p.hiddenSuffix=="string"?p.hiddenSuffix:"_submit"],t=t[0]+e.name+t[1]);v._hidden=n('")[0];b.on("change."+y.id,function(){v._hidden.value=e.value?v.get("select",p.formatSubmit):""})}function et(){if(k&&c)v.$holder.find("."+w.frame).one("transitionend",function(){v.$holder.eq(0).focus()});else setTimeout(function(){v.$holder.eq(0).focus()},0)}function tt(n){n.stopPropagation();b.addClass(w.target);v.$root.addClass(w.focused);v.open()}function it(n){var t=n.keyCode,i=/^(8|46)$/.test(t);if(t==27)return v.close(!0),!1;(t==32||i||!y.open&&v.component.key[t])&&(n.preventDefault(),n.stopPropagation(),i?v.clear().close():v.open())}if(!e)return t;var k=!1,y={id:e.id||"P"+Math.abs(~~(Math.random()*new Date)),handlingOpen:!1},p=h?n.extend(!0,{},h.defaults,a):a||{},w=n.extend({},t.klasses(),p.klass),b=n(e),d=function(){return this.start()},v=d.prototype={constructor:d,$node:b,start:function(){if(y&&y.start)return v;y.methods={};y.start=!0;y.open=!1;y.type=e.type;e.autofocus=e==o();e.readOnly=!p.editable;p.id=e.id=e.id||y.id;e.type!="text"&&(e.type="text");v.component=new h(v,p);v.$root=n('
');ut();v.$holder=n(g()).appendTo(v.$root);nt();p.formatSubmit&&ft();rt();p.containerHidden?n(p.containerHidden).append(v._hidden):b.after(v._hidden);p.container?n(p.container).append(v.$root):b.after(v.$root);v.on({start:v.component.onStart,render:v.component.onRender,stop:v.component.onStop,open:v.component.onOpen,close:v.component.onClose,set:v.component.onSet}).on({start:p.onStart,render:p.onRender,stop:p.onStop,open:p.onOpen,close:p.onClose,set:p.onSet});return k=l(v.$holder[0]),e.autofocus&&v.open(),v.trigger("start").trigger("render")},render:function(t){return t?(v.$holder=n(g()),nt(),v.$root.html(v.$holder)):v.$root.find("."+w.box).html(v.component.nodes(y.open)),v.trigger("render")},stop:function(){return y.start?(v.close(),v._hidden&&v._hidden.parentNode.removeChild(v._hidden),v.$root.remove(),b.removeClass(w.input).removeData(s),setTimeout(function(){b.off("."+y.id)},0),e.type=y.type,e.readOnly=!1,v.trigger("stop"),y.methods={},y.start=!1,v):v},open:function(o){if(y.open)return v;if(b.addClass(w.active),setTimeout(function(){v.$root.addClass(w.opened);i(v.$root[0],"hidden",!1)},0),o!==!1){y.open=!0;k&&n("body").css("overflow","hidden").css("padding-right","+="+f());et();u.on("click."+y.id+" focusin."+y.id,function(n){if(!y.handlingOpen){var t=r(n,e);n.isSimulated||t==e||t==document||n.which==3||v.close(t===v.$holder[0])}}).on("keydown."+y.id,function(i){var u=i.keyCode,f=v.component.key[u],o=r(i,e);u==27?v.close(!0):o==v.$holder[0]&&(f||u==13)?(i.preventDefault(),f?t._.trigger(v.component.key.go,v,[t._.trigger(f)]):v.$root.find("."+w.highlighted).hasClass(w.disabled)||(v.set("select",v.component.item.highlight),p.closeOnSelect&&v.close(!0))):n.contains(v.$root[0],o)&&u==13&&(i.preventDefault(),o.click())})}return v.trigger("open")},close:function(t){return(t&&(p.editable?e.focus():(v.$holder.off("focus.toOpen").focus(),setTimeout(function(){v.$holder.on("focus.toOpen",tt)},0))),b.removeClass(w.active),setTimeout(function(){v.$root.removeClass(w.opened+" "+w.focused);i(v.$root[0],"hidden",!0)},0),!y.open)?v:(y.open=!1,k&&n("body").css("overflow","").css("padding-right","-="+f()),u.off("."+y.id),v.trigger("close"))},clear:function(n){return v.set("clear",null,n)},set:function(t,i,r){var u,f,o=n.isPlainObject(t),e=o?t:{};if(r=o&&n.isPlainObject(i)?i:r||{},t){o||(e[t]=i);for(u in e)f=e[u],u in v.component.item&&(f===undefined&&(f=null),v.component.set(u,f,r)),(u=="select"||u=="clear")&&p.updateInput&&b.val(u=="clear"?"":v.get(u,p.format)).trigger("change");v.render()}return r.muted?v:v.trigger("set",e)},get:function(n,i){if(n=n||"value",y[n]!=null)return y[n];if(n=="valueSubmit"){if(v._hidden)return v._hidden.value;n="value"}if(n=="value")return e.value;if(n in v.component.item){if(typeof i=="string"){var r=v.component.get(n);return r?t._.trigger(v.component.formats.toString,v.component,[i,r]):""}return v.component.get(n)}},on:function(t,i,r){var u,e,o=n.isPlainObject(t),f=o?t:{};if(t){o||(f[t]=i);for(u in f)e=f[u],r&&(u="_"+u),y.methods[u]=y.methods[u]||[],y.methods[u].push(e)}return v},off:function(){var n,t,i=arguments;for(n=0,namesCount=i.length;n').appendTo("body"),i=t[0].offsetWidth,t.css("overflow","scroll"),r=n('
').appendTo(t),u=r[0].offsetWidth,t.remove(),i-u)}function r(n,t){var i=[];return(n.path&&(i=n.path),n.originalEvent&&n.originalEvent.path&&(i=n.originalEvent.path),i&&i.length>0)?t&&i.indexOf(t)>=0?t:i[0]:n.target}function i(t,i,r){if(n.isPlainObject(i))for(var u in i)e(t,u,i[u]);else e(t,i,r)}function e(n,t,i){n.setAttribute((t=="role"?"":"aria-")+t,i)}function a(t,i){var r,u,f;n.isPlainObject(t)||(t={attribute:i});i="";for(r in t)u=(r=="role"?"":"aria-")+r,f=t[r],i+=f==null?"":u+'="'+t[r]+'"';return i}function o(){try{return document.activeElement}catch(n){}}var s=n(window),u=n(document),h=n(document.documentElement),c=document.documentElement.style.transition!=null;return t.klasses=function(n){return n=n||"picker",{picker:n,opened:n+"--opened",focused:n+"--focused",input:n+"__input",active:n+"__input--active",target:n+"__input--target",holder:n+"__holder",frame:n+"__frame",wrap:n+"__wrap",box:n+"__box"}},t._={group:function(n){for(var i,u="",r=t._.trigger(n.min,n);r<=t._.trigger(n.max,n,[r]);r+=n.i)i=t._.trigger(n.item,n,[r]),u+=t._.node(n.node,i[0],i[1],i[2]);return u},node:function(t,i,r,u){return i?(i=n.isArray(i)?i.join(""):i,r=r?' class="'+r+'"':"",u=u?" "+u:"","<"+t+r+u+">"+i+"<\/"+t+">"):""},lead:function(n){return(n<10?"0":"")+n},trigger:function(n,t,i){return typeof n=="function"?n.apply(t,i||[]):n},digits:function(n){return/\d/.test(n[1])?2:1},isDate:function(n){return{}.toString.call(n).indexOf("Date")>-1&&this.isInteger(n.getDate())},isInteger:function(n){return{}.toString.call(n).indexOf("Number")>-1&&n%1==0},ariaAttr:a},t.extend=function(i,r){n.fn[i]=function(u,f){var e=this.data(i);return u=="picker"?e:e&&typeof u=="string"?t._.trigger(e[u],e,[f]):this.each(function(){var f=n(this);f.data(i)||new t(this,i,r,u)})};n.fn[i].defaults=r.defaults},t}); /*! * Date picker for pickadate.js v3.6.4 * http://amsul.github.io/pickadate.js/date.htm */ (function(n){typeof define=="function"&&define.amd?define(["./picker","jquery"],n):typeof exports=="object"?module.exports=n(require("./picker.js"),require("jquery")):n(Picker,jQuery)})(function(n,t){function r(n,t){var i=this,r=n.$node[0],o=r.value,u=n.$node.data("value"),f=u||o,s=u?t.formatSubmit:t.format,e=function(){return r.currentStyle?r.currentStyle.direction=="rtl":getComputedStyle(n.$root[0]).direction=="rtl"};i.settings=t;i.$node=n.$node;i.queue={min:"measure create",max:"measure create",now:"now create",select:"parse create validate",highlight:"parse navigate create validate",view:"parse create validate viewset",disable:"deactivate",enable:"activate"};i.item={};i.item.clear=null;i.item.disable=(t.disable||[]).slice(0);i.item.enable=-function(n){return n[0]===!0?n.shift():-1}(i.item.disable);i.set("min",t.min).set("max",t.max).set("now");f?i.set("select",f,{format:s,defaultValue:!0}):i.set("select",null).set("highlight",i.item.now);i.key={40:7,38:-7,39:function(){return e()?-1:1},37:function(){return e()?1:-1},go:function(n){var t=i.item.highlight,r=new Date(t.year,t.month,t.date+n);i.set("highlight",r,{interval:n});this.render()}};n.on("render",function(){n.$root.find("."+t.klass.selectMonth).on("change",function(){var i=this.value;i&&(n.set("highlight",[n.get("view").year,i,n.get("highlight").date]),n.$root.find("."+t.klass.selectMonth).trigger("focus"))});n.$root.find("."+t.klass.selectYear).on("change",function(){var i=this.value;i&&(n.set("highlight",[i,n.get("view").month,n.get("highlight").date]),n.$root.find("."+t.klass.selectYear).trigger("focus"))})},1).on("open",function(){var r="";i.disabled(i.get("now"))&&(r=":not(."+t.klass.buttonToday+")");n.$root.find("button"+r+", select").attr("disabled",!1)},1).on("close",function(){n.$root.find("button, select").attr("disabled",!0)},1)}var u=7,f=6,i=n._;r.prototype.set=function(n,t,i){var r=this,u=r.item;return t===null?(n=="clear"&&(n="select"),u[n]=t,r):(u[n=="enable"?"disable":n=="flip"?"enable":n]=r.queue[n].split(" ").map(function(u){return t=r[u](n,t,i)}).pop(),n=="select"?r.set("highlight",u.select,i):n=="highlight"?r.set("view",u.highlight,i):n.match(/^(flip|min|max|disable|enable)$/)&&(u.select&&r.disabled(u.select)&&r.set("select",u.select,i),u.highlight&&r.disabled(u.highlight)&&r.set("highlight",u.highlight,i)),r)};r.prototype.get=function(n){return this.item[n]};r.prototype.create=function(n,r,u){var f,e=this;return r=r===undefined?n:r,r==-Infinity||r==Infinity?f=r:t.isPlainObject(r)&&i.isInteger(r.pick)?r=r.obj:t.isArray(r)?(r=new Date(r[0],r[1],r[2]),r=i.isDate(r)?r:e.create().obj):r=i.isInteger(r)||i.isDate(r)?e.normalize(new Date(r),u):e.now(n,r,u),{year:f||r.getFullYear(),month:f||r.getMonth(),date:f||r.getDate(),day:f||r.getDay(),obj:f||r,pick:f||r.getTime()}};r.prototype.createRange=function(n,r){var f=this,u=function(n){return n===!0||t.isArray(n)||i.isDate(n)?f.create(n):n};return i.isInteger(n)||(n=u(n)),i.isInteger(r)||(r=u(r)),i.isInteger(n)&&t.isPlainObject(r)?n=[r.year,r.month,r.date+n]:i.isInteger(r)&&t.isPlainObject(n)&&(r=[n.year,n.month,n.date+r]),{from:u(n),to:u(r)}};r.prototype.withinRange=function(n,t){return n=this.createRange(n.from,n.to),t.pick>=n.from.pick&&t.pick<=n.to.pick};r.prototype.overlapRanges=function(n,t){var i=this;return n=i.createRange(n.from,n.to),t=i.createRange(t.from,t.to),i.withinRange(n,t.from)||i.withinRange(n,t.to)||i.withinRange(t,n.from)||i.withinRange(t,n.to)};r.prototype.now=function(n,t,i){return t=new Date,i&&i.rel&&t.setDate(t.getDate()+i.rel),this.normalize(t,i)};r.prototype.navigate=function(n,i,r){var s,f,u,e,c=t.isArray(i),h=t.isPlainObject(i),o=this.item.view;if(c||h){for(h?(f=i.year,u=i.month,e=i.date):(f=+i[0],u=+i[1],e=+i[2]),r&&r.nav&&o&&o.month!==u&&(f=o.year,u=o.month),s=new Date(f,u+(r&&r.nav?r.nav:0),1),f=s.getFullYear(),u=s.getMonth();new Date(f,u,e).getMonth()!==u;)e-=1;i=[f,u,e]}return i};r.prototype.normalize=function(n){return n.setHours(0,0,0,0),n};r.prototype.measure=function(n,t){var r=this;return i.isInteger(t)?t=r.now(n,t,{rel:t}):t?typeof t=="string"&&(t=r.parse(n,t)):t=n=="min"?-Infinity:Infinity,t};r.prototype.viewset=function(n,t){return this.create([t.year,t.month,1])};r.prototype.validate=function(n,r,u){var f=this,c=r,e=u&&u.interval?u.interval:1,h=f.item.enable===-1,l,a,o=f.item.min,s=f.item.max,v,y,p=h&&f.item.disable.filter(function(n){if(t.isArray(n)){var u=f.create(n).pick;ur.pick&&(a=!0)}return i.isInteger(n)}).length;if((!u||!u.nav&&!u.defaultValue)&&(!h&&f.disabled(r)||h&&f.disabled(r)&&(p||l||a)||!h&&(r.pick<=o.pick||r.pick>=s.pick)))for(h&&!p&&(!a&&e>0||!l&&e<0)&&(e*=-1);f.disabled(r);){if(Math.abs(e)>1&&(r.monthc.month)&&(r=c,e=e>0?1:-1),r.pick<=o.pick?(v=!0,e=1,r=f.create([o.year,o.month,o.date+(r.pick===o.pick?0:-1)])):r.pick>=s.pick&&(y=!0,e=-1,r=f.create([s.year,s.month,s.date+(r.pick===s.pick?0:1)])),v&&y)break;r=f.create([r.year,r.month,r.date+e])}return r};r.prototype.disabled=function(n){var r=this,u=r.item.disable.filter(function(u){return i.isInteger(u)?n.day===(r.settings.firstDay?u:u-1)%7:t.isArray(u)||i.isDate(u)?n.pick===r.create(u).pick:t.isPlainObject(u)?r.withinRange(u,n):void 0});return u=u.length&&!u.filter(function(n){return t.isArray(n)&&n[3]=="inverted"||t.isPlainObject(n)&&n.inverted}).length,r.item.enable===-1?!u:u||n.pickr.item.max.pick};r.prototype.parse=function(n,t,r){var f=this,u={};return!t||typeof t!="string"?t:(r&&r.format||(r=r||{},r.format=f.settings.format),f.formats.toArray(r.format).map(function(n){var r=f.formats[n],e=r?i.trigger(r,f,[t,u]):n.replace(/^!/,"").length;r&&(u[n]=t.substr(0,e));t=t.substr(e)}),[u.yyyy||u.yy,+(u.mm||u.m)-1,u.dd||u.d])};r.prototype.formats=function(){function n(n,t,i){var r=n.match(/[^\x00-\x7F]+|[a-zA-Z0-9_\u0080-\u00FF]+/)[0];return i.mm||i.m||(i.m=t.indexOf(r)+1),r.length}function t(n){return n.match(/[a-zA-Z0-9_\u0080-\u00FF]+/)[0].length}return{d:function(n,t){return n?i.digits(n):t.date},dd:function(n,t){return n?2:i.lead(t.date)},ddd:function(n,i){return n?t(n):this.settings.weekdaysShort[i.day]},dddd:function(n,i){return n?t(n):this.settings.weekdaysFull[i.day]},m:function(n,t){return n?i.digits(n):t.month+1},mm:function(n,t){return n?2:i.lead(t.month+1)},mmm:function(t,i){var r=this.settings.monthsShort;return t?n(t,r,i):r[i.month]},mmmm:function(t,i){var r=this.settings.monthsFull;return t?n(t,r,i):r[i.month]},yy:function(n,t){return n?2:(""+t.year).slice(2)},yyyy:function(n,t){return n?4:t.year},toArray:function(n){return n.split(/(d{1,4}|m{1,4}|y{4}|yy|!.)/g)},toString:function(n,t){var r=this;return r.formats.toArray(n).map(function(n){return i.trigger(r.formats[n],r,[0,t])||n.replace(/^!/,"")}).join("")}}}();r.prototype.isDateExact=function(n,r){var u=this;return i.isInteger(n)&&i.isInteger(r)||typeof n=="boolean"&&typeof r=="boolean"?n===r:(i.isDate(n)||t.isArray(n))&&(i.isDate(r)||t.isArray(r))?u.create(n).pick===u.create(r).pick:t.isPlainObject(n)&&t.isPlainObject(r)?u.isDateExact(n.from,r.from)&&u.isDateExact(n.to,r.to):!1};r.prototype.isDateOverlap=function(n,r){var u=this,f=u.settings.firstDay?1:0;return i.isInteger(n)&&(i.isDate(r)||t.isArray(r))?(n=n%7+f,n===u.create(r).day+1):i.isInteger(r)&&(i.isDate(n)||t.isArray(n))?(r=r%7+f,r===u.create(n).day+1):t.isPlainObject(n)&&t.isPlainObject(r)?u.overlapRanges(n,r):!1};r.prototype.flipEnable=function(n){var t=this.item;t.enable=n||(t.enable==-1?1:-1)};r.prototype.deactivate=function(n,r){var f=this,u=f.item.disable.slice(0);return r=="flip"?f.flipEnable():r===!1?(f.flipEnable(1),u=[]):r===!0?(f.flipEnable(-1),u=[]):r.map(function(n){for(var e,r=0;r=h.year&&e.month>=h.month||!n&&e.year<=s.year&&e.month<=s.month?" "+t.klass.navDisabled:""),"data-nav="+(n||-1)+' tabindex="0" '+i.ariaAttr({role:"button",controls:r.$node[0].id+"_table"})+' title="'+(n?t.labelMonthNext:t.labelMonthPrev)+'"')},y=function(){var u=t.showMonthsShort?t.monthsShort:t.monthsFull;return t.selectMonths?i.node("select",i.group({min:0,max:11,i:1,node:"option",item:function(n){return[u[n],0,"value="+n+(e.month==n?" selected":"")+(e.year==s.year&&nh.month?" disabled":"")]}}),t.klass.selectMonth,(n?"":"disabled")+" "+i.ariaAttr({controls:r.$node[0].id+"_table"})+' title="'+t.labelMonthSelect+'"'):i.node("div",u[e.month],t.klass.month)},p=function(){var o=e.year,l=t.selectYears===!0?5:~~(t.selectYears/2),v,y;if(l){var c=s.year,a=h.year,u=o-l,f=o+l;return c>u&&(f+=c-u,u=c),ay?y:v,f=a),i.node("select",i.group({min:u,max:f,i:1,node:"option",item:function(n){return[n,0,"value="+n+(o==n?" selected":"")]}}),t.klass.selectYear,(n?"":"disabled")+" "+i.ariaAttr({controls:r.$node[0].id+"_table"})+' title="'+t.labelYearSelect+'"')}return i.node("div",o,t.klass.year)};return i.node("div",(t.selectYears?p()+y():y()+p())+v()+v(1),t.klass.header)+i.node("table",b+i.node("tbody",i.group({min:0,max:f-1,i:1,node:"tr",item:function(n){var f=t.firstDay&&r.create([e.year,e.month,1]).day===0?-7:0;return[i.group({min:u*n-e.day+f+1,max:function(){return this.min+u-1},i:1,node:"td",item:function(n){n=r.create([e.year,e.month,n+(t.firstDay?1:0)]);var u=l&&l.pick==n.pick,f=a&&a.pick==n.pick,o=w&&r.disabled(n)||n.pickh.pick,v=i.trigger(r.formats.toString,r,[t.format,n]),y=t.id+"_"+n.pick;return[i.node("div",n.date,function(i){return i.push(e.month==n.month?t.klass.infocus:t.klass.outfocus),c.pick==n.pick&&i.push(t.klass.now),u&&i.push(t.klass.selected),f&&i.push(t.klass.highlighted),o&&i.push(t.klass.disabled),i.join(" ")}([t.klass.day]),"data-pick="+n.pick+" id="+y+' tabindex="0" '+i.ariaAttr({role:"gridcell",label:v,selected:u&&r.$node.val()===v?!0:null,activedescendant:f?n.pick:null,disabled:o?!0:null})),""]}})]}})),t.klass.table,'id="'+r.$node[0].id+'_table" '+i.ariaAttr({role:"grid",controls:r.$node[0].id,readonly:!0}))+i.node("div",i.node("button",t.today,t.klass.buttonToday,"type=button data-pick="+c.pick+(n&&!r.disabled(c)?"":" disabled")+" "+i.ariaAttr({controls:r.$node[0].id}))+i.node("button",t.clear,t.klass.buttonClear,"type=button data-clear=1"+(n?"":" disabled")+" "+i.ariaAttr({controls:r.$node[0].id}))+i.node("button",t.close,t.klass.buttonClose,"type=button data-close=true "+(n?"":" disabled")+" "+i.ariaAttr({controls:r.$node[0].id})),t.klass.footer)};r.defaults=function(n){return{labelMonthNext:"Next month",labelMonthPrev:"Previous month",labelMonthSelect:"Select a month",labelYearSelect:"Select a year",monthsFull:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],weekdaysFull:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],weekdaysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],today:"Today",clear:"Clear",close:"Close",closeOnSelect:!0,closeOnClear:!0,updateInput:!0,format:"d mmmm, yyyy",klass:{table:n+"table",header:n+"header",navPrev:n+"nav--prev",navNext:n+"nav--next",navDisabled:n+"nav--disabled",month:n+"month",year:n+"year",selectMonth:n+"select--month",selectYear:n+"select--year",weekdays:n+"weekday",day:n+"day",disabled:n+"day--disabled",selected:n+"day--selected",highlighted:n+"day--highlighted",now:n+"day--today",infocus:n+"day--infocus",outfocus:n+"day--outfocus",footer:n+"footer",buttonClear:n+"button--clear",buttonToday:n+"button--today",buttonClose:n+"button--close"}}}(n.klasses().picker+"__");n.extend("pickadate",r)}); /*! * Time picker for pickadate.js v3.6.4 * http://amsul.github.io/pickadate.js/time.htm */ (function(n){typeof define=="function"&&define.amd?define(["./picker","jquery"],n):typeof exports=="object"?module.exports=n(require("./picker.js"),require("jquery")):n(Picker,jQuery)})(function(n,t){function r(n,t){var i=this,f=n.$node[0].value,r=n.$node.data("value"),u=r||f,e=r?t.formatSubmit:t.format;i.settings=t;i.$node=n.$node;i.queue={interval:"i",min:"measure create",max:"measure create",now:"now create",select:"parse create validate",highlight:"parse create validate",view:"parse create validate",disable:"deactivate",enable:"activate"};i.item={};i.item.clear=null;i.item.interval=t.interval||30;i.item.disable=(t.disable||[]).slice(0);i.item.enable=-function(n){return n[0]===!0?n.shift():-1}(i.item.disable);i.set("min",t.min).set("max",t.max).set("now");u?i.set("select",u,{format:e}):i.set("select",null).set("highlight",i.item.now);i.key={40:1,38:-1,39:1,37:-1,go:function(n){i.set("highlight",i.item.highlight.pick+n*i.item.interval,{interval:n*i.item.interval});this.render()}};n.on("render",function(){var i=n.$root.children(),r=i.find("."+t.klass.viewset),u=function(n){return["webkit","moz","ms","o",""].map(function(t){return(t?"-"+t+"-":"")+n})},f=function(n,t){u("transform").map(function(i){n.css(i,t)});u("transition").map(function(i){n.css(i,t)})};r.length&&(f(i,"none"),i[0].scrollTop=~~r.position().top-r[0].clientHeight*2,f(i,""))},1).on("open",function(){n.$root.find("button").attr("disabled",!1)},1).on("close",function(){n.$root.find("button").attr("disabled",!0)},1)}var e=24,u=60,o=12,f=e*u,i=n._;r.prototype.set=function(n,t,i){var r=this,u=r.item;return t===null?(n=="clear"&&(n="select"),u[n]=t,r):(u[n=="enable"?"disable":n=="flip"?"enable":n]=r.queue[n].split(" ").map(function(u){return t=r[u](n,t,i)}).pop(),n=="select"?r.set("highlight",u.select,i):n=="highlight"?r.set("view",u.highlight,i):n=="interval"?r.set("min",u.min,i).set("max",u.max,i):n.match(/^(flip|min|max|disable|enable)$/)&&(u.select&&r.disabled(u.select)&&r.set("select",t,i),u.highlight&&r.disabled(u.highlight)&&r.set("highlight",t,i),n=="min"&&r.set("max",u.max,i)),r)};r.prototype.get=function(n){return this.item[n]};r.prototype.create=function(n,r,o){var s=this;return r=r===undefined?n:r,i.isDate(r)&&(r=[r.getHours(),r.getMinutes()]),t.isPlainObject(r)&&i.isInteger(r.pick)?r=r.pick:t.isArray(r)?r=+r[0]*u+ +r[1]:i.isInteger(r)||(r=s.now(n,r,o)),n=="max"&&r=n.from.pick&&t.pick<=n.to.pick};r.prototype.overlapRanges=function(n,t){var i=this;return n=i.createRange(n.from,n.to),t=i.createRange(t.from,t.to),i.withinRange(n,t.from)||i.withinRange(n,t.to)||i.withinRange(t,n.from)||i.withinRange(t,n.to)};r.prototype.now=function(n,t){var f=this.item.interval,o=new Date,r=o.getHours()*u+o.getMinutes(),s=i.isInteger(t),e;return r-=r%f,e=t<0&&f*t+r<=-f,r+=n=="min"&&e?0:f,s&&(r+=f*(e&&n!="max"?t+1:t)),r};r.prototype.normalize=function(n,t){var i=this.item.interval,r=this.item.min&&this.item.min.pick||0;return t-(n=="min"?0:(t-r)%i)};r.prototype.measure=function(n,r,f){var o=this;return r||(r=n=="min"?[0,0]:[e-1,u-1]),typeof r=="string"?r=o.parse(n,r):r===!0||i.isInteger(r)?r=o.now(n,r,f):t.isPlainObject(r)&&i.isInteger(r.pick)&&(r=o.normalize(n,r.pick,f)),r};r.prototype.validate=function(n,t,i){var r=this,u=i&&i.interval?i.interval:r.item.interval;return r.disabled(t)&&(t=r.shift(t,u)),t=r.scope(t),r.disabled(t)&&(t=r.shift(t,u*-1)),t};r.prototype.disabled=function(n){var r=this,u=r.item.disable.filter(function(u){return i.isInteger(u)?n.hour==u:t.isArray(u)||i.isDate(u)?n.pick==r.create(u).pick:t.isPlainObject(u)?r.withinRange(u,n):void 0});return u=u.length&&!u.filter(function(n){return t.isArray(n)&&n[2]=="inverted"||t.isPlainObject(n)&&n.inverted}).length,r.item.enable===-1?!u:u||n.pickr.item.max.pick};r.prototype.shift=function(n,t){var i=this,r=i.item.min.pick,u=i.item.max.pick;for(t=t||i.item.interval;i.disabled(n);)if(n=i.create(n.pick+=t),n.pick<=r||n.pick>=u)break;return n};r.prototype.scope=function(n){var t=this.item.min.pick,i=this.item.max.pick;return this.create(n.pick>i?i:n.pickt.time%f?"a.m.":"p.m."},A:function(n,t){return n?2:f/2>t.time%f?"AM":"PM"},toArray:function(n){return n.split(/(h{1,2}|H{1,2}|i|a|A|!.)/g)},toString:function(n,t){var r=this;return r.formats.toArray(n).map(function(n){return i.trigger(r.formats[n],r,[0,t])||n.replace(/^!/,"")}).join("")}};r.prototype.isTimeExact=function(n,r){var u=this;return i.isInteger(n)&&i.isInteger(r)||typeof n=="boolean"&&typeof r=="boolean"?n===r:(i.isDate(n)||t.isArray(n))&&(i.isDate(r)||t.isArray(r))?u.create(n).pick===u.create(r).pick:t.isPlainObject(n)&&t.isPlainObject(r)?u.isTimeExact(n.from,r.from)&&u.isTimeExact(n.to,r.to):!1};r.prototype.isTimeOverlap=function(n,r){var u=this;return i.isInteger(n)&&(i.isDate(r)||t.isArray(r))?n===u.create(r).hour:i.isInteger(r)&&(i.isDate(n)||t.isArray(n))?r===u.create(n).hour:t.isPlainObject(n)&&t.isPlainObject(r)?u.overlapRanges(n,r):!1};r.prototype.flipEnable=function(n){var t=this.item;t.enable=n||(t.enable==-1?1:-1)};r.prototype.deactivate=function(n,r){var f=this,u=f.item.disable.slice(0);return r=="flip"?f.flipEnable():r===!1?(f.flipEnable(1),u=[]):r===!0?(f.flipEnable(-1),u=[]):r.map(function(n){for(var e,r=0;r0?t:this.item.interval};r.prototype.nodes=function(n){var t=this,r=t.settings,u=t.item.select,f=t.item.highlight,e=t.item.view,o=t.item.disable;return i.node("ul",i.group({min:t.item.min.pick,max:t.item.max.pick,i:t.item.interval,node:"li",item:function(n){n=t.create(n);var s=n.pick,h=u&&u.pick==s,c=f&&f.pick==s,l=o&&t.disabled(n),a=i.trigger(t.formats.toString,t,[r.format,n]);return[i.trigger(t.formats.toString,t,[i.trigger(r.formatLabel,t,[n])||r.format,n]),function(n){return h&&n.push(r.klass.selected),c&&n.push(r.klass.highlighted),e&&e.pick==s&&n.push(r.klass.viewset),l&&n.push(r.klass.disabled),n.join(" ")}([r.klass.listItem]),"data-pick="+n.pick+" "+i.ariaAttr({role:"option",label:a,selected:h&&t.$node.val()===a?!0:null,activedescendant:c?!0:null,disabled:l?!0:null})]}})+i.node("li",i.node("button",r.clear,r.klass.buttonClear,"type=button data-clear=1"+(n?"":" disabled")+" "+i.ariaAttr({controls:t.$node[0].id})),"",i.ariaAttr({role:"presentation"})),r.klass.list,i.ariaAttr({role:"listbox",controls:t.$node[0].id}))};r.defaults=function(n){return{clear:"Clear",format:"h:i A",interval:30,closeOnSelect:!0,closeOnClear:!0,updateInput:!0,klass:{picker:n+" "+n+"--time",holder:n+"__holder",list:n+"__list",listItem:n+"__list-item",disabled:n+"__list-item--disabled",selected:n+"__list-item--selected",highlighted:n+"__list-item--highlighted",viewset:n+"__list-item--viewset",now:n+"__list-item--now",buttonClear:n+"__button--clear"}}}(n.klasses().picker);n.extend("pickatime",r)}); // Gets Json object using a given url. function GetJson(url) { var result; $.ajaxSetup({ async: false }); $.post(url, function (data) { result = data; }); $.ajaxSetup({ async: true }); return result; } function maxLength(field, maxChars) { if (field.value.length >= maxChars) { event.returnValue = false; return false; } } function maxLengthPaste(field, maxChars) { var copyText = field.value + window.clipboardData.getData("Text"); field.value = copyText.substr(0, maxChars); if ((copyText.length) > maxChars) { return false; } event.returnValue = true; } function appendFilesToInput(appendInput, mainFileInput) { const valid = validateMultiFileUpload(appendInput, true); if (!valid) { alert("The file you are trying to upload is not an allowed file type or has an invalid file name. These are the accepted characters: A-z 0-9 ~ ! ( ) - + = [ ] { } , . _"); appendInput.value = null; return; } const dt = new DataTransfer(); const originalFiles = Array.from(mainFileInput.files); const existingSet = new Set(originalFiles.map(({ name, size, lastModified }) => `${name}-${size}-${lastModified}`)); originalFiles.forEach(file => { dt.items.add(file); }) const addedFiles = Array.from(appendInput.files); addedFiles.forEach(file => { if (!existingSet.has(`${file.name}-${file.size}-${file.lastModified}`)) { dt.items.add(file); } }) mainFileInput.files = dt.files; mainFileInput.dispatchEvent(new Event("change")); } function fileAppender(mainFileInput) { const li = document.createElement("li"); const label = document.createElement("label"); label.innerHTML = 'Add Files' const appendInput = document.createElement("input"); appendInput.type = "file"; appendInput.multiple = true; appendInput.className = "visuallyhidden"; appendInput.addEventListener("change", e => { appendFilesToInput(appendInput, mainFileInput); }); label.appendChild(appendInput); const placeholder = document.createElement("span"); li.appendChild(placeholder); li.appendChild(label); return li; } function removeFileFromInput(input, idx) { const dt = new DataTransfer(); const files = Array.from(input.files); files.splice(idx, 1); files.forEach(file => { dt.items.add(file); }); input.files = dt.files; } function listItemFile(input, file, idx) { const li = document.createElement("li"); const fileNameSpan = document.createElement("span"); fileNameSpan.textContent = file.name; li.appendChild(fileNameSpan); const removeButton = document.createElement("button"); removeButton.title = `Remove ${file.name}`; removeButton.addEventListener("click", e => { e.preventDefault(); removeFileFromInput(input, idx); input.dispatchEvent(new Event("change")); }); removeButton.innerHTML = ''; const removeButtonSpan = document.createElement("span"); removeButtonSpan.textContent = `Remove ${file.name}`; removeButtonSpan.className = "visuallyhidden"; removeButton.appendChild(removeButtonSpan); li.appendChild(removeButton); return li; } function listFileInputFiles(fileInput) { if (fileInput.nextElementSibling?.className === "file-list") { fileInput.nextElementSibling.remove(); } const files = fileInput.files || []; const valid = files.length && validateMultiFileUpload(fileInput, true) if (!valid) { fileInput.value = null; return; } if (files.length > 1) { const ul = document.createElement("ul"); ul.className = "file-list"; for (let i = 0; i < files.length; i++) { const li = listItemFile(fileInput, files[i], i); ul.appendChild(li); } const fileAppenderLi = fileAppender(fileInput); ul.appendChild(fileAppenderLi); fileInput.after(ul); } } function initFileInputs() { if (!window.FeatureToggles.isActive("CMS.FormCenter.MultipleFileUploadEnhancement")) { return; } document.querySelectorAll(".FileUpload input[type='file']").forEach(fileInput => { listFileInputFiles(fileInput); fileInput.addEventListener("change", e => { listFileInputFiles(fileInput) }) }); } ; /// /// /// /// /// /// /// /// /// //////// ENUMERATIONS /////////// var FormCenterHomeJS = (function ($) { var self = this; // This value is set on the ItemDetailFE.ascx page, using a value from the // View Model. self.submissionURL = ''; return self; }(jQuery)); var FormCenterHomeScriptResources = GetJson("/FormCenter/Localization"); // Field formats. var FieldValidation = { Any: 0, Letters: 1, Numeric: 2, PhoneNumber: 3, PostalCode: 4, EmailAddress: 5, RegEx: 6, Currency: 7, Date: 8, Time: 9, DateTime: 10, DateSpan: 11, TimeSpan: 12, DateTimeSpan: 13 }; // Supported field types. var FieldTypes = { ShortAnswer: 1, LongAnswer: 2, Checkboxes: 3, RadioButtons: 4, Dropdown: 5, FileUpload: 6, ReplyEmail: 10, Password: 11, DateTime: 18, EPayment: 23 }; //////// GLOBALS //////////////// // Stores instantiated form validator/condition instances for the current form. var formValidators = null; var formConditions = null; // Use with form submissions. var redirectNewWindow = null; //////// SUPPORT METHODS ////////f // Shows extra information for a form detail. function moreInfo(id) { changeInfo(id, 'addClass', 'removeClass'); } // Hides extra information for a form detail. function lessInfo(id) { changeInfo(id, 'removeClass', 'addClass'); } // Internal. Hides or shows extra information. function changeInfo(id, lessFn, moreFn) { $([document.getElementById('spnLess' + id), document.getElementById('lnkMore' + id)])[lessFn]('hidden'); $(document.getElementById('spnMore' + id))[moreFn]('hidden'); } // Used to expand and collapse category sections. function expandCollaspseCategory(catID) { var $elem = $('#section' + catID); var $elemArrow = $('#span' + catID); var supportSlide = !isie7; // If we can find a better way to detect the incorrect behavior IE7 mode is exhibiting, go for it... if ($elem.is(':visible')) { $elemArrow.html('►'); if (supportSlide) $elem.slideUp(150); else $elem.hide(); } else { $elemArrow.html('▼'); if (supportSlide) $elem.slideDown(150); else $elem.show(); } } // Assigns bulk action checkbox group to jQuery expression. function assignBulkCheckGroup($children, $parent) { // Isolate children from parent in event of overlap ($children containing the $parent). // Vastly simplifies the logic in the event handlers by doing this. var $isolatedChildren = $children.filter( function (index) { return $parent.filter(this).length == 0; } ); // Cache current number of checked children. $isolatedChildren.lengthChecked = $isolatedChildren.filter(':checked').length; // Hook childen change. $isolatedChildren.change(function (event) { $isolatedChildren.lengthChecked += (this.checked ? 1 : -1); var allChildrenChecked = ($isolatedChildren.lengthChecked == $isolatedChildren.length); $parent.each(function () { this.checked = allChildrenChecked; }); }); // Hook parent change. $parent.change(function (event) { var parentChecked = this.checked; $isolatedChildren.lengthChecked = this.checked ? $isolatedChildren.length : 0; $isolatedChildren.each(function () { this.checked = parentChecked; }); }); } function initCommon() { // Hack: Internet Explorer 7 mode bizarre display bugs. $('.sidebar .search.noStyles').css('zoom', '1'); // Hook search category bulk checks. var $bulkCheck = $('#categoryFilter_0'); var $bulkGroup = $('.categoryList input[type="checkbox"]'); assignBulkCheckGroup($bulkGroup, $bulkCheck); // Get input jQuery refs. var $inputFCTerm = $('#inputFCTerm'); var $inputFCSearch = $('#inputFCSearch'); // Hook search button and textbox to capture enter key. $inputFCTerm.keydown(function (event) { // If user presses enter, submit for search. switch (event.which) { case 10: // LF case 13: // CR event.preventDefault(); $inputFCSearch.click(); break; } }); $inputFCSearch.click(function (event) { event.preventDefault(); // Build search querystring. var qs = {}; var formID = extractFormIDFromURL(location.href); var categoryID = extractCategoryIDFromURL(location.href); var searchTerm = $.trim(isNull($inputFCTerm.val(), '')); if (formID) qs.formID = formID; if (categoryID) qs.categoryID = categoryID; if (searchTerm != '') qs.term = searchTerm; if (!$bulkCheck[0].checked) { var values = []; $bulkGroup.filter(':checked').each(function () { values.push(this.value); }); if (values.length > 0) qs.categoryFilter = values.join(','); } // Set search URL and go. window.location = '/FormCenter/Search' + (new QueryStringBuilder(qs)).toString(); }); // Hook search category dropdown. var $catList = $('#categoryList'); var $catListToggle = $('a.mega'); $catListToggle.click(function (e) { e.preventDefault(); if ($catList.hasClass('open')) $catList.slideUp(300); else $catList.slideDown(300); $catListToggle.toggleClass('active'); $catList.toggleClass('open'); }); // Show print dialog if URL contains standard print query string. if (containsPrint(location.href)) window.print(); } // Initialization for search (Search.aspx view). function initSearch() { if (this.wasInit) return; this.wasInit = true; attachCategoryVisibilityTogglers(); initCommon(); } // Initialization for category/form list (Index.aspx view). function initCategoryList() { if (this.wasInit) return; this.wasInit = true; attachCategoryVisibilityTogglers(); initCommon(); } // Initialization for confirmation (Confirmation.aspx view). function initConfirmation() { if (this.wasInit) return; this.wasInit = true; initCommon(); } function initPostSubmissionSpam() { initCommon(); } // Causes current form to be submitted for printing. function printForm(saveData) { if (formValidate()) { //check for valid responses before creating print window var frm = document.aspnetForm; var $form = $(document.aspnetForm); var printPrevType = (getPrintPreviewType() == 1 ? 'Print' : 'Preview'); var formID = extractFormIDFromURL(location.href); $form.attr('target', 'PrintWindow'); // Change target/action to print data. frm.action = '/FormCenter/Print?formID=' + formID + '&' + printPrevType + '=YES&Save=' + (saveData ? 'True' : 'False'); var savedProgressID = $('#hdnSavedProgressID').val(); if (savedProgressID != null) { frm.action = frm.action + '&savedProgressID=' + savedProgressID; } submitForm($form, true, saveData, formID); } else { enableDisableSubmit(true); } } function submitFormHandler(e) { try { let json = JSON.parse(this.response); if (this.status !== 200 || json.Success !== true) { $('.submissionConfirmationMessage').html("Something went wrong with the submission. Please try again."); $('.submissionConfirmation').show(); enableDisableSubmit(true); return; } const responseUrl = this.responseURL && new URL(this.responseURL); const saveSubmission = responseUrl && responseUrl.searchParams.get('save') && responseUrl.searchParams.get('save').toLowerCase() === 'true'; const doPrint = responseUrl && responseUrl.searchParams.get('print') && responseUrl.searchParams.get('print').toLowerCase() === 'true'; const redirectAfterSubmissionSaved = json.Redirect && json.Redirect === true && saveSubmission === true; if (redirectAfterSubmissionSaved) { if (json.IsHttps === false) { json.Message = json.Message.replace("https://", "http://"); } location.href = json.Message; } else { if (saveSubmission === true) { $('.submissionConfirmationMessage').html(json.Message); typeof displayStep === "function" && displayStep(1); $('.submitForm').hide(); $('.submissionConfirmation').show(); } enableDisableSubmit(true); } if (doPrint === true) { window.open("/FormCenter/Print?formId=" + json.FormId.toString() + '&save=' + (saveSubmission ? 'True' : 'False')); } if (json.Success === true) { document.aspnetForm.reset(); if (typeof (grecaptcha) !== "undefined") { grecaptcha.reset(); } } !window.isRemoveSetHeights && typeof SetHeights === "function" && SetHeights(); } catch (ex) { console.log(ex); } } function submitForm($form, print, saveSubmission, formID) { var submittedViaWidget = $form.parents(".widgetBody").length > 0; serializeSpecialFields(); if (submittedViaWidget !== true) { var printWindow; if (print === true) { printWindow = window.open("", "PrintWindow"); // Deferred object at the window level, this becomes available on the opened window via window.opener // Whichever view gets rendered will resolve it and pass the appropriate status code. window.deferredStatus = $.Deferred(); } if (printWindow) { window.deferredStatus.done(function (status) { if (status === CP_DynamicForm_PrintSubmission.StatusCodes.Success) { if (saveSubmission && saveSubmission === true) { window.location = '/FormCenter/Confirmation?formID=' + formID; } } else { printWindow.close(); if (saveSubmission) { window.location = '/FormCenter/ErrorSubmittingForm?formID=' + formID; } } }); } $form.submit(); } else { var submissionUrl = FormCenterHomeJS.submissionURL + (saveSubmission ? '&save=True' : ""); submissionUrl = submissionUrl + (print ? '&print=True' : ''); var formData = new FormData($form[0]); var xhr = new XMLHttpRequest(); xhr.onload = submitFormHandler; xhr.onloadend = ajaxPostBackEnd; xhr.onerror = function() { console.log("A network error occurred with the transaction."); }; xhr.open("POST", submissionUrl); ajaxPostBackStart('Loading'); xhr.send(formData); } } function serializeSpecialFields() { submitCheckboxHandler(); submitRadioHandler(); submitDateTimeHandler(); } // Initialization for form item printing (Print.aspx view). function initFormPrint() { if (this.wasInit) return; this.wasInit = true; initCommon(); initValidationAndConditions(); registerFormPrintEvents(); } function initValidationAndConditions() { // Register validation. if (typeof getFormValidatorData !== 'undefined') { formValidators = FieldValidator.createMulti(getFormValidatorData()); } else { formValidators = []; } // Register conditions. if (getFormConditionData) { formConditions = FieldConditions.createMulti(getFormConditionData(), formValidators); } else { formConditions = FieldConditions.createMulti([], formValidators); } // Register condition runner and make initial condition check. formConditionsRunner = new FieldConditionsRunner(formConditions, $.noop, true, false); // TODO: Finish up, put debugCondRunnerLogResults for $.noop. formConditionsRunner.run(); } // Initialization for form item (Item.aspx view). function initForm() { if (this.wasInit) return; this.wasInit = true; initCommon(); initValidationAndConditions(); initDatePickers(); initTimePickers(); initFileInputs(); registerFormEvents(); // Hook up buttons (submit/cancel/etc). } function initDatePickers() { if ($('.telerikDatePicker').length > 0) { $('.telerikDatePicker').each(function () { if (typeof (cp) !== 'undefined') cp.datetimepicker && cp.datetimepicker.createDatePicker(this); }); } } function initTimePickers() { if ($('.formCenterTimePicker').length > 0) { $('.formCenterTimePicker').focusout(function () { var text = $(this).val().toLowerCase(); if (text != '' && (text.indexOf('am') < 0 && text.indexOf('pm') < 0)) { text = $(this).val().trim() + ' AM'; $(this).val(text); } }); } else { $('.telerikTimePicker').each(function () { if (typeof (cp) !== 'undefined') cp.datetimepicker && cp.datetimepicker.createTimePicker(this, { format: 'h:i A' }); }); } } // Registers event handlers for form. function registerFormPrintEvents() { $('#btnFormContinue').click(function (event) { event.preventDefault(); var frm = document.aspnetForm; var formID = extractFormIDFromURL(location.href); var $form = $(document.aspnetForm); // Change target/action to confirmation page. frm.action = '/FormCenter/Confirmation?formID=' + formID; $form.trigger("submit"); }); } // Registers event handlers for form. function registerFormEvents() { // Remove troublemakers (prevent the jQuery submit handler from ever firing, and not needed for this screen anyways). document.aspnetForm.removeAttribute('onsubmit'); document.aspnetForm.onsubmit = null; var $form = $(document.aspnetForm); // TODO: Plug this into other validation. var wantCopyAddr, $wantCopyAddrLI; var wantCopy = document.getElementById('wantCopy'); if (wantCopy) { wantCopyAddr = document.getElementById('wantCopyAddress'); $wantCopyAddrLI = $(wantCopyAddr.parentNode.parentNode); $(wantCopy).change(function (event) { if (this.checked) $wantCopyAddrLI.show(); else $wantCopyAddrLI.hide(); }); } /* #2378*/ $(document).keydown(function (event) { if ((event.keyCode == 13) && (event.target.id != 'btnFormSubmit') && (event.target.tagName != 'TEXTAREA') && (event.target.getAttribute('data-enable-enter-keypress') != 'true')) { event.preventDefault(); return false; } if (event.keyCode === 32 && event.target.tagName === 'A' && event.target.getAttribute('role') === 'button') { $(event.target).trigger('click'); event.preventDefault(); return false; } }); $form.submit(function () { // Run validation, stop data submission if necessary. if (!formValidate()) { enableDisableSubmit(true); return false; } if (isNull(redirectNewWindow, '').trimEnd() != '') window.open(redirectNewWindow); // Field types requiring special serialization code (radio/check/file). // The deserialization of dictionaries from forms in MVC 2 is somewhat sensitive. serializeSpecialFields(); return true; }); $('#btnFormSubmit').click(function (event) { event.preventDefault(); if (formValidate()) { processSubmit(handleSubmitClick); } }); $('#btnFormPrint').click(function (event) { event.preventDefault(); printForm(false); }); $('#btnFormSubmitPrint').click(function (event) { event.preventDefault(); if (formValidate()) { processSubmit(handleSubmitPrintClick); } }); $('#btnCalculateTotals').click(function (e) { e.preventDefault(); submitCheckboxHandler(); submitRadioHandler(); if (formValidate()) { var $form = $(document.aspnetForm); $.ajax({ url: '/FormCenter/Home/CalculateTotal?formID=' + $('#hdnFormID').val(), type: 'POST', data: $(document.aspnetForm).serializeArray(), success: function (response) { openCpModal({ title: FormCenterHomeScriptResources.CalculateTotals, className: 'modalCalculateTotal', isFrontEnd: window.location.href.indexOf('/Admin/FormCenter') == -1, htmlContent: response }); }, error: function (xhr, textStatus, exception) { alert('Error: ' + xhr.statusText + '\nStatus: ' + xhr.status); } }); } }); $('#btnProceedToCheckOut').click(function (e) { proceedToCheckOut(e); }); if ($('.submissionConfirmationOk').length > 0) { $('.submissionConfirmationOk').unbind('click').click(function () { $('.submitForm').show(); $('.submissionConfirmation').hide(); !window.isRemoveSetHeights && typeof SetHeights === "function" && SetHeights(); }) } } function onRecaptchaLoadCallback() { window.gRecaptchaClientId = grecaptcha.render('inline-recaptcha', { 'sitekey': document.querySelector('#inline-recaptcha').dataset.sitekey, 'badge': 'inline', 'size': 'invisible' }); } function processSubmit(callback) { const recaptcha = document.querySelector('.recaptcha'); if (!recaptcha) { callback(); return; } if (!window.FeatureToggles.isActive("CMS.FormCenter.RecaptchaV3Enabled")) { window.recaptchaCallback = callback; grecaptcha.execute(); return; } grecaptcha.ready(function() { grecaptcha.execute(window.gRecaptchaClientId, { action: 'submit' }).then(callback); }); } function enableDisableSubmit(enable) { if (enable) { if ($('#btnFormSubmitPrint').length > 0) { $('#btnFormSubmitPrint').removeClass('inactive'); $('#btnFormSubmitPrint').click(function (event) { handleSubmitPrintClick(); }); } if ($('#btnFormSubmit').length > 0) { $('#btnFormSubmit').removeClass('inactive'); $('#btnFormSubmit').click(function (event) { event.preventDefault(); if (formValidate()) { closeModalDialog('editItemBehavior'); processSubmit(handleSubmitClick); } }); } } else { if ($('#btnFormSubmitPrint').length > 0) { $('#btnFormSubmitPrint').addClass("inactive"); $('#btnFormSubmitPrint').unbind(); } if ($('#btnFormSubmit').length > 0) { $('#btnFormSubmit').addClass("inactive"); $('#btnFormSubmit').unbind(); } } } function handleSubmitClick() { enableDisableSubmit(false); var frm = document.aspnetForm; frm.action = FormCenterHomeJS.submissionURL; var $form = $(frm); var formID = extractFormIDFromURL(location.href); submitForm($form, false, true, formID); } function handleSubmitPrintClick() { enableDisableSubmit(false); printForm(true); } function proceedToCheckOut(e) { e.preventDefault(); serializeSpecialFields(); if (formValidate()) { var savedProgressID = $('#hdnSavedProgressID').val(); var submitUrl = '/FormCenter/Home/ProceedToCheckOut?formID=' + $('#hdnFormID').val(); if (savedProgressID != null) { submitUrl = submitUrl + '&savedProgressID=' + savedProgressID; } var $form = $(document.aspnetForm); $form.attr('action', submitUrl); $form.submit(); } } function getModalDialogObjects() { return { iframe: document.getElementById('liveEditDialog'), windowElement: $('.modalContainerCP')[0], behavior: $find('editItemBehavior'), titleElement: $('.modalTitle')[0] }; } function getBooleanValue(value) { switch (value.toLowerCase()) { case "true": case "yes": case "1": return true; case "false": case "no": case "0": case null: return false; default: return Boolean(string); } } // Validates current form. function formValidate() { var assignFocus = true; var ERROR_MSG = FormCenterHomeScriptResources.InvalidEmailAddressFormat2; var wantCopy = document.getElementById('wantCopy'); if (wantCopy) { wantCopyAddr = document.getElementById('wantCopyAddress'); $wantCopyAddrLI = $(wantCopyAddr.parentNode.parentNode); if ($wantCopyAddrLI.is(":visible") && wantCopyAddr.value != "") { if (!emailValidate(wantCopyAddr.value)) { errorShow(ERROR_MSG); return false; } } if (wantCopy.checked == false)//if the checkbox is not checked then empty the emailaddress textbox document.getElementById('wantCopyAddress').value = ""; } else { //if the checkbox is not checked then empty the emailaddress textbox var wantCopyAddress = document.getElementById('wantCopyAddress'); if (wantCopyAddress) document.getElementById('wantCopyAddress').value = ""; } if (typeof formValidators.keys !== 'undefined') { var liCurrent = $('li.current'); var step = "1"; if (liCurrent.length > 0) { step = liCurrent.attr('id').replace('liStep', ''); } var wizardStep = $('#wizard' + step); if (wizardStep.length > 0) { wizardStep = wizardStep[0]; } var checkForInappropriateWords = new Array(); for (var i = 0, len = formValidators.keys.length; i < len; i++) { var key = formValidators.keys[i]; if (wizardStep == null || wizardStep.length == 0 || (wizardStep != null && wizardStep.contains(formValidators[key].elemContainer))) { if (!formValidators[key].validate(assignFocus, checkForInappropriateWords)) assignFocus = false; } } if (validateInappropriateWords(checkForInappropriateWords)) { assignFocus = false; } } return assignFocus; } function validateInappropriateWords(checkForInappropriateWords) { var data = {}; var j = 0; var inappropriateWordsFound = false; for (j = 0; j < checkForInappropriateWords.length; j++) { data[checkForInappropriateWords[j].id.toString()] = checkForInappropriateWords[j].elemInput.value.trim(); } var results = HasInappropriateWordsMultiple(data); for (j = 0; j < checkForInappropriateWords.length; j++) { if (results[checkForInappropriateWords[j].id.toString()] == true) { checkForInappropriateWords[j].handleInappropriateWords(inappropriateWordsFound == false); inappropriateWordsFound = true; } } return inappropriateWordsFound; } // Displays error message if email validation failed function errorShow(message) { var elemContainer = $('.anonEmail'); elemContainer.addClass('error'); if (elemContainer.find('.explanation').length == 0) { var errorElemMsg = document.createElement('p'); errorElemMsg.className = 'explanation'; errorElemMsg.innerHTML = message; elemContainer.append(errorElemMsg); } } // Determines if URL contains print querystring. function containsPrint(url) { return url.search(/(&|\?)print\=yes(&.*|)$/i) > -1; } // Extracts CategoryID identifier from URL specified. function extractCategoryIDFromURL(url) { url = url.toLowerCase(); var indexOfForm = url.lastIndexOf("/formcenter/"); if (indexOfForm > -1) { //extract the categoryurl var formURL = url.substr(indexOfForm + 12); //check whether u have formid appended if (formURL.indexOf("/") > -1) formURL = formURL.substr(0, formURL.indexOf("/")); //check wheter the url has categoryName var indexOfHypen = formURL.lastIndexOf("-"); var categoryID = 0; if (indexOfHypen > -1) categoryID = formURL.substr(indexOfHypen + 1); else categoryID = formURL; return categoryID; } else return null; } // Extracts form identifier from URL specified. function extractFormIDFromURL(url) { return $('#hdnFormID').val(); //there is some query string appended if so remove those if (url.indexOf("/?") > -1) { url = url.substr(0, url.indexOf("/?")); } url = url.toLowerCase(); var indexOfForm = url.lastIndexOf("/formcenter/"); if (indexOfForm > -1) { //extract the url var formURL = url.substr(indexOfForm + 12); if (formURL.indexOf("/") > -1) { formURL = formURL.substr(formURL.indexOf("/") + 1); //check wheter the url has categoryName var indexOfHypen = formURL.lastIndexOf("-"); var formID = 0; if (indexOfHypen > -1) formID = formURL.substr(indexOfHypen + 1); else if (formURL == "") return null; else formID = formURL; return formID; } else return null; } else return null; } // Attaches expand/collapse handlers to section headers. function attachCategoryVisibilityTogglers() { $('#FormCenterContent .contentMain').click(function (event) { var target = event.target; if (/^lnkLess[0-9]*$/.test(target.id)) { // Form details should shrink. lessInfo(parseInt(target.id.substr(7), 10)); event.preventDefault(); } else if (/^lnkMore[0-9]*$/.test(target.id)) { // Form details should expand. moreInfo(parseInt(target.id.substr(7), 10)); event.preventDefault(); } else { // If the arrow glyph was clicked, treat it as if the header was clicked. if (target.nodeName == 'SPAN' && target.className == 'arrow') target = target.parentNode; // If the header was clicked. if (target.nodeName == 'H2') { var parent = target.parentNode; // If parent identifier matches expected pattern, get category ID and expand/collapse it. if (parent && /^cat[0-9]*$/.test(parent.id)) { var categoryID = parseInt(parent.id.substr(3), 10); expandCollaspseCategory(categoryID); // Prevent default code from executing. event.preventDefault(); } } } }); } // Called by form submittal to handle radio buttons for serialization. function submitRadioHandler() { var names = []; var values = {}; $checkBoxSelector = null; $webCheckBox = $('div.formWrap ol.cpForm input[type=radio]'); $mobileCheckBox = $('.mobileGuts input[type=radio]'); if ($webCheckBox.length != 0 && $mobileCheckBox.length == 0) $checkBoxSelector = $webCheckBox; if ($webCheckBox.length == 0 && $mobileCheckBox.length != 0) $checkBoxSelector = $mobileCheckBox; if ($checkBoxSelector != null) { // Get list of radio inputs and their values. $checkBoxSelector.each(function () { if (!names.contains(this.name)) { names.push(this.name); values[this.name] = ''; } if (this.checked) values[this.name] = this.value; }) } // Map collected data to hidden inputs submitted to server. for (var i = 0, len = names.length; i < len; i++) { var inputName = names[i]; var id = (inputName.match(/_/g) || []).length == 2 ? inputName.substring(inputName.indexOf('_') + 1) : inputName; document.getElementById(id).value = values[inputName]; } } // Called by form submittal to handle checkboxes for serialization. function submitCheckboxHandler() { var names = []; var values = {}; $checkBoxSelector = null; $webCheckBox = $('div.formWrap ol.cpForm input[type=checkbox]'); $mobileCheckBox = $('.mobileGuts input[type=checkbox]'); if ($webCheckBox.length != 0 && $mobileCheckBox.length == 0) $checkBoxSelector = $webCheckBox; if ($webCheckBox.length == 0 && $mobileCheckBox.length != 0) $checkBoxSelector = $mobileCheckBox; // Get list of checkbox inputs and their values. if ($checkBoxSelector != null) { $checkBoxSelector.each(function () { if (!names.contains(this.name)) { names.push(this.name); values[this.name] = []; } if (this.checked) { var val = this.value.replace(/\,/g, '_comma_'); if (val.trim() == '') val = '_empty_value_'; values[this.name].push(val); } }); } // Map collected data to hidden inputs submitted to server. for (var i = 0, len = names.length; i < len; i++) document.getElementById(names[i]).value = values[names[i]].join(','); } function submitDateTimeHandler() { var names = []; var values = []; var $datePickers, $timePickers; if ($('.formCenterDatePicker').length > 0) { $datePickers = $('.formCenterDatePicker'); $timePickers = $('.formCenterTimePicker'); } else { $datePickers = $('.telerikDatePicker'); $timePickers = $('.telerikTimePicker'); } $datePickers.each(function () { if (!names.contains(this.name)) { names.push(this.name); values[this.name] = [this.value]; } else { values[this.name].push(this.value); } }); $timePickers.each(function () { if (!names.contains(this.name)) { names.push(this.name); values[this.name] = ['', '', this.value]; } else { if (values[this.name].length == 1) { values[this.name].push(''); } values[this.name].push(this.value); } }); for (var i = 0, len = names.length; i < len; i++) document.getElementById(names[i]).value = values[names[i]].join(); } $(function () { $('#aspnetForm,form[name=aspnetForm]').attr('enctype', "multipart/form-data"); $('#aspnetForm,form[name=aspnetForm]').addClass('submitForm'); }); ; /// /// /// /// /// /// // Overridden on a per-form basis. Retrieves validator information for submission validation. //function getFormValidatorData() { // return []; //} var FormCenterHomeScriptResources = GetJson("/FormCenter/Localization"); var originalTextColorRadio; var originalTextColorCheckBox; $.getScript("/Assets/Scripts/InappropriateWords.js"); // Used to properly localize strings. String.prototype.format = function () { var args = arguments; return this.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match ; }); }; // Performs validation for a form field. function FieldValidator(elemInput, id, fieldType, isInternal, isRequired, formatValidation, formatValidationCustom, minAnswer, maxAnswer, maxLength) { var self = this; this.elemInputIsArray = $.isArray(elemInput); if (this.elemInputIsArray) { for (var i = 0, len = elemInput.length; i < len; i++) { if (typeof (elemInput[i]) == "string") elemInput[i] = document.getElementById(elemInput[i]); } if (elemInput.length > 0 && elemInput[0]) { this.elemContainer = elemInput[0].parentNode.parentNode.parentNode.parentNode; this.elemInput = elemInput; } } else { if (typeof (elemInput) == "string") elemInput = document.getElementById(elemInput); if (elemInput) { if (fieldType === FieldTypes.DatePicker) this.elemContainer = elemInput.parentNode.parentNode.parentNode.parentNode; else this.elemContainer = elemInput.parentNode.parentNode; this.elemInput = elemInput; } } this.enabled = true; this.$elemContainer = $(this.elemContainer); this.fieldType = fieldType; if (this.fieldType === FieldTypes.FileUpload) { //When validating , we need to update the elemInput reference since it is created a new one when failing inside validateFileUpload method - LC var validateInputFileUpload = function () { var $this = $(this); if (!validateMultiFileUpload($this[0], true)) { alert("The file you are trying to upload is not an allowed file type or has an invalid file name. These are the accepted characters: A-z 0-9 ~ ! ( ) - + = [ ] { } , . _"); self.elemInput.value = null; self.elemInput.focus(); } }; $(this.elemInput).attr("change", "").removeAttr("onChange").unbind("change").change(validateInputFileUpload); } this.id = id; this.isInternal = isInternal; this.isRequired = isRequired; this.formatValidation = formatValidation; this.formatValidationCustom = formatValidationCustom; this.elemErrorNote = null; this.minAnswer = minAnswer; this.maxAnswer = maxAnswer; this.maxLength = maxLength; this.focusElementIndex = 0; this.alreadySetFocus = false; var isRequiredInfoLableDisplayed = false; if (this.isRequired && !isRequiredInfoLableDisplayed) { $('#liRequiredFieldInfo').show(); isRequiredInfoLableDisplayed = true; } } // Static. Creates a single validation object from an options object. FieldValidator.createSingle = function (options) { return new FieldValidator( options.elemInput, options.id, options.fieldType, options.isInternal, options.isRequired, options.formatValidation, options.formatValidationCustom, options.minAnswer, options.maxAnswer, options.maxLength); }; // Static. Creates array of validation objects from array of option objects. FieldValidator.createMulti = function (optionsArray) { var key = null; var ret = { keys: [], add: function (validator) { var key = validator.id; this[key] = validator; this.keys.push(key); } }; for (var i = 0, len = optionsArray.length; i < len; i++) ret.add(FieldValidator.createSingle(optionsArray[i])); return ret; }; // Internal. Used by validation() to ensure the input does not exceed the max length. FieldValidator.prototype.validateMaxLength = function (errorMsg) { var ERROR_MSG = FormCenterHomeScriptResources.MaxLengthErrorMessage.format(this.maxLength); if (this.maxLength == null) return true; var cleanValue = this.elemInput.value.trim(); if (cleanValue != null && cleanValue.length > this.maxLength) { errorMsg.push(ERROR_MSG); return false; } return true; }; // Internal. Used by validate() to ensure user-enterable fields are phone numbers (of NANP format). FieldValidator.prototype.validatePhone = function (errorMsg) { var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidPhoneNumberFormat); var origLen = errorMsg.length; switch (this.fieldType) { case FieldTypes.ShortAnswer: case FieldTypes.LongAnswer: case FieldTypes.Password: var cleanValue = this.elemInput.value.trim(); if (cleanValue != '' && !phoneValidate(cleanValue, intCountryCode)) errorMsg.push(ERROR_MSG); break; } // Return false if validation check failed (number of errors changed). return origLen == errorMsg.length; } // Internal. Used by validate() to ensure user-enterable fields are postal codes. FieldValidator.prototype.validatePostal = function (errorMsg) { var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidPostalCode); var origLen = errorMsg.length; switch (this.fieldType) { case FieldTypes.ShortAnswer: case FieldTypes.LongAnswer: case FieldTypes.Password: var cleanValue = this.elemInput.value.trim(); if (cleanValue != '' && !isZipCode(cleanValue, intCountryCode)) errorMsg.push(ERROR_MSG); break; } // Return false if validation check failed (number of errors changed). return origLen == errorMsg.length; } // Internal. Used by validate() to ensure user-enterable fields are email addresses. FieldValidator.prototype.validateEmail = function (errorMsg) { var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidEmailAddressFormat2); var origLen = errorMsg.length; switch (this.fieldType) { case FieldTypes.ShortAnswer: case FieldTypes.LongAnswer: case FieldTypes.Password: case FieldTypes.ReplyEmail: var cleanValue = this.elemInput.value.trim(); if (cleanValue != '' && !emailValidate(cleanValue)) errorMsg.push(ERROR_MSG); break; } // Return false if validation check failed (number of errors changed). return origLen == errorMsg.length; } function getNumericThousandsSeparator() { var dummy = new Number(11111111); var thousandSep = dummy.toLocaleString().replace(/1/g, ''); return (thousandSep.length > 0 ? thousandSep.charAt(0) : ','); } // Internal. Used by validate() to ensure user-enterable fields match custom expression. FieldValidator.prototype.validateCustom = function (expr, errorMsg) { var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidGenericField); var origLen = errorMsg.length; var customRegExp = new RegExp(expr); switch (this.fieldType) { case FieldTypes.ShortAnswer: case FieldTypes.LongAnswer: case FieldTypes.Password: var cleanValue = this.elemInput.value.trim(); if (cleanValue != '' && (!customRegExp.test(cleanValue))) errorMsg.push(ERROR_MSG); break; } // Return false if validation check failed (number of errors changed). return origLen == errorMsg.length; } // Internal. Used by validate() to ensure user-enterable fields are letters only. FieldValidator.prototype.validateLetters = function (errorMsg) { var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.LettersOnlyField); var origLen = errorMsg.length; var letterRegExp = /^[a-zA-Z ]+$/; switch (this.fieldType) { case FieldTypes.ShortAnswer: case FieldTypes.LongAnswer: case FieldTypes.Password: var cleanValue = this.elemInput.value.trim(); if (cleanValue != '' && (!letterRegExp.test(cleanValue))) errorMsg.push(ERROR_MSG); break; } // Return false if validation check failed (number of errors changed). return origLen == errorMsg.length; } // Internal. Used by validate() to ensure user-enterable fields are numeric (numbers, decimal separators, and group separators allowed). FieldValidator.prototype.validateNumeric = function (errorMsg) { var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.NumericOnlyField); var origLen = errorMsg.length; var numericRegExp = new RegExp("^(([0-9]+?[0-9%G]+?[0-9](|%D[0-9]+))|([0-9]*(|%D[0-9]+)))$" .replace(/%G/g, RegExp.metaEscape(getNumericThousandsSeparator())) .replace(/%D/g, RegExp.metaEscape(getNumericDecimalSeparator()))); switch (this.fieldType) { case FieldTypes.ShortAnswer: case FieldTypes.LongAnswer: case FieldTypes.Password: var cleanValue = this.elemInput.value.trim(); if (cleanValue != '' && (!numericRegExp.test(cleanValue))) errorMsg.push(ERROR_MSG); break; } // Return false if validation check failed (number of errors changed). return origLen == errorMsg.length; } FieldValidator.prototype.validateCurrency = function (errorMsg) { var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.CurrencyOnlyField); var origLen = errorMsg.length; var value = this.elemInput.value.trim(); if (!this.isValidMoney(value)) { errorMsg.push(ERROR_MSG);; } // Return false if validation check failed (nubmer of errors changed). return origLen == errorMsg.length; } FieldValidator.prototype.isValidMoney = function (value) { if (value && value != '') return /^\$?\s*\d+(,\d{3})*(\.\d{1,2})?$/.test(value); else return true; }; //#region Date Validation FieldValidator.prototype.validateDate = function (errorMsg) { var origLen = errorMsg.length; var date = $(this.elemInput[0]).val(); var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidDate); if (!this.isValidDate(date, this.isRequired)) { errorMsg.push(ERROR_MSG); } // Return false if validation check failed (nubmer of errors changed). return origLen == errorMsg.length; } FieldValidator.prototype.validateTime = function (errorMsg) { var origLen = errorMsg.length; var time = $(this.elemInput[0]).val(); var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidTime); if (!this.isValidTime(time, this.isRequired)) { errorMsg.push(ERROR_MSG); } // Return false if validation check failed (nubmer of errors changed). return origLen == errorMsg.length; } FieldValidator.prototype.validateDateTime = function (errorMsg) { var origLen = errorMsg.length; var date = $(this.elemInput[0]).val(); var time = $(this.elemInput[1]).val(); var validDate = this.isValidDate(date, this.isRequired); var validTime = this.isValidTime(time, this.isRequired); var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.InvalidDateTime); if (!validDate && !validTime) { if (!this.alreadySetFocus) { this.focusElementIndex = 0; this.alreadySetFocus = true; } errorMsg.push(ERROR_MSG); } else if (!validDate) { if (!this.alreadySetFocus) { this.focusElementIndex = 0; this.alreadySetFocus = true; } errorMsg.push(ERROR_MSG); } else if (!validTime) { if (!this.alreadySetFocus) { this.focusElementIndex = 1; this.alreadySetFocus = true; } errorMsg.push(ERROR_MSG); } // Return false if validation check failed (nubmer of errors changed). return origLen == errorMsg.length; } FieldValidator.prototype.validateDateSpan = function (errorMsg) { var origLen = errorMsg.length; var date = $(this.elemInput[0]).val(); var dateSpan = $(this.elemInput[1]).val(); if (!this.isValidDate(date, this.isRequired)) { if (!this.alreadySetFocus) { this.focusElementIndex = 0; this.alreadySetFocus = true; } errorMsg.push(FormCenterHomeScriptResources.InvalidStartDate); } if (!this.isValidDate(dateSpan, this.isRequired)) { if (!this.alreadySetFocus) { this.focusElementIndex = 1; this.alreadySetFocus = true; } errorMsg.push(FormCenterHomeScriptResources.InvalidEndDate); } if (!this.isValidDateRange(date, dateSpan, this.isRequired, this.isRequired)) { if (!this.alreadySetFocus) { this.focusElementIndex = 0; this.alreadySetFocus = true; } errorMsg.push(FormCenterHomeScriptResources.InvalidDateSpan); } // Return false if validation check failed (nubmer of errors changed). return origLen == errorMsg.length; } FieldValidator.prototype.validateTimeSpan = function (errorMsg) { var origLen = errorMsg.length; var time = $(this.elemInput[0]).val(); var timeSpan = $(this.elemInput[1]).val(); if (!this.isValidTime(time, this.isRequired)) { if (!this.alreadySetFocus) { this.focusElementIndex = 0; this.alreadySetFocus = true; } errorMsg.push(FormCenterHomeScriptResources.InvalidStartTime); } if (!this.isValidTime(timeSpan, this.isRequired)) { if (!this.alreadySetFocus) { this.focusElementIndex = 1; this.alreadySetFocus = true; } errorMsg.push(FormCenterHomeScriptResources.InvalidEndTime); } if (!this.isValidTimeRange(time, timeSpan, this.isRequired, this.isRequired)) { if (!this.alreadySetFocus) { this.focusElementIndex = 0; this.alreadySetFocus = true; } errorMsg.push(FormCenterHomeScriptResources.InvalidTimeSpan); } // Return false if validation check failed (nubmer of errors changed). return origLen == errorMsg.length; } FieldValidator.prototype.validateDateTimeSpan = function (errorMsg) { var origLen = errorMsg.length; var date = $(this.elemInput[0]).val(); var dateSpan = $(this.elemInput[1]).val(); var time = $(this.elemInput[2]).val(); var timeSpan = $(this.elemInput[3]).val(); var validDate = this.isValidDate(date, this.isRequired); var validTime = this.isValidTime(time, this.isRequired); if (!validDate && !validTime) { if (!this.alreadySetFocus) { this.focusElementIndex = 0; this.alreadySetFocus = true; } errorMsg.push(FormCenterHomeScriptResources.InvalidStartDateTime); } else if (!validDate) { if (!this.alreadySetFocus) { this.focusElementIndex = 0; this.alreadySetFocus = true; } errorMsg.push(FormCenterHomeScriptResources.InvalidStartDate); } else if (!validTime) { if (!this.alreadySetFocus) { this.focusElementIndex = 2; this.alreadySetFocus = true; } errorMsg.push(FormCenterHomeScriptResources.InvalidStartTime); } var validSpanDate = this.isValidDate(dateSpan, this.isRequired); var validSpanTime = this.isValidTime(timeSpan, this.isRequired); if (!validSpanDate && !validSpanTime) { if (!this.alreadySetFocus) { this.focusElementIndex = 1; this.alreadySetFocus = true; } errorMsg.push(FormCenterHomeScriptResources.InvalidEndDateTime); } else if (!validSpanDate) { if (!this.alreadySetFocus) { this.focusElementIndex = 1; this.alreadySetFocus = true; } errorMsg.push(FormCenterHomeScriptResources.InvalidEndDate); } else if (!validSpanTime) { if (!this.alreadySetFocus) { this.focusElementIndex = 3; this.alreadySetFocus = true; } errorMsg.push(FormCenterHomeScriptResources.InvalidEndTime); } var isDayBeforeMonth = getDateFormat().toLocaleLowerCase() == "dd/mm/yyyy" ? true : false; if (!this.isValidDateTimeRange(getDateFromInput(this.elemInput[0], isDayBeforeMonth), getDateFromInput(this.elemInput[1], isDayBeforeMonth), this.isRequired, this.isRequired, time, timeSpan, this.isRequired, this.isRequired)) { if (!this.alreadySetFocus) { this.focusElementIndex = 1; this.alreadySetFocus = true; } errorMsg.push(FormCenterHomeScriptResources.InvalidDateTimeSpan); } // Return false if validation check failed (nubmer of errors changed). return origLen == errorMsg.length; } FieldValidator.prototype.isValidDate = function (date, dateRequired) { var objDate = new dateValidator(); return objDate.dateValidateNew(date, dateRequired, ''); } FieldValidator.prototype.isValidTime = function (time, timeRequired) { var objDate = new dateValidator(); var amIndex = time.toLowerCase().indexOf('am'); var pmIndex = time.toLowerCase().indexOf('pm'); if (amIndex != -1) { time = time.substring(0, amIndex).replace(" ", ""); if (time.trim() === "") { return false; } } else if (pmIndex != -1) { time = time.substring(0, pmIndex).replace(" ", ""); if (time.trim() === "") { return false; } } return objDate.timeValidate(time, timeRequired, ''); } FieldValidator.prototype.isValidTimeRange = function (startTime, endTime, startTimeRequired, endTimeRequired) { var objDate = new dateValidator(); objDate.ysnAllowTimeOnly = true; objDate.dtiStartTime = this.stripAMPM(startTime); objDate.ysnStartTimeRequired = startTimeRequired; objDate.dtiEndTime = this.stripAMPM(endTime); objDate.ysnEndTimeRequired = endTimeRequired; objDate.ysnDatesAreEqual = true; objDate.strStartAMPM = this.getAMPMString(startTime); objDate.strEndAMPM = this.getAMPMString(endTime); objDate.timesAlreadyValidated = true; return objDate.timeOrderValidate(); } FieldValidator.prototype.isValidDateRange = function (startDate, endDate, startDateRequired, endDateRequired) { var objDate = new dateValidator(); objDate.setStartDate(checkDateFormatReturnUSString(startDate, false)); objDate.setEndDate(checkDateFormatReturnUSString(endDate, false)); objDate.setStartDateRequired(startDateRequired); objDate.setEndDateRequired(endDateRequired); objDate.datesAlreadyValidated = true; return objDate.dateOrderValidateNew(); } FieldValidator.prototype.isValidDateTimeRange = function (startDate, endDate, startDateRequired, endDateRequired, startTime, endTime, startTimeRequired, endTimeRequired) { var objDate = new dateValidator(); objDate.setStartDate(checkDateFormatReturnUSString(startDate, false)); objDate.setEndDate(checkDateFormatReturnUSString(endDate, false)); objDate.setStartDateRequired(startDateRequired); objDate.setEndDateRequired(endDateRequired); objDate.ysnAllowEqualDates = true; objDate.datesAlreadyValidated = true; var validDateOrder = objDate.dateOrderValidateNew(); objDate.strStartAMPM = this.getAMPMString(startTime); objDate.strEndAMPM = this.getAMPMString(endTime); objDate.ysnAllowTimeOnly = true; objDate.ysnAllowEqualTimes = !objDate.ysnDatesAreEqual; objDate.dtiStartTime = this.stripAMPM(startTime); objDate.ysnStartTimeRequired = startTimeRequired; objDate.dtiEndTime = this.stripAMPM(endTime); objDate.ysnEndTimeRequired = endTimeRequired; objDate.timesAlreadyValidated = true; var validTimeOrder = objDate.timeOrderValidate(); return validDateOrder && validTimeOrder; } FieldValidator.prototype.stripAMPM = function (time) { var amIndex = time.toLowerCase().indexOf('am'); var pmIndex = time.toLowerCase().indexOf('pm'); if (amIndex != -1) { time = time.substring(0, amIndex).replace(" ", ""); } else if (pmIndex != -1) { time = time.substring(0, pmIndex).replace(" ", ""); } return time; } FieldValidator.prototype.getAMPMString = function (time) { var amIndex = time.toLowerCase().indexOf('am'); var pmIndex = time.toLowerCase().indexOf('pm'); var AMPM = ''; if (amIndex != -1) { AMPM = time.substring(amIndex).replace(" ", ""); } else if (pmIndex != -1) { AMPM = time.substring(pmIndex).replace(" ", ""); } return AMPM; } //#endregion Date Validation //checkbox validation done for min and max answer selcted FieldValidator.prototype.checkBoxValidation = function (errorMsg) { var origLen = errorMsg.length; if (this.fieldType == FieldTypes.Checkboxes && ((this.minAnswer != "" && this.minAnswer != undefined) || (this.maxAnswer != "" && this.maxAnswer != undefined))) { var i = 0, len = this.elemInput.length; var checkedCount = 0; for (; i < len; i++) { if (this.elemInput[i].checked) checkedCount++; } //validation for checkbox min max fields if (this.minAnswer != "" && this.minAnswer != undefined) { if (checkedCount < parseInt(this.minAnswer, 10)) // the message is not localized on purpose as this has text and dynamic value errorMsg.push("This field must have at least " + parseInt(this.minAnswer, 10) + " options selected"); } if (origLen == errorMsg.length && this.maxAnswer != "" && this.maxAnswer != undefined) { if (checkedCount > parseInt(this.maxAnswer, 10)) // the message is not localized on purpose as this has text and dynamic value errorMsg.push("This field can have at most " + parseInt(this.maxAnswer, 10) + " options selected"); } } // Return false if validation check failed (number of errors changed). return origLen == errorMsg.length; }; // Internal. Used by validate() to ensure required fields are set. FieldValidator.prototype.validateRequired = function (errorMsg) { var ERROR_MSG = this.getErrorMessage(FormCenterHomeScriptResources.RequiredField);//FormCenterHomeScriptResources.RequiredField; var origLen = errorMsg.length; switch (this.fieldType) { case FieldTypes.ShortAnswer: case FieldTypes.LongAnswer: case FieldTypes.ReplyEmail: case FieldTypes.Password: case FieldTypes.FileUpload: case FieldTypes.CodeSnippet: case FieldTypes.InputLink: case FieldTypes.DatePicker: case FieldTypes.InputImage: if (this.elemInput != 'undefined' && this.elemInput.value != undefined) { if (this.elemInput.value.trim() == '') errorMsg.push(ERROR_MSG); } break; case FieldTypes.Checkboxes: case FieldTypes.RadioButtons: var i = 0, len = this.elemInput.length; for (; i < len; i++) { if (this.elemInput[i].checked) break; } if (i == len) errorMsg.push(ERROR_MSG); break; case FieldTypes.Dropdown: case FieldTypes.FormLink: if (this.elemInput.selectedIndex <= 0) errorMsg.push(ERROR_MSG); break; case FieldTypes.DateTime: var i = 0, len = this.elemInput.length; for (; i < len; i++) { if (this.elemInput[i].value.trim() == '') { errorMsg.push(ERROR_MSG); this.focusElementIndex = i; break; } } } // Return false if validation check failed (number of errors changed). return origLen == errorMsg.length; }; // Performs validation for field and updates format if necessary. FieldValidator.prototype.validate = function (assignFocusOnFailure, checkForInappropriateWords) { var errorMsg = []; // Element not present OR disabled, pass (skipped). if (this.elemInput == null || !this.enabled) return true; if (!this.isRequired || (this.isRequired && this.validateRequired(errorMsg))) { //checkbox validation done for min and max answer selected if (this.checkBoxValidation(errorMsg)) { switch (this.formatValidation) { case FieldValidation.Letters: this.validateLetters(errorMsg); break; case FieldValidation.Numeric: this.validateNumeric(errorMsg); break; case FieldValidation.Currency: this.validateCurrency(errorMsg); break; case FieldValidation.PhoneNumber: this.validatePhone(errorMsg); break; case FieldValidation.PostalCode: this.validatePostal(errorMsg); break; case FieldValidation.EmailAddress: this.validateEmail(errorMsg); break; case FieldValidation.RegEx: this.validateCustom(this.formatValidationCustom, errorMsg); break; case FieldValidation.Date: this.validateDate(errorMsg); break; case FieldValidation.Time: this.validateTime(errorMsg); break; case FieldValidation.DateTime: this.validateDateTime(errorMsg); break; case FieldValidation.DateSpan: this.validateDateSpan(errorMsg); break; case FieldValidation.TimeSpan: this.validateTimeSpan(errorMsg); break; case FieldValidation.DateTimeSpan: this.validateDateTimeSpan(errorMsg); break; } } } if (this.fieldType === FieldTypes.DatePicker && this.elemInput.value.trim() != '') { //validate date picker value (based on telerik mvc datePicker) var datepicker = $(this.elemInput).data("tDatePicker"); if ($(this.elemInput).hasClass('t-state-error') || datepicker.parse(this.elemInput.value.trim()) == null) errorMsg.push("Invalid date format"); } if (this.fieldType === FieldTypes.ShortAnswer || this.fieldType === FieldTypes.LongAnswer) { var validator = this; if (checkForInappropriateWords != null && typeof (checkForInappropriateWords.push) == 'function') { checkForInappropriateWords.push(validator); } else { if (HasInappropriateWords(this.elemInput.value.trim())) { $(this.elemInput).addClass('t-state-error'); errorMsg.push(FormCenterHomeScriptResources.InappropriateWords); } } } if (FeatureToggles.isActive("CMS.FormCenter.EnableServerSideValidationsForSubmissions") && this.fieldType === FieldTypes.FileUpload && this.elemInput.value.trim() != '') { if (Math.round((this.elemInput.files[0].size / 1024)) > 20480) errorMsg.push("Files cannot be larger than 20 MB."); } this.validateMaxLength(errorMsg); if (errorMsg.length > 0 && $(this.elemInput).is(":visible")) { this.errorShow(errorMsg); if (assignFocusOnFailure) { this.focusErrorElement(); } return false; } else { this.errorClear(); return true; } }; // Performs validation for admin edit internal only fields and updates format if necessary. FieldValidator.prototype.validateInternal = function (assignFocusOnFailure, checkForInappropriateWords) { if (this.isInternal) { var errorMsg = []; // Element not present OR disabled, pass (skipped). if (this.elemInput == null || !this.enabled) return true; if (!this.isRequired || (this.isRequired && this.validateRequired(errorMsg))) { //checkbox validation done for min and max answer selected if (this.checkBoxValidation(errorMsg)) { switch (this.formatValidation) { case FieldValidation.Letters: this.validateLetters(errorMsg); break; case FieldValidation.Numeric: this.validateNumeric(errorMsg); break; case FieldValidation.Currency: this.validateCurrency(errorMsg); break; case FieldValidation.PhoneNumber: this.validatePhone(errorMsg); break; case FieldValidation.PostalCode: this.validatePostal(errorMsg); break; case FieldValidation.EmailAddress: this.validateEmail(errorMsg); break; case FieldValidation.RegEx: this.validateCustom(this.formatValidationCustom, errorMsg); break; case FieldValidation.Date: this.validateDate(errorMsg); break; case FieldValidation.Time: this.validateTime(errorMsg); break; case FieldValidation.DateTime: this.validateDateTime(errorMsg); break; case FieldValidation.DateSpan: this.validateDateSpan(errorMsg); break; case FieldValidation.TimeSpan: this.validateTimeSpan(errorMsg); break; case FieldValidation.DateTimeSpan: this.validateDateTimeSpan(errorMsg); break; } } } if (this.fieldType === FieldTypes.DatePicker && this.elemInput.value.trim() != '') { //validate date picker value (based on telerik mvc datePicker) var datepicker = $(this.elemInput).data("tDatePicker"); if ($(this.elemInput).hasClass('t-state-error') || datepicker.parse(this.elemInput.value.trim()) == null) errorMsg.push("Invalid date format"); } if (this.fieldType === FieldTypes.ShortAnswer || this.fieldType === FieldTypes.LongAnswer) { var validator = this; if (checkForInappropriateWords != null && typeof (checkForInappropriateWords.push) == 'function') { checkForInappropriateWords.push(validator); } else { if (HasInappropriateWords(this.elemInput.value.trim())) { $(this.elemInput).addClass('t-state-error'); errorMsg.push(FormCenterHomeScriptResources.InappropriateWords); } } } this.validateMaxLength(errorMsg); if (errorMsg.length > 0 && $(this.elemInput).is(":visible")) { this.errorShow(errorMsg); if (assignFocusOnFailure) { this.focusErrorElement(); } return false; } else { this.errorClear(); return true; } } else { return true; } }; FieldValidator.prototype.handleInappropriateWords = function (focus) { var errorMsg = []; $(this.elemInput).addClass('t-state-error'); errorMsg.push(FormCenterHomeScriptResources.InappropriateWords); this.errorShow(errorMsg); if (focus) { this.focusErrorElement(); } }; FieldValidator.prototype.focusErrorElement = function () { var scrollIntoView = function (element) { var offset = $(element).offset(); var elementTop = offset.top; // Add a 50px padding to the top of the element, just for aesthetics $(document).scrollTop(elementTop - 150); }; if (this.elemInputIsArray) { if ($(this.elemInput).is(":visible")) { if (this.elemInput.length > this.focusElementIndex) { this.elemInput[this.focusElementIndex].focus(); } else { this.elemInput[0].focus(); } scrollIntoView(this.elemInput[0]); } this.alreadySetFocus = false; this.focusElementIndex = 0; } else { if ($(this.elemInput).is(":visible")) { this.elemInput.focus(); scrollIntoView(this.elemInput); } } } // Shows error message for field. Called by validate() if field value fails validation. FieldValidator.prototype.errorShow = function (messages) { if (this.elemErrorNote) this.errorClear(); // Element not defined, cannot perform operation. if (this.elemInput == null) return; this.$elemContainer.addClass('error'); this.elemErrorNote = []; $('ol li.error div').addClass('selfClear'); if (this.elemInput != undefined) { if (this.elemInput["0"] != undefined) { //Check current element is radio if (this.elemInput["0"].type == "radio" & !(this.$elemContainer.closest('li').hasClass('error'))) { this.$elemContainer.closest('li').addClass('error'); originalTextColorRadio = this.$elemContainer.closest("fieldset")[0].childNodes[0].style.color; this.$elemContainer.closest("fieldset")[0].childNodes[0].style.color = "#800000"; } else //Check current element is checkbox if (this.elemInput["0"].type == "checkbox" & !(this.$elemContainer.closest('li').hasClass('error'))) { this.$elemContainer.closest('li').addClass('error'); originalTextColorCheckBox = this.$elemContainer.closest("fieldset")[0].childNodes[0].style.color; this.$elemContainer.closest("fieldset")[0].childNodes[0].style.color = "#800000"; } } } for (var i = 0, len = messages.length; i < len; i++) { var errorElemMsg = document.createElement('p'); errorElemMsg.className = 'explanation'; var multiSelectable = this.elemInput[0] !== undefined && this.elemInput.tagName !== "SELECT"; if (multiSelectable) { errorElemMsg.id = 'errorMsg' + this.elemInput[0].id; } else { errorElemMsg.id = 'errorMsg' + this.elemInput.id; } errorElemMsg.innerHTML = messages[i]; if (this.elemInput != undefined) { if (this.elemInput["0"] != undefined) { if (this.elemInput["0"].type == "radio" || this.elemInput["0"].type == "checkbox") { errorElemMsg.style.backgroundColor = "#940E0D" errorElemMsg.style.color = "#FFFFFF"; errorElemMsg.style.fontWeight = "bold" errorElemMsg.style.lineHeight = "1.2" errorElemMsg.style.width = "94%" errorElemMsg.style.margin = ".5em 0 0" errorElemMsg.style.padding = ".5em" } } } this.elemContainer.appendChild(errorElemMsg); this.elemErrorNote.push(errorElemMsg); } !window.isRemoveSetHeights && typeof SetHeights === "function" && SetHeights(); }; // Clears error message for field. Called by validate() if field value passes validation. FieldValidator.prototype.errorClear = function () { if (this.elemInput != undefined) { if (this.elemInput["0"] != undefined) { var i = 0, len = this.elemInput.length; for (; i < len; i++) { if (this.elemInput[i].checked) break; } if (i != len) { if (this.elemInput["0"].type == "radio") { this.$elemContainer.closest('li').removeClass('error'); this.$elemContainer.closest("fieldset")[0].childNodes[0].style.color = originalTextColorRadio; } else if (this.elemInput["0"].type == "checkbox") { this.$elemContainer.closest('li').removeClass('error'); this.$elemContainer.closest("fieldset")[0].childNodes[0].style.color = originalTextColorCheckBox; } } } } if (this.elemErrorNote == null) return; else if (this.elemInput == null) return; if (this.elemErrorNote.length > 0) { var errorParent = this.elemErrorNote[0].parentNode; for (var i = 0, len = this.elemErrorNote.length; i < len; i++) errorParent.removeChild(this.elemErrorNote[i]); this.elemErrorNote = null; } this.$elemContainer.removeClass('error'); !window.isRemoveSetHeights && typeof SetHeights === "function" && SetHeights(); }; FieldValidator.prototype.getErrorMessage = function (errorTemplateMsg) { var $fieldElemContainer = $(this.elemContainer); if (!$fieldElemContainer.hasClass('formFieldContainer')) { $fieldElemContainer = $fieldElemContainer.parents('.formFieldContainer'); } var $fieldLabelElem = $fieldElemContainer.find('.labelForFieldElement'); var fieldLabel = ''; if ($fieldLabelElem.length > 0) { fieldLabel = $fieldLabelElem.text().replace('*', ''); } else { $fieldLabelElem = $fieldElemContainer.find('legend'); if ($fieldLabelElem.length > 0) { fieldLabel = $fieldLabelElem.text().replace('*', ''); } } var errorMsg = errorTemplateMsg.format(fieldLabel); return errorMsg; }; /// /// /// /// /// // Configurable in debug console. Controls behavior of FieldConditionsRunner.log(). var condRunnerHideLogDupes = true; // Missing methods for IE if (!Element.prototype.matches) { Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; } if (!Element.prototype.closest) { Element.prototype.closest = function (s) { var el = this; do { if (Element.prototype.matches.call(el, s)) return el; el = el.parentElement || el.parentNode; } while (el !== null && el.nodeType === 1); return null; }; } ////////// Helper Functions /////////////// $("*").focus(function () { var inputs = $("input[type=text][cp5ph=true], textarea[cp5ph=true]"); if (inputs != null) { for (var i = 0; i < inputs.length; i++) { var elementName = inputs[i].getAttribute('id'); if (elementName != null) { var top = $('#' + elementName).offset().top; var left = $('#' + elementName).offset().left; if (top != -2 && left != -2) $('#ph_' + elementName).offset({ left: (left + 5), top: (top + 5) }); } } } }); // Helper that handles replacement of special characters. // * value - variable to handle characters of. function HandleCharacters(value) { return value.replace(/,/g, '_d'); } if (Array.prototype.any == null && !$.isFunction(Array.prototype.any)) { // Returns true if callback condition returns true for any items in array. // * callback - Callback function with single argument for current index. The 'this' reference points to the array. Array.prototype.any = function (callback) { if (this == null) return false; for (var i = 0, len = this.length; i < len; i++) { if (callback.call(this, i)) return true; } return false; } } if (Array.prototype.all == null && !$.isFunction(Array.prototype.all)) { // Returns true if callback condition returns true for all items in array. // * callback - Callback function with single argument for current index. The 'this' reference points to the array. Array.prototype.all = function (callback) { if (this == null) return false; for (var i = 0, len = this.length; i < len; i++) { if (!callback.call(this, i)) return false; } return true; }; } if (Error.argNull == null || !$.isFunction(Error.argNull)) { // Static helper that creates error when null argument that should not be null is encountered. // * argName - Name of problematic null argument. Error.argNull = function (argName) { return new ReferenceError(argName + " cannot be null"); } } // Overridden on a per-form basis. Retrieves validator information for submission validation. // * validators - Validator dictionary. function getFormConditionData() { return []; } // Prints useful debugging information for FieldConditionsRunner.run() results. Use as done callback. // Note: When minifiying the JavaScript, this function can/should be removed. // * logs - Log generated by run(). function debugCondRunnerLogResults(logs) { if (logs == null) throw new Error.argNull("logs"); console.log("## run() started at " + (new Date()) + " ##"); for (var i = 0, iLen = logs.length; i < iLen; i++) { var log = logs[i]; var resultEx = log.isMet ? " (met)" : " (not met)"; console.log( "field: " + log.id + ", condIndex: " + log.condIndex + ", action: " + ConditionActions.getName(log.actType) + ", result: " + ConditionRunnerActResult.getName(log.result) + resultEx); if (log.needRestart) console.log("-- restart --"); } console.log("## run() ended ##"); console.log("\t"); } // Helper that repositions line siblings by re-assigning left/middle/right classes. // * liSiblingList - Array of LI elements for a form line. function repositionLineSiblings(liSiblingList) { if (liSiblingList == null) throw new Error.argNull("liSiblingList"); var sibling, $sibling; var len = liSiblingList.length; if (len > 0) { var operableNodes = []; for (var i = 0; i < len; i++) { sibling = liSiblingList[i]; $sibling = $(sibling); if (!$sibling.hasClass('hidden')) operableNodes.push($sibling); } len = operableNodes.length; if (len > 0) { operableNodes[0].removeClass('middle right').addClass('left'); var j = 1; for (; j < len - 1; j++) operableNodes[j].removeClass('left right').addClass('middle'); if (j < len) operableNodes[j].removeClass('left middle').addClass('right'); } } } // Helper that gets sibling field LI elements for a line field LI element. // * liElem - The LI element for a form field to get line siblings LIs for. function getLineSiblings(liElem) { if (liElem == null && (window.location.href).toString().toLowerCase().indexOf("print") != -1) return ""; if (liElem == null) throw new Error.argNull("liElem"); var nodeList = []; var startNode = liElem; // Get start of line. while (startNode && !$(startNode).hasClass('lineStart')) startNode = previousElementSibling(startNode); // Get end of line. if (startNode) { var endNode = startNode; var $endNode = null; while (endNode != null) { $endNode = $(endNode); if ($endNode.hasClass('lineEnd')) break; endNode = nextElementSibling(endNode); } } if (startNode && endNode) { var nodeEnum = startNode; while (true) { nodeList.push(nodeEnum); if (nodeEnum == endNode) break; nodeEnum = nextElementSibling(nodeEnum); } } return nodeList; } ////////// Enumerations /////////////////// // Condition actions. var ConditionActions = { None: 0, Show: 1, Hide: 2, Require: 3, RedirectTo: 4, getName: function (value) { for (var k in ConditionActions) { if (ConditionActions[k] == value) return k; } return null; } }; // Condition comparison types. var ConditionComparison = { None: 0, GreaterThan: 1, LessThan: 2, EqualTo: 3, NotEqualTo: 4, Contains: 5, Available: 6, Unavailable: 7, Between: 8, getName: function (value) { for (var k in ConditionComparison) { if (ConditionComparison[k] == value) return k; } return null; } }; // Condition runner action results. var ConditionRunnerActResult = { None: 0, SuccessImplicit: 1, SuccessExplicit: 2, SkipDuplicate: 3, SkipContradiction: 4, getName: function (value) { for (var k in ConditionRunnerActResult) { if (ConditionRunnerActResult[k] == value) return k; } return null; } }; ////////// FieldCondition Class /////////// // Internal. Creates instance of FieldCondition class. // * parent - Parent FieldConditions instance. // * condInfo - Object containing properties {compType, compValue, actElemInput, actID, actType, actFieldType, actURL, actURLNewWindow}. function FieldCondition(parent, condInfo) { if (parent == null) throw new Error.argNull("parent"); else if (condInfo == null) throw new Error.argNull("condInfo"); $.extend(this, condInfo); // Set instance parent. this.parent = parent; // Process actElemInput argument. var actElemInput = this.actElemInput; this.actElemInputIsArray = $.isArray(actElemInput); if (this.actElemInputIsArray) { for (var i = 0, len = actElemInput.length; i < len; i++) { if (typeof (actElemInput[i]) == "string") actElemInput[i] = document.getElementById(actElemInput[i]); } if (actElemInput.length > 0 && actElemInput[0]) { this.actElemContainer = actElemInput[0].closest('.formFieldContainer'); this.actElemInput = actElemInput; } } else { if (typeof (actElemInput) == "string") actElemInput = document.getElementById(actElemInput); if (actElemInput) { this.actElemContainer = actElemInput.closest('.formFieldContainer'); this.actElemInput = actElemInput; } } // Get shared container. this.$actElemContainer = $(this.actElemContainer); } // Static. Creates multiple instances from list of condition information. FieldCondition.createMulti = function (parent, condList) { if (parent == null) throw new Error.argNull("parent"); else if (condList == null) throw new Error.argNull("condList"); var ret = []; for (var i = 0, len = condList.length; i < len; i++) ret.push(new FieldCondition(parent, condList[i])); return ret; } // Checks if condition is met and performs any necessary action. // * updateUI - Determines if UI is updated after check. Treated as true if null/unspecified. FieldCondition.prototype.check = function (updateUI) { // TODO: Handle checkboxes/radios/dropdowns when Akila gets that done on back-end. var thisValue = []; var compValue = this.compValue; var isMet = false; switch (this.actFieldType) { case FieldTypes.Checkboxes: for (var i = 0, len = this.actElemInput.length; i < len; i++) { if (this.actElemInput[i].checked) thisValue.push(this.actElemInput[i].value.replace(/\,/g, '_comma_')); } break; case FieldTypes.RadioButtons: for (var i = 0, len = this.actElemInput.length; i < len; i++) { if (this.actElemInput[i].checked) { thisValue = [this.actElemInput[i].value]; break; } } break; case FieldTypes.DateTime: var tempArray = new Array(); for (var i = 0, len = this.actElemInput.length; i < len; i++) { tempArray.push([this.actElemInput[i].value]) } thisValue = [tempArray.join(',')]; break; default: thisValue = [this.actElemInput.value]; } var extractMoneyValue = function (v) { var stringBeginsWith = function (val, beginString) { return val.substring(0, beginString.length) === beginString } if (v && v != '') { if (stringBeginsWith(v, '$')) { return v.substring(1).replace(',', ''); } } return v.replace(',', ''); }; var isNum = function (val) { var extracted = extractMoneyValue(val); return parseFloat(extracted) === +extracted; }; var checkAgainst = function (compValue) { switch (this.compType) { case ConditionComparison.GreaterThan: return thisValue.any(function (index) { if (isNum(this[index]) && isNum(HandleCharacters(compValue))) { return parseFloat(extractMoneyValue(this[index])) > parseFloat(extractMoneyValue(HandleCharacters(compValue))); } return false; }); case ConditionComparison.LessThan: return thisValue.any(function (index) { if (isNum(this[index]) && isNum(HandleCharacters(compValue))) { return parseFloat(extractMoneyValue(this[index])) < parseFloat(extractMoneyValue(HandleCharacters(compValue))); } return false; }); case ConditionComparison.EqualTo: if (this.actFieldType == FieldTypes.DateTime) { if (this.actIsDateTimeSpan) { return this.checkDateEqualSpan(thisValue[0], compValue); } else { return this.checkDateEqualTo(thisValue[0], compValue); } } else { return thisValue.any(function (index) { return (isNull(HandleCharacters(this[index]), '') == isNull(HandleCharacters(compValue), '')); }); } case ConditionComparison.NotEqualTo: return thisValue.any(function (index) { return (isNull(this[index], '').toUpperCase() != isNull(HandleCharacters(compValue), '').toUpperCase()); }); break; case ConditionComparison.Contains: var containsExp = new RegExp(RegExp.metaEscape(HandleCharacters(compValue)), 'i'); return thisValue.any(function (index) { return containsExp.test(this[index]); }); case ConditionComparison.Unavailable: return this.$actElemContainer.hasClass('unavailable'); case ConditionComparison.Available: return !this.$actElemContainer.hasClass('unavailable'); case ConditionComparison.Between: return this.checkDateBetween(thisValue[0], compValue); return; case ConditionComparison.None: default: return true; } }; switch (this.actFieldType) { case FieldTypes.Checkboxes: var compArr = compValue.split(','); isMet = true; for (var i = 0, len = compArr.length; i < len; i++) { if (!checkAgainst.call(this, compArr[i])) { isMet = false; break; } } break; default: isMet = checkAgainst.call(this, compValue); } if (updateUI) this.doAction(isMet); return isMet; }; // Performs changes to applying field based on condition action and comparison result. FieldCondition.prototype.doAction = function (isMet) { var validator = (this.parent.validators ? this.parent.validators[this.parent.id] : null); switch (this.actType) { case ConditionActions.Show: this.doActionShow(isMet, validator); break; case ConditionActions.Hide: this.doActionHide(isMet, validator); break; case ConditionActions.Require: this.doActionRequire(isMet, validator); break; case ConditionActions.RedirectTo: this.doActionRedirect(isMet, validator); break; } }; FieldCondition.prototype.doActionShow = function (isMet, validator) { if (isMet) { this.parent.$elemContainer.removeClass('hidden'); this.parent.$elemContainer.removeClass('unavailable'); // Update classes assigned to fields (e.g. since what was "left" may now be hidden and a new "left" is needed). repositionLineSiblings(getLineSiblings(this.parent.elemContainer)); if (this.parent.$elemContainer.find('label > span') != null && this.parent.$elemContainer.find('label > span').length > 0) $('#liRequiredFieldInfo').show(); if (validator) validator.enabled = true; } else { this.parent.$elemContainer.addClass('hidden'); this.parent.$elemContainer.addClass('unavailable'); // Update classes assigned to fields (e.g. since what was "left" may now be hidden and a new "left" is needed). repositionLineSiblings(getLineSiblings(this.parent.elemContainer)); if (validator) validator.enabled = false; } }; FieldCondition.prototype.doActionHide = function (isMet, validator) { if (isMet) { this.parent.$elemContainer.addClass('hidden'); this.parent.$elemContainer.addClass('unavailable'); // Update classes assigned to fields (e.g. since what was "left" may now be hidden and a new "left" is needed). repositionLineSiblings(getLineSiblings(this.parent.elemContainer)); if (validator) validator.enabled = false; } else { this.parent.$elemContainer.removeClass('hidden'); this.parent.$elemContainer.removeClass('unavailable'); // Update classes assigned to fields (e.g. since what was "left" may now be hidden and a new "left" is needed). repositionLineSiblings(getLineSiblings(this.parent.elemContainer)); if (validator) validator.enabled = true; } }; FieldCondition.prototype.doActionRequire = function (isMet, validator) { if (isMet) { this.parent.$elemReq.removeClass('hidden'); if (validator == null) { validator = new FieldValidator(this.parent.elemInput, this.parent.id, this.parent.fieldType, this.parent.isInternal, true, FieldValidation.Any); this.parent.validators.add(validator); } this.parent.$elemContainer.find('label.labelForFieldElement > span').show(); $('#liRequiredFieldInfo').show(); if (validator) validator.isRequired = true; } else { this.parent.$elemReq.addClass('hidden'); this.parent.$elemContainer.find('label.labelForFieldElement > span').hide(); if (validator) validator.isRequired = false; } }; FieldCondition.prototype.doActionRedirect = function (isMet, validator) { // TODO: Some point alter this to pass in references for submitRedirect/redirectNewWindow. Not ideal at moment to ref. global vars. var submitRedirect = document.getElementById('submitRedirect'); redirectNewWindow = null; submitRedirect.value = ''; if (isMet) { if (this.actURLNewWindow) { redirectNewWindow = this.actURL; submitRedirect.value = ''; } else submitRedirect.value = this.actURL; } }; // Attachs event handler to field to monitor changes. // * condRunner - FieldConditionsRunner instance to attach. // Note: Calling more than once will have no effect. FieldCondition.prototype.attachRunner = function (condRunner) { if (condRunner == null) throw new Error.argNull("condRunner"); // Do not try to bind this if it is an internal field condition and we are not running internal field // conditions. if (this.parent.isInternal && !condRunner.runInternal) return; if ($.data(this.actElemInput, "runner_chghook") == null) { var changeHook = function (event) { condRunner.run(true); !window.isRemoveSetHeights && typeof SetHeights === "function" && SetHeights(); }; $.data(this.actElemInput, "runner_chghook", changeHook); $(this.actElemInput).change(changeHook); } }; // Removes event handler that monitors changes. // Note: Calling more than once will have no effect. FieldCondition.prototype.detachRunner = function () { var changeHook = $.data(this.actElemInput, "runner_chghook"); if (changeHook) { $(this.actElemInput).unbind('change', changeHook); $.removeData(this.actElemInput, "runner_chghook"); } }; FieldCondition.prototype.checkDateCommon = function (thisValue, compValue) { var defaultDate = '1/1/70'; var defualtDateObj = new Date(defaultDate); var compArr = compValue.split(','); var valueArr = thisValue.split(','); var hasTimeOfDayStart = false; var hasTimeOfDayEnd = false; var compareStartDate; var compareEndDate; if (compArr[0] == '') { compareStartDate = new Date(defaultDate + ' ' + compArr[2]); } else { compareStartDate = new Date(compArr[0] + ' ' + compArr[2]); } if (compArr[1] == '') { compareEndDate = new Date(defaultDate + ' ' + compArr[3]); } else { compareEndDate = new Date(compArr[1] + ' ' + compArr[3]); } var validStartDate = new Date(defaultDate); var validEndDate = new Date(defaultDate); var timeOfDayStart = ''; var timeOfDayEnd = ''; if (valueArr.length == 4) { if (valueArr[0] == '') { validStartDate = new Date(defaultDate + ' ' + valueArr[2]); } else { validStartDate = new Date(valueArr[0] + ' ' + valueArr[2]); } timeOfDayStart = this.getAMPMString(valueArr[2]); if (timeOfDayStart != '') hasTimeOfDayStart = true; if (valueArr[1] == '') { validEndDate = new Date(defaultDate + ' ' + valueArr[3]); } else { validEndDate = new Date(valueArr[1] + ' ' + valueArr[3]); } timeOfDayEnd = this.getAMPMString(valueArr[3]); if (timeOfDayEnd != '') hasTimeOfDayEnd = true; } else if (valueArr.length == 2) { timeOfDayStart = this.getAMPMString(valueArr[0]); if (timeOfDayStart == '') { if (valueArr[0] != '') { validStartDate = new Date(valueArr[0]); hasTimeOfDayStart = true; } } else { validStartDate = new Date(defaultDate + ' ' + valueArr[0]); hasTimeOfDayStart = true; } timeOfDayEnd = this.getAMPMString(valueArr[1]); if (timeOfDayEnd == '') { if (valueArr[1] != '') { validEndDate = new Date(valueArr[1]); hasTimeOfDayEnd = true; } } else { validEndDate = new Date(defaultDate + ' ' + valueArr[1]); hasTimeOfDayEnd = true; } } return { validStartDate: validStartDate, compareStartDate: compareStartDate, compareEndDate: compareEndDate, hasTimeOfDayStart: hasTimeOfDayStart, validEndDate: validEndDate, hasTimeOfDayEnd: hasTimeOfDayEnd }; }; FieldCondition.prototype.checkDateBetween = function (thisValue, compValue) { var checkDateCommonData = this.checkDateCommon(thisValue, compValue); return (checkDateCommonData.validStartDate.getTime() >= checkDateCommonData.compareStartDate.getTime() && checkDateCommonData.validStartDate.getTime() <= checkDateCommonData.compareEndDate.getTime() && checkDateCommonData.hasTimeOfDayStart) && (checkDateCommonData.validEndDate.getTime() <= checkDateCommonData.compareEndDate.getTime() && checkDateCommonData.validEndDate.getTime() >= checkDateCommonData.compareStartDate.getTime() && checkDateCommonData.hasTimeOfDayEnd); }; FieldCondition.prototype.checkDateEqualSpan = function (thisValue, compValue) { var checkDateCommonData = this.checkDateCommon(thisValue, compValue); return (checkDateCommonData.validStartDate.getTime() == checkDateCommonData.compareStartDate.getTime() && checkDateCommonData.hasTimeOfDayStart) && (checkDateCommonData.validEndDate.getTime() == checkDateCommonData.compareEndDate.getTime() && checkDateCommonData.hasTimeOfDayEnd); }; FieldCondition.prototype.checkDateEqualTo = function (thisValue, compValue) { var defaultDate = '1/1/70'; var defualtDateObj = new Date(defaultDate); var compArr = compValue.split(','); var valueArr = thisValue.split(','); var compareDate; var hasTimeOfDay = false; if (compArr[0] == '') { compareDate = new Date(defaultDate + ' ' + compArr[2]); } else { compareDate = new Date(compArr[0] + ' ' + compArr[2]); } var validDate = new Date(defaultDate); var timeOfDay = ''; if (valueArr.length == 1) { timeOfDay = this.getAMPMString(valueArr[0]); if (timeOfDay == '') { if (valueArr[0] != '') { validDate = new Date(valueArr[0]); hasTimeOfDay = true; } } else { hasTimeOfDay = true; validDate = new Date(valueArr[0]); } } else if (valueArr.length == 2) { timeOfDay = this.getAMPMString(valueArr[1]); if (timeOfDay != '') hasTimeOfDay = true; if (valueArr[0] != '') { validDate = new Date((valueArr[0] + ' ' + valueArr[1] + ' ').replace(/\-/g, '/')); } else { validDate = new Date((defaultDate + ' ' + valueArr[0] + ' ').replace(/\-/g, '/')); } } return validDate.getTime() == compareDate.getTime() && hasTimeOfDay; }; FieldCondition.prototype.getAMPMString = function (time) { var amIndex = time.indexOf('AM'); var pmIndex = time.indexOf('PM'); var timeOfDay = ''; // First see if the time is military time... if so we need to convert it to AM/PM so the rest // of this function will return the proper value. if (amIndex === -1 && pmIndex === -1) { time = militaryTimeToStandard(time); amIndex = time.indexOf('AM'); pmIndex = time.indexOf('PM'); } if (amIndex != -1) { timeOfDay = time.substring(amIndex).replace(" ", ""); } else if (pmIndex != -1) { timeOfDay = time.substring(pmIndex).replace(" ", ""); } return timeOfDay; }; function militaryTimeToStandard(militaryTime) { var colonIndex = militaryTime.indexOf(':'); var hours = ''; var min = ''; if (colonIndex === -1) { hours = militaryTime.substring(0, 2); min = militaryTime.substring(2, 4); } else { var tokens = militaryTime.split(':'); hours = tokens[0]; min = tokens[1]; } if (hours < 12) { ampm = 'AM'; } else { hours = hours - 12; ampm = 'PM'; } return parseInt(hours) + ':' + ('00' + min).slice('-2') + ' ' + ampm; ß } ////////// FieldConditions Class ////////// // Creates instance of FieldConditions class. // * elemInput - Reference to DOM element of field with condition. May be a DOM element or string containing ID. May also be array of DOM elements or IDs. Multiple elements must share same parent. // * id - The ID of the field with the condition. // * fieldType - The field type of the field with the condition. // * isInternal - Whether or not this condition is for internal-only fields. // * condList - List (array) of zero or more condition clauses for the field. // * validators - Validator dictionary. function FieldConditions(options, validators) { if (options.elemInput == null) throw new Error.argNull("options.elemInput"); else if (options.id == null) throw new Error.argNull("id"); else if (options.fieldType == null) throw new Error.argNull("options.fieldType"); else if (options.condList == null) throw new Error.argNull("options.condList"); else if (validators == null) throw new Error.argNull("validators"); this.elemInputIsArray = $.isArray(options.elemInput); // Process elemInput argument. if (this.elemInputIsArray) { for (var i = 0, len = options.elemInput.length; i < len; i++) { if (typeof (options.elemInput[i]) == "string") options.elemInput[i] = document.getElementById(options.elemInput[i]); } if (options.elemInput.length > 0 && options.elemInput[0]) { this.elemContainer = options.elemInput[0].closest('.formFieldContainer'); this.elemInput = options.elemInput; } } else { if (typeof (options.elemInput) == "string") options.elemInput = document.getElementById(options.elemInput); if (options.elemInput) { this.elemContainer = options.elemInput.closest('.formFieldContainer'); this.elemInput = options.elemInput; } } this.validators = validators; this.elemReq = document.getElementById('r_' + options.id); this.$elemContainer = $(this.elemContainer); this.$elemReq = $(this.elemReq); this.fieldType = options.fieldType; this.id = options.id; this.isInternal = options.isInternal; this.conditions = FieldCondition.createMulti(this, options.condList); } // Static. Creates a single conditions object from an options object. FieldConditions.createSingle = function (options, validators) { if (options == null) throw new Error.argNull("options"); else if (validators == null) throw new Error.argNull("validators"); return new FieldConditions( options, validators); }; // Static. Creates dictionary of conditions objects from array of option objects. FieldConditions.createMulti = function (optionsArray, validators) { if (optionsArray == null) throw new Error.argNull("optionsArray"); else if (validators == null) throw new Error.argNull("validators"); var ret = { keys: [] }; var key = null; for (var i = 0, len = optionsArray.length; i < len; i++) { if (optionsArray[i].id != null) { key = optionsArray[i].id; ret[key] = FieldConditions.createSingle(optionsArray[i], validators); ret.keys.push(key); } } return ret; }; // Attachs event handler to field to monitor changes. // * condRunner - FieldConditionsRunner instance to attach. // Note: Calling more than once will have no effect. FieldConditions.prototype.attachRunner = function (condRunner) { if (condRunner == null) throw new Error.argNull("condRunner"); for (var i = 0, len = this.conditions.length; i < len; i++) this.conditions[i].attachRunner(condRunner); }; // Removes event handler that monitors changes. // Note: Calling more than once will have no effect. FieldConditions.prototype.detachRunner = function () { for (var i = 0, len = this.conditions.length; i < len; i++) this.conditions[i].detachRunner(); }; ////////// FieldConditionsRunner Class //// // Creates new instance of conditions runners for the field conditions objects provided. // * allFieldConditions - Array of FieldConditions objects to execute checks for. // * doneCallback - Method executed when run() completes. Recieves log information as argument. // * autoAttach - Determines if allFieldConditions are automatically attached to this instance by the constructor. If null/unspecified, treated as true. // * runInternal - Set to true to execute internal-only fields. function FieldConditionsRunner(allFieldConditions, doneCallback, autoAttach, runInternal) { if (allFieldConditions == null) throw new Error.argNull("allFieldConditions"); else if (doneCallback == null) throw new Error.argNull("doneCallback"); this.fieldConditions = allFieldConditions; this.doneCallback = doneCallback; this.runInternal = runInternal; if (autoAttach == null || autoAttach) this.attachConditions(); } // Static. Internal. Creates static information object for state tracking during execution. FieldConditionsRunner.createFieldStateInfo = function () { var ret = {}; ret[ConditionActions.None] = ConditionRunnerActResult.None; ret[ConditionActions.Show] = ConditionRunnerActResult.None; ret[ConditionActions.Hide] = ConditionRunnerActResult.None; ret[ConditionActions.Require] = ConditionRunnerActResult.None; ret[ConditionActions.RedirectTo] = ConditionRunnerActResult.None; return ret; }; // Attaches to FieldConditions/FieldCondition objects that runner will use. FieldConditionsRunner.prototype.attachConditions = function () { for (var i = 0, iLen = this.fieldConditions.keys.length; i < iLen; i++) this.fieldConditions[this.fieldConditions.keys[i]].attachRunner(this); }; // Detaches to FieldConditions/FieldCondition objects that runner may have used. FieldConditionsRunner.prototype.detachConditions = function () { for (var i = 0, iLen = this.fieldConditions.keys.length; i < iLen; i++) this.fieldConditions[this.fieldConditions.keys[i]].detachRunner(this); }; // Internal. Cleans up runner for use again. FieldConditionsRunner.prototype.cleanup = function () { if (this.fieldConditionResults != null) { delete this.fieldConditionResults; delete this.fieldConditionLog; } }; // Internal. Called by run() to log result for each condition. FieldConditionsRunner.prototype.log = function (id, condIndex, actType, result, isMet, needRestart) { if (condRunnerHideLogDupes && result == ConditionRunnerActResult.SkipDuplicate) return; this.fieldConditionLog.push({ id: id, condIndex: condIndex, actType: actType, result: result, isMet: isMet, needRestart: needRestart }); }; // Internal. Sets whether or not the condition engine is executing. FieldConditionsRunner.prototype.setRunning = function (value) { if (arguments.length == 0) this.isRunning = true; else this.isRunning = value; }; // Gets whether or not the condition engine is executing. FieldConditionsRunner.prototype.getRunning = function () { return this.isRunning; }; // Internal. Tells condition execution task to reset cycle (done whenever something changes). FieldConditionsRunner.prototype.setRestart = function (value) { if (arguments == null || arguments.length == 0) this.needRestart = true; else this.needRestart = value; }; // Internal. Gets whether or not the runner needs to restart. FieldConditionsRunner.prototype.getRestart = function () { return this.needRestart; }; // Launches execution of conditions. // * fromEvent - Should be set to true when triggerd from DOM events. // NOTE: fromEvent may be a race condition but will be left for now while debugging (to simplify logs). FieldConditionsRunner.prototype.run = function (fromEvent) { if (this.getRunning() && !fromEvent) this.setRestart(); else { this.setRunning(); this.cleanup(); this.runTask(); this.doneCallback(this.fieldConditionLog); this.setRunning(false); } }; // Internal. Executes conditions. Should not be called while already running, so run() has sync mechanism for this. // * runInternal - If true, conditions for internal conditions will be ran. FieldConditionsRunner.prototype.runTask = function (runInternal) { var needRestart = true; // Prepare objects for execution. this.fieldConditionLog = []; this.fieldConditionResults = []; this.setRedirectUrl = false; // Populate state information. var condCondList = this.fieldConditions; var condListInfo = null; var condList = null; for (var i = 0, iLen = condCondList.keys.length; i < iLen; i++) this.fieldConditionResults[condCondList[condCondList.keys[i]].id] = FieldConditionsRunner.createFieldStateInfo(); // Number of restart actions (tracked to eventually kill infinite loops that should not happen). var numRestarts = 0; // Start/restart actions. while (needRestart && (++numRestarts < 65535)) { needRestart = false; this.setRestart(needRestart); for (var i = 0, iLen = condCondList.keys.length; i < iLen && !needRestart; i++) { condListInfo = condCondList[condCondList.keys[i]]; // If we are on the front-end, we don't want to have anything to do with back-end (internal only) // conditions, they will cause javascript errors. if (!this.runInternal && condListInfo.isInternal == true) continue; if (condListInfo.isInternal == false && document.URL.indexOf("Admin") > -1 && document.URL.indexOf("Submissions") > -1) continue; condList = condListInfo.conditions; for (var j = 0, jLen = condList.length; j < jLen && !needRestart; j++) { var cond = condList[j]; var results = this.fieldConditionResults[condListInfo.id]; var logState = ConditionRunnerActResult.None; // Determine whether or not condition is met. var isMet = cond.check(false); // This is because the effective action for a failed explicit Show is an implicit Hide (and vice versa). var effectiveActType = cond.actType; // Determine if action is contradictory or duplicate and skip UI changes if so. switch (effectiveActType) { case ConditionActions.Show: // Show can collide with hide. var resultsHide = results[ConditionActions.Hide]; if (resultsHide == ConditionRunnerActResult.SuccessExplicit || (resultsHide == ConditionRunnerActResult.SuccessImplicit && !isMet)) logState = ConditionRunnerActResult.SkipContradiction; break; case ConditionActions.Hide: // Hide can collide with show. var resultsShow = results[ConditionActions.Show]; if (resultsShow == ConditionRunnerActResult.SuccessExplicit || (resultsShow == ConditionRunnerActResult.SuccessImplicit && !isMet)) logState = ConditionRunnerActResult.SkipContradiction; break; case ConditionActions.RedirectTo: // Redirects work differently since they span all fields. Extra contradiction detection needed. if (this.setRedirectUrl) logState = ConditionRunnerActResult.SkipContradiction; else if (isMet) this.setRedirectUrl = true; break; } if (isMet && results[effectiveActType] == ConditionRunnerActResult.SuccessExplicit) logState = ConditionRunnerActResult.SkipDuplicate; else if (!isMet && results[effectiveActType] == ConditionRunnerActResult.SuccessExplicit) logState = ConditionRunnerActResult.SkipContradiction; else if (!isMet && results[effectiveActType] == ConditionRunnerActResult.SuccessImplicit) logState = ConditionRunnerActResult.SkipDuplicate; if (logState == ConditionRunnerActResult.None) { // Determine log result. logState = isMet ? ConditionRunnerActResult.SuccessExplicit : ConditionRunnerActResult.SuccessImplicit; // Update running state info. results[effectiveActType] = logState; // Update form UI. cond.doAction(isMet); // Restart task. this.setRestart(); needRestart = true; } // Log result. this.log(condListInfo.id, j, cond.actType, logState, isMet, needRestart); // Some other action could cause this to get set. if (this.getRestart()) needRestart = true; } } } if (numRestarts >= 65535) console[console.warn ? "warn" : "log"]("Infinite Loop (heuristic-detected) in FieldConditionsRunner.runTask()"); }; ; // This file contains javascript functions for the "External Integration" field type. // REQUIREMENTS: // FieldSetDesigner.js // These values must match the values provided in CivicPlus.Entities.Modules.FormCenter.Enums.ExternalIntegrationCommandType var ExternalIntegrationCommandType = { XMLCommand: 1, EchoCommand: 2 }; // Closure containing the client-side functionality for the External Integration field type. // * externalIntegrationClass - The name of the CSS class that is used to identify external integration buttons. function ExternalIntegration(externalIntegrationClassname, fieldSetDesigner) { this.cssClassname = externalIntegrationClassname; this.fieldSetDesigner = fieldSetDesigner; this.hookEvents = function () { var my = this; if (my.cssClassname == null) throw 'No external integration button CSS class name has been specified.' $('.' + this.cssClassname).click(function (event) { var fieldID = null; fieldID = event.target.id; my.sendRequest(fieldID); }); }; this.sendRequest = function (fieldID) { var params = this.getFormData(); var formID = $('#Item_FormID').val(); var intFieldID = fieldID.replace('e_', ''); var my = this; var sendData = { id: formID, fieldID: intFieldID, parameters: JSON.stringify(params) }; $.ajax({ type: 'post', url: '/FormCenter/ExecuteExternalIntegrationCommand', data: sendData, success: function (data) { my.updateFormData(data, my); }, error: function (xhr, status, error) { alert('An error occurred while sending the request.'); }, beforeSend: function () { ajaxPostBackStart('Loading'); }, complete: function () { ajaxPostBackEnd(); } }); }; // This function takes the values from the JSON result and sets the appropriate // form field values. this.updateFormData = function (responseFromController, externalIntegrationObject) { if (responseFromController.error) { alert('An error occurred: ' + responseFromController.errorMessage); return; } for (var i = 0, len = responseFromController.length; i < len; i++) { var param = responseFromController[i]; switch (responseFromController[i].Type) { case FieldTypes.ShortAnswer: externalIntegrationObject.updateShortAnswerField(param); break; case FieldTypes.LongAnswer: externalIntegrationObject.updateLongAnswerField(param); break; case FieldTypes.Checkboxes: externalIntegrationObject.updateCheckboxField(param); break; case FieldTypes.Dropdown: externalIntegrationObject.updateDropdownField(param); break; case FieldTypes.Password: externalIntegrationObject.updatePasswordField(param); break; case FieldTypes.RadioButtons: externalIntegrationObject.updateRadioField(param); break; case FieldTypes.DateTime: externalIntegrationObject.updateDateField(param); break; } } } this.getFormData = function () { var params = []; this.appendShortAnswerFields(params); this.appendCheckboxFields(params); this.appendRadioFields(params); this.appendDropdowns(params); this.appendTextAreaFields(params); this.appendPasswordFields(params); return params; }; this.createFieldValue = function (fieldID, type, value, externalName) { return { ID: fieldID, Type: type, Value: value, ExternalName: externalName}; }; this.appendShortAnswerFields = function (params) { var my = this; $('input[id^="e_"][type="text"]').each(function (i) { var element = $(this); params.push(my.createFieldValue(element.attr('id'), FieldTypes.ShortAnswer, element.val(), my.externalSubmissionName(element))); }); }; this.externalSubmissionName = function($element) { return $element.parents('*[data-external-submission-name]').attr('data-external-submission-name'); }; this.updateShortAnswerField = function (param) { var id = param.ID; $('#' + param.ID).val(param.Value); } this.appendCheckboxFields = function (params) { var my = this; $('input[id^="e_"][type="checkbox"]').each(function (index) { var item = $(this); var value = item.attr('value'); var checked = false; if (item.is(':checked')) { checked = true; } var fieldValue = my.createFieldValue(item.attr('id'), FieldTypes.Checkboxes, value, my.externalSubmissionName(item)); fieldValue.Checked = checked; params.push(fieldValue); }); }; this.updateCheckboxField = function (param) { var id = param.ID; if (param.Checked == true) $('#' + param.ID).attr('checked', true); else $('#' + param.ID).attr('checked', false); }; this.appendRadioFields = function (params) { var my = this; $('input[id^="e_"][type="radio"]').each(function (index) { var item = $(this); var value = item.attr('value'); var checked = false; if (item.is(':checked')) { checked = true; } var fieldValue = my.createFieldValue(item.attr('id'), FieldTypes.RadioButtons, value, my.externalSubmissionName(item)); fieldValue.Checked = checked; params.push(fieldValue); }); }; this.updateRadioField = function (param) { var id = param.ID; var value = param.Value; var button = $('input[id^="' + id + '"][value="' + value + '"]'); button.attr('checked', 'checked'); }; this.appendDropdowns = function (params) { var my = this; $('select[id^="e_"]').each(function (index) { var item = $(this); params.push(my.createFieldValue(item.attr('id'), FieldTypes.Dropdown, item.val(), my.externalSubmissionName(item))); }); }; this.updateDropdownField = function (param) { $('#' + param.ID).val(param.Value); } this.appendTextAreaFields = function (params) { var my = this; $('textarea[id^="e_"]').each(function (index) { var element = $(this); if (element.closest('li.LongAnswer').length > 0) { params.push(my.createFieldValue(element.attr('id'), FieldTypes.LongAnswer, element.text(), my.externalSubmissionName(element))); } }); }; this.updateLongAnswerField = function (param) { $('#' + param.ID).text(param.Value); } this.appendPasswordFields = function (params) { var my = this; $('input[id^="e_"][type="password"').each(function (i) { var element = $(this); params.push(my.createFieldValue(element.attr('id'), FieldTypes.Password, element.val(), my.externalSubmissionName(element))); }); } this.updatePasswordField = function (param) { // We don't want to update password information with values returned from the remote service. return; } this.updateDateField = function (param) { var my = this; var isSpan = (param.Value.indexOf(',') >= 0); var dateID = param.ID + '_date'; var timeID = param.ID + '_time'; var endDateID = param.ID + '_dateSpan'; var endTimeID = param.ID + '_timeSpan'; var updateDate = function (selector, val) { var datePicker = $('#' + selector); if (datePicker.length == 0) return; datePicker.data('tDatePicker').value(val); }; var updateTime = function (selector, val) { var timePicker = $('#' + selector); if (timePicker.length == 0) return; timePicker.data('tTimePicker').value(val); }; if (isSpan) { var dateArray = param.Value.split(','); var startDate = new Date(dateArray[0]); var endDate = new Date(dateArray[1]); updateDate(dateID, startDate); updateTime(timeID, startDate); updateDate(endDateID, endDate); updateTime(endTimeID, endDate); } else { var startDate = new Date(param.Value); updateDate(dateID, startDate); updateTime(timeID, startDate); } } }; // Calls subroutines used to initialize the ExternalIntegration javascript object. ExternalIntegration.prototype.initialize = function () { this.hookEvents(); }; var CP_DynamicForm_ExternalSubmissionFE = function($) { var self = this; self.getExternalSubmissionData = function() { var $fieldContainers = $('.formFieldContainer'); var data = {}; $fieldContainers.each(function (index) { var $container = $(this); var externalSubmissionName = self.getExternalSubmissionName($container); var singleFieldData = self.getSingleFieldData($container); if (singleFieldData != null) { data[externalSubmissionName] = self.getSingleFieldData($container); } }); return data; }; self.getExternalSubmissionName = function($container) { return $container.attr('data-external-submission-name'); }; self.getSingleFieldData = function($container) { var self = this; var result = null; if ($container.hasClass('ShortAnswer')) { result = self.submissionDataShortAnswer($container); } else if ($container.hasClass('LongAnswer')) { result = self.submissionDataLongAnswer($container); } else if ($container.hasClass('Checkboxes')) { result = self.submissionDataCheckboxes($container); } else if ($container.hasClass('Dropdown')) { result = self.submissionDataDropdown($container); } else if ($container.hasClass('RadioButtons')) { result = self.submissionDataRadioButtons($container); } else if ($container.hasClass('ReplyEmail')) { result = self.submissionDataReplyEmail($container); } else if ($container.hasClass('DateTime')) { result = self.submissionDataDateTime($container); } else if ($container.hasClass('DateTimeSpan')) { result = self.submissionDataDateTimeSpan($container); } else if ($container.hasClass('Password')) { result = self.submissionDataPassword($container); } return result; }; // // There needs to be one function for each type of field that will be passed to // an external submission service. // self.submissionDataShortAnswer = function($container) { return $('input[id^=e_]', $container).val(); }; self.submissionDataLongAnswer = function($container) { return $('textarea', $container).html(); }; self.submissionDataPassword = function($container) { return $('input[id^=e_]', $container).val(); }; self.submissionDataCheckboxes = function($container) { var result = []; var $checkedItems = $('input[type=checkbox]:checked', $container); $checkedItems.each(function (index) { result.push($(this).attr('Value')); }); return result.join(); }; self.submissionDataDropdown = function($container) { return $('select option:selected').val(); }; self.submissionDataRadioButtons = function($container) { return $('input:radio:checked', $container).val(); }; self.submissionDataReplyEmail = function($container) { return $('input[id^=e_]', $container).val(); }; self.isDateTimeValueEmpty = function(val) { // The telerik controls sometimes have just "0" if the user does not // enter a value, so this function checks for both an empty value and for "0" if (val == null || val == '' || val == '0') return true; else return false; }; self.submissionDataDateTime = function($container) { var $dateDiv = $('div.date', $container).not('.time')[0]; var $timeDiv = $('div.time', $container)[0]; var date = $('input', $dateDiv).val(); var time = $('input', $timeDiv).val(); return formatDateTime(date, time); }; self.formatDateTime = function(date, time) { var dateEmpty = isDateTimeValueEmpty(date); var timeEmpty = isDateTimeValueEmpty(time); if (dateEmpty && timeEmpty) return ''; else if (!dateEmpty && timeEmpty) return date; else if (dateEmpty && !timeEmpty) return time; else return date + ' ' + time; } self.submissionDataDateTimeSpan = function($container) { var $startDateDiv = $('div.date', $container).not('.time')[0]; var $startTimeDiv = $('div.date.time', $container)[0]; var startDate = $('input', $startDateDiv).val(); var startTime = $('input', $startTimeDiv).val(); var $endDateDiv = $('div.date', $container).not('.time')[1]; var $endTimeDiv = $('div.date.time', $container)[1]; var endDate = $('input', $endDateDiv).val(); var endTime = $('input', $endTimeDiv).val(); var startDateTime = formatDateTime(startDate, startTime); var endDateTime = formatDateTime(endDate, endTime); if (startDateTime == '' && endDateTime == '') return ''; return startDateTime + ',' + endDateTime; }; return self; }(jQuery); var CP_DynamicForm_PrintSubmission = (function () { self.StatusCodes = { Loading: 1, Success: 2, Spam: 3, Timeout: 4 }; return self; })(); /* * ----------------------------- JSTORAGE ------------------------------------- * Simple local storage wrapper to save data on the browser side, supporting * all major browsers - IE6+, Firefox2+, Safari4+, Chrome4+ and Opera 10.5+ * * Copyright (c) 2010 - 2012 Andris Reinman, andris.reinman@gmail.com * Project homepage: www.jstorage.info * * Licensed under MIT-style license: * * 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 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. */ (function () { var /* jStorage version */ JSTORAGE_VERSION = "0.4.3", /* detect a dollar object or create one if not found */ $ = window.jQuery || window.$ || (window.$ = {}), /* check for a JSON handling support */ JSON = { parse: window.JSON && (window.JSON.parse || window.JSON.decode) || String.prototype.evalJSON && function (str) { return String(str).evalJSON(); } || $.parseJSON || $.evalJSON, stringify: Object.toJSON || window.JSON && (window.JSON.stringify || window.JSON.encode) || $.toJSON }; // Break if no JSON support was found if (!JSON.parse || !JSON.stringify) { throw new Error("No JSON support found, include //cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js to page"); } var /* This is the object, that holds the cached values */ _storage = { __jstorage_meta: { CRC32: {} } }, /* Actual browser storage (localStorage or globalStorage['domain']) */ _storage_service = { jStorage: "{}" }, /* DOM element for older IE versions, holds userData behavior */ _storage_elm = null, /* How much space does the storage take */ _storage_size = 0, /* which backend is currently used */ _backend = false, /* onchange observers */ _observers = {}, /* timeout to wait after onchange event */ _observer_timeout = false, /* last update time */ _observer_update = 0, /* pubsub observers */ _pubsub_observers = {}, /* skip published items older than current timestamp */ _pubsub_last = +new Date(), /* Next check for TTL */ _ttl_timeout, /** * XML encoding and decoding as XML nodes can't be JSON'ized * XML nodes are encoded and decoded if the node is the value to be saved * but not if it's as a property of another object * Eg. - * $.jStorage.set("key", xmlNode); // IS OK * $.jStorage.set("key", {xml: xmlNode}); // NOT OK */ _XMLService = { /** * Validates a XML node to be XML * based on jQuery.isXML function */ isXML: function (elm) { var documentElement = (elm ? elm.ownerDocument || elm : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }, /** * Encodes a XML node to string * based on http://www.mercurytide.co.uk/news/article/issues-when-working-ajax/ */ encode: function (xmlNode) { if (!this.isXML(xmlNode)) { return false; } try { // Mozilla, Webkit, Opera return new XMLSerializer().serializeToString(xmlNode); } catch (E1) { try { // IE return xmlNode.xml; } catch (E2) { } } return false; }, /** * Decodes a XML node from string * loosely based on http://outwestmedia.com/jquery-plugins/xmldom/ */ decode: function (xmlString) { var dom_parser = ("DOMParser" in window && (new DOMParser()).parseFromString) || (window.ActiveXObject && function (_xmlString) { var xml_doc = new ActiveXObject('Microsoft.XMLDOM'); xml_doc.async = 'false'; xml_doc.loadXML(_xmlString); return xml_doc; }), resultXML; if (!dom_parser) { return false; } resultXML = dom_parser.call("DOMParser" in window && (new DOMParser()) || window, xmlString, 'text/xml'); return this.isXML(resultXML) ? resultXML : false; } }; ////////////////////////// PRIVATE METHODS //////////////////////// /** * Initialization function. Detects if the browser supports DOM Storage * or userData behavior and behaves accordingly. */ function _init() { /* Check if browser supports localStorage */ var localStorageReallyWorks = false; if ("localStorage" in window) { try { window.localStorage.setItem('_tmptest', 'tmpval'); localStorageReallyWorks = true; window.localStorage.removeItem('_tmptest'); } catch (BogusQuotaExceededErrorOnIos5) { // Thanks be to iOS5 Private Browsing mode which throws // QUOTA_EXCEEDED_ERRROR DOM Exception 22. } } if (localStorageReallyWorks) { try { if (window.localStorage) { _storage_service = window.localStorage; _backend = "localStorage"; _observer_update = _storage_service.jStorage_update; } } catch (E3) {/* Firefox fails when touching localStorage and cookies are disabled */ } } /* Check if browser supports globalStorage */ else if ("globalStorage" in window) { try { if (window.globalStorage) { _storage_service = window.globalStorage[window.location.hostname]; _backend = "globalStorage"; _observer_update = _storage_service.jStorage_update; } } catch (E4) {/* Firefox fails when touching localStorage and cookies are disabled */ } } /* Check if browser supports userData behavior */ else { _storage_elm = document.createElement('link'); if (_storage_elm.addBehavior) { /* Use a DOM element to act as userData storage */ _storage_elm.style.behavior = 'url(#default#userData)'; /* userData element needs to be inserted into the DOM! */ document.getElementsByTagName('head')[0].appendChild(_storage_elm); try { _storage_elm.load("jStorage"); } catch (E) { // try to reset cache _storage_elm.setAttribute("jStorage", "{}"); _storage_elm.save("jStorage"); _storage_elm.load("jStorage"); } var data = "{}"; try { data = _storage_elm.getAttribute("jStorage"); } catch (E5) { } try { _observer_update = _storage_elm.getAttribute("jStorage_update"); } catch (E6) { } _storage_service.jStorage = data; _backend = "userDataBehavior"; } else { _storage_elm = null; return; } } // Load data from storage _load_storage(); // remove dead keys _handleTTL(); // start listening for changes _setupObserver(); // initialize publish-subscribe service _handlePubSub(); // handle cached navigation if ("addEventListener" in window) { window.addEventListener("pageshow", function (event) { if (event.persisted) { _storageObserver(); } }, false); } } /** * Reload data from storage when needed */ function _reloadData() { var data = "{}"; if (_backend == "userDataBehavior") { _storage_elm.load("jStorage"); try { data = _storage_elm.getAttribute("jStorage"); } catch (E5) { } try { _observer_update = _storage_elm.getAttribute("jStorage_update"); } catch (E6) { } _storage_service.jStorage = data; } _load_storage(); // remove dead keys _handleTTL(); _handlePubSub(); } /** * Sets up a storage change observer */ function _setupObserver() { if (_backend == "localStorage" || _backend == "globalStorage") { if ("addEventListener" in window) { window.addEventListener("storage", _storageObserver, false); } else { document.attachEvent("onstorage", _storageObserver); } } else if (_backend == "userDataBehavior") { setInterval(_storageObserver, 1000); } } /** * Fired on any kind of data change, needs to check if anything has * really been changed */ function _storageObserver() { var updateTime; // cumulate change notifications with timeout clearTimeout(_observer_timeout); _observer_timeout = setTimeout(function () { if (_backend == "localStorage" || _backend == "globalStorage") { updateTime = _storage_service.jStorage_update; } else if (_backend == "userDataBehavior") { _storage_elm.load("jStorage"); try { updateTime = _storage_elm.getAttribute("jStorage_update"); } catch (E5) { } } if (updateTime && updateTime != _observer_update) { _observer_update = updateTime; _checkUpdatedKeys(); } }, 25); } /** * Reloads the data and checks if any keys are changed */ function _checkUpdatedKeys() { var oldCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32)), newCrc32List; _reloadData(); newCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32)); var key, updated = [], removed = []; for (key in oldCrc32List) { if (oldCrc32List.hasOwnProperty(key)) { if (!newCrc32List[key]) { removed.push(key); continue; } if (oldCrc32List[key] != newCrc32List[key] && String(oldCrc32List[key]).substr(0, 2) == "2.") { updated.push(key); } } } for (key in newCrc32List) { if (newCrc32List.hasOwnProperty(key)) { if (!oldCrc32List[key]) { updated.push(key); } } } _fireObservers(updated, "updated"); _fireObservers(removed, "deleted"); } /** * Fires observers for updated keys * * @param {Array|String} keys Array of key names or a key * @param {String} action What happened with the value (updated, deleted, flushed) */ function _fireObservers(keys, action) { keys = [].concat(keys || []); if (action == "flushed") { keys = []; for (var key in _observers) { if (_observers.hasOwnProperty(key)) { keys.push(key); } } action = "deleted"; } for (var i = 0, len = keys.length; i < len; i++) { if (_observers[keys[i]]) { for (var j = 0, jlen = _observers[keys[i]].length; j < jlen; j++) { _observers[keys[i]][j](keys[i], action); } } if (_observers["*"]) { for (var j = 0, jlen = _observers["*"].length; j < jlen; j++) { _observers["*"][j](keys[i], action); } } } } /** * Publishes key change to listeners */ function _publishChange() { var updateTime = (+new Date()).toString(); if (_backend == "localStorage" || _backend == "globalStorage") { _storage_service.jStorage_update = updateTime; } else if (_backend == "userDataBehavior") { _storage_elm.setAttribute("jStorage_update", updateTime); _storage_elm.save("jStorage"); } _storageObserver(); } /** * Loads the data from the storage based on the supported mechanism */ function _load_storage() { /* if jStorage string is retrieved, then decode it */ if (_storage_service.jStorage) { try { _storage = JSON.parse(String(_storage_service.jStorage)); } catch (E6) { _storage_service.jStorage = "{}"; } } else { _storage_service.jStorage = "{}"; } _storage_size = _storage_service.jStorage ? String(_storage_service.jStorage).length : 0; if (!_storage.__jstorage_meta) { _storage.__jstorage_meta = {}; } if (!_storage.__jstorage_meta.CRC32) { _storage.__jstorage_meta.CRC32 = {}; } } /** * This functions provides the "save" mechanism to store the jStorage object */ function _save() { _dropOldEvents(); // remove expired events try { _storage_service.jStorage = JSON.stringify(_storage); // If userData is used as the storage engine, additional if (_storage_elm) { _storage_elm.setAttribute("jStorage", _storage_service.jStorage); _storage_elm.save("jStorage"); } _storage_size = _storage_service.jStorage ? String(_storage_service.jStorage).length : 0; } catch (E7) {/* probably cache is full, nothing is saved this way*/ } } /** * Function checks if a key is set and is string or numberic * * @param {String} key Key name */ function _checkKey(key) { if (!key || (typeof key != "string" && typeof key != "number")) { throw new TypeError('Key name must be string or numeric'); } if (key == "__jstorage_meta") { throw new TypeError('Reserved key name'); } return true; } /** * Removes expired keys */ function _handleTTL() { var curtime, i, TTL, CRC32, nextExpire = Infinity, changed = false, deleted = []; clearTimeout(_ttl_timeout); if (!_storage.__jstorage_meta || typeof _storage.__jstorage_meta.TTL != "object") { // nothing to do here return; } curtime = +new Date(); TTL = _storage.__jstorage_meta.TTL; CRC32 = _storage.__jstorage_meta.CRC32; for (i in TTL) { if (TTL.hasOwnProperty(i)) { if (TTL[i] <= curtime) { delete TTL[i]; delete CRC32[i]; delete _storage[i]; changed = true; deleted.push(i); } else if (TTL[i] < nextExpire) { nextExpire = TTL[i]; } } } // set next check if (nextExpire != Infinity) { _ttl_timeout = setTimeout(_handleTTL, nextExpire - curtime); } // save changes if (changed) { _save(); _publishChange(); _fireObservers(deleted, "deleted"); } } /** * Checks if there's any events on hold to be fired to listeners */ function _handlePubSub() { var i, len; if (!_storage.__jstorage_meta.PubSub) { return; } var pubelm, _pubsubCurrent = _pubsub_last; for (i = len = _storage.__jstorage_meta.PubSub.length - 1; i >= 0; i--) { pubelm = _storage.__jstorage_meta.PubSub[i]; if (pubelm[0] > _pubsub_last) { _pubsubCurrent = pubelm[0]; _fireSubscribers(pubelm[1], pubelm[2]); } } _pubsub_last = _pubsubCurrent; } /** * Fires all subscriber listeners for a pubsub channel * * @param {String} channel Channel name * @param {Mixed} payload Payload data to deliver */ function _fireSubscribers(channel, payload) { if (_pubsub_observers[channel]) { for (var i = 0, len = _pubsub_observers[channel].length; i < len; i++) { // send immutable data that can't be modified by listeners _pubsub_observers[channel][i](channel, JSON.parse(JSON.stringify(payload))); } } } /** * Remove old events from the publish stream (at least 2sec old) */ function _dropOldEvents() { if (!_storage.__jstorage_meta.PubSub) { return; } var retire = +new Date() - 2000; for (var i = 0, len = _storage.__jstorage_meta.PubSub.length; i < len; i++) { if (_storage.__jstorage_meta.PubSub[i][0] <= retire) { // deleteCount is needed for IE6 _storage.__jstorage_meta.PubSub.splice(i, _storage.__jstorage_meta.PubSub.length - i); break; } } if (!_storage.__jstorage_meta.PubSub.length) { delete _storage.__jstorage_meta.PubSub; } } /** * Publish payload to a channel * * @param {String} channel Channel name * @param {Mixed} payload Payload to send to the subscribers */ function _publish(channel, payload) { if (!_storage.__jstorage_meta) { _storage.__jstorage_meta = {}; } if (!_storage.__jstorage_meta.PubSub) { _storage.__jstorage_meta.PubSub = []; } _storage.__jstorage_meta.PubSub.unshift([+new Date, channel, payload]); _save(); _publishChange(); } /** * JS Implementation of MurmurHash2 * * SOURCE: https://github.com/garycourt/murmurhash-js (MIT licensed) * * @author Gary Court * @see http://github.com/garycourt/murmurhash-js * @author Austin Appleby * @see http://sites.google.com/site/murmurhash/ * * @param {string} str ASCII only * @param {number} seed Positive integer only * @return {number} 32-bit positive integer hash */ function murmurhash2_32_gc(str, seed) { var l = str.length, h = seed ^ l, i = 0, k; while (l >= 4) { k = ((str.charCodeAt(i) & 0xff)) | ((str.charCodeAt(++i) & 0xff) << 8) | ((str.charCodeAt(++i) & 0xff) << 16) | ((str.charCodeAt(++i) & 0xff) << 24); k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); k ^= k >>> 24; k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k; l -= 4; ++i; } switch (l) { case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16; case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8; case 1: h ^= (str.charCodeAt(i) & 0xff); h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); } h ^= h >>> 13; h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); h ^= h >>> 15; return h >>> 0; } ////////////////////////// PUBLIC INTERFACE ///////////////////////// $.jStorage = { /* Version number */ version: JSTORAGE_VERSION, /** * Sets a key's value. * * @param {String} key Key to set. If this value is not set or not * a string an exception is raised. * @param {Mixed} value Value to set. This can be any value that is JSON * compatible (Numbers, Strings, Objects etc.). * @param {Object} [options] - possible options to use * @param {Number} [options.TTL] - optional TTL value * @return {Mixed} the used value */ set: function (key, value, options) { _checkKey(key); options = options || {}; // undefined values are deleted automatically if (typeof value == "undefined") { this.deleteKey(key); return value; } if (_XMLService.isXML(value)) { value = { _is_xml: true, xml: _XMLService.encode(value) }; } else if (typeof value == "function") { return undefined; // functions can't be saved! } else if (value && typeof value == "object") { // clone the object before saving to _storage tree value = JSON.parse(JSON.stringify(value)); } _storage[key] = value; _storage.__jstorage_meta.CRC32[key] = "2." + murmurhash2_32_gc(JSON.stringify(value), 0x9747b28c); this.setTTL(key, options.TTL || 0); // also handles saving and _publishChange _fireObservers(key, "updated"); return value; }, /** * Looks up a key in cache * * @param {String} key - Key to look up. * @param {mixed} def - Default value to return, if key didn't exist. * @return {Mixed} the key value, default value or null */ get: function (key, def) { _checkKey(key); if (key in _storage) { if (_storage[key] && typeof _storage[key] == "object" && _storage[key]._is_xml) { return _XMLService.decode(_storage[key].xml); } else { return _storage[key]; } } return typeof (def) == 'undefined' ? null : def; }, /** * Deletes a key from cache. * * @param {String} key - Key to delete. * @return {Boolean} true if key existed or false if it didn't */ deleteKey: function (key) { _checkKey(key); if (key in _storage) { delete _storage[key]; // remove from TTL list if (typeof _storage.__jstorage_meta.TTL == "object" && key in _storage.__jstorage_meta.TTL) { delete _storage.__jstorage_meta.TTL[key]; } delete _storage.__jstorage_meta.CRC32[key]; _save(); _publishChange(); _fireObservers(key, "deleted"); return true; } return false; }, /** * Sets a TTL for a key, or remove it if ttl value is 0 or below * * @param {String} key - key to set the TTL for * @param {Number} ttl - TTL timeout in milliseconds * @return {Boolean} true if key existed or false if it didn't */ setTTL: function (key, ttl) { var curtime = +new Date(); _checkKey(key); ttl = Number(ttl) || 0; if (key in _storage) { if (!_storage.__jstorage_meta.TTL) { _storage.__jstorage_meta.TTL = {}; } // Set TTL value for the key if (ttl > 0) { _storage.__jstorage_meta.TTL[key] = curtime + ttl; } else { delete _storage.__jstorage_meta.TTL[key]; } _save(); _handleTTL(); _publishChange(); return true; } return false; }, /** * Gets remaining TTL (in milliseconds) for a key or 0 when no TTL has been set * * @param {String} key Key to check * @return {Number} Remaining TTL in milliseconds */ getTTL: function (key) { var curtime = +new Date(), ttl; _checkKey(key); if (key in _storage && _storage.__jstorage_meta.TTL && _storage.__jstorage_meta.TTL[key]) { ttl = _storage.__jstorage_meta.TTL[key] - curtime; return ttl || 0; } return 0; }, /** * Deletes everything in cache. * * @return {Boolean} Always true */ flush: function () { _storage = { __jstorage_meta: { CRC32: {} } }; _save(); _publishChange(); _fireObservers(null, "flushed"); return true; }, /** * Returns a read-only copy of _storage * * @return {Object} Read-only copy of _storage */ storageObj: function () { function F() { } F.prototype = _storage; return new F(); }, /** * Returns an index of all used keys as an array * ['key1', 'key2',..'keyN'] * * @return {Array} Used keys */ index: function () { var index = [], i; for (i in _storage) { if (_storage.hasOwnProperty(i) && i != "__jstorage_meta") { index.push(i); } } return index; }, /** * How much space in bytes does the storage take? * * @return {Number} Storage size in chars (not the same as in bytes, * since some chars may take several bytes) */ storageSize: function () { return _storage_size; }, /** * Which backend is currently in use? * * @return {String} Backend name */ currentBackend: function () { return _backend; }, /** * Test if storage is available * * @return {Boolean} True if storage can be used */ storageAvailable: function () { return !!_backend; }, /** * Register change listeners * * @param {String} key Key name * @param {Function} callback Function to run when the key changes */ listenKeyChange: function (key, callback) { _checkKey(key); if (!_observers[key]) { _observers[key] = []; } _observers[key].push(callback); }, /** * Remove change listeners * * @param {String} key Key name to unregister listeners against * @param {Function} [callback] If set, unregister the callback, if not - unregister all */ stopListening: function (key, callback) { _checkKey(key); if (!_observers[key]) { return; } if (!callback) { delete _observers[key]; return; } for (var i = _observers[key].length - 1; i >= 0; i--) { if (_observers[key][i] == callback) { _observers[key].splice(i, 1); } } }, /** * Subscribe to a Publish/Subscribe event stream * * @param {String} channel Channel name * @param {Function} callback Function to run when the something is published to the channel */ subscribe: function (channel, callback) { channel = (channel || "").toString(); if (!channel) { throw new TypeError('Channel not defined'); } if (!_pubsub_observers[channel]) { _pubsub_observers[channel] = []; } _pubsub_observers[channel].push(callback); }, /** * Publish data to an event stream * * @param {String} channel Channel name * @param {Mixed} payload Payload to deliver */ publish: function (channel, payload) { channel = (channel || "").toString(); if (!channel) { throw new TypeError('Channel not defined'); } _publish(channel, payload); }, /** * Reloads the data from browser storage */ reInit: function () { _reloadData(); } }; // Initialize jStorage _init(); })(); window.pageHandleResponsive = true; $.when(window.Pages.rwdReady).done(function () { toggleClassMedia("maxWidth600px", ".cpForm:media(this-max-width: 600px)"); toggleClassMedia("maxWidth515px", "#FormCenterContent:media(this-max-width: 515px)"); toggleClassMedia("maxWidth485px", "#FormCenterContent:media(this-max-width: 485px)"); toggleClassMedia("maxWidth440px", ".cpForm:media(this-max-width: 440px)"); toggleClassMedia("maxWidth395px", "#FormCenterContent:media(this-max-width: 395px)"); toggleClassMedia("maxWidth380px", ".cpForm:media(this-max-width: 380px)"); }); /** cp.datepicker.js provides an JavaScript Date picker control. */ var cp = cp || {}; $(document).ready(function() { cp.datetimepicker = (function($) { // These are the publicly-accessible methods if (!$) { return; } return { createTimePicker: createTimePicker, createDatePicker: createDatePicker, }; // getOptionsFromHtmlAttributes parses through any attribute in the user-specific HTML date or time picker and // overwrites the values in "options" with values corresponding to "data-cp-datetimepicker-{optionName}". The // "optionName" portion of the attribute should correspond to a property of the pickadate or pickatime // options element. function getOptionsFromHtmlAttributes($inputElement, originalOptions) { $($inputElement[0].attributes).each(function() { if (this.name.match('^data-cp-datetimepicker-')) { var optionName = this.name.replace('data-cp-datetimepicker-', ''); var originalValue = originalOptions[optionName]; if (!originalValue) { // We only want to set the option value if it was not already set in the JavaScript options. // That is, the JavaScript options should always win over the HTML5 options. var optionVal = this.value; if (parseInt(optionVal)) { optionVal = parseInt(optionVal); } originalOptions[optionName] = optionVal; } } }); return originalOptions; } // createTimePicker creates a new time picker object out of the DOM object specified by timeTextboxSelector. // The timeTextboxSelector object must be an HTML INPUT element. function createTimePicker(timeTextboxSelector, options) { // The actualy Input Time component will be a hidden field. The DOM object in the source HTML // will be the editable text field for the user. options = options || {}; var $inputTextBox = $(timeTextboxSelector); if (!($inputTextBox) || $inputTextBox.length === 0) { // We got passed a bad selector console.log('ERR: cp.datetimepicker :: Could not find element: ' + timeTextboxSelector); return; } // Set any options that were specified directly from within the HTML tag. options = getOptionsFromHtmlAttributes($inputTextBox, options); //Wrap fieldSetSelector inside div if wrapInsideDiv is true var fieldSetSelector = '
'; if (options.wrapInsideDiv) { fieldSetSelector = '
' + fieldSetSelector + '
'; } $fieldset = $(fieldSetSelector); $inputTextBox.wrap($fieldset); var $hiddenTimeInput = $(''); $hiddenTimeInput.attr('data-cp-time-textbox-selector', timeTextboxSelector); $hiddenTimeInput.attr('aria-hidden', true); $hiddenTimeInput.insertAfter($inputTextBox); // We need to force "editable" in the options, otherwise things start to break. options.editable = true; $hiddenTimeInput.pickatime(options); var pickerObject = $hiddenTimeInput.pickatime('picker'); // reference to the pickatime object $inputTextBox.on({ change: function() { var inputTime = this.value; pickerObject.set('customSelect', insertColonIfOverFourChars(inputTime), options); }, focus: function() { pickerObject.open(false); // We have to set the tab-index of the "clear" button, so tabbing through fields works properly. $('.picker__button--clear').attr('tabindex', -1); }, blur: function() { pickerObject.close(true); } }); pickerObject.on('set', function(e) { var inputVal = $inputTextBox.val(); var selectedVal = autoTimeFormat(inputVal); if (typeof e.clear === "object" || (typeof e.select !== "undefined" && !isNaN(e.select)) || (e.customSelect && !selectedVal.match(/^([1-9]|1[012])(:[0-5]\d) [APap][mM]$/))) { selectedVal = this.get('value') === '' ? '12:00 AM' : this.get('value'); } $inputTextBox.val(selectedVal); $inputTextBox.attr('value', selectedVal); }); // Priming initialization if there was a value specified for the input if ($inputTextBox.val() !== '') { pickerObject.set('select', $inputTextBox.val(), options); } $(pickerObject.$root).find('.picker__list').attr('aria-label', 'Time List'); return pickerObject; } // createDatePicker creates a new date picker object using the element specified by "dateTextboxSelector". // The dateTextboxSelector object must be an HTML INPUT element. function createDatePicker(dateTextboxSelector, options) { // The actualy Input Date component will be a hidden field. The DOM object in the source HTML // will be the editable text field for the user. options = options || {}; var $inputTextBox = $(dateTextboxSelector); if (!($inputTextBox) || $inputTextBox.length === 0) { // We got passed a bad selector console.log('ERR: cp.datetimepicker :: Could not find element: ' + dateTextboxSelector); return; } // Set any options that were specified directly from within the HTML tag. options = getOptionsFromHtmlAttributes($inputTextBox, options); var dateAsString = $inputTextBox.val(); if (options.format == 'dd/mm/yyyy' && dateAsString.length > 0) { var splitDate = autoCompleteDate(dateAsString, options.format).split('/'); $inputTextBox.val(splitDate[1] + '/' + splitDate[0] + '/' + splitDate[2]); } if (options.useNativeControls) { $inputTextBox.prop('type', 'date'); return; } var $hiddenDateInput = $(''); $hiddenDateInput.attr('data-cp-date-textbox-selector', dateTextboxSelector); $hiddenDateInput.attr('aria-hidden', true); var fieldsetSelector = '
'; if (options.wrapInsideDiv) fieldsetSelector = '
' + fieldsetSelector + '
'; $fieldset = $(fieldsetSelector); $fieldset.attr("data-cp-datetimepicker-selector", dateTextboxSelector); $inputTextBox.wrap($fieldset); $hiddenDateInput.insertAfter($inputTextBox); // We have to force the editable option, otherwise things start to break. options.editable = true; $hiddenDateInput.pickadate(options); var pickerObject = $hiddenDateInput.pickadate('picker'); // reference to the pickadate object $inputTextBox.attr("role", "combobox"); $inputTextBox.attr("aria-haspopup", "dialog"); $inputTextBox.attr("aria-expanded", "false"); $inputTextBox.attr("aria-controls", pickerObject.$root.attr("id")); // Add handler to make sure datepicker is visible when shown pickerObject && pickerObject.on('open', function() { $inputTextBox.attr("aria-expanded", "true"); // Add a slight delay to ensure that the flyout has been added to the dom and the flyoutHeight is nonzero setTimeout(function() { // Get the position of the datepicker flyout relative to the top of the document var flyoutTop = pickerObject.$holder[0].getBoundingClientRect().top; // Get the height of the datepicker flyout var flyoutHeight = pickerObject.$holder[0].offsetHeight; // Get the height of the viewport var viewportHeight = window.innerHeight; // Calculate the amount of scrolling needed to make the entire datepicker flyout visible var scrollAmount = flyoutTop + flyoutHeight - viewportHeight; // If the datepicker flyout is not fully visible, scroll the viewport down to make it visible if (scrollAmount > 0) { window.scrollTo(0, scrollAmount + window.scrollY); } }, 50); }); function focusInput() { $inputTextBox.off("focus", openPicker); $inputTextBox.focus(); $inputTextBox.on("focus", openPicker); } pickerObject.on('close', function() { //Trigger the change event on the picker object's element. window.parent.$(dateTextboxSelector).change(); $inputTextBox.attr("aria-expanded", "false"); focusInput(); }); // setDate is a helper function that should only be called from within this module. function setDate(dateAsString, placeholder) { if (dateAsString === '') { pickerObject.set('clear', null, null); } else { if (pickerObject.component.settings.format == 'dd/mm/yyyy') { var splitDate = autoCompleteDate(dateAsString, pickerObject.component.settings.format).split('/'); var date = splitDate[1] + '/' + splitDate[0] + '/' + splitDate[2]; var epochDate = Date.parse(date); } else { var epochDate = Date.parse(autoCompleteDate(dateAsString, pickerObject.component.settings.format)); } if (!epochDate) { return; } else { var parsedDate = new Date(epochDate); pickerObject.set('select', [parsedDate.getFullYear(), parsedDate.getMonth(), parsedDate.getDate()]); } } } var intervalID; //Moves the date picker further up the DOM so it isn't overlapped https://civicplus.tpondemand.com/entity/22312 function adjustDTPicker() { if (intervalID === 0) { return; } var elemPicker = $('.picker--opened')[0]; if (elemPicker) { $(elemPicker).appendTo('#cpDatePickerWrapper'); elemPicker.style.fontSize = 'inherit'; } clearInterval(intervalID); $('.cpDatePickerElevate').each(function() { var $dateInput = $(this); if ($dateInput.is(':focus')) { adjustFlyoutPosition($dateInput, $('#cpDatePickerWrapper')); } }); intervalID = 0; } if ($('#cpDatePickerWrapper').length > 0) { $(window).resize(function() { $('.cpDatePickerElevate').each(function() { var $dateInput = $(this); if ($dateInput.is(':focus')) { adjustFlyoutPosition($dateInput, $('#cpDatePickerWrapper')); } }); }); } function openPicker() { // We have to set the tab-index of the "today", "close", and "clear" buttons, so tabbing through fields works properly. $('.picker__button--close').attr('tabindex', -1); $('.picker__button--today').attr('tabindex', -1); $('.picker__button--clear').attr('tabindex', -1); pickerObject.$holder.find('[tabindex="-1"]').attr('tabindex', 0) pickerObject.open(false); if ($('#cpDatePickerWrapper').length > 0) intervalID = setInterval(adjustDTPicker, 50); } $inputTextBox.on({ change: function() { setDate(this.value); }, focus: openPicker, click: openPicker, keydown: function(e) { if (e.keyCode === 9) { pickerObject.$holder.find('[tabindex="0"]').attr('tabindex', -1); } if (e.keyCode === 40) { e.preventDefault(); pickerObject.open(); } }, blur: function(e) { pickerObject.close(true); $inputTextBox.attr("aria-expanded", "false"); }, }); pickerObject.on('set', function() { $inputTextBox.val(this.get('value')); $inputTextBox.attr('value', this.get('value')); }); // Priming initialization if there was a value specified for the input if ($inputTextBox.val() !== '') { setDate($inputTextBox.val()); } return pickerObject; } function insertColonIfOverFourChars(inputString) { if (inputString != null && inputString.length > 3 && inputString.indexOf(":") < 0) { inputString = inputString.slice(0, 2) + ":" + inputString.slice(2, inputString.length); } return inputString; } function autoCompleteDate(dateAsString, formatString) { try { var fdts = null; var currentDate = new Date(); //guard clauses if (formatString == null || formatString.length === 0) { formatString === "mm/dd/yyyy"; } if ((dateAsString == null || dateAsString.length == 0 || dateAsString.indexOf(".") != -1) && formatString.toLowerCase == "dd/mm/yyyy") { return ('0' + currentDate.getDate()).slice(-2) + '/' + ('0' + (currentDate.getMonth() + 1)).slice(-2) + '/' + currentDate.getFullYear(); } else if (dateAsString == null || dateAsString.length == 0 || dateAsString.indexOf(".") != -1) { return ('0' + (currentDate.getMonth() + 1)).slice(-2) + '/' + ('0' + currentDate.getDate()).slice(-2) + '/' + currentDate.getFullYear(); } fdts = dateAsString.split("/"); if (fdts != null) { //switch mm/dd/yyyy to be dd/mm/yyyy for logic further down if (formatString.toLowerCase() !== "dd/mm/yyyy") { var day = fdts[1]; var month = fdts[0]; fdts[0] = day; fdts[1] = month; } if (fdts[0] == null || fdts[0] === '0' || fdts[0].length < 1 || fdts[0].length > 2) { fdts[0] = currentDate.getDate(); } if (fdts[1] == null || fdts[1] === '0' || fdts[1].length < 1 || fdts[1].length > 2) { fdts[1] = currentDate.getMonth() + 1; } if (fdts[2] == null || (fdts[2].length !== 2 && fdts[2].length !== 4)) { //For last year's date it also adds time at the end of date so extracting year fdts[2] = !isNaN(fdts[2].substr(0, 4)) ? fdts[2].substr(0, 4) : currentDate.getFullYear(); } else if (fdts[2].length === 2) { var yr = fdts[2]; var crDate = new Date(); var crCtry = crDate.getFullYear(); var pstCnry = crCtry - 100; crCtry = crCtry + ' '; pstCnry = pstCnry + ' '; crCtry = crCtry.substr(0, 2); pstCnry = pstCnry.substr(0, 2); if (yr >= 32) yr = pstCnry + yr; else yr = crCtry + yr; fdts[2] = yr; } } if (formatString.toLowerCase() === "dd/mm/yyyy") { dateAsString = ('0' + fdts[0]).slice(-2) + '/' + ('0' + fdts[1]).slice(-2) + '/' + fdts[2]; } else { dateAsString = ('0' + fdts[1]).slice(-2) + '/' + ('0' + fdts[0]).slice(-2) + '/' + fdts[2]; } return dateAsString; } catch (e) { return ""; } } function autoTimeFormat(inputString) { const regex1 = /^(0?[1-9]|1[0-2]) ?([ap]m)$/i; //eg: 5AM -> 5:00 AM const regex2 = /^(\d{1,2})(\d{2}) ?([ap]m)$/i; //eg: 500AM -> 5:00 AM const regex3 = /^(\d{1,2})(?::(\d{2}))?\s*([ap]m)?$/i; //eg: 05:00 am or 5:00 am -> 5:00 AM if (regex1.test(inputString)) { return inputString.replace(regex1, (match, hour, period) => { const hourNum = parseInt(hour); const formattedHour = hourNum === 12 ? 12 : hourNum % 12; // Convert to 12-hour format const formattedMinute = "00"; // Add 00 as minutes const formattedPeriod = period.toUpperCase(); // Convert period to uppercase return `${formattedHour}:${formattedMinute} ${formattedPeriod}`; }); } else if (regex2.test(inputString)) { return inputString.replace(regex2, (match, hour, minute, period) => { const hourNum = parseInt(hour); const formattedHour = hourNum === 12 ? 12 : hourNum % 12; // Convert to 12-hour format const formattedMinute = minute.padStart(2, "0"); // Pad minute with zero if necessary const formattedPeriod = period.toUpperCase(); // Convert period to uppercase return `${formattedHour}:${formattedMinute} ${formattedPeriod}`; }); } else if (regex3.test(inputString)) { return inputString.replace(regex3, (match, hour, minute, period) => { const hourNum = parseInt(hour); const formattedHour = hourNum === 12 ? 12 : hourNum % 12; // Convert to 12-hour format const formattedMinute = minute ? minute : "00"; // Set minute to "00" if not provided const formattedPeriod = period ? period.toUpperCase() : ""; // Convert period to uppercase if provided return `${formattedHour}:${formattedMinute} ${formattedPeriod}`; }); } else { return inputString; } } })(window.FeatureToggles.isActive("CMS.JqueryUpgrade.UpgradeTo224") && $('#hdnModuleEligibleForJquery224Upgrade').val() == "true" ? jQuery : typeof jQuery182 === "function" ? jQuery182 : null ); }); ; /*! * jQuery Form Plugin * version: 2.69 (06-APR-2011) * @requires jQuery v1.3.2 or later * * Examples and documentation at: http://malsup.com/jquery/form/ * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html */ ; (function ($) { /* Usage Note: ----------- Do not use both ajaxSubmit and ajaxForm on the same form. These functions are intended to be exclusive. Use ajaxSubmit if you want to bind your own submit handler to the form. For example, $(document).ready(function() { $('#myForm').bind('submit', function(e) { e.preventDefault(); // <-- important $(this).ajaxSubmit({ target: '#output' }); }); }); Use ajaxForm when you want the plugin to manage all the event binding for you. For example, $(document).ready(function() { $('#myForm').ajaxForm({ target: '#output' }); }); When using ajaxForm, the ajaxSubmit function will be invoked for you at the appropriate time. */ /** * ajaxSubmit() provides a mechanism for immediately submitting * an HTML form using AJAX. */ $.fn.ajaxSubmit = function (options) { // fast fail if nothing selected (http://dev.jquery.com/ticket/2752) if (!this.length) { log('ajaxSubmit: skipping submit process - no element selected'); return this; } if (typeof options == 'function') { options = { success: options }; } var action = this.attr('action'); var url = (typeof action === 'string') ? $.trim(action) : ''; if (url) { // clean url (don't include hash vaue) url = (url.match(/^([^#]+)/) || [])[1]; } url = url || window.location.href || ''; options = $.extend(true, { url: url, success: $.ajaxSettings.success, type: this[0].getAttribute('method') || 'GET', // IE7 massage (see issue 57) iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank' }, options); // hook for manipulating the form data before it is extracted; // convenient for use with rich editors like tinyMCE or FCKEditor var veto = {}; this.trigger('form-pre-serialize', [this, options, veto]); if (veto.veto) { log('ajaxSubmit: submit vetoed via form-pre-serialize trigger'); return this; } // provide opportunity to alter form data before it is serialized if (options.beforeSerialize && options.beforeSerialize(this, options) === false) { log('ajaxSubmit: submit aborted via beforeSerialize callback'); return this; } var n, v, a = this.formToArray(options.semantic); if (options.data) { options.extraData = options.data; for (n in options.data) { if (options.data[n] instanceof Array) { for (var k in options.data[n]) { a.push({ name: n, value: options.data[n][k] }); } } else { v = options.data[n]; v = $.isFunction(v) ? v() : v; // if value is fn, invoke it a.push({ name: n, value: v }); } } } // give pre-submit callback an opportunity to abort the submit if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) { log('ajaxSubmit: submit aborted via beforeSubmit callback'); return this; } // fire vetoable 'validate' event this.trigger('form-submit-validate', [a, this, options, veto]); if (veto.veto) { log('ajaxSubmit: submit vetoed via form-submit-validate trigger'); return this; } var q = $.param(a); if (options.type.toUpperCase() == 'GET') { options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q; options.data = null; // data is null for 'get' } else { options.data = q; // data is the query string for 'post' } var $form = this, callbacks = []; if (options.resetForm) { callbacks.push(function () { $form.resetForm(); }); } if (options.clearForm) { callbacks.push(function () { $form.clearForm(); }); } // perform a load on the target only if dataType is not provided if (!options.dataType && options.target) { var oldSuccess = options.success || function () { }; callbacks.push(function (data) { var fn = options.replaceTarget ? 'replaceWith' : 'html'; $(options.target)[fn](data).each(oldSuccess, arguments); }); } else if (options.success) { callbacks.push(options.success); } options.success = function (data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg var context = options.context || options; // jQuery 1.4+ supports scope context for (var i = 0, max = callbacks.length; i < max; i++) { callbacks[i].apply(context, [data, status, xhr || $form, $form]); } }; // are there files to upload? var fileInputs = $('input:file', this).length > 0; var mp = 'multipart/form-data'; var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp); // options.iframe allows user to force iframe mode // 06-NOV-09: now defaulting to iframe mode if file input is detected if (options.iframe !== false && (fileInputs || options.iframe || multipart)) { // hack to fix Safari hang (thanks to Tim Molendijk for this) // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d if (options.closeKeepAlive) { $.get(options.closeKeepAlive, fileUpload); } else { fileUpload(); } } else { $.ajax(options); } // fire 'notify' event this.trigger('form-submit-notify', [this, options]); return this; // private function for handling file uploads (hat tip to YAHOO!) function fileUpload() { var form = $form[0]; if ($(':input[name=submit],:input[id=submit]', form).length) { // if there is an input with a name or id of 'submit' then we won't be // able to invoke the submit fn on the form (at least not x-browser) alert('Error: Form elements must not have name or id of "submit".'); return; } var s = $.extend(true, {}, $.ajaxSettings, options); s.context = s.context || s; var id = 'jqFormIO' + (new Date().getTime()), fn = '_' + id; var $io = $('