/* Minification failed. Returning unminified contents.
(1834,30-31): run-time error JS1195: Expected expression: >
(1834,49-50): run-time error JS1004: Expected ';': )
(1835,5-6): run-time error JS1002: Syntax error: }
(1843,10-11): run-time error JS1004: Expected ';': :
(1843,28-29): run-time error JS1004: Expected ';': {
(1844,31-32): run-time error JS1195: Expected expression: >
(1844,50-51): run-time error JS1004: Expected ';': )
(1846,1-2): run-time error JS1002: Syntax error: }
(1851,10-11): run-time error JS1004: Expected ';': :
(1851,41-42): run-time error JS1004: Expected ';': {
(1861,1-2): run-time error JS1002: Syntax error: }
(1867,10-11): run-time error JS1004: Expected ';': :
(1867,41-42): run-time error JS1004: Expected ';': {
(1872,1-2): run-time error JS1002: Syntax error: }
(1872,3-4): run-time error JS1197: Too many errors. The file might not be a JavaScript file: ;
(1844,9-50): run-time error JS1018: 'return' statement outside of function: return this.every(a1 => arr1.includes(a1)
 */
/*
 AngularJS v1.6.6
 (c) 2010-2017 Google, Inc. http://angularjs.org
 License: MIT
*/
(function(u){'use strict';function oe(a){if(E(a))t(a.objectMaxDepth)&&(Lc.objectMaxDepth=Ub(a.objectMaxDepth)?a.objectMaxDepth:NaN);else return Lc}function Ub(a){return Y(a)&&0<a}function M(a,b){b=b||Error;return function(){var d=arguments[0],c;c="["+(a?a+":":"")+d+"] http://errors.angularjs.org/1.6.6/"+(a?a+"/":"")+d;for(d=1;d<arguments.length;d++){c=c+(1==d?"?":"&")+"p"+(d-1)+"=";var e=encodeURIComponent,f;f=arguments[d];f="function"==typeof f?f.toString().replace(/ \{[\s\S]*$/,""):"undefined"==
typeof f?"undefined":"string"!=typeof f?JSON.stringify(f):f;c+=e(f)}return new b(c)}}function xa(a){if(null==a||$a(a))return!1;if(I(a)||D(a)||B&&a instanceof B)return!0;var b="length"in Object(a)&&a.length;return Y(b)&&(0<=b&&(b-1 in a||a instanceof Array)||"function"===typeof a.item)}function p(a,b,d){var c,e;if(a)if(A(a))for(c in a)"prototype"!==c&&"length"!==c&&"name"!==c&&a.hasOwnProperty(c)&&b.call(d,a[c],c,a);else if(I(a)||xa(a)){var f="object"!==typeof a;c=0;for(e=a.length;c<e;c++)(f||c in
a)&&b.call(d,a[c],c,a)}else if(a.forEach&&a.forEach!==p)a.forEach(b,d,a);else if(Mc(a))for(c in a)b.call(d,a[c],c,a);else if("function"===typeof a.hasOwnProperty)for(c in a)a.hasOwnProperty(c)&&b.call(d,a[c],c,a);else for(c in a)ra.call(a,c)&&b.call(d,a[c],c,a);return a}function Nc(a,b,d){for(var c=Object.keys(a).sort(),e=0;e<c.length;e++)b.call(d,a[c[e]],c[e]);return c}function Vb(a){return function(b,d){a(d,b)}}function pe(){return++sb}function Wb(a,b,d){for(var c=a.$$hashKey,e=0,f=b.length;e<f;++e){var g=
b[e];if(E(g)||A(g))for(var k=Object.keys(g),h=0,l=k.length;h<l;h++){var m=k[h],n=g[m];d&&E(n)?ea(n)?a[m]=new Date(n.valueOf()):ab(n)?a[m]=new RegExp(n):n.nodeName?a[m]=n.cloneNode(!0):Xb(n)?a[m]=n.clone():(E(a[m])||(a[m]=I(n)?[]:{}),Wb(a[m],[n],!0)):a[m]=n}}c?a.$$hashKey=c:delete a.$$hashKey;return a}function P(a){return Wb(a,ya.call(arguments,1),!1)}function qe(a){return Wb(a,ya.call(arguments,1),!0)}function Z(a){return parseInt(a,10)}function Yb(a,b){return P(Object.create(a),b)}function C(){}
function bb(a){return a}function ka(a){return function(){return a}}function Zb(a){return A(a.toString)&&a.toString!==ha}function w(a){return"undefined"===typeof a}function t(a){return"undefined"!==typeof a}function E(a){return null!==a&&"object"===typeof a}function Mc(a){return null!==a&&"object"===typeof a&&!Oc(a)}function D(a){return"string"===typeof a}function Y(a){return"number"===typeof a}function ea(a){return"[object Date]"===ha.call(a)}function $b(a){switch(ha.call(a)){case "[object Error]":return!0;
case "[object Exception]":return!0;case "[object DOMException]":return!0;default:return a instanceof Error}}function A(a){return"function"===typeof a}function ab(a){return"[object RegExp]"===ha.call(a)}function $a(a){return a&&a.window===a}function cb(a){return a&&a.$evalAsync&&a.$watch}function Na(a){return"boolean"===typeof a}function re(a){return a&&Y(a.length)&&se.test(ha.call(a))}function Xb(a){return!(!a||!(a.nodeName||a.prop&&a.attr&&a.find))}function te(a){var b={};a=a.split(",");var d;for(d=
0;d<a.length;d++)b[a[d]]=!0;return b}function za(a){return N(a.nodeName||a[0]&&a[0].nodeName)}function db(a,b){var d=a.indexOf(b);0<=d&&a.splice(d,1);return d}function pa(a,b,d){function c(a,b,c){c--;if(0>c)return"...";var d=b.$$hashKey,g;if(I(a)){g=0;for(var f=a.length;g<f;g++)b.push(e(a[g],c))}else if(Mc(a))for(g in a)b[g]=e(a[g],c);else if(a&&"function"===typeof a.hasOwnProperty)for(g in a)a.hasOwnProperty(g)&&(b[g]=e(a[g],c));else for(g in a)ra.call(a,g)&&(b[g]=e(a[g],c));d?b.$$hashKey=d:delete b.$$hashKey;
return b}function e(a,b){if(!E(a))return a;var d=g.indexOf(a);if(-1!==d)return k[d];if($a(a)||cb(a))throw qa("cpws");var d=!1,e=f(a);void 0===e&&(e=I(a)?[]:Object.create(Oc(a)),d=!0);g.push(a);k.push(e);return d?c(a,e,b):e}function f(a){switch(ha.call(a)){case "[object Int8Array]":case "[object Int16Array]":case "[object Int32Array]":case "[object Float32Array]":case "[object Float64Array]":case "[object Uint8Array]":case "[object Uint8ClampedArray]":case "[object Uint16Array]":case "[object Uint32Array]":return new a.constructor(e(a.buffer),
a.byteOffset,a.length);case "[object ArrayBuffer]":if(!a.slice){var b=new ArrayBuffer(a.byteLength);(new Uint8Array(b)).set(new Uint8Array(a));return b}return a.slice(0);case "[object Boolean]":case "[object Number]":case "[object String]":case "[object Date]":return new a.constructor(a.valueOf());case "[object RegExp]":return b=new RegExp(a.source,a.toString().match(/[^/]*$/)[0]),b.lastIndex=a.lastIndex,b;case "[object Blob]":return new a.constructor([a],{type:a.type})}if(A(a.cloneNode))return a.cloneNode(!0)}
var g=[],k=[];d=Ub(d)?d:NaN;if(b){if(re(b)||"[object ArrayBuffer]"===ha.call(b))throw qa("cpta");if(a===b)throw qa("cpi");I(b)?b.length=0:p(b,function(a,c){"$$hashKey"!==c&&delete b[c]});g.push(a);k.push(b);return c(a,b,d)}return e(a,d)}function ac(a,b){return a===b||a!==a&&b!==b}function sa(a,b){if(a===b)return!0;if(null===a||null===b)return!1;if(a!==a&&b!==b)return!0;var d=typeof a,c;if(d===typeof b&&"object"===d)if(I(a)){if(!I(b))return!1;if((d=a.length)===b.length){for(c=0;c<d;c++)if(!sa(a[c],
b[c]))return!1;return!0}}else{if(ea(a))return ea(b)?ac(a.getTime(),b.getTime()):!1;if(ab(a))return ab(b)?a.toString()===b.toString():!1;if(cb(a)||cb(b)||$a(a)||$a(b)||I(b)||ea(b)||ab(b))return!1;d=S();for(c in a)if("$"!==c.charAt(0)&&!A(a[c])){if(!sa(a[c],b[c]))return!1;d[c]=!0}for(c in b)if(!(c in d)&&"$"!==c.charAt(0)&&t(b[c])&&!A(b[c]))return!1;return!0}return!1}function eb(a,b,d){return a.concat(ya.call(b,d))}function Ra(a,b){var d=2<arguments.length?ya.call(arguments,2):[];return!A(b)||b instanceof
RegExp?b:d.length?function(){return arguments.length?b.apply(a,eb(d,arguments,0)):b.apply(a,d)}:function(){return arguments.length?b.apply(a,arguments):b.call(a)}}function Pc(a,b){var d=b;"string"===typeof a&&"$"===a.charAt(0)&&"$"===a.charAt(1)?d=void 0:$a(b)?d="$WINDOW":b&&u.document===b?d="$DOCUMENT":cb(b)&&(d="$SCOPE");return d}function fb(a,b){if(!w(a))return Y(b)||(b=b?2:null),JSON.stringify(a,Pc,b)}function Qc(a){return D(a)?JSON.parse(a):a}function Rc(a,b){a=a.replace(ue,"");var d=Date.parse("Jan 01, 1970 00:00:00 "+
a)/6E4;return T(d)?b:d}function bc(a,b,d){d=d?-1:1;var c=a.getTimezoneOffset();b=Rc(b,c);d*=b-c;a=new Date(a.getTime());a.setMinutes(a.getMinutes()+d);return a}function Aa(a){a=B(a).clone().empty();var b=B("<div>").append(a).html();try{return a[0].nodeType===Oa?N(b):b.match(/^(<[^>]+>)/)[1].replace(/^<([\w-]+)/,function(a,b){return"<"+N(b)})}catch(d){return N(b)}}function Sc(a){try{return decodeURIComponent(a)}catch(b){}}function Tc(a){var b={};p((a||"").split("&"),function(a){var c,e,f;a&&(e=a=a.replace(/\+/g,
"%20"),c=a.indexOf("="),-1!==c&&(e=a.substring(0,c),f=a.substring(c+1)),e=Sc(e),t(e)&&(f=t(f)?Sc(f):!0,ra.call(b,e)?I(b[e])?b[e].push(f):b[e]=[b[e],f]:b[e]=f))});return b}function cc(a){var b=[];p(a,function(a,c){I(a)?p(a,function(a){b.push(ia(c,!0)+(!0===a?"":"="+ia(a,!0)))}):b.push(ia(c,!0)+(!0===a?"":"="+ia(a,!0)))});return b.length?b.join("&"):""}function gb(a){return ia(a,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function ia(a,b){return encodeURIComponent(a).replace(/%40/gi,
"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,b?"%20":"+")}function ve(a,b){var d,c,e=Ha.length;for(c=0;c<e;++c)if(d=Ha[c]+b,D(d=a.getAttribute(d)))return d;return null}function we(a,b){var d,c,e={};p(Ha,function(b){b+="app";!d&&a.hasAttribute&&a.hasAttribute(b)&&(d=a,c=a.getAttribute(b))});p(Ha,function(b){b+="app";var e;!d&&(e=a.querySelector("["+b.replace(":","\\:")+"]"))&&(d=e,c=e.getAttribute(b))});d&&(xe?(e.strictDi=null!==ve(d,"strict-di"),
b(d,c?[c]:[],e)):u.console.error("Angular: disabling automatic bootstrap. <script> protocol indicates an extension, document.location.href does not match."))}function Uc(a,b,d){E(d)||(d={});d=P({strictDi:!1},d);var c=function(){a=B(a);if(a.injector()){var c=a[0]===u.document?"document":Aa(a);throw qa("btstrpd",c.replace(/</,"&lt;").replace(/>/,"&gt;"));}b=b||[];b.unshift(["$provide",function(b){b.value("$rootElement",a)}]);d.debugInfoEnabled&&b.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);
b.unshift("ng");c=hb(b,d.strictDi);c.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return c},e=/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;u&&e.test(u.name)&&(d.debugInfoEnabled=!0,u.name=u.name.replace(e,""));if(u&&!f.test(u.name))return c();u.name=u.name.replace(f,"");$.resumeBootstrap=function(a){p(a,function(a){b.push(a)});return c()};A($.resumeDeferredBootstrap)&&$.resumeDeferredBootstrap()}function ye(){u.name=
"NG_ENABLE_DEBUG_INFO!"+u.name;u.location.reload()}function ze(a){a=$.element(a).injector();if(!a)throw qa("test");return a.get("$$testability")}function Vc(a,b){b=b||"_";return a.replace(Ae,function(a,c){return(c?b:"")+a.toLowerCase()})}function Be(){var a;if(!Wc){var b=tb();(la=w(b)?u.jQuery:b?u[b]:void 0)&&la.fn.on?(B=la,P(la.fn,{scope:Sa.scope,isolateScope:Sa.isolateScope,controller:Sa.controller,injector:Sa.injector,inheritedData:Sa.inheritedData}),a=la.cleanData,la.cleanData=function(b){for(var c,
e=0,f;null!=(f=b[e]);e++)(c=la._data(f,"events"))&&c.$destroy&&la(f).triggerHandler("$destroy");a(b)}):B=U;$.element=B;Wc=!0}}function ib(a,b,d){if(!a)throw qa("areq",b||"?",d||"required");return a}function ub(a,b,d){d&&I(a)&&(a=a[a.length-1]);ib(A(a),b,"not a function, got "+(a&&"object"===typeof a?a.constructor.name||"Object":typeof a));return a}function Ia(a,b){if("hasOwnProperty"===a)throw qa("badname",b);}function Xc(a,b,d){if(!b)return a;b=b.split(".");for(var c,e=a,f=b.length,g=0;g<f;g++)c=
b[g],a&&(a=(e=a)[c]);return!d&&A(a)?Ra(e,a):a}function vb(a){for(var b=a[0],d=a[a.length-1],c,e=1;b!==d&&(b=b.nextSibling);e++)if(c||a[e]!==b)c||(c=B(ya.call(a,0,e))),c.push(b);return c||a}function S(){return Object.create(null)}function dc(a){if(null==a)return"";switch(typeof a){case "string":break;case "number":a=""+a;break;default:a=!Zb(a)||I(a)||ea(a)?fb(a):a.toString()}return a}function Ce(a){function b(a,b,c){return a[b]||(a[b]=c())}var d=M("$injector"),c=M("ng");a=b(a,"angular",Object);a.$$minErr=
a.$$minErr||M;return b(a,"module",function(){var a={};return function(f,g,k){var h={};if("hasOwnProperty"===f)throw c("badname","module");g&&a.hasOwnProperty(f)&&(a[f]=null);return b(a,f,function(){function a(b,c,d,g){g||(g=e);return function(){g[d||"push"]([b,c,arguments]);return p}}function b(a,c,d){d||(d=e);return function(b,e){e&&A(e)&&(e.$$moduleName=f);d.push([a,c,arguments]);return p}}if(!g)throw d("nomod",f);var e=[],q=[],G=[],L=a("$injector","invoke","push",q),p={_invokeQueue:e,_configBlocks:q,
_runBlocks:G,info:function(a){if(t(a)){if(!E(a))throw c("aobj","value");h=a;return this}return h},requires:g,name:f,provider:b("$provide","provider"),factory:b("$provide","factory"),service:b("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),decorator:b("$provide","decorator",q),animation:b("$animateProvider","register"),filter:b("$filterProvider","register"),controller:b("$controllerProvider","register"),directive:b("$compileProvider","directive"),component:b("$compileProvider",
"component"),config:L,run:function(a){G.push(a);return this}};k&&L(k);return p})}})}function ja(a,b){if(I(a)){b=b||[];for(var d=0,c=a.length;d<c;d++)b[d]=a[d]}else if(E(a))for(d in b=b||{},a)if("$"!==d.charAt(0)||"$"!==d.charAt(1))b[d]=a[d];return b||a}function De(a,b){var d=[];Ub(b)&&(a=$.copy(a,null,b));return JSON.stringify(a,function(a,b){b=Pc(a,b);if(E(b)){if(0<=d.indexOf(b))return"...";d.push(b)}return b})}function Ee(a){P(a,{errorHandlingConfig:oe,bootstrap:Uc,copy:pa,extend:P,merge:qe,equals:sa,
element:B,forEach:p,injector:hb,noop:C,bind:Ra,toJson:fb,fromJson:Qc,identity:bb,isUndefined:w,isDefined:t,isString:D,isFunction:A,isObject:E,isNumber:Y,isElement:Xb,isArray:I,version:Fe,isDate:ea,lowercase:N,uppercase:wb,callbacks:{$$counter:0},getTestability:ze,reloadWithDebugInfo:ye,$$minErr:M,$$csp:Ja,$$encodeUriSegment:gb,$$encodeUriQuery:ia,$$stringify:dc});ec=Ce(u);ec("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:Ge});a.provider("$compile",Yc).directive({a:He,input:Zc,
textarea:Zc,form:Ie,script:Je,select:Ke,option:Le,ngBind:Me,ngBindHtml:Ne,ngBindTemplate:Oe,ngClass:Pe,ngClassEven:Qe,ngClassOdd:Re,ngCloak:Se,ngController:Te,ngForm:Ue,ngHide:Ve,ngIf:We,ngInclude:Xe,ngInit:Ye,ngNonBindable:Ze,ngPluralize:$e,ngRepeat:af,ngShow:bf,ngStyle:cf,ngSwitch:df,ngSwitchWhen:ef,ngSwitchDefault:ff,ngOptions:gf,ngTransclude:hf,ngModel:jf,ngList:kf,ngChange:lf,pattern:$c,ngPattern:$c,required:ad,ngRequired:ad,minlength:bd,ngMinlength:bd,maxlength:cd,ngMaxlength:cd,ngValue:mf,
ngModelOptions:nf}).directive({ngInclude:of}).directive(xb).directive(dd);a.provider({$anchorScroll:pf,$animate:qf,$animateCss:rf,$$animateJs:sf,$$animateQueue:tf,$$AnimateRunner:uf,$$animateAsyncRun:vf,$browser:wf,$cacheFactory:xf,$controller:yf,$document:zf,$$isDocumentHidden:Af,$exceptionHandler:Bf,$filter:ed,$$forceReflow:Cf,$interpolate:Df,$interval:Ef,$http:Ff,$httpParamSerializer:Gf,$httpParamSerializerJQLike:Hf,$httpBackend:If,$xhrFactory:Jf,$jsonpCallbacks:Kf,$location:Lf,$log:Mf,$parse:Nf,
$rootScope:Of,$q:Pf,$$q:Qf,$sce:Rf,$sceDelegate:Sf,$sniffer:Tf,$templateCache:Uf,$templateRequest:Vf,$$testability:Wf,$timeout:Xf,$window:Yf,$$rAF:Zf,$$jqLite:$f,$$Map:ag,$$cookieReader:bg})}]).info({angularVersion:"1.6.6"})}function jb(a,b){return b.toUpperCase()}function yb(a){return a.replace(cg,jb)}function fc(a){a=a.nodeType;return 1===a||!a||9===a}function fd(a,b){var d,c,e=b.createDocumentFragment(),f=[];if(gc.test(a)){d=e.appendChild(b.createElement("div"));c=(dg.exec(a)||["",""])[1].toLowerCase();
c=aa[c]||aa._default;d.innerHTML=c[1]+a.replace(eg,"<$1></$2>")+c[2];for(c=c[0];c--;)d=d.lastChild;f=eb(f,d.childNodes);d=e.firstChild;d.textContent=""}else f.push(b.createTextNode(a));e.textContent="";e.innerHTML="";p(f,function(a){e.appendChild(a)});return e}function U(a){if(a instanceof U)return a;var b;D(a)&&(a=Q(a),b=!0);if(!(this instanceof U)){if(b&&"<"!==a.charAt(0))throw hc("nosel");return new U(a)}if(b){b=u.document;var d;a=(d=fg.exec(a))?[b.createElement(d[1])]:(d=fd(a,b))?d.childNodes:
[];ic(this,a)}else A(a)?gd(a):ic(this,a)}function jc(a){return a.cloneNode(!0)}function zb(a,b){!b&&fc(a)&&B.cleanData([a]);a.querySelectorAll&&B.cleanData(a.querySelectorAll("*"))}function hd(a,b,d,c){if(t(c))throw hc("offargs");var e=(c=Ab(a))&&c.events,f=c&&c.handle;if(f)if(b){var g=function(b){var c=e[b];t(d)&&db(c||[],d);t(d)&&c&&0<c.length||(a.removeEventListener(b,f),delete e[b])};p(b.split(" "),function(a){g(a);Bb[a]&&g(Bb[a])})}else for(b in e)"$destroy"!==b&&a.removeEventListener(b,f),delete e[b]}
function kc(a,b){var d=a.ng339,c=d&&kb[d];c&&(b?delete c.data[b]:(c.handle&&(c.events.$destroy&&c.handle({},"$destroy"),hd(a)),delete kb[d],a.ng339=void 0))}function Ab(a,b){var d=a.ng339,d=d&&kb[d];b&&!d&&(a.ng339=d=++gg,d=kb[d]={events:{},data:{},handle:void 0});return d}function lc(a,b,d){if(fc(a)){var c,e=t(d),f=!e&&b&&!E(b),g=!b;a=(a=Ab(a,!f))&&a.data;if(e)a[yb(b)]=d;else{if(g)return a;if(f)return a&&a[yb(b)];for(c in b)a[yb(c)]=b[c]}}}function Cb(a,b){return a.getAttribute?-1<(" "+(a.getAttribute("class")||
"")+" ").replace(/[\n\t]/g," ").indexOf(" "+b+" "):!1}function Db(a,b){b&&a.setAttribute&&p(b.split(" "),function(b){a.setAttribute("class",Q((" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+Q(b)+" "," ")))})}function Eb(a,b){if(b&&a.setAttribute){var d=(" "+(a.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");p(b.split(" "),function(a){a=Q(a);-1===d.indexOf(" "+a+" ")&&(d+=a+" ")});a.setAttribute("class",Q(d))}}function ic(a,b){if(b)if(b.nodeType)a[a.length++]=b;else{var d=
b.length;if("number"===typeof d&&b.window!==b){if(d)for(var c=0;c<d;c++)a[a.length++]=b[c]}else a[a.length++]=b}}function id(a,b){return Fb(a,"$"+(b||"ngController")+"Controller")}function Fb(a,b,d){9===a.nodeType&&(a=a.documentElement);for(b=I(b)?b:[b];a;){for(var c=0,e=b.length;c<e;c++)if(t(d=B.data(a,b[c])))return d;a=a.parentNode||11===a.nodeType&&a.host}}function jd(a){for(zb(a,!0);a.firstChild;)a.removeChild(a.firstChild)}function Gb(a,b){b||zb(a);var d=a.parentNode;d&&d.removeChild(a)}function hg(a,
b){b=b||u;if("complete"===b.document.readyState)b.setTimeout(a);else B(b).on("load",a)}function gd(a){function b(){u.document.removeEventListener("DOMContentLoaded",b);u.removeEventListener("load",b);a()}"complete"===u.document.readyState?u.setTimeout(a):(u.document.addEventListener("DOMContentLoaded",b),u.addEventListener("load",b))}function kd(a,b){var d=Hb[b.toLowerCase()];return d&&ld[za(a)]&&d}function ig(a,b){var d=function(c,d){c.isDefaultPrevented=function(){return c.defaultPrevented};var f=
b[d||c.type],g=f?f.length:0;if(g){if(w(c.immediatePropagationStopped)){var k=c.stopImmediatePropagation;c.stopImmediatePropagation=function(){c.immediatePropagationStopped=!0;c.stopPropagation&&c.stopPropagation();k&&k.call(c)}}c.isImmediatePropagationStopped=function(){return!0===c.immediatePropagationStopped};var h=f.specialHandlerWrapper||jg;1<g&&(f=ja(f));for(var l=0;l<g;l++)c.isImmediatePropagationStopped()||h(a,c,f[l])}};d.elem=a;return d}function jg(a,b,d){d.call(a,b)}function kg(a,b,d){var c=
b.relatedTarget;c&&(c===a||lg.call(a,c))||d.call(a,b)}function $f(){this.$get=function(){return P(U,{hasClass:function(a,b){a.attr&&(a=a[0]);return Cb(a,b)},addClass:function(a,b){a.attr&&(a=a[0]);return Eb(a,b)},removeClass:function(a,b){a.attr&&(a=a[0]);return Db(a,b)}})}}function Pa(a,b){var d=a&&a.$$hashKey;if(d)return"function"===typeof d&&(d=a.$$hashKey()),d;d=typeof a;return d="function"===d||"object"===d&&null!==a?a.$$hashKey=d+":"+(b||pe)():d+":"+a}function md(){this._keys=[];this._values=
[];this._lastKey=NaN;this._lastIndex=-1}function nd(a){a=Function.prototype.toString.call(a).replace(mg,"");return a.match(ng)||a.match(og)}function pg(a){return(a=nd(a))?"function("+(a[1]||"").replace(/[\s\r\n]+/," ")+")":"fn"}function hb(a,b){function d(a){return function(b,c){if(E(b))p(b,Vb(a));else return a(b,c)}}function c(a,b){Ia(a,"service");if(A(b)||I(b))b=q.instantiate(b);if(!b.$get)throw Ba("pget",a);return n[a+"Provider"]=b}function e(a,b){return function(){var c=z.invoke(b,this);if(w(c))throw Ba("undef",
a);return c}}function f(a,b,d){return c(a,{$get:!1!==d?e(a,b):b})}function g(a){ib(w(a)||I(a),"modulesToLoad","not an array");var b=[],c;p(a,function(a){function d(a){var b,c;b=0;for(c=a.length;b<c;b++){var e=a[b],g=q.get(e[0]);g[e[1]].apply(g,e[2])}}if(!m.get(a)){m.set(a,!0);try{D(a)?(c=ec(a),z.modules[a]=c,b=b.concat(g(c.requires)).concat(c._runBlocks),d(c._invokeQueue),d(c._configBlocks)):A(a)?b.push(q.invoke(a)):I(a)?b.push(q.invoke(a)):ub(a,"module")}catch(e){throw I(a)&&(a=a[a.length-1]),e.message&&
e.stack&&-1===e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Ba("modulerr",a,e.stack||e.message||e);}}});return b}function k(a,c){function d(b,e){if(a.hasOwnProperty(b)){if(a[b]===h)throw Ba("cdep",b+" <- "+l.join(" <- "));return a[b]}try{return l.unshift(b),a[b]=h,a[b]=c(b,e),a[b]}catch(g){throw a[b]===h&&delete a[b],g;}finally{l.shift()}}function e(a,c,g){var f=[];a=hb.$$annotate(a,b,g);for(var h=0,k=a.length;h<k;h++){var l=a[h];if("string"!==typeof l)throw Ba("itkn",l);f.push(c&&c.hasOwnProperty(l)?
c[l]:d(l,g))}return f}return{invoke:function(a,b,c,d){"string"===typeof c&&(d=c,c=null);c=e(a,c,d);I(a)&&(a=a[a.length-1]);d=a;if(Ca||"function"!==typeof d)d=!1;else{var g=d.$$ngIsClass;Na(g)||(g=d.$$ngIsClass=/^(?:class\b|constructor\()/.test(Function.prototype.toString.call(d)));d=g}return d?(c.unshift(null),new (Function.prototype.bind.apply(a,c))):a.apply(b,c)},instantiate:function(a,b,c){var d=I(a)?a[a.length-1]:a;a=e(a,b,c);a.unshift(null);return new (Function.prototype.bind.apply(d,a))},get:d,
annotate:hb.$$annotate,has:function(b){return n.hasOwnProperty(b+"Provider")||a.hasOwnProperty(b)}}}b=!0===b;var h={},l=[],m=new Ib,n={$provide:{provider:d(c),factory:d(f),service:d(function(a,b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:d(function(a,b){return f(a,ka(b),!1)}),constant:d(function(a,b){Ia(a,"constant");n[a]=b;G[a]=b}),decorator:function(a,b){var c=q.get(a+"Provider"),d=c.$get;c.$get=function(){var a=z.invoke(d,c);return z.invoke(b,null,{$delegate:a})}}}},
q=n.$injector=k(n,function(a,b){$.isString(b)&&l.push(b);throw Ba("unpr",l.join(" <- "));}),G={},L=k(G,function(a,b){var c=q.get(a+"Provider",b);return z.invoke(c.$get,c,void 0,a)}),z=L;n.$injectorProvider={$get:ka(L)};z.modules=q.modules=S();var v=g(a),z=L.get("$injector");z.strictDi=b;p(v,function(a){a&&z.invoke(a)});return z}function pf(){var a=!0;this.disableAutoScrolling=function(){a=!1};this.$get=["$window","$location","$rootScope",function(b,d,c){function e(a){var b=null;Array.prototype.some.call(a,
function(a){if("a"===za(a))return b=a,!0});return b}function f(a){if(a){a.scrollIntoView();var c;c=g.yOffset;A(c)?c=c():Xb(c)?(c=c[0],c="fixed"!==b.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):Y(c)||(c=0);c&&(a=a.getBoundingClientRect().top,b.scrollBy(0,a-c))}else b.scrollTo(0,0)}function g(a){a=D(a)?a:Y(a)?a.toString():d.hash();var b;a?(b=k.getElementById(a))?f(b):(b=e(k.getElementsByName(a)))?f(b):"top"===a&&f(null):f(null)}var k=b.document;a&&c.$watch(function(){return d.hash()},
function(a,b){a===b&&""===a||hg(function(){c.$evalAsync(g)})});return g}]}function lb(a,b){if(!a&&!b)return"";if(!a)return b;if(!b)return a;I(a)&&(a=a.join(" "));I(b)&&(b=b.join(" "));return a+" "+b}function qg(a){D(a)&&(a=a.split(" "));var b=S();p(a,function(a){a.length&&(b[a]=!0)});return b}function Ka(a){return E(a)?a:{}}function rg(a,b,d,c){function e(a){try{a.apply(null,ya.call(arguments,1))}finally{if(L--,0===L)for(;z.length;)try{z.pop()()}catch(b){d.error(b)}}}function f(){y=null;k()}function g(){v=
J();v=w(v)?null:v;sa(v,K)&&(v=K);s=K=v}function k(){var a=s;g();if(Ta!==h.url()||a!==v)Ta=h.url(),s=v,p(H,function(a){a(h.url(),v)})}var h=this,l=a.location,m=a.history,n=a.setTimeout,q=a.clearTimeout,G={};h.isMock=!1;var L=0,z=[];h.$$completeOutstandingRequest=e;h.$$incOutstandingRequestCount=function(){L++};h.notifyWhenNoOutstandingRequests=function(a){0===L?a():z.push(a)};var v,s,Ta=l.href,ma=b.find("base"),y=null,J=c.history?function(){try{return m.state}catch(a){}}:C;g();h.url=function(b,d,e){w(e)&&
(e=null);l!==a.location&&(l=a.location);m!==a.history&&(m=a.history);if(b){var f=s===e;if(Ta===b&&(!c.history||f))return h;var k=Ta&&La(Ta)===La(b);Ta=b;s=e;!c.history||k&&f?(k||(y=b),d?l.replace(b):k?(d=l,e=b.indexOf("#"),e=-1===e?"":b.substr(e),d.hash=e):l.href=b,l.href!==b&&(y=b)):(m[d?"replaceState":"pushState"](e,"",b),g());y&&(y=b);return h}return y||l.href.replace(/%27/g,"'")};h.state=function(){return v};var H=[],ta=!1,K=null;h.onUrlChange=function(b){if(!ta){if(c.history)B(a).on("popstate",
f);B(a).on("hashchange",f);ta=!0}H.push(b);return b};h.$$applicationDestroyed=function(){B(a).off("hashchange popstate",f)};h.$$checkUrlChange=k;h.baseHref=function(){var a=ma.attr("href");return a?a.replace(/^(https?:)?\/\/[^/]*/,""):""};h.defer=function(a,b){var c;L++;c=n(function(){delete G[c];e(a)},b||0);G[c]=!0;return c};h.defer.cancel=function(a){return G[a]?(delete G[a],q(a),e(C),!0):!1}}function wf(){this.$get=["$window","$log","$sniffer","$document",function(a,b,d,c){return new rg(a,c,b,
d)}]}function xf(){this.$get=function(){function a(a,c){function e(a){a!==n&&(q?q===a&&(q=a.n):q=a,f(a.n,a.p),f(a,n),n=a,n.n=null)}function f(a,b){a!==b&&(a&&(a.p=b),b&&(b.n=a))}if(a in b)throw M("$cacheFactory")("iid",a);var g=0,k=P({},c,{id:a}),h=S(),l=c&&c.capacity||Number.MAX_VALUE,m=S(),n=null,q=null;return b[a]={put:function(a,b){if(!w(b)){if(l<Number.MAX_VALUE){var c=m[a]||(m[a]={key:a});e(c)}a in h||g++;h[a]=b;g>l&&this.remove(q.key);return b}},get:function(a){if(l<Number.MAX_VALUE){var b=
m[a];if(!b)return;e(b)}return h[a]},remove:function(a){if(l<Number.MAX_VALUE){var b=m[a];if(!b)return;b===n&&(n=b.p);b===q&&(q=b.n);f(b.n,b.p);delete m[a]}a in h&&(delete h[a],g--)},removeAll:function(){h=S();g=0;m=S();n=q=null},destroy:function(){m=k=h=null;delete b[a]},info:function(){return P({},k,{size:g})}}}var b={};a.info=function(){var a={};p(b,function(b,e){a[e]=b.info()});return a};a.get=function(a){return b[a]};return a}}function Uf(){this.$get=["$cacheFactory",function(a){return a("templates")}]}
function Yc(a,b){function d(a,b,c){var d=/^\s*([@&<]|=(\*?))(\??)\s*([\w$]*)\s*$/,e=S();p(a,function(a,g){if(a in n)e[g]=n[a];else{var f=a.match(d);if(!f)throw ba("iscp",b,g,a,c?"controller bindings definition":"isolate scope definition");e[g]={mode:f[1][0],collection:"*"===f[2],optional:"?"===f[3],attrName:f[4]||g};f[4]&&(n[a]=e[g])}});return e}function c(a){var b=a.charAt(0);if(!b||b!==N(b))throw ba("baddir",a);if(a!==a.trim())throw ba("baddir",a);}function e(a){var b=a.require||a.controller&&a.name;
!I(b)&&E(b)&&p(b,function(a,c){var d=a.match(l);a.substring(d[0].length)||(b[c]=d[0]+c)});return b}var f={},g=/^\s*directive:\s*([\w-]+)\s+(.*)$/,k=/(([\w-]+)(?::([^;]+))?;?)/,h=te("ngSrc,ngSrcset,src,srcset"),l=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,m=/^(on[a-z]+|formaction)$/,n=S();this.directive=function ma(b,d){ib(b,"name");Ia(b,"directive");D(b)?(c(b),ib(d,"directiveFactory"),f.hasOwnProperty(b)||(f[b]=[],a.factory(b+"Directive",["$injector","$exceptionHandler",function(a,c){var d=[];p(f[b],function(g,
f){try{var h=a.invoke(g);A(h)?h={compile:ka(h)}:!h.compile&&h.link&&(h.compile=ka(h.link));h.priority=h.priority||0;h.index=f;h.name=h.name||b;h.require=e(h);var k=h,l=h.restrict;if(l&&(!D(l)||!/[EACM]/.test(l)))throw ba("badrestrict",l,b);k.restrict=l||"EA";h.$$moduleName=g.$$moduleName;d.push(h)}catch(m){c(m)}});return d}])),f[b].push(d)):p(b,Vb(ma));return this};this.component=function y(a,b){function c(a){function e(b){return A(b)||I(b)?function(c,d){return a.invoke(b,this,{$element:c,$attrs:d})}:
b}var g=b.template||b.templateUrl?b.template:"",f={controller:d,controllerAs:sg(b.controller)||b.controllerAs||"$ctrl",template:e(g),templateUrl:e(b.templateUrl),transclude:b.transclude,scope:{},bindToController:b.bindings||{},restrict:"E",require:b.require};p(b,function(a,b){"$"===b.charAt(0)&&(f[b]=a)});return f}if(!D(a))return p(a,Vb(Ra(this,y))),this;var d=b.controller||function(){};p(b,function(a,b){"$"===b.charAt(0)&&(c[b]=a,A(d)&&(d[b]=a))});c.$inject=["$injector"];return this.directive(a,
c)};this.aHrefSanitizationWhitelist=function(a){return t(a)?(b.aHrefSanitizationWhitelist(a),this):b.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(a){return t(a)?(b.imgSrcSanitizationWhitelist(a),this):b.imgSrcSanitizationWhitelist()};var q=!0;this.debugInfoEnabled=function(a){return t(a)?(q=a,this):q};var G=!1;this.preAssignBindingsEnabled=function(a){return t(a)?(G=a,this):G};var L=!1;this.strictComponentBindingsEnabled=function(a){return t(a)?(L=a,this):L};var z=10;this.onChangesTtl=
function(a){return arguments.length?(z=a,this):z};var v=!0;this.commentDirectivesEnabled=function(a){return arguments.length?(v=a,this):v};var s=!0;this.cssClassDirectivesEnabled=function(a){return arguments.length?(s=a,this):s};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$sce","$animate","$$sanitizeUri",function(a,b,c,e,n,F,R,x,W,r){function O(){try{if(!--Fa)throw ga=void 0,ba("infchng",z);R.$apply(function(){for(var a=[],b=0,
c=ga.length;b<c;++b)try{ga[b]()}catch(d){a.push(d)}ga=void 0;if(a.length)throw a;})}finally{Fa++}}function mc(a,b){if(b){var c=Object.keys(b),d,e,g;d=0;for(e=c.length;d<e;d++)g=c[d],this[g]=b[g]}else this.$attr={};this.$$element=a}function Ua(a,b,c){Ba.innerHTML="<span "+b+">";b=Ba.firstChild.attributes;var d=b[0];b.removeNamedItem(d.name);d.value=c;a.attributes.setNamedItem(d)}function na(a,b){try{a.addClass(b)}catch(c){}}function ca(a,b,c,d,e){a instanceof B||(a=B(a));var g=Va(a,b,a,c,d,e);ca.$$addScopeClass(a);
var f=null;return function(b,c,d){if(!a)throw ba("multilink");ib(b,"scope");e&&e.needsNewScope&&(b=b.$parent.$new());d=d||{};var h=d.parentBoundTranscludeFn,k=d.transcludeControllers;d=d.futureParentElement;h&&h.$$boundTransclude&&(h=h.$$boundTransclude);f||(f=(d=d&&d[0])?"foreignobject"!==za(d)&&ha.call(d).match(/SVG/)?"svg":"html":"html");d="html"!==f?B(ja(f,B("<div>").append(a).html())):c?Sa.clone.call(a):a;if(k)for(var l in k)d.data("$"+l+"Controller",k[l].instance);ca.$$addScopeInfo(d,b);c&&
c(d,b);g&&g(b,d,d,h);c||(a=g=null);return d}}function Va(a,b,c,d,e,g){function f(a,c,d,e){var g,k,l,m,q,n,H;if(s)for(H=Array(c.length),m=0;m<h.length;m+=3)g=h[m],H[g]=c[g];else H=c;m=0;for(q=h.length;m<q;)k=H[h[m++]],c=h[m++],g=h[m++],c?(c.scope?(l=a.$new(),ca.$$addScopeInfo(B(k),l)):l=a,n=c.transcludeOnThisElement?Ma(a,c.transclude,e):!c.templateOnThisElement&&e?e:!e&&b?Ma(a,b):null,c(g,l,k,d,n)):g&&g(a,k.childNodes,void 0,e)}for(var h=[],k=I(a)||a instanceof B,l,m,q,n,s,H=0;H<a.length;H++){l=new mc;
11===Ca&&Da(a,H,k);m=M(a[H],[],l,0===H?d:void 0,e);(g=m.length?Y(m,a[H],l,b,c,null,[],[],g):null)&&g.scope&&ca.$$addScopeClass(l.$$element);l=g&&g.terminal||!(q=a[H].childNodes)||!q.length?null:Va(q,g?(g.transcludeOnThisElement||!g.templateOnThisElement)&&g.transclude:b);if(g||l)h.push(H,g,l),n=!0,s=s||g;g=null}return n?f:null}function Da(a,b,c){var d=a[b],e=d.parentNode,g;if(d.nodeType===Oa)for(;;){g=e?d.nextSibling:a[b+1];if(!g||g.nodeType!==Oa)break;d.nodeValue+=g.nodeValue;g.parentNode&&g.parentNode.removeChild(g);
c&&g===a[b+1]&&a.splice(b+1,1)}}function Ma(a,b,c){function d(e,g,f,h,k){e||(e=a.$new(!1,k),e.$$transcluded=!0);return b(e,g,{parentBoundTranscludeFn:c,transcludeControllers:f,futureParentElement:h})}var e=d.$$slots=S(),g;for(g in b.$$slots)e[g]=b.$$slots[g]?Ma(a,b.$$slots[g],c):null;return d}function M(a,b,c,d,e){var g=c.$attr,f;switch(a.nodeType){case 1:f=za(a);T(b,Ea(f),"E",d,e);for(var h,l,m,q,n=a.attributes,s=0,H=n&&n.length;s<H;s++){var J=!1,G=!1;h=n[s];l=h.name;m=h.value;h=Ea(l);(q=Pa.test(h))&&
(l=l.replace(od,"").substr(8).replace(/_(.)/g,function(a,b){return b.toUpperCase()}));(h=h.match(Qa))&&$(h[1])&&(J=l,G=l.substr(0,l.length-5)+"end",l=l.substr(0,l.length-6));h=Ea(l.toLowerCase());g[h]=l;if(q||!c.hasOwnProperty(h))c[h]=m,kd(a,h)&&(c[h]=!0);xa(a,b,m,h,q);T(b,h,"A",d,e,J,G)}"input"===f&&"hidden"===a.getAttribute("type")&&a.setAttribute("autocomplete","off");if(!La)break;g=a.className;E(g)&&(g=g.animVal);if(D(g)&&""!==g)for(;a=k.exec(g);)h=Ea(a[2]),T(b,h,"C",d,e)&&(c[h]=Q(a[3])),g=g.substr(a.index+
a[0].length);break;case Oa:oa(b,a.nodeValue);break;case 8:if(!Ka)break;nc(a,b,c,d,e)}b.sort(ka);return b}function nc(a,b,c,d,e){try{var f=g.exec(a.nodeValue);if(f){var h=Ea(f[1]);T(b,h,"M",d,e)&&(c[h]=Q(f[2]))}}catch(k){}}function pd(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ba("uterdir",b,c);1===a.nodeType&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return B(d)}function U(a,b,c){return function(d,e,g,f,h){e=
pd(e[0],b,c);return a(d,e,g,f,h)}}function V(a,b,c,d,e,g){var f;return a?ca(b,c,d,e,g):function(){f||(f=ca(b,c,d,e,g),b=c=g=null);return f.apply(this,arguments)}}function Y(a,b,d,e,g,f,h,k,l){function m(a,b,c,d){if(a){c&&(a=U(a,c,d));a.require=x.require;a.directiveName=W;if(K===x||x.$$isolateScope)a=ua(a,{isolateScope:!0});h.push(a)}if(b){c&&(b=U(b,c,d));b.require=x.require;b.directiveName=W;if(K===x||x.$$isolateScope)b=ua(b,{isolateScope:!0});k.push(b)}}function q(a,e,g,f,l){function m(a,b,c,d){var e;
cb(a)||(d=c,c=b,b=a,a=void 0);ta&&(e=L);c||(c=ta?fa.parent():fa);if(d){var g=l.$$slots[d];if(g)return g(a,b,e,c,O);if(w(g))throw ba("noslot",d,Aa(fa));}else return l(a,b,e,c,O)}var n,x,F,y,R,L,z,fa;b===g?(f=d,fa=d.$$element):(fa=B(g),f=new mc(fa,d));R=e;K?y=e.$new(!0):s&&(R=e.$parent);l&&(z=m,z.$$boundTransclude=l,z.isSlotFilled=function(a){return!!l.$$slots[a]});J&&(L=da(fa,f,z,J,y,e,K));K&&(ca.$$addScopeInfo(fa,y,!0,!(v&&(v===K||v===K.$$originalDirective))),ca.$$addScopeClass(fa,!0),y.$$isolateBindings=
K.$$isolateBindings,x=qa(e,f,y,y.$$isolateBindings,K),x.removeWatches&&y.$on("$destroy",x.removeWatches));for(n in L){x=J[n];F=L[n];var W=x.$$bindings.bindToController;if(G){F.bindingInfo=W?qa(R,f,F.instance,W,x):{};var r=F();r!==F.instance&&(F.instance=r,fa.data("$"+x.name+"Controller",r),F.bindingInfo.removeWatches&&F.bindingInfo.removeWatches(),F.bindingInfo=qa(R,f,F.instance,W,x))}else F.instance=F(),fa.data("$"+x.name+"Controller",F.instance),F.bindingInfo=qa(R,f,F.instance,W,x)}p(J,function(a,
b){var c=a.require;a.bindToController&&!I(c)&&E(c)&&P(L[b].instance,X(b,c,fa,L))});p(L,function(a){var b=a.instance;if(A(b.$onChanges))try{b.$onChanges(a.bindingInfo.initialChanges)}catch(d){c(d)}if(A(b.$onInit))try{b.$onInit()}catch(e){c(e)}A(b.$doCheck)&&(R.$watch(function(){b.$doCheck()}),b.$doCheck());A(b.$onDestroy)&&R.$on("$destroy",function(){b.$onDestroy()})});n=0;for(x=h.length;n<x;n++)F=h[n],wa(F,F.isolateScope?y:e,fa,f,F.require&&X(F.directiveName,F.require,fa,L),z);var O=e;K&&(K.template||
null===K.templateUrl)&&(O=y);a&&a(O,g.childNodes,void 0,l);for(n=k.length-1;0<=n;n--)F=k[n],wa(F,F.isolateScope?y:e,fa,f,F.require&&X(F.directiveName,F.require,fa,L),z);p(L,function(a){a=a.instance;A(a.$postLink)&&a.$postLink()})}l=l||{};for(var n=-Number.MAX_VALUE,s=l.newScopeDirective,J=l.controllerDirectives,K=l.newIsolateScopeDirective,v=l.templateDirective,y=l.nonTlbTranscludeDirective,R=!1,L=!1,ta=l.hasElementTranscludeDirective,F=d.$$element=B(b),x,W,z,r=e,O,t=!1,Jb=!1,u,Da=0,C=a.length;Da<
C;Da++){x=a[Da];var Ua=x.$$start,D=x.$$end;Ua&&(F=pd(b,Ua,D));z=void 0;if(n>x.priority)break;if(u=x.scope)x.templateUrl||(E(u)?(aa("new/isolated scope",K||s,x,F),K=x):aa("new/isolated scope",K,x,F)),s=s||x;W=x.name;if(!t&&(x.replace&&(x.templateUrl||x.template)||x.transclude&&!x.$$tlb)){for(u=Da+1;t=a[u++];)if(t.transclude&&!t.$$tlb||t.replace&&(t.templateUrl||t.template)){Jb=!0;break}t=!0}!x.templateUrl&&x.controller&&(J=J||S(),aa("'"+W+"' controller",J[W],x,F),J[W]=x);if(u=x.transclude)if(R=!0,
x.$$tlb||(aa("transclusion",y,x,F),y=x),"element"===u)ta=!0,n=x.priority,z=F,F=d.$$element=B(ca.$$createComment(W,d[W])),b=F[0],la(g,ya.call(z,0),b),z[0].$$parentNode=z[0].parentNode,r=V(Jb,z,e,n,f&&f.name,{nonTlbTranscludeDirective:y});else{var na=S();if(E(u)){z=[];var Va=S(),Ma=S();p(u,function(a,b){var c="?"===a.charAt(0);a=c?a.substring(1):a;Va[a]=b;na[b]=null;Ma[b]=c});p(F.contents(),function(a){var b=Va[Ea(za(a))];b?(Ma[b]=!0,na[b]=na[b]||[],na[b].push(a)):z.push(a)});p(Ma,function(a,b){if(!a)throw ba("reqslot",
b);});for(var N in na)na[N]&&(na[N]=V(Jb,na[N],e))}else z=B(jc(b)).contents();F.empty();r=V(Jb,z,e,void 0,void 0,{needsNewScope:x.$$isolateScope||x.$$newScope});r.$$slots=na}if(x.template)if(L=!0,aa("template",v,x,F),v=x,u=A(x.template)?x.template(F,d):x.template,u=Ia(u),x.replace){f=x;z=gc.test(u)?qd(ja(x.templateNamespace,Q(u))):[];b=z[0];if(1!==z.length||1!==b.nodeType)throw ba("tplrt",W,"");la(g,F,b);C={$attr:{}};u=M(b,[],C);var nc=a.splice(Da+1,a.length-(Da+1));(K||s)&&Z(u,K,s);a=a.concat(u).concat(nc);
ea(d,C);C=a.length}else F.html(u);if(x.templateUrl)L=!0,aa("template",v,x,F),v=x,x.replace&&(f=x),q=ia(a.splice(Da,a.length-Da),F,d,g,R&&r,h,k,{controllerDirectives:J,newScopeDirective:s!==x&&s,newIsolateScopeDirective:K,templateDirective:v,nonTlbTranscludeDirective:y}),C=a.length;else if(x.compile)try{O=x.compile(F,d,r);var T=x.$$originalDirective||x;A(O)?m(null,Ra(T,O),Ua,D):O&&m(Ra(T,O.pre),Ra(T,O.post),Ua,D)}catch($){c($,Aa(F))}x.terminal&&(q.terminal=!0,n=Math.max(n,x.priority))}q.scope=s&&!0===
s.scope;q.transcludeOnThisElement=R;q.templateOnThisElement=L;q.transclude=r;l.hasElementTranscludeDirective=ta;return q}function X(a,b,c,d){var e;if(D(b)){var g=b.match(l);b=b.substring(g[0].length);var f=g[1]||g[3],g="?"===g[2];"^^"===f?c=c.parent():e=(e=d&&d[b])&&e.instance;if(!e){var h="$"+b+"Controller";e=f?c.inheritedData(h):c.data(h)}if(!e&&!g)throw ba("ctreq",b,a);}else if(I(b))for(e=[],f=0,g=b.length;f<g;f++)e[f]=X(a,b[f],c,d);else E(b)&&(e={},p(b,function(b,g){e[g]=X(a,b,c,d)}));return e||
null}function da(a,b,c,d,e,g,f){var h=S(),k;for(k in d){var l=d[k],m={$scope:l===f||l.$$isolateScope?e:g,$element:a,$attrs:b,$transclude:c},n=l.controller;"@"===n&&(n=b[l.name]);m=F(n,m,!0,l.controllerAs);h[l.name]=m;a.data("$"+l.name+"Controller",m.instance)}return h}function Z(a,b,c){for(var d=0,e=a.length;d<e;d++)a[d]=Yb(a[d],{$$isolateScope:b,$$newScope:c})}function T(b,c,e,g,h,k,l){if(c===h)return null;var m=null;if(f.hasOwnProperty(c)){h=a.get(c+"Directive");for(var n=0,q=h.length;n<q;n++)if(c=
h[n],(w(g)||g>c.priority)&&-1!==c.restrict.indexOf(e)){k&&(c=Yb(c,{$$start:k,$$end:l}));if(!c.$$bindings){var s=m=c,H=c.name,J={isolateScope:null,bindToController:null};E(s.scope)&&(!0===s.bindToController?(J.bindToController=d(s.scope,H,!0),J.isolateScope={}):J.isolateScope=d(s.scope,H,!1));E(s.bindToController)&&(J.bindToController=d(s.bindToController,H,!0));if(J.bindToController&&!s.controller)throw ba("noctrl",H);m=m.$$bindings=J;E(m.isolateScope)&&(c.$$isolateBindings=m.isolateScope)}b.push(c);
m=c}}return m}function $(b){if(f.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,e=c.length;d<e;d++)if(b=c[d],b.multiElement)return!0;return!1}function ea(a,b){var c=b.$attr,d=a.$attr;p(a,function(d,e){"$"!==e.charAt(0)&&(b[e]&&b[e]!==d&&(d=d.length?d+(("style"===e?";":" ")+b[e]):b[e]),a.$set(e,d,!0,c[e]))});p(b,function(b,e){a.hasOwnProperty(e)||"$"===e.charAt(0)||(a[e]=b,"class"!==e&&"style"!==e&&(d[e]=c[e]))})}function ia(a,b,d,g,f,h,k,l){var m=[],n,q,s=b[0],J=a.shift(),x=Yb(J,{templateUrl:null,
transclude:null,replace:null,$$originalDirective:J}),G=A(J.templateUrl)?J.templateUrl(b,d):J.templateUrl,F=J.templateNamespace;b.empty();e(G).then(function(c){var e,H;c=Ia(c);if(J.replace){c=gc.test(c)?qd(ja(F,Q(c))):[];e=c[0];if(1!==c.length||1!==e.nodeType)throw ba("tplrt",J.name,G);c={$attr:{}};la(g,b,e);var K=M(e,[],c);E(J.scope)&&Z(K,!0);a=K.concat(a);ea(d,c)}else e=s,b.html(c);a.unshift(x);n=Y(a,e,d,f,b,J,h,k,l);p(g,function(a,c){a===e&&(g[c]=b[0])});for(q=Va(b[0].childNodes,f);m.length;){c=
m.shift();H=m.shift();var v=m.shift(),y=m.shift(),K=b[0];if(!c.$$destroyed){if(H!==s){var L=H.className;l.hasElementTranscludeDirective&&J.replace||(K=jc(e));la(v,B(H),K);na(B(K),L)}H=n.transcludeOnThisElement?Ma(c,n.transclude,y):y;n(q,c,K,g,H)}}m=null}).catch(function(a){$b(a)&&c(a)});return function(a,b,c,d,e){a=e;b.$$destroyed||(m?m.push(b,c,d,a):(n.transcludeOnThisElement&&(a=Ma(b,n.transclude,e)),n(q,b,c,d,a)))}}function ka(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name<
b.name?-1:1:a.index-b.index}function aa(a,b,c,d){function e(a){return a?" (module: "+a+")":""}if(b)throw ba("multidir",b.name,e(b.$$moduleName),c.name,e(c.$$moduleName),a,Aa(d));}function oa(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:function(a){a=a.parent();var b=!!a.length;b&&ca.$$addBindingClass(a);return function(a,c){var e=c.parent();b||ca.$$addBindingClass(e);ca.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function ja(a,b){a=N(a||"html");switch(a){case "svg":case "math":var c=
u.document.createElement("div");c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function va(a,b){if("srcdoc"===b)return x.HTML;var c=za(a);if("src"===b||"ngSrc"===b){if(-1===["img","video","audio","source","track"].indexOf(c))return x.RESOURCE_URL}else if("xlinkHref"===b||"form"===c&&"action"===b||"link"===c&&"href"===b)return x.RESOURCE_URL}function xa(a,c,d,e,g){var f=va(a,e),k=h[e]||g,l=b(d,!g,f,k);if(l){if("multiple"===e&&"select"===za(a))throw ba("selmulti",
Aa(a));if(m.test(e))throw ba("nodomevents");c.push({priority:100,compile:function(){return{pre:function(a,c,g){c=g.$$observers||(g.$$observers=S());var h=g[e];h!==d&&(l=h&&b(h,!0,f,k),d=h);l&&(g[e]=l(a),(c[e]||(c[e]=[])).$$inter=!0,(g.$$observers&&g.$$observers[e].$$scope||a).$watch(l,function(a,b){"class"===e&&a!==b?g.$updateClass(a,b):g.$set(e,a)}))}}}})}}function la(a,b,c){var d=b[0],e=b.length,g=d.parentNode,f,h;if(a)for(f=0,h=a.length;f<h;f++)if(a[f]===d){a[f++]=c;h=f+e-1;for(var k=a.length;f<
k;f++,h++)h<k?a[f]=a[h]:delete a[f];a.length-=e-1;a.context===d&&(a.context=c);break}g&&g.replaceChild(c,d);a=u.document.createDocumentFragment();for(f=0;f<e;f++)a.appendChild(b[f]);B.hasData(d)&&(B.data(c,B.data(d)),B(d).off("$destroy"));B.cleanData(a.querySelectorAll("*"));for(f=1;f<e;f++)delete b[f];b[0]=c;b.length=1}function ua(a,b){return P(function(){return a.apply(null,arguments)},a,b)}function wa(a,b,d,e,g,f){try{a(b,d,e,g,f)}catch(h){c(h,Aa(d))}}function pa(a,b){if(L)throw ba("missingattr",
a,b);}function qa(a,c,d,e,g){function f(b,c,e){A(d.$onChanges)&&!ac(c,e)&&(ga||(a.$$postDigest(O),ga=[]),m||(m={},ga.push(h)),m[b]&&(e=m[b].previousValue),m[b]=new Kb(e,c))}function h(){d.$onChanges(m);m=void 0}var k=[],l={},m;p(e,function(e,h){var m=e.attrName,q=e.optional,s,H,x,G;switch(e.mode){case "@":q||ra.call(c,m)||(pa(m,g.name),d[h]=c[m]=void 0);q=c.$observe(m,function(a){if(D(a)||Na(a))f(h,a,d[h]),d[h]=a});c.$$observers[m].$$scope=a;s=c[m];D(s)?d[h]=b(s)(a):Na(s)&&(d[h]=s);l[h]=new Kb(oc,
d[h]);k.push(q);break;case "=":if(!ra.call(c,m)){if(q)break;pa(m,g.name);c[m]=void 0}if(q&&!c[m])break;H=n(c[m]);G=H.literal?sa:ac;x=H.assign||function(){s=d[h]=H(a);throw ba("nonassign",c[m],m,g.name);};s=d[h]=H(a);q=function(b){G(b,d[h])||(G(b,s)?x(a,b=d[h]):d[h]=b);return s=b};q.$stateful=!0;q=e.collection?a.$watchCollection(c[m],q):a.$watch(n(c[m],q),null,H.literal);k.push(q);break;case "<":if(!ra.call(c,m)){if(q)break;pa(m,g.name);c[m]=void 0}if(q&&!c[m])break;H=n(c[m]);var F=H.literal,v=d[h]=
H(a);l[h]=new Kb(oc,d[h]);q=a.$watch(H,function(a,b){if(b===a){if(b===v||F&&sa(b,v))return;b=v}f(h,a,b);d[h]=a},F);k.push(q);break;case "&":q||ra.call(c,m)||pa(m,g.name);H=c.hasOwnProperty(m)?n(c[m]):C;if(H===C&&q)break;d[h]=function(b){return H(a,b)}}});return{initialChanges:l,removeWatches:k.length&&function(){for(var a=0,b=k.length;a<b;++a)k[a]()}}}var Ja=/^\w/,Ba=u.document.createElement("div"),Ka=v,La=s,Fa=z,ga;mc.prototype={$normalize:Ea,$addClass:function(a){a&&0<a.length&&W.addClass(this.$$element,
a)},$removeClass:function(a){a&&0<a.length&&W.removeClass(this.$$element,a)},$updateClass:function(a,b){var c=rd(a,b);c&&c.length&&W.addClass(this.$$element,c);(c=rd(b,a))&&c.length&&W.removeClass(this.$$element,c)},$set:function(a,b,d,e){var g=kd(this.$$element[0],a),f=sd[a],h=a;g?(this.$$element.prop(a,b),e=g):f&&(this[f]=b,h=f);this[a]=b;e?this.$attr[a]=e:(e=this.$attr[a])||(this.$attr[a]=e=Vc(a,"-"));g=za(this.$$element);if("a"===g&&("href"===a||"xlinkHref"===a)||"img"===g&&"src"===a)this[a]=
b=r(b,"src"===a);else if("img"===g&&"srcset"===a&&t(b)){for(var g="",f=Q(b),k=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,k=/\s/.test(f)?k:/(,)/,f=f.split(k),k=Math.floor(f.length/2),l=0;l<k;l++)var m=2*l,g=g+r(Q(f[m]),!0),g=g+(" "+Q(f[m+1]));f=Q(f[2*l]).split(/\s/);g+=r(Q(f[0]),!0);2===f.length&&(g+=" "+Q(f[1]));this[a]=b=g}!1!==d&&(null===b||w(b)?this.$$element.removeAttr(e):Ja.test(e)?this.$$element.attr(e,b):Ua(this.$$element[0],e,b));(a=this.$$observers)&&p(a[h],function(a){try{a(b)}catch(d){c(d)}})},
$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers=S()),e=d[a]||(d[a]=[]);e.push(b);R.$evalAsync(function(){e.$$inter||!c.hasOwnProperty(a)||w(c[a])||b(c[a])});return function(){db(e,b)}}};var Ga=b.startSymbol(),Ha=b.endSymbol(),Ia="{{"===Ga&&"}}"===Ha?bb:function(a){return a.replace(/\{\{/g,Ga).replace(/}}/g,Ha)},Pa=/^ngAttr[A-Z]/,Qa=/^(.+)Start$/;ca.$$addBindingInfo=q?function(a,b){var c=a.data("$binding")||[];I(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:C;ca.$$addBindingClass=
q?function(a){na(a,"ng-binding")}:C;ca.$$addScopeInfo=q?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:C;ca.$$addScopeClass=q?function(a,b){na(a,b?"ng-isolate-scope":"ng-scope")}:C;ca.$$createComment=function(a,b){var c="";q&&(c=" "+(a||"")+": ",b&&(c+=b+" "));return u.document.createComment(c)};return ca}]}function Kb(a,b){this.previousValue=a;this.currentValue=b}function Ea(a){return a.replace(od,"").replace(tg,jb)}function rd(a,b){var d="",c=a.split(/\s+/),
e=b.split(/\s+/),f=0;a:for(;f<c.length;f++){for(var g=c[f],k=0;k<e.length;k++)if(g===e[k])continue a;d+=(0<d.length?" ":"")+g}return d}function qd(a){a=B(a);var b=a.length;if(1>=b)return a;for(;b--;){var d=a[b];(8===d.nodeType||d.nodeType===Oa&&""===d.nodeValue.trim())&&ug.call(a,b,1)}return a}function sg(a,b){if(b&&D(b))return b;if(D(a)){var d=td.exec(a);if(d)return d[3]}}function yf(){var a={},b=!1;this.has=function(b){return a.hasOwnProperty(b)};this.register=function(b,c){Ia(b,"controller");E(b)?
P(a,b):a[b]=c};this.allowGlobals=function(){b=!0};this.$get=["$injector","$window",function(d,c){function e(a,b,c,d){if(!a||!E(a.$scope))throw M("$controller")("noscp",d,b);a.$scope[b]=c}return function(f,g,k,h){var l,m,n;k=!0===k;h&&D(h)&&(n=h);if(D(f)){h=f.match(td);if(!h)throw ud("ctrlfmt",f);m=h[1];n=n||h[3];f=a.hasOwnProperty(m)?a[m]:Xc(g.$scope,m,!0)||(b?Xc(c,m,!0):void 0);if(!f)throw ud("ctrlreg",m);ub(f,m,!0)}if(k)return k=(I(f)?f[f.length-1]:f).prototype,l=Object.create(k||null),n&&e(g,n,
l,m||f.name),P(function(){var a=d.invoke(f,l,g,m);a!==l&&(E(a)||A(a))&&(l=a,n&&e(g,n,l,m||f.name));return l},{instance:l,identifier:n});l=d.instantiate(f,g,m);n&&e(g,n,l,m||f.name);return l}}]}function zf(){this.$get=["$window",function(a){return B(a.document)}]}function Af(){this.$get=["$document","$rootScope",function(a,b){function d(){e=c.hidden}var c=a[0],e=c&&c.hidden;a.on("visibilitychange",d);b.$on("$destroy",function(){a.off("visibilitychange",d)});return function(){return e}}]}function Bf(){this.$get=
["$log",function(a){return function(b,d){a.error.apply(a,arguments)}}]}function pc(a){return E(a)?ea(a)?a.toISOString():fb(a):a}function Gf(){this.$get=function(){return function(a){if(!a)return"";var b=[];Nc(a,function(a,c){null===a||w(a)||A(a)||(I(a)?p(a,function(a){b.push(ia(c)+"="+ia(pc(a)))}):b.push(ia(c)+"="+ia(pc(a))))});return b.join("&")}}}function Hf(){this.$get=function(){return function(a){function b(a,e,f){null===a||w(a)||(I(a)?p(a,function(a,c){b(a,e+"["+(E(a)?c:"")+"]")}):E(a)&&!ea(a)?
Nc(a,function(a,c){b(a,e+(f?"":"[")+c+(f?"":"]"))}):d.push(ia(e)+"="+ia(pc(a))))}if(!a)return"";var d=[];b(a,"",!0);return d.join("&")}}}function qc(a,b){if(D(a)){var d=a.replace(vg,"").trim();if(d){var c=b("Content-Type"),c=c&&0===c.indexOf(vd),e;(e=c)||(e=(e=d.match(wg))&&xg[e[0]].test(d));if(e)try{a=Qc(d)}catch(f){if(!c)return a;throw rc("baddata",a,f);}}}return a}function wd(a){var b=S(),d;D(a)?p(a.split("\n"),function(a){d=a.indexOf(":");var e=N(Q(a.substr(0,d)));a=Q(a.substr(d+1));e&&(b[e]=
b[e]?b[e]+", "+a:a)}):E(a)&&p(a,function(a,d){var f=N(d),g=Q(a);f&&(b[f]=b[f]?b[f]+", "+g:g)});return b}function xd(a){var b;return function(d){b||(b=wd(a));return d?(d=b[N(d)],void 0===d&&(d=null),d):b}}function yd(a,b,d,c){if(A(c))return c(a,b,d);p(c,function(c){a=c(a,b,d)});return a}function Ff(){var a=this.defaults={transformResponse:[qc],transformRequest:[function(a){return E(a)&&"[object File]"!==ha.call(a)&&"[object Blob]"!==ha.call(a)&&"[object FormData]"!==ha.call(a)?fb(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},
post:ja(sc),put:ja(sc),patch:ja(sc)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer",jsonpCallbackParam:"callback"},b=!1;this.useApplyAsync=function(a){return t(a)?(b=!!a,this):b};var d=this.interceptors=[];this.$get=["$browser","$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector","$sce",function(c,e,f,g,k,h,l,m){function n(b){function d(a,b){for(var c=0,e=b.length;c<e;){var g=b[c++],f=b[c++];a=a.then(g,f)}b.length=0;return a}
function e(a,b){var c,d={};p(a,function(a,e){A(a)?(c=a(b),null!=c&&(d[e]=c)):d[e]=a});return d}function g(a){var b=P({},a);b.data=yd(a.data,a.headers,a.status,f.transformResponse);a=a.status;return 200<=a&&300>a?b:h.reject(b)}if(!E(b))throw M("$http")("badreq",b);if(!D(m.valueOf(b.url)))throw M("$http")("badreq",b.url);var f=P({method:"get",transformRequest:a.transformRequest,transformResponse:a.transformResponse,paramSerializer:a.paramSerializer,jsonpCallbackParam:a.jsonpCallbackParam},b);f.headers=
function(b){var c=a.headers,d=P({},b.headers),g,f,h,c=P({},c.common,c[N(b.method)]);a:for(g in c){f=N(g);for(h in d)if(N(h)===f)continue a;d[g]=c[g]}return e(d,ja(b))}(b);f.method=wb(f.method);f.paramSerializer=D(f.paramSerializer)?l.get(f.paramSerializer):f.paramSerializer;c.$$incOutstandingRequestCount();var k=[],n=[];b=h.resolve(f);p(v,function(a){(a.request||a.requestError)&&k.unshift(a.request,a.requestError);(a.response||a.responseError)&&n.push(a.response,a.responseError)});b=d(b,k);b=b.then(function(b){var c=
b.headers,d=yd(b.data,xd(c),void 0,b.transformRequest);w(d)&&p(c,function(a,b){"content-type"===N(b)&&delete c[b]});w(b.withCredentials)&&!w(a.withCredentials)&&(b.withCredentials=a.withCredentials);return q(b,d).then(g,g)});b=d(b,n);return b=b.finally(function(){c.$$completeOutstandingRequest(C)})}function q(c,d){function g(a){if(a){var c={};p(a,function(a,d){c[d]=function(c){function d(){a(c)}b?k.$applyAsync(d):k.$$phase?d():k.$apply(d)}});return c}}function l(a,c,d,e,g){function f(){q(c,a,d,e,
g)}R&&(200<=a&&300>a?R.put(O,[a,c,wd(d),e,g]):R.remove(O));b?k.$applyAsync(f):(f(),k.$$phase||k.$apply())}function q(a,b,d,e,g){b=-1<=b?b:0;(200<=b&&300>b?K.resolve:K.reject)({data:a,status:b,headers:xd(d),config:c,statusText:e,xhrStatus:g})}function H(a){q(a.data,a.status,ja(a.headers()),a.statusText,a.xhrStatus)}function v(){var a=n.pendingRequests.indexOf(c);-1!==a&&n.pendingRequests.splice(a,1)}var K=h.defer(),F=K.promise,R,x,W=c.headers,r="jsonp"===N(c.method),O=c.url;r?O=m.getTrustedResourceUrl(O):
D(O)||(O=m.valueOf(O));O=G(O,c.paramSerializer(c.params));r&&(O=L(O,c.jsonpCallbackParam));n.pendingRequests.push(c);F.then(v,v);!c.cache&&!a.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(R=E(c.cache)?c.cache:E(a.cache)?a.cache:z);R&&(x=R.get(O),t(x)?x&&A(x.then)?x.then(H,H):I(x)?q(x[1],x[0],ja(x[2]),x[3],x[4]):q(x,200,{},"OK","complete"):R.put(O,F));w(x)&&((x=zd(c.url)?f()[c.xsrfCookieName||a.xsrfCookieName]:void 0)&&(W[c.xsrfHeaderName||a.xsrfHeaderName]=x),e(c.method,O,d,l,W,c.timeout,
c.withCredentials,c.responseType,g(c.eventHandlers),g(c.uploadEventHandlers)));return F}function G(a,b){0<b.length&&(a+=(-1===a.indexOf("?")?"?":"&")+b);return a}function L(a,b){if(/[&?][^=]+=JSON_CALLBACK/.test(a))throw rc("badjsonp",a);if((new RegExp("[&?]"+b+"=")).test(a))throw rc("badjsonp",b,a);return a+=(-1===a.indexOf("?")?"?":"&")+b+"=JSON_CALLBACK"}var z=g("$http");a.paramSerializer=D(a.paramSerializer)?l.get(a.paramSerializer):a.paramSerializer;var v=[];p(d,function(a){v.unshift(D(a)?l.get(a):
l.invoke(a))});n.pendingRequests=[];(function(a){p(arguments,function(a){n[a]=function(b,c){return n(P({},c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){p(arguments,function(a){n[a]=function(b,c,d){return n(P({},d||{},{method:a,url:b,data:c}))}})})("post","put","patch");n.defaults=a;return n}]}function Jf(){this.$get=function(){return function(){return new u.XMLHttpRequest}}}function If(){this.$get=["$browser","$jsonpCallbacks","$document","$xhrFactory",function(a,b,d,c){return yg(a,
c,a.defer,b,d[0])}]}function yg(a,b,d,c,e){function f(a,b,d){a=a.replace("JSON_CALLBACK",b);var f=e.createElement("script"),m=null;f.type="text/javascript";f.src=a;f.async=!0;m=function(a){f.removeEventListener("load",m);f.removeEventListener("error",m);e.body.removeChild(f);f=null;var g=-1,G="unknown";a&&("load"!==a.type||c.wasCalled(b)||(a={type:"error"}),G=a.type,g="error"===a.type?404:200);d&&d(g,G)};f.addEventListener("load",m);f.addEventListener("error",m);e.body.appendChild(f);return m}return function(e,
k,h,l,m,n,q,G,L,z){function v(){ma&&ma();y&&y.abort()}function s(a,b,c,e,g,f){t(H)&&d.cancel(H);ma=y=null;a(b,c,e,g,f)}k=k||a.url();if("jsonp"===N(e))var r=c.createCallback(k),ma=f(k,r,function(a,b){var d=200===a&&c.getResponse(r);s(l,a,d,"",b,"complete");c.removeCallback(r)});else{var y=b(e,k);y.open(e,k,!0);p(m,function(a,b){t(a)&&y.setRequestHeader(b,a)});y.onload=function(){var a=y.statusText||"",b="response"in y?y.response:y.responseText,c=1223===y.status?204:y.status;0===c&&(c=b?200:"file"===
ua(k).protocol?404:0);s(l,c,b,y.getAllResponseHeaders(),a,"complete")};y.onerror=function(){s(l,-1,null,null,"","error")};y.onabort=function(){s(l,-1,null,null,"","abort")};y.ontimeout=function(){s(l,-1,null,null,"","timeout")};p(L,function(a,b){y.addEventListener(b,a)});p(z,function(a,b){y.upload.addEventListener(b,a)});q&&(y.withCredentials=!0);if(G)try{y.responseType=G}catch(J){if("json"!==G)throw J;}y.send(w(h)?null:h)}if(0<n)var H=d(v,n);else n&&A(n.then)&&n.then(v)}}function Df(){var a="{{",
b="}}";this.startSymbol=function(b){return b?(a=b,this):a};this.endSymbol=function(a){return a?(b=a,this):b};this.$get=["$parse","$exceptionHandler","$sce",function(d,c,e){function f(a){return"\\\\\\"+a}function g(c){return c.replace(n,a).replace(q,b)}function k(a,b,c,d){var e=a.$watch(function(a){e();return d(a)},b,c);return e}function h(f,h,q,n){function s(a){try{var b=a;a=q?e.getTrusted(q,b):e.valueOf(b);return n&&!t(a)?a:dc(a)}catch(d){c(Fa.interr(f,d))}}if(!f.length||-1===f.indexOf(a)){var p;
h||(h=g(f),p=ka(h),p.exp=f,p.expressions=[],p.$$watchDelegate=k);return p}n=!!n;var r,y,J=0,H=[],ta=[];p=f.length;for(var K=[],F=[];J<p;)if(-1!==(r=f.indexOf(a,J))&&-1!==(y=f.indexOf(b,r+l)))J!==r&&K.push(g(f.substring(J,r))),J=f.substring(r+l,y),H.push(J),ta.push(d(J,s)),J=y+m,F.push(K.length),K.push("");else{J!==p&&K.push(g(f.substring(J)));break}q&&1<K.length&&Fa.throwNoconcat(f);if(!h||H.length){var R=function(a){for(var b=0,c=H.length;b<c;b++){if(n&&w(a[b]))return;K[F[b]]=a[b]}return K.join("")};
return P(function(a){var b=0,d=H.length,e=Array(d);try{for(;b<d;b++)e[b]=ta[b](a);return R(e)}catch(g){c(Fa.interr(f,g))}},{exp:f,expressions:H,$$watchDelegate:function(a,b){var c;return a.$watchGroup(ta,function(d,e){var g=R(d);A(b)&&b.call(this,g,d!==e?c:g,a);c=g})}})}}var l=a.length,m=b.length,n=new RegExp(a.replace(/./g,f),"g"),q=new RegExp(b.replace(/./g,f),"g");h.startSymbol=function(){return a};h.endSymbol=function(){return b};return h}]}function Ef(){this.$get=["$rootScope","$window","$q",
"$$q","$browser",function(a,b,d,c,e){function f(f,h,l,m){function n(){q?f.apply(null,G):f(v)}var q=4<arguments.length,G=q?ya.call(arguments,4):[],L=b.setInterval,p=b.clearInterval,v=0,s=t(m)&&!m,r=(s?c:d).defer(),ma=r.promise;l=t(l)?l:0;ma.$$intervalId=L(function(){s?e.defer(n):a.$evalAsync(n);r.notify(v++);0<l&&v>=l&&(r.resolve(v),p(ma.$$intervalId),delete g[ma.$$intervalId]);s||a.$apply()},h);g[ma.$$intervalId]=r;return ma}var g={};f.cancel=function(a){return a&&a.$$intervalId in g?(g[a.$$intervalId].promise.$$state.pur=
!0,g[a.$$intervalId].reject("canceled"),b.clearInterval(a.$$intervalId),delete g[a.$$intervalId],!0):!1};return f}]}function tc(a){a=a.split("/");for(var b=a.length;b--;)a[b]=gb(a[b]);return a.join("/")}function Ad(a,b){var d=ua(a);b.$$protocol=d.protocol;b.$$host=d.hostname;b.$$port=Z(d.port)||zg[d.protocol]||null}function Bd(a,b){if(Ag.test(a))throw mb("badpath",a);var d="/"!==a.charAt(0);d&&(a="/"+a);var c=ua(a);b.$$path=decodeURIComponent(d&&"/"===c.pathname.charAt(0)?c.pathname.substring(1):
c.pathname);b.$$search=Tc(c.search);b.$$hash=decodeURIComponent(c.hash);b.$$path&&"/"!==b.$$path.charAt(0)&&(b.$$path="/"+b.$$path)}function uc(a,b){return a.slice(0,b.length)===b}function va(a,b){if(uc(b,a))return b.substr(a.length)}function La(a){var b=a.indexOf("#");return-1===b?a:a.substr(0,b)}function nb(a){return a.replace(/(#.+)|#$/,"$1")}function vc(a,b,d){this.$$html5=!0;d=d||"";Ad(a,this);this.$$parse=function(a){var d=va(b,a);if(!D(d))throw mb("ipthprfx",a,b);Bd(d,this);this.$$path||(this.$$path=
"/");this.$$compose()};this.$$compose=function(){var a=cc(this.$$search),d=this.$$hash?"#"+gb(this.$$hash):"";this.$$url=tc(this.$$path)+(a?"?"+a:"")+d;this.$$absUrl=b+this.$$url.substr(1);this.$$urlUpdatedByLocation=!0};this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;t(f=va(a,c))?(g=f,g=d&&t(f=va(d,f))?b+(va("/",f)||f):a+g):t(f=va(b,c))?g=b+f:b===c+"/"&&(g=b);g&&this.$$parse(g);return!!g}}function wc(a,b,d){Ad(a,this);this.$$parse=function(c){var e=va(a,
c)||va(b,c),f;w(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",w(e)&&(a=c,this.replace())):(f=va(d,e),w(f)&&(f=e));Bd(f,this);c=this.$$path;var e=a,g=/^\/[A-Z]:(\/.*)/;uc(f,e)&&(f=f.replace(e,""));g.exec(f)||(c=(f=g.exec(c))?f[1]:c);this.$$path=c;this.$$compose()};this.$$compose=function(){var b=cc(this.$$search),e=this.$$hash?"#"+gb(this.$$hash):"";this.$$url=tc(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+(this.$$url?d+this.$$url:"");this.$$urlUpdatedByLocation=!0};this.$$parseLinkUrl=function(b,d){return La(a)===
La(b)?(this.$$parse(b),!0):!1}}function Cd(a,b,d){this.$$html5=!0;wc.apply(this,arguments);this.$$parseLinkUrl=function(c,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;a===La(c)?f=c:(g=va(b,c))?f=a+d+g:b===c+"/"&&(f=b);f&&this.$$parse(f);return!!f};this.$$compose=function(){var b=cc(this.$$search),e=this.$$hash?"#"+gb(this.$$hash):"";this.$$url=tc(this.$$path)+(b?"?"+b:"")+e;this.$$absUrl=a+d+this.$$url;this.$$urlUpdatedByLocation=!0}}function Lb(a){return function(){return this[a]}}
function Dd(a,b){return function(d){if(w(d))return this[a];this[a]=b(d);this.$$compose();return this}}function Lf(){var a="!",b={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(b){return t(b)?(a=b,this):a};this.html5Mode=function(a){if(Na(a))return b.enabled=a,this;if(E(a)){Na(a.enabled)&&(b.enabled=a.enabled);Na(a.requireBase)&&(b.requireBase=a.requireBase);if(Na(a.rewriteLinks)||D(a.rewriteLinks))b.rewriteLinks=a.rewriteLinks;return this}return b};this.$get=["$rootScope","$browser",
"$sniffer","$rootElement","$window",function(d,c,e,f,g){function k(a,b,d){var e=l.url(),g=l.$$state;try{c.url(a,b,d),l.$$state=c.state()}catch(f){throw l.url(e),l.$$state=g,f;}}function h(a,b){d.$broadcast("$locationChangeSuccess",l.absUrl(),a,l.$$state,b)}var l,m;m=c.baseHref();var n=c.url(),q;if(b.enabled){if(!m&&b.requireBase)throw mb("nobase");q=n.substring(0,n.indexOf("/",n.indexOf("//")+2))+(m||"/");m=e.history?vc:Cd}else q=La(n),m=wc;var G=q.substr(0,La(q).lastIndexOf("/")+1);l=new m(q,G,"#"+
a);l.$$parseLinkUrl(n,n);l.$$state=c.state();var p=/^\s*(javascript|mailto):/i;f.on("click",function(a){var e=b.rewriteLinks;if(e&&!a.ctrlKey&&!a.metaKey&&!a.shiftKey&&2!==a.which&&2!==a.button){for(var h=B(a.target);"a"!==za(h[0]);)if(h[0]===f[0]||!(h=h.parent())[0])return;if(!D(e)||!w(h.attr(e))){var e=h.prop("href"),k=h.attr("href")||h.attr("xlink:href");E(e)&&"[object SVGAnimatedString]"===e.toString()&&(e=ua(e.animVal).href);p.test(e)||!e||h.attr("target")||a.isDefaultPrevented()||!l.$$parseLinkUrl(e,
k)||(a.preventDefault(),l.absUrl()!==c.url()&&(d.$apply(),g.angular["ff-684208-preventDefault"]=!0))}}});nb(l.absUrl())!==nb(n)&&c.url(l.absUrl(),!0);var z=!0;c.onUrlChange(function(a,b){uc(a,G)?(d.$evalAsync(function(){var c=l.absUrl(),e=l.$$state,g;a=nb(a);l.$$parse(a);l.$$state=b;g=d.$broadcast("$locationChangeStart",a,c,b,e).defaultPrevented;l.absUrl()===a&&(g?(l.$$parse(c),l.$$state=e,k(c,!1,e)):(z=!1,h(c,e)))}),d.$$phase||d.$digest()):g.location.href=a});d.$watch(function(){if(z||l.$$urlUpdatedByLocation){l.$$urlUpdatedByLocation=
!1;var a=nb(c.url()),b=nb(l.absUrl()),g=c.state(),f=l.$$replace,m=a!==b||l.$$html5&&e.history&&g!==l.$$state;if(z||m)z=!1,d.$evalAsync(function(){var b=l.absUrl(),c=d.$broadcast("$locationChangeStart",b,a,l.$$state,g).defaultPrevented;l.absUrl()===b&&(c?(l.$$parse(a),l.$$state=g):(m&&k(b,f,g===l.$$state?null:l.$$state),h(a,g)))})}l.$$replace=!1});return l}]}function Mf(){var a=!0,b=this;this.debugEnabled=function(b){return t(b)?(a=b,this):a};this.$get=["$window",function(d){function c(a){$b(a)&&(a.stack&&
f?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=d.console||{},e=b[a]||b.log||C;return function(){var a=[];p(arguments,function(b){a.push(c(b))});return Function.prototype.apply.call(e,b,a)}}var f=Ca||/\bEdge\//.test(d.navigator&&d.navigator.userAgent);return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){a&&c.apply(b,
arguments)}}()}}]}function Bg(a){return a+""}function Cg(a,b){return"undefined"!==typeof a?a:b}function Ed(a,b){return"undefined"===typeof a?b:"undefined"===typeof b?a:a+b}function Dg(a,b){switch(a.type){case r.MemberExpression:if(a.computed)return!1;break;case r.UnaryExpression:return 1;case r.BinaryExpression:return"+"!==a.operator?1:!1;case r.CallExpression:return!1}return void 0===b?Fd:b}function V(a,b,d){var c,e,f=a.isPure=Dg(a,d);switch(a.type){case r.Program:c=!0;p(a.body,function(a){V(a.expression,
b,f);c=c&&a.expression.constant});a.constant=c;break;case r.Literal:a.constant=!0;a.toWatch=[];break;case r.UnaryExpression:V(a.argument,b,f);a.constant=a.argument.constant;a.toWatch=a.argument.toWatch;break;case r.BinaryExpression:V(a.left,b,f);V(a.right,b,f);a.constant=a.left.constant&&a.right.constant;a.toWatch=a.left.toWatch.concat(a.right.toWatch);break;case r.LogicalExpression:V(a.left,b,f);V(a.right,b,f);a.constant=a.left.constant&&a.right.constant;a.toWatch=a.constant?[]:[a];break;case r.ConditionalExpression:V(a.test,
b,f);V(a.alternate,b,f);V(a.consequent,b,f);a.constant=a.test.constant&&a.alternate.constant&&a.consequent.constant;a.toWatch=a.constant?[]:[a];break;case r.Identifier:a.constant=!1;a.toWatch=[a];break;case r.MemberExpression:V(a.object,b,f);a.computed&&V(a.property,b,f);a.constant=a.object.constant&&(!a.computed||a.property.constant);a.toWatch=a.constant?[]:[a];break;case r.CallExpression:c=d=a.filter?!b(a.callee.name).$stateful:!1;e=[];p(a.arguments,function(a){V(a,b,f);c=c&&a.constant;e.push.apply(e,
a.toWatch)});a.constant=c;a.toWatch=d?e:[a];break;case r.AssignmentExpression:V(a.left,b,f);V(a.right,b,f);a.constant=a.left.constant&&a.right.constant;a.toWatch=[a];break;case r.ArrayExpression:c=!0;e=[];p(a.elements,function(a){V(a,b,f);c=c&&a.constant;e.push.apply(e,a.toWatch)});a.constant=c;a.toWatch=e;break;case r.ObjectExpression:c=!0;e=[];p(a.properties,function(a){V(a.value,b,f);c=c&&a.value.constant;e.push.apply(e,a.value.toWatch);a.computed&&(V(a.key,b,!1),c=c&&a.key.constant,e.push.apply(e,
a.key.toWatch))});a.constant=c;a.toWatch=e;break;case r.ThisExpression:a.constant=!1;a.toWatch=[];break;case r.LocalsExpression:a.constant=!1,a.toWatch=[]}}function Gd(a){if(1===a.length){a=a[0].expression;var b=a.toWatch;return 1!==b.length?b:b[0]!==a?b:void 0}}function Hd(a){return a.type===r.Identifier||a.type===r.MemberExpression}function Id(a){if(1===a.body.length&&Hd(a.body[0].expression))return{type:r.AssignmentExpression,left:a.body[0].expression,right:{type:r.NGValueParameter},operator:"="}}
function Jd(a){this.$filter=a}function Kd(a){this.$filter=a}function xc(a,b,d){this.ast=new r(a,d);this.astCompiler=d.csp?new Kd(b):new Jd(b)}function yc(a){return A(a.valueOf)?a.valueOf():Eg.call(a)}function Nf(){var a=S(),b={"true":!0,"false":!1,"null":null,undefined:void 0},d,c;this.addLiteral=function(a,c){b[a]=c};this.setIdentifierFns=function(a,b){d=a;c=b;return this};this.$get=["$filter",function(e){function f(a,b,c){return null==a||null==b?a===b:"object"!==typeof a||(a=yc(a),"object"!==typeof a||
c)?a===b||a!==a&&b!==b:!1}function g(a,b,c,d,e){var g=d.inputs,h;if(1===g.length){var k=f,g=g[0];return a.$watch(function(a){var b=g(a);f(b,k,g.isPure)||(h=d(a,void 0,void 0,[b]),k=b&&yc(b));return h},b,c,e)}for(var l=[],m=[],n=0,p=g.length;n<p;n++)l[n]=f,m[n]=null;return a.$watch(function(a){for(var b=!1,c=0,e=g.length;c<e;c++){var k=g[c](a);if(b||(b=!f(k,l[c],g[c].isPure)))m[c]=k,l[c]=k&&yc(k)}b&&(h=d(a,void 0,void 0,m));return h},b,c,e)}function k(a,b,c,d,e){function f(a){return d(a)}function h(a,
c,d){l=a;A(b)&&b(a,c,d);t(a)&&d.$$postDigest(function(){t(l)&&k()})}var k,l;return k=d.inputs?g(a,h,c,d,e):a.$watch(f,h,c)}function h(a,b,c,d){function e(a){var b=!0;p(a,function(a){t(a)||(b=!1)});return b}var g,f;return g=a.$watch(function(a){return d(a)},function(a,c,d){f=a;A(b)&&b(a,c,d);e(a)&&d.$$postDigest(function(){e(f)&&g()})},c)}function l(a,b,c,d){var e=a.$watch(function(a){e();return d(a)},b,c);return e}function m(a,b){if(!b)return a;var c=a.$$watchDelegate,d=!1,e=c!==h&&c!==k?function(c,
e,g,f){g=d&&f?f[0]:a(c,e,g,f);return b(g,c,e)}:function(c,d,e,g){e=a(c,d,e,g);c=b(e,c,d);return t(e)?c:e},d=!a.inputs;c&&c!==g?(e.$$watchDelegate=c,e.inputs=a.inputs):b.$stateful||(e.$$watchDelegate=g,e.inputs=a.inputs?a.inputs:[a]);e.inputs&&(e.inputs=e.inputs.map(function(a){return a.isPure===Fd?function(b){return a(b)}:a}));return e}var n={csp:Ja().noUnsafeEval,literals:pa(b),isIdentifierStart:A(d)&&d,isIdentifierContinue:A(c)&&c};return function(b,c){var d,f,p;switch(typeof b){case "string":return p=
b=b.trim(),d=a[p],d||(":"===b.charAt(0)&&":"===b.charAt(1)&&(f=!0,b=b.substring(2)),d=new zc(n),d=(new xc(d,e,n)).parse(b),d.constant?d.$$watchDelegate=l:f?d.$$watchDelegate=d.literal?h:k:d.inputs&&(d.$$watchDelegate=g),a[p]=d),m(d,c);case "function":return m(b,c);default:return m(C,c)}}}]}function Pf(){var a=!0;this.$get=["$rootScope","$exceptionHandler",function(b,d){return Ld(function(a){b.$evalAsync(a)},d,a)}];this.errorOnUnhandledRejections=function(b){return t(b)?(a=b,this):a}}function Qf(){var a=
!0;this.$get=["$browser","$exceptionHandler",function(b,d){return Ld(function(a){b.defer(a)},d,a)}];this.errorOnUnhandledRejections=function(b){return t(b)?(a=b,this):a}}function Ld(a,b,d){function c(){return new e}function e(){var a=this.promise=new f;this.resolve=function(b){h(a,b)};this.reject=function(b){m(a,b)};this.notify=function(b){q(a,b)}}function f(){this.$$state={status:0}}function g(){for(;!t&&u.length;){var a=u.shift();if(!a.pur){a.pur=!0;var c=a.value,c="Possibly unhandled rejection: "+
("function"===typeof c?c.toString().replace(/ \{[\s\S]*$/,""):w(c)?"undefined":"string"!==typeof c?De(c,void 0):c);$b(a.value)?b(a.value,c):b(c)}}}function k(b){!d||b.pending||2!==b.status||b.pur||(0===t&&0===u.length&&a(g),u.push(b));!b.processScheduled&&b.pending&&(b.processScheduled=!0,++t,a(function(){var c,e,f;f=b.pending;b.processScheduled=!1;b.pending=void 0;try{for(var k=0,l=f.length;k<l;++k){b.pur=!0;e=f[k][0];c=f[k][b.status];try{A(c)?h(e,c(b.value)):1===b.status?h(e,b.value):m(e,b.value)}catch(n){m(e,
n)}}}finally{--t,d&&0===t&&a(g)}}))}function h(a,b){a.$$state.status||(b===a?n(a,s("qcycle",b)):l(a,b))}function l(a,b){function c(b){f||(f=!0,l(a,b))}function d(b){f||(f=!0,n(a,b))}function e(b){q(a,b)}var g,f=!1;try{if(E(b)||A(b))g=b.then;A(g)?(a.$$state.status=-1,g.call(b,c,d,e)):(a.$$state.value=b,a.$$state.status=1,k(a.$$state))}catch(h){d(h)}}function m(a,b){a.$$state.status||n(a,b)}function n(a,b){a.$$state.value=b;a.$$state.status=2;k(a.$$state)}function q(c,d){var e=c.$$state.pending;0>=
c.$$state.status&&e&&e.length&&a(function(){for(var a,c,g=0,f=e.length;g<f;g++){c=e[g][0];a=e[g][3];try{q(c,A(a)?a(d):d)}catch(h){b(h)}}})}function G(a){var b=new f;m(b,a);return b}function r(a,b,c){var d=null;try{A(c)&&(d=c())}catch(e){return G(e)}return d&&A(d.then)?d.then(function(){return b(a)},G):b(a)}function z(a,b,c,d){var e=new f;h(e,a);return e.then(b,c,d)}function v(a){if(!A(a))throw s("norslvr",a);var b=new f;a(function(a){h(b,a)},function(a){m(b,a)});return b}var s=M("$q",TypeError),t=
0,u=[];P(f.prototype,{then:function(a,b,c){if(w(a)&&w(b)&&w(c))return this;var d=new f;this.$$state.pending=this.$$state.pending||[];this.$$state.pending.push([d,a,b,c]);0<this.$$state.status&&k(this.$$state);return d},"catch":function(a){return this.then(null,a)},"finally":function(a,b){return this.then(function(b){return r(b,y,a)},function(b){return r(b,G,a)},b)}});var y=z;v.prototype=f.prototype;v.defer=c;v.reject=G;v.when=z;v.resolve=y;v.all=function(a){var b=new f,c=0,d=I(a)?[]:{};p(a,function(a,
e){c++;z(a).then(function(a){d[e]=a;--c||h(b,d)},function(a){m(b,a)})});0===c&&h(b,d);return b};v.race=function(a){var b=c();p(a,function(a){z(a).then(b.resolve,b.reject)});return b.promise};return v}function Zf(){this.$get=["$window","$timeout",function(a,b){var d=a.requestAnimationFrame||a.webkitRequestAnimationFrame,c=a.cancelAnimationFrame||a.webkitCancelAnimationFrame||a.webkitCancelRequestAnimationFrame,e=!!d,f=e?function(a){var b=d(a);return function(){c(b)}}:function(a){var c=b(a,16.66,!1);
return function(){b.cancel(c)}};f.supported=e;return f}]}function Of(){function a(a){function b(){this.$$watchers=this.$$nextSibling=this.$$childHead=this.$$childTail=null;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$id=++sb;this.$$ChildScope=null}b.prototype=a;return b}var b=10,d=M("$rootScope"),c=null,e=null;this.digestTtl=function(a){arguments.length&&(b=a);return b};this.$get=["$exceptionHandler","$parse","$browser",function(f,g,k){function h(a){a.currentScope.$$destroyed=
!0}function l(a){9===Ca&&(a.$$childHead&&l(a.$$childHead),a.$$nextSibling&&l(a.$$nextSibling));a.$parent=a.$$nextSibling=a.$$prevSibling=a.$$childHead=a.$$childTail=a.$root=a.$$watchers=null}function m(){this.$id=++sb;this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=null;this.$root=this;this.$$destroyed=!1;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$$isolateBindings=null}function n(a){if(s.$$phase)throw d("inprog",
s.$$phase);s.$$phase=a}function q(a,b){do a.$$watchersCount+=b;while(a=a.$parent)}function G(a,b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function r(){}function z(){for(;y.length;)try{y.shift()()}catch(a){f(a)}e=null}function v(){null===e&&(e=k.defer(function(){s.$apply(z)}))}m.prototype={constructor:m,$new:function(b,c){var d;c=c||this;b?(d=new m,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=a(this)),d=new this.$$ChildScope);
d.$parent=c;d.$$prevSibling=c.$$childTail;c.$$childHead?(c.$$childTail.$$nextSibling=d,c.$$childTail=d):c.$$childHead=c.$$childTail=d;(b||c!==this)&&d.$on("$destroy",h);return d},$watch:function(a,b,d,e){var f=g(a);if(f.$$watchDelegate)return f.$$watchDelegate(this,b,d,f,a);var h=this,k=h.$$watchers,l={fn:b,last:r,get:f,exp:e||a,eq:!!d};c=null;A(b)||(l.fn=C);k||(k=h.$$watchers=[],k.$$digestWatchIndex=-1);k.unshift(l);k.$$digestWatchIndex++;q(this,1);return function(){var a=db(k,l);0<=a&&(q(h,-1),
a<k.$$digestWatchIndex&&k.$$digestWatchIndex--);c=null}},$watchGroup:function(a,b){function c(){h=!1;k?(k=!1,b(e,e,f)):b(e,d,f)}var d=Array(a.length),e=Array(a.length),g=[],f=this,h=!1,k=!0;if(!a.length){var l=!0;f.$evalAsync(function(){l&&b(e,e,f)});return function(){l=!1}}if(1===a.length)return this.$watch(a[0],function(a,c,g){e[0]=a;d[0]=c;b(e,a===c?e:d,g)});p(a,function(a,b){var k=f.$watch(a,function(a,g){e[b]=a;d[b]=g;h||(h=!0,f.$evalAsync(c))});g.push(k)});return function(){for(;g.length;)g.shift()()}},
$watchCollection:function(a,b){function c(a){e=a;var b,d,g,h;if(!w(e)){if(E(e))if(xa(e))for(f!==n&&(f=n,p=f.length=0,l++),a=e.length,p!==a&&(l++,f.length=p=a),b=0;b<a;b++)h=f[b],g=e[b],d=h!==h&&g!==g,d||h===g||(l++,f[b]=g);else{f!==q&&(f=q={},p=0,l++);a=0;for(b in e)ra.call(e,b)&&(a++,g=e[b],h=f[b],b in f?(d=h!==h&&g!==g,d||h===g||(l++,f[b]=g)):(p++,f[b]=g,l++));if(p>a)for(b in l++,f)ra.call(e,b)||(p--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,h,k=1<b.length,l=0,m=
g(a,c),n=[],q={},s=!0,p=0;return this.$watch(m,function(){s?(s=!1,b(e,e,d)):b(e,h,d);if(k)if(E(e))if(xa(e)){h=Array(e.length);for(var a=0;a<e.length;a++)h[a]=e[a]}else for(a in h={},e)ra.call(e,a)&&(h[a]=e[a]);else h=e})},$digest:function(){var a,g,h,l,m,q,p,G=b,y,v=[],w,B;n("$digest");k.$$checkUrlChange();this===s&&null!==e&&(k.defer.cancel(e),z());c=null;do{p=!1;y=this;for(q=0;q<t.length;q++){try{B=t[q],l=B.fn,l(B.scope,B.locals)}catch(C){f(C)}c=null}t.length=0;a:do{if(q=y.$$watchers)for(q.$$digestWatchIndex=
q.length;q.$$digestWatchIndex--;)try{if(a=q[q.$$digestWatchIndex])if(m=a.get,(g=m(y))!==(h=a.last)&&!(a.eq?sa(g,h):T(g)&&T(h)))p=!0,c=a,a.last=a.eq?pa(g,null):g,l=a.fn,l(g,h===r?g:h,y),5>G&&(w=4-G,v[w]||(v[w]=[]),v[w].push({msg:A(a.exp)?"fn: "+(a.exp.name||a.exp.toString()):a.exp,newVal:g,oldVal:h}));else if(a===c){p=!1;break a}}catch(E){f(E)}if(!(q=y.$$watchersCount&&y.$$childHead||y!==this&&y.$$nextSibling))for(;y!==this&&!(q=y.$$nextSibling);)y=y.$parent}while(y=q);if((p||t.length)&&!G--)throw s.$$phase=
null,d("infdig",b,v);}while(p||t.length);for(s.$$phase=null;J<u.length;)try{u[J++]()}catch(D){f(D)}u.length=J=0;k.$$checkUrlChange()},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this===s&&k.$$applicationDestroyed();q(this,-this.$$watchersCount);for(var b in this.$$listenerCount)G(this,this.$$listenerCount[b],b);a&&a.$$childHead===this&&(a.$$childHead=this.$$nextSibling);a&&a.$$childTail===this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&
(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=C;this.$on=this.$watch=this.$watchGroup=function(){return C};this.$$listeners={};this.$$nextSibling=null;l(this)}},$eval:function(a,b){return g(a)(this,b)},$evalAsync:function(a,b){s.$$phase||t.length||k.defer(function(){t.length&&s.$digest()});t.push({scope:this,fn:g(a),locals:b})},$$postDigest:function(a){u.push(a)},
$apply:function(a){try{n("$apply");try{return this.$eval(a)}finally{s.$$phase=null}}catch(b){f(b)}finally{try{s.$digest()}catch(c){throw f(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&y.push(b);a=g(a);v()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,G(e,1,a))}},$emit:function(a,
b){var c=[],d,e=this,g=!1,h={name:a,targetScope:e,stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=eb([h],arguments,1),l,m;do{d=e.$$listeners[a]||c;h.currentScope=e;l=0;for(m=d.length;l<m;l++)if(d[l])try{d[l].apply(null,k)}catch(n){f(n)}else d.splice(l,1),l--,m--;if(g)return h.currentScope=null,h;e=e.$parent}while(e);h.currentScope=null;return h},$broadcast:function(a,b){var c=this,d=this,e={name:a,targetScope:this,preventDefault:function(){e.defaultPrevented=
!0},defaultPrevented:!1};if(!this.$$listenerCount[a])return e;for(var g=eb([e],arguments,1),h,k;c=d;){e.currentScope=c;d=c.$$listeners[a]||[];h=0;for(k=d.length;h<k;h++)if(d[h])try{d[h].apply(null,g)}catch(l){f(l)}else d.splice(h,1),h--,k--;if(!(d=c.$$listenerCount[a]&&c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d=c.$$nextSibling);)c=c.$parent}e.currentScope=null;return e}};var s=new m,t=s.$$asyncQueue=[],u=s.$$postDigestQueue=[],y=s.$$applyAsyncQueue=[],J=0;return s}]}function Ge(){var a=
/^\s*(https?|ftp|mailto|tel|file):/,b=/^\s*((https?|ftp|file|blob):|data:image\/)/;this.aHrefSanitizationWhitelist=function(b){return t(b)?(a=b,this):a};this.imgSrcSanitizationWhitelist=function(a){return t(a)?(b=a,this):b};this.$get=function(){return function(d,c){var e=c?b:a,f;f=ua(d).href;return""===f||f.match(e)?d:"unsafe:"+f}}}function Fg(a){if("self"===a)return a;if(D(a)){if(-1<a.indexOf("***"))throw wa("iwcard",a);a=Md(a).replace(/\\\*\\\*/g,".*").replace(/\\\*/g,"[^:/.?&;]*");return new RegExp("^"+
a+"$")}if(ab(a))return new RegExp("^"+a.source+"$");throw wa("imatcher");}function Nd(a){var b=[];t(a)&&p(a,function(a){b.push(Fg(a))});return b}function Sf(){this.SCE_CONTEXTS=oa;var a=["self"],b=[];this.resourceUrlWhitelist=function(b){arguments.length&&(a=Nd(b));return a};this.resourceUrlBlacklist=function(a){arguments.length&&(b=Nd(a));return b};this.$get=["$injector",function(d){function c(a,b){return"self"===a?zd(b):!!a.exec(b.href)}function e(a){var b=function(a){this.$$unwrapTrustedValue=
function(){return a}};a&&(b.prototype=new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()};b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};return b}var f=function(a){throw wa("unsafe");};d.has("$sanitize")&&(f=d.get("$sanitize"));var g=e(),k={};k[oa.HTML]=e(g);k[oa.CSS]=e(g);k[oa.URL]=e(g);k[oa.JS]=e(g);k[oa.RESOURCE_URL]=e(k[oa.URL]);return{trustAs:function(a,b){var c=k.hasOwnProperty(a)?k[a]:null;if(!c)throw wa("icontext",a,b);if(null===b||w(b)||
""===b)return b;if("string"!==typeof b)throw wa("itype",a);return new c(b)},getTrusted:function(d,e){if(null===e||w(e)||""===e)return e;var g=k.hasOwnProperty(d)?k[d]:null;if(g&&e instanceof g)return e.$$unwrapTrustedValue();if(d===oa.RESOURCE_URL){var g=ua(e.toString()),n,q,p=!1;n=0;for(q=a.length;n<q;n++)if(c(a[n],g)){p=!0;break}if(p)for(n=0,q=b.length;n<q;n++)if(c(b[n],g)){p=!1;break}if(p)return e;throw wa("insecurl",e.toString());}if(d===oa.HTML)return f(e);throw wa("unsafe");},valueOf:function(a){return a instanceof
g?a.$$unwrapTrustedValue():a}}}]}function Rf(){var a=!0;this.enabled=function(b){arguments.length&&(a=!!b);return a};this.$get=["$parse","$sceDelegate",function(b,d){if(a&&8>Ca)throw wa("iequirks");var c=ja(oa);c.isEnabled=function(){return a};c.trustAs=d.trustAs;c.getTrusted=d.getTrusted;c.valueOf=d.valueOf;a||(c.trustAs=c.getTrusted=function(a,b){return b},c.valueOf=bb);c.parseAs=function(a,d){var e=b(d);return e.literal&&e.constant?e:b(d,function(b){return c.getTrusted(a,b)})};var e=c.parseAs,
f=c.getTrusted,g=c.trustAs;p(oa,function(a,b){var d=N(b);c[("parse_as_"+d).replace(Ac,jb)]=function(b){return e(a,b)};c[("get_trusted_"+d).replace(Ac,jb)]=function(b){return f(a,b)};c[("trust_as_"+d).replace(Ac,jb)]=function(b){return g(a,b)}});return c}]}function Tf(){this.$get=["$window","$document",function(a,b){var d={},c=!((!a.nw||!a.nw.process)&&a.chrome&&(a.chrome.app&&a.chrome.app.runtime||!a.chrome.app&&a.chrome.runtime&&a.chrome.runtime.id))&&a.history&&a.history.pushState,e=Z((/android (\d+)/.exec(N((a.navigator||
{}).userAgent))||[])[1]),f=/Boxee/i.test((a.navigator||{}).userAgent),g=b[0]||{},k=g.body&&g.body.style,h=!1,l=!1;k&&(h=!!("transition"in k||"webkitTransition"in k),l=!!("animation"in k||"webkitAnimation"in k));return{history:!(!c||4>e||f),hasEvent:function(a){if("input"===a&&Ca)return!1;if(w(d[a])){var b=g.createElement("div");d[a]="on"+a in b}return d[a]},csp:Ja(),transitions:h,animations:l,android:e}}]}function Vf(){var a;this.httpOptions=function(b){return b?(a=b,this):a};this.$get=["$exceptionHandler",
"$templateCache","$http","$q","$sce",function(b,d,c,e,f){function g(k,h){g.totalPendingRequests++;if(!D(k)||w(d.get(k)))k=f.getTrustedResourceUrl(k);var l=c.defaults&&c.defaults.transformResponse;I(l)?l=l.filter(function(a){return a!==qc}):l===qc&&(l=null);return c.get(k,P({cache:d,transformResponse:l},a)).finally(function(){g.totalPendingRequests--}).then(function(a){d.put(k,a.data);return a.data},function(a){h||(a=Gg("tpload",k,a.status,a.statusText),b(a));return e.reject(a)})}g.totalPendingRequests=
0;return g}]}function Wf(){this.$get=["$rootScope","$browser","$location",function(a,b,d){return{findBindings:function(a,b,d){a=a.getElementsByClassName("ng-binding");var g=[];p(a,function(a){var c=$.element(a).data("$binding");c&&p(c,function(c){d?(new RegExp("(^|\\s)"+Md(b)+"(\\s|\\||$)")).test(c)&&g.push(a):-1!==c.indexOf(b)&&g.push(a)})});return g},findModels:function(a,b,d){for(var g=["ng-","data-ng-","ng\\:"],k=0;k<g.length;++k){var h=a.querySelectorAll("["+g[k]+"model"+(d?"=":"*=")+'"'+b+'"]');
if(h.length)return h}},getLocation:function(){return d.url()},setLocation:function(b){b!==d.url()&&(d.url(b),a.$digest())},whenStable:function(a){b.notifyWhenNoOutstandingRequests(a)}}}]}function Xf(){this.$get=["$rootScope","$browser","$q","$$q","$exceptionHandler",function(a,b,d,c,e){function f(f,h,l){A(f)||(l=h,h=f,f=C);var m=ya.call(arguments,3),n=t(l)&&!l,q=(n?c:d).defer(),p=q.promise,r;r=b.defer(function(){try{q.resolve(f.apply(null,m))}catch(b){q.reject(b),e(b)}finally{delete g[p.$$timeoutId]}n||
a.$apply()},h);p.$$timeoutId=r;g[r]=q;return p}var g={};f.cancel=function(a){return a&&a.$$timeoutId in g?(g[a.$$timeoutId].promise.$$state.pur=!0,g[a.$$timeoutId].reject("canceled"),delete g[a.$$timeoutId],b.defer.cancel(a.$$timeoutId)):!1};return f}]}function ua(a){Ca&&(X.setAttribute("href",a),a=X.href);X.setAttribute("href",a);return{href:X.href,protocol:X.protocol?X.protocol.replace(/:$/,""):"",host:X.host,search:X.search?X.search.replace(/^\?/,""):"",hash:X.hash?X.hash.replace(/^#/,""):"",hostname:X.hostname,
port:X.port,pathname:"/"===X.pathname.charAt(0)?X.pathname:"/"+X.pathname}}function zd(a){a=D(a)?ua(a):a;return a.protocol===Od.protocol&&a.host===Od.host}function Yf(){this.$get=ka(u)}function Pd(a){function b(a){try{return decodeURIComponent(a)}catch(b){return a}}var d=a[0]||{},c={},e="";return function(){var a,g,k,h,l;try{a=d.cookie||""}catch(m){a=""}if(a!==e)for(e=a,a=e.split("; "),c={},k=0;k<a.length;k++)g=a[k],h=g.indexOf("="),0<h&&(l=b(g.substring(0,h)),w(c[l])&&(c[l]=b(g.substring(h+1))));
return c}}function bg(){this.$get=Pd}function ed(a){function b(d,c){if(E(d)){var e={};p(d,function(a,c){e[c]=b(c,a)});return e}return a.factory(d+"Filter",c)}this.register=b;this.$get=["$injector",function(a){return function(b){return a.get(b+"Filter")}}];b("currency",Qd);b("date",Rd);b("filter",Hg);b("json",Ig);b("limitTo",Jg);b("lowercase",Kg);b("number",Sd);b("orderBy",Td);b("uppercase",Lg)}function Hg(){return function(a,b,d,c){if(!xa(a)){if(null==a)return a;throw M("filter")("notarray",a);}c=
c||"$";var e;switch(Bc(b)){case "function":break;case "boolean":case "null":case "number":case "string":e=!0;case "object":b=Mg(b,d,c,e);break;default:return a}return Array.prototype.filter.call(a,b)}}function Mg(a,b,d,c){var e=E(a)&&d in a;!0===b?b=sa:A(b)||(b=function(a,b){if(w(a))return!1;if(null===a||null===b)return a===b;if(E(b)||E(a)&&!Zb(a))return!1;a=N(""+a);b=N(""+b);return-1!==a.indexOf(b)});return function(f){return e&&!E(f)?ga(f,a[d],b,d,!1):ga(f,a,b,d,c)}}function ga(a,b,d,c,e,f){var g=
Bc(a),k=Bc(b);if("string"===k&&"!"===b.charAt(0))return!ga(a,b.substring(1),d,c,e);if(I(a))return a.some(function(a){return ga(a,b,d,c,e)});switch(g){case "object":var h;if(e){for(h in a)if(h.charAt&&"$"!==h.charAt(0)&&ga(a[h],b,d,c,!0))return!0;return f?!1:ga(a,b,d,c,!1)}if("object"===k){for(h in b)if(f=b[h],!A(f)&&!w(f)&&(g=h===c,!ga(g?a:a[h],f,d,c,g,g)))return!1;return!0}return d(a,b);case "function":return!1;default:return d(a,b)}}function Bc(a){return null===a?"null":typeof a}function Qd(a){var b=
a.NUMBER_FORMATS;return function(a,c,e){w(c)&&(c=b.CURRENCY_SYM);w(e)&&(e=b.PATTERNS[1].maxFrac);return null==a?a:Ud(a,b.PATTERNS[1],b.GROUP_SEP,b.DECIMAL_SEP,e).replace(/\u00A4/g,c)}}function Sd(a){var b=a.NUMBER_FORMATS;return function(a,c){return null==a?a:Ud(a,b.PATTERNS[0],b.GROUP_SEP,b.DECIMAL_SEP,c)}}function Ng(a){var b=0,d,c,e,f,g;-1<(c=a.indexOf(Vd))&&(a=a.replace(Vd,""));0<(e=a.search(/e/i))?(0>c&&(c=e),c+=+a.slice(e+1),a=a.substring(0,e)):0>c&&(c=a.length);for(e=0;a.charAt(e)===Cc;e++);
if(e===(g=a.length))d=[0],c=1;else{for(g--;a.charAt(g)===Cc;)g--;c-=e;d=[];for(f=0;e<=g;e++,f++)d[f]=+a.charAt(e)}c>Wd&&(d=d.splice(0,Wd-1),b=c-1,c=1);return{d:d,e:b,i:c}}function Og(a,b,d,c){var e=a.d,f=e.length-a.i;b=w(b)?Math.min(Math.max(d,f),c):+b;d=b+a.i;c=e[d];if(0<d){e.splice(Math.max(a.i,d));for(var g=d;g<e.length;g++)e[g]=0}else for(f=Math.max(0,f),a.i=1,e.length=Math.max(1,d=b+1),e[0]=0,g=1;g<d;g++)e[g]=0;if(5<=c)if(0>d-1){for(c=0;c>d;c--)e.unshift(0),a.i++;e.unshift(1);a.i++}else e[d-
1]++;for(;f<Math.max(0,b);f++)e.push(0);if(b=e.reduceRight(function(a,b,c,d){b+=a;d[c]=b%10;return Math.floor(b/10)},0))e.unshift(b),a.i++}function Ud(a,b,d,c,e){if(!D(a)&&!Y(a)||isNaN(a))return"";var f=!isFinite(a),g=!1,k=Math.abs(a)+"",h="";if(f)h="\u221e";else{g=Ng(k);Og(g,e,b.minFrac,b.maxFrac);h=g.d;k=g.i;e=g.e;f=[];for(g=h.reduce(function(a,b){return a&&!b},!0);0>k;)h.unshift(0),k++;0<k?f=h.splice(k,h.length):(f=h,h=[0]);k=[];for(h.length>=b.lgSize&&k.unshift(h.splice(-b.lgSize,h.length).join(""));h.length>
b.gSize;)k.unshift(h.splice(-b.gSize,h.length).join(""));h.length&&k.unshift(h.join(""));h=k.join(d);f.length&&(h+=c+f.join(""));e&&(h+="e+"+e)}return 0>a&&!g?b.negPre+h+b.negSuf:b.posPre+h+b.posSuf}function Mb(a,b,d,c){var e="";if(0>a||c&&0>=a)c?a=-a+1:(a=-a,e="-");for(a=""+a;a.length<b;)a=Cc+a;d&&(a=a.substr(a.length-b));return e+a}function da(a,b,d,c,e){d=d||0;return function(f){f=f["get"+a]();if(0<d||f>-d)f+=d;0===f&&-12===d&&(f=12);return Mb(f,b,c,e)}}function ob(a,b,d){return function(c,e){var f=
c["get"+a](),g=wb((d?"STANDALONE":"")+(b?"SHORT":"")+a);return e[g][f]}}function Xd(a){var b=(new Date(a,0,1)).getDay();return new Date(a,0,(4>=b?5:12)-b)}function Yd(a){return function(b){var d=Xd(b.getFullYear());b=+new Date(b.getFullYear(),b.getMonth(),b.getDate()+(4-b.getDay()))-+d;b=1+Math.round(b/6048E5);return Mb(b,a)}}function Dc(a,b){return 0>=a.getFullYear()?b.ERAS[0]:b.ERAS[1]}function Rd(a){function b(a){var b;if(b=a.match(d)){a=new Date(0);var f=0,g=0,k=b[8]?a.setUTCFullYear:a.setFullYear,
h=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=Z(b[9]+b[10]),g=Z(b[9]+b[11]));k.call(a,Z(b[1]),Z(b[2])-1,Z(b[3]));f=Z(b[4]||0)-f;g=Z(b[5]||0)-g;k=Z(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));h.call(a,f,g,k,b)}return a}var d=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,d,f){var g="",k=[],h,l;d=d||"mediumDate";d=a.DATETIME_FORMATS[d]||d;D(c)&&(c=Pg.test(c)?Z(c):b(c));Y(c)&&(c=new Date(c));if(!ea(c)||!isFinite(c.getTime()))return c;
for(;d;)(l=Qg.exec(d))?(k=eb(k,l,1),d=k.pop()):(k.push(d),d=null);var m=c.getTimezoneOffset();f&&(m=Rc(f,m),c=bc(c,f,!0));p(k,function(b){h=Rg[b];g+=h?h(c,a.DATETIME_FORMATS,m):"''"===b?"'":b.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function Ig(){return function(a,b){w(b)&&(b=2);return fb(a,b)}}function Jg(){return function(a,b,d){b=Infinity===Math.abs(Number(b))?Number(b):Z(b);if(T(b))return a;Y(a)&&(a=a.toString());if(!xa(a))return a;d=!d||isNaN(d)?0:Z(d);d=0>d?Math.max(0,a.length+
d):d;return 0<=b?Ec(a,d,d+b):0===d?Ec(a,b,a.length):Ec(a,Math.max(0,d+b),d)}}function Ec(a,b,d){return D(a)?a.slice(b,d):ya.call(a,b,d)}function Td(a){function b(b){return b.map(function(b){var c=1,d=bb;if(A(b))d=b;else if(D(b)){if("+"===b.charAt(0)||"-"===b.charAt(0))c="-"===b.charAt(0)?-1:1,b=b.substring(1);if(""!==b&&(d=a(b),d.constant))var e=d(),d=function(a){return a[e]}}return{get:d,descending:c}})}function d(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}
function c(a,b){var c=0,d=a.type,h=b.type;if(d===h){var h=a.value,l=b.value;"string"===d?(h=h.toLowerCase(),l=l.toLowerCase()):"object"===d&&(E(h)&&(h=a.index),E(l)&&(l=b.index));h!==l&&(c=h<l?-1:1)}else c=d<h?-1:1;return c}return function(a,f,g,k){if(null==a)return a;if(!xa(a))throw M("orderBy")("notarray",a);I(f)||(f=[f]);0===f.length&&(f=["+"]);var h=b(f),l=g?-1:1,m=A(k)?k:c;a=Array.prototype.map.call(a,function(a,b){return{value:a,tieBreaker:{value:b,type:"number",index:b},predicateValues:h.map(function(c){var e=
c.get(a);c=typeof e;if(null===e)c="string",e="null";else if("object"===c)a:{if(A(e.valueOf)&&(e=e.valueOf(),d(e)))break a;Zb(e)&&(e=e.toString(),d(e))}return{value:e,type:c,index:b}})}});a.sort(function(a,b){for(var d=0,e=h.length;d<e;d++){var g=m(a.predicateValues[d],b.predicateValues[d]);if(g)return g*h[d].descending*l}return(m(a.tieBreaker,b.tieBreaker)||c(a.tieBreaker,b.tieBreaker))*l});return a=a.map(function(a){return a.value})}}function Qa(a){A(a)&&(a={link:a});a.restrict=a.restrict||"AC";
return ka(a)}function Nb(a,b,d,c,e){this.$$controls=[];this.$error={};this.$$success={};this.$pending=void 0;this.$name=e(b.name||b.ngForm||"")(d);this.$dirty=!1;this.$valid=this.$pristine=!0;this.$submitted=this.$invalid=!1;this.$$parentForm=Ob;this.$$element=a;this.$$animate=c;Zd(this)}function Zd(a){a.$$classCache={};a.$$classCache[$d]=!(a.$$classCache[pb]=a.$$element.hasClass(pb))}function ae(a){function b(a,b,c){c&&!a.$$classCache[b]?(a.$$animate.addClass(a.$$element,b),a.$$classCache[b]=!0):
!c&&a.$$classCache[b]&&(a.$$animate.removeClass(a.$$element,b),a.$$classCache[b]=!1)}function d(a,c,d){c=c?"-"+Vc(c,"-"):"";b(a,pb+c,!0===d);b(a,$d+c,!1===d)}var c=a.set,e=a.unset;a.clazz.prototype.$setValidity=function(a,g,k){w(g)?(this.$pending||(this.$pending={}),c(this.$pending,a,k)):(this.$pending&&e(this.$pending,a,k),be(this.$pending)&&(this.$pending=void 0));Na(g)?g?(e(this.$error,a,k),c(this.$$success,a,k)):(c(this.$error,a,k),e(this.$$success,a,k)):(e(this.$error,a,k),e(this.$$success,a,
k));this.$pending?(b(this,"ng-pending",!0),this.$valid=this.$invalid=void 0,d(this,"",null)):(b(this,"ng-pending",!1),this.$valid=be(this.$error),this.$invalid=!this.$valid,d(this,"",this.$valid));g=this.$pending&&this.$pending[a]?void 0:this.$error[a]?!1:this.$$success[a]?!0:null;d(this,a,g);this.$$parentForm.$setValidity(a,g,this)}}function be(a){if(a)for(var b in a)if(a.hasOwnProperty(b))return!1;return!0}function Fc(a){a.$formatters.push(function(b){return a.$isEmpty(b)?b:b.toString()})}function Wa(a,
b,d,c,e,f){var g=N(b[0].type);if(!e.android){var k=!1;b.on("compositionstart",function(){k=!0});b.on("compositionend",function(){k=!1;l()})}var h,l=function(a){h&&(f.defer.cancel(h),h=null);if(!k){var e=b.val();a=a&&a.type;"password"===g||d.ngTrim&&"false"===d.ngTrim||(e=Q(e));(c.$viewValue!==e||""===e&&c.$$hasNativeValidators)&&c.$setViewValue(e,a)}};if(e.hasEvent("input"))b.on("input",l);else{var m=function(a,b,c){h||(h=f.defer(function(){h=null;b&&b.value===c||l(a)}))};b.on("keydown",function(a){var b=
a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||m(a,this,this.value)});if(e.hasEvent("paste"))b.on("paste cut",m)}b.on("change",l);if(ce[g]&&c.$$hasNativeValidators&&g===d.type)b.on("keydown wheel mousedown",function(a){if(!h){var b=this.validity,c=b.badInput,d=b.typeMismatch;h=f.defer(function(){h=null;b.badInput===c&&b.typeMismatch===d||l(a)})}});c.$render=function(){var a=c.$isEmpty(c.$viewValue)?"":c.$viewValue;b.val()!==a&&b.val(a)}}function Pb(a,b){return function(d,c){var e,f;if(ea(d))return d;
if(D(d)){'"'===d.charAt(0)&&'"'===d.charAt(d.length-1)&&(d=d.substring(1,d.length-1));if(Sg.test(d))return new Date(d);a.lastIndex=0;if(e=a.exec(d))return e.shift(),f=c?{yyyy:c.getFullYear(),MM:c.getMonth()+1,dd:c.getDate(),HH:c.getHours(),mm:c.getMinutes(),ss:c.getSeconds(),sss:c.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},p(e,function(a,c){c<b.length&&(f[b[c]]=+a)}),new Date(f.yyyy,f.MM-1,f.dd,f.HH,f.mm,f.ss||0,1E3*f.sss||0)}return NaN}}function qb(a,b,d,c){return function(e,
f,g,k,h,l,m){function n(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function q(a){return t(a)&&!ea(a)?d(a)||void 0:a}Gc(e,f,g,k);Wa(e,f,g,k,h,l);var p=k&&k.$options.getOption("timezone"),r;k.$$parserName=a;k.$parsers.push(function(a){if(k.$isEmpty(a))return null;if(b.test(a))return a=d(a,r),p&&(a=bc(a,p)),a});k.$formatters.push(function(a){if(a&&!ea(a))throw rb("datefmt",a);if(n(a))return(r=a)&&p&&(r=bc(r,p,!0)),m("date")(a,c,p);r=null;return""});if(t(g.min)||g.ngMin){var z;k.$validators.min=
function(a){return!n(a)||w(z)||d(a)>=z};g.$observe("min",function(a){z=q(a);k.$validate()})}if(t(g.max)||g.ngMax){var v;k.$validators.max=function(a){return!n(a)||w(v)||d(a)<=v};g.$observe("max",function(a){v=q(a);k.$validate()})}}}function Gc(a,b,d,c){(c.$$hasNativeValidators=E(b[0].validity))&&c.$parsers.push(function(a){var c=b.prop("validity")||{};return c.badInput||c.typeMismatch?void 0:a})}function de(a){a.$$parserName="number";a.$parsers.push(function(b){if(a.$isEmpty(b))return null;if(Tg.test(b))return parseFloat(b)});
a.$formatters.push(function(b){if(!a.$isEmpty(b)){if(!Y(b))throw rb("numfmt",b);b=b.toString()}return b})}function Xa(a){t(a)&&!Y(a)&&(a=parseFloat(a));return T(a)?void 0:a}function Hc(a){var b=a.toString(),d=b.indexOf(".");return-1===d?-1<a&&1>a&&(a=/e-(\d+)$/.exec(b))?Number(a[1]):0:b.length-d-1}function ee(a,b,d){a=Number(a);var c=(a|0)!==a,e=(b|0)!==b,f=(d|0)!==d;if(c||e||f){var g=c?Hc(a):0,k=e?Hc(b):0,h=f?Hc(d):0,g=Math.max(g,k,h),g=Math.pow(10,g);a*=g;b*=g;d*=g;c&&(a=Math.round(a));e&&(b=Math.round(b));
f&&(d=Math.round(d))}return 0===(a-b)%d}function fe(a,b,d,c,e){if(t(c)){a=a(c);if(!a.constant)throw rb("constexpr",d,c);return a(b)}return e}function Ic(a,b){function d(a,b){if(!a||!a.length)return[];if(!b||!b.length)return a;var c=[],d=0;a:for(;d<a.length;d++){for(var e=a[d],f=0;f<b.length;f++)if(e===b[f])continue a;c.push(e)}return c}function c(a){var b=a;I(a)?b=a.map(c).join(" "):E(a)&&(b=Object.keys(a).filter(function(b){return a[b]}).join(" "));return b}function e(a){var b=a;if(I(a))b=a.map(e);
else if(E(a)){var c=!1,b=Object.keys(a).filter(function(b){b=a[b];!c&&w(b)&&(c=!0);return b});c&&b.push(void 0)}return b}a="ngClass"+a;var f;return["$parse",function(g){return{restrict:"AC",link:function(k,h,l){function m(a,b){var c=[];p(a,function(a){if(0<b||s[a])s[a]=(s[a]||0)+b,s[a]===+(0<b)&&c.push(a)});return c.join(" ")}function n(a){if(a===b){var c=w,c=m(c&&c.split(" "),1);l.$addClass(c)}else c=w,c=m(c&&c.split(" "),-1),l.$removeClass(c);u=a}function q(a){a=c(a);a!==w&&r(a)}function r(a){if(u===
b){var c=w&&w.split(" "),e=a&&a.split(" "),g=d(c,e),c=d(e,c),g=m(g,-1),c=m(c,1);l.$addClass(c);l.$removeClass(g)}w=a}var t=l[a].trim(),z=":"===t.charAt(0)&&":"===t.charAt(1),t=g(t,z?e:c),v=z?q:r,s=h.data("$classCounts"),u=!0,w;s||(s=S(),h.data("$classCounts",s));"ngClass"!==a&&(f||(f=g("$index",function(a){return a&1})),k.$watch(f,n));k.$watch(t,v,z)}}}]}function Qb(a,b,d,c,e,f,g,k,h){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=void 0;this.$validators={};this.$asyncValidators=
{};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=void 0;this.$name=h(d.name||"",!1)(a);this.$$parentForm=Ob;this.$options=Rb;this.$$parsedNgModel=e(d.ngModel);this.$$parsedNgModelAssign=this.$$parsedNgModel.assign;this.$$ngModelGet=this.$$parsedNgModel;this.$$ngModelSet=this.$$parsedNgModelAssign;this.$$pendingDebounce=null;this.$$parserValid=
void 0;this.$$currentValidationRunId=0;Object.defineProperty(this,"$$scope",{value:a});this.$$attr=d;this.$$element=c;this.$$animate=f;this.$$timeout=g;this.$$parse=e;this.$$q=k;this.$$exceptionHandler=b;Zd(this);Ug(this)}function Ug(a){a.$$scope.$watch(function(b){b=a.$$ngModelGet(b);if(b!==a.$modelValue&&(a.$modelValue===a.$modelValue||b===b)){a.$modelValue=a.$$rawModelValue=b;a.$$parserValid=void 0;for(var d=a.$formatters,c=d.length,e=b;c--;)e=d[c](e);a.$viewValue!==e&&(a.$$updateEmptyClasses(e),
a.$viewValue=a.$$lastCommittedViewValue=e,a.$render(),a.$$runValidators(a.$modelValue,a.$viewValue,C))}return b})}function Jc(a){this.$$options=a}function ge(a,b){p(b,function(b,c){t(a[c])||(a[c]=b)})}function Ga(a,b){a.prop("selected",b);a.attr("selected",b)}var Lc={objectMaxDepth:5},Vg=/^\/(.+)\/([a-z]*)$/,ra=Object.prototype.hasOwnProperty,N=function(a){return D(a)?a.toLowerCase():a},wb=function(a){return D(a)?a.toUpperCase():a},Ca,B,la,ya=[].slice,ug=[].splice,Wg=[].push,ha=Object.prototype.toString,
Oc=Object.getPrototypeOf,qa=M("ng"),$=u.angular||(u.angular={}),ec,sb=0;Ca=u.document.documentMode;var T=Number.isNaN||function(a){return a!==a};C.$inject=[];bb.$inject=[];var I=Array.isArray,se=/^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array]$/,Q=function(a){return D(a)?a.trim():a},Md=function(a){return a.replace(/([-()[\]{}+?*.$^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")},Ja=function(){if(!t(Ja.rules)){var a=u.document.querySelector("[ng-csp]")||u.document.querySelector("[data-ng-csp]");
if(a){var b=a.getAttribute("ng-csp")||a.getAttribute("data-ng-csp");Ja.rules={noUnsafeEval:!b||-1!==b.indexOf("no-unsafe-eval"),noInlineStyle:!b||-1!==b.indexOf("no-inline-style")}}else{a=Ja;try{new Function(""),b=!1}catch(d){b=!0}a.rules={noUnsafeEval:b,noInlineStyle:!1}}}return Ja.rules},tb=function(){if(t(tb.name_))return tb.name_;var a,b,d=Ha.length,c,e;for(b=0;b<d;++b)if(c=Ha[b],a=u.document.querySelector("["+c.replace(":","\\:")+"jq]")){e=a.getAttribute(c+"jq");break}return tb.name_=e},ue=/:/g,
Ha=["ng-","data-ng-","ng:","x-ng-"],xe=function(a){var b=a.currentScript;if(!b)return!0;if(!(b instanceof u.HTMLScriptElement||b instanceof u.SVGScriptElement))return!1;b=b.attributes;return[b.getNamedItem("src"),b.getNamedItem("href"),b.getNamedItem("xlink:href")].every(function(b){if(!b)return!0;if(!b.value)return!1;var c=a.createElement("a");c.href=b.value;if(a.location.origin===c.origin)return!0;switch(c.protocol){case "http:":case "https:":case "ftp:":case "blob:":case "file:":case "data:":return!0;
default:return!1}})}(u.document),Ae=/[A-Z]/g,Wc=!1,Oa=3,Fe={full:"1.6.6",major:1,minor:6,dot:6,codeName:"interdimensional-cable"};U.expando="ng339";var kb=U.cache={},gg=1;U._data=function(a){return this.cache[a[this.expando]]||{}};var cg=/-([a-z])/g,Xg=/^-ms-/,Bb={mouseleave:"mouseout",mouseenter:"mouseover"},hc=M("jqLite"),fg=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,gc=/<|&#?\w+;/,dg=/<([\w:-]+)/,eg=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,aa={option:[1,'<select multiple="multiple">',
"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};aa.optgroup=aa.option;aa.tbody=aa.tfoot=aa.colgroup=aa.caption=aa.thead;aa.th=aa.td;var lg=u.Node.prototype.contains||function(a){return!!(this.compareDocumentPosition(a)&16)},Sa=U.prototype={ready:gd,toString:function(){var a=[];p(this,function(b){a.push(""+b)});return"["+a.join(", ")+"]"},
eq:function(a){return 0<=a?B(this[a]):B(this[this.length+a])},length:0,push:Wg,sort:[].sort,splice:[].splice},Hb={};p("multiple selected checked disabled readOnly required open".split(" "),function(a){Hb[N(a)]=a});var ld={};p("input select option textarea button form details".split(" "),function(a){ld[a]=!0});var sd={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern",ngStep:"step"};p({data:lc,removeData:kc,hasData:function(a){for(var b in kb[a.ng339])return!0;
return!1},cleanData:function(a){for(var b=0,d=a.length;b<d;b++)kc(a[b])}},function(a,b){U[b]=a});p({data:lc,inheritedData:Fb,scope:function(a){return B.data(a,"$scope")||Fb(a.parentNode||a,["$isolateScope","$scope"])},isolateScope:function(a){return B.data(a,"$isolateScope")||B.data(a,"$isolateScopeNoTemplate")},controller:id,injector:function(a){return Fb(a,"$injector")},removeAttr:function(a,b){a.removeAttribute(b)},hasClass:Cb,css:function(a,b,d){b=yb(b.replace(Xg,"ms-"));if(t(d))a.style[b]=d;
else return a.style[b]},attr:function(a,b,d){var c=a.nodeType;if(c!==Oa&&2!==c&&8!==c&&a.getAttribute){var c=N(b),e=Hb[c];if(t(d))null===d||!1===d&&e?a.removeAttribute(b):a.setAttribute(b,e?c:d);else return a=a.getAttribute(b),e&&null!==a&&(a=c),null===a?void 0:a}},prop:function(a,b,d){if(t(d))a[b]=d;else return a[b]},text:function(){function a(a,d){if(w(d)){var c=a.nodeType;return 1===c||c===Oa?a.textContent:""}a.textContent=d}a.$dv="";return a}(),val:function(a,b){if(w(b)){if(a.multiple&&"select"===
za(a)){var d=[];p(a.options,function(a){a.selected&&d.push(a.value||a.text)});return d}return a.value}a.value=b},html:function(a,b){if(w(b))return a.innerHTML;zb(a,!0);a.innerHTML=b},empty:jd},function(a,b){U.prototype[b]=function(b,c){var e,f,g=this.length;if(a!==jd&&w(2===a.length&&a!==Cb&&a!==id?b:c)){if(E(b)){for(e=0;e<g;e++)if(a===lc)a(this[e],b);else for(f in b)a(this[e],f,b[f]);return this}e=a.$dv;g=w(e)?Math.min(g,1):g;for(f=0;f<g;f++){var k=a(this[f],b,c);e=e?e+k:k}return e}for(e=0;e<g;e++)a(this[e],
b,c);return this}});p({removeData:kc,on:function(a,b,d,c){if(t(c))throw hc("onargs");if(fc(a)){c=Ab(a,!0);var e=c.events,f=c.handle;f||(f=c.handle=ig(a,e));c=0<=b.indexOf(" ")?b.split(" "):[b];for(var g=c.length,k=function(b,c,g){var k=e[b];k||(k=e[b]=[],k.specialHandlerWrapper=c,"$destroy"===b||g||a.addEventListener(b,f));k.push(d)};g--;)b=c[g],Bb[b]?(k(Bb[b],kg),k(b,void 0,!0)):k(b)}},off:hd,one:function(a,b,d){a=B(a);a.on(b,function e(){a.off(b,d);a.off(b,e)});a.on(b,d)},replaceWith:function(a,
b){var d,c=a.parentNode;zb(a);p(new U(b),function(b){d?c.insertBefore(b,d.nextSibling):c.replaceChild(b,a);d=b})},children:function(a){var b=[];p(a.childNodes,function(a){1===a.nodeType&&b.push(a)});return b},contents:function(a){return a.contentDocument||a.childNodes||[]},append:function(a,b){var d=a.nodeType;if(1===d||11===d){b=new U(b);for(var d=0,c=b.length;d<c;d++)a.appendChild(b[d])}},prepend:function(a,b){if(1===a.nodeType){var d=a.firstChild;p(new U(b),function(b){a.insertBefore(b,d)})}},
wrap:function(a,b){var d=B(b).eq(0).clone()[0],c=a.parentNode;c&&c.replaceChild(d,a);d.appendChild(a)},remove:Gb,detach:function(a){Gb(a,!0)},after:function(a,b){var d=a,c=a.parentNode;if(c){b=new U(b);for(var e=0,f=b.length;e<f;e++){var g=b[e];c.insertBefore(g,d.nextSibling);d=g}}},addClass:Eb,removeClass:Db,toggleClass:function(a,b,d){b&&p(b.split(" "),function(b){var e=d;w(e)&&(e=!Cb(a,b));(e?Eb:Db)(a,b)})},parent:function(a){return(a=a.parentNode)&&11!==a.nodeType?a:null},next:function(a){return a.nextElementSibling},
find:function(a,b){return a.getElementsByTagName?a.getElementsByTagName(b):[]},clone:jc,triggerHandler:function(a,b,d){var c,e,f=b.type||b,g=Ab(a);if(g=(g=g&&g.events)&&g[f])c={preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return!0===this.defaultPrevented},stopImmediatePropagation:function(){this.immediatePropagationStopped=!0},isImmediatePropagationStopped:function(){return!0===this.immediatePropagationStopped},stopPropagation:C,type:f,target:a},b.type&&(c=P(c,
b)),b=ja(g),e=d?[c].concat(d):[c],p(b,function(b){c.isImmediatePropagationStopped()||b.apply(a,e)})}},function(a,b){U.prototype[b]=function(b,c,e){for(var f,g=0,k=this.length;g<k;g++)w(f)?(f=a(this[g],b,c,e),t(f)&&(f=B(f))):ic(f,a(this[g],b,c,e));return t(f)?f:this}});U.prototype.bind=U.prototype.on;U.prototype.unbind=U.prototype.off;var Yg=Object.create(null);md.prototype={_idx:function(a){if(a===this._lastKey)return this._lastIndex;this._lastKey=a;return this._lastIndex=this._keys.indexOf(a)},_transformKey:function(a){return T(a)?
Yg:a},get:function(a){a=this._transformKey(a);a=this._idx(a);if(-1!==a)return this._values[a]},set:function(a,b){a=this._transformKey(a);var d=this._idx(a);-1===d&&(d=this._lastIndex=this._keys.length);this._keys[d]=a;this._values[d]=b},delete:function(a){a=this._transformKey(a);a=this._idx(a);if(-1===a)return!1;this._keys.splice(a,1);this._values.splice(a,1);this._lastKey=NaN;this._lastIndex=-1;return!0}};var Ib=md,ag=[function(){this.$get=[function(){return Ib}]}],ng=/^([^(]+?)=>/,og=/^[^(]*\(\s*([^)]*)\)/m,
Zg=/,/,$g=/^\s*(_?)(\S+?)\1\s*$/,mg=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Ba=M("$injector");hb.$$annotate=function(a,b,d){var c;if("function"===typeof a){if(!(c=a.$inject)){c=[];if(a.length){if(b)throw D(d)&&d||(d=a.name||pg(a)),Ba("strictdi",d);b=nd(a);p(b[1].split(Zg),function(a){a.replace($g,function(a,b,d){c.push(d)})})}a.$inject=c}}else I(a)?(b=a.length-1,ub(a[b],"fn"),c=a.slice(0,b)):ub(a,"fn",!0);return c};var he=M("$animate"),sf=function(){this.$get=C},tf=function(){var a=new Ib,b=[];this.$get=
["$$AnimateRunner","$rootScope",function(d,c){function e(a,b,c){var d=!1;b&&(b=D(b)?b.split(" "):I(b)?b:[],p(b,function(b){b&&(d=!0,a[b]=c)}));return d}function f(){p(b,function(b){var c=a.get(b);if(c){var d=qg(b.attr("class")),e="",f="";p(c,function(a,b){a!==!!d[b]&&(a?e+=(e.length?" ":"")+b:f+=(f.length?" ":"")+b)});p(b,function(a){e&&Eb(a,e);f&&Db(a,f)});a.delete(b)}});b.length=0}return{enabled:C,on:C,off:C,pin:C,push:function(g,k,h,l){l&&l();h=h||{};h.from&&g.css(h.from);h.to&&g.css(h.to);if(h.addClass||
h.removeClass)if(k=h.addClass,l=h.removeClass,h=a.get(g)||{},k=e(h,k,!0),l=e(h,l,!1),k||l)a.set(g,h),b.push(g),1===b.length&&c.$$postDigest(f);g=new d;g.complete();return g}}}]},qf=["$provide",function(a){var b=this,d=null,c=null;this.$$registeredAnimations=Object.create(null);this.register=function(c,d){if(c&&"."!==c.charAt(0))throw he("notcsel",c);var g=c+"-animation";b.$$registeredAnimations[c.substr(1)]=g;a.factory(g,d)};this.customFilter=function(a){1===arguments.length&&(c=A(a)?a:null);return c};
this.classNameFilter=function(a){if(1===arguments.length&&(d=a instanceof RegExp?a:null)&&/[(\s|\/)]ng-animate[(\s|\/)]/.test(d.toString()))throw d=null,he("nongcls","ng-animate");return d};this.$get=["$$animateQueue",function(a){function b(a,c,d){if(d){var e;a:{for(e=0;e<d.length;e++){var f=d[e];if(1===f.nodeType){e=f;break a}}e=void 0}!e||e.parentNode||e.previousElementSibling||(d=null)}d?d.after(a):c.prepend(a)}return{on:a.on,off:a.off,pin:a.pin,enabled:a.enabled,cancel:function(a){a.end&&a.end()},
enter:function(c,d,h,l){d=d&&B(d);h=h&&B(h);d=d||h.parent();b(c,d,h);return a.push(c,"enter",Ka(l))},move:function(c,d,h,l){d=d&&B(d);h=h&&B(h);d=d||h.parent();b(c,d,h);return a.push(c,"move",Ka(l))},leave:function(b,c){return a.push(b,"leave",Ka(c),function(){b.remove()})},addClass:function(b,c,d){d=Ka(d);d.addClass=lb(d.addclass,c);return a.push(b,"addClass",d)},removeClass:function(b,c,d){d=Ka(d);d.removeClass=lb(d.removeClass,c);return a.push(b,"removeClass",d)},setClass:function(b,c,d,f){f=Ka(f);
f.addClass=lb(f.addClass,c);f.removeClass=lb(f.removeClass,d);return a.push(b,"setClass",f)},animate:function(b,c,d,f,m){m=Ka(m);m.from=m.from?P(m.from,c):c;m.to=m.to?P(m.to,d):d;m.tempClasses=lb(m.tempClasses,f||"ng-inline-animate");return a.push(b,"animate",m)}}}]}],vf=function(){this.$get=["$$rAF",function(a){function b(b){d.push(b);1<d.length||a(function(){for(var a=0;a<d.length;a++)d[a]();d=[]})}var d=[];return function(){var a=!1;b(function(){a=!0});return function(d){a?d():b(d)}}}]},uf=function(){this.$get=
["$q","$sniffer","$$animateAsyncRun","$$isDocumentHidden","$timeout",function(a,b,d,c,e){function f(a){this.setHost(a);var b=d();this._doneCallbacks=[];this._tick=function(a){c()?e(a,0,!1):b(a)};this._state=0}f.chain=function(a,b){function c(){if(d===a.length)b(!0);else a[d](function(a){!1===a?b(!1):(d++,c())})}var d=0;c()};f.all=function(a,b){function c(f){e=e&&f;++d===a.length&&b(e)}var d=0,e=!0;p(a,function(a){a.done(c)})};f.prototype={setHost:function(a){this.host=a||{}},done:function(a){2===
this._state?a():this._doneCallbacks.push(a)},progress:C,getPromise:function(){if(!this.promise){var b=this;this.promise=a(function(a,c){b.done(function(b){!1===b?c():a()})})}return this.promise},then:function(a,b){return this.getPromise().then(a,b)},"catch":function(a){return this.getPromise()["catch"](a)},"finally":function(a){return this.getPromise()["finally"](a)},pause:function(){this.host.pause&&this.host.pause()},resume:function(){this.host.resume&&this.host.resume()},end:function(){this.host.end&&
this.host.end();this._resolve(!0)},cancel:function(){this.host.cancel&&this.host.cancel();this._resolve(!1)},complete:function(a){var b=this;0===b._state&&(b._state=1,b._tick(function(){b._resolve(a)}))},_resolve:function(a){2!==this._state&&(p(this._doneCallbacks,function(b){b(a)}),this._doneCallbacks.length=0,this._state=2)}};return f}]},rf=function(){this.$get=["$$rAF","$q","$$AnimateRunner",function(a,b,d){return function(b,e){function f(){a(function(){g.addClass&&(b.addClass(g.addClass),g.addClass=
null);g.removeClass&&(b.removeClass(g.removeClass),g.removeClass=null);g.to&&(b.css(g.to),g.to=null);k||h.complete();k=!0});return h}var g=e||{};g.$$prepared||(g=pa(g));g.cleanupStyles&&(g.from=g.to=null);g.from&&(b.css(g.from),g.from=null);var k,h=new d;return{start:f,end:f}}}]},ba=M("$compile"),oc=new function(){};Yc.$inject=["$provide","$$sanitizeUriProvider"];Kb.prototype.isFirstChange=function(){return this.previousValue===oc};var od=/^((?:x|data)[:\-_])/i,tg=/[:\-_]+(.)/g,ud=M("$controller"),
td=/^(\S+)(\s+as\s+([\w$]+))?$/,Cf=function(){this.$get=["$document",function(a){return function(b){b?!b.nodeType&&b instanceof B&&(b=b[0]):b=a[0].body;return b.offsetWidth+1}}]},vd="application/json",sc={"Content-Type":vd+";charset=utf-8"},wg=/^\[|^\{(?!\{)/,xg={"[":/]$/,"{":/}$/},vg=/^\)]\}',?\n/,rc=M("$http"),Fa=$.$interpolateMinErr=M("$interpolate");Fa.throwNoconcat=function(a){throw Fa("noconcat",a);};Fa.interr=function(a,b){return Fa("interr",a,b.toString())};var Kf=function(){this.$get=function(){function a(a){var b=
function(a){b.data=a;b.called=!0};b.id=a;return b}var b=$.callbacks,d={};return{createCallback:function(c){c="_"+(b.$$counter++).toString(36);var e="angular.callbacks."+c,f=a(c);d[e]=b[c]=f;return e},wasCalled:function(a){return d[a].called},getResponse:function(a){return d[a].data},removeCallback:function(a){delete b[d[a].id];delete d[a]}}}},ah=/^([^?#]*)(\?([^#]*))?(#(.*))?$/,zg={http:80,https:443,ftp:21},mb=M("$location"),Ag=/^\s*[\\/]{2,}/,bh={$$absUrl:"",$$html5:!1,$$replace:!1,absUrl:Lb("$$absUrl"),
url:function(a){if(w(a))return this.$$url;var b=ah.exec(a);(b[1]||""===a)&&this.path(decodeURIComponent(b[1]));(b[2]||b[1]||""===a)&&this.search(b[3]||"");this.hash(b[5]||"");return this},protocol:Lb("$$protocol"),host:Lb("$$host"),port:Lb("$$port"),path:Dd("$$path",function(a){a=null!==a?a.toString():"";return"/"===a.charAt(0)?a:"/"+a}),search:function(a,b){switch(arguments.length){case 0:return this.$$search;case 1:if(D(a)||Y(a))a=a.toString(),this.$$search=Tc(a);else if(E(a))a=pa(a,{}),p(a,function(b,
c){null==b&&delete a[c]}),this.$$search=a;else throw mb("isrcharg");break;default:w(b)||null===b?delete this.$$search[a]:this.$$search[a]=b}this.$$compose();return this},hash:Dd("$$hash",function(a){return null!==a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};p([Cd,wc,vc],function(a){a.prototype=Object.create(bh);a.prototype.state=function(b){if(!arguments.length)return this.$$state;if(a!==vc||!this.$$html5)throw mb("nostate");this.$$state=w(b)?null:b;this.$$urlUpdatedByLocation=
!0;return this}});var Ya=M("$parse"),Eg={}.constructor.prototype.valueOf,Sb=S();p("+ - * / % === !== == != < > <= >= && || ! = |".split(" "),function(a){Sb[a]=!0});var ch={n:"\n",f:"\f",r:"\r",t:"\t",v:"\v","'":"'",'"':'"'},zc=function(a){this.options=a};zc.prototype={constructor:zc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index<this.text.length;)if(a=this.text.charAt(this.index),'"'===a||"'"===a)this.readString(a);else if(this.isNumber(a)||"."===a&&this.isNumber(this.peek()))this.readNumber();
else if(this.isIdentifierStart(this.peekMultichar()))this.readIdent();else if(this.is(a,"(){}[].,;:?"))this.tokens.push({index:this.index,text:a}),this.index++;else if(this.isWhitespace(a))this.index++;else{var b=a+this.peek(),d=b+this.peek(2),c=Sb[b],e=Sb[d];Sb[a]||c||e?(a=e?d:c?b:a,this.tokens.push({index:this.index,text:a,operator:!0}),this.index+=a.length):this.throwError("Unexpected next character ",this.index,this.index+1)}return this.tokens},is:function(a,b){return-1!==b.indexOf(a)},peek:function(a){a=
a||1;return this.index+a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=a&&"9">=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdentifierStart:function(a){return this.options.isIdentifierStart?this.options.isIdentifierStart(a,this.codePointAt(a)):this.isValidIdentifierStart(a)},isValidIdentifierStart:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isIdentifierContinue:function(a){return this.options.isIdentifierContinue?
this.options.isIdentifierContinue(a,this.codePointAt(a)):this.isValidIdentifierContinue(a)},isValidIdentifierContinue:function(a,b){return this.isValidIdentifierStart(a,b)||this.isNumber(a)},codePointAt:function(a){return 1===a.length?a.charCodeAt(0):(a.charCodeAt(0)<<10)+a.charCodeAt(1)-56613888},peekMultichar:function(){var a=this.text.charAt(this.index),b=this.peek();if(!b)return a;var d=a.charCodeAt(0),c=b.charCodeAt(0);return 55296<=d&&56319>=d&&56320<=c&&57343>=c?a+b:a},isExpOperator:function(a){return"-"===
a||"+"===a||this.isNumber(a)},throwError:function(a,b,d){d=d||this.index;b=t(b)?"s "+b+"-"+this.index+" ["+this.text.substring(b,d)+"]":" "+d;throw Ya("lexerr",a,b,this.text);},readNumber:function(){for(var a="",b=this.index;this.index<this.text.length;){var d=N(this.text.charAt(this.index));if("."===d||this.isNumber(d))a+=d;else{var c=this.peek();if("e"===d&&this.isExpOperator(c))a+=d;else if(this.isExpOperator(d)&&c&&this.isNumber(c)&&"e"===a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||
c&&this.isNumber(c)||"e"!==a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:b,text:a,constant:!0,value:Number(a)})},readIdent:function(){var a=this.index;for(this.index+=this.peekMultichar().length;this.index<this.text.length;){var b=this.peekMultichar();if(!this.isIdentifierContinue(b))break;this.index+=b.length}this.tokens.push({index:a,text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var b=this.index;this.index++;
for(var d="",c=a,e=!1;this.index<this.text.length;){var f=this.text.charAt(this.index),c=c+f;if(e)"u"===f?(e=this.text.substring(this.index+1,this.index+5),e.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+e+"]"),this.index+=4,d+=String.fromCharCode(parseInt(e,16))):d+=ch[f]||f,e=!1;else if("\\"===f)e=!0;else{if(f===a){this.index++;this.tokens.push({index:b,text:c,constant:!0,value:d});return}d+=f}this.index++}this.throwError("Unterminated quote",b)}};var r=function(a,b){this.lexer=
a;this.options=b};r.Program="Program";r.ExpressionStatement="ExpressionStatement";r.AssignmentExpression="AssignmentExpression";r.ConditionalExpression="ConditionalExpression";r.LogicalExpression="LogicalExpression";r.BinaryExpression="BinaryExpression";r.UnaryExpression="UnaryExpression";r.CallExpression="CallExpression";r.MemberExpression="MemberExpression";r.Identifier="Identifier";r.Literal="Literal";r.ArrayExpression="ArrayExpression";r.Property="Property";r.ObjectExpression="ObjectExpression";
r.ThisExpression="ThisExpression";r.LocalsExpression="LocalsExpression";r.NGValueParameter="NGValueParameter";r.prototype={ast:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.program();0!==this.tokens.length&&this.throwError("is an unexpected token",this.tokens[0]);return a},program:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.expressionStatement()),!this.expect(";"))return{type:r.Program,body:a}},expressionStatement:function(){return{type:r.ExpressionStatement,
expression:this.filterChain()}},filterChain:function(){for(var a=this.expression();this.expect("|");)a=this.filter(a);return a},expression:function(){return this.assignment()},assignment:function(){var a=this.ternary();if(this.expect("=")){if(!Hd(a))throw Ya("lval");a={type:r.AssignmentExpression,left:a,right:this.assignment(),operator:"="}}return a},ternary:function(){var a=this.logicalOR(),b,d;return this.expect("?")&&(b=this.expression(),this.consume(":"))?(d=this.expression(),{type:r.ConditionalExpression,
test:a,alternate:b,consequent:d}):a},logicalOR:function(){for(var a=this.logicalAND();this.expect("||");)a={type:r.LogicalExpression,operator:"||",left:a,right:this.logicalAND()};return a},logicalAND:function(){for(var a=this.equality();this.expect("&&");)a={type:r.LogicalExpression,operator:"&&",left:a,right:this.equality()};return a},equality:function(){for(var a=this.relational(),b;b=this.expect("==","!=","===","!==");)a={type:r.BinaryExpression,operator:b.text,left:a,right:this.relational()};
return a},relational:function(){for(var a=this.additive(),b;b=this.expect("<",">","<=",">=");)a={type:r.BinaryExpression,operator:b.text,left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),b;b=this.expect("+","-");)a={type:r.BinaryExpression,operator:b.text,left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),b;b=this.expect("*","/","%");)a={type:r.BinaryExpression,operator:b.text,left:a,right:this.unary()};return a},
unary:function(){var a;return(a=this.expect("+","-","!"))?{type:r.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.selfReferential.hasOwnProperty(this.peek().text)?a=pa(this.selfReferential[this.consume().text]):this.options.literals.hasOwnProperty(this.peek().text)?a={type:r.Literal,value:this.options.literals[this.consume().text]}:
this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():this.throwError("not a primary expression",this.peek());for(var b;b=this.expect("(","[",".");)"("===b.text?(a={type:r.CallExpression,callee:a,arguments:this.parseArguments()},this.consume(")")):"["===b.text?(a={type:r.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===b.text?a={type:r.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");
return a},filter:function(a){a=[a];for(var b={type:r.CallExpression,callee:this.identifier(),arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return b},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.filterChain());while(this.expect(","))}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:r.Identifier,name:a.text}},constant:function(){return{type:r.Literal,value:this.consume().value}},
arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:r.ArrayExpression,elements:a}},object:function(){var a=[],b;if("}"!==this.peekToken().text){do{if(this.peek("}"))break;b={type:r.Property,kind:"init"};this.peek().constant?(b.key=this.constant(),b.computed=!1,this.consume(":"),b.value=this.expression()):this.peek().identifier?(b.key=this.identifier(),b.computed=!1,this.peek(":")?
(this.consume(":"),b.value=this.expression()):b.value=b.key):this.peek("[")?(this.consume("["),b.key=this.expression(),this.consume("]"),b.computed=!0,this.consume(":"),b.value=this.expression()):this.throwError("invalid key",this.peek());a.push(b)}while(this.expect(","))}this.consume("}");return{type:r.ObjectExpression,properties:a}},throwError:function(a,b){throw Ya("syntax",b.text,a,b.index+1,this.text,this.text.substring(b.index));},consume:function(a){if(0===this.tokens.length)throw Ya("ueoe",
this.text);var b=this.expect(a);b||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return b},peekToken:function(){if(0===this.tokens.length)throw Ya("ueoe",this.text);return this.tokens[0]},peek:function(a,b,d,c){return this.peekAhead(0,a,b,d,c)},peekAhead:function(a,b,d,c,e){if(this.tokens.length>a){a=this.tokens[a];var f=a.text;if(f===b||f===d||f===c||f===e||!(b||d||c||e))return a}return!1},expect:function(a,b,d,c){return(a=this.peek(a,b,d,c))?(this.tokens.shift(),a):!1},selfReferential:{"this":{type:r.ThisExpression},
$locals:{type:r.LocalsExpression}}};var Fd=2;Jd.prototype={compile:function(a){var b=this;this.state={nextId:0,filters:{},fn:{vars:[],body:[],own:{}},assign:{vars:[],body:[],own:{}},inputs:[]};V(a,b.$filter);var d="",c;this.stage="assign";if(c=Id(a))this.state.computing="assign",d=this.nextId(),this.recurse(c,d),this.return_(d),d="fn.assign="+this.generateFunction("assign","s,v,l");c=Gd(a.body);b.stage="inputs";p(c,function(a,c){var d="fn"+c;b.state[d]={vars:[],body:[],own:{}};b.state.computing=d;
var k=b.nextId();b.recurse(a,k);b.return_(k);b.state.inputs.push({name:d,isPure:a.isPure});a.watchId=c});this.state.computing="fn";this.stage="main";this.recurse(a);a='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+d+this.watchFns()+"return fn;";a=(new Function("$filter","getStringValue","ifDefined","plus",a))(this.$filter,Bg,Cg,Ed);this.state=this.stage=void 0;return a},USE:"use",STRICT:"strict",watchFns:function(){var a=[],b=this.state.inputs,
d=this;p(b,function(b){a.push("var "+b.name+"="+d.generateFunction(b.name,"s"));b.isPure&&a.push(b.name,".isPure="+JSON.stringify(b.isPure)+";")});b.length&&a.push("fn.inputs=["+b.map(function(a){return a.name}).join(",")+"];");return a.join("")},generateFunction:function(a,b){return"function("+b+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=[],b=this;p(this.state.filters,function(d,c){a.push(d+"=$filter("+b.escape(c)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?
"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,b,d,c,e,f){var g,k,h=this,l,m,n;c=c||C;if(!f&&t(a.watchId))b=b||this.nextId(),this.if_("i",this.lazyAssign(b,this.computedMember("i",a.watchId)),this.lazyRecurse(a,b,d,c,e,!0));else switch(a.type){case r.Program:p(a.body,function(b,c){h.recurse(b.expression,void 0,void 0,function(a){k=a});c!==a.body.length-1?h.current().body.push(k,";"):h.return_(k)});break;case r.Literal:m=this.escape(a.value);
this.assign(b,m);c(b||m);break;case r.UnaryExpression:this.recurse(a.argument,void 0,void 0,function(a){k=a});m=a.operator+"("+this.ifDefined(k,0)+")";this.assign(b,m);c(m);break;case r.BinaryExpression:this.recurse(a.left,void 0,void 0,function(a){g=a});this.recurse(a.right,void 0,void 0,function(a){k=a});m="+"===a.operator?this.plus(g,k):"-"===a.operator?this.ifDefined(g,0)+a.operator+this.ifDefined(k,0):"("+g+")"+a.operator+"("+k+")";this.assign(b,m);c(m);break;case r.LogicalExpression:b=b||this.nextId();
h.recurse(a.left,b);h.if_("&&"===a.operator?b:h.not(b),h.lazyRecurse(a.right,b));c(b);break;case r.ConditionalExpression:b=b||this.nextId();h.recurse(a.test,b);h.if_(b,h.lazyRecurse(a.alternate,b),h.lazyRecurse(a.consequent,b));c(b);break;case r.Identifier:b=b||this.nextId();d&&(d.context="inputs"===h.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name);h.if_("inputs"===h.stage||h.not(h.getHasOwnProperty("l",a.name)),function(){h.if_("inputs"===
h.stage||"s",function(){e&&1!==e&&h.if_(h.isNull(h.nonComputedMember("s",a.name)),h.lazyAssign(h.nonComputedMember("s",a.name),"{}"));h.assign(b,h.nonComputedMember("s",a.name))})},b&&h.lazyAssign(b,h.nonComputedMember("l",a.name)));c(b);break;case r.MemberExpression:g=d&&(d.context=this.nextId())||this.nextId();b=b||this.nextId();h.recurse(a.object,g,void 0,function(){h.if_(h.notNull(g),function(){a.computed?(k=h.nextId(),h.recurse(a.property,k),h.getStringValue(k),e&&1!==e&&h.if_(h.not(h.computedMember(g,
k)),h.lazyAssign(h.computedMember(g,k),"{}")),m=h.computedMember(g,k),h.assign(b,m),d&&(d.computed=!0,d.name=k)):(e&&1!==e&&h.if_(h.isNull(h.nonComputedMember(g,a.property.name)),h.lazyAssign(h.nonComputedMember(g,a.property.name),"{}")),m=h.nonComputedMember(g,a.property.name),h.assign(b,m),d&&(d.computed=!1,d.name=a.property.name))},function(){h.assign(b,"undefined")});c(b)},!!e);break;case r.CallExpression:b=b||this.nextId();a.filter?(k=h.filter(a.callee.name),l=[],p(a.arguments,function(a){var b=
h.nextId();h.recurse(a,b);l.push(b)}),m=k+"("+l.join(",")+")",h.assign(b,m),c(b)):(k=h.nextId(),g={},l=[],h.recurse(a.callee,k,g,function(){h.if_(h.notNull(k),function(){p(a.arguments,function(b){h.recurse(b,a.constant?void 0:h.nextId(),void 0,function(a){l.push(a)})});m=g.name?h.member(g.context,g.name,g.computed)+"("+l.join(",")+")":k+"("+l.join(",")+")";h.assign(b,m)},function(){h.assign(b,"undefined")});c(b)}));break;case r.AssignmentExpression:k=this.nextId();g={};this.recurse(a.left,void 0,
g,function(){h.if_(h.notNull(g.context),function(){h.recurse(a.right,k);m=h.member(g.context,g.name,g.computed)+a.operator+k;h.assign(b,m);c(b||m)})},1);break;case r.ArrayExpression:l=[];p(a.elements,function(b){h.recurse(b,a.constant?void 0:h.nextId(),void 0,function(a){l.push(a)})});m="["+l.join(",")+"]";this.assign(b,m);c(b||m);break;case r.ObjectExpression:l=[];n=!1;p(a.properties,function(a){a.computed&&(n=!0)});n?(b=b||this.nextId(),this.assign(b,"{}"),p(a.properties,function(a){a.computed?
(g=h.nextId(),h.recurse(a.key,g)):g=a.key.type===r.Identifier?a.key.name:""+a.key.value;k=h.nextId();h.recurse(a.value,k);h.assign(h.member(b,g,a.computed),k)})):(p(a.properties,function(b){h.recurse(b.value,a.constant?void 0:h.nextId(),void 0,function(a){l.push(h.escape(b.key.type===r.Identifier?b.key.name:""+b.key.value)+":"+a)})}),m="{"+l.join(",")+"}",this.assign(b,m));c(b||m);break;case r.ThisExpression:this.assign(b,"s");c(b||"s");break;case r.LocalsExpression:this.assign(b,"l");c(b||"l");break;
case r.NGValueParameter:this.assign(b,"v"),c(b||"v")}},getHasOwnProperty:function(a,b){var d=a+"."+b,c=this.current().own;c.hasOwnProperty(d)||(c[d]=this.nextId(!1,a+"&&("+this.escape(b)+" in "+a+")"));return c[d]},assign:function(a,b){if(a)return this.current().body.push(a,"=",b,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)||(this.state.filters[a]=this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,b){return"ifDefined("+a+","+this.escape(b)+")"},plus:function(a,
b){return"plus("+a+","+b+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,b,d){if(!0===a)b();else{var c=this.current().body;c.push("if(",a,"){");b();c.push("}");d&&(c.push("else{"),d(),c.push("}"))}},not:function(a){return"!("+a+")"},isNull:function(a){return a+"==null"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,b){var d=/[^$_a-zA-Z0-9]/g;return/^[$_a-zA-Z][$_a-zA-Z0-9]*$/.test(b)?a+"."+b:a+'["'+b.replace(d,this.stringEscapeFn)+'"]'},computedMember:function(a,
b){return a+"["+b+"]"},member:function(a,b,d){return d?this.computedMember(a,b):this.nonComputedMember(a,b)},getStringValue:function(a){this.assign(a,"getStringValue("+a+")")},lazyRecurse:function(a,b,d,c,e,f){var g=this;return function(){g.recurse(a,b,d,c,e,f)}},lazyAssign:function(a,b){var d=this;return function(){d.assign(a,b)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(D(a))return"'"+a.replace(this.stringEscapeRegex,
this.stringEscapeFn)+"'";if(Y(a))return a.toString();if(!0===a)return"true";if(!1===a)return"false";if(null===a)return"null";if("undefined"===typeof a)return"undefined";throw Ya("esc");},nextId:function(a,b){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(b?"="+b:""));return d},current:function(){return this.state[this.state.computing]}};Kd.prototype={compile:function(a){var b=this;V(a,b.$filter);var d,c;if(d=Id(a))c=this.recurse(d);d=Gd(a.body);var e;d&&(e=[],p(d,function(a,c){var d=
b.recurse(a);d.isPure=a.isPure;a.input=d;e.push(d);a.watchId=c}));var f=[];p(a.body,function(a){f.push(b.recurse(a.expression))});a=0===a.body.length?C:1===a.body.length?f[0]:function(a,b){var c;p(f,function(d){c=d(a,b)});return c};c&&(a.assign=function(a,b,d){return c(a,d,b)});e&&(a.inputs=e);return a},recurse:function(a,b,d){var c,e,f=this,g;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case r.Literal:return this.value(a.value,b);case r.UnaryExpression:return e=this.recurse(a.argument),
this["unary"+a.operator](e,b);case r.BinaryExpression:return c=this.recurse(a.left),e=this.recurse(a.right),this["binary"+a.operator](c,e,b);case r.LogicalExpression:return c=this.recurse(a.left),e=this.recurse(a.right),this["binary"+a.operator](c,e,b);case r.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),b);case r.Identifier:return f.identifier(a.name,b,d);case r.MemberExpression:return c=this.recurse(a.object,!1,!!d),a.computed||
(e=a.property.name),a.computed&&(e=this.recurse(a.property)),a.computed?this.computedMember(c,e,b,d):this.nonComputedMember(c,e,b,d);case r.CallExpression:return g=[],p(a.arguments,function(a){g.push(f.recurse(a))}),a.filter&&(e=this.$filter(a.callee.name)),a.filter||(e=this.recurse(a.callee,!0)),a.filter?function(a,c,d,f){for(var n=[],q=0;q<g.length;++q)n.push(g[q](a,c,d,f));a=e.apply(void 0,n,f);return b?{context:void 0,name:void 0,value:a}:a}:function(a,c,d,f){var n=e(a,c,d,f),q;if(null!=n.value){q=
[];for(var p=0;p<g.length;++p)q.push(g[p](a,c,d,f));q=n.value.apply(n.context,q)}return b?{value:q}:q};case r.AssignmentExpression:return c=this.recurse(a.left,!0,1),e=this.recurse(a.right),function(a,d,f,g){var n=c(a,d,f,g);a=e(a,d,f,g);n.context[n.name]=a;return b?{value:a}:a};case r.ArrayExpression:return g=[],p(a.elements,function(a){g.push(f.recurse(a))}),function(a,c,d,e){for(var f=[],q=0;q<g.length;++q)f.push(g[q](a,c,d,e));return b?{value:f}:f};case r.ObjectExpression:return g=[],p(a.properties,
function(a){a.computed?g.push({key:f.recurse(a.key),computed:!0,value:f.recurse(a.value)}):g.push({key:a.key.type===r.Identifier?a.key.name:""+a.key.value,computed:!1,value:f.recurse(a.value)})}),function(a,c,d,e){for(var f={},q=0;q<g.length;++q)g[q].computed?f[g[q].key(a,c,d,e)]=g[q].value(a,c,d,e):f[g[q].key]=g[q].value(a,c,d,e);return b?{value:f}:f};case r.ThisExpression:return function(a){return b?{value:a}:a};case r.LocalsExpression:return function(a,c){return b?{value:c}:c};case r.NGValueParameter:return function(a,
c,d){return b?{value:d}:d}}},"unary+":function(a,b){return function(d,c,e,f){d=a(d,c,e,f);d=t(d)?+d:0;return b?{value:d}:d}},"unary-":function(a,b){return function(d,c,e,f){d=a(d,c,e,f);d=t(d)?-d:-0;return b?{value:d}:d}},"unary!":function(a,b){return function(d,c,e,f){d=!a(d,c,e,f);return b?{value:d}:d}},"binary+":function(a,b,d){return function(c,e,f,g){var k=a(c,e,f,g);c=b(c,e,f,g);k=Ed(k,c);return d?{value:k}:k}},"binary-":function(a,b,d){return function(c,e,f,g){var k=a(c,e,f,g);c=b(c,e,f,g);
k=(t(k)?k:0)-(t(c)?c:0);return d?{value:k}:k}},"binary*":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)*b(c,e,f,g);return d?{value:c}:c}},"binary/":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)/b(c,e,f,g);return d?{value:c}:c}},"binary%":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)%b(c,e,f,g);return d?{value:c}:c}},"binary===":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)===b(c,e,f,g);return d?{value:c}:c}},"binary!==":function(a,b,d){return function(c,e,f,g){c=a(c,
e,f,g)!==b(c,e,f,g);return d?{value:c}:c}},"binary==":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)==b(c,e,f,g);return d?{value:c}:c}},"binary!=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)!=b(c,e,f,g);return d?{value:c}:c}},"binary<":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)<b(c,e,f,g);return d?{value:c}:c}},"binary>":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)>b(c,e,f,g);return d?{value:c}:c}},"binary<=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,
g)<=b(c,e,f,g);return d?{value:c}:c}},"binary>=":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)>=b(c,e,f,g);return d?{value:c}:c}},"binary&&":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)&&b(c,e,f,g);return d?{value:c}:c}},"binary||":function(a,b,d){return function(c,e,f,g){c=a(c,e,f,g)||b(c,e,f,g);return d?{value:c}:c}},"ternary?:":function(a,b,d,c){return function(e,f,g,k){e=a(e,f,g,k)?b(e,f,g,k):d(e,f,g,k);return c?{value:e}:e}},value:function(a,b){return function(){return b?{context:void 0,
name:void 0,value:a}:a}},identifier:function(a,b,d){return function(c,e,f,g){c=e&&a in e?e:c;d&&1!==d&&c&&null==c[a]&&(c[a]={});e=c?c[a]:void 0;return b?{context:c,name:a,value:e}:e}},computedMember:function(a,b,d,c){return function(e,f,g,k){var h=a(e,f,g,k),l,m;null!=h&&(l=b(e,f,g,k),l+="",c&&1!==c&&h&&!h[l]&&(h[l]={}),m=h[l]);return d?{context:h,name:l,value:m}:m}},nonComputedMember:function(a,b,d,c){return function(e,f,g,k){e=a(e,f,g,k);c&&1!==c&&e&&null==e[b]&&(e[b]={});f=null!=e?e[b]:void 0;
return d?{context:e,name:b,value:f}:f}},inputs:function(a,b){return function(d,c,e,f){return f?f[b]:a(d,c,e)}}};xc.prototype={constructor:xc,parse:function(a){a=this.ast.ast(a);var b=this.astCompiler.compile(a);b.literal=0===a.body.length||1===a.body.length&&(a.body[0].expression.type===r.Literal||a.body[0].expression.type===r.ArrayExpression||a.body[0].expression.type===r.ObjectExpression);b.constant=a.constant;return b}};var wa=M("$sce"),oa={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",
JS:"js"},Ac=/_([a-z])/g,Gg=M("$compile"),X=u.document.createElement("a"),Od=ua(u.location.href);Pd.$inject=["$document"];ed.$inject=["$provide"];var Wd=22,Vd=".",Cc="0";Qd.$inject=["$locale"];Sd.$inject=["$locale"];var Rg={yyyy:da("FullYear",4,0,!1,!0),yy:da("FullYear",2,0,!0,!0),y:da("FullYear",1,0,!1,!0),MMMM:ob("Month"),MMM:ob("Month",!0),MM:da("Month",2,1),M:da("Month",1,1),LLLL:ob("Month",!1,!0),dd:da("Date",2),d:da("Date",1),HH:da("Hours",2),H:da("Hours",1),hh:da("Hours",2,-12),h:da("Hours",
1,-12),mm:da("Minutes",2),m:da("Minutes",1),ss:da("Seconds",2),s:da("Seconds",1),sss:da("Milliseconds",3),EEEE:ob("Day"),EEE:ob("Day",!0),a:function(a,b){return 12>a.getHours()?b.AMPMS[0]:b.AMPMS[1]},Z:function(a,b,d){a=-1*d;return a=(0<=a?"+":"")+(Mb(Math[0<a?"floor":"ceil"](a/60),2)+Mb(Math.abs(a%60),2))},ww:Yd(2),w:Yd(1),G:Dc,GG:Dc,GGG:Dc,GGGG:function(a,b){return 0>=a.getFullYear()?b.ERANAMES[0]:b.ERANAMES[1]}},Qg=/((?:[^yMLdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|L+|d+|H+|h+|m+|s+|a|Z|G+|w+))([\s\S]*)/,
Pg=/^-?\d+$/;Rd.$inject=["$locale"];var Kg=ka(N),Lg=ka(wb);Td.$inject=["$parse"];var He=ka({restrict:"E",compile:function(a,b){if(!b.href&&!b.xlinkHref)return function(a,b){if("a"===b[0].nodeName.toLowerCase()){var e="[object SVGAnimatedString]"===ha.call(b.prop("href"))?"xlink:href":"href";b.on("click",function(a){b.attr(e)||a.preventDefault()})}}}}),xb={};p(Hb,function(a,b){function d(a,d,e){a.$watch(e[c],function(a){e.$set(b,!!a)})}if("multiple"!==a){var c=Ea("ng-"+b),e=d;"checked"===a&&(e=function(a,
b,e){e.ngModel!==e[c]&&d(a,b,e)});xb[c]=function(){return{restrict:"A",priority:100,link:e}}}});p(sd,function(a,b){xb[b]=function(){return{priority:100,link:function(a,c,e){if("ngPattern"===b&&"/"===e.ngPattern.charAt(0)&&(c=e.ngPattern.match(Vg))){e.$set("ngPattern",new RegExp(c[1],c[2]));return}a.$watch(e[b],function(a){e.$set(b,a)})}}}});p(["src","srcset","href"],function(a){var b=Ea("ng-"+a);xb[b]=function(){return{priority:99,link:function(d,c,e){var f=a,g=a;"href"===a&&"[object SVGAnimatedString]"===
ha.call(c.prop("href"))&&(g="xlinkHref",e.$attr[g]="xlink:href",f=null);e.$observe(b,function(b){b?(e.$set(g,b),Ca&&f&&c.prop(f,e[g])):"href"===a&&e.$set(g,null)})}}}});var Ob={$addControl:C,$$renameControl:function(a,b){a.$name=b},$removeControl:C,$setValidity:C,$setDirty:C,$setPristine:C,$setSubmitted:C};Nb.$inject=["$element","$attrs","$scope","$animate","$interpolate"];Nb.prototype={$rollbackViewValue:function(){p(this.$$controls,function(a){a.$rollbackViewValue()})},$commitViewValue:function(){p(this.$$controls,
function(a){a.$commitViewValue()})},$addControl:function(a){Ia(a.$name,"input");this.$$controls.push(a);a.$name&&(this[a.$name]=a);a.$$parentForm=this},$$renameControl:function(a,b){var d=a.$name;this[d]===a&&delete this[d];this[b]=a;a.$name=b},$removeControl:function(a){a.$name&&this[a.$name]===a&&delete this[a.$name];p(this.$pending,function(b,d){this.$setValidity(d,null,a)},this);p(this.$error,function(b,d){this.$setValidity(d,null,a)},this);p(this.$$success,function(b,d){this.$setValidity(d,null,
a)},this);db(this.$$controls,a);a.$$parentForm=Ob},$setDirty:function(){this.$$animate.removeClass(this.$$element,Za);this.$$animate.addClass(this.$$element,Tb);this.$dirty=!0;this.$pristine=!1;this.$$parentForm.$setDirty()},$setPristine:function(){this.$$animate.setClass(this.$$element,Za,Tb+" ng-submitted");this.$dirty=!1;this.$pristine=!0;this.$submitted=!1;p(this.$$controls,function(a){a.$setPristine()})},$setUntouched:function(){p(this.$$controls,function(a){a.$setUntouched()})},$setSubmitted:function(){this.$$animate.addClass(this.$$element,
"ng-submitted");this.$submitted=!0;this.$$parentForm.$setSubmitted()}};ae({clazz:Nb,set:function(a,b,d){var c=a[b];c?-1===c.indexOf(d)&&c.push(d):a[b]=[d]},unset:function(a,b,d){var c=a[b];c&&(db(c,d),0===c.length&&delete a[b])}});var ie=function(a){return["$timeout","$parse",function(b,d){function c(a){return""===a?d('this[""]').assign:d(a).assign||C}return{name:"form",restrict:a?"EAC":"E",require:["form","^^?form"],controller:Nb,compile:function(d,f){d.addClass(Za).addClass(pb);var g=f.name?"name":
a&&f.ngForm?"ngForm":!1;return{pre:function(a,d,e,f){var n=f[0];if(!("action"in e)){var q=function(b){a.$apply(function(){n.$commitViewValue();n.$setSubmitted()});b.preventDefault()};d[0].addEventListener("submit",q);d.on("$destroy",function(){b(function(){d[0].removeEventListener("submit",q)},0,!1)})}(f[1]||n.$$parentForm).$addControl(n);var p=g?c(n.$name):C;g&&(p(a,n),e.$observe(g,function(b){n.$name!==b&&(p(a,void 0),n.$$parentForm.$$renameControl(n,b),p=c(n.$name),p(a,n))}));d.on("$destroy",function(){n.$$parentForm.$removeControl(n);
p(a,void 0);P(n,Ob)})}}}}}]},Ie=ie(),Ue=ie(!0),Sg=/^\d{4,}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+(?:[+-][0-2]\d:[0-5]\d|Z)$/,dh=/^[a-z][a-z\d.+-]*:\/*(?:[^:@]+(?::[^@]+)?@)?(?:[^\s:/?#]+|\[[a-f\d:]+])(?::\d+)?(?:\/[^?#]*)?(?:\?[^#]*)?(?:#.*)?$/i,eh=/^(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*$/,Tg=/^\s*(-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,je=/^(\d{4,})-(\d{2})-(\d{2})$/,
ke=/^(\d{4,})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Kc=/^(\d{4,})-W(\d\d)$/,le=/^(\d{4,})-(\d\d)$/,me=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,ce=S();p(["date","datetime-local","month","time","week"],function(a){ce[a]=!0});var ne={text:function(a,b,d,c,e,f){Wa(a,b,d,c,e,f);Fc(c)},date:qb("date",je,Pb(je,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":qb("datetimelocal",ke,Pb(ke,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:qb("time",me,Pb(me,["HH","mm",
"ss","sss"]),"HH:mm:ss.sss"),week:qb("week",Kc,function(a,b){if(ea(a))return a;if(D(a)){Kc.lastIndex=0;var d=Kc.exec(a);if(d){var c=+d[1],e=+d[2],f=d=0,g=0,k=0,h=Xd(c),e=7*(e-1);b&&(d=b.getHours(),f=b.getMinutes(),g=b.getSeconds(),k=b.getMilliseconds());return new Date(c,0,h.getDate()+e,d,f,g,k)}}return NaN},"yyyy-Www"),month:qb("month",le,Pb(le,["yyyy","MM"]),"yyyy-MM"),number:function(a,b,d,c,e,f){Gc(a,b,d,c);de(c);Wa(a,b,d,c,e,f);var g,k;if(t(d.min)||d.ngMin)c.$validators.min=function(a){return c.$isEmpty(a)||
w(g)||a>=g},d.$observe("min",function(a){g=Xa(a);c.$validate()});if(t(d.max)||d.ngMax)c.$validators.max=function(a){return c.$isEmpty(a)||w(k)||a<=k},d.$observe("max",function(a){k=Xa(a);c.$validate()});if(t(d.step)||d.ngStep){var h;c.$validators.step=function(a,b){return c.$isEmpty(b)||w(h)||ee(b,g||0,h)};d.$observe("step",function(a){h=Xa(a);c.$validate()})}},url:function(a,b,d,c,e,f){Wa(a,b,d,c,e,f);Fc(c);c.$$parserName="url";c.$validators.url=function(a,b){var d=a||b;return c.$isEmpty(d)||dh.test(d)}},
email:function(a,b,d,c,e,f){Wa(a,b,d,c,e,f);Fc(c);c.$$parserName="email";c.$validators.email=function(a,b){var d=a||b;return c.$isEmpty(d)||eh.test(d)}},radio:function(a,b,d,c){var e=!d.ngTrim||"false"!==Q(d.ngTrim);w(d.name)&&b.attr("name",++sb);b.on("click",function(a){var g;b[0].checked&&(g=d.value,e&&(g=Q(g)),c.$setViewValue(g,a&&a.type))});c.$render=function(){var a=d.value;e&&(a=Q(a));b[0].checked=a===c.$viewValue};d.$observe("value",c.$render)},range:function(a,b,d,c,e,f){function g(a,c){b.attr(a,
d[a]);d.$observe(a,c)}function k(a){n=Xa(a);T(c.$modelValue)||(m?(a=b.val(),n>a&&(a=n,b.val(a)),c.$setViewValue(a)):c.$validate())}function h(a){q=Xa(a);T(c.$modelValue)||(m?(a=b.val(),q<a&&(b.val(q),a=q<n?n:q),c.$setViewValue(a)):c.$validate())}function l(a){p=Xa(a);T(c.$modelValue)||(m&&c.$viewValue!==b.val()?c.$setViewValue(b.val()):c.$validate())}Gc(a,b,d,c);de(c);Wa(a,b,d,c,e,f);var m=c.$$hasNativeValidators&&"range"===b[0].type,n=m?0:void 0,q=m?100:void 0,p=m?1:void 0,r=b[0].validity;a=t(d.min);
e=t(d.max);f=t(d.step);var z=c.$render;c.$render=m&&t(r.rangeUnderflow)&&t(r.rangeOverflow)?function(){z();c.$setViewValue(b.val())}:z;a&&(c.$validators.min=m?function(){return!0}:function(a,b){return c.$isEmpty(b)||w(n)||b>=n},g("min",k));e&&(c.$validators.max=m?function(){return!0}:function(a,b){return c.$isEmpty(b)||w(q)||b<=q},g("max",h));f&&(c.$validators.step=m?function(){return!r.stepMismatch}:function(a,b){return c.$isEmpty(b)||w(p)||ee(b,n||0,p)},g("step",l))},checkbox:function(a,b,d,c,e,
f,g,k){var h=fe(k,a,"ngTrueValue",d.ngTrueValue,!0),l=fe(k,a,"ngFalseValue",d.ngFalseValue,!1);b.on("click",function(a){c.$setViewValue(b[0].checked,a&&a.type)});c.$render=function(){b[0].checked=c.$viewValue};c.$isEmpty=function(a){return!1===a};c.$formatters.push(function(a){return sa(a,h)});c.$parsers.push(function(a){return a?h:l})},hidden:C,button:C,submit:C,reset:C,file:C},Zc=["$browser","$sniffer","$filter","$parse",function(a,b,d,c){return{restrict:"E",require:["?ngModel"],link:{pre:function(e,
f,g,k){k[0]&&(ne[N(g.type)]||ne.text)(e,f,g,k[0],b,a,d,c)}}}}],fh=/^(true|false|\d+)$/,mf=function(){function a(a,d,c){var e=t(c)?c:9===Ca?"":null;a.prop("value",e);d.$set("value",c)}return{restrict:"A",priority:100,compile:function(b,d){return fh.test(d.ngValue)?function(b,d,f){b=b.$eval(f.ngValue);a(d,f,b)}:function(b,d,f){b.$watch(f.ngValue,function(b){a(d,f,b)})}}}},Me=["$compile",function(a){return{restrict:"AC",compile:function(b){a.$$addBindingClass(b);return function(b,c,e){a.$$addBindingInfo(c,
e.ngBind);c=c[0];b.$watch(e.ngBind,function(a){c.textContent=dc(a)})}}}}],Oe=["$interpolate","$compile",function(a,b){return{compile:function(d){b.$$addBindingClass(d);return function(c,d,f){c=a(d.attr(f.$attr.ngBindTemplate));b.$$addBindingInfo(d,c.expressions);d=d[0];f.$observe("ngBindTemplate",function(a){d.textContent=w(a)?"":a})}}}}],Ne=["$sce","$parse","$compile",function(a,b,d){return{restrict:"A",compile:function(c,e){var f=b(e.ngBindHtml),g=b(e.ngBindHtml,function(b){return a.valueOf(b)});
d.$$addBindingClass(c);return function(b,c,e){d.$$addBindingInfo(c,e.ngBindHtml);b.$watch(g,function(){var d=f(b);c.html(a.getTrustedHtml(d)||"")})}}}}],lf=ka({restrict:"A",require:"ngModel",link:function(a,b,d,c){c.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),Pe=Ic("",!0),Re=Ic("Odd",0),Qe=Ic("Even",1),Se=Qa({compile:function(a,b){b.$set("ngCloak",void 0);a.removeClass("ng-cloak")}}),Te=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],dd={},gh={blur:!0,focus:!0};
p("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var b=Ea("ng-"+a);dd[b]=["$parse","$rootScope",function(d,c){return{restrict:"A",compile:function(e,f){var g=d(f[b]);return function(b,d){d.on(a,function(d){var e=function(){g(b,{$event:d})};gh[a]&&c.$$phase?b.$evalAsync(e):b.$apply(e)})}}}}]});var We=["$animate","$compile",function(a,b){return{multiElement:!0,transclude:"element",priority:600,
terminal:!0,restrict:"A",$$tlb:!0,link:function(d,c,e,f,g){var k,h,l;d.$watch(e.ngIf,function(d){d?h||g(function(d,f){h=f;d[d.length++]=b.$$createComment("end ngIf",e.ngIf);k={clone:d};a.enter(d,c.parent(),c)}):(l&&(l.remove(),l=null),h&&(h.$destroy(),h=null),k&&(l=vb(k.clone),a.leave(l).done(function(a){!1!==a&&(l=null)}),k=null))})}}}],Xe=["$templateRequest","$anchorScroll","$animate",function(a,b,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:$.noop,compile:function(c,
e){var f=e.ngInclude||e.src,g=e.onload||"",k=e.autoscroll;return function(c,e,m,n,q){var p=0,r,z,v,s=function(){z&&(z.remove(),z=null);r&&(r.$destroy(),r=null);v&&(d.leave(v).done(function(a){!1!==a&&(z=null)}),z=v,v=null)};c.$watch(f,function(f){var m=function(a){!1===a||!t(k)||k&&!c.$eval(k)||b()},y=++p;f?(a(f,!0).then(function(a){if(!c.$$destroyed&&y===p){var b=c.$new();n.template=a;a=q(b,function(a){s();d.enter(a,null,e).done(m)});r=b;v=a;r.$emit("$includeContentLoaded",f);c.$eval(g)}},function(){c.$$destroyed||
y!==p||(s(),c.$emit("$includeContentError",f))}),c.$emit("$includeContentRequested",f)):(s(),n.template=null)})}}}}],of=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(b,d,c,e){ha.call(d[0]).match(/SVG/)?(d.empty(),a(fd(e.template,u.document).childNodes)(b,function(a){d.append(a)},{futureParentElement:d})):(d.html(e.template),a(d.contents())(b))}}}],Ye=Qa({priority:450,compile:function(){return{pre:function(a,b,d){a.$eval(d.ngInit)}}}}),kf=function(){return{restrict:"A",
priority:100,require:"ngModel",link:function(a,b,d,c){var e=d.ngList||", ",f="false"!==d.ngTrim,g=f?Q(e):e;c.$parsers.push(function(a){if(!w(a)){var b=[];a&&p(a.split(g),function(a){a&&b.push(f?Q(a):a)});return b}});c.$formatters.push(function(a){if(I(a))return a.join(e)});c.$isEmpty=function(a){return!a||!a.length}}}},pb="ng-valid",$d="ng-invalid",Za="ng-pristine",Tb="ng-dirty",rb=M("ngModel");Qb.$inject="$scope $exceptionHandler $attrs $element $parse $animate $timeout $q $interpolate".split(" ");
Qb.prototype={$$initGetterSetters:function(){if(this.$options.getOption("getterSetter")){var a=this.$$parse(this.$$attr.ngModel+"()"),b=this.$$parse(this.$$attr.ngModel+"($$$p)");this.$$ngModelGet=function(b){var c=this.$$parsedNgModel(b);A(c)&&(c=a(b));return c};this.$$ngModelSet=function(a,c){A(this.$$parsedNgModel(a))?b(a,{$$$p:c}):this.$$parsedNgModelAssign(a,c)}}else if(!this.$$parsedNgModel.assign)throw rb("nonassign",this.$$attr.ngModel,Aa(this.$$element));},$render:C,$isEmpty:function(a){return w(a)||
""===a||null===a||a!==a},$$updateEmptyClasses:function(a){this.$isEmpty(a)?(this.$$animate.removeClass(this.$$element,"ng-not-empty"),this.$$animate.addClass(this.$$element,"ng-empty")):(this.$$animate.removeClass(this.$$element,"ng-empty"),this.$$animate.addClass(this.$$element,"ng-not-empty"))},$setPristine:function(){this.$dirty=!1;this.$pristine=!0;this.$$animate.removeClass(this.$$element,Tb);this.$$animate.addClass(this.$$element,Za)},$setDirty:function(){this.$dirty=!0;this.$pristine=!1;this.$$animate.removeClass(this.$$element,
Za);this.$$animate.addClass(this.$$element,Tb);this.$$parentForm.$setDirty()},$setUntouched:function(){this.$touched=!1;this.$untouched=!0;this.$$animate.setClass(this.$$element,"ng-untouched","ng-touched")},$setTouched:function(){this.$touched=!0;this.$untouched=!1;this.$$animate.setClass(this.$$element,"ng-touched","ng-untouched")},$rollbackViewValue:function(){this.$$timeout.cancel(this.$$pendingDebounce);this.$viewValue=this.$$lastCommittedViewValue;this.$render()},$validate:function(){if(!T(this.$modelValue)){var a=
this.$$lastCommittedViewValue,b=this.$$rawModelValue,d=this.$valid,c=this.$modelValue,e=this.$options.getOption("allowInvalid"),f=this;this.$$runValidators(b,a,function(a){e||d===a||(f.$modelValue=a?b:void 0,f.$modelValue!==c&&f.$$writeModelToScope())})}},$$runValidators:function(a,b,d){function c(){var c=!0;p(h.$validators,function(d,e){var g=Boolean(d(a,b));c=c&&g;f(e,g)});return c?!0:(p(h.$asyncValidators,function(a,b){f(b,null)}),!1)}function e(){var c=[],d=!0;p(h.$asyncValidators,function(e,
g){var h=e(a,b);if(!h||!A(h.then))throw rb("nopromise",h);f(g,void 0);c.push(h.then(function(){f(g,!0)},function(){d=!1;f(g,!1)}))});c.length?h.$$q.all(c).then(function(){g(d)},C):g(!0)}function f(a,b){k===h.$$currentValidationRunId&&h.$setValidity(a,b)}function g(a){k===h.$$currentValidationRunId&&d(a)}this.$$currentValidationRunId++;var k=this.$$currentValidationRunId,h=this;(function(){var a=h.$$parserName||"parse";if(w(h.$$parserValid))f(a,null);else return h.$$parserValid||(p(h.$validators,function(a,
b){f(b,null)}),p(h.$asyncValidators,function(a,b){f(b,null)})),f(a,h.$$parserValid),h.$$parserValid;return!0})()?c()?e():g(!1):g(!1)},$commitViewValue:function(){var a=this.$viewValue;this.$$timeout.cancel(this.$$pendingDebounce);if(this.$$lastCommittedViewValue!==a||""===a&&this.$$hasNativeValidators)this.$$updateEmptyClasses(a),this.$$lastCommittedViewValue=a,this.$pristine&&this.$setDirty(),this.$$parseAndValidate()},$$parseAndValidate:function(){var a=this.$$lastCommittedViewValue,b=this;if(this.$$parserValid=
w(a)?void 0:!0)for(var d=0;d<this.$parsers.length;d++)if(a=this.$parsers[d](a),w(a)){this.$$parserValid=!1;break}T(this.$modelValue)&&(this.$modelValue=this.$$ngModelGet(this.$$scope));var c=this.$modelValue,e=this.$options.getOption("allowInvalid");this.$$rawModelValue=a;e&&(this.$modelValue=a,b.$modelValue!==c&&b.$$writeModelToScope());this.$$runValidators(a,this.$$lastCommittedViewValue,function(d){e||(b.$modelValue=d?a:void 0,b.$modelValue!==c&&b.$$writeModelToScope())})},$$writeModelToScope:function(){this.$$ngModelSet(this.$$scope,
this.$modelValue);p(this.$viewChangeListeners,function(a){try{a()}catch(b){this.$$exceptionHandler(b)}},this)},$setViewValue:function(a,b){this.$viewValue=a;this.$options.getOption("updateOnDefault")&&this.$$debounceViewValueCommit(b)},$$debounceViewValueCommit:function(a){var b=this.$options.getOption("debounce");Y(b[a])?b=b[a]:Y(b["default"])&&(b=b["default"]);this.$$timeout.cancel(this.$$pendingDebounce);var d=this;0<b?this.$$pendingDebounce=this.$$timeout(function(){d.$commitViewValue()},b):this.$$scope.$root.$$phase?
this.$commitViewValue():this.$$scope.$apply(function(){d.$commitViewValue()})},$overrideModelOptions:function(a){this.$options=this.$options.createChild(a)}};ae({clazz:Qb,set:function(a,b){a[b]=!0},unset:function(a,b){delete a[b]}});var jf=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:Qb,priority:1,compile:function(b){b.addClass(Za).addClass("ng-untouched").addClass(pb);return{pre:function(a,b,e,f){var g=f[0];b=f[1]||g.$$parentForm;if(f=f[2])g.$options=
f.$options;g.$$initGetterSetters();b.$addControl(g);e.$observe("name",function(a){g.$name!==a&&g.$$parentForm.$$renameControl(g,a)});a.$on("$destroy",function(){g.$$parentForm.$removeControl(g)})},post:function(b,c,e,f){function g(){k.$setTouched()}var k=f[0];if(k.$options.getOption("updateOn"))c.on(k.$options.getOption("updateOn"),function(a){k.$$debounceViewValueCommit(a&&a.type)});c.on("blur",function(){k.$touched||(a.$$phase?b.$evalAsync(g):b.$apply(g))})}}}}}],Rb,hh=/(\s+|^)default(\s+|$)/;Jc.prototype=
{getOption:function(a){return this.$$options[a]},createChild:function(a){var b=!1;a=P({},a);p(a,function(d,c){"$inherit"===d?"*"===c?b=!0:(a[c]=this.$$options[c],"updateOn"===c&&(a.updateOnDefault=this.$$options.updateOnDefault)):"updateOn"===c&&(a.updateOnDefault=!1,a[c]=Q(d.replace(hh,function(){a.updateOnDefault=!0;return" "})))},this);b&&(delete a["*"],ge(a,this.$$options));ge(a,Rb.$$options);return new Jc(a)}};Rb=new Jc({updateOn:"",updateOnDefault:!0,debounce:0,getterSetter:!1,allowInvalid:!1,
timezone:null});var nf=function(){function a(a,d){this.$$attrs=a;this.$$scope=d}a.$inject=["$attrs","$scope"];a.prototype={$onInit:function(){var a=this.parentCtrl?this.parentCtrl.$options:Rb,d=this.$$scope.$eval(this.$$attrs.ngModelOptions);this.$options=a.createChild(d)}};return{restrict:"A",priority:10,require:{parentCtrl:"?^^ngModelOptions"},bindToController:!0,controller:a}},Ze=Qa({terminal:!0,priority:1E3}),ih=M("ngOptions"),jh=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([$\w][$\w]*)|(?:\(\s*([$\w][$\w]*)\s*,\s*([$\w][$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,
gf=["$compile","$document","$parse",function(a,b,d){function c(a,b,c){function e(a,b,c,d,f){this.selectValue=a;this.viewValue=b;this.label=c;this.group=d;this.disabled=f}function f(a){var b;if(!p&&xa(a))b=a;else{b=[];for(var c in a)a.hasOwnProperty(c)&&"$"!==c.charAt(0)&&b.push(c)}return b}var n=a.match(jh);if(!n)throw ih("iexp",a,Aa(b));var q=n[5]||n[7],p=n[6];a=/ as /.test(n[0])&&n[1];var r=n[9];b=d(n[2]?n[1]:q);var z=a&&d(a)||b,t=r&&d(r),s=r?function(a,b){return t(c,b)}:function(a){return Pa(a)},
w=function(a,b){return s(a,A(a,b))},u=d(n[2]||n[1]),y=d(n[3]||""),J=d(n[4]||""),H=d(n[8]),B={},A=p?function(a,b){B[p]=b;B[q]=a;return B}:function(a){B[q]=a;return B};return{trackBy:r,getTrackByValue:w,getWatchables:d(H,function(a){var b=[];a=a||[];for(var d=f(a),e=d.length,g=0;g<e;g++){var k=a===d?g:d[g],l=a[k],k=A(l,k),l=s(l,k);b.push(l);if(n[2]||n[1])l=u(c,k),b.push(l);n[4]&&(k=J(c,k),b.push(k))}return b}),getOptions:function(){for(var a=[],b={},d=H(c)||[],g=f(d),k=g.length,n=0;n<k;n++){var q=d===
g?n:g[n],p=A(d[q],q),t=z(c,p),q=s(t,p),v=u(c,p),G=y(c,p),p=J(c,p),t=new e(q,t,v,G,p);a.push(t);b[q]=t}return{items:a,selectValueMap:b,getOptionFromViewValue:function(a){return b[w(a)]},getViewValueFromOption:function(a){return r?pa(a.viewValue):a.viewValue}}}}}var e=u.document.createElement("option"),f=u.document.createElement("optgroup");return{restrict:"A",terminal:!0,require:["select","ngModel"],link:{pre:function(a,b,c,d){d[0].registerOption=C},post:function(d,k,h,l){function m(a){var b=(a=s.getOptionFromViewValue(a))&&
a.element;b&&!b.selected&&(b.selected=!0);return a}function n(a,b){a.element=b;b.disabled=a.disabled;a.label!==b.label&&(b.label=a.label,b.textContent=a.label);b.value=a.selectValue}var q=l[0],r=l[1],w=h.multiple;l=0;for(var z=k.children(),v=z.length;l<v;l++)if(""===z[l].value){q.hasEmptyOption=!0;q.emptyOption=z.eq(l);break}k.empty();l=!!q.emptyOption;B(e.cloneNode(!1)).val("?");var s,u=c(h.ngOptions,k,d),A=b[0].createDocumentFragment();q.generateUnknownOptionValue=function(a){return"?"};w?(q.writeValue=
function(a){if(s){var b=a&&a.map(m)||[];s.items.forEach(function(a){a.element.selected&&-1===Array.prototype.indexOf.call(b,a)&&(a.element.selected=!1)})}},q.readValue=function(){var a=k.val()||[],b=[];p(a,function(a){(a=s.selectValueMap[a])&&!a.disabled&&b.push(s.getViewValueFromOption(a))});return b},u.trackBy&&d.$watchCollection(function(){if(I(r.$viewValue))return r.$viewValue.map(function(a){return u.getTrackByValue(a)})},function(){r.$render()})):(q.writeValue=function(a){if(s){var b=k[0].options[k[0].selectedIndex],
c=s.getOptionFromViewValue(a);b&&b.removeAttribute("selected");c?(k[0].value!==c.selectValue&&(q.removeUnknownOption(),k[0].value=c.selectValue,c.element.selected=!0),c.element.setAttribute("selected","selected")):q.selectUnknownOrEmptyOption(a)}},q.readValue=function(){var a=s.selectValueMap[k.val()];return a&&!a.disabled?(q.unselectEmptyOption(),q.removeUnknownOption(),s.getViewValueFromOption(a)):null},u.trackBy&&d.$watch(function(){return u.getTrackByValue(r.$viewValue)},function(){r.$render()}));
l&&(a(q.emptyOption)(d),k.prepend(q.emptyOption),8===q.emptyOption[0].nodeType?(q.hasEmptyOption=!1,q.registerOption=function(a,b){""===b.val()&&(q.hasEmptyOption=!0,q.emptyOption=b,q.emptyOption.removeClass("ng-scope"),r.$render(),b.on("$destroy",function(){var a=q.$isEmptyOptionSelected();q.hasEmptyOption=!1;q.emptyOption=void 0;a&&r.$render()}))}):q.emptyOption.removeClass("ng-scope"));d.$watchCollection(u.getWatchables,function(){var a=s&&q.readValue();if(s)for(var b=s.items.length-1;0<=b;b--){var c=
s.items[b];t(c.group)?Gb(c.element.parentNode):Gb(c.element)}s=u.getOptions();var d={};s.items.forEach(function(a){var b;if(t(a.group)){b=d[a.group];b||(b=f.cloneNode(!1),A.appendChild(b),b.label=null===a.group?"null":a.group,d[a.group]=b);var c=e.cloneNode(!1);b.appendChild(c);n(a,c)}else b=e.cloneNode(!1),A.appendChild(b),n(a,b)});k[0].appendChild(A);r.$render();r.$isEmpty(a)||(b=q.readValue(),(u.trackBy||w?sa(a,b):a===b)||(r.$setViewValue(b),r.$render()))})}}}}],$e=["$locale","$interpolate","$log",
function(a,b,d){var c=/{}/g,e=/^when(Minus)?(.+)$/;return{link:function(f,g,k){function h(a){g.text(a||"")}var l=k.count,m=k.$attr.when&&g.attr(k.$attr.when),n=k.offset||0,q=f.$eval(m)||{},r={},t=b.startSymbol(),z=b.endSymbol(),v=t+l+"-"+n+z,s=$.noop,u;p(k,function(a,b){var c=e.exec(b);c&&(c=(c[1]?"-":"")+N(c[2]),q[c]=g.attr(k.$attr[b]))});p(q,function(a,d){r[d]=b(a.replace(c,v))});f.$watch(l,function(b){var c=parseFloat(b),e=T(c);e||c in q||(c=a.pluralCat(c-n));c===u||e&&T(u)||(s(),e=r[c],w(e)?(null!=
b&&d.debug("ngPluralize: no rule defined for '"+c+"' in "+m),s=C,h()):s=f.$watch(e,h),u=c)})}}}],af=["$parse","$animate","$compile",function(a,b,d){var c=M("ngRepeat"),e=function(a,b,c,d,e,m,n){a[c]=d;e&&(a[e]=m);a.$index=b;a.$first=0===b;a.$last=b===n-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=0===(b&1))};return{restrict:"A",multiElement:!0,transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,compile:function(f,g){var k=g.ngRepeat,h=d.$$createComment("end ngRepeat",k),l=k.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
if(!l)throw c("iexp",k);var m=l[1],n=l[2],q=l[3],r=l[4],l=m.match(/^(?:(\s*[$\w]+)|\(\s*([$\w]+)\s*,\s*([$\w]+)\s*\))$/);if(!l)throw c("iidexp",m);var t=l[3]||l[1],z=l[2];if(q&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(q)||/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(q)))throw c("badident",q);var v,s,u,w,y={$id:Pa};r?v=a(r):(u=function(a,b){return Pa(b)},w=function(a){return a});return function(a,d,f,g,l){v&&(s=function(b,c,d){z&&(y[z]=b);y[t]=c;y.$index=
d;return v(a,y)});var m=S();a.$watchCollection(n,function(f){var g,n,r=d[0],v,y=S(),B,A,G,C,E,D,I;q&&(a[q]=f);if(xa(f))E=f,n=s||u;else for(I in n=s||w,E=[],f)ra.call(f,I)&&"$"!==I.charAt(0)&&E.push(I);B=E.length;I=Array(B);for(g=0;g<B;g++)if(A=f===E?g:E[g],G=f[A],C=n(A,G,g),m[C])D=m[C],delete m[C],y[C]=D,I[g]=D;else{if(y[C])throw p(I,function(a){a&&a.scope&&(m[a.id]=a)}),c("dupes",k,C,G);I[g]={id:C,scope:void 0,clone:void 0};y[C]=!0}for(v in m){D=m[v];C=vb(D.clone);b.leave(C);if(C[0].parentNode)for(g=
0,n=C.length;g<n;g++)C[g].$$NG_REMOVED=!0;D.scope.$destroy()}for(g=0;g<B;g++)if(A=f===E?g:E[g],G=f[A],D=I[g],D.scope){v=r;do v=v.nextSibling;while(v&&v.$$NG_REMOVED);D.clone[0]!==v&&b.move(vb(D.clone),null,r);r=D.clone[D.clone.length-1];e(D.scope,g,t,G,z,A,B)}else l(function(a,c){D.scope=c;var d=h.cloneNode(!1);a[a.length++]=d;b.enter(a,null,r);r=d;D.clone=a;y[D.id]=D;e(D.scope,g,t,G,z,A,B)});m=y})}}}}],bf=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(b,d,c){b.$watch(c.ngShow,
function(b){a[b?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],Ve=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(b,d,c){b.$watch(c.ngHide,function(b){a[b?"addClass":"removeClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],cf=Qa(function(a,b,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&p(d,function(a,c){b.css(c,"")});a&&b.css(a)},!0)}),df=["$animate","$compile",function(a,b){return{require:"ngSwitch",controller:["$scope",function(){this.cases=
{}}],link:function(d,c,e,f){var g=[],k=[],h=[],l=[],m=function(a,b){return function(c){!1!==c&&a.splice(b,1)}};d.$watch(e.ngSwitch||e.on,function(c){for(var d,e;h.length;)a.cancel(h.pop());d=0;for(e=l.length;d<e;++d){var r=vb(k[d].clone);l[d].$destroy();(h[d]=a.leave(r)).done(m(h,d))}k.length=0;l.length=0;(g=f.cases["!"+c]||f.cases["?"])&&p(g,function(c){c.transclude(function(d,e){l.push(e);var f=c.element;d[d.length++]=b.$$createComment("end ngSwitchWhen");k.push({clone:d});a.enter(d,f.parent(),
f)})})})}}}],ef=Qa({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,b,d,c,e){a=d.ngSwitchWhen.split(d.ngSwitchWhenSeparator).sort().filter(function(a,b,c){return c[b-1]!==a});p(a,function(a){c.cases["!"+a]=c.cases["!"+a]||[];c.cases["!"+a].push({transclude:e,element:b})})}}),ff=Qa({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,b,d,c,e){c.cases["?"]=c.cases["?"]||[];c.cases["?"].push({transclude:e,element:b})}}),kh=M("ngTransclude"),
hf=["$compile",function(a){return{restrict:"EAC",terminal:!0,compile:function(b){var d=a(b.contents());b.empty();return function(a,b,f,g,k){function h(){d(a,function(a){b.append(a)})}if(!k)throw kh("orphan",Aa(b));f.ngTransclude===f.$attr.ngTransclude&&(f.ngTransclude="");f=f.ngTransclude||f.ngTranscludeSlot;k(function(a,c){var d;if(d=a.length)a:{d=0;for(var f=a.length;d<f;d++){var g=a[d];if(g.nodeType!==Oa||g.nodeValue.trim()){d=!0;break a}}d=void 0}d?b.append(a):(h(),c.$destroy())},null,f);f&&!k.isSlotFilled(f)&&
h()}}}}],Je=["$templateCache",function(a){return{restrict:"E",terminal:!0,compile:function(b,d){"text/ng-template"===d.type&&a.put(d.id,b[0].text)}}}],lh={$setViewValue:C,$render:C},mh=["$element","$scope",function(a,b){function d(){g||(g=!0,b.$$postDigest(function(){g=!1;e.ngModelCtrl.$render()}))}function c(a){k||(k=!0,b.$$postDigest(function(){b.$$destroyed||(k=!1,e.ngModelCtrl.$setViewValue(e.readValue()),a&&e.ngModelCtrl.$render())}))}var e=this,f=new Ib;e.selectValueMap={};e.ngModelCtrl=lh;
e.multiple=!1;e.unknownOption=B(u.document.createElement("option"));e.hasEmptyOption=!1;e.emptyOption=void 0;e.renderUnknownOption=function(b){b=e.generateUnknownOptionValue(b);e.unknownOption.val(b);a.prepend(e.unknownOption);Ga(e.unknownOption,!0);a.val(b)};e.updateUnknownOption=function(b){b=e.generateUnknownOptionValue(b);e.unknownOption.val(b);Ga(e.unknownOption,!0);a.val(b)};e.generateUnknownOptionValue=function(a){return"? "+Pa(a)+" ?"};e.removeUnknownOption=function(){e.unknownOption.parent()&&
e.unknownOption.remove()};e.selectEmptyOption=function(){e.emptyOption&&(a.val(""),Ga(e.emptyOption,!0))};e.unselectEmptyOption=function(){e.hasEmptyOption&&Ga(e.emptyOption,!1)};b.$on("$destroy",function(){e.renderUnknownOption=C});e.readValue=function(){var b=a.val(),b=b in e.selectValueMap?e.selectValueMap[b]:b;return e.hasOption(b)?b:null};e.writeValue=function(b){var c=a[0].options[a[0].selectedIndex];c&&Ga(B(c),!1);e.hasOption(b)?(e.removeUnknownOption(),c=Pa(b),a.val(c in e.selectValueMap?
c:b),Ga(B(a[0].options[a[0].selectedIndex]),!0)):e.selectUnknownOrEmptyOption(b)};e.addOption=function(a,b){if(8!==b[0].nodeType){Ia(a,'"option value"');""===a&&(e.hasEmptyOption=!0,e.emptyOption=b);var c=f.get(a)||0;f.set(a,c+1);d()}};e.removeOption=function(a){var b=f.get(a);b&&(1===b?(f.delete(a),""===a&&(e.hasEmptyOption=!1,e.emptyOption=void 0)):f.set(a,b-1))};e.hasOption=function(a){return!!f.get(a)};e.$hasEmptyOption=function(){return e.hasEmptyOption};e.$isUnknownOptionSelected=function(){return a[0].options[0]===
e.unknownOption[0]};e.$isEmptyOptionSelected=function(){return e.hasEmptyOption&&a[0].options[a[0].selectedIndex]===e.emptyOption[0]};e.selectUnknownOrEmptyOption=function(a){null==a&&e.emptyOption?(e.removeUnknownOption(),e.selectEmptyOption()):e.unknownOption.parent().length?e.updateUnknownOption(a):e.renderUnknownOption(a)};var g=!1,k=!1;e.registerOption=function(a,b,f,g,k){if(f.$attr.ngValue){var p,r=NaN;f.$observe("value",function(a){var d,f=b.prop("selected");t(r)&&(e.removeOption(p),delete e.selectValueMap[r],
d=!0);r=Pa(a);p=a;e.selectValueMap[r]=a;e.addOption(a,b);b.attr("value",r);d&&f&&c()})}else g?f.$observe("value",function(a){e.readValue();var d,f=b.prop("selected");t(p)&&(e.removeOption(p),d=!0);p=a;e.addOption(a,b);d&&f&&c()}):k?a.$watch(k,function(a,d){f.$set("value",a);var g=b.prop("selected");d!==a&&e.removeOption(d);e.addOption(a,b);d&&g&&c()}):e.addOption(f.value,b);f.$observe("disabled",function(a){if("true"===a||a&&b.prop("selected"))e.multiple?c(!0):(e.ngModelCtrl.$setViewValue(null),e.ngModelCtrl.$render())});
b.on("$destroy",function(){var a=e.readValue(),b=f.value;e.removeOption(b);d();(e.multiple&&a&&-1!==a.indexOf(b)||a===b)&&c(!0)})}}],Ke=function(){return{restrict:"E",require:["select","?ngModel"],controller:mh,priority:1,link:{pre:function(a,b,d,c){var e=c[0],f=c[1];if(f){if(e.ngModelCtrl=f,b.on("change",function(){e.removeUnknownOption();a.$apply(function(){f.$setViewValue(e.readValue())})}),d.multiple){e.multiple=!0;e.readValue=function(){var a=[];p(b.find("option"),function(b){b.selected&&!b.disabled&&
(b=b.value,a.push(b in e.selectValueMap?e.selectValueMap[b]:b))});return a};e.writeValue=function(a){p(b.find("option"),function(b){var c=!!a&&(-1!==Array.prototype.indexOf.call(a,b.value)||-1!==Array.prototype.indexOf.call(a,e.selectValueMap[b.value]));c!==b.selected&&Ga(B(b),c)})};var g,k=NaN;a.$watch(function(){k!==f.$viewValue||sa(g,f.$viewValue)||(g=ja(f.$viewValue),f.$render());k=f.$viewValue});f.$isEmpty=function(a){return!a||0===a.length}}}else e.registerOption=C},post:function(a,b,d,c){var e=
c[1];if(e){var f=c[0];e.$render=function(){f.writeValue(e.$viewValue)}}}}}},Le=["$interpolate",function(a){return{restrict:"E",priority:100,compile:function(b,d){var c,e;t(d.ngValue)||(t(d.value)?c=a(d.value,!0):(e=a(b.text(),!0))||d.$set("value",b.text()));return function(a,b,d){var h=b.parent();(h=h.data("$selectController")||h.parent().data("$selectController"))&&h.registerOption(a,b,d,c,e)}}}}],ad=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){c&&(d.required=!0,c.$validators.required=
function(a,b){return!d.required||!c.$isEmpty(b)},d.$observe("required",function(){c.$validate()}))}}},$c=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e,f=d.ngPattern||d.pattern;d.$observe("pattern",function(a){D(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw M("ngPattern")("noregexp",f,a,Aa(b));e=a||void 0;c.$validate()});c.$validators.pattern=function(a,b){return c.$isEmpty(b)||w(e)||e.test(b)}}}}},cd=function(){return{restrict:"A",require:"?ngModel",
link:function(a,b,d,c){if(c){var e=-1;d.$observe("maxlength",function(a){a=Z(a);e=T(a)?-1:a;c.$validate()});c.$validators.maxlength=function(a,b){return 0>e||c.$isEmpty(b)||b.length<=e}}}}},bd=function(){return{restrict:"A",require:"?ngModel",link:function(a,b,d,c){if(c){var e=0;d.$observe("minlength",function(a){e=Z(a)||0;c.$validate()});c.$validators.minlength=function(a,b){return c.$isEmpty(b)||b.length>=e}}}}};u.angular.bootstrap?u.console&&console.log("WARNING: Tried to load angular more than once."):
(Be(),Ee($),$.module("ngLocale",[],["$provide",function(a){function b(a){a+="";var b=a.indexOf(".");return-1==b?0:a.length-b-1}a.value("$locale",{DATETIME_FORMATS:{AMPMS:["AM","PM"],DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"],FIRSTDAYOFWEEK:6,MONTH:"January February March April May June July August September October November December".split(" "),SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),
STANDALONEMONTH:"January February March April May June July August September October November December".split(" "),WEEKENDRANGE:[5,6],fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",medium:"MMM d, y h:mm:ss a",mediumDate:"MMM d, y",mediumTime:"h:mm:ss a","short":"M/d/yy h:mm a",shortDate:"M/d/yy",shortTime:"h:mm a"},NUMBER_FORMATS:{CURRENCY_SYM:"$",DECIMAL_SEP:".",GROUP_SEP:",",PATTERNS:[{gSize:3,lgSize:3,maxFrac:3,minFrac:0,minInt:1,negPre:"-",negSuf:"",posPre:"",posSuf:""},{gSize:3,lgSize:3,maxFrac:2,
minFrac:2,minInt:1,negPre:"-\u00a4",negSuf:"",posPre:"\u00a4",posSuf:""}]},id:"en-us",localeID:"en_US",pluralCat:function(a,c){var e=a|0,f=c;void 0===f&&(f=Math.min(b(a),3));Math.pow(10,f);return 1==e&&0==f?"one":"other"}})}]),B(function(){we(u.document,Uc)}))})(window);!window.angular.$$csp().noInlineStyle&&window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
//# sourceMappingURL=angular.min.js.map
;
/**
 * @license angular-recaptcha build:2017-10-13
 * https://github.com/vividcortex/angular-recaptcha
 * Copyright (c) 2017 VividCortex
**/


!function(a){"use strict";a.module("vcRecaptcha",[])}(angular),function(a){"use strict";function b(){throw new Error('You need to set the "key" attribute to your public reCaptcha key. If you don\'t have a key, please get one from https://www.google.com/recaptcha/admin/create')}a.module("vcRecaptcha").provider("vcRecaptchaService",function(){var c=this,d={};c.onLoadFunctionName="vcRecaptchaApiLoaded",c.setDefaults=function(b){a.copy(b,d)},c.setSiteKey=function(a){d.key=a},c.setTheme=function(a){d.theme=a},c.setStoken=function(a){d.stoken=a},c.setSize=function(a){d.size=a},c.setType=function(a){d.type=a},c.setLang=function(a){d.lang=a},c.setBadge=function(a){d.badge=a},c.setOnLoadFunctionName=function(a){c.onLoadFunctionName=a},c.$get=["$rootScope","$window","$q","$document",function(e,f,g,h){function i(){return k?g.when(k):m}function j(){if(!k)throw new Error("reCaptcha has not been loaded yet.")}var k,l=g.defer(),m=l.promise,n={};f.vcRecaptchaApiLoadedCallback=f.vcRecaptchaApiLoadedCallback||[];var o=function(){k=f.grecaptcha,l.resolve(k)};if(f.vcRecaptchaApiLoadedCallback.push(o),f[c.onLoadFunctionName]=function(){f.vcRecaptchaApiLoadedCallback.forEach(function(a){a()})},a.isDefined(f.grecaptcha))o();else{var p=f.document.createElement("script");p.async=!0,p.defer=!0,p.src="https://www.google.com/recaptcha/api.js?onload="+c.onLoadFunctionName+"&render=explicit",h.find("body")[0].appendChild(p)}return{create:function(a,c){return c.sitekey=c.key||d.key,c.theme=c.theme||d.theme,c.stoken=c.stoken||d.stoken,c.size=c.size||d.size,c.type=c.type||d.type,c.hl=c.lang||d.lang,c.badge=c.badge||d.badge,c.sitekey&&40===c.sitekey.length||b(),i().then(function(b){var d=b.render(a,c);return n[d]=a,d})},reload:function(a){j(),k.reset(a),e.$broadcast("reCaptchaReset",a)},execute:function(a){j(),k.execute(a)},useLang:function(a,b){var c=n[a];if(!c)throw new Error("reCaptcha Widget ID not exists",a);var d=c.querySelector("iframe");if(!b)return d&&d.src&&/[?&]hl=\w+/.test(d.src)?d.src.replace(/.+[?&]hl=(\w+)([^\w].+)?/,"$1"):null;if(d&&d.src){var e=d.src;/[?&]hl=/.test(e)?e=e.replace(/([?&]hl=)\w+/,"$1"+b):e+=(-1===e.indexOf("?")?"?":"&")+"hl="+b,d.src=e}},getResponse:function(a){return j(),k.getResponse(a)},getInstance:function(a){return n[a]},destroy:function(a){delete n[a]}}}]})}(angular),function(a){"use strict";a.module("vcRecaptcha").directive("vcRecaptcha",["$document","$timeout","vcRecaptchaService",function(b,c,d){return{restrict:"A",require:"?^^form",scope:{response:"=?ngModel",key:"=?",stoken:"=?",theme:"=?",size:"=?",type:"=?",lang:"=?",badge:"=?",tabindex:"=?",required:"=?",onCreate:"&",onSuccess:"&",onExpire:"&"},link:function(e,f,g,h){function i(){h&&h.$setValidity("recaptcha",null),l()}function j(){c(function(){e.response="",k(),e.onExpire({widgetId:e.widgetId,fn:'expire'})})}function k(){h&&h.$setValidity("recaptcha",!1===e.required?null:Boolean(e.response))}function l(){d.destroy(e.widgetId),a.element(b[0].querySelectorAll(".pls-container")).parent().remove()}e.widgetId=null,h&&a.isDefined(g.required)&&e.$watch("required",k);var m=e.$watch("key",function(b){var h=function(a){c(function(){e.response=a,k(),e.onSuccess({response:a,widgetId:e.widgetId,fn:'success'})})};d.create(f[0],{callback:h,key:b,stoken:e.stoken||g.stoken||null,theme:e.theme||g.theme||null,type:e.type||g.type||null,lang:e.lang||g.lang||null,tabindex:e.tabindex||g.tabindex||null,size:e.size||g.size||null,badge:e.badge||g.badge||null,"expired-callback":j}).then(function(b){k(),e.widgetId=b,e.onCreate({widgetId:b, fn:'create'}),e.$on("$destroy",i),e.$on("reCaptchaReset",function(c,d){(a.isUndefined(d)||b===d)&&(e.response="",k())})}),m()})}}}])}(angular);;
/*
 AngularJS v1.6.6
 (c) 2010-2017 Google, Inc. http://angularjs.org
 License: MIT
*/
(function(n,c){'use strict';function l(b,a,g){var d=g.baseHref(),k=b[0];return function(b,e,f){var g,h;f=f||{};h=f.expires;g=c.isDefined(f.path)?f.path:d;c.isUndefined(e)&&(h="Thu, 01 Jan 1970 00:00:00 GMT",e="");c.isString(h)&&(h=new Date(h));e=encodeURIComponent(b)+"="+encodeURIComponent(e);e=e+(g?";path="+g:"")+(f.domain?";domain="+f.domain:"");e+=h?";expires="+h.toUTCString():"";e+=f.secure?";secure":"";f=e.length+1;4096<f&&a.warn("Cookie '"+b+"' possibly not set or overflowed because it was too large ("+
f+" > 4096 bytes)!");k.cookie=e}}c.module("ngCookies",["ng"]).info({angularVersion:"1.6.6"}).provider("$cookies",[function(){var b=this.defaults={};this.$get=["$$cookieReader","$$cookieWriter",function(a,g){return{get:function(d){return a()[d]},getObject:function(d){return(d=this.get(d))?c.fromJson(d):d},getAll:function(){return a()},put:function(d,a,m){g(d,a,m?c.extend({},b,m):b)},putObject:function(d,b,a){this.put(d,c.toJson(b),a)},remove:function(a,k){g(a,void 0,k?c.extend({},b,k):b)}}}]}]);c.module("ngCookies").factory("$cookieStore",
["$cookies",function(b){return{get:function(a){return b.getObject(a)},put:function(a,c){b.putObject(a,c)},remove:function(a){b.remove(a)}}}]);l.$inject=["$document","$log","$browser"];c.module("ngCookies").provider("$$cookieWriter",function(){this.$get=l})})(window,window.angular);
//# sourceMappingURL=angular-cookies.min.js.map
;
/**
 * angular-ui-notification - Angular.js service providing simple notifications using Bootstrap 3 styles with css transitions for animating
 * @author Alex_Crack
 * @version v0.3.6
 * @link https://github.com/alexcrack/angular-ui-notification
 * @license MIT
 */
angular.module("ui-notification", []), angular.module("ui-notification").provider("Notification", function () { this.options = { delay: 5e3, startTop: 10, startRight: 10, verticalSpacing: 10, horizontalSpacing: 10, positionX: "right", positionY: "top", replaceMessage: !1, templateUrl: "angular-ui-notification.html", onClose: void 0, closeOnClick: !0, maxCount: 0, container: "body", priority: 10, classNoti: '' }, this.setOptions = function (t) { if (!angular.isObject(t)) throw new Error("Options should be an object!"); this.options = angular.extend({}, this.options, t) }, this.$get = ["$timeout", "$http", "$compile", "$templateCache", "$rootScope", "$injector", "$sce", "$q", "$window", function (t, i, e, n, o, s, a, r, l) { var p = this.options, c = p.startTop, u = p.startRight, d = p.verticalSpacing, f = p.horizontalSpacing, m = p.delay, g = [], h = !1, y = function (s, y) { function C(i) { function n(t) { ["-webkit-transition", "-o-transition", "transition"].forEach(function (i) { C.css(i, t) }) } var o = s.scope.$new(); o.message = a.trustAsHtml(s.message), o.title = a.trustAsHtml(s.title), o.t = s.type.substr(0, 1), o.delay = s.delay, o.onClose = s.onClose; var r = function (t, i) { return t._priority - i._priority }, m = function (t, i) { return i._priority - t._priority }, y = function () { var t = 0, i = 0, e = c, n = u, o = []; "top" === s.positionY ? g.sort(r) : "bottom" === s.positionY && g.sort(m); for (var a = g.length - 1; a >= 0; a--) { var l = g[a]; if (s.replaceMessage && a < g.length - 1) l.addClass("killed"); else { var h = parseInt(l[0].offsetHeight), y = parseInt(l[0].offsetWidth), C = o[l._positionY + l._positionX]; v + h > window.innerHeight && (C = c, i++, t = 0); var v = e = C ? 0 === t ? C : C + d : c, _ = n + i * (f + y); l.css(l._positionY, v + "px"), "center" == l._positionX ? l.css("left", parseInt(window.innerWidth / 2 - y / 2) + "px") : l.css(l._positionX, _ + "px"), o[l._positionY + l._positionX] = v + h, p.maxCount > 0 && g.length > p.maxCount && 0 === a && l.scope().kill(!0), t++ } } }, C = e(i)(o); C._positionY = s.positionY, C._positionX = s.positionX, C._priority = s.priority, C.addClass(s.type + ' '+ s.classNoti); var _ = function (t) { t = t.originalEvent || t, ("click" === t.type || "opacity" === t.propertyName && t.elapsedTime >= 1) && (o.onClose && o.$apply(o.onClose(C)), C.remove(), g.splice(g.indexOf(C), 1), o.$destroy(), y()) }; s.closeOnClick && (C.addClass("clickable"), C.bind("click", _)), C.bind("webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd", _), angular.isNumber(s.delay) && t(function () { C.addClass("killed") }, s.delay), n("none"), angular.element(document.querySelector(s.container)).append(C); var k = -(parseInt(C[0].offsetHeight) + 50); if (C.css(C._positionY, k + "px"), g.push(C), "center" == s.positionX) { var w = parseInt(C[0].offsetWidth); C.css("left", parseInt(window.innerWidth / 2 - w / 2) + "px") } t(function () { n("") }), o._templateElement = C, o.kill = function (i) { i ? (o.onClose && o.$apply(o.onClose(o._templateElement)), g.splice(g.indexOf(o._templateElement), 1), o._templateElement.remove(), o.$destroy(), t(y)) : o._templateElement.addClass("killed") }, t(y), h || (angular.element(l).bind("resize", function (i) { t(y) }), h = !0), v.resolve(o) } var v = r.defer(); "object" == typeof s && null !== s || (s = { message: s }), s.scope = s.scope ? s.scope : o, s.template = s.templateUrl ? s.templateUrl : p.templateUrl, s.delay = angular.isUndefined(s.delay) ? m : s.delay, s.type = y || s.type || p.type || "", s.positionY = s.positionY ? s.positionY : p.positionY, s.positionX = s.positionX ? s.positionX : p.positionX, s.replaceMessage = s.replaceMessage ? s.replaceMessage : p.replaceMessage, s.onClose = s.onClose ? s.onClose : p.onClose, s.closeOnClick = null !== s.closeOnClick && void 0 !== s.closeOnClick ? s.closeOnClick : p.closeOnClick, s.container = s.container ? s.container : p.container, s.priority = s.priority ? s.priority : p.priority; var _ = n.get(s.template); return _ ? C(_) : i.get(s.template, { cache: !0 }).then(function (t) { C(t.data) })["catch"](function (t) { throw new Error("Template (" + s.template + ") could not be loaded. " + t) }), v.promise }; return y.primary = function (t) { return this(t, "primary") }, y.error = function (t) { return this(t, "error") }, y.success = function (t) { return this(t, "success") }, y.info = function (t) { return this(t, "info") }, y.warning = function (t) { return this(t, "warning") }, y.clearAll = function () { angular.forEach(g, function (t) { t.addClass("killed") }) }, y }] }), angular.module("ui-notification").run(["$templateCache", function (t) { t.put("angular-ui-notification.html", '<div class="ui-notification"><h3 ng-if="title" ng-bind-html="title"></h3><div class="message" ng-bind-html="message"></div></div>') }]);;
/*!
 * Bootstrap v3.3.7 (http://getbootstrap.com)
 * Copyright 2011-2016 Twitter, Inc.
 * Licensed under the MIT license
 */
if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",c).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f,g.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=300,c.BACKDROP_TRANSITION_DURATION=150,c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var d=this,e=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){d.$element.one("mouseup.dismiss.bs.modal",function(b){a(b.target).is(d.$element)&&(d.ignoreBackdropClick=!0)})}),this.backdrop(function(){var e=a.support.transition&&d.$element.hasClass("fade");d.$element.parent().length||d.$element.appendTo(d.$body),d.$element.show().scrollTop(0),d.adjustDialog(),e&&d.$element[0].offsetWidth,d.$element.addClass("in"),d.enforceFocus();var f=a.Event("shown.bs.modal",{relatedTarget:b});e?d.$dialog.one("bsTransitionEnd",function(){d.$element.trigger("focus").trigger(f)}).emulateTransitionEnd(c.TRANSITION_DURATION):d.$element.trigger("focus").trigger(f)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(c.TRANSITION_DURATION):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){document===a.target||this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},c.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$body.removeClass("modal-open"),a.resetAdjustments(),a.resetScrollbar(),a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var d=this,e=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var f=a.support.transition&&e;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+e).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;f?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.adjustDialog()},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth<a,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"",this.bodyIsOverflowing&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad)},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",a,b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-m<o.top?"bottom":"right"==h&&k.right+l>o.width?"left":"left"==h&&k.left-l<o.left?"right":h,f.removeClass(n).addClass(h)}var p=this.getCalculatedOffset(h,k,l,m);this.applyPlacement(p,h);var q=function(){var a=e.hoverState;e.$element.trigger("shown.bs."+e.type),e.hoverState=null,"out"==a&&e.leave(e)};a.support.transition&&this.$tip.hasClass("fade")?f.one("bsTransitionEnd",q).emulateTransitionEnd(c.TRANSITION_DURATION):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top+=g,b.left+=h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=/top|bottom/.test(c),m=l?2*k.left-e+i:2*k.top-f+j,n=l?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(m,d[0][n],l)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c?"left":"top",50*(1-a/b)+"%").css(c?"top":"left","")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(b){function d(){"in"!=e.hoverState&&f.detach(),e.$element&&e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),b&&b()}var e=this,f=a(this.$tip),g=a.Event("hide.bs."+this.type);if(this.$element.trigger(g),!g.isDefaultPrevented())return f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",d).emulateTransitionEnd(c.TRANSITION_DURATION):d(),this.hoverState=null,this},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName,e=c.getBoundingClientRect();null==e.width&&(e=a.extend({},e,{width:e.right-e.left,height:e.bottom-e.top}));var f=window.SVGElement&&c instanceof window.SVGElement,g=d?{top:0,left:0}:f?null:b.offset(),h={scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop()},i=d?{width:a(window).width(),height:a(window).height()}:null;return a.extend({},e,h,i,g)},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<e[0])return this.activeTarget=null,this.clear();for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(void 0===e[a+1]||b<e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){
this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]})})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e<c&&"top";if("bottom"==this.affixed)return null!=c?!(e+this.unpin<=f.top)&&"bottom":!(e+g<=a-d)&&"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&e<=c?"top":null!=d&&i+j>=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);;
function util() {
    /// <summary>
    /// Example usage:
    /// Must be declared in the requires of ngAWDSApp.js -> var util = new util();
    /// Anywhere in the application use EngineRoom.util.generateUID();
    /// </summary>
    this.getServiceFromAngular = function (serviceName) {
        //*** call angularjs service
        return angular.element('[ng-app="AWDSApp"]').injector().get(serviceName);
    }

    this.trimString = function (val, defaultVal)
    {
        if (defaultVal) {
        } else {
            defaultVal = "";
        }
        return this.isNullOrEmpty(val) ? defaultVal : (val+'').trim();
    }
    this.showLoadingIcon = function (element, isShow) {
        this.updateButtonSpinnerService(element, isShow);

        ///<summary>
        ///required css 
        ///.loading-icon {
        ///    width: 100%;
        ///    height: 100%;
        ///    float: left;
        ///    top: 0;
        ///    left: 0;
        ///    background-color: rgba(255,255,255,0.8);
        ///    z-index: 999;
        ///    position: absolute;
        ///    background-image: url('images/loading_2x.gif');
        ///    background-repeat: no-repeat;
        ///    background-position: 50% 50%;
        ///}
        /// </summary>
        if (isShow) {
            element.append('<div class="loading-icon"><div class="cssload-loader"><div class="cssload-inner cssload-one"></div><div class="cssload-inner cssload-two"></div><div class="cssload-inner cssload-three"></div></div></div>');            
            //return;
        }
        if (!isShow && element.find('.loading-icon').length > 0) {
            element.find('.loading-icon').each(function(idx, ele) {
                if ($(ele).hasClass('bg-color-back') == false)
                {
                    $(ele).remove();
                }
            });
        }
    }
    this.showLoadingIcon2 = function (element, isShow) {

        this.updateButtonSpinnerService(element, isShow);
        if (isShow) {
            var ele = $('<div class="loading-icon-section" style="height:' + $('body').height() + 'px;"><div class="loading-icon-section-box"><div class="scwindow-checkout-close"><a href="#" class="btn btn-sm btnclose" role="button">X</a></div><span class="box-loading-icon"></span><div class="scwindow-checkout-continue"><a href="#">Continue</a></div></div></div>');
            element.append(ele);
            //element.append('<div class="loading-icon bg-color-back"><a href="#" class="btn btn-sm btnclose" role="button">X</a><div class="scwindow-checkout-continue"><a href="#">Continuer</a></div></div>');
            //element.addClass('loading-icon-box');
            //return ele;
        }
        //if (!isShow && element.find('.loading-icon.bg-color-back').length > 0) {
        //    element.find('.loading-icon.bg-color-back').remove();
        //    //element.removeClass('loading-icon-box');
        //}
        if (!isShow && element.find('.loading-icon-section').length > 0) {
            element.find('.loading-icon-section').remove();
            //element.removeClass('loading-icon-box');
        }
    },
    this.showLoadingIconInner = function (element, isShow) {
        this.updateButtonSpinnerService(element, isShow);

        if (isShow) {
            element.append('<div class="loading-icon"></div>');
            element.addClass('loading-icon-box');
            //return;
        }
        if (!isShow && element.find('.loading-icon').length > 0) {
            element.find('.loading-icon').remove();
            element.removeClass('loading-icon-box');
        }
    }
    
    this.showLoadingButton = function (element, isLoading) {
        if (element && element.length > 0) {
            isLoading = isLoading || false;
            element.button((isLoading ? "loading" : "reset"));
        }
    }
    this.setStatusButton = function (jqElement, sStatus) {
        if (jqElement && jqElement.length > 0) {
            jqElement.button(sStatus);
        }
    }
    this.disableButton = function (jqElement, isDisable) {
        if (jqElement && jqElement.length > 0) {
            isDisable = isDisable || true;
            if (isDisable) {
                jqElement.attr('disabled', 'disabled');
            } else {
                jqElement.removeAttr('disabled');
            }
        }
    }

    this.updateButtonSpinnerService = function (ele, isShow)
    {
        var btnSpinnerService = this.getServiceFromAngular('btnSpinnerService');
        setTimeout(function () {
            if (ele.find('.' + window.webApp.btnSpinner.cl_btn + '.' + window.webApp.btnSpinner.cl_clicked).length > 0) {
                
                var eleButtons = ele.find('.' + window.webApp.btnSpinner.cl_btn + '.' + window.webApp.btnSpinner.cl_clicked);
                eleButtons.each(function (idx, eleBtn) {
                    if (isShow == true) {
                        btnSpinnerService.loading($(eleBtn));
                    }
                    else {
                        btnSpinnerService.reset($(eleBtn));
                    }
                });
            }
        }, 1);
    }

    this.isNullOrEmpty = function(Val) {
        if (typeof Val === "string") return Val.isNullOrEmpty();//*** isNullOrEmpty function from ExtensionMethods file ***
        if (Val === undefined || Val === null) return true;
        if (Val === 0 || Val === false) return false;
        if (Val) return false;//*** will evaluate to true if value is not: 0, false ***
        else return true;
    }
    this.isEmpty = function (Val) {
        if (typeof Val === "string") return Val.isEmpty();//*** isEmpty function from ExtensionMethods file ***
        if (Val === undefined || Val === null) return true;
        if (Val === 0 || Val === false) return false;
        if (Val) return false;//*** will evaluate to true if value is not: 0, false ***
        else return true;
    }
    this.isUndefined = function (val) {
        return (typeof (val) == undefined);
    }
    this.isDefined = function (val) {
        return this.isUndefined(val) == false;
    }
    this.isBrowserIE = function () {
        var ua = window.navigator.userAgent;

        // Test values; Uncomment to check result …

        // IE 10
        // ua = 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0)';

        // IE 11
        // ua = 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko';

        // Edge 12 (Spartan)
        // ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 Edge/12.0';

        // Edge 13
        // ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586';

        var msie = ua.indexOf('MSIE ');
        if (msie > 0) {
            //// IE 10 or older => return version number
            //return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
            return true;
        }

        var trident = ua.indexOf('Trident/');
        if (trident > 0) {
            //// IE 11 => return version number
            //var rv = ua.indexOf('rv:');
            //return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
            return true;
        }

        var edge = ua.indexOf('Edge/');
        if (edge > 0) {
            //// Edge (IE 12+) => return version number
            //return parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10);
            return true;
        }

        // other browser
        return false;
    }

    this.isMobile = function () {
        
        var lPlatforms = (navigator.userAgent.match(/Android/i) ||
            navigator.userAgent.match(/webOS/i) ||
            navigator.userAgent.match(/iPad/i) ||
            navigator.userAgent.match(/iPhone/i) ||
            navigator.userAgent.match(/iPod/i) ||
            navigator.userAgent.match(/BlackBerry/i) ||
            navigator.userAgent.match(/Windows Phone/i)
            );
        return lPlatforms != null && lPlatforms.length > 0;
    }
    this.isAppleSafari = function () {

        var lPlatforms = (navigator.userAgent.match(/iPad/i) ||
            navigator.userAgent.match(/iPhone/i) ||
            navigator.userAgent.match(/iPod/i) ||
            navigator.userAgent.match(/Mac/i) 
            );
        //var sMobile = this.isMobile() && navigator.userAgent.match(/Safari/i);
        return lPlatforms != null && lPlatforms.length > 0;
    }

    this.hasVal = function (val)
    {
        return !this.isNullOrEmpty(val);
    }
    this.equalsLowerCase = function (val1, val2) {
        return this.trimString(val1).toLowerCase() == this.trimString(val2).toLowerCase();
    }

    this.equalsWithSplit = function (str1, strSplit, sComma) {
        if (!(this.hasVal(str1) && this.hasVal(strSplit))) return false;
        str1 = this.trimString(str1);
        strSplit = this.trimString(strSplit);
        sComma = (sComma || ',');
        if (strSplit.indexOf(sComma) > -1) {
            var arrStr = strSplit.split(sComma);
            return arrStr.indexOfLowerCase(str1);//*** fn indexOfLowerCase into ExtensionMethods.js file
        } else {
            return this.equalsLowerCase(str1, strSplit);
        }
    }
    this.includesAnyWithSplit = function (str1, str2, sComma) {
        if (!(this.hasVal(str1) && this.hasVal(str2))) return false;
        str1 = this.trimString(str1);
        str2 = this.trimString(str2);
        sComma = (sComma || ',');

        return str1.split(sComma).includesAny(str2.split(sComma));
    }

    this.indexOfLowerCase = function (val1, val2) {
        return this.trimString(val1).toLowerCase().indexOf(this.trimString(val2).toLowerCase()) >= 0;
    }
    
    this.startWithLowerCase = function (val1, val2) {
        return this.trimString(val1).toLowerCase().indexOf(this.trimString(val2).toLowerCase()) == 0;
    }
    this.dateCompare = function (DateA, DateB) {
        // this function is good for dates > 01/01/1970
        var a = DateA;//new Date(DateA);
        var b = DateB;//new Date(DateB);

        var msDateA = Date.UTC(a.getFullYear(), a.getMonth() + 1, a.getDate());
        var msDateB = Date.UTC(b.getFullYear(), b.getMonth() + 1, b.getDate());

        if (parseFloat(msDateA) < parseFloat(msDateB))
            return -1;  // lt
        else if (parseFloat(msDateA) == parseFloat(msDateB))
            return 0;  // eq
        else if (parseFloat(msDateA) > parseFloat(msDateB))
            return 1;  // gt
        else
            return null;  // error
    }
    this.toBool = function (val) {
        /// <summary>String to Bool or False</summary>
        /// <returns type="Bool"></returns>
        if (this.isNullOrEmpty(val)) {
            return false;
        }
        val += "";
        if (val.toLowerCase() === "true" || val.toLowerCase() === "yes" || val === "1") {
            return true;
        }
        if (val.toLowerCase() === "false" || val.toLowerCase() === "no" || val === "0") {
            return false;
        }
        //return this.isNullOrEmpty() ? false : !!this;
    }
    this.toNumber = function (val, defaultVal) {
        var result = 0;
        if (defaultVal) result = defaultVal;
        if (isFinite(val)) {
            return Number(val);
        }
        return result;
    }
    this.toFloat = function (val, defaultVal) {        
        var result = 0;
        if (defaultVal) result = defaultVal;
        if (Number.isNaN(parseFloat(val)) == false) {
            return parseFloat(val);
        }
        return result;
    }
    this.convertCurrencyToNumber = function (val, defaultVal) {
        if (!this.hasVal(val)) return defaultVal;

        var result = 0;
        if (defaultVal) result = defaultVal;

        var numberString = val.replace(/[^0-9.-]+/g, "");

        if (isFinite(numberString)) {
            result = parseFloat(numberString);
        }
        return result;
    }
    this.toCurrency = function (val)
    {
        if (isFinite(val))
        {
            return Number(val).toCurrency();
        }
        return "";
    }
    this.toCurrencyZero = function (val) {
        if (isFinite(val))
        {
            return Number(val).toCurrency();
        }
        return 0;
    }

    this.getGSTAmount = function (priceInc) {
        if (isFinite(priceInc) && Number(priceInc) > 0) {
            var val = priceInc / 11;
            return val;
        }
        return null;
    }
    this.getPriceInc = function (priceEx, gstRate) {
        if (isFinite(priceEx) && Number(priceEx) > 0) {
            var val = priceEx * (1 + (gstRate / 100));
            return val;
        }
        return null;
    }
    this.to5CentRounding = function (val) {
        if (isFinite(val) && Number(val) > 0) {
            //var price = "$" + (Math.round((val) * 20) / 20).toCurrency(2);
            //if (window.webApp && this.toBool(window.webApp.isPriceSpanFormat) == true) {
            //    price = price.replace(/(\D*)(\d*\.)(\d*)/, '<span style="font-size:16px;">$1</span><span style="font-size:22px;">$2</span><span style="font-size:14px;">$3</span>');
            //}
            //return price;
            if (window.webApp && window.webApp.isUnuse5CentRoundingFormat && window.webApp.isUnuse5CentRoundingFormat == true)
            {
                return "$" + Number(val).toCurrency(2);
            }
            return "$" + (Math.round((val) * 20) / 20).toCurrency(2);
        }
        
        return "";
    }
    this.toLowerCaseExt = function (val) {
        if (this.hasVal(val) == false) return "";        
        return this.trimString(val).toLowerCase();
    }
    this.toUpperFirstChar = function (val) {
        if (this.hasVal(val) == false) return "";
        var arr = val.split(' ');
        for (var i = 0; i < arr.length; i++) {
            if (this.hasVal(arr[i]))
            {
                arr[i] = arr[i].length > 0 ? arr[i].charAt(0).toUpperCase() + arr[i].substr(1).toLowerCase() : arr[i].toUpperCase();
            }
        }
        return arr.join(' ');
    }

    //#region String Left, Right, Mid
    this.leftString = function(text, length)
    {
        /// Return characters starting from the left of the string/text; text.Substring(0, length);
        if (this.isEmpty(text)) return text;
        if (length < 0) return text;
        return (text.length <= length) ? text : text.substring(0, length);
    }
    this.rightString = function (text, length) {
        /// Return characters starting from the right of the string/text;
        if (this.isEmpty(text)) return text;
        if (length < 0) return text;
        return (text.length <= length) ? text : text.substring(text.length - length , length);
    }
    this.midString = function (text, startIndex, length) {
        /// Return characters starting from the startIndex of the string/text;
        if (this.isEmpty(text)) return text;
        if (startIndex < text.length) {
            var maxLength = text.length - startIndex;
            if (length <= 0 || length >= maxLength) {
                return text.substring(startIndex, maxLength);
            } else {
                return text.substring(startIndex, length);
            }
        } else {
            return "";
        }
        if (length < 0) return text;
        return (text.length <= length) ? text : text.substring(0, length);
    }
    this.ellipsis3Dot = function (text, length) {
        /// Return characters starting from the left of the string/text and Add 3 dots at end of text
        if (this.isEmpty(text)) return text;
        if (length < 0) return text;
        return (text.length <= length) ? text : text.substring(0, length) + '...';
    }
    //#endregion

    //#region datetime
    this.dateParse = function (Val) {
        /// <summary>ResponseData to Date or Null</summary>
        /// <returns type="Date"></returns>
        return isNullOrEmpty(Val) ? null : Date.parse(Val);// kendo.parseDate(Val);
    }
    this.formatDateNumberToDate = function (sDateNumber) {
        /// <summary>format datetime "/Date(1533707940000)/" to Date</summary>
        /// <returns type="Date"></returns>      
        if (this.isNullOrEmpty(sDateNumber)) return null;
        if (typeof sDateNumber !== 'string') return sDateNumber;
        return this.isNullOrEmpty(sDateNumber) ? null : new Date(parseInt(sDateNumber.replace("/Date(", "").replace(")/", ""), 10));
    }
    //this.formatDateNumberToDate = function (sDateNumber) {
    //    /// <summary>format datetime "/Date(1533707940000)/" to Date</summary>
    //    /// <returns type="Date"></returns>      
    //    if (this.isNullOrEmpty(sDateNumber)) return null;
    //    if (typeof sDateNumber !== 'string') return sDateNumber;
    //    var iDateNum = parseInt(sDateNumber.replace("/Date(", "").replace(")/", ""), 10);
    //    function z(n) { return (n < 10 ? '0' : '') + n }
    //    var offset = new Date().getTimezoneOffset();
    //    var sign = offset < 0 ? '+' : '-';
    //    offset = Math.abs(offset);//mins
    //    if (sign == '+') {
    //        iDateNum = iDateNum + ((offset * 60) * 1000) //millisecond
    //    } else {
    //        iDateNum = iDateNum - ((offset * 60) * 1000) //millisecond
    //    }
    //    return new Date(iDateNum);
    //}
    this.getMyTimezoneOffset = function () {
        function z(n){return (n<10? '0' : '') + n}
        var offset = new Date().getTimezoneOffset();
        var sign = offset < 0? '+' : '-';
        offset = Math.abs(offset);
        return sign + z(offset/60 | 0) + z(offset%60); //return +0700
    }
    this.stringToDate = function (sDate, format) {
        var normalized = sDate.replace(/[^a-zA-Z0-9]/g, '-');
        var normalizedFormat = format.toLowerCase().replace(/[^a-zA-Z0-9]/g, '-');
        var formatItems = normalizedFormat.split('-');
        var dateItems = normalized.split('-');

        var monthIndex = formatItems.indexOf("mm");
        var dayIndex = formatItems.indexOf("dd");
        var yearIndex = formatItems.indexOf("yyyy");
        var hourIndex = formatItems.indexOf("hh");
        var minutesIndex = formatItems.indexOf("ii");
        var secondsIndex = formatItems.indexOf("ss");

        var today = new Date();

        var year = yearIndex > -1 ? dateItems[yearIndex] : today.getFullYear();
        var month = monthIndex > -1 ? dateItems[monthIndex] - 1 : today.getMonth() - 1;
        var day = dayIndex > -1 ? dateItems[dayIndex] : today.getDate();

        var hour = hourIndex > -1 ? dateItems[hourIndex] : 0; //today.getHours();
        var minute = minutesIndex > -1 ? dateItems[minutesIndex] : 0; //today.getMinutes();
        var second = secondsIndex > -1 ? dateItems[secondsIndex] : 0; //today.getSeconds();

        return new Date(year, month, day, hour, minute, second);
    }
    this.toDateTime = function (sDateStrISO) {
        if (sDateStrISO != null && this.hasVal(sDateStrISO)) {
            return new Date(sDateStrISO);
        } else {
            return null;
        }
    }
    this.toISOStr = function (dtValue) {
        if (dtValue != null) {
            return dtValue.toISOString();
        } else {
            return null;
        }
    }
    //#endregion

    //#region general function
    this.generateUID = function () {
        function s4() {
            var sStr = Math.floor((1 + Math.random()) * 0x10000)
              .toString(16)
              .substring(1);
            if (sStr)
            {
                sStr = sStr.replace(/ /g, '+');
            }
            return sStr;
        }
        return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
          s4() + '-' + s4() + s4() + s4();
    }
    this.generateKey = function (iLen) {
        iLen = iLen || 10;
        var sStr = this.generateUID();
        sStr = sStr.replace(/-/g, '');
        return this.leftString(sStr, iLen);
    }
    
    this.getFileExtension = function (fileName) {
        return fileName.split('.').pop();
    }
    this.getFileNameFromPath = function (fileName) {
        if (fileName)
            return fileName.replace(/^.*[\\\/]/, '');
        else
            return "";
    }
    this.getFileNameFromPathWithOutExtension = function (fileName) {
        if (fileName)
            return this.getFileNameFromPath(fileName).replace(/\.[^/.]+$/, '');
        else
            return "";
    }    
    this.getWeekdays = function ()
    {
        var weekday = new Array(7);
        weekday[0] = "Sunday";
        weekday[1] = "Monday";
        weekday[2] = "Tuesday";
        weekday[3] = "Wednesday";
        weekday[4] = "Thursday";
        weekday[5] = "Friday";
        weekday[6] = "Saturday";
        return weekday;
    }
    this.getParameterByName = function (name, url) {
        ///query string: ?foo=lorem&bar=&baz
        ///var foo = getParameterByName('foo'); // "lorem"
        ///var bar = getParameterByName('bar'); // "" (present with empty value)
        ///var baz = getParameterByName('baz'); // "" (present with no value)
        ///var qux = getParameterByName('qux'); // null (absent)
        if (!url) url = window.location.href;
        name = name.replace(/[\[\]]/g, '\\$&');
        var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
            results = regex.exec(url);
        if (!results) return null;
        if (!results[2]) return '';
        return decodeURIComponent(results[2].replace(/\+/g, ' '));
    }
    this.setParameterByName = function (url, name, val) {
        ///query string: ?foo=lorem&bar=&baz 
        if (this.hasVal(name) == false) return url;
        url = this.trimString(url);        
        if (this.hasVal(val)) val = window.encodeURIComponent(val);
        
        var sFlag = name + '=' + val;
        var sExisting = this.getParameterByName(name);

        if (sExisting === null) {
            var sKey = '';
            if (url.indexOf('?') < 0) {
                //add ?
                sKey = '?';
            } else {
                var sSplitUrl = url.split('?');
                if (sSplitUrl.length > 1) {
                    //add &
                    sKey = '&';
                } else {
                    //add 
                }
            }
            url = url + sKey + sFlag;
        } else {
            //replace
            url = url.replace(name + '=' + sExisting, sFlag);
        }
        return url;
    }
    this.calculateRepayment = function (price, financeFees, interestRate, loanTerm, loanType, isTo5Cent) {
        return this.calculateRepayment2(price, financeFees, interestRate, loanTerm, loanType, null, isTo5Cent);              
    }
    this.calculateRepayment3 = function (price, financeFees, interestRate, loanTerm, loanType, balloonPercent, isTo5Cent) {
        if (balloonPercent != null && balloonPercent > 0)
        {
            balloonPercent = price * balloonPercent;
        }
        return this.calculateRepayment2(price, financeFees, interestRate, loanTerm, loanType, balloonPercent, isTo5Cent);
    }
    this.calculateRepayment2 = function (price, financeFees, interestRate, loanTerm, loanType, balloon, isTo5Cent)
    {
        /// <summary>Finance calculate payment</summary>
        /// <param name="price" type="number">loan amount</param>
        /// <param name="loanTerm" type="number">default number of year.</param>
        /// <param name="loanType" type="string">Weekly/Fortnightly/Monthly/Yearly</param>
        /// <param name="isTo5Cent" type="bool">if true, return string format $1.25 / $$1.30</param>
        /// <returns type="function">Return function</returns>

        if (price < 1) return null;
        if (typeof (isTo5Cent) == undefined || isTo5Cent == null) isTo5Cent = true;


        if (this.hasVal(financeFees) == false) {
            financeFees = 0;
        }
        if (this.hasVal(interestRate) == false) {
            interestRate = 0.1495;
        }

        if (this.hasVal(loanTerm) == false) {
            loanTerm = 60;//default 5 years
        }

        var iLoanYear = loanTerm;
        var iLoanWeekly = 0;
        switch (loanType) {            
            case 'Fortnightly':
                iLoanWeekly = 26;
                if (loanTerm > 7) iLoanYear = loanTerm / 12;
                break;
            case 'Monhly':
            case 'Monthly':
                iLoanWeekly = 12;
                iLoanYear = loanTerm / iLoanWeekly;
                break;
            case 'Yearly':
                iLoanWeekly = 1;
                if (loanTerm > 7) iLoanYear = loanTerm / 12;
                break;
            case 'Weekly':            
            default:
                iLoanWeekly = 52;
                if (loanTerm > 7) iLoanYear = loanTerm / 12;
                break;
        }
        
        var dInterestRate = (interestRate / iLoanWeekly);//interest rate weekly/monthly ----dInterestRateMon
        var iDuration = iLoanYear * iLoanWeekly;// (double)(iLoanYear * totalMonthly);// duration (increments - weeks/months) ------iDuration
        var dLoanAmount = (-1 * (price + financeFees));
        //var balloon = 0;//balloon
        if (this.hasVal(balloon) == false) {
            balloon = 0;//default 5 years
        }
        
        //var result = (h + (h + p) / (Math.pow(1 + v, d) - 1)) * (v * -1 / m);
        var result = (dLoanAmount + (dLoanAmount + balloon) / (Math.pow(1 + dInterestRate, iDuration) - 1)) * (dInterestRate * -1 / 1);
        if (isTo5Cent == true) {
            return this.to5CentRounding(result);
        } else {
            return result;
        }
    }
    this.cWeekdayToStr = function (iDay)
    {
        ///convert week day (number) to string. ex: 0 = Sunday
        if (this.isNullOrEmpty(iDay)) return null;
        if (iDay >= 0 && iDay < 7) {
            return this.getWeekdays()[iDay];
        }
        else {
            return null;
        }
    }
    this.cWeekdayToInt = function (sDay)
    {
        ///convert week day (str) to int. ex: Sunday = 0
        if (this.isNullOrEmpty(sDay)) return null;
        var iResult = null;
        var weekday = this.getWeekdays();
        for (var i = 0; i < 7; i++) {
            if (weekday[i] == sDay)
            {
                sResult = i;
                break;
            }
        }
        return iResult;
    }
    this.replaceEndStr = function (sVal, sReplacement, sFind) {
        if (this.hasVal(sVal) == false) return "";
        return sVal.replace(new RegExp(sFind + '$'), sReplacement);
    }
    this.replaceAllSpaces = function (sVal, sReplacement) {
        if (this.hasVal(sVal) == false) return "";
        //return sVal.replace(new RegExp(sFind + '$'), sReplacement);
        var str = sVal.replace(/\s+/g, sReplacement);
        if (!str.isNullOrEmpty())
        {
            str = str.toLowerCase()
        }
        return str;
    }
    this.replaceAllSpecialCharsToDashLower = function (sVal)
    {
        if (this.hasVal(sVal))
        {
            sVal = sVal.replace(/[^a-z0-9]/gi, '-');
            sVal = sVal.replace(/-+/g, '-');
        }

        if (this.hasVal(sVal) && sVal.substring(sVal.length, sVal.length - 1) == "-") {
            sVal = sVal.substring(0, sVal.length - 1);
        }

        return this.trimString(sVal).toLowerCase();
    }
    this.replaceAllSpecialCharsToSpace = function (sVal) {
        if (this.hasVal(sVal)) {
            sVal = sVal.replace(/[^a-z0-9]/gi, ' ');
            sVal = sVal.replace(/ +/g, ' ');
        }

        if (this.hasVal(sVal) && sVal.substring(sVal.length, sVal.length - 1) == " ") {
            sVal = sVal.substring(0, sVal.length - 1);
        }

        return this.trimString(sVal).toLowerCase();
    }
    this.replaceAllAlphabetic = function (sVal)
    {
        if (this.hasVal(sVal)) {
            sVal = sVal.replace(/[^0-9]/gi, '');
        }
        return sVal;
    }
    this.redirectTo = function (uri, defaultUri) {
        if (this.isNullOrEmpty(uri)) {
            window.location.href = this.trimString(defaultUri);
        } else {
            window.location.href = uri;
        }
    }
    this.historyBack = function (opts)
    {
        /**** Minh::20240705:: 
        *
        * in Javascript
        * stackoverflow.com/questions/3588315/how-to-check-if-the-user-can-go-back-in-browser-history-or-not
        * case 1: open new empty tab, and run a page          => history.length = 2 => we CANNOT use back event 
        * case 2: right click open new tab from result        => history.length = 1 => we CANNOT use back event
        * case 3: redirect to detail from result              => history.length > 1 => we CAN use back event
        *
        * in C# Request.UrlReferrer
        * case 1: open new empty tab, and run a page          => history.length = 2 => Request.UrlReferrer == null => we CANNOT use back event 
        * case 2: right click open new tab from result        => history.length = 1 => Request.UrlReferrer != null => we CANNOT use back event
        * case 3: redirect to detail from result              => history.length > 1 => Request.UrlReferrer != null => we CAN use back event
        *
        * if history.length == 1  => CANNOT call back() event => redirect to page with default-value
        * if history.length => 2 
        *    if from new temp tab => CANNOT call back() event => redirect to page with default-value (timeout check prevPage)
        *    if from result  page => CAN    call back() event => redirect to page with back() event
        */

        if (this.hasVal(opts.defVal) == false) opts.defVal = window.webApp.util.getUrlHasPrefix("/"); //window.webApp.rootURL;
        else opts.defVal = window.webApp.util.getUrlHasPrefix(opts.defVal);

        if (this.hasVal(opts.urlRef) == false)
        {
            this.redirectTo(opts.defVal);//*** if Url Referrer of server-side is empty, redirect to page with default-value
            return;
        }

        try {
            if (window.history.length < 2) {
                this.redirectTo(opts.defVal);
            }
            else
            {
                //*** server-side: UrlReferrer (urlRef)
                
                     
                var prevPage = window.location.href;                
                window.history.back();
                
                setTimeout(function () {

                    if (window.location.href == prevPage) {
                        this.redirectTo(opts.defVal);
                    }
                }, 500);
            }
            
        } catch (e) {
            this.redirectTo(opts.defVal);
        }
    }
    
    this.roundToPrecision = function (price, precision) {
        //ex: round_to_precision(36.14, 0.05) return 36.15
        var y = +price + (precision === undefined ? 0.5 : precision / 2);
        return y - (y % (precision === undefined ? 1 : +precision));
    }
    this.sumOfVal = function (data, key1, key2) {
        var iVal = null;
        if (data && data.length > 0 && this.hasVal(key1))
        {
            if (this.hasVal(key2)) {
                for (var i = 0; i < data.length; i++) {
                    iVal = this.toNumber(iVal) + (this.toNumber(data[i][key1]) * this.toNumber(data[i][key2]));
                }
            } else {
                for (var i = 0; i < data.length; i++) {
                    iVal = this.toNumber(iVal) + this.toNumber(data[i][key1]);
                }
            }            
        }
        return iVal;
    }

    //#endregion

    //#region AusPost functions
    
    this.ausPostDelivery =
    {
        isValidLength: function (value) {
            return (value > 0 && value <= 105);
        },
        isValidWeight: function (value) {
            return (value > 0 && value <= 22);
        },
        isValidCubicMeter: function (valueL, valueW, valueH) {
            return (((valueL / 100) * (valueW / 100) * (valueH / 100)) < 0.25);
        },
        isValidByObj: function (oItem) {
            if (oItem.L < 0 || oItem.W < 0 || oItem.H < 0 || oItem.WT < 0) return false;
            if (this.isValidLength(oItem.L) == false || this.isValidLength(oItem.W) == false || this.isValidLength(oItem.H) == false) {
                console.log('The length cannot exceed 105cm.');
                return false;
            }
            if (this.isValidWeight(oItem.WT) == false) {
                console.log('The maximum weight of a parcel is 22 kg.');
                return false;
            }
            if (this.isValidCubicMeter(oItem.L, oItem.W, oItem.H) == false) {
                console.log('The Cubic Measurement cannot exceed 0.25 cubic meters.');
                return false;
            }
            return true;
        },
        isValidParcel: function (iLength, iWidth, iHeight, iWeight)
        {
            return this.isValidByObj({ L: iLength, W: iWidth, H: iHeight, WT: iWeight });
        }
    }

    //#endregion

    //#region pagination
    this.generatePagination = function (TotalRecords, TotalPage, CurrentPage) {
        var arrayPages = [];
        var minPage = 1;
        // output nice pagination
        // always have a group of 5
        var minRange = Math.max(minPage, CurrentPage - 2);
        var maxRange = Math.min(TotalPage, CurrentPage + 2);
        if (minRange != minPage) {
            arrayPages.push({
                idx: arrayPages.length,
                val: minPage + ""
            });
            arrayPages.push({
                idx: arrayPages.length,
                val: "..."
            });
        }
        for (var i = minRange; i <= maxRange; i++) {
            arrayPages.push({
                idx: arrayPages.length,
                val: i + ""
            });
        }
        if (maxRange != TotalPage) {
            arrayPages.push({
                idx: arrayPages.length,
                val: "..."
            });
            arrayPages.push({
                idx: arrayPages.length,
                val: TotalPage + ""
            });
        }
        return arrayPages;
    }
    this.pagination = {
        next: function (iPageNum, iTotal, cbReload)
        {
            if (iPageNum < iTotal)
            {
                cbReload(iPageNum + 1);
            }
        },
        page: function (sPageNum, cbReload)
        {
            if (sPageNum.indexOf('...') < 0)
            {
                cbReload(Number(sPageNum));
            }
        },
        prev: function (iPageNum, cbReload) {
            if (iPageNum > 1) {
                cbReload(iPageNum - 1);
            }
        }
    }
    //#endregion
    this.scrollToTop = function (ele, minusTop)
    {
        minusTop = minusTop || 0;

        var jq;
        if (ele) {
            jq = ele;
        } else {
            jq = $('html, body');
        }        
        $('html, body').animate({
            scrollTop: jq.offset().top - minusTop
        }, 1000);
    }
    this.scrollToTopNotAnimate = function (ele, minusTop) {
        minusTop = minusTop || 0;

        var jq;
        if (ele) {
            jq = ele;
        } else {
            jq = $('html, body');
        }
        $('html, body').scrollTop((jq.offset().top - minusTop));
    }

    //#region Cookie
    this.deleteCookie = function (c_name) {
        document.cookie = encodeURIComponent(c_name) + "=deleted; expires=" + new Date(0).toUTCString();
    }
    this.setCookie = function (c_name, value, exdays) {
        var exdate = new Date();
        if (exdays == null) {
            exdate.setDate(exdate.getDate());
        } else {
            exdate.setDate(exdate.getDate() + exdays);
        }
        var c_value = escape(value) + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString());
        document.cookie = c_name + "=" + c_value;
    }
    this.getCookie = function (c_name) {
        var c_value = document.cookie;
        var c_start = c_value.indexOf(" " + c_name + "=");
        if (c_start == -1) {
            c_start = c_value.indexOf(c_name + "=");
        }
        if (c_start == -1) {
            c_value = null;
        }
        else {
            c_start = c_value.indexOf("=", c_start) + 1;
            var c_end = c_value.indexOf(";", c_start);
            if (c_end == -1) {
                c_end = c_value.length;
            }
            c_value = unescape(c_value.substring(c_start, c_end));
        }
        return c_value;
    }
    //#endregion
    
    //this.mappingData = function (dataItem, lMappingFields)
    //{
    //    //lMappingFields = [{ from: '', to: '' }];
    //    for (var i = 0; i < lMappingFields.length; i++) {
    //        if (this.hasVal(dataItem[lMappingFields[i].from])) {
    //            dataItem[lMappingFields[i].to] = dataItem[lMappingFields[i].from];
    //        }
    //    }
    //}
    this.buildQueryString = function (obj) {
        return buildQueryStringExtensionMethod(obj);
    }
    this.mappingContactInfor = function (oMail, fieldName) {
        
        if (this.isDefined(oMail) && oMail != null && this.isDefined(oMail[fieldName])) // && (this.hasVal(oMail[fieldName]) || (typeof oMail[fieldName]) == 'boolean')
        {
            var isBooleanValue = false;
            var mappingField = null;
            switch (fieldName) {
                case 'ContactName':
                case 'inputFullName':
                case 'inputYourName':
                case 'inputFirstName':
                case 'inputName':
                case 'FullName':
                    mappingField = 'FirstName';
                    break;
                case 'inputLastName':
                    mappingField = 'LastName';
                    break;
                //case 'MailFrom':
                case 'inputEmail':
                    mappingField = 'ContactEmail';
                    break;
                case 'inputPhone':
                case 'PhoneNumber':
                    mappingField = 'ContactNumber';
                    break;
                case 'IsReceivePromo':
                case 'inputNewsSpecial':
                    mappingField = 'FlagSubscribeForMarketing';
                    isBooleanValue = true;
                    break;
                case 'IsContactedBySalesperson':
                case 'inputSalesPerson':
                    mappingField = 'FlagSalesContactRequest';
                    isBooleanValue = true;
                    break;
                default:
                    break;
            }
            if (mappingField != null) {
                if (oMail[fieldName] != null)
                {
                    if (isBooleanValue) {
                        oMail[mappingField] = this.toBool(oMail[fieldName]);
                    } else {
                        if(this.hasVal(oMail[fieldName])) oMail[mappingField] = this.trimString(oMail[fieldName]);
                    }
                }
                
            }

        }
    }

    var _base64 = {
        _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
        _utf8_encode: function (e) { e = e.replace(/\r\n/g, "\n"); var t = ""; for (var n = 0; n < e.length; n++) { var r = e.charCodeAt(n); if (r < 128) { t += String.fromCharCode(r) } else if (r > 127 && r < 2048) { t += String.fromCharCode(r >> 6 | 192); t += String.fromCharCode(r & 63 | 128) } else { t += String.fromCharCode(r >> 12 | 224); t += String.fromCharCode(r >> 6 & 63 | 128); t += String.fromCharCode(r & 63 | 128) } } return t },
        _utf8_decode: function (e) { var t = ""; var n = 0; var r = c1 = c2 = 0; while (n < e.length) { r = e.charCodeAt(n); if (r < 128) { t += String.fromCharCode(r); n++ } else if (r > 191 && r < 224) { c2 = e.charCodeAt(n + 1); t += String.fromCharCode((r & 31) << 6 | c2 & 63); n += 2 } else { c2 = e.charCodeAt(n + 1); c3 = e.charCodeAt(n + 2); t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63); n += 3 } } return t },
        encode: function (e) { var t = ""; var n, r, i, s, o, u, a; var f = 0; e = _base64._utf8_encode(e); while (f < e.length) { n = e.charCodeAt(f++); r = e.charCodeAt(f++); i = e.charCodeAt(f++); s = n >> 2; o = (n & 3) << 4 | r >> 4; u = (r & 15) << 2 | i >> 6; a = i & 63; if (isNaN(r)) { u = a = 64 } else if (isNaN(i)) { a = 64 } t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a) } return t },
        decode: function (e) { var t = ""; var n, r, i; var s, o, u, a; var f = 0; e = e.replace(/[^A-Za-z0-9+/=]/g, ""); while (f < e.length) { s = this._keyStr.indexOf(e.charAt(f++)); o = this._keyStr.indexOf(e.charAt(f++)); u = this._keyStr.indexOf(e.charAt(f++)); a = this._keyStr.indexOf(e.charAt(f++)); n = s << 2 | o >> 4; r = (o & 15) << 4 | u >> 2; i = (u & 3) << 6 | a; t = t + String.fromCharCode(n); if (u != 64) { t = t + String.fromCharCode(r) } if (a != 64) { t = t + String.fromCharCode(i) } } t = _base64._utf8_decode(t); return t },
        generateCode: function (iWebsiteId, capId, sDateStrShort) {
            var sCode = iWebsiteId + capId + sDateStrShort;//code format: webid + form.CapId + dd/MM/yyyy
            return this.encode(sCode);
        }
    }

    this.base64Extend = _base64;


    return this;
}


function historyState() {
    var DOM_EVENT = {
        RESIZE: 'resize',
        SCROLL: 'scroll',
        CLICK: 'click',
        KEYDOWN: 'keydown',
        FOCUS: 'focus',
        INPUT: 'input'
    };

    var _unused = null;//sUnused || 'state-title';
    var _url = null;//sUrl || window.location.pathname;
    var _state = {
        data: null,
        scrollPosition: null
    };
    var _hasHistoryPushed = false;


    var _init = function (opts) {
        _unused = opts.unused || 'state-title';
        _url = opts.url || window.location.pathname;

        if (window.history.state != null) {
            _state.data = window.history.state.data;
            _state.scrollPosition = window.history.state.scrollPosition;
            _hasHistoryPushed = true;
        }
        _wireupEvents();
    }

    var _wireupEvents = function () {

        $(document).on(DOM_EVENT.CLICK, function (event) {
            //var $event = event;            
            //$scope.$evalAsync(function () {
            //    _handleDocumentClick($event);
            //});
            if (_hasHistoryPushed == true) {
                _updatePosition();
            }
        });
    }    
    var _scrollTo = function (delay) {
        delay = delay || 1000;
        if (_hasHistoryPushed == true && _state.scrollPosition != null)
        {
            window.setTimeout(function(){
                $(window).scrollTop(_state.scrollPosition);
            }, delay);
        }
            
    }

    var _pushState = function () {
        window.history.pushState(_state, _unused, _url);
        _hasHistoryPushed = true;
    }
    var _replaceState = function () {
        window.history.replaceState(_state, _unused, _url);
        //window.history.replaceState({}, 'state-title', window.location.pathname);
    }
    var _updatePosition = function () {
        _state.scrollPosition = $(window).scrollTop();
        _replaceState();
    }

    var _hasData = function () {
        return _state.data != null;
    }


    //**** public functions
    this.push = function (stateData) {
        _state.data = stateData;
        _state.scrollPosition = $(window).scrollTop();
        _pushState();
    }

    //this.updateState = function () {
    //    _state.scrollPosition = $(window).scrollTop();
    //    _updatePosition();
    //}

    this.getStateData = function () {
        return _state.data;
    }
    this.hasData = function ()
    {
        return _hasData();
    }
    this.scrollToPrevious = function (delay) {
        _scrollTo(delay);
    }
    this.init = function (sUnused, sUrl) {
        _init({ unused: sUnused, url: sUrl});
    }


    return this;
};
//#region String Extensions
if (typeof String.prototype.trim !== 'function') {
    String.prototype.trim = function () {
        return this.replace(/^\s+|\s+$/g, '');
    }
}
String.prototype.trimString = function () {
    return this.isNullOrEmpty() ? "" : this.trim();
}
String.prototype.isEmpty = function () {
    return (this.length === 0 || !this.trim());
}
String.prototype.isNullOrEmpty = function () {
    return (this === undefined || this === null || this.isEmpty());
}
String.prototype.hasVal = function () {
    return !(this === undefined || this === null || this.isEmpty());
}
String.prototype.toDateNull = function () {
    /// <summary>String to Date or Null</summary>
    /// <returns type="Date"></returns>
    return this.isNullOrEmpty() ? null : new Date(this.trimString());
}
String.prototype.toBool = function () {
    /// <summary>String to Bool or False</summary>
    /// <returns type="Bool"></returns>
    if (this.isNullOrEmpty()) {
        return false
    }
    if (this.toLowerCase() === "true") {
        return true
    }
    if (this.toLowerCase() === "false") {
        return false
    }
    //return this.isNullOrEmpty() ? false : !!this;
}
String.prototype.isBool = function () {
    /// <summary>String to Bool or False</summary>
    /// <returns type="Bool"></returns>
    if (this.isNullOrEmpty()) {
        return false
    }

    if (this.toLowerCase() === "true" || this.toLowerCase() === "false") {
        return true;
    }
    else {
        return false;
    }
}
//#endregion

Number.prototype.toCurrency = function (n, x) {
    var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\.' : '$') + ')';
    return this.toFixed(Math.max(0, ~ ~n)).replace(new RegExp(re, 'g'), '$&,');
};

//#region Date Extensions
Date.prototype.toLocaleDateStringExt = function (options) {
    /// <summary>Uses day-month-year (dd/MM/yyyy)</summary>
    /// <returns type="String"></returns>
    if (IsNullOrEmpty(options)) options = { year: "numeric", month: "numeric", day: "2-digit" };
    return IsNullOrEmpty(this) ? "" : this.toLocaleDateString('en-GB', options);
}
Date.prototype.toLocaleTimeStringExt = function (options) {
    /// <summary>Uses hour:minute:second (HH:mm:ss)</summary>
    /// <returns type="String"></returns>    
    if (IsNullOrEmpty(options)) options = { hour: '2-digit', minute: '2-digit', second: '2-digit' };
    return IsNullOrEmpty(this) ? "" : this.toLocaleTimeString('en-GB', options);
}
Date.prototype.addDays = function (days) {
    var date = new Date(this.valueOf());
    date.setDate(date.getDate() + days);
    return date;
}
Date.prototype.toStartOfDay = function () {
    var year = this.getFullYear();
    var month = this.getMonth();
    var day = this.getDate();
    return new Date(year, month, day, 0, 0, 0);
}
Date.prototype.toEndOfDay = function () {
    var year = this.getFullYear();
    var month = this.getMonth();
    var day = this.getDate();
    return new Date(year, month, day, 23, 59, 59);
}
Date.prototype.toStartOfWeek = function () {
    //*** local time: 0 for Sunday, 1 for Monday, 2 for Tuesday, and so on

    //clone date object, so we don't mutate it
    var dt = this.toStartOfDay();// new Date(this);
    var dayOfWeek = dt.getDay();// get day of week
    var dayOfMonth = dt.getDate();// get day of week
    //day of month - day of week (-6 if Sunday), otherwise +1
    var diff = dayOfMonth - dayOfWeek + (dayOfWeek === 0 ? -6 : 1);
    return new Date(dt.setDate(diff));
}
Date.prototype.toEndOfWeek = function () {
    //*** local time: 0 for Sunday, 1 for Monday, 2 for Tuesday, and so on
    var dt = this.toEndOfDay().toStartOfWeek();
    return dt.addDays(+6);// new Date(dt.setDate(dt.getDate() + 6));
}
Date.prototype.toStartOfMonth = function () {
    var year = this.getFullYear();
    var month = this.getMonth();
    return new Date(year, month, 1, 0, 0, 0);
}
Date.prototype.toEndOfMonth = function () {
    var year = this.getFullYear();
    var month = this.getMonth();
    return new Date(year, month + 1, 0, 23, 59, 59);
}
Object.defineProperty(Date.prototype, 'toYYYYMMDDHHMMSS', {
    value: function () {
        function pad2(n) {  // always returns a string
            return (n < 10 ? '0' : '') + n;
        }

        return this.getFullYear() +
               pad2(this.getMonth() + 1) +
               pad2(this.getDate()) +
               pad2(this.getHours()) +
               pad2(this.getMinutes()) +
               pad2(this.getSeconds());
    }
});
//#endregion

//#region Array Extensions
//Array.prototype.getMaxByFieldName = function (field) {
//    //www.reddit.com/r/javascript/comments/37bhug/map_or_reduce_to_calculate_max_value_from_json/?st=jentf5wh&sh=453d55c5
//    //return Math.max.apply(Math,array.map(function(o){return o.y;}));
//    return this.reduce(function (max, x) { return (x[field] > max) ? x[field] : max; }, 0);
//}
//Array.prototype.getSelectedItem = function (value) {
//    var item = null;
//    //return this.trimString(val1).toLowerCase() == this.trimString(val2).toLowerCase();
//    for (var i = 0; i < this.length; i++) {
//        if (TrimString(this[i].Value).toLowerCase() == TrimString(value).toLowerCase())
//        {
//            item = this[i];
//        }
//    }
//    return item;
//}
//Array.prototype.removeItemByFieldName = function (val, field) {
//    for (var i = 0; i < this.length; i++) {
//        if (this[i][field] === val) this.splice(i, 1);
//    }
//}
//Array.prototype.removeItemByIndex = function (idx) {
//    this.splice(idx, 1);
//}
Object.defineProperty(Array.prototype, 'getMaxByFieldName', {
    //example: var aTemps = data.groupBy(function (item) { return item.NewModelMakeID; });
    enumerable: false,
    value: function (field) {
        return this.reduce(function (max, x) { return (x[field] > max) ? x[field] : max; }, 0);
    }
});
Object.defineProperty(Array.prototype, 'getSelectedItem', {
    //example: var aTemps = data.groupBy(function (item) { return item.NewModelMakeID; });
    enumerable: false,
    value: function (value) {
        var item = null;
        //return this.trimString(val1).toLowerCase() == this.trimString(val2).toLowerCase();
        for (var i = 0; i < this.length; i++) {
            var val1, val2;
            if (IsInteger(this[i].Value)) {
                val1 = this[i].Value;
                val2 = value;
            }
            else {
                val1 = TrimString(this[i].Value).toLowerCase();
                val2 = TrimString(value).toLowerCase();
            }
            if (val1 == val2) {
                item = this[i];
            }
        }
        return item;
    }
});
Object.defineProperty(Array.prototype, 'moveItemAt', {
    //example: arr.moveItemAt(arr.length, function(x){return x.Value == 'Att';}); //*** move to last item
    enumerable: false,
    value: function (position, comparer) {
        //var arr = this;
        for (var i = 0; i < this.length; i++) {
            if (comparer(this[i]))
            {
                this.splice(position, 0, this.splice(i, 1)[0]);
                break;
            }
        }
    }
});
Object.defineProperty(Array.prototype, 'removeItemByFieldName', {
    //example: var aTemps = data.groupBy(function (item) { return item.NewModelMakeID; });
    enumerable: false,
    value: function (val, field) {
        for (var i = 0; i < this.length; i++) {
            if (this[i][field] === val)
            {
                this.splice(i, 1);
                break;
            }
        }
        return this;
    }
});
Object.defineProperty(Array.prototype, 'removeItemByIndex', {
    //example: var aTemps = data.groupBy(function (item) { return item.NewModelMakeID; });
    enumerable: false,
    value: function (idx) {
        this.splice(idx, 1);
        return this;
    }
});
Object.defineProperty(Array.prototype, 'removeItem', {
    //*** lBreadcrumbs.removeItem(function (x) { return x.fieldName == lDeletings[i].fieldName && x.val == lDeletings[i].val; });
    enumerable: false,
    value: function (comparer) {

        for (var i = 0; i < this.length; i++) {
            if (comparer(this[i])) {
                this.splice(i, 1);
            }
        }
    }
});

Object.defineProperty(Array.prototype, 'groupBy', {
    //example: var aTemps = data.groupBy(function (item) { return item.NewModelMakeID; });
    enumerable: false,
    value: function (key) {
        var map = {};
        this.forEach(function (e) {
            var k = key(e);
            map[k] = map[k] || [];
            map[k].push(e);
        });
        return Object.keys(map).map(function (k) {
            return { key: k, key2: (k === 'null' ? '' : k), data: map[k] };//*** use key2 for orderby
        });
    }
});

Object.defineProperty(Array.prototype, 'groupBy2', {
    //example: var aTemps = data.groupBy(function (item) { return item.NewModelMakeID; });
    enumerable: false,
    value: function (key, sort) {
        var map = {};
        this.forEach(function (e) {
            var k = key(e);
            map[k] = map[k] || [];
            map[k].push(e);
        });

        return Object.keys(map).map(function (k) {
            var flagSort = '';
            if (sort && map[k].length > 0) {
                flagSort = sort(map[k][0]);
            } else {
                flagSort = k;//***default sort
            }
            return { key: k, sort: flagSort, data: map[k] };//*** use sort for orderby
        });

        //return records.sort(records.sortBy("sort", false, null));
    }
});

Object.defineProperty(Array.prototype, 'sortBy', {
    //example: var aTemps = $scope.lBreadcrumbs.sort($scope.lBreadcrumbs.sortBy("Sort", false, parseInt));
    //sort function has supported by browser
    enumerable: false,
    value: function (field, reverse, primer) {

        var key = primer ?
            function (x) { return primer(x[field]) } :
            function (x) { return x[field] };

        reverse = !reverse ? 1 : -1;

        return function (a, b) {
            return a = key(a), b = key(b), reverse * ((a > b) - (b > a));
        }
    }
});

// check if an element exists in array using a comparer function
// comparer : function(currentElement)
Object.defineProperty(Array.prototype, 'inArray', {
    //example: var aTemps = data.groupBy(function (item) { return item.NewModelMakeID; });
    enumerable: false,
    value: function (comparer) {
        for (var i = 0; i < this.length; i++) {
            if (comparer(this[i])) return true;
        }
        return false;
    }
});
Object.defineProperty(Array.prototype, 'includesAny', {
    //example: 
    //  [1, 2, 3, 4].includesAll([2, 9]); // true
    //  [1, 2, 3, 4].includesAll([8, 9]); // false
    enumerable: false,
    value: function (arr1) {       
        return this.some(a1 => arr1.includes(a1));
    }
});
Object.defineProperty(Array.prototype, 'includesAll', {
    //www.30secondsofcode.org/js/s/array-includes-any-or-all-values/#:~:text=or%20all%20values-,Check%20if%20a%20JavaScript%20array%20includes%20any%20or%20all%20values,array%20includes%20a%20specific%20value.
    //example: 
    //  [1, 2, 3, 4].includesAll([1, 4]); // true
    //  [1, 2, 3, 4].includesAll([1, 5]); // false
    enumerable: false,
    value: function (arr1) {
        return this.every(a1 => arr1.includes(a1));
    }
});

Object.defineProperty(Array.prototype, 'updateIfExists', {
    //example: $scope.oRecord.WSLClients.updateIfExists(data.item, function (x) { return (data.item.CLIUID == x.CLIUID); });
    enumerable: false,
    value: function (element, comparer) {
        for (var i = 0; i < this.length; i++) {
            if (comparer(this[i])) {
                this[i] = element;
                break;
            }
        }
        //return this;
        //return false;
    }
});

// adds an element to the array if it does not already exist using a comparer 
Object.defineProperty(Array.prototype, 'pushIfNotExist', {
    //example: eleLamListTemp.pushIfNotExist(angular.copy(ele), function (x) { return $(x).data("modelid") == $(ele).data("modelid"); });
    enumerable: false,
    value: function (element, comparer) {
        if (!this.inArray(comparer)) {
            this.push(element);
        }
    }
});
Object.defineProperty(Array.prototype, 'unshiftIfNotExist', {
    //example: eleLamListTemp.unshiftIfNotExist(angular.copy(ele), function (x) { return $(x).data("modelid") == $(ele).data("modelid"); });
    enumerable: false,
    value: function (element, comparer) {
        if (!this.inArray(comparer)) {
            this.unshift(element);
        }
    }
});
Object.defineProperty(Array.prototype, 'spliceIfNotExist', {
    //var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
    //myFish.splice(2, 0, 'drum');
    //myFish is ["angel", "clown", "drum", "mandarin", "sturgeon"]
    //example: response.oAusPostServices.service.spliceIfNotExist(moAUSPost, iIndexArray, function (oService) {return oService.code == moAUSPost.code; });
    enumerable: false,
    value: function (element, idx, comparer) {
        if (!this.inArray(comparer)) {
            this.splice(idx, 0, element);
        }
    }
});

Object.defineProperty(Array.prototype, 'indexOfLowerCase', {
    //example: ['Apple', 'nokia'].indexOfLowerCase('apple') => return true
    enumerable: false,
    value: function (val, fromIndex) {
        if (val === undefined || val === null || val.isEmpty()) return false;
        
        var idx = (fromIndex || 0),
        arrLen = this.length;
        var bVal = false;

        while (idx < arrLen) {
            if (this[idx].hasVal() && this[idx].toLowerCase() === val.toLowerCase()) {
                bVal = true;
                break;
            }
            idx++;
        }
        return bVal;
    }
});

Object.defineProperty(Array.prototype, 'outerExcludingJoin', {
    //*** This outerExcludingJoin function will return all of the records in the left table (Table_A) and all of the records in the right table (Table_B) that do not match
    //example: ['Apple', 'nokia'].diffLowerCase(['APPLE', 'samsung']) => return ['nokia', 'samsung']
    enumerable: false,
    value: function (arr2) {        
        //return this.filter(x => !arr2.includes(x));
        //*** includes() is not supported in Edge 13 (or earlier).
        //*** change to use indexOf()
        return this.filter(x => arr2.indexOfLowerCase(x) == false).concat(arr2.filter(x => this.indexOfLowerCase(x) == false));
    }
});
//#endregion

//#region Standard Methods
function isMobile() {
    return (navigator.userAgent.match(/Android/i) ||
        navigator.userAgent.match(/webOS/i) ||
        navigator.userAgent.match(/iPad/i) ||
        navigator.userAgent.match(/iPhone/i) ||
        navigator.userAgent.match(/iPod/i)
        );
}
function isAppleSafari() {
    return (navigator.userAgent.match(/iPad/i) ||
        navigator.userAgent.match(/iPhone/i) ||
        navigator.userAgent.match(/iPod/i)
        );
}

function IsNullOrEmpty(Val) {
    if (typeof Val === "string") return Val.isNullOrEmpty();
    if (Val === undefined || Val === null) return true;
    if (Val === 0 || Val === false) return false;
    if (Val) return false;//*** will evaluate to true if value is not: 0, false ***
    else return true;
}
function IsInteger(Val)
{
    var reg = /^[\+\-]?\d*\.?\d+(?:[Ee][\+\-]?\d+)?$/;
    return reg.test(Val);
}
function isCallBackFuncion(callback) {
    if (callback && typeof (callback) === 'function') {
        return true;
    } else {
        return false;
    }
}
function TrimString(Val)
{
    if (IsNullOrEmpty(Val) || typeof Val !== "string") return "";
    return Val.trimString();
}
function CDateNull(Val) {
    /// <summary>ResponseData to Date or Null</summary>
    /// <returns type="Date"></returns>
    return IsNullOrEmpty(Val) ? null : Date.parse(Val);
}

function CLocaleDateStringExt(val, options) {
    if (IsNullOrEmpty(val)) return "";
    return val.toLocaleDateStringExt(options);
}
function CLocaleTimeStringExt(val, options) {
    if (IsNullOrEmpty(val)) return "";
    return val.toLocaleTimeStringExt(options);
}

function CNumberZero(Val)
{
    if (!IsInteger(Val)) return 0;
    return Number(Val);
}
function CNumberNull(Val) {
    if (!IsInteger(Val)) return null;
    return Number(Val);
}
//#endregion

//#region Common Methods
var GeneratePagination = function (TotalRecords, TotalPage, CurrentPage) {
    var arrayPages = [];
    var minPage = 1;
    // output nice pagination
    // always have a group of 5
    var minRange = Math.max(minPage, CurrentPage - 2);
    var maxRange = Math.min(TotalPage, CurrentPage + 2);
    if (minRange != minPage) {
        arrayPages.push(minPage + "");
        arrayPages.push("...");
    }
    for (var i = minRange; i <= maxRange; i++) {
        arrayPages.push(i + "");
    }
    if (maxRange != TotalPage) {
        arrayPages.push("...");
        arrayPages.push(TotalPage + "");
    }
    console.warn("Minh: ", arrayPages);
    return arrayPages;
}
function generateUID() {
    function s4() {
        return Math.floor((1 + Math.random()) * 0x10000)
          .toString(16)
          .substring(1);
    }
    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
      s4() + '-' + s4() + s4() + s4();
}
function getFileExtension(fileName) {
    return fileName.split('.').pop();
}
function convertImageToBase64(file, callback) {
    var oResult = {};
    oResult = $.extend({}, oResult, file);
    var reader = new FileReader();
    reader.onload = function (img) {
        oResult.Status = "OK";
        oResult.Data = img.target.result;
        callback(oResult);
    }
    reader.onerror = function () {
        oResult.Status = "ERROR";
        oResult.Data = reader.error;
        callback(oResult);
    };
    reader.readAsDataURL(file);
}
function convertBase64ToImage(dataurl, filename) {
    var arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);

    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }

    return new File([u8arr], filename, { type: mime });
}

function buildQueryStringExtensionMethod(obj, parentKey) {
    parentKey = parentKey || '';
    return Object.keys(obj)
        .filter(key => obj[key] !== null) // Filter out properties with null values
        .map(key => {
            const fullKey = parentKey ? `${parentKey}.${key}` : key;
            const value = obj[key];
            if (typeof value === 'object' && value !== null) {
                return buildQueryStringExtensionMethod(value, fullKey);
            } else {
                return `${fullKey}=${encodeURIComponent(value)}`;
            }
        })
        .filter(Boolean) // Remove any empty strings resulting from null values
        .join('&');
}
//#endregion;
var AWDSApp = new function () {
    this.util = new util();
    //this.historyState = new historyState();
}

var load_lib_ui_bootstrap_tpls = function (cbLoaded) {
    function initScript(d, s, id) {
        var js, fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) {
            cbLoaded();
            //return;
        }
        else {
            js = d.createElement(s); js.id = id;
            if (angular.isDefined(window.webApp) && angular.isDefined(window.webApp.rootURL)) {
                js.src = window.webApp.rootURL + "Areas/Stock/Scripts/Libs/Common/ui-bootstrap-tpls-2.5.0.js";
            } else {
                js.src = (angular.isDefined(window.rootURL) ? window.rootURL : '/') + "Areas/Stock/Scripts/Libs/Common/ui-bootstrap-tpls-2.5.0.js";
            }
            fjs.parentNode.insertBefore(js, fjs);
            js.onload = function () {
                if (cbLoaded && typeof cbLoaded == 'function') {
                    cbLoaded();
                }
            };
        }
    }
    initScript(document, 'script', 'lib-ui-bootstrap-tpls');
}

var ngAWDSApp = angular.module("AWDSApp", ['ngCookies', 'vcRecaptcha', 'ui-notification']); //, 'ngSanitize'



//angular.module('AWDSApp').requires.push('ui.bootstrap');
try {
    angular.module('ui.bootstrap');
    angular.module('AWDSApp').requires.push('ui.bootstrap');
} catch (err) {
    load_lib_ui_bootstrap_tpls(function () {
        angular.module('AWDSApp').requires.push('ui.bootstrap');
    });
}

ngAWDSApp.run(['$rootScope', '$window', 'HttpFactory', '$timeout', function ($rootScope, $window, HttpFactory, $timeout) {
    
    $rootScope.rootURL = window.rootURL;//*** we will remove this option after changed to webApp object
    $rootScope.ConfigFormMail = angular.copy(window.ConfigFormMail);//*** we will remove this option after changed to webApp object
    //window.ConfigFormMail = null;    
    //***using util object in HTML
    var oUtil = {
        getUrlHasPrefix: function (sAction) {
            if (AWDSApp.util.isNullOrEmpty(sAction))
            {
                return "";
            }
            return $rootScope.webApp.rootURL + (sAction.substring(0, 1) == '/' ? sAction.substring(1, sAction.length) : sAction).toLowerCase();
        },
        loadPaypalScript: function (cbLoaded) {
            function initScript(d, s, id) {
                var js, fjs = d.getElementsByTagName(s)[0];
                if (d.getElementById(id)) {
                    cbLoaded();
                    //return;
                }
                else {
                    js = d.createElement(s); js.id = id;
                    js.src = "https://www.paypalobjects.com/api/checkout.js";
                    fjs.parentNode.insertBefore(js, fjs);
                    js.onload = function () {
                        if (cbLoaded && typeof cbLoaded == 'function')
                        {
                            cbLoaded();
                        }
                    };
                }
            }
            initScript(document, 'script', 'paypal-jscheckout');
        },
        loadPaypalScriptByClientId: function (clientId, cbLoaded) {
            function initScript(d, s, id) {
                var js, fjs = d.getElementsByTagName(s)[0];
                if (d.getElementById(id)) {
                    cbLoaded();
                    //return;
                }
                else {
                    js = d.createElement(s); js.id = id;
                    js.src = "https://www.paypal.com/sdk/js?locale=en_AU&enable-funding=card,credit&currency=AUD&client-id=" + clientId;// + '&debug=true';
                    fjs.parentNode.insertBefore(js, fjs);
                    js.onload = function () {
                        if (cbLoaded && typeof cbLoaded == 'function') {
                            cbLoaded();
                        }
                    };
                }
            }
            initScript(document, 'script', 'paypal-jscheckout');
        },
        loadPaymentScript: function (id, src, async, cbOnload) {
            var d = document;
            var s = 'script';
            var js, fjs = d.getElementsByTagName(s)[0];
            if (d.getElementById(id)) {
                return;
            }
            else {
                js = d.createElement(s); js.id = id;
                js.src = src;
                js.async = async;
                fjs.parentNode.insertBefore(js, fjs);
                if (angular.isFunction(cbOnload)) {
                    js.onload = cbOnload;
                }
                //js.onload = function () {                    
                //};
            }
        },
        loadSecurepayV2Script: function (isSandbox, cbLoaded) {
            function initScript(d, s, id) {
                var js, fjs = d.getElementsByTagName(s)[0];
                if (d.getElementById(id)) {
                    return;
                }
                else {
                    js = d.createElement(s); js.id = id;
                    if (isSandbox) {
                        js.src = "https://payments-stest.npe.auspost.zone/v3/ui/client/securepay-ui.min.js";//sandbox
                    } else {
                        js.src = "https://payments.auspost.net.au/v3/ui/client/securepay-ui.min.js";//live
                    }
                
                    fjs.parentNode.insertBefore(js, fjs);
                    js.onload = function () {
                        if (cbLoaded && typeof cbLoaded == 'function') {
                            cbLoaded();
                        }
                    };
                }
            }
            initScript(document, 'script', 'securepay-v2-ui-jscheckout');
        },
        getObjectLength: function (objValue)
        {
            var iObjLength = 0;
            var objKey = Object.keys(objValue);
            for (var i = 0; i < objKey.length; i++)
            {
                var sFieldName = objKey[i];
                if (angular.isArray(objValue[sFieldName])) {
                    for (var j = 0; j < objValue[sFieldName].length; j++) {
                        iObjLength = iObjLength + this.getObjectLength(objValue[sFieldName][j]);
                    }                
                } else if (angular.isObject(objValue[sFieldName])) {
                    //iObjLength = iObjLength + Object.keys(objValue[sFieldName]).length;
                    iObjLength = iObjLength + this.getObjectLength(objValue[sFieldName]);
                } else {
                    iObjLength++;
                }
            }
            return iObjLength;
        }
    }
    angular.merge(oUtil, AWDSApp.util);
    $rootScope.util = oUtil;//*** we will remove this option after changed to webApp object

    //****************************************************************
    if (window.webApp) {
        window.webApp.util = oUtil;
        if ($rootScope.util.isNullOrEmpty(window.rootURL))
        {
            window.rootURL = window.webApp.rootURL;
        }
        if ($rootScope.util.isNullOrEmpty(window.RecaptchaSiteKey)) {
            window.RecaptchaSiteKey = window.webApp.ga.recaptchaSiteKey;
        }        
    }
    else {
        window.webApp = {
            rootURL: window.rootURL,
            fb: {
                appId: window.FBAppId//*** the key for login ***
            },
            ga: {
                appId: window.GoogleAppId,//*** the key for login ***
                recaptchaSiteKey: window.RecaptchaSiteKey
            },
            formMailOptions: {
                redirectToThankYou: {
                    formMailSubscribeDirective: null,
                    formMailEnquiry3Directive: null,
                    formMailBasicDirective: null
                }
            },
            util: oUtil
        };
        if (window.ConfigFormMail)
        {
            if (window.ConfigFormMail.formMailSubscribeDirective) {
                window.webApp.formMailOptions.redirectToThankYou.formMailSubscribeDirective = window.ConfigFormMail.formMailSubscribeDirective.sThankYou;
            }
            if (window.ConfigFormMail.formMailEnquiry3Directive) {
                window.webApp.formMailOptions.redirectToThankYou.formMailEnquiry3Directive = window.ConfigFormMail.formMailEnquiry3Directive.sThankYou;
            }
            if (window.ConfigFormMail.formMailBasicDirective) {
                window.webApp.formMailOptions.redirectToThankYou.formMailBasicDirective = window.ConfigFormMail.formMailBasicDirective.sThankYou;
            }
            if (window.ConfigFormMail.webAppExt) {
                angular.merge(window.webApp, window.ConfigFormMail.webAppExt);
            }
        }
    }
    //namespace AWDS.Data.Common.Config
    window.webApp.WebsiteIdCode = {
        BrisbaneRV201: 201,
        SunseekerRV214: 214,
        SAMotorcycle222: 222,
        RovaRange229: 229,
        kratzmann250: 250,
        JaycoAlburyWodonga261: 261,
        YamahaDubbo276: 276,
        Carlins316: 316,
        BunburyTrucks351: 351,
        Lawrencerv352: 352,
        Freestylervs3025: 3025,
        EliteMotorcycles325: 325,
        NewAgeGoldCoast3001: 3001,//Stock site
        NewAgeAdelaide3002: 3002,
        AdventureDubbo3004: 3004,
        FarmAndGarden3008: 3008,
        WorkRestPlay3009: 3009,
        StreetCaravans3012: 3012,
        AutoGiant3018: 3018,
        DestinyRVGoldCoast3028: 3028,//Stock site
        GippslandRVStock3032: 3032,//Stock site
        BrisbaneYamahaPart3040: 3040,
        BodyShop3041: 3041,
        WangarattaCaravans3036: 3036,
        AlburyCaravans3039: 3039,
        Offtrackrv3042: 3042
    }

    window.webApp.btnSpinner = {
        cl_btn: 'btn-spinner-service',
        cl_clicked: 'clicking',
        cl_loading: 'loading'
    }

    //window.webApp.historyState = new historyState();

    $rootScope.webApp = window.webApp;

    //$http.defaults.headers.common.IANATimeZoneName = $rootScope.webApp.util.getTimezoneName();// + ';tos=' + sTimeOffset;
    if (angular.isDefined(window.sJsonWebInfo) && window.sJsonWebInfo != null)
    {
        //*** the sJsonWebInfo value come from <script src="@Url.Content("~/stock/website/getwebsiteinfoscript")"></script>
        var jsonData = angular.fromJson(window.sJsonWebInfo);
        $rootScope.webApp.oWebsite = jsonData;
        window.webApp.oWebsite = jsonData;
        delete window.sJsonWebInfo;
    }
    else {
        HttpFactory.get({}, "Stock/Website/GetWebsite").then(function (response) {
            var jsonData = angular.fromJson(response.data);
            $rootScope.webApp.oWebsite = jsonData;
            window.webApp.oWebsite = jsonData;
        }, function (responseError) { });
    }

    if (IsNullOrEmpty($rootScope.webApp.rootURL)) {
        console.error("rootURL is empty. please set rootURL value in Layout");
    }

}]);
ngAWDSApp.config(['$provide', '$httpProvider', '$cookiesProvider', 'vcRecaptchaServiceProvider', 'NotificationProvider', '$locationProvider', function ($provide, $httpProvider, $cookiesProvider, vcRecaptchaServiceProvider, NotificationProvider, $locationProvider) {
    //Set default google site key    
    if (window.RecaptchaSiteKey) {
        vcRecaptchaServiceProvider.setSiteKey(window.RecaptchaSiteKey);
        if (window.webApp && window.webApp.ga && window.webApp.ga.recaptchaSize)
        {
            //console.warn('Minh: setSize', window.webApp.ga.recaptchaSize);
            vcRecaptchaServiceProvider.setSize(window.webApp.ga.recaptchaSize);
        }
    }
    else console.warn("system - no google re-captcha key");

    //Set default notification
    NotificationProvider.setOptions({
        delay: 3000,
        positionX: "center",
        //classNoti: 'shopping-noti'
    });

    $httpProvider.interceptors.push(['$q', '$timeout', function ($q, $timeout) {
        return {
            'request': function (config) {
                // Contains the data about the request before it is sent.
                if (config.beforeSend)
                    config.beforeSend(config);
                // Return the config or wrap it in a promise if blank.
                return config || $q.when(config);
            },

            'responseError': function (rejection) {
                if (!(angular.isDefined(rejection.config) && angular.isDefined(rejection.config.suppressGloablErrorHandeler) && rejection.config.suppressGloablErrorHandeler == true)) {
                    console.error(rejection);
                }
                //btnSpinnerService.endLast();
                return $q.reject(rejection);
            },
            'response': function (response)
            {
                //btnSpinnerService.endLast();
                return response;
            }
        };
    }]);

    if (!$httpProvider.defaults.headers.get) {
        $httpProvider.defaults.headers.get = {};
    }

    // Answer edited to include suggestions from comments
    // because previous version of code introduced browser-related errors
    if (AWDSApp.util.isBrowserIE())
    {
        //disable IE ajax request caching
        $httpProvider.defaults.headers.get['If-Modified-Since'] = 'Sun, 01 Jan 2017 05:00:00 GMT';
        //// extra
        $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
        $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
    }

    //console.warn('Minh: CONFIG user-portal', window.webApp.userPortal);
    if (window.webApp && window.webApp.userPortal)
    {
        $httpProvider.defaults.headers.common['User-Portal'] = window.webApp.userPortal;
    }

    $locationProvider.html5Mode({
        enabled: true,
        requireBase: false,
        rewriteLinks: false
    });
}]);



if (navigator.serviceWorker != null) {
    navigator.serviceWorker.getRegistrations().then(function (registrations) {
        for (var i = 0; i < registrations.length; i++) {
            registrations[i].unregister();
        }
    });
}


//------------------- Responsive Left Filter New Model Farm 
$(function () {//document.ready()
    $(".btn-filter-farm").click(function () {
        $(".content-filter-farm").toggleClass("active");
    });
    $(".content-filter-farm").click(function () {
        $(this).removeClass("active");
    })

})
function createStaticMenu(lProduct) {    
    addNewModelMakeToLeftFilter($(".filter-list .list-menu"), lProduct)
}
function addNewModelMakeToLeftFilter(element, lProducts) {
    var strHtml = "";
    for (var i = 0; i < lProducts.length; i++) {
        var item = lProducts[i];
        strHtml += '<li class=""><a href="' + item.link + '" target="' + item.target + '">' + item.name + '<i class="glyphicon glyphicon-menu-right"></i></a></li>';

    }
    $(element).append(strHtml);
};
ngAWDSApp.directive("btnComprareDir", ['$timeout', '$rootScope', 'ModalService', 'localstorageFactory', 'Notification', function ($timeout, $rootScope, ModalService, localstorageFactory, Notification) {
    return {
        restrict: 'EA',
        replace: true, //*** will replace the directives original HTML on view
        scope: {
            fieldNameId: '@',
            dataItem: '=dItem',
            photo: '@'
        },
        template: '<div><a class="btn-link" ng-click="addToCompare()" ng-show="oItem.IsAdded == false">Add to my compare list</a>'
                    + '<a class="btn-link" ng-show="oItem.IsAdded">Added to my compare list</a></div>',
        link: function ($scope, $element, attr, ngModel) {
            $timeout(function () {
                $scope.init();
            }, 1);
        },
        controller: ['$scope', '$element', '$attrs', '$parse', function ($scope, $element, $attrs, $parse) {
            var sLocalStorageKey = 'compare';
            $scope.lCompares = [];
            $scope.oItem = [];
            $scope.init = function () {
                sLocalStorageKey += $scope.fieldNameId;
                $scope.dataItem[$scope.fieldNameId] = $rootScope.webApp.util.toNumber($scope.dataItem[$scope.fieldNameId]);                
                $scope.mappingDataItem();

                $scope.lCompares = localstorageFactory.getObject(sLocalStorageKey, []);
                if ($scope.lCompares.length > 0) {
                    for (var i = 0; i < $scope.lCompares.length; i++) {
                        if ($scope.lCompares[i].id == $scope.dataItem[$scope.fieldNameId]) {
                            $scope.oItem.IsAdded = true;
                            break;
                        }
                    }
                }
            }
            $scope.mappingDataItem = function () {
                var oItem = {
                    id: $scope.dataItem[$scope.fieldNameId],
                    ref: $scope.fieldNameId,
                    photo: $scope.photo,
                    title: null,
                    desc: null,
                    IsAdded: false
                };
                switch ($scope.fieldNameId) {
                    case 'NewModelID':
                        oItem.title = $scope.dataItem.Model + ' ' + $scope.dataItem.Series;
                        oItem.desc = $scope.dataItem.BodyAxles + ' Caravan';                        
                        break;
                    default:
                        break;
                }
                $scope.oItem = oItem;
            }
            //#region HTMLEvent
            $scope.getUrlHasPrefix = function (sAction) {
                return $rootScope.webApp.util.getUrlHasPrefix(sAction);
            }
            //#endregion


            $scope.addToCompare = function () {
                $scope.lCompares = localstorageFactory.getObject(sLocalStorageKey, []);
                if ($scope.lCompares.length > 2) {
                    Notification.warning('Your compare list is full!');
                } else {
                    $scope.oItem.IsAdded = true;
                    $scope.lCompares.pushIfNotExist($scope.oItem, function (x) { return $scope.oItem.id == x.id; });
                    localstorageFactory.setObject(sLocalStorageKey, $scope.lCompares);
                }

            }
        }]
    }
}]);
//angular.module('AWDSApp').requires.push('ui.bootstrap');//rzSliderForceRender
ngAWDSApp.directive("btnLogin", ['$timeout', '$rootScope', 'ModalService', function ($timeout, $rootScope, ModalService) {
    return {
        restrict: 'E',
        replace: true, //*** will replace the directives original HTML on view
        scope: {
            bActiveLoginTab: '@',
            templateUrl: '@'
        },
        template: '<a class="btn-link" ng-click="openLoginModal()"><i class="login-icon-cls"></i> <span>Log in / Sign up</span></a>',
        controller: ['$scope', '$element', '$attrs', '$parse', function ($scope, $element, $attrs, $parse) {

            $scope.bActiveLoginTab = $rootScope.webApp.util.toBool($scope.bActiveLoginTab);

            //#region HTMLEvent
            $scope.getUrlHasPrefix = function (sAction) {
                return $rootScope.webApp.util.getUrlHasPrefix(sAction);
            }
            //#endregion


            $scope.openLoginModal = function () {
                ModalService.loginModal({
                    templateUrl: $scope.templateUrl,// 'modalLoginUserTemplate.html',
                    bActiveLoginTab: true
                });
            }
        }]
    }
}])

;
ngAWDSApp.directive("btnLogout", ['$timeout', '$rootScope', function ($timeout, $rootScope) {
    return {
        restrict: 'E',
        replace: true, //*** will replace the directives original HTML on view
        scope: {
            returnUrl: '@'
        },
        template: '<a class="btn-link" ng-click="loggout()"><span>Logout</span></a>',
        controller: ['$scope', '$element', '$attrs', 'HttpFactory', function ($scope, $element, $attrs, HttpFactory) {

            var sUrlLoginController = "Stock/ShoppingCart";
            var oUrlLoginAction = {
                logout: sUrlLoginController + '/Logout'
            }

            $scope.loggout = function () {
                HttpFactory.post({}, oUrlLoginAction.logout).then(function (response) {
                    //var jsonData = response.data;
                    if ($rootScope.webApp.util.hasVal($scope.returnUrl)) {
                        $rootScope.webApp.util.redirectTo($rootScope.webApp.util.getUrlHasPrefix($scope.returnUrl));
                    } else {
                        $rootScope.$broadcast('btnLogoutDirSuccess', response); //*** the $rootScope.$broadcast event will fire an event down the $scope.$on('btnLogoutDirSuccess', {}) events
                    }
                }, function () { })
            }
        }]
    }
}]);
ngAWDSApp.directive('convertToLowercase', function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, modelCtrl) {
            //*** Minh: not working with <select>
            var capitalize = function (inputValue) {
                if (inputValue == undefined) inputValue = '';
                var capitalized = inputValue.toLowerCase();
                if (capitalized !== inputValue) {
                    // see where the cursor is before the update so that we can set it back
                    var selection = element[0].selectionStart;
                    modelCtrl.$setViewValue(capitalized);
                    modelCtrl.$render();
                    // set back the cursor after rendering
                    element[0].selectionStart = selection;
                    element[0].selectionEnd = selection;
                }
                return capitalized;
            }
            modelCtrl.$parsers.push(capitalize);
            capitalize(scope[attrs.ngModel]); // capitalize initial value
        }
    };
});;
ngAWDSApp.directive('convertToNumber', function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            ngModel.$parsers.push(function (val) {
                return val != null ? parseInt(val, 10) : null;
            });
            ngModel.$formatters.push(function (val) {
                return val != null ? '' + val : null;
            });
        }
    };
});

ngAWDSApp.directive('convertToFloat', function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
            ngModel.$parsers.push(function (val) {
                return val != null ? parseFloat(val) : null;
            });
            ngModel.$formatters.push(function (val) {
                return val != null ? '' + val : null;
            });
        }
    };
});
;
ngAWDSApp.directive("filterAutocomplete", ['$timeout', '$q', '$compile', '$window', '$document', function ($timeout, $q, $compile, $window, $document) {
    
    var defaultOptions = {
        /**
        * A template for the dropddown list. it no include another templates (itemTemplate, loadMoreTemplate,...)
        * @default null. if null, will itemTemplate logic
        */
        template: null,
        /**
         * A template for the dropddown list item. For example "<p ng-bind-html='renderItem.Make'></p>";
         * Or using interpolation "<p>{{renderItem.Make}}></p>".
         * @default "<p>{{renderItem.Text}}></p>"
         */
        itemTemplate: '<p>{{renderItem.Text}}</p>',        
        /**
         * The template used to display the message when no items match the search text.
         * @default "<span>No results match '{{searchText}}'></span>"
         */
        noMatchTemplate: "<span>No results match '{{searchText}}'</span>",
        loadMoreTemplate: '<span> {{renderItems.length}}/{{totalRecords}} Load more</span>',

        /**
         * CSS class applied to the dropdown container.
         * @default null
         */
        containerCssClass: null,
        /**
         * CSS class applied to the selected list element.
         * @default auto-complete-item-selected
         */
        selectedCssClass: 'auto-complete-item-selected',
        fieldValue: 'Value',
        placeholder: null,
        searchIconEnable: true,
        /**
         * If true displays the dropdown list when the search-icon gets click.
         * @default false
         */
        activateOnClickSearchIcon: false,
        /**
         * Set to true to enable callback when invoked load more
         * @default false
         */
        loadMoreCallbackEnable: false,
        /**
         * CSS class applied to the search-text container.
         * @default null
         */
        searchTextCssClass: null,
        /**
         * Width in "px" of the input. This can also be applied using CSS.
         * @default 'auto'
         */
        searchTextWidth: 'auto',
        /**
         * Width in "px" of the dropddown list. This can also be applied using CSS.
         * @default 'auto'
         */
        dropdownWidth: 'auto',
        /**
         * Maximum height in "px" of the dropddown list. This can also be applied using CSS.
         * @default 'auto'
         */
        dropdownHeight: 'auto',
        /**
         * Minimum number of characters required to display the dropdown.
         * @default 1
         */
        minimumChars: 1,
        /**
         * Maximum number of items to render in the list.
         * @default 20
         */
        maxItemsToRender: 20,
        /**
         * If true displays the dropdown list when the textbox gets focus.
         * @default false
         */
        activateOnFocus: false,
        /**
         * Callback to get the data for the dropdown. The callback receives the search text as the first parameter.
         * If paging is enabled the callback receives an object with "pageIndex" and "pageSize" properties as the second parameter.
         * This function must return a promise.
         * @default angular.noop
         */
        data: angular.noop,
        /**
         * Callback before the "data" callback is invoked.
         * @default angular.noop
         */
        loading: angular.noop,
        /**
         * Callback after the items are rendered in the dropdown
         * @default angular.noop
         */
        loadingComplete: angular.noop,
        /**
         * Callback after the plugin is initialized and ready. The callback receives an object with the following methods:
         * @default angular.noop
         */
        ready: angular.noop,
        /**
         * Callback after press enter. The callback receives an object with a search-text
         * @default angular.noop
         */
        search: angular.noop,
        /**
         * Callback if loadMoreCallbackEnable true. The callback receives an object with a search-text
         * @default angular.noop
         */
        loadMore: angular.noop,
        /**
         * Callback if activateOnClickSearchIcon true. The callback receives an object with a search-text
         * @default angular.noop
         */
        searchIconCallback: angular.noop
    };
    var DOM_EVENT = {
        RESIZE: 'resize',
        SCROLL: 'scroll',
        CLICK: 'click',
        KEYDOWN: 'keydown',
        FOCUS: 'focus',
        INPUT: 'input'
    };

    var KEYCODE = {
        TAB: 9,
        BACKSPACE: 8,
        ENTER: 13,
        CTRL: 17,
        ALT: 18,
        ESCAPE: 27,
        LEFTARROW: 37,
        UPARROW: 38,
        RIGHTARROW: 39,
        DOWNARROW: 40,
        DELETE: 46,
        MAC_COMMAND_LEFT: 91,
        MAC_COMMAND_RIGHT: 93
    };
    return {
        //require: 'ngModel',
        restrict: 'E',
        replace: true, //*** will replace the directives original HTML on view
        //*** if scope = undefined or scope = false or scope attibute missing, it will use parent controller $scope
        //*** if scope = {} or scope = true, it will create new $scope
        //scope: {
        //    //There are 3 types of prefixes in AngularJS:
        //    //‘@’ – Text binding / one-way binding
        //    //‘=’ – Direct model binding / two-way binding
        //    //‘&’ – Behavior binding / Method binding
        //},
        scope: {            
            cOptions: '&' //– Behavior binding / Method binding                 
        },
        link: function ($scope, $element, $attrs) {

            $timeout(function () {
                // execute the options expression
                
                $q.when($scope.cOptions()).then(_initialize);
            });
            function _initialize(options) {
                options = options || {};
                $scope.init(angular.extend({}, defaultOptions, options));
                
                _initializeContainer();
                _wireupEvents();
            }
            function _initializeContainer() {
                $scope.container = _getDefaultContainer();
                if ($scope.options.containerCssClass) {
                    $scope.container.addClass($scope.options.containerCssClass);
                }
                if ($scope.options.searchTextCssClass) {
                    $scope.container.find('.search-text-container').addClass($scope.options.searchTextCssClass);
                }
                if ($scope.options.searchTextWidth) {
                    $scope.container.find('.search-text-container input.search-text').width($scope.options.searchTextWidth);
                }
                
                $element.append($scope.container);
                // keep a reference to the <ul> element
                $scope.elementUL = angular.element($scope.container[0].querySelector('ul.auto-complete-results'));
                $scope.targetSearchText = angular.element($scope.container[0].querySelector('input.search-text'));
                if ($scope.options.searchIconEnable) {
                    $scope.targetSearchIcon = angular.element($scope.container[0].querySelector('.icon-search'));
                }

                console.warn('Minh::::' + $element.find('input.search-text').length, $element.find('input.search-text').val());
            }
            function _getDefaultContainer() {
                var linkFn = $compile(_getContainerTemplate());
                return linkFn($scope);
            }
            function _getContainerTemplate() {
                var html = '';
                html += '<div class="auto-complete-container">'
                        + '<div class="search-text-container">'
                            + '<input type="text" class="search-text" ng-model="searchText" placeholder="{{options.placeholder}}" />'
                            + '<i class="glyphicon glyphicon-search icon-search ng-hide" ng-show="options.searchIconEnable"></i>'
                        + '</div>';
                html += _getDropdownListTemplate();
                html += '</div>';
                return html;
            }
            function _getDropdownListTemplate() {
                var html = '';
                var sItem = '';
                if ($scope.options.template != null) {
                    html = $scope.options.template;
                }
                else {
                    if ($scope.options.itemTemplate.indexOf('<li') == 0) {
                        sItem = $scope.options.itemTemplate;
                    } else {
                        sItem = '<li ng-if="renderItems.length" class="item"'
                                    + 'ng-repeat="renderItem in renderItems"'
                                    + 'data-index="{{$index}}"'
                                    + 'ng-class="getSelectedCssClass($index)"'
                                    + 'ng-click="selectItem($index, true)">'
                                    + $scope.options.itemTemplate
                                + '</li>'
                    }
                    html += '<ul class="auto-complete-results" ng-show="containerVisible">'
                                + sItem
                                + '<li ng-if="!renderItems.length"'
                                    + 'class="item no-match">'
                                    + $scope.options.noMatchTemplate
                                + '</li>'
                                + '<li ng-if="renderItems.length"'
                                    + 'class="item load-more"'
                                    + 'ng-click="loadMore()">'
                                    + $scope.options.loadMoreTemplate
                                + '</li>'
                            + '</ul>';
                }
                              
                return html;
            }

            function _wireupEvents() {
                var elementSearchText = $element.find('input.search-text');
                // when the target(textbox) gets focus activate the corresponding container
                elementSearchText.on(DOM_EVENT.FOCUS, function () {
                    $scope.$evalAsync(function () {                        
                        if ($scope.options.activateOnFocus) {
                            _waitAndQuery(elementSearchText.val(), 100);
                        }
                    });
                });

                elementSearchText.on(DOM_EVENT.INPUT, function () {
                    $scope.$evalAsync(function () {
                        _tryQuery(elementSearchText.val());
                    });
                });

                elementSearchText.on(DOM_EVENT.KEYDOWN, function (event) {
                    var $event = event;
                    $scope.$evalAsync(function () {
                        _handleElementKeyDown($event);
                    });
                });
                //$scope.container.find('ul').on(DOM_EVENT.SCROLL, function () {
                //    if (!$scope.options.pagingEnabled) {
                //        return;
                //    }
                //    var list = this;
                //    $scope.$evalAsync(function () {
                //        if (!$scope.containerVisible) {
                //            return;
                //        }
                //        // scrolled to the bottom?
                //        if ((list.offsetHeight + list.scrollTop) >= list.scrollHeight) {
                //            $scope.tryLoadNextPage();
                //        }
                //    });
                //});
                //$document.on(DOM_EVENT.KEYDOWN, function (event) {
                //    var $event = event;
                //    $scope.$evalAsync(function () {
                //        _handleDocumentKeyDown($event);
                //    });
                //});
                $document.on(DOM_EVENT.CLICK, function (event) {
                    var $event = event;
                    $scope.$evalAsync(function () {
                        _handleDocumentClick($event);
                    });
                });
                //// $window is a reference to the browser's window object
                //angular.element($window).on(DOM_EVENT.RESIZE, function () {
                //    if ($scope.options.hideDropdownOnWindowResize) {
                //        $scope.$evalAsync(function () {
                //            $scope.autoHide();
                //        });
                //    }
                //});
            }
           
            function _waitAndQuery(searchText, delay) {
                var elementSearchText = $element.find('input.search-text');
                // wait few millisecs before calling query(); this to check if the user has stopped typing
                var promise = $timeout(function () {
                    // has searchText unchanged?
                    if (searchText === elementSearchText.val()) {
                        $scope.query(searchText);
                    }

                    //cancel the timeout
                    $timeout.cancel(promise);

                }, (delay || 300));
            }
            function _containerContainsTarget(target) {
                // use native Node.contains
                // https://developer.mozilla.org/en-US/docs/Web/API/Node/contains
                var container = $scope.container[0];
                if (angular.isFunction(container.contains) && container.contains(target)) {
                    return true;
                }

                // otherwise use .has() if jQuery is available
                if (window.jQuery && angular.isFunction($scope.container.has) &&
                    $scope.container.has(target).length > 0) {

                    return true;
                }

                // assume target is not in container
                return false;
            }
            function _handleDocumentClick(event) {
                var elementSearchText = $element.find('input.search-text');
                //// ignore inline
                //if ($scope.isInline()) {
                //    return;
                //}

                // no container. probably destroyed in scope $destroy
                if (!$scope.container) {
                    return;
                }

                // ignore target click
                if (event.target === $scope.targetSearchText[0]) {
                    event.stopPropagation();
                    return;
                }

                
                if (event.target === $scope.targetSearchIcon[0]) {                    
                    if ($scope.options.activateOnClickSearchIcon)
                    {
                        if ($scope.options.searchIconCallback) {
                            $scope.searchIconClicked(elementSearchText.val());
                        } else {
                            _waitAndQuery(elementSearchText.val(), 100);
                        }
                        
                    }
                }

                if (_containerContainsTarget(event.target)) {
                    event.stopPropagation();
                    return;
                }
                $scope.autoHide();
            }
            function _ignoreKeyCode(keyCode) {
                return [
                    KEYCODE.TAB,
                    KEYCODE.ALT,
                    KEYCODE.CTRL,
                    KEYCODE.LEFTARROW,
                    KEYCODE.RIGHTARROW,
                    KEYCODE.MAC_COMMAND_LEFT,
                    KEYCODE.MAC_COMMAND_RIGHT
                ].indexOf(keyCode) !== -1;
            }

            function _handleElementKeyDown(event) {
                var keyCode = event.charCode || event.keyCode || 0;

                if (_ignoreKeyCode(keyCode)) {
                    return;
                }

                switch (keyCode) {
                    case KEYCODE.UPARROW:
                        $scope.scrollToPreviousItem();

                        event.stopPropagation();
                        event.preventDefault();

                        break;

                    case KEYCODE.DOWNARROW:
                        $scope.scrollToNextItem();

                        event.stopPropagation();
                        event.preventDefault();

                        break;

                    case KEYCODE.ENTER:

                        if ($scope.selectedIndex == -1) {
                            $scope.search();
                        }
                        else {
                            $scope.selectItem($scope.selectedIndex, true);
                        }

                        //prevent postback upon hitting enter
                        event.preventDefault();
                        event.stopPropagation();

                        break;
                    case KEYCODE.BACKSPACE:
                    case KEYCODE.DELETE:
                        var elementSearchText = $element.find('input.search-text');
                        $scope.removedSearchText(elementSearchText.val());

                        //prevent postback upon hitting enter
                        event.preventDefault();
                        event.stopPropagation();

                        break;

                    case KEYCODE.ESCAPE:
                        $scope.restoreOriginalText();
                        $scope.autoHide();

                        event.preventDefault();
                        event.stopPropagation();

                        break;

                    default:
                        break;
                }
            }
            function _tryQuery(searchText) {
                // query only if minimum number of chars are typed; else hide dropdown
                if (($scope.options.minimumChars === 0)
                    || (searchText && searchText.trim().length !== 0 && searchText.length >= $scope.options.minimumChars)) {
                    _waitAndQuery(searchText);
                    return;
                } 
            }
        },
        controller: ['$scope', '$element', '$attrs', '$rootScope', function ($scope, $element, $attrs, $rootScope) {
            var originalSearchText = null;
            var queryCounter = 0;
            var currentPageIndex = 0;
            var endOfPagedList = false;
            var dataLoadInProgress = false;

            $scope.selectedIndex = -1;
            $scope.containerVisible = false;
            $scope.totalRecords = 0;
            $scope.renderItems = [];
            
            var dataRenderFieldNames = [];
            var bScrolledToloadMoreItem = false;


            $scope.init = function (options) {
                $scope.options = options;
                _safeCallback($scope.options.ready, publicApi);
            }
            $scope.query = function (searchText) {
                //$scope.selectedIndex = -1;
                $scope.emptyRenderItems();

                currentPageIndex = 0;

                return _query(searchText, 0);
            }
            $scope.selectItem = function (itemIndex, closeDropdownAndRaiseCallback) {
                //var item = $scope.renderItems[itemIndex];
                
                //var item = $scope[_getRenderFieldNameByIndex(itemIndex)][itemIndex];
                if (bScrolledToloadMoreItem == false) {
                    var item = _getItemByIndex(itemIndex);
                    if (!item) {
                        return;
                    }
                    $scope.selectedIndex = itemIndex;
                    //_setSearchText(item[$scope.options.fieldValue]);
                    _setSearchText(item[_getFieldValueByIndex(itemIndex)]);

                    if (closeDropdownAndRaiseCallback) {
                        _hideDropdown();
                        _safeCallback($scope.options.itemSelected, { item: item, renderType: _getRenderFieldNameByIndex(itemIndex), searchText: $scope.searchText });
                    }

                }
                else
                {
                    $scope.selectedIndex = itemIndex;
                    if (closeDropdownAndRaiseCallback)
                    {
                        $scope.loadMore();
                    }                    
                }
            };
            $scope.selectItemByType = function (item, sType) {                
                _hideDropdown();
                _safeCallback($scope.options.itemSelectedByType, { item: item, type: sType, searchText: $scope.searchText });

            };
            $scope.search = function () {
                if (angular.isFunction($scope.options.search))
                {
                    _hideDropdown();
                    _safeCallback($scope.options.search, { searchText: $scope.searchText });
                }                
            }

            $scope.searchIconClicked = function () {
                if ($scope.options.searchIconCallback) {
                    _hideDropdown();
                    _safeCallback($scope.options.searchIconCallback, { searchText: $scope.searchText });
                }
            }

            $scope.loadMore = function () {
                if ($scope.options.loadMoreCallbackEnable) {
                    _hideDropdown();
                    _safeCallback($scope.options.loadMore, { searchText: $scope.searchText });
                } else {
                    _loadNextPage();
                }
            }
            
            $scope.getSelectedCssClass = function (itemIndex) {
                return (itemIndex === $scope.selectedIndex) ? $scope.options.selectedCssClass : '';
            };
            $scope.emptyRenderItems = function () {                
                $scope.selectedIndex = -1;
                $scope.renderItems = [];
                for (var i = 0; i < dataRenderFieldNames.length; i++) {
                    $scope[dataLoadInProgress[i]] = [];
                }
            }
            $scope.restoreOriginalText = function () {
                if (!originalSearchText) {
                    return;
                }

                _setSearchText(originalSearchText);
            };
            $scope.removedSearchText = function (searchText) {

                if (!(searchText && searchText.trim().length !== 0))
                {
                    _safeCallback($scope.options.searchTextRemoved, {});
                }
            }
            $scope.scrollToNextItem = function () {
                var itemIndex = _getItemIndexFromOffset(1);
                if (itemIndex === -1)
                {                    
                    return;
                }

                _scrollToItem(itemIndex);

                //if (_shouldLoadNextPageAtItemIndex(itemIndex)) {
                //    _loadNextPage();
                //}
            };
            $scope.scrollToPreviousItem = function () {
                var itemIndex = _getItemIndexFromOffset(-1);
                if (itemIndex === -1) {
                    return;
                }

                _scrollToItem(itemIndex);
            };
            $scope.show = function () {
                // the show() method is called after the items are ready for display
                // the textbox position can change (ex: window resize) when it has focus
                // so reposition the dropdown before it's shown
                _positionDropdown();

                // callback
                _safeCallback($scope.options.dropdownShown);
            }
            $scope.autoHide = function () {
                if ($scope.options) {
                    _hideDropdown();
                }
            };


            function _loadNextPage() {
                return _query(originalSearchText, (currentPageIndex + 1));
            }
            function _query(searchText, pageNumber) {
                var params = {
                    searchText: searchText,
                    pageNumber: pageNumber,
                    queryId: ++queryCounter
                };

                return _queryInternal(params);
            }
            function _queryInternal(params) {               

                // backup original search term in case we need to restore if user hits ESCAPE
                originalSearchText = params.searchText;

                dataLoadInProgress = true;

                _safeCallback($scope.options.loading);

                return $q.when($scope.options.data(params),
                    function successCallback(responses) {
                        // verify that the queryId did not change since the possibility exists that the
                        // search text changed before the 'data' promise was resolved. Say, due to a lag
                        // in getting data from a remote web service.
                        if (_didQueryIdChange(params)) {
                            _hideDropdown();
                            return;
                        }

                        // verify that the searchText did not change since the possibility exists that the
                        // search text changed before the 'data' promise was resolved. Say, due to a lag
                        // in getting data from a remote web service.
                        if (_didValueChange(params)) {
                            //_hideDropdown();
                            return;
                        }

                        try {
                            /**** Minh::20230925:: change result obj to array
                            * support render multiple data in autocomplete template
                            */
                            var result;
                            var cbDataRender = [];
                            var iTotalRecords = 0;
                            dataRenderFieldNames = [];

                            if (angular.isArray(responses)) {
                                for (var i = 0; i < responses.length; i++) {
                                    if (responses[i].fieldNameInTemplate == 'renderItems') {
                                        result = responses[i];
                                    } else {
                                        dataRenderFieldNames.push(responses[i].fieldNameInTemplate);
                                        $scope[responses[i].fieldNameInTemplate] = responses[i].records;
                                        iTotalRecords += responses[i].totalRecords;
                                    }
                                }

                            } else {
                                result = responses;//*** keep old way
                            }

                            if (result) {
                                // in case of paged list we add to the array instead of replacing it
                                angular.forEach(result.records, function (item) {
                                    $scope.renderItems.push(item);
                                });
                                iTotalRecords += result.totalRecords;
                                //$scope.totalRecords = result.totalRecords;
                            }

                            $scope.totalRecords = iTotalRecords;
                            $scope.searchText = params.searchText;

                            //$scope.searchText = params.searchText;
                            currentPageIndex = params.pageNumber;

                            $scope.show();
                            // callback
                            _safeCallback($scope.options.loadingComplete, {
                                dataSources: responses,
                                renderItems: $scope.renderItems,
                                setOptions: _setOptions
                            });
                        } catch (e) {
                            console.error('unknown error', e);
                        }
                    },
                    function errorCallback(error) {
                        _hideDropdown();

                        _safeCallback($scope.options.loadingComplete, { error: error });
                    }).then(function () {
                        dataLoadInProgress = false;
                    });
            }
            function _didValueChange(params) {
                var elementSearchText = $element.find('input.search-text');
                console.warn('Minh: _didValueChange: ', params.queryId + '; counter: ' + queryCounter, params, elementSearchText.val());
                return (params.searchText !== elementSearchText.val());
            }
            function _didQueryIdChange(params) {
                console.warn('Minh: _didQueryIdChange: ', params.queryId + '; counter: ' + queryCounter, params);
                return (params.queryId !== queryCounter);
            }
            function _hideDropdown() {
                if (!$scope.containerVisible) {
                    return;
                }

                // reset scroll position
                //$scope.elementUL[0].scrollTop = 0;
                $scope.containerVisible = false;
                $scope.emptyRenderItems();

                _resetSearchText();

                // callback
                _safeCallback($scope.options.dropdownHidden);
            }
            function _resetSearchText() {
                //originalSearchText = $scope.searchText = null;
                originalSearchText = null;
                currentPageIndex = 0;
            }
            
            function _scrollToItem(itemIndex) {
                if (!$scope.containerVisible) {
                    return;
                }

                //dataRenderFieldNames
                $scope.selectItem(itemIndex, false);

                var attrSelector = 'li[data-index="' + itemIndex + '"]';
                if (itemIndex == _getTotalItemRendered())
                {
                    attrSelector = 'li.load-more';
                }

                // use jquery.scrollTo plugin if available
                // http://flesler.blogspot.com/2007/10/jqueryscrollto.html
                if (window.jQuery && window.jQuery.scrollTo) {  // requires jquery to be loaded
                    $scope.elementUL.scrollTo($scope.elementUL.find(attrSelector));
                    return;
                }

                var li = $scope.elementUL[0].querySelector(attrSelector);
                if (li) {
                    // this was causing the page to jump/scroll
                    //    li.scrollIntoView(true);
                    $scope.elementUL[0].scrollTop = li.offsetTop;
                }
            }
            function _safeCallback(fn, args) {
                if (!angular.isFunction(fn)) {
                    return;
                }

                try {
                    return fn.call($element, args);
                } catch (ex) {
                    //ignore
                }
            }
            function _setOptions(options) {
                if (_.isEmpty(options)) {
                    return;
                }
                angular.forEach(options, function (value, key) {
                    if (defaultOptions.hasOwnProperty(key)) {
                        $scope.options[key] = value;
                    }
                });
            }
            
            function _setSearchText(sVal) {
                $scope.searchText = sVal;
            }
            function _getTotalItemRendered() {
                var itotalItemRendered = $scope.renderItems.length;
                if (dataRenderFieldNames.length > 0) {
                    for (var i = 0; i < dataRenderFieldNames.length; i++) {
                        itotalItemRendered = itotalItemRendered + $scope[dataRenderFieldNames[i]].length;
                    }
                }
                return itotalItemRendered;
            }
            function _getItemIndexFromOffset(itemOffset) {
                var itemIndex = $scope.selectedIndex + itemOffset;
                bScrolledToloadMoreItem = false;

                //if (itemIndex >= $scope[_getRenderFieldNameByIndex(itemIndex)].length) {
                //    return -1;
                //}
                var itotalItemRendered = $scope.renderItems.length;
                if (dataRenderFieldNames.length > 0)
                {
                    for (var i = 0; i < dataRenderFieldNames.length; i++) {
                        itotalItemRendered = itotalItemRendered + $scope[dataRenderFieldNames[i]].length;
                    }                    
                }

                
                if (itemIndex >= itotalItemRendered) {
                    if ($scope.options.loadMoreCallbackEnable && itemIndex == itotalItemRendered)
                    {
                        bScrolledToloadMoreItem = true;
                        //load more item
                        return itemIndex;
                    } else {
                        return -1;
                    }
                }

                return itemIndex;
            }
            function _getRenderFieldNameByIndex(itemIndex) {
                return _getAttrByIndexFromLI(itemIndex, 'render-type', 'renderItems');
            }
            function _getFieldValueByIndex(itemIndex) {
                return _getAttrByIndexFromLI(itemIndex, 'field-type', $scope.options.fieldValue);//for text search
            }
            function _getFieldIdByIndex(itemIndex) {
                return _getAttrByIndexFromLI(itemIndex, 'field-id', null);
            }
            function _getFieldIdValByIndex(itemIndex) {
                return _getAttrByIndexFromLI(itemIndex, 'fiedl-id-val', null);
            }
            function _getItemByIndex(itemIndex) {
                var item;// = $scope[_getRenderFieldNameByIndex(itemIndex)][itemIndex];
                if (dataRenderFieldNames.length > 0)
                {
                    var propNameOfScope = _getRenderFieldNameByIndex(itemIndex);
                    var propFieldIdOfItem = _getFieldIdByIndex(itemIndex);
                    var sFieldIdValOfItem = _getFieldIdValByIndex(itemIndex);
                    if (propFieldIdOfItem != null && sFieldIdValOfItem != null) {
                        for (var i = 0; i < $scope[propNameOfScope].length; i++) {
                            var sFieldIdOfItem = $scope[propNameOfScope][i][propFieldIdOfItem];
                            if (sFieldIdOfItem == sFieldIdValOfItem) {
                                item = $scope[propNameOfScope][i];
                                break;
                            }
                        }
                    }
                    else {
                        item = $scope['renderItems'][itemIndex];
                    }
                } else {
                    item = $scope['renderItems'][itemIndex];
                }

                return item;
            }
            function _getAttrByIndexFromLI(itemIndex, attrName, defaultVal) {
                var attrSelector = 'li[data-index="' + itemIndex + '"]';
                if ($scope.elementUL.find(attrSelector).length > 0) {
                    var attrVal = $scope.elementUL.find(attrSelector).attr(attrName);
                    if (attrVal) {
                        return attrVal;
                    }
                }
                return defaultVal;
            }

            function _positionDropdown() {
                var dropdownWidth = null;
                // same as textbox width
                dropdownWidth = $scope.targetSearchText[0].getBoundingClientRect().width + 'px';
                //if ($scope.options.searchIconEnable) {
                //    dropdownWidth = $scope.targetSearchText[0].getBoundingClientRect().width + ($scope.targetSearchIcon[0].getBoundingClientRect().width * 2) + 'px';
                //}
                //dropdownWidth = $element[0].getBoundingClientRect().width + 'px';
                $scope.container.css({ 'width': dropdownWidth });
                $scope.elementUL.css({ 'width': dropdownWidth });

                if ($scope.options.dropdownHeight && $scope.options.dropdownHeight !== 'auto') {
                    $scope.elementUL.css({ 'max-height': $scope.options.dropdownHeight });
                }
                _positionUsingDomAPI();
            }
            function _positionUsingDomAPI() {
                var rect = $scope.targetSearchText[0].getBoundingClientRect();
                var DOCUMENT = $document[0];

                var scrollTop = DOCUMENT.body.scrollTop || DOCUMENT.documentElement.scrollTop || $window.pageYOffset;
                var scrollLeft = DOCUMENT.body.scrollLeft || DOCUMENT.documentElement.scrollLeft || $window.pageXOffset;

                $scope.container.css({
                    'left': rect.left + scrollLeft + 'px',
                    'top': rect.top + rect.height + scrollTop + 'px'
                });
                var maxZindex = _maxZindex();
                $scope.elementUL.css({
                    //'left': rect.left + scrollLeft + 'px',
                    //'top': rect.top + rect.height + scrollTop + 'px',
                    'z-index': maxZindex + 1,
                    'position': 'absolute',
                    'background': 'wheat'
                });

                $scope.containerVisible = true;
            }
            function _maxZindex() {
                var maxZ = Math.max.apply(null, $.map($('body > *'), function (e, n) {
                        return parseInt($(e).css('z-index')) || 1;
                    })
                );
                return maxZ;
                //el.closest(".k-dialog").css('z-index', maxZ + 1);
                //$(".k-overlay").css('z-index', maxZ + 1);
            }
            var publicApi = (function () {
                return {
                    setOptions: _setOptions,
                    //positionDropdown: _positionDropdownIfVisible,
                    //hideDropdown: _hideDropdown
                };
            })();

        }]

    }
}]);;
ngAWDSApp.directive("filterCheckbox", ['$timeout', '$filter', function ($timeout, $filter) {
    return {
        //require: 'ngModel',
        restrict: 'E',
        replace: true, //*** will replace the directives original HTML on view
        //*** if scope = undefined or scope = false or scope attibute missing, it will use parent controller $scope
        //*** if scope = {} or scope = true, it will create new $scope
        //scope: {
        //    //There are 3 types of prefixes in AngularJS:
        //    //‘@’ – Text binding / one-way binding
        //    //‘=’ – Direct model binding / two-way binding
        //    //‘&’ – Behavior binding / Method binding
        //},
        scope: {
            cNgModel: '=', //two-way binding
            cOptions: '=', //two-way binding; configuration for this drop down & callback function
            staffDropDown: '=' //two-way binding; will store the kendo drop down object, you can access from the parent controller using the bound varable on the view
        },
        //{ code: "All", count: 51, description: "Used"} cOptions.filterData format
        template: '<div class="ckb-group">'
                    + '<div class="search-box" ng-show="cOptions.hasSearchText">'
                        + '<input type="text" class="form-control" ng-model="cOptions.sSearchText" placeholder="{{cOptions.placeholder}}" />'
                        + '<span><i class="glyphicon glyphicon-search"></i></span>'
                    + '</div>'
                    + '<div ng-repeat="x in (lFiltered = (cOptions.filterData | filter:{\'Text\': cOptions.sSearchText})) | orderBy: [\'!Sort\', \'Sort\', \'Text\'] | limitTo:cOptions.iLimitTo">'
                        + '<input type="checkbox" name="ckbItem{{cOptions.fieldNameInFilter}}[]" id="ckbItem{{cOptions.fieldNameInFilter}}{{$index}}" value="{{x.Value}}" ng-model="x.Selected" ng-click="selectItem(x)">'
                        + '<label for="ckbItem{{cOptions.fieldNameInFilter}}{{$index}}">{{displayText(x)}}</label>'
                    + '</div>'
                    + '<div ng-show="lFiltered.length > cOptions.iLimitTo">'
                        + '<span class="lbl-more-options" ng-click="cOptions.iLimitTo = lFiltered.length">{{(lFiltered.length - 8)}} more options...</span>'
                    + '</div>'
                    + '<div ng-show="lFiltered.length == cOptions.iLimitTo">'
                        + '<span class="lbl-less-options" ng-click="cOptions.iLimitTo = 8">less options...</span>'
                    + '</div>'                    
				+ '</div>'
		,
        link: function ($scope, $element, $attrs) {

        },
        controller: ['$scope', '$element', '$attrs', '$rootScope', function ($scope, $element, $attrs, $rootScope) {
            $scope.cOptionsDefault = {
                fieldNameInFilter: null,
                fieldNameAllInFilter: null,
                isShowDescription: false,
                hasEmptyAtFirst: false,
                hasSearchText: true,
                sSearchText: '',
                placeholder: '',
                iLimitTo: 8,
                filterChanged: function () { }, //empty function so nothing is fired if function not passed in                
            }            
            //merge the default options into the passed in options
            $scope.cOptions = angular.merge({}, $scope.cOptionsDefault, $scope.cOptions);
            $scope.displayText = function (item) {
                return $scope.cOptions.isShowDescription ? item.Description : item.Text;
            }
            
            //add directive function we can call from controller
            $scope.cOptions.resetFilter = function () {
                angular.element($element).addClass('loading');
                $scope.cOptions.filterData = null;
            }
            $scope.cOptions.loadFilter = function (filter, filterData, isHideOnNoData, isMoveSelectedToTop) {
                angular.element($element).addClass('loading');
                isMoveSelectedToTop = (angular.isUndefined(isMoveSelectedToTop) || isMoveSelectedToTop == null) ? false : isMoveSelectedToTop;
                $scope.cOptions.filterData = filterData;

                //*** set selected item if fieldName has val
                if ($rootScope.webApp.util.hasVal(filter[$scope.cOptions.fieldNameInFilter])) {
                    

                    for (var j = 0; j < $scope.cOptions.filterData.length; j++)
                    {
                        if ($rootScope.webApp.util.includesAnyWithSplit($scope.cOptions.filterData[j].Value, filter[$scope.cOptions.fieldNameInFilter], ',')) {
                        
                            $scope.cOptions.filterData[j].Selected = true;

                            if (isMoveSelectedToTop == true)
                            {
                                $scope.cOptions.filterData[j].Sort = 9999;
                            }

                        } else {
                            $scope.cOptions.filterData[j].Selected = false;
                            //$scope.cOptions.filterData[j].Sort = null;
                        }
                    }

                    //var splitVal = filter[$scope.cOptions.fieldNameInFilter].split(',');
                    //for (var i = 0; i < splitVal.length; i++) {
                    //    for (var j = 0; j < $scope.cOptions.filterData.length; j++) {
                    //        if ($rootScope.webApp.util.indexOfLowerCase($scope.cOptions.filterData[j].Value, splitVal[i]))
                    //        {
                    //            $scope.cOptions.filterData[j].Selected = true;
                    //            break;
                    //        }
                    //    }
                    //}


                    if ($filter('filter')($scope.cOptions.filterData, function (x) { return x.Selected == true; }).length == $scope.cOptions.filterData.length) {
                        filter[$scope.cOptions.fieldNameAllInFilter] = true;
                    }
                }


                if ($rootScope.webApp.util.toBool(isHideOnNoData)) {
                    //hide filters that have no data
                    if ($scope.cOptions.filterData.length < 1) {
                        angular.element($element).find('.ckb-group').hide();
                    } else {
                        angular.element($element).find('.ckb-group').show();
                    }
                }

                angular.element($element).removeClass('loading');
            }
            $scope.cOptions.updateBreadcrumb = function (filter, lBreadcrumbs)
            {
                lBreadcrumbs = lBreadcrumbs || [];
                var lSelectedItems = $filter('filter')($scope.cOptions.filterData, function (x) { return x.Selected == true; });
                var lBreadcrumbsTemp = $filter('filter')(lBreadcrumbs, function (x) { return x.fieldName == $scope.cOptions.fieldNameInFilter; });
                //var iTotalBreadcrumbsTemp = lBreadcrumbsTemp.length;

                var lDeletings = $filter('filter')(lBreadcrumbsTemp, function (bcItem) { return !lSelectedItems.inArray(function (item) { return bcItem.val == item.Value; }); });
                var lInsertings = $filter('filter')(lSelectedItems, function (item) { return !lBreadcrumbsTemp.inArray(function (bcItem) { return item.Value == bcItem.val; }); });
                
                if (lDeletings.length > 0) {
                    for (var i = 0; i < lDeletings.length; i++) {
                        lBreadcrumbs.removeItem(function (x) { return x.fieldName == lDeletings[i].fieldName && x.val == lDeletings[i].val; });
                    }
                }
                if (lInsertings.length > 0) {
                    for (var i = 0; i < lInsertings.length; i++) {
                        var oItem = {
                            fieldName: $scope.cOptions.fieldNameInFilter,
                            lbl: $scope.cOptions.lblBreadcrumb,
                            val: lInsertings[i].Value,
                            text: lInsertings[i].Text
                        }
                        lBreadcrumbs.pushIfNotExist(oItem, function (x) { return x.fieldName == oItem.fieldName && x.val == oItem.val; });
                    }
                }                
            }
            $scope.cOptions.removeBreadcrumb = function (oDeleting, lBreadcrumbs)
            {
                lBreadcrumbs.removeItem(function (x) { return x.fieldName == oDeleting.fieldName && x.val == oDeleting.val; });
                for (var i = 0; i < $scope.cOptions.filterData.length; i++)
                {
                    if ($scope.cOptions.filterData[i].Value == oDeleting.val)
                    {
                        $scope.cOptions.filterData[i].Selected = false;
                        $scope.selectItem($scope.cOptions.filterData[i]);
                        break;
                    }
                }
            }

            $scope.updateCheckboxItemAll = function () {
                $scope.checkedValForAll = $scope.cOptions.filterData.every(function (x) { return x.Selected == true; });
            }
            $scope.updateCheckboxItem = function () {
                var sVal = '';
                $scope.cOptions.filterData.forEach(function (x) {
                    if (x.Selected == true) {
                        sVal += (sVal != '' ? "," : "") + x.Value;
                    }
                });
                if (sVal != "") {
                    if ($scope.cOptions.hasEmptyAtFirst == true)
                    {
                        sVal = "," + sVal;//push one more empty (,) item to get all variants have value is null
                    }
                    
                } else {
                    sVal = null;//*** if null, allow show all records. if "-1", show empty
                    $scope.checkedValForAll = null;
                }
                $scope.checkedValForItem = sVal;
            }

            $scope.selectItem = function (item) {
                //console.warn('Minh: checkbox clicked', item);
                //_safeCallback($scope.cOptions.filterClicked, { item: item });

                $scope.updateCheckboxItemAll();
                $scope.updateCheckboxItem();

                $scope.filterChangedIternal();
            }
            $scope.filterChangedIternal = function () {
                //update the new value to the currentFilter if we have one, its optional so we can skip this if we want to handle in the controller                
                $scope.cOptions.filterChanged($scope.checkedValForAll, $scope.cOptions.fieldNameAllInFilter, $scope.checkedValForItem, $scope.cOptions.fieldNameInFilter); //this will call the function set on the view directive
            }
        }]

    }
}]);
;
ngAWDSApp.directive("filterDropdown", ['$timeout', function ($timeout) {
    return {
        //require: 'ngModel',
        restrict: 'E',
        replace: true, //*** will replace the directives original HTML on view
        //*** if scope = undefined or scope = false or scope attibute missing, it will use parent controller $scope
        //*** if scope = {} or scope = true, it will create new $scope
        //scope: {
        //    //There are 3 types of prefixes in AngularJS:
        //    //‘@’ – Text binding / one-way binding
        //    //‘=’ – Direct model binding / two-way binding
        //    //‘&’ – Behavior binding / Method binding
        //},
        scope: {
            cNgModel: '=', //two-way binding
            cOptions: '=', //two-way binding; configuration for this drop down & callback function
            staffDropDown: '=' //two-way binding; will store the kendo drop down object, you can access from the parent controller using the bound varable on the view
        },
        //{ code: "All", count: 51, description: "Used"} cOptions.filterData format
        template: '<div class="ddl-group">'
                    //+ '<select ng-if="cOptions.isShowDescription == false" class="form-control" ng-options="item.Value as item.Text for item in cOptions.filterData" ng-model="selectedVal" ng-change="filterChangedIternal()">'
	                //    //+ '<option value="">All Categories</option>' //*** we will push this option before call the directive
                    //+ '</select>'
                    + '<select class="form-control" ng-options="item.Value as displayText(item) for item in cOptions.filterData" ng-model="selectedVal" ng-change="filterChangedIternal()">'
                    + '</select>'
				+ '</div>'
		,
        link: function ($scope, $element, $attrs) {

        },
        controller: ['$scope', '$element', '$attrs', '$rootScope', function ($scope, $element, $attrs, $rootScope) {
            $scope.cOptionsDefault = {
                //defaultFilter: null,
                //currentFilter: null,
                //isDeSelectedFilterAllowed: true,
                //filter: null,
                //requiredFilterText: 'Missing Required Filter Text',
                fieldNameInFilter: null,
                isShowRequiredFilter: false,
                isShowDescription: false,
                isTextSEOToValue: false,
                isConvertStr: false,
                selectedItem: null,
                filterChanged: function () { }, //empty function so nothing is fired if function not passed in
            }
            //merge the default options into the passed in options
            $scope.cOptions = angular.merge({}, $scope.cOptionsDefault, $scope.cOptions);
            $scope.displayText = function (item) {
                return $scope.cOptions.isShowDescription ? item.Description : item.Text;
            }
            
            //add directive function we can call from controller
            $scope.cOptions.resetFilter = function () {
                angular.element($element).addClass('loading');
                $scope.cOptions.filterData = null;
                $scope.cOptions.isShowRequiredFilter = false;
            }
            $scope.cOptions.loadFilter = function (filter, filterData, isHideOnNoData, isShowRequiredFilter) {
                angular.element($element).addClass('loading');

                if ($rootScope.webApp.util.toBool($scope.cOptions.isTextSEOToValue) == true) {
                    for (var i = 0; i < filterData.length; i++) {
                        if ($rootScope.webApp.util.hasVal(filterData[i].TextSEO)) {
                            filterData[i].Value = filterData[i].TextSEO;
                        }
                        else {
                            filterData[i].Value = null;
                        }
                    }
                }

                $scope.cOptions.filterData = filterData;

                if (angular.isObject(filter[$scope.cOptions.fieldNameInFilter])) {
                    $scope.selectedVal = filter[$scope.cOptions.fieldNameInFilter].Value;
                } else {
                    if (angular.isUndefined(filter[$scope.cOptions.fieldNameInFilter])) filter[$scope.cOptions.fieldNameInFilter] = null;
                    $scope.selectedVal = filter[$scope.cOptions.fieldNameInFilter];

                    //*** convert number to string
                    if (angular.isDefined($scope.selectedVal) && $scope.selectedVal != null) {
                        if ($scope.cOptions.isConvertStr) {
                            $scope.selectedVal = $scope.selectedVal.toString();
                        } else {
                            switch ($scope.cOptions.fieldNameInFilter) {
                                case "PageSize":
                                    $scope.selectedVal = $scope.selectedVal.toString();
                                    break;
                            }
                        }                        
                    }
                }
                $scope.cOptions.isShowRequiredFilter = isShowRequiredFilter;

                if ($rootScope.webApp.util.toBool(isHideOnNoData)) {
                    //hide filters that have no data
                    if ($scope.cOptions.filterData.length < 1) {
                        angular.element($element).find('select').hide();
                    } else {
                        angular.element($element).find('select').show();
                    }
                }

                angular.element($element).removeClass('loading');
            }
            $scope.filterChangedIternal = function () {                
                //update the new value to the currentFilter if we have one, its optional so we can skip this if we want to handle in the controller                                
                var isSelected = $rootScope.webApp.util.hasVal($scope.selectedVal);
                $scope.cOptions.selectedItem = null;
                if (isSelected) {
                    for (var i = 0; i < $scope.cOptions.filterData.length; i++) {
                        if ($scope.cOptions.filterData[i].Value == $scope.selectedVal) {
                            $scope.cOptions.selectedItem = $scope.cOptions.filterData[i];
                            break;
                        }
                    }
                }
                
                $scope.cOptions.filterChanged(isSelected, $scope.selectedVal, $scope.cOptions.fieldNameInFilter); //this will call the function set on the view directive
            }
        }]

    }
}]);
ngAWDSApp.directive("filterDropdownSearch", ['$timeout', '$q', '$document', '$filter', function ($timeout, $q, $document, $filter) {
    var DOM_EVENT = {
        RESIZE: 'resize',
        SCROLL: 'scroll',
        CLICK: 'click',
        KEYDOWN: 'keydown',
        FOCUS: 'focus',
        INPUT: 'input'
    };

    var KEYCODE = {
        TAB: 9,
        BACKSPACE: 8,
        ENTER: 13,
        CTRL: 17,
        ALT: 18,
        ESCAPE: 27,
        LEFTARROW: 37,
        UPARROW: 38,
        RIGHTARROW: 39,
        DOWNARROW: 40,
        DELETE: 46,
        MAC_COMMAND_LEFT: 91,
        MAC_COMMAND_RIGHT: 93
    };
    return {
        //require: 'ngModel',
        restrict: 'E',
        replace: true, //*** will replace the directives original HTML on view
        //*** if scope = undefined or scope = false or scope attibute missing, it will use parent controller $scope
        //*** if scope = {} or scope = true, it will create new $scope
        //scope: {
        //    //There are 3 types of prefixes in AngularJS:
        //    //‘@’ – Text binding / one-way binding
        //    //‘=’ – Direct model binding / two-way binding
        //    //‘&’ – Behavior binding / Method binding
        //},
        scope: {
            cNgModel: '=', //two-way binding
            cOptions: '=', //two-way binding; configuration for this drop down & callback function
            staffDropDown: '=' //two-way binding; will store the kendo drop down object, you can access from the parent controller using the bound varable on the view
        },
        //{ code: "All", count: 51, description: "Used"} cOptions.filterData format
        templateUrl: function ($element, $attrs) {
            return $attrs.template;
        },
        //template: '<div class="relative">'
        //        + '<div class="relative group">'
        //            + '<button ng-click="dropdownButtonClick()" class="w-full px-4 py-3 text-left text-xl font-medium text-white bg-neutral-800 border border-neutral-800 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-blue-500 z-10">'
        //                + '<span class="mr-2">{{selectedText}}</span>'
        //                + '<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 mt-1 float-right" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">'
        //                    + '<path fill-rule="evenodd" d="M6.293 9.293a1 1 0 011.414 0L10 11.586l2.293-2.293a1 1 0 111.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" />'
        //                + '</svg>'
        //            + '</button>'
        //            + '<div ng-show="cOptions.isOpen" class="ng-hide absolute right-0 mt-2 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 p-1 space-y-1 z-20 w-full">'
        //                + '<input ng-model="inputSearch" class="block w-full px-4 py-2 text-gray-800 border rounded-md border-gray-300 focus:outline-none" type="text" placeholder="Search items" autocomplete="off">'
        //                + '<a ng-repeat="item in cOptions.filterData | filter:inputSearch" class="block px-4 py-2 text-gray-700 hover:bg-gray-100 active:bg-blue-100 cursor-pointer rounded-md text-base no-underline hover:no-underline hover:text-neutral-950"'
        //                    + 'ng-class="{\'active\': item.Value == selectedVal}" ng-click="filterChangedIternal(true,item)" >{{item.Text}}</a>'
        //                + '<div ng-if="cOptions.filterData.length == 0">'
		//			        + 'no results found'
		//			    + '</div>'
        //            + '</div>'
		//		+ '</div>'
        //    + '</div>'
		//,
        link: function ($scope, $element, $attrs) {

            $timeout(function () {
                // execute the options expression
                //$q.when($scope.cOptions()).then(_initialize);
                _initialize();
            });
            function _initialize() {
                //options = options || {};
                //$scope.init(angular.extend({}, defaultOptions, options));
                $scope.init();

                _initializeContainer();
                _wireupEvents();
            }

            function _initializeContainer() {
                $scope.container = $element; //_getDefaultContainer();

                //$scope.elementUL = angular.element($scope.container[0].querySelector('ul.auto-complete-results'));
                $scope.targetSearchText = angular.element($scope.container[0].querySelector('input.search-text'));
                $scope.targetButton = angular.element($scope.container[0].querySelector('.dropdown-btn')) || angular.element($scope.container[0].querySelector('button'));
                $scope.targetMenuResults = angular.element($scope.container[0].querySelector('.dropdown-menu-results'));
                
            }

            function _wireupEvents() {
                $document.on(DOM_EVENT.CLICK, function (event) {
                    var $event = event;
                    $scope.$evalAsync(function () {
                        _handleDocumentClick($event);
                    });
                });
            }
            function _containerContainsTarget(target) {
                // use native Node.contains
                // https://developer.mozilla.org/en-US/docs/Web/API/Node/contains
                var container = $scope.container[0];
                if (angular.isFunction(container.contains) && container.contains(target)) {
                    return true;
                }

                // otherwise use .has() if jQuery is available
                if (window.jQuery && angular.isFunction($scope.container.has) &&
                    $scope.container.has(target).length > 0) {

                    return true;
                }

                // assume target is not in container
                return false;
            }

            function _containerDropdownButtonContainsTarget(target) {
                // use native Node.contains
                // https://developer.mozilla.org/en-US/docs/Web/API/Node/contains

                if ($scope.targetButton)
                {
                    var container = $scope.targetButton[0];
                    if (angular.isFunction(container.contains) && container.contains(target)) {
                        return true;
                    }

                    // otherwise use .has() if jQuery is available
                    if (window.jQuery && angular.isFunction($scope.targetButton.has) &&
                        $scope.targetButton.has(target).length > 0) {

                        return true;
                    }
                }
                // assume target is not in container
                return false;
            }
            function _srollToItemActive() {
                var attrSelector = 'a.active';

                if ($scope.targetMenuResults) {
                    // use jquery.scrollTo plugin if available
                    // http://flesler.blogspot.com/2007/10/jqueryscrollto.html
                    if (window.jQuery && window.jQuery.scrollTo) {  // requires jquery to be loaded
                        $scope.targetMenuResults.scrollTo($scope.targetMenuResults.find(attrSelector));
                        return;
                    }
                    
                    var aTag = $scope.targetMenuResults[0].querySelector(attrSelector);
                    if (aTag)
                    {
                        // this was causing the page to jump/scroll
                        //    li.scrollIntoView(true);
                        $scope.targetMenuResults[0].scrollTop = aTag.offsetTop;
                    }
                    
                }
            }
            function _handleDocumentClick(event) {
                var elementSearchText = $scope.container.find('input.search-text');
                var elementButton = $scope.container.find('.dropdown-btn');
                
                //// ignore inline
                //if ($scope.isInline()) {
                //    return;
                //}
                                

                // no container. probably destroyed in scope $destroy
                if (!$scope.container) {
                    return;
                }

                // ignore target click                 
                if (event.target === elementButton[0] || _containerDropdownButtonContainsTarget(event.target)) {
                    $element.find('input.search-text').focus();
                    _srollToItemActive();
                    event.stopPropagation();
                    return;
                }

                // ignore target click
                if (event.target === $scope.targetSearchText[0]) {
                    event.stopPropagation();
                    return;
                }


                //if (event.target === $scope.targetSearchIcon[0]) {
                //    if ($scope.options.activateOnClickSearchIcon) {
                //        if ($scope.options.searchIconCallback) {
                //            $scope.searchIconClicked(elementSearchText.val());
                //        } else {
                //            _waitAndQuery(elementSearchText.val(), 100);
                //        }

                //    }
                //}

                if (_containerContainsTarget(event.target)) {
                    event.stopPropagation();
                    return;
                }
                $scope.autoHide();
            }

            
        },
        controller: ['$scope', '$element', '$attrs', '$rootScope', function ($scope, $element, $attrs, $rootScope) {
            $scope.cOptionsDefault = {
                defaultFilter: null,
                //currentFilter: null,
                isDeSelectedFilterAllowed: true,
                //filter: null,
                fieldNameInFilter: null,
                isShowRequiredFilter: false,
                isHideCount: false,
                isOpen: false,
                requiredFilterText: 'Missing Required Filter Text',
                filterChanged: function () { }, //empty function so nothing is fired if function not passed in
            }
            $scope.inputSearch = null;
            //merge the default options into the passed in options
            $scope.init = function () {
                $scope.cOptions = angular.merge({}, $scope.cOptionsDefault, $scope.cOptions);
            }
            
            $scope.autoHide = function () {
                if ($scope.cOptions) {
                    _hideDropdown();
                }
            };
            $scope.dropdownButtonClick = function () {
                $scope.cOptions.isOpen = !$scope.cOptions.isOpen;                
            }

            function _hideDropdown() {
                if (!$scope.cOptions.isOpen) {
                    return;
                }

                // reset scroll position
                //$scope.elementUL[0].scrollTop = 0;
                $scope.cOptions.isOpen = false;
                //$scope.emptyRenderItems();
                //_resetSearchText();
                //// callback
                //_safeCallback($scope.options.dropdownHidden);
            }


            $scope.ngFilterSearchText = function () {
                return function (dataItem) {
                    var bResult = false;

                    if ($rootScope.webApp.util.hasVal($scope.inputSearch))
                    {
                        bResult = ($rootScope.webApp.util.indexOfLowerCase(dataItem.Text, $scope.inputSearch));
                    }
                    else {
                        //*** if search-text is empty, show all items
                        bResult = true;
                    }
                    
                    return bResult;
                }

            }

            //add directive function we can call from controller
            $scope.cOptions.resetFilter = function () {
                $element.parents('.panel.panel-default').find('.panel-heading a').addClass('loading');
                $scope.cOptions.filterData = null;
                $scope.cOptions.isShowRequiredFilter = false;
            }
            $scope.cOptions.loadFilter = function (filter, filterData, isHideOnNoData, isShowRequiredFilter) {
                $element.find('button').addClass('loading');
                //$scope.cOptions.filterData = filterData;
                //if (angular.isObject(filter[$scope.cOptions.fieldNameInFilter])) {
                //    $scope.selectedVal = filter[$scope.cOptions.fieldNameInFilter].Min || filter[$scope.cOptions.fieldNameInFilter].Max;
                //} else {
                //    $scope.selectedVal = filter[$scope.cOptions.fieldNameInFilter];
                //}

                //for (var i = 0; i < filterData.length; i++) {
                //    if (filterData[i].Value == $scope.selectedVal) {
                //        $scope.selectedText = filterData[i].Text;
                //        break;
                //    }
                //}

                //$scope.cOptions.isShowRequiredFilter = isShowRequiredFilter;

                //if ($rootScope.webApp.util.toBool(isHideOnNoData)) {
                //    ////hide filters that have no data
                //    //if ($scope.cOptions.filterData.length < 1) {
                //    //    angular.element($element).closest('.panel.panel-default').hide();
                //    //} else {
                //    //    angular.element($element).closest('.panel.panel-default').show();
                //    //}
                //}



                ////////////////////////
                if ($rootScope.webApp.util.toBool($scope.cOptions.isTextSEOToValue) == true) {
                    for (var i = 0; i < filterData.length; i++) {
                        if ($rootScope.webApp.util.hasVal(filterData[i].TextSEO)) {
                            filterData[i].Value = filterData[i].TextSEO;
                        }
                        else {
                            filterData[i].Value = null;
                        }
                    }
                }

                $scope.cOptions.filterData = filterData;

                if (angular.isObject(filter[$scope.cOptions.fieldNameInFilter])) {
                    $scope.selectedVal = filter[$scope.cOptions.fieldNameInFilter].Value;
                } else {
                    if (angular.isUndefined(filter[$scope.cOptions.fieldNameInFilter])) filter[$scope.cOptions.fieldNameInFilter] = null;
                    $scope.selectedVal = filter[$scope.cOptions.fieldNameInFilter];

                    //*** convert number to string
                    if (angular.isDefined($scope.selectedVal) && $scope.selectedVal != null) {
                        if ($scope.cOptions.isConvertStr) {
                            $scope.selectedVal = $scope.selectedVal.toString();
                        } else {
                            switch ($scope.cOptions.fieldNameInFilter) {
                                case "PageSize":
                                    $scope.selectedVal = $scope.selectedVal.toString();
                                    break;
                            }
                        }
                    }
                }
                //*** update selected Text
                for (var i = 0; i < filterData.length; i++) {
                    if (filterData[i].Value == $scope.selectedVal) {
                        $scope.selectedText = filterData[i].Text;
                        break;
                    }
                }

                $scope.cOptions.isShowRequiredFilter = isShowRequiredFilter;

                if ($rootScope.webApp.util.toBool(isHideOnNoData)) {
                    //hide filters that have no data
                    if ($scope.cOptions.filterData.length < 1) {
                        angular.element($element).find('select').hide();
                    } else {
                        angular.element($element).find('select').show();
                    }
                }




                $element.find('button').removeClass('loading');
            }
            $scope.filterChangedIternal = function (isSelected, item) {

                if (isSelected) {
                    //update the new value to the currentFilter if we have one, its optional so we can skip this if we want to handle in the controller
                    //if (!$rootScope.webApp.util.isEmpty($scope.cOptions.currentFilter)) {
                    //	$scope.cOptions.currentFilter[$scope.cOptions.fieldNameInFilter] = item.Value;
                    //}
                    $scope.selectedVal = item.Value;
                    
                } else {
                    if ($rootScope.webApp.util.toBool($scope.cOptions.isDeSelectedFilterAllowed)) {
                        $scope.selectedVal = null; //We only allow somefilter 
                        //update the default value to the currentFilter if we have one, its optional so we can skip this if we want to handle in the controller
                        //if (!$rootScope.webApp.util.isEmpty($scope.cOptions.currentFilter)) {
                        //	$scope.cOptions.currentFilter[$scope.cOptions.fieldNameInFilter] = null;
                        //}
                        //if (!$rootScope.webApp.util.isEmpty($scope.cOptions.currentFilter) && !$rootScope.webApp.util.isEmpty($scope.cOptions.defaultFilter)) {
                        //	$scope.cOptions.currentFilter[$scope.cOptions.fieldNameInFilter] = defaultFilter[$scope.cOptions.fieldNameInFilter]
                        //}
                    }
                }

                //update the new value to the currentFilter if we have one, its optional so we can skip this if we want to handle in the controller                                
                //var isSelected = $rootScope.webApp.util.hasVal($scope.selectedVal);
                $scope.cOptions.selectedItem = null;
                if (isSelected) {
                    for (var i = 0; i < $scope.cOptions.filterData.length; i++) {
                        if ($scope.cOptions.filterData[i].Value == $scope.selectedVal) {
                            $scope.cOptions.selectedItem = $scope.cOptions.filterData[i];
                            break;
                        }
                    }
                }
                $scope.selectedText = item.Text;
                $scope.dropdownButtonClick();//hide ddl content
                //$scope.cOptions.filterChanged(isSelected, item, $scope.cOptions.fieldNameInFilter); //this will call the function set on the view directive
                $scope.cOptions.filterChanged(isSelected, $scope.selectedVal, $scope.cOptions.fieldNameInFilter); //this will call the function set on the view directive
            }
        }]

    }
}]);;
ngAWDSApp.directive("filterRange", ['$timeout', function ($timeout) {
    return {
        //require: 'ngModel',
        restrict: 'E',
        replace: true, //*** will replace the directives original HTML on view
        //*** if scope = undefined or scope = false or scope attibute missing, it will use parent controller $scope
        //*** if scope = {} or scope = true, it will create new $scope
        //scope: {
        //    //There are 3 types of prefixes in AngularJS:
        //    //‘@’ – Text binding / one-way binding
        //    //‘=’ – Direct model binding / two-way binding
        //    //‘&’ – Behavior binding / Method binding
        //},
        scope: {
            cOptions: '=', //two-way binding; configuration for this drop down & callback function
        },
        //{ code: "All", count: 51, description: "Used"} cOptions.filterData format
        //template: '<ul class="list-group">'
		//	        + '<li class="list-group-item" ng-repeat="item in cOptions.filterData" ng-click="item.Value != selectedVal ? filterChangedIternal(true,item) : filterChangedIternal(false,item)">'
		//				+ '<div class="checkbox-box"><input type="checkbox" class="checkbox" ng-checked="item.Value == selectedVal">'
		//					+ '<label class="ckb-label"></label><span>{{item.Text}}</span> <span ng-hide="item.Count > 0">({{item.Count}})</span>'
		//				+ '</div>'
		//			+ '</li>'
		//			+ '<li class="list-group-item" ng-if="isShowRequiredFilter" >'
		//				+ '<div style="text-align: center">'
		//					+ '{{cOption.requiredFilterText}}'
		//				+ '</div>'
		//			+ '</li>'
		//			+ '<div ng-if="cOptions.filterData.length == 0" style="margin-left:22px;margin-bottom: 5px">'
		//			+ 'no results found'
		//			+ '</div>'
		//		+ '</ul>'
		//,
        template: '<div class="row">'
                    + '<div class="col-sm-6 select-padleft">'
                        + '<div class="controls">'
                            //+ '<select ng-options="item for item in cOptions.filterDataMin" ng-change="filterChangedIternal("min", item)"></select>'
                            + '<select ng-options="item.Value as item.Text for item in cOptions.filterDataMin" ng-model="selectedMin" class="form-control" ng-change="filterChangedIternal()">'
                            + '<option value=""> Min </option>'
                            + '</select>'
                            //+ '<select ng-model="selectedMin" ng-options="item.Value for x in cOptions.filterDataMin"></select>'item.name as item.shade for item in colors
                        + '</div>'
                    + '</div>'
                    + '<div class="col-sm-6 select-padright">'
                        + '<div class="controls">'
                            + '<select ng-options="item.Value as item.Text for item in cOptions.filterDataMax" ng-model="selectedMax" class="form-control" ng-change="filterChangedIternal()">'
                            + '<option value=""> Max </option>'
                            + '</select>'
                        + '</div>'
                    + '</div>'
                    + '<div class="col-xs-6" ng-if="!cOptions.isAutoRefresh">'
						+ '<div>'
							+ '<button ng-click="filterClearIternal()" class="btn-sm btn-clear">Clear</button>'
						+ '</div>'
					+ '</div>'
                    + '<div class="col-xs-6" ng-if="!cOptions.isAutoRefresh">'
						+ '<div>'
							+ '<button ng-click="filterUpdateIternal()" class="btn btn-primary btn-sm">Update</button>'
						+ '</div>'
					+ '</div>'
                    + '<div class="col-sm-12" ng-if="isShowRequiredFilter" >'
						+ '<div style="text-align: center">'
							+ '{{cOption.requiredFilterText}}'
						+ '</div>'
					+ '</div>'
                + '</div>',
        controller: ['$scope', '$element', '$attrs', '$rootScope', function ($scope, $element, $attrs, $rootScope) {
            $scope.cOptionsDefault = {
                defaultFilter: null,
                //currentFilter: null,
                isDeSelectedFilterAllowed: true,
                //filter: null,
                fieldNameInFilter: null,
                isShowRequiredFilter: false,
                isAutoRefresh: false,
                requiredFilterText: 'Missing Required Filter Text',
                filterDataMin: [],
                filterDataMax: [],
                filterChanged: function () { }, //empty function so nothing is fired if function not passed in
            }
            //merge the default options into the passed in options
            $scope.cOptions = angular.merge({}, $scope.cOptionsDefault, $scope.cOptions);

            //add directive function we can call from controller
            $scope.cOptions.resetFilter = function () {
                $element.parents('.panel.panel-default').find('.panel-heading a').addClass('loading');
                $scope.cOptions.filterDataMin = null;
                $scope.cOptions.filterDataMax = null;
                $scope.cOptions.isShowRequiredFilter = false;
            }
            $scope.cOptions.loadFilter = function (filter, filterDataMin, filterDataMax, isHideOnNoData, isShowRequiredFilter) {
                $element.parents('.panel.panel-default').find('.panel-heading a').addClass('loading');

                if (filter[$scope.cOptions.fieldNameInFilter] == null) {
                    filter[$scope.cOptions.fieldNameInFilter] = {};
                }

                $scope.cOptions.filterDataMin = filterDataMin;
                $scope.cOptions.filterDataMax = filterDataMax;
                $scope.selectedMin = filter[$scope.cOptions.fieldNameInFilter].Min;
                $scope.selectedMax = filter[$scope.cOptions.fieldNameInFilter].Max;

                //*** convert number to string
                switch ($scope.cOptions.fieldNameInFilter) {
                    case "YearFilter":
                    case "PriceFilter":
                        if (angular.isDefined($scope.selectedMin) && $scope.selectedMin != null) $scope.selectedMin = $scope.selectedMin;
                        if (angular.isDefined($scope.selectedMax) && $scope.selectedMax != null) $scope.selectedMax = $scope.selectedMax;
                        break;
                }
                $scope.cOptions.isShowRequiredFilter = isShowRequiredFilter;
                if ($rootScope.webApp.util.toBool(isHideOnNoData)) {
                    //hide filters that have no data
                    if ($scope.cOptions.filterDataMin.length < 1 && $scope.cOptions.filterDataMax.length < 1) {
                        angular.element($element).closest('.panel.panel-default').hide();
                    } else {
                        angular.element($element).closest('.panel.panel-default').show();
                    }
                }

                $element.parents('.panel.panel-default').find('.panel-heading a').removeClass('loading');
            }
            $scope.filterChangedIternal = function (item) {
                if ($scope.cOptions.isAutoRefresh)
                {
                    $scope.filterUpdateIternal();
                }
            }
            $scope.filterUpdateIternal = function ()
            {
                $scope.cOptions.filterChanged($scope.selectedMin, $scope.selectedMax, $scope.cOptions.fieldNameInFilter); //this will call the function set on the view directive
            }
            $scope.filterClearIternal = function () {
                $scope.selectedMin = null;
                $scope.selectedMax = null;
                $scope.filterUpdateIternal();
            }
        }]

    }
}]);


ngAWDSApp.directive("filterRangeSingle", ['$timeout', function ($timeout) {
    return {
        //require: 'ngModel',
        restrict: 'E',
        replace: true, //*** will replace the directives original HTML on view
        //*** if scope = undefined or scope = false or scope attibute missing, it will use parent controller $scope
        //*** if scope = {} or scope = true, it will create new $scope
        //scope: {
        //    //There are 3 types of prefixes in AngularJS:
        //    //‘@’ – Text binding / one-way binding
        //    //‘=’ – Direct model binding / two-way binding
        //    //‘&’ – Behavior binding / Method binding
        //},
        scope: {
            cOptions: '=', //two-way binding; configuration for this drop down & callback function
        },
        template: '<div class="ddl-group">'
                    + '<select class="form-control" ng-options="item.Value as displayText(item) for item in cOptions.filterData" ng-model="selectedVal" ng-change="filterChangedIternal()">'
                    + '</select>'
				+ '</div>',
        controller: ['$scope', '$element', '$attrs', '$rootScope', '$filter', function ($scope, $element, $attrs, $rootScope, $filter) {
            $scope.cOptionsDefault = {
                //defaultFilter: null,
                //currentFilter: null,
                //isDeSelectedFilterAllowed: true,
                //filter: null,
                fieldNameInFilter: null,
                isShowRequiredFilter: false,
                //isAutoRefresh: false,
                //requiredFilterText: 'Missing Required Filter Text',
                defaultOptionText: null,
                //filterData: [],
                filterChanged: function () { }, //empty function so nothing is fired if function not passed in
            }
            //merge the default options into the passed in options
            $scope.cOptions = angular.merge({}, $scope.cOptionsDefault, $scope.cOptions);
            $scope.displayText = function (item) {
                return item.Text;
            }


            //add directive function we can call from controller
            $scope.cOptions.resetFilter = function () {
                angular.element($element).addClass('loading');
                $scope.cOptions.filterData = null;
                $scope.cOptions.isShowRequiredFilter = false;
            }
            $scope.cOptions.loadFilter = function (filter, filterData, isHideOnNoData, isShowRequiredFilter) {
                angular.element($element).addClass('loading');

                if (filter[$scope.cOptions.fieldNameInFilter] == null) {
                    filter[$scope.cOptions.fieldNameInFilter] = {};
                }


                $scope.cOptions.filterData = [];//filterData;
                $scope.selectedVal = null;
                var priceFrom, priceTo;
                for (var i = 0; i < filterData.length; i++) {
                    if (i == 0) {
                        priceFrom = 0;
                        priceTo = filterData[i];
                    } else {
                        priceFrom = filterData[i - 1];
                        priceTo = filterData[i];
                    }
                    $scope.cOptions.filterData.push({ Value: priceFrom + '-' + priceTo, Text: $filter('extCurrencyZero')(priceFrom, '$', 0) + '-' + $filter('extCurrencyZero')(priceTo, '$', 0) });

                    //*** set selected value
                    if (angular.isDefined(filter[$scope.cOptions.fieldNameInFilter])
                        && (filter[$scope.cOptions.fieldNameInFilter].Min != null || filter[$scope.cOptions.fieldNameInFilter].Max != null))
                    {
                        if((filter[$scope.cOptions.fieldNameInFilter].Min == priceFrom || filter[$scope.cOptions.fieldNameInFilter].Min == null)
                            && (filter[$scope.cOptions.fieldNameInFilter].Max == priceTo || filter[$scope.cOptions.fieldNameInFilter].Max == null)
                            )
                        {
                            $scope.selectedVal = priceFrom + '-' + priceTo;
                        }
                    }
                }
                if ($scope.cOptions.defaultOptionText != null) {
                    $scope.cOptions.filterData.unshift({ Value: null, Text: $scope.cOptions.defaultOptionText });
                }

                //$scope.selectedMin = filter[$scope.cOptions.fieldNameInFilter].Min;
                //$scope.selectedMax = filter[$scope.cOptions.fieldNameInFilter].Max;
                ////*** convert number to string
                //switch ($scope.cOptions.fieldNameInFilter) {
                //    case "YearFilter":
                //    case "PriceFilter":
                //        if (angular.isDefined($scope.selectedMin) && $scope.selectedMin != null) $scope.selectedMin = $scope.selectedMin;
                //        if (angular.isDefined($scope.selectedMax) && $scope.selectedMax != null) $scope.selectedMax = $scope.selectedMax;
                //        break;
                //}


                $scope.cOptions.isShowRequiredFilter = isShowRequiredFilter;
                if ($rootScope.webApp.util.toBool(isHideOnNoData)) {
                    //hide filters that have no data
                    if ($scope.cOptions.filterData.length < 1) {
                        angular.element($element).find('select').hide();
                    } else {
                        angular.element($element).find('select').show();
                    }
                }
                angular.element($element).removeClass('loading');
            }
            $scope.filterChangedIternal = function (item) {
                if ($scope.cOptions.isAutoRefresh) {
                    $scope.filterUpdateIternal();
                }
            }
            $scope.filterUpdateIternal = function () {
                var min = null, max = null;
                if ($scope.selectedVal != null)
                {
                    min = $scope.selectedVal.split('-')[0];
                    max = $scope.selectedVal.split('-')[1];
                }
                $scope.cOptions.filterChanged($scope.selectedVal, min, max, $scope.cOptions.fieldNameInFilter); //this will call the function set on the view directive
            }
            $scope.filterClearIternal = function () {
                $scope.selectedVal = null;
                $scope.filterUpdateIternal();
            }
        }]

    }
}]);;
ngAWDSApp.directive("filterSlider", ['$timeout', function ($timeout) {
    return {
        //require: 'ngModel',
        restrict: 'E',
        replace: true, //*** will replace the directives original HTML on view
        //*** if scope = undefined or scope = false or scope attibute missing, it will use parent controller $scope
        //*** if scope = {} or scope = true, it will create new $scope
        //scope: {
        //    //There are 3 types of prefixes in AngularJS:
        //    //‘@’ – Text binding / one-way binding
        //    //‘=’ – Direct model binding / two-way binding
        //    //‘&’ – Behavior binding / Method binding
        //},
        scope: {
            cNgModel: '=', //two-way binding
            cOptions: '=', //two-way binding; configuration for this drop down & callback function
            staffDropDown: '=' //two-way binding; will store the kendo drop down object, you can access from the parent controller using the bound varable on the view
        },
        //{ code: "All", count: 51, description: "Used"} cOptions.filterData format
        template: '<div class="slider-group">'                    
                    + '<rzslider rz-slider-model="iSliderMin"'
                            + 'rz-slider-high="iSliderMax"'
                            + 'rz-slider-options="cOptions.oSliderOptions"></rzslider>'
				+ '</div>'
		,
        link: function ($scope, $element, $attrs) {

        },
        controller: ['$scope', '$element', '$attrs', '$rootScope', function ($scope, $element, $attrs, $rootScope) {
            $scope.cOptionsDefault = {
                defaultFilter: null,
                //currentFilter: null,
                isDeSelectedFilterAllowed: true,
                //filter: null,
                fieldNameInFilter: null,
                isShowRequiredFilter: false,
                requiredFilterText: 'Missing Required Filter Text',
                filterChanged: function () { }, //empty function so nothing is fired if function not passed in
            }
            //merge the default options into the passed in options
            $scope.cOptions = angular.merge({}, $scope.cOptionsDefault, $scope.cOptions);
            $scope.iSliderMin = 0;
            $scope.iSliderMax = 0;//the field is set selected value of slider            

            //add directive function we can call from controller
            $scope.cOptions.resetFilter = function () {
                angular.element($element).addClass('loading');
                $scope.cOptions.oSliderOptions = null;
                $scope.cOptions.isShowRequiredFilter = false;
            }
            $scope.cOptions.loadFilter = function (oFilter, oSliderOptions, isHideOnNoData, isShowRequiredFilter) {
                angular.element($element).addClass('loading');

                $scope.cOptions.oSliderOptions = oSliderOptions;
                $scope.iSliderMin = oFilter[$scope.cOptions.fieldNameInFilter].Min;
                $scope.iSliderMax = oFilter[$scope.cOptions.fieldNameInFilter].Max;

                oFilter[$scope.cOptions.fieldNameInFilter].Ceil = oSliderOptions.ceil;

                if ($scope.iSliderMax == null)//!$rootScope.webApp.util.hasVal($scope.iSliderMax)
                {
                    $scope.iSliderMax = oSliderOptions.ceil;
                }
                if ($scope.iSliderMax > oSliderOptions.ceil)
                {
                    $scope.iSliderMax = oSliderOptions.ceil;
                }

                //if (angular.isObject(filter[$scope.cOptions.fieldNameInFilter])) {
                //    $scope.selectedVal = filter[$scope.cOptions.fieldNameInFilter].Value;
                //} else {
                //    $scope.selectedVal = filter[$scope.cOptions.fieldNameInFilter];
                //}
                $scope.cOptions.isShowRequiredFilter = isShowRequiredFilter;

                if ($rootScope.webApp.util.toBool(isHideOnNoData)) {
                    //hide filters that have no data
                    if (!$rootScope.webApp.util.hasVal($scope.iSliderMax)) {
                        angular.element($element).find('select').hide();
                    } else {
                        angular.element($element).find('select').show();
                    }
                }

                angular.element($element).removeClass('loading');
            }

            $scope.$on('slideEnded', function () {
                // user finished sliding a handle
                $scope.filterChangedIternal();
            })

            $scope.filterChangedIternal = function () {
                //update the new value to the currentFilter if we have one, its optional so we can skip this if we want to handle in the controller   
                //oFilter[$scope.cOptions.fieldNameInFilter].Ceil = angular.copy($scope.iCeil);
                $scope.cOptions.filterChanged($scope.iSliderMin, $scope.iSliderMax, $scope.cOptions.fieldNameInFilter); //this will call the function set on the view directive
            }
        }]

    }
}]);
ngAWDSApp.directive("filterSliderSingle", ['$timeout', function ($timeout) {
    return {
        //require: 'ngModel',
        restrict: 'E',
        replace: true, //*** will replace the directives original HTML on view
        //*** if scope = undefined or scope = false or scope attibute missing, it will use parent controller $scope
        //*** if scope = {} or scope = true, it will create new $scope
        //scope: {
        //    //There are 3 types of prefixes in AngularJS:
        //    //‘@’ – Text binding / one-way binding
        //    //‘=’ – Direct model binding / two-way binding
        //    //‘&’ – Behavior binding / Method binding
        //},
        scope: {
            cNgModel: '=', //two-way binding
            cOptions: '=', //two-way binding; configuration for this drop down & callback function
            staffDropDown: '=' //two-way binding; will store the kendo drop down object, you can access from the parent controller using the bound varable on the view
        },
        //{ code: "All", count: 51, description: "Used"} cOptions.filterData format
        template: '<div class="slider-group">'
                    + '<rzslider rz-slider-model="iSliderMin"'                            
                            + 'rz-slider-options="cOptions.oSliderOptions"></rzslider>'
				+ '</div>'
        
		,
        link: function ($scope, $element, $attrs) {

        },
        controller: ['$scope', '$element', '$attrs', '$rootScope', function ($scope, $element, $attrs, $rootScope) {
            $scope.cOptionsDefault = {
                defaultFilter: null,
                //currentFilter: null,
                isDeSelectedFilterAllowed: true,
                //filter: null,
                fieldNameInFilter: null,
                isShowRequiredFilter: false,
                requiredFilterText: 'Missing Required Filter Text',
                filterChanged: function () { }, //empty function so nothing is fired if function not passed in
            }
            //merge the default options into the passed in options
            $scope.cOptions = angular.merge({}, $scope.cOptionsDefault, $scope.cOptions);
            $scope.iSliderMin = 0;
            //$scope.iSliderMax = 0;//the field is set selected value of slider            

            //add directive function we can call from controller
            $scope.cOptions.resetFilter = function () {
                angular.element($element).addClass('loading');
                $scope.cOptions.oSliderOptions = null;
                $scope.cOptions.isShowRequiredFilter = false;
            }
            $scope.cOptions.loadFilter = function (oFilter, oSliderOptions, isHideOnNoData, isShowRequiredFilter) {
                angular.element($element).addClass('loading');

                $scope.cOptions.oSliderOptions = oSliderOptions;
                $scope.iSliderMin = oFilter[$scope.cOptions.fieldNameInFilter].Min;
                //$scope.iSliderMax = oFilter[$scope.cOptions.fieldNameInFilter].Max;

//                console.warn('Minh: loadFilter: ' + $scope.cOptions.fieldNameInFilter, $scope.iSliderMin);

                oFilter[$scope.cOptions.fieldNameInFilter].Ceil = oSliderOptions.ceil;

                //if ($scope.iSliderMax == null)//!$rootScope.webApp.util.hasVal($scope.iSliderMax)
                //{
                //    $scope.iSliderMax = oSliderOptions.ceil;
                //}
                //if ($scope.iSliderMax > oSliderOptions.ceil) {
                //    $scope.iSliderMax = oSliderOptions.ceil;
                //}

                //if (angular.isObject(filter[$scope.cOptions.fieldNameInFilter])) {
                //    $scope.selectedVal = filter[$scope.cOptions.fieldNameInFilter].Value;
                //} else {
                //    $scope.selectedVal = filter[$scope.cOptions.fieldNameInFilter];
                //}
                $scope.cOptions.isShowRequiredFilter = isShowRequiredFilter;

                if ($rootScope.webApp.util.toBool(isHideOnNoData)) {
                    ////hide filters that have no data
                    //if (!$rootScope.webApp.util.hasVal($scope.iSliderMax)) {
                    //    angular.element($element).find('select').hide();
                    //} else {
                    //    angular.element($element).find('select').show();
                    //}
                }

                angular.element($element).removeClass('loading');
            }

            $scope.$on('slideEnded', function () {
                // user finished sliding a handle
                $scope.filterChangedIternal();
            })

            $scope.filterChangedIternal = function () {
                //update the new value to the currentFilter if we have one, its optional so we can skip this if we want to handle in the controller   
                //oFilter[$scope.cOptions.fieldNameInFilter].Ceil = angular.copy($scope.iCeil);
                $scope.cOptions.filterChanged($scope.iSliderMin, $scope.cOptions.fieldNameInFilter); //this will call the function set on the view directive
            }
        }]

    }
}]);;
ngAWDSApp.directive("filterStandard", ['$timeout', function ($timeout) {
    return {
        //require: 'ngModel',
        restrict: 'E',
        replace: true, //*** will replace the directives original HTML on view
        //*** if scope = undefined or scope = false or scope attibute missing, it will use parent controller $scope
        //*** if scope = {} or scope = true, it will create new $scope
        //scope: {
        //    //There are 3 types of prefixes in AngularJS:
        //    //‘@’ – Text binding / one-way binding
        //    //‘=’ – Direct model binding / two-way binding
        //    //‘&’ – Behavior binding / Method binding
        //},
        scope: {
            cNgModel: '=', //two-way binding
            cOptions: '=', //two-way binding; configuration for this drop down & callback function
            staffDropDown: '=' //two-way binding; will store the kendo drop down object, you can access from the parent controller using the bound varable on the view
        },
        //{ code: "All", count: 51, description: "Used"} cOptions.filterData format
        template: '<ul class="list-group">'
			//+ '<li class="list-group-item" ng-repeat="item in cOptions.filterData" ng-class="{\'active\': item.Value == selectedVal}" ng-click="item.Value != selectedVal ? filterChangedIternal(true,item) : filterChangedIternal(false,item)">'
            + '<li class="list-group-item" ng-repeat="item in cOptions.filterData" ng-class="{\'active\': item.Value == selectedVal}" ng-click="filterChangedIternal(true,item)">'
						+ '<div class="checkbox-box item-{{item.TextSEO}}"><input type="checkbox" class="checkbox" ng-checked="item.Value == selectedVal">'
							+ '<label class="ckb-label"></label><span>{{item.Text}}</span> <span ng-hide="cOptions.isHideCount">({{item.Count}})</span>'
						+ '</div>'
					+ '</li>'
					+ '<li class="list-group-item" ng-if="isShowRequiredFilter" >'
						+ '<div style="text-align: center">'
							+ '{{cOption.requiredFilterText}}'
						+ '</div>'
					+ '</li>'
					+ '<div ng-if="cOptions.filterData.length == 0" style="margin-left:22px;margin-bottom: 5px">'
					+ 'no results found'
					+ '</div>'
				+ '</ul>'
		,
        link: function ($scope, $element, $attrs) {

        },
        controller: ['$scope', '$element', '$attrs', '$rootScope', function ($scope, $element, $attrs, $rootScope) {
            $scope.cOptionsDefault = {
                defaultFilter: null,
                //currentFilter: null,
                isDeSelectedFilterAllowed: true,
                //filter: null,
                fieldNameInFilter: null,
                isShowRequiredFilter: false,
                isHideCount: false,
                requiredFilterText: 'Missing Required Filter Text',                
                filterChanged: function () { }, //empty function so nothing is fired if function not passed in
            }
            //merge the default options into the passed in options
            $scope.cOptions = angular.merge({}, $scope.cOptionsDefault, $scope.cOptions);

            //add directive function we can call from controller
            $scope.cOptions.resetFilter = function () {
                $element.parents('.panel.panel-default').find('.panel-heading a').addClass('loading');
                $scope.cOptions.filterData = null;
                $scope.cOptions.isShowRequiredFilter = false;
            }
            $scope.cOptions.loadFilter = function (filter, filterData, isHideOnNoData, isShowRequiredFilter) {
                $element.parents('.panel.panel-default').find('.panel-heading a').addClass('loading');
                $scope.cOptions.filterData = filterData;
                if (angular.isObject(filter[$scope.cOptions.fieldNameInFilter])) {
                    $scope.selectedVal = filter[$scope.cOptions.fieldNameInFilter].Min || filter[$scope.cOptions.fieldNameInFilter].Max;
                } else {
                    $scope.selectedVal = filter[$scope.cOptions.fieldNameInFilter];                    
                }

                
                $scope.cOptions.isShowRequiredFilter = isShowRequiredFilter;

                if ($rootScope.webApp.util.toBool(isHideOnNoData)) {
                    //hide filters that have no data
                    if ($scope.cOptions.filterData.length < 1) {
                        angular.element($element).closest('.panel.panel-default').hide();
                    } else {
                        angular.element($element).closest('.panel.panel-default').show();
                    }
                }

                $element.parents('.panel.panel-default').find('.panel-heading a').removeClass('loading');
            }
            $scope.filterChangedIternal = function (isSelected, item) {

                if (isSelected) {
                    //update the new value to the currentFilter if we have one, its optional so we can skip this if we want to handle in the controller
                    //if (!$rootScope.webApp.util.isEmpty($scope.cOptions.currentFilter)) {
                    //	$scope.cOptions.currentFilter[$scope.cOptions.fieldNameInFilter] = item.Value;
                    //}
                    $scope.selectedVal = item.Value;
                } else {
                    if ($rootScope.webApp.util.toBool($scope.cOptions.isDeSelectedFilterAllowed)) {
                        $scope.selectedVal = null; //We only allow somefilter 
                        //update the default value to the currentFilter if we have one, its optional so we can skip this if we want to handle in the controller
                        //if (!$rootScope.webApp.util.isEmpty($scope.cOptions.currentFilter)) {
                        //	$scope.cOptions.currentFilter[$scope.cOptions.fieldNameInFilter] = null;
                        //}
                        //if (!$rootScope.webApp.util.isEmpty($scope.cOptions.currentFilter) && !$rootScope.webApp.util.isEmpty($scope.cOptions.defaultFilter)) {
                        //	$scope.cOptions.currentFilter[$scope.cOptions.fieldNameInFilter] = defaultFilter[$scope.cOptions.fieldNameInFilter]
                        //}
                    }                    
                }                
                $scope.cOptions.filterChanged(isSelected, item, $scope.cOptions.fieldNameInFilter); //this will call the function set on the view directive
            }
        }]

    }
}]);;
ngAWDSApp.directive("gplaceApiDirective", function () {
    return {
        restrict: "EA",
        scope: {
            apiParam: "@apiParam",
            apiKey: "@apiKey"
        },
        template: '<span>{{sConent}}</span>',
        controller: ['$scope', 'HttpFactory', function ($scope, HttpFactory) {
            //restrict: 'EA', //E = element, A = attribute, C = class, M = comment         
            //scope: {
            //    //@ reads the attribute value, = provides two-way binding, & works with functions
            //    title: '@'
            //},
            if ($scope.apiParam != null && $scope.apiParam != null) {
                //*** Minh::20190724:: the function has many requests to google API (same time), so the API stoped. we will use another application to get data and then uncomment code bellow
                //HttpFactory.get({ ApiParam: $scope.apiParam, ApiKey: $scope.apiKey }, "Stock/ThirdPartyApi/GetGPlace").then(function (response) {
                //    $scope.sConent = response.data;
                //}, function (responseError) { });
            } else {
                console.error("Minh: GPlaceApi required Param and Key");
            }
        }]
    }
});;
ngAWDSApp.directive('ngErrorSrc', function () {
    return {
        link: function (scope, element, attrs) {
            element.bind('error', function () {
                if (attrs.src != attrs.onErrorSrc && attrs.onErrorSrc != null) {
                    attrs.$set('src', attrs.onErrorSrc);
                }
            });
        }
    }
});;

ngAWDSApp.directive('ngRepeatFinish', ['$timeout', function ($timeout) {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            if (scope.$last === true) {
                $timeout(function () {
                    scope.$emit('ngRepeatFinished');
                });
            }
        }
    }
}]);;
ngAWDSApp.directive('ngSrc', ['$timeout', '$rootScope', function ($timeout, $rootScope) {
    //**** lazy loading
    return {
        restrict: 'A',
        terminal: true,
        priority: 100,//*** override ng-src directive
        link: function ($scope, $element, $attrs) {
            var observer;

            function loadImg(changes) {
                $element.addClass('ng-lz-loading');
                changes.forEach(function (change) {
                    if (change.intersectionRatio > 0) {
                        observer.unobserve(change.target);

                        change.target.src = $attrs.ngSrc;
                        //console.warn('Minh: ', change);
                        change.target.classList.add('ng-lz-visible');
                        //change.target.classList.remove('ng-lz-loading');
                        //change.target.classList.remove('lazy-load');
                        //change.target.parentElement.classList.add('lazy-image--handled');
                        //change.target.parentElement.classList.remove('lazy-load');
                    } else {
                        change.target.classList.add('ng-lz-non-visible');
                    }
                });
            }

            $attrs.$observe('ngSrc', function (value) {
                if (!value) return;

                try {
                    /**** 
                    * dev.to/iamafro/lazy-loading-images-in-your-angularjs-project-using-the-intersectionobserver-api-ae9
                    * The Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport.
                    */
                    var isLazyLoading = $rootScope.webApp.util.toBool(($attrs.isLazy || true));
                    if (isLazyLoading == true) {
                        
                        observer = new IntersectionObserver(loadImg);
                        var img = angular.element($element)[0];
                        img.onload = function () {
                            $element.addClass('ng-lz-loaded');
                            $element.removeClass('ng-lz-loading');
                        }
                        observer.observe(img);
                    } else {
                        $attrs.$set('src', value);
                    }
                    
                }
                catch (e) {
                    //$attrs.$observe('ngSrc', function (value) {
                        $attrs.$set('src', value);
                    //});
                }

            });
        }
    };
}]);

//ngAWDSApp.directive('ngSrc1', ['$timeout', '$rootScope', '$window', '$document', 'Notification', function ($timeout, $rootScope, $window, $document, Notification) {
//    //**** lazy loading
//    return {
//        restrict: 'A',
//        terminal: true,
//        priority: 100,//*** override ng-src directive
//        link: function ($scope, $element, $attrs) {
//            /**** check-if-an-element-is-visible-in-the-viewport 
//                www.javascripttutorial.net/dom/css/check-if-an-element-is-visible-in-the-viewport/#:~:text=Use%20the%20getBoundingClientRect()%20method%20to%20get%20the%20size%20of,in%20the%20viewport%20or%20not.
//            */
//            //$(elem).attr('src', attr.ngSrc);
//            $scope.sNgSrc = null;
//            $attrs.$observe('ngSrc', function (value) {
//                if (!value)
//                    return;
//                //// Make your changes here!!
//                ////value = 'prefix-' + value;
//                //$timeout(function () {
//                //    //attr.$set('src', value);                            
//                //    updateSrc();
//                //}, 100);
//                updateSrc();
//            });
//            function updateSrc() {
//                if (angular.isUndefined($attrs.src)) {
//                    $timeout(function () {
//                        var bIsVisibleInScreen = isVisibleInScreen();
//                        if (angular.isDefined(bIsVisibleInScreen) && isValidFile()) {
//                            if ($element.hasClass('ng-lz-loaded') == false) {
//                                if (isVisibleInScreen()) {
//                                    $attrs.$set('src', $attrs.ngSrc);
//                                    $element.addClass('ng-lz-loaded');
//                                    $element.removeClass('ng-lz-loading');
//                                } else {
//                                    $element.addClass('ng-lz-loading');
//                                }
//                            }
//                        } else {
//                            //*** browser is not support the function getBoundingClientRect()
//                            if ($($element).attr('src')) {
//                            } else {
//                                $attrs.$set('src', $attrs.ngSrc);
//                            }
//                        }
//                    }, 1);
//                }
//            }
//            function isValidFile() {
//                var bVal = true;
//                if ($attrs.ngSrc) {
//                    var arrEntens = ['svg'];//*** no need to use lazy loading if existing the arrEntens
//                    var sExten = webApp.util.getFileExtension($attrs.ngSrc);
//                    if (arrEntens.indexOfLowerCase(sExten)) {
//                        bVal = false;
//                    }
//                }
//                return bVal;
//            }
//            function isVisibleInScreen() {
//                var bVal = undefined;
//                if ($element.length > 0) {
//                    try {
//                        if ($element.parents().is(':hidden')) {
//                            bVal = false;
//                        }
//                        else {
//                            var elementSelector = $element[0]; //document.querySelector('#main-container');
//                            var rect = elementSelector.getBoundingClientRect();
//                            bVal = false;
//                            /*
//                                To get the width the height of the viewport, you use the window.innerWidth and window.innerHeight in modern browsers. Some browsers, however, use the document.documentElement.clientWidth and document.documentElement.clientHeight.
//                            */
//                            //bVal = (
//                            //    rect.top >= 0 &&
//                            //    rect.left >= 0 &&
//                            //    rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
//                            //    rect.right <= (window.innerWidth || document.documentElement.clientWidth)
//                            //);
//                            // checking whether fully visible
//                            if (rect.top >= 0 && rect.bottom <= ($window.innerHeight || $document.documentElement.clientHeight)) {
//                                //console.log('Element is fully visible in screen');
//                                bVal = true;
//                            }
//                            // checking for partial visibility
//                            if (bVal == false && (rect.top < ($window.innerHeight || $document.documentElement.clientHeight) && rect.bottom >= 0)) {
//                                //console.log('Element is partially visible in screen');
//                                bVal = true;
//                            }
//                        }
//                    } catch (e) {
//                        bVal = undefined;
//                    }
//                }
//                return bVal;
//            }
//            /* Add one or more listeners to an element
//            ** @param {DOMElement} element - DOM element to add listeners to
//            ** @param {string} eventNames - space separated list of event names, e.g. 'click change'
//            ** @param {Function} listener - function to attach for each event as a listener
//            */
//            function addListenerMulti(element, eventNames, listener) {
//                if (element && element.length > 0) {
//                    var events = eventNames.split(' ');
//                    for (var i = 0, iLen = events.length; i < iLen; i++) {
//                        element.addEventListener(events[i], listener, false);
//                    }
//                }
//            }
//            angular.element($document).ready(function () {
//                //var _events = 'scroll mouseover click';
//                var _events = 'scroll';
//                var lElementModalBody = document.querySelectorAll('.modal-body');
//                if ($rootScope.webApp.util.isMobile()) {
//                    //window.addEventListener('touchstart', function () {
//                    //    Notification.warning('touchstart');
//                    //    updateSrc();
//                    //}, false);
//                    //window.addEventListener('touchmove', function () {
//                    //    //Notification.warning('touchmove');
//                    //    updateSrc();
//                    //}, false);
//                    //window.addEventListener('touchend', function () {
//                    //    Notification.warning('touchend');
//                    //    updateSrc();
//                    //}, false);
//                    angular.forEach(lElementModalBody, function (ele, idx) {
//                        //ele.addEventListener('touchstart', function () {
//                        //    updateSrc();
//                        //}, false);
//                        //ele.addEventListener('touchmove', function () {
//                        //    updateSrc();
//                        //}, false);
//                        //ele.addEventListener('touchend', function () {
//                        //    updateSrc();
//                        //}, false);
//                    });
//                }
//                addListenerMulti(window, _events, function () {
//                    Notification.warning('on event ' + _events);
//                    updateSrc();
//                })
//                //*** angularjs $document does not support function .querySelector('.modal-body')                 
//                angular.forEach(lElementModalBody, function (ele, idx) {
//                    addListenerMulti(ele, _events, function () {
//                        updateSrc();
//                    });
//                });
//                //window.addEventListener('scroll', function () {
//                //    updateSrc();
//                //});
//                //window.addEventListener('mouseover', function () {
//                //    updateSrc();
//                //});
//                //window.addEventListener('click', function () {
//                //    updateSrc();
//                //});
//                //document.querySelector('.modal-body').addEventListener('scroll', function () {
//                //    updateSrc();
//                //});
//                ////document.querySelector('.modal-body').addEventListener('mouseover', function () {
//                ////    updateSrc();
//                ////});
//                $(document).on('shown.bs.modal', '.modal', function () {
//                    updateSrc();
//                });
//            })
//        }
//    };
//}]);;
ngAWDSApp.directive('numbersQty', function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attr, ngModelCtrl) {
            function fromUser(text) {
                if (text) {
                    var transformedInput = text.replace(/[^0-9]/g, '');

                    if (transformedInput !== text) {
                        ngModelCtrl.$setViewValue(transformedInput);
                        ngModelCtrl.$render();
                    }
                    return transformedInput;
                }
                return undefined;
            }
            ngModelCtrl.$parsers.push(fromUser);
        }
    };
});;
ngAWDSApp.directive('ngClick', ['btnSpinnerService', '$rootScope', function (btnSpinnerService, $rootScope) {

    //we can override ng-click directive by same name, or use $provide.decorator.
    // $provide.decorator for example: stackoverflow.com/questions/69370369/overriding-angularjs-directive-at-runtime
    return {
        restrict: 'A',
        //terminal: true,
        priority: 0,//*** override ng-click directive
        link: function ($scope, $element, $attr) {

            if (!$attr.dataLoadingText)
            {
                $element.attr('data-loading-text', '<span class="button__text">loading...</span>');
            }
            $element.bind('click', function () {
                if ($element.hasClass($rootScope.webApp.btnSpinner.cl_btn)) {
                    if (!$attr.disabled) {
                        btnSpinnerService.clicked($element);
                    }
                }
            });
        }
    }
}]);

ngAWDSApp.directive('btnSpinner', ['btnSpinnerService', '$rootScope', function (btnSpinnerService, $rootScope) {

    //we can override ng-click directive by same name, or use $provide.decorator.
    // $provide.decorator for example: stackoverflow.com/questions/69370369/overriding-angularjs-directive-at-runtime
    return {
        restrict: 'A',
        //terminal: true,
        priority: 0,//*** override ng-click directive
        link: function ($scope, $element, $attr) {

            if (!$attr.dataLoadingText) {
                $element.attr('data-loading-text', '<span class="button__text">loading...</span>');
            }

            $element.bind('click', function () {
                if ($element.hasClass($rootScope.webApp.btnSpinner.cl_btn)) {
                    if (!$attr.disabled)
                    {
                        //*** if form $valid, enable class clicking
                        btnSpinnerService.clicked($element);
                    }
                }
            });
        }
    }
}]);


ngAWDSApp.service('btnSpinnerService', ['$rootScope', function ($rootScope) {
    //var arrButtons = [];
    /**
    * 1) clicked on button: add class clicking. showloadingicon function will find the button and change state
    * 2) if showloadingicon function is called, change button state to loading
    * 3) if hideloadingicon function is called, change button state to reset and remove class clicking
    */
    var _setState = function (ele, state) {
        switch (state) {
            case 'clicked':
                if (ele.hasClass($rootScope.webApp.btnSpinner.cl_clicked) == false) ele.addClass($rootScope.webApp.btnSpinner.cl_clicked);
                break;
            case 'loading':
                ele.button("loading");
                if (ele.hasClass($rootScope.webApp.btnSpinner.cl_loading) == false) ele.addClass($rootScope.webApp.btnSpinner.cl_loading);//add class loading for custom css
                break;
            case 'reset':
                ele.button("reset");
                ele.removeClass($rootScope.webApp.btnSpinner.cl_clicked).removeClass($rootScope.webApp.btnSpinner.cl_loading);
                break;
            default:
                break;
        }
    }

    this.clicked = function (ele) {
        _setState(ele, 'clicked');
    }
    this.loading = function (ele) {
        _setState(ele, 'loading');
    }
    this.reset = function (ele) {
        _setState(ele, 'reset');
    }
}]);;
ngAWDSApp.directive("paginationDirective", ['$rootScope', function ($rootScope) {
    return {
        restrict: "EA",
        //*** if scope = undefined or scope = false or scope attibute missing, it will use parent controller $scope
        //*** if scope = {} or scope = true, it will create new $scope
        //scope: {
        //    //There are 3 types of prefixes in AngularJS:
        //    //‘@’ – Text binding / one-way binding
        //    //‘=’ – Direct model binding / two-way binding
        //    //‘&’ – Behavior binding / Method binding
        //},
        scope: {
            dataSource: "=source",
            pageNumber: "=pageNumber",
            totalPages: "=totalPages",
            totalRecords: "=totalRecords",
            showPageTitle: "@showPageTitle",
            onPrevPage: "&",
            onNextPage: "&",
            onPage: "&",
            onResetFilter: "&",
        },
        template: '<div class="row justify-content-md-center" ng-if="dataSource.length > 0">'
                        + '<p class="page-title ng-hide" ng-show="bShowPageTitle">Page {{pageNumber}} of {{totalPages}}</p>'
                        + '<ul class="pagination">'
                            + '<li class="page-item" ng-class="{\'disabled\': pageNumber == 1}">'
                                + '<a class="btn page-link page-prev" ng-click="onPrevPage()" tabindex="-1">Prev</a>'
                            + '</li>'
                            + '<li ng-repeat="x in lPageNumber" class="page-item" ng-class="{\'active\': x.val == pageNumber, \'disabled\': x.val == \'...\'}">'
                                + '<a class="btn page-link" ng-if="x.val == pageNumber">{{x.val}}<span class="sr-only">(current)</span></a>'
                                + '<a class="btn page-link" ng-if="x.val != pageNumber" ng-click="onPage({page:x.val})" ng-class="{\'disabled\': x.val == \'...\'}">{{x.val}}</a>'
                            + '</li>'
                            + '<li class="page-item" ng-class="{\'disabled\': pageNumber == totalPages}">'
                                + '<a class="btn page-link page-next" ng-click="onNextPage()">Next</a>'
                            + '</li>'
                        + '</ul>'
                    + '</div>'
                    + '<div class="row justify-content-md-center" ng-if="totalRecords != null && dataSource.length < 1">'
                        + '<p>Your search filters have returned 0 results. Please broaden your search.</p>'
                        + '<p><a class="btn btn-moreDetails btn-reset-filter" ng-click="onResetFilter()">Reset Filters</a></p>'
                    + '</div>',
        link: function ($scope) {
            $scope.showPageTitle = $scope.showPageTitle || 'true';
            $scope.bShowPageTitle = $rootScope.webApp.util.toBool($scope.showPageTitle);
            $scope.resetPageNumber = function () {
                $scope.lPageNumber = $rootScope.webApp.util.generatePagination($scope.totalRecords, $scope.totalPages, $scope.pageNumber);
            }
            /*
            * $watch() will be triggered by:
            * $scope.myArray = [];
            * $scope.myArray = null;
            * $scope.myArray = someOtherArray;
            *
            * $watch(..., true) will be triggered by EVERYTHING above AND:
            * $scope.myArray[0].someProperty = "someValue";
            *
            *
            * $watchCollection() will be triggered by everything above AND:
            * $scope.myArray.push({}); // add element
            * $scope.myArray.splice(0, 1); // remove element
            * $scope.myArray[0] = {}; // assign index to different value
            * 
            * jsfiddle.net/luisperezphd/2zj9k872/
            */
            $scope.$watchCollection('dataSource', function (newVal, oldVal) {
                if (newVal != oldVal) {
                    $scope.resetPageNumber();
                }
            });

            //$scope.$watch('totalRecords', function (newVal, oldVal) {
            //    if (newVal != oldVal) {
            //        $scope.resetPageNumber();
            //    }
            //});
        }
    };
}]);;
/* check strong password
* one or more lowercase letter
* one or more captial (uppercase) letter
* one or more number (Digit)
* one or more special characters letter
* minimum 8 characters letter or number => use min-length

var LOWER_REGEXP = new RegExp("(?=.*[a-z])");
var UPPER_REGEXP = new RegExp("(?=.*[A-Z])");
var DIGIT_REGEXP = new RegExp("(?=.*[0-9])");
//var SPECIAL_REGEXP = new RegExp("(?=.*[$@^!%*?&])");
var SPECIAL_REGEXP = new RegExp("(?=.*[!\";#$%&'()*+,-./:;<=>?@[]^_`{|}~])");
*/


ngAWDSApp.directive('requiresDigit', ['$rootScope', function ($rootScope) {
    /* check strong password
    * one or more lowercase letter
    * one or more captial (uppercase) letter
    * one or more number (Digit)
    * one or more special characters letter
    * minimum 8 characters letter or number => use min-length
    */    
    var DIGIT_REGEXP = new RegExp("(?=.*[0-9])");

    return {
        //restrict: 'A', // only activate on element attribute
        require: 'ngModel', // get a hold of NgModelController
        link: function (scope, elem, attrs, ngModel) {
            if (!ngModel) return; // do nothing if no ng-model

            ngModel.$validators.requiresDigit = function (modelValue) {
                if (ngModel.$isEmpty(modelValue)) {
                    // consider empty models to be valid
                    return true;
                }
                if (attrs.requiresDigit == "false") {
                    return true;
                }
                if (DIGIT_REGEXP.test(modelValue)) {
                    return true;
                }
                else {
                    return false;
                }
            };
        }
    }
}]);
ngAWDSApp.directive('requiresLower', ['$rootScope', function ($rootScope) {
    var LOWER_REGEXP = new RegExp("(?=.*[a-z])");
    return {
        //restrict: 'A', // only activate on element attribute
        require: 'ngModel', // get a hold of NgModelController
        link: function (scope, elem, attrs, ngModel) {
            if (!ngModel) return; // do nothing if no ng-model

            ngModel.$validators.requiresLower = function (modelValue) {
                if (ngModel.$isEmpty(modelValue)) {
                    // consider empty models to be valid
                    return true;
                }
                if (attrs.requiresLower == "false") {
                    return true;
                }
                if (LOWER_REGEXP.test(modelValue)) {
                    return true;
                }
                else {
                    return false;
                }
            };
        }
    }
}]);
ngAWDSApp.directive('requiresUpper', ['$rootScope', function ($rootScope) {
    var UPPER_REGEXP = new RegExp("(?=.*[A-Z])");

    return {
        //restrict: 'A', // only activate on element attribute
        require: 'ngModel', // get a hold of NgModelController
        link: function (scope, elem, attrs, ngModel) {
            if (!ngModel) return; // do nothing if no ng-model

            ngModel.$validators.requiresUpper = function (modelValue) {
                if (ngModel.$isEmpty(modelValue)) {
                    // consider empty models to be valid
                    return true;
                }
                if (attrs.requiresUpper == "false") {
                    return true;
                }

                if (UPPER_REGEXP.test(modelValue)) {
                    return true;
                }
                else {
                    return false;
                }
            };
        }
    }
}]);
ngAWDSApp.directive('requiresSpecialchar', ['$rootScope', function ($rootScope) {
    var SPECIAL_REGEXP = new RegExp("(?=.*[$@^!%*?&#])");
    //var SPECIAL_REGEXP = new RegExp("(?=.*[!\";#$%&'()*+,-./:;<=>?@[]^_`{|}~])");
    //var SPECIAL_REGEXP = new RegExp("(?=.*[^A-z0-9])");//missing these letters: -_`^[]\
    //SPECIAL_REGEXP = new RegExp("!@#$%&*+")
    //var SPECIAL_REGEXP = new RegExp("(?=.*[$@^!%*?&])");

    
    

    return {
        //restrict: 'A', // only activate on element attribute
        require: 'ngModel', // get a hold of NgModelController
        link: function (scope, elem, attrs, ngModel) {
            if (!ngModel) return; // do nothing if no ng-model

            ngModel.$validators.requiresSpecialchar = function (modelValue) {
                if (ngModel.$isEmpty(modelValue)) {
                    // consider empty models to be valid
                    return true;
                }
                if (attrs.requiresSpecialchar == "false") {
                    return true;
                }
                if (SPECIAL_REGEXP.test(modelValue)) {
                    return true;
                }
                else {
                    return false;
                }
            };
        }
    }
}]);
ngAWDSApp.directive('requiresMatch', ['$rootScope', function ($rootScope) {

    return {
        //restrict: 'A', // only activate on element attribute
        require: 'ngModel', // get a hold of NgModelController
        link: function (scope, elem, attrs, ngModel) {
            if (!ngModel) return; // do nothing if no ng-model

            var isMatched = function (modelValue, attrVal) {
                if (ngModel.$isEmpty(modelValue))
                {
                    return true;
                }
                if ($rootScope.webApp.util.toBool(attrs.required) == false)
                {
                    return true;
                }
                if ($rootScope.webApp.util.equalsLowerCase(modelValue, attrVal)) {
                    return true;
                } else {
                    return false;
                }
            }

            //ngModel.$validators.requiresMatch = function (modelValue) {
            //    if (ngModel.$isEmpty(modelValue)) {
            //        // consider empty models to be valid
            //        return true;
            //    }
            //    var parentVal = attrs.requiresMatch;
            //    if ($rootScope.webApp.util.equalsLowerCase(parentVal, modelValue)) {
            //        return true;
            //    }
            //    else {
            //        return false;
            //    }
            //};

            scope.$watch(attrs.ngModel, function () {
                ngModel.$setValidity('requiresMatch', isMatched(ngModel.$viewValue, attrs.requiresMatch));
            });

            // observe the other value and re-validate on change
            attrs.$observe('requiresMatch', function (parentVal) {
                //console.warn('Minh: val: ', val, 'viewmodel:' + ngModel.$viewValue, 'attrs:' + attrs.requiresMatch)
                ngModel.$setValidity('requiresMatch', isMatched(ngModel.$viewValue, parentVal));
                
            });
        }
    }
}]);



//*** passwordVerify is old function
ngAWDSApp.directive('passwordVerify', ['$rootScope', function ($rootScope) {
    return {
        restrict: 'A', // only activate on element attribute
        require: '?ngModel', // get a hold of NgModelController
        link: function (scope, elem, attrs, ngModel) {
            if (!ngModel) return; // do nothing if no ng-model

            // watch own value and re-validate on change
            scope.$watch(attrs.ngModel, function () {
                validate();
            });

            // observe the other value and re-validate on change
            attrs.$observe('passwordVerify', function (val) {
                validate();
            });

            var validate = function () {
                // values
                var val1 = $rootScope.webApp.util.trimString(ngModel.$viewValue); 
                var val2 = attrs.passwordVerify;

                // set validity
                if ($rootScope.webApp.util.toBool(attrs.required)) {
                    var isEquals = $rootScope.webApp.util.equalsLowerCase(val1, val2);
                    ngModel.$setValidity('passwordVerify', isEquals);
                } else {
                    ngModel.$setValidity('passwordVerify', true);
                }

                
            };
        }
    }
}]);;
ngAWDSApp.directive("multipleEmails", function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ctrl) {
            function validateMultipleEmails(viewValue) {
                var emails = viewValue.split(';');
                // define single email validator here
                //var email_regexp = /^[_a-z0-9-]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,20})$/;
                var email_regexp = /^[a-z0-9!'#$%&*+\/=?^_`{|}~-]+(?:\.[a-z0-9!'#$%&*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-zA-Z]{2,}$/i;
                var validityArr = viewValue.trim() == "" || $.map(emails, function (str) {
                    if (str.trim() == "") {
                        return true;
                    } else {
                        return email_regexp.test(str.trim());
                    }
                }); // sample return is [true, true, true, false, false, false]

                var atLeastOneInvalid = false;
                angular.forEach(validityArr, function (value) {
                    if (value === false)
                        atLeastOneInvalid = true;
                });
                if (!atLeastOneInvalid) {
                    ctrl.$setValidity('multipleEmails', true);
                    return viewValue;
                } else {
                    ctrl.$setValidity('multipleEmails', false);
                    return undefined;
                }
            }
            element.ready(function () {
                scope.$apply(function () {
                    return validateMultipleEmails(element.val());
                })
            });
            ctrl.$parsers.unshift(function (viewValue) {
                return validateMultipleEmails(viewValue);
            });
        }
    };
});
ngAWDSApp.directive("validEmail", function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, ctrl) {

            function isValidEmails(viewValue)
            {
                /**** input type="email"
                * default validation of angularjs is allow minh@acs -> missed .com or .vn or .net or v.v...
                * so use this function  to check them if want
                */

                //var emails = viewValue.split(';');                
                // define single email validator here
                //var email_regexp = /^[_a-z0-9-]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,20})$/;
                var email_regexp = /^[a-z0-9!'#$%&*+\/=?^_`{|}~-]+(?:\.[a-z0-9!'#$%&*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-zA-Z]{2,}$/i;
                var validityArr = viewValue.trim() == "" || email_regexp.test(viewValue.trim());

                var atLeastOneInvalid = (validityArr == false);//false;
                //angular.forEach(validityArr, function (value) {
                //    if (value === false)
                //        atLeastOneInvalid = true;
                //});
                if (!atLeastOneInvalid) {
                    //ctrl.$setValidity('validEmail', true);
                    ctrl.$setValidity('email', true);
                    return viewValue;
                } else {
                    //ctrl.$setValidity('validEmail', false);
                    ctrl.$setValidity('email', false);
                    return undefined;
                }
            }
            element.ready(function () {
                scope.$apply(function () {
                    return isValidEmails(element.val());
                })
            });
            ctrl.$parsers.unshift(function (viewValue) {
                return isValidEmails(viewValue);
            });
        }
    };
});

ngAWDSApp.directive("validEmailSrv", ['$q', '$timeout', 'HttpFactory', function ($q, $timeout, HttpFactory)
{
    //*** Minh::20240315:: created this function
    //var EMAIL_REGEXP = /^[_a-z0-9-]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,20})$/;
    var EMAIL_REGEXP = /^[a-z0-9!'#$%&*+\/=?^_`{|}~-]+(?:\.[a-z0-9!'#$%&*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-zA-Z]{2,}$/i;
    return {
        require: '?ngModel',
        link: function (scope, element, attrs, ctrl) {

            // only apply the validator if ngModel is present and AngularJS has added the email validator
            if (ctrl && ctrl.$validators.email)
            {
                var sServerErrorMsgCallback = attrs['validEmailSrv']

                // this will overwrite the default AngularJS email validator
                ctrl.$validators.email = function (modelValue) {
                    /**** input type="email"
                    * default validation of angularjs is allow minh@acs -> missed .com or .vn or .net or v.v...
                    * so use this function  to check them if want
                    * if valid, send to server-side to validate more
                    */
                    return ctrl.$isEmpty(modelValue) || EMAIL_REGEXP.test(modelValue);
                };

                //ctrl.$validators.validEmailSrv = function (modelValue) {
                //    if (ctrl.$validators.email(modelValue)) {
                //        return ctrl.$isEmpty(modelValue) || (EMAIL_REGEXP.test(modelValue) && 'minh@acs.com' == (modelValue));
                //    }
                //    else {
                //        return true;//*** not need to show error message if not pass the email validator
                //    }
                //};
                ctrl.$serverError = null;
                ctrl.$asyncValidators.validEmailSrv = function (modelValue, viewValue) {

                    if (ctrl.$validators.email(modelValue) == false) {
                        //*** not need to show error message if not pass the email validator
                        //*** consider "not pass the email validator" model valid
                        return $q.resolve();
                    }

                    var def = $q.defer();

                    HttpFactory.post({ sEmailAddress: modelValue }, "Stock/EmailProcesser/EmailValidation").then(function (response) {
                        //return $q.resolve();   // to mark as valid or
                        // return $q.reject();   // to mark as invalid
                        var jsonData = angular.fromJson(response.data);
                        if (jsonData.IsVaid) {
                            def.resolve();
                        }
                        else {
                            ctrl.$serverError = jsonData.MessageResponse;
                            def.reject();
                        }
                    }, function (response) {
                        def.reject(response);
                    });

                    //$timeout(function () {
                    //    // Mock a delayed response
                    //    if ('minh@acs.com' == (modelValue)) {
                    //        // The username is available
                    //        def.resolve('success');
                    //    }
                    //    else {
                    //        console.warn('Minh: ', scope, element, attrs, ctrl)
                    //        ctrl.$serverError = 'error msg';
                    //        //scope.$eval(sServerErrorMsgCallback);
                    //        def.reject('error msg');
                    //    }
                    //}, 2000);

                    return def.promise;

                };
            }

            //if (ctrl && ctrl.$validators.email) {
            //    // this will overwrite the default AngularJS email validator
            //    ctrl.$validators.email = function (modelValue) {
            //        return ctrl.$isEmpty(modelValue) || EMAIL_REGEXP.test(modelValue);
            //    };
            //}

        }
    };
}]);;
ngAWDSApp.directive('validUbsCaptcha', ['$http', '$q', '$rootScope', 'HttpFactory', function ($http, $q, $rootScope, HttpFactory) {
    return {
        restrict: 'A',
        require: 'ngModel',
        scope: {
            recaptcha: "="
        },
        link: function (scope, element, attrs, ctrl) {

            //*** we changed to validate it in server
            if (attrs.ngModel) {
                scope.recaptcha.CaptCode = scope[attrs.ngModel];
            }

            //ctrl.$asyncValidators.validUbsCaptcha = function (modelValue, viewValue) {
            //    if (ctrl.$isEmpty(modelValue)) {
            //        return $q.when();
            //    }
            //    scope.recaptcha.CaptCode = modelValue;
            //    //HttpFactory.post(scope.recaptcha, "Stock/EmailProcesser/ValidateUbsCaptcha").then(function (response) {
            //    //    //return $q.resolve();   // to mark as valid or
            //    //    // return $q.reject();   // to mark as invalid
            //    //    if (response.data) {
            //    //        result.resolve();
            //    //    } else {
            //    //        result.reject();
            //    //    }
            //    //}, function (response) {
            //    //    result.reject(response);
            //    //});
            //    //return result.promise;
            //};
        }
    };
}]);;

ngAWDSApp.factory("breadcrumbsService", ['$rootScope', function ($rootScope) {
    var saveBreadcrumbs = function (breadcrumbs, item) {
        breadcrumbs = breadcrumbs || [];
        
        var isInsertNew = true;
        var isRemoveItem = false;
        var isDefinedValue2 = item.Value2 !== undefined;


        for (var i = 0; i < breadcrumbs.length; i++) {
            if (breadcrumbs[i].fieldNameInFilter == item.fieldNameInFilter) {
                isInsertNew = false;
                if (isDefinedValue2) {
                    if ($rootScope.webApp.util.isNullOrEmpty(item.Value) && $rootScope.webApp.util.isNullOrEmpty(item.Value2)) {
                        isRemoveItem = true;
                    }
                } else {
                    if ($rootScope.webApp.util.isNullOrEmpty(item.Value)) {
                        isRemoveItem = true;
                    }
                }
                if (isRemoveItem) {
                    //delete
                    breadcrumbs.removeItemByIndex(i);
                } else {
                    //edit
                    breadcrumbs[i].Text = item.Text;
                    breadcrumbs[i].Value = item.Value;
                    breadcrumbs[i].Value2 = item.Value2;//*** if value2 != undefined, it's mean the breadcrumbs has 2value (min - max)
                    //breadcrumbs[i].fieldNameInFilter = item.fieldNameInFilter;
                    //breadcrumbs[i].Sort = item.Sort;
                }

                break;
            }
        }
        if (isInsertNew == true) {
            //insert
            switch (item.fieldNameInFilter)
            {
                case 'SearchText':
                    item.Sort = 1;
                    break;
                case 'Make':
                    item.Sort = 2;
                    break;
                case 'Model':
                    item.Sort = 3;
                    break;
                case 'Series':
                    item.Sort = 4;
                    break;
                case 'Variant':
                    item.Sort = 5;
                    break;
                default:                    
                    item.Sort = breadcrumbs.getMaxByFieldName('Sort') + 1;
                    break;
            }
            

            if (isDefinedValue2) {
                if ($rootScope.webApp.util.hasVal(item.Value) && $rootScope.webApp.util.hasVal(item.Value2)) {
                    breadcrumbs.push(item);
                }
            } else {
                if ($rootScope.webApp.util.hasVal(item.Value)) {
                    breadcrumbs.push(item);
                }
            }
            
            
        }
        return breadcrumbs;
    }
    var removeBreadcrumbs = function (breadcrumbs, item) {
        breadcrumbs = breadcrumbs || [];
        for (var i = 0; i < breadcrumbs.length; i++) {
            if (breadcrumbs[i].fieldNameInFilter == item.fieldNameInFilter) {
                breadcrumbs.removeItemByIndex(i);
                break;
            }
        }
        //breadcrumbs = breadcrumbs.sort(breadcrumbs.sortBy("Sort", false, parseInt))
        return breadcrumbs.sort(breadcrumbs.sortBy("Sort", false, parseInt));            
    }
    return {
        saveBreadcrumbs: saveBreadcrumbs,
        removeBreadcrumbs: removeBreadcrumbs
    };
}]);;
ngAWDSApp.factory("commonFactory", ['HttpFactory', '$window', function (HttpFactory, $window) {
    
    return {
        getPCodeState: function () {
            return HttpFactory.get({}, "Stock/Website/GetPCodeState");
        },
        getPCode: function (sSuburb) {
            return HttpFactory.get({ Suburb: sSuburb }, "Stock/Website/GetPCode");
        },
        getSystemMakes: function () {
            return HttpFactory.get({}, "Stock/VehicleRequest/GetSystemMakes");
        },
        getSystemModels: function (sMake) {
            return HttpFactory.get({Make: sMake}, "Stock/VehicleRequest/GetSystemModels");
        },
        getSystemMakesV2: function (oParams) {
            return HttpFactory.post(oParams, "Stock/VehicleRequest/GetSystemMakesV2");
        },
        getSystemModelsV2: function (oParams) {
            return HttpFactory.post(oParams, "Stock/VehicleRequest/GetSystemModelsV2");
        }
    };
}]);;
ngAWDSApp.factory("CommonServices", [function () {
    var _GeneratePagination = function (TotalRecords, TotalPage, CurrentPage) {
        var arrayPages = [];
        var minPage = 1;
        // output nice pagination
        // always have a group of 5
        var minRange = Math.max(minPage, CurrentPage - 2);
        var maxRange = Math.min(TotalPage, CurrentPage + 2);
        if (minRange != minPage) {
            arrayPages.push({
                idx: arrayPages.length,
                val: minPage + ""
            });
            arrayPages.push({
                idx: arrayPages.length,
                val: "..."
            });
        }
        for (var i = minRange; i <= maxRange; i++) {
            arrayPages.push({
                idx: arrayPages.length,
                val: i + ""
            });
        }
        if (maxRange != TotalPage) {
            arrayPages.push({
                idx: arrayPages.length,
                val: "..."
            });
            arrayPages.push({
                idx: arrayPages.length,
                val: TotalPage + ""
            });
        }
        return arrayPages;
    }
    return {
        generatePagination: _GeneratePagination
    };
}]);;
ngAWDSApp.factory("ERNewModelFactory", ['HttpFactory', '$window', function (HttpFactory, $window) {

    var getUri = function (sAction) {
        return "Stock/NewModel/" + sAction;
    }
    var getUriAngular = function (sAction) {
        return "Stock/NewModelAngular/" + sAction;
    }
    var getFilterData = function (sAction, oParams) {
        return HttpFactory.post(oParams, getUriAngular(sAction));
    }
    //#region get
    var getDefaultData = function (oParams) {
        return HttpFactory.get(oParams, getUriAngular("GetDefaultData"));
    }
    //#endregion

    //#region post

    var getRecords = function (oParams) {
        return HttpFactory.post(oParams, getUriAngular("GetWebsiteNewModels"));
    }
    var getRecordsChild = function (oParams) {
        return HttpFactory.post(oParams, getUriAngular("GetWebsiteNewModelsChild"));
    }

    //#endregion

    //#region submit
    
    //#endregion

    return {
        getDefaultData: getDefaultData,
        getRecords: getRecords,
        getRecordsChild: getRecordsChild,
        getFilterData: getFilterData
    };
}]);;
ngAWDSApp.factory("ERProductFactory", ['HttpFactory', '$window', function (HttpFactory, $window) {

    var getUri = function (sAction) {
        return "Stock/ERProduct/" + sAction;
    }
    var getUriAngular = function (sAction) {
        return "Stock/ERProductAngular/" + sAction;
    }
    var getFilterData = function (sAction, oParams) {
        return HttpFactory.post(oParams, getUriAngular(sAction));
    }
    //#region get
    var getDefaultData = function (oParams, sUrl) {
        if (angular.isUndefined(sUrl) || sUrl == null) sUrl = getUriAngular("GetDefaultData");
        return HttpFactory.get(oParams, sUrl);
    }
    //#endregion

    //#region post

    var getRecords = function (oParams) {
        return HttpFactory.post(oParams, getUriAngular("GetProducts"));
    }

    //#endregion

    //#region submit

    //#endregion

    return {
        getDefaultData: getDefaultData,
        getRecords: getRecords,
        getFilterData: getFilterData
    };
}]);;
ngAWDSApp.factory("FormMailFactory", ['HttpFactory', '$window', function (HttpFactory, $window) {
    var sUrlEmailProcesserPrefix = "Stock/EmailProcesser/";
    var _GetDataFormSortBy = function (oParams, FormSortByNumber) {
        return HttpFactory.get(oParams, "Stock/WSStock/GetDataFormSortBy" + FormSortByNumber);
    }
    var _getUbsCaptcha = function (oParams) {
        return HttpFactory.get(oParams, sUrlEmailProcesserPrefix + "GetUbsCaptcha");
    }

    var _postToServer = function (oData, sAction)
    {
        var mappingData = function (item)
        {
            //*** Minh::20230804:: monday task #4914424617
            //*** When user submits a form, we need to collect more information as separate fields in ER.
            //'MailFrom', 
            var lFieldNames = ['ContactName', 'inputFullName', 'inputYourName', 'inputFirstName', 'inputName', 'FullName',
                'inputLastName', 'inputEmail', 'PhoneNumber', 'inputPhone',
                'IsReceivePromo', 'inputNewsSpecial', 'IsContactedBySalesperson', 'inputSalesPerson'];
            for (var i = 0; i < lFieldNames.length; i++) {
                $window.webApp.util.mappingContactInfor(item, lFieldNames[i]);
            }            
        }        
        mappingData(oData);
        if ($window.webApp.util.isDefined(oData.SecondMail)) mappingData(oData.SecondMail);

        return HttpFactory.post(oData, sUrlEmailProcesserPrefix + sAction);
    }

    //#region post
    var _verifyGoogleRecaptcha = function (oData) {
        return HttpFactory.post(oData, sUrlEmailProcesserPrefix + "VerifyGoogleRecaptcha");
    }
    
    var _sendMailBasic = function (oData) {
        return _postToServer(oData, "SendMailBasic");
        //return HttpFactory.post(oData, sUrlEmailProcesserPrefix + "SendMailBasic");
    }
    var _sendMailWithoutCap = function (oData) {
        return _postToServer(oData, "SendMailWithoutCap");
        //return HttpFactory.post(oData, sUrlEmailProcesserPrefix + "SendMailWithoutCap");
    }
    var _sendMailBasicV2 = function (oData) {
        return _postToServer(oData, "SendMailBasicV2");
        //return HttpFactory.post(oData, sUrlEmailProcesserPrefix + "SendMailBasicV2");
    }
    var _sendMailEnquiry = function (oData) {
        return _postToServer(oData, "SendMailEnquiry");
        //return HttpFactory.post(oData, sUrlEmailProcesserPrefix + "SendMailEnquiry");
    }
    var _sendMailEnquiryV2 = function (oData) {
        return _postToServer(oData, "SendMailEnquiryV2");
        //return HttpFactory.post(oData, sUrlEmailProcesserPrefix + "SendMailEnquiryV2");
    }
    var _sendMailSubscribe = function (oData) {
        return _postToServer(oData, "SendMailSubscribe");
        //return HttpFactory.post(oData, sUrlEmailProcesserPrefix + "SendMailSubscribe");
    }
    var _sendMailWithNewModelMedia = function (oData) {
        return _postToServer(oData, "SendMailWithNewModelMedia");
        //return HttpFactory.post(oData, sUrlEmailProcesserPrefix + "SendMailWithNewModelMedia");
    }
    var _sendMailWithNewModelMediaV2 = function (oData) {
        return _postToServer(oData, "SendMailWithNewModelMediaV2");
        //return HttpFactory.post(oData, sUrlEmailProcesserPrefix + "SendMailWithNewModelMediaV2");
    }
    var getMainDealership = function (oData) {
        return HttpFactory.post(oData, "Stock/Website/GetMainDealership");
    }
    //#endregion

    //#region general
    var _validateUbsCaptcha = function (oData) {
        return HttpFactory.post(oData, sUrlEmailProcesserPrefix + "ValidateUbsCaptcha");
    }
    //#endregion
    return {
        verifyGoogleRecaptcha: _verifyGoogleRecaptcha,
        SendMailBasic: _sendMailBasic,
        sendMailWithoutCap: _sendMailWithoutCap,
        SendMailBasicV2: _sendMailBasicV2,
        SendMailEnquiry: _sendMailEnquiry,
        sendMailEnquiryV2: _sendMailEnquiryV2,
        SendMailSubscribe: _sendMailSubscribe,
        SendMailWithNewModelMedia: _sendMailWithNewModelMedia,
        sendMailWithNewModelMediaV2: _sendMailWithNewModelMediaV2,
        getUbsCaptcha: _getUbsCaptcha,
        validateUbsCaptcha: _validateUbsCaptcha,
        getMainDealership: getMainDealership
    };
}]);;
ngAWDSApp.factory("FormMailServices", ['$rootScope', 'FormMailFactory', 'HttpFactory', '$filter', function ($rootScope, FormMailFactory, HttpFactory, $filter) {

    // Create Base64 Object // https://scotch.io/tutorials/how-to-encode-and-decode-strings-with-base64-in-javascript
    var Base64 = {
        _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
        encode: function (e) { var t = ""; var n, r, i, s, o, u, a; var f = 0; e = Base64._utf8_encode(e); while (f < e.length) { n = e.charCodeAt(f++); r = e.charCodeAt(f++); i = e.charCodeAt(f++); s = n >> 2; o = (n & 3) << 4 | r >> 4; u = (r & 15) << 2 | i >> 6; a = i & 63; if (isNaN(r)) { u = a = 64 } else if (isNaN(i)) { a = 64 } t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a) } return t },
        decode: function (e) { var t = ""; var n, r, i; var s, o, u, a; var f = 0; e = e.replace(/[^A-Za-z0-9+/=]/g, ""); while (f < e.length) { s = this._keyStr.indexOf(e.charAt(f++)); o = this._keyStr.indexOf(e.charAt(f++)); u = this._keyStr.indexOf(e.charAt(f++)); a = this._keyStr.indexOf(e.charAt(f++)); n = s << 2 | o >> 4; r = (o & 15) << 4 | u >> 2; i = (u & 3) << 6 | a; t = t + String.fromCharCode(n); if (u != 64) { t = t + String.fromCharCode(r) } if (a != 64) { t = t + String.fromCharCode(i) } } t = Base64._utf8_decode(t); return t },
        _utf8_encode: function (e) { e = e.replace(/\r\n/g, "\n"); var t = ""; for (var n = 0; n < e.length; n++) { var r = e.charCodeAt(n); if (r < 128) { t += String.fromCharCode(r) } else if (r > 127 && r < 2048) { t += String.fromCharCode(r >> 6 | 192); t += String.fromCharCode(r & 63 | 128) } else { t += String.fromCharCode(r >> 12 | 224); t += String.fromCharCode(r >> 6 & 63 | 128); t += String.fromCharCode(r & 63 | 128) } } return t },
        _utf8_decode: function (e) { var t = ""; var n = 0; var r = c1 = c2 = 0; while (n < e.length) { r = e.charCodeAt(n); if (r < 128) { t += String.fromCharCode(r); n++ } else if (r > 191 && r < 224) { c2 = e.charCodeAt(n + 1); t += String.fromCharCode((r & 31) << 6 | c2 & 63); n += 2 } else { c2 = e.charCodeAt(n + 1); c3 = e.charCodeAt(n + 2); t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63); n += 3 } } return t },
        generateCode: function (capId) {
            var sCode = $rootScope.webApp.oWebsite.WebsiteID + capId + $filter('toDateStrShort')(new Date());//code format: webid + form.CapId + dd/MM/yyyy
            return this.encode(sCode);
        }
    }

    var isLoadedUbsCaptcha = function () {
        return $rootScope.webApp.util.isNullOrEmpty($rootScope.webApp.ga.recaptchaSiteKey);
    }
    var reloadUbsCaptcha = function (cbSuccess) {
        if ($rootScope.webApp.util.isNullOrEmpty($rootScope.webApp.ga.recaptchaSiteKey)) {
            FormMailFactory.getUbsCaptcha({}).then(function (response) {
                //$scope.Recaptcha = response.data;
                cbSuccess(response);
            }, function (responseError) {
            })
        } else {
            console.error("Minh: ", "cannot reload ubs captcha because RecaptchaSiteKey has value");
        }
    }
    var getWSStock = function (VehicleId, cbSuccess)
    {
        //HttpFactory.get({ VehicleId: VehicleId }, "Stock/WSStockAngular/GetStockDetail").then(function (response) {
        //    cbSuccess(response);
        //}, function (responseError) {
        //});
        console.error("web-error", "not found function WSStockAngular/GetStockDetail by vehicleid: " + VehicleId);
    }
    var getWSStockAndOptions = function (VehicleId, FilterId, cbSuccess) {
        HttpFactory.get({ VehicleId: VehicleId, FilterId: FilterId }, "Stock/WSStockAngular/GetDefaultDataStockDetail").then(function (response) {
            cbSuccess(response);
        }, function (responseError) {
        });
    }
    var getThankYouUri = function (sDirectiveName) {
        //*** Minh ::20190802:: created new function
        var sUri = "";
        if (angular.isDefined($rootScope.webApp) && angular.isDefined($rootScope.webApp.formMailOptions) && angular.isDefined($rootScope.webApp.formMailOptions) && angular.isDefined($rootScope.webApp.formMailOptions.redirectToThankYou)) {
            if (!$rootScope.webApp.util.isNullOrEmpty($rootScope.webApp.formMailOptions.redirectToThankYou[sDirectiveName]))
            {
                sUri = $rootScope.webApp.util.getUrlHasPrefix($rootScope.webApp.formMailOptions.redirectToThankYou[sDirectiveName]);//new setup
            }
        } else {
            if (angular.isDefined($rootScope.ConfigFormMail) && angular.isDefined($rootScope.ConfigFormMail[sDirectiveName]))
            {
                sUri = $rootScope.util.getUrlHasPrefix($rootScope.ConfigFormMail[sDirectiveName].sThankYou);//old setup
            }
        }
        return sUri;
    }
    var redirectToThankYou = function (sDirectiveName, element, sMsgResponse) {
        //*** Minh ::20190802:: created new function
        var sThankYouUri = getThankYouUri(sDirectiveName);
        if (sThankYouUri != "") {
            window.location = sThankYouUri;
        } else {
            if (!(angular.isDefined(sMsgResponse) && $rootScope.webApp.util.hasVal(sMsgResponse))) {
                sMsgResponse = "<strong>We have received your enquiry and will be in touch with you shortly.</strong><br /><br />Regards";
            }
            element.html(sMsgResponse);
        }
    }
    
    //var mappingContactInfor = function (oMail, fieldName)
    //{
    //    if ($rootScope.webApp.util.hasVal(oMail[fieldName]))
    //    {
    //        var mappingField = null;
    //        switch (fieldName) {
    //            case 'ContactName':
    //                mappingField = 'FirstName';
    //                break;
    //            //case 'ContactName':
    //            //    mappingField = 'LastName';
    //            //    break;
    //            case 'MailFrom':
    //                mappingField = 'ContactEmail';
    //                break;
    //            case 'ContactNumber':
    //            case 'PhoneNumber':
    //                mappingField = 'ContactNumber';
    //                break;
    //            //case 'ContactName':
    //            //    mappingField = 'FlagSubscribeForMarketing';
    //            //    break;
    //            //case 'ContactName':
    //            //    mappingField = 'FlagSalesContactRequest';
    //                break;
    //            default:
    //                break;
    //        }
    //        if (mappingField != null)
    //        {
    //            oMail[mappingField] = oMail[fieldName];
    //        }
            
    //    }
    //}

    return {
        reloadUbsCaptcha: reloadUbsCaptcha,
        isLoadedUbsCaptcha: isLoadedUbsCaptcha,
        getWSStock: getWSStock,
        getWSStockAndOptions: getWSStockAndOptions,
        getThankYouUri: getThankYouUri,
        redirectToThankYou: redirectToThankYou,
        Base64: Base64,

    };
}]);;
ngAWDSApp.factory("HttpFactory", ['$q', '$http', '$window', '$rootScope', '$sce', 'sessionstorageFactory', function ($q, $http, $window, $rootScope, $sce, sessionstorageFactory) {
    var _HTTPGet = function (oParams, sUrl) {
        return _HTTPGetApi(oParams, $rootScope.util.getUrlHasPrefix(sUrl));
    }
    
    var _HTTPPost = function (oData, sUrl) {
        return _HTTPPostApi(oData, $rootScope.util.getUrlHasPrefix(sUrl));
    }

    var _HTTPPostSerialization = function (data, sUrl) {
        return _HTTPPostApiSerialization(data, $rootScope.util.getUrlHasPrefix(sUrl));
    }
    var _HTTPUpload = function (oData, sUrl) {
        return _HTTPUploadApi(oData, $rootScope.util.getUrlHasPrefix(sUrl));
    }
    var _HTTPGetApi = function (oParams, sUrl) {
        var result = $q.defer();
        sUrl = angular.lowercase(sUrl);
        $http({
            method: 'GET',
            url: sUrl,
            params: oParams,
            beforeSend: function (req) {
            }
        }).then(function (response) {
            result.resolve(response);
        }, function (response) {
            result.reject(response);
        });
        return result.promise;
    }

    var _HTTPPostApi = function (oData, sUrl) {
        var deferred = $q.defer();        
        var oConfig = {
            method: 'POST',
            url: sUrl,
            data: oData,
            beforeSend: function (req) {
                //console.warn("Minh: before send " + sUrl, oData);
            }
        };
        //if ($window.webApp.antiForgeryAjaxToken) {
        //    oConfig.headers = {
        //        'RequestVerificationToken': oData.antiForgeryAjaxToken
        //    }
        //} else {
        //    if (oData.antiForgeryAjaxToken) {
        //        oConfig.headers = {
        //            'RequestVerificationToken': oData.antiForgeryAjaxToken
        //        }
        //        //delete oData.antiForgeryAjaxToken;
        //    }
        //}
        
        $http(oConfig).then(function (response) {
            deferred.resolve(response);
            
        }, function (responseError) {
            deferred.reject(responseError);
            
        });
        //.catch(function (responseError) {
        //    console.warn('Minh: $http-finally', responseError);
        //    deferred.reject(responseError);
        //})
        //.finally(function (response) {
        //    console.warn('Minh: $http-finally', response);
        //    deferred.resolve(response);
        //});
        return deferred.promise;
    }
    var _HTTPPostApiSerialization = function (data, sUrl) {
        var result = $q.defer();
        $http({
            method: 'POST',
            url: sUrl,
            data: $.param(data),
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
            },
            beforeSend: function (req) {
            }
        }).then(function (response) {
            result.resolve(response);
        }, function (response) {
            result.reject(response);
        });
        return result.promise;
    }
    var _HTTPUploadApi = function (oData, sUrl) {
        var result = $q.defer();
        $http({
            method: 'POST',
            url: sUrl,
            data: oData,
            headers: {
                'Content-Type': undefined
            },
            beforeSend: function (req) {
            }
        }).then(function (response) {
            result.resolve(response);
        }, function (response) {
            result.reject(response);
        });
        return result.promise;
    }

    var _HTTPJsonp = function (sUrl, oParams) {
        var result = $q.defer();
        sUrl = angular.lowercase(sUrl);
        var trustedUrl = $sce.trustAsResourceUrl(sUrl); //via $sce as a trusted resource URL

        $http.jsonp(trustedUrl, { jsonpCallbackParam: 'callback' })
            .then(function (response) {
                result.resolve(response);
            }, function (response) {
                result.reject(response);
            });
        //stackoverflow.com/questions/12066002/parsing-jsonp-http-jsonp-response-in-angular-js
        return result.promise;
        //var result = $q.defer();
        //sUrl = angular.lowercase(sUrl);
        //var trustedUrl = $sce.trustAsResourceUrl(sUrl);
        //$http({
        //    method: 'JSONP',
        //    url: trustedUrl,
        //    jsonpCallbackParam: 'callback',
        //    beforeSend: function (req) {
        //    }
        //}).then(function (response) {
        //    result.resolve(response);
        //}, function (response) {
        //    result.reject(response);
        //});
        //return result.promise;
    }


    var fnPromise = function (fn, data)
    {
        var deferred = $q.defer();
        setTimeout(function () {
            if (angular.isFunction(fn)) {
                try {
                    var data = fn.call(this, data);
                    deferred.resolve({
                        config: {
                            url: fn.name,
                            method: 'function'
                        },
                        data: data//fn.call(this, data)
                    });
                } catch (e) {
                    deferred.reject('function call fail.');
                }
            } else {
                deferred.reject('is not function type');
            }
        }, 100);
        return deferred.promise;

        

        //return $q(function (resolve, reject) {
        //    setTimeout(function () {
        //        if (angular.isFunction(fn)) {
        //            resolve({
        //                config: {
        //                    url: fn.name,
        //                    method: 'function'
        //                },
        //                data: fn.call(this, data)
        //            });
        //        } else {
        //            reject('is not function type');
        //        }                
        //    }, 100);
        //});
    }
    

    var _HTTPPostWithSessionStorage = function (oData, sUrl, secondDuration)
    {
        //var userPortal = window.webApp.userPortal;
        var iWebsiteID = ($window.webApp && $window.webApp.oWebsite) ? $window.webApp.oWebsite.WebsiteID : 0;
        var sReleaseVersionNumberAreas = ($window.webApp && $window.webApp.vAreas) ? $window.webApp.vAreas : '2526.0607.9';
        var sKey = angular.toJson({ action: sUrl, param: oData, websiteId: iWebsiteID, vAreas: sReleaseVersionNumberAreas, userPortal: window.webApp.userPortal });
        var sKeyBase64 = $window.webApp.util.base64Extend.encode(sKey);

        if (sessionstorageFactory.get(sKeyBase64) != false) {            
            return fnPromise(function () {
                var decodeResponse = $window.webApp.util.base64Extend.decode(sessionstorageFactory.get(sKeyBase64));
                var response = angular.fromJson(decodeResponse);
                return response.data;
            }, {});
        }
        else {
            return $q.all([_HTTPPostApi(oData, $rootScope.util.getUrlHasPrefix(sUrl))])
                .then(function (responses) {

                    var encodeResponse = $window.webApp.util.base64Extend.encode(angular.toJson(responses[0]));
                    sessionstorageFactory.set(sKeyBase64, encodeResponse, secondDuration);

                    return responses[0];
                },
                    function (responsesError) {
                        return responsesError[0];
                    }
                );
        }
        //return _HTTPPostApi(oData, $rootScope.util.getUrlHasPrefix(sUrl));
    }
    var _HTTPGetWithSessionStorage = function (oData, sUrl, secondDuration) {
        //var userPortal = window.webApp.userPortal;
        var iWebsiteID = ($window.webApp && $window.webApp.oWebsite) ? $window.webApp.oWebsite.WebsiteID : 0;
        var sKey = angular.toJson({ action: sUrl, param: oData, websiteId: iWebsiteID, userPortal: window.webApp.userPortal });
        var sKeyBase64 = $window.webApp.util.base64Extend.encode(sKey);

        if (sessionstorageFactory.get(sKeyBase64) != false) {
            return fnPromise(function () {
                var decodeResponse = $window.webApp.util.base64Extend.decode(sessionstorageFactory.get(sKeyBase64));
                var response = angular.fromJson(decodeResponse);
                return response.data;
            }, {});
        }
        else {
            return $q.all([_HTTPGetApi(oData, $rootScope.util.getUrlHasPrefix(sUrl))])
                .then(function (responses) {

                    var encodeResponse = $window.webApp.util.base64Extend.encode(angular.toJson(responses[0]));
                    sessionstorageFactory.set(sKeyBase64, encodeResponse, secondDuration);

                    return responses[0];
                },
                    function (responsesError) {
                        return responsesError[0];
                    }
                );
        }
        //return _HTTPPostApi(oData, $rootScope.util.getUrlHasPrefix(sUrl));
    }

    return {
        get: _HTTPGet,
        getApi: _HTTPGetApi,
        post: _HTTPPost,
        postApi: _HTTPPostApi,
        postSerialization: _HTTPPostSerialization,
        upload: _HTTPUpload,
        fnPromise: fnPromise,
        jsonpApi: _HTTPJsonp,
        postWithSession: _HTTPPostWithSessionStorage,
        getWithSession: _HTTPGetWithSessionStorage
    };
}]);

;
ngAWDSApp.factory('localstorageFactory', ['$window', function ($window) {
    return {
        set: function (key, value) {
            $window.localStorage[key] = value;
        },
        get: function (key, defaultValue) {
            return $window.localStorage[key] || defaultValue || false;
        },
        setObject: function (key, value) {
            $window.localStorage[key] = JSON.stringify(value);
        },
        getObject: function (key, defaultValue) {
            if ($window.localStorage[key] != undefined) {
                return JSON.parse($window.localStorage[key]);
            } else {
                return defaultValue || false;
            }
        },
        remove: function (key) {
            $window.localStorage.removeItem(key);
        },
        clear: function () {
            $window.localStorage.clear();
        }
    }
}]);

ngAWDSApp.factory('sessionstorageFactory', ['$window', '$filter', function ($window, $filter) {
    var _formatDateExpiry = "YYYYMMDDHHMMSS"; //.toYYYYMMDDHHMMSS()

    var _generateDateExpiry = function (secondDuration)
    {
        var val = '';
        if (secondDuration > 0)
        {
            var dtNow = new Date();
            dtNow.setSeconds(secondDuration);
            val = dtNow.toYYYYMMDDHHMMSS();// $filter('date')(dtNow, _formatDateExpiry, null);
        }
        return val;
    }
    var _getValueWithoutDateExpiry = function (value) {
        
        if (value != null) {
            var data = value.substring(0, value.length - _formatDateExpiry.length);
            var sDateFormatted = value.substring(value.length - _formatDateExpiry.length, value.length);
            if (isFinite(sDateFormatted) == false) return value;//*** if end string not datetime format, return value back

            var y = sDateFormatted.substring(0, 4);
            var m = sDateFormatted.substring(4, 6); m = parseInt(m) - 1;
            var d = sDateFormatted.substring(6, 8);
            var hh = sDateFormatted.substring(8, 10);
            var mm = sDateFormatted.substring(10, 12);
            var ss = sDateFormatted.substring(12, 14);
            var dtExpired = new Date(y, m, d, hh, mm, ss);

            var dtNow = new Date();
            if (dtExpired <= dtNow) {
                return null;
            } else {
                return data;
            }
            
        }
        return null;
    }

    return {
        set: function (key, value, secondDuration) {
            secondDuration = secondDuration || ((1 * 60) * 60);//default: session will expire about 1 hrs
            $window.sessionStorage[key] = value + _generateDateExpiry(secondDuration);
        },
        get: function (key, defaultValue) {
            if ($window.sessionStorage[key] != undefined) {
                var val = _getValueWithoutDateExpiry($window.sessionStorage[key]);
                if (val == null) {
                    return (defaultValue || false);
                } else {
                    return val;
                }
            } else {
                return defaultValue || false;
            }
            //return $window.sessionStorage[key] || defaultValue || false;
        },
        setObject: function (key, value) {
            $window.sessionStorage[key] = JSON.stringify(value);
        },
        getObject: function (key, defaultValue) {
            if ($window.sessionStorage[key] != undefined) {
                return JSON.parse($window.sessionStorage[key]);
            } else {
                return defaultValue || false;
            }
        },
        remove: function (key) {
            $window.sessionStorage.removeItem(key);
        },
        clear: function () {
            $window.sessionStorage.clear();
        }
    }
}]);;
ngAWDSApp.factory('ModalService', ['$window', '$rootScope', '$uibModal', function ($window, $rootScope, $uibModal) {
    var _defaultTitle = null;

    var _custom = function (options) {
        //if (oData == null) oData = {};
        //if (oData.sTitle == null || oData.sTitle == undefined) oData.sTitle = _defaultTitle;

        var _defaultOption = {
            //title: 'EngineRoom',
            cbSuccess: function () { },
            modal: {
                animation: true,
                backdrop: 'static',//*** default true. Includes a modal-backdrop element. Alternatively, specify static for a backdrop which doesn't close the modal on click.
                //template: '<div class="modal-header">'
                //        + '<h3 class="modal-title">' + _defaultTitle + '</h3>'
                //    + '</div>'
                //    + '<div class="modal-body">'                        
                //    + '</div>'
                //    + '<div class="modal-footer">'
                //        + '<button class="btn btn-primary" ng-click="saveModal()">OK</button>'
                //        + '<button class="btn btn-warning" ng-click="closeModal()">Cancel</button>'
                //    + '</div>',
                //controller: 'ConfirmModalCtrl',
                resolve: {
                    param: function () {
                        return {};
                    },
                    modalOpts: function () {
                        return {};
                    }
                }
            }
        }
        var oOptions = angular.merge(_defaultOption, options);

        var modalInstance = $uibModal.open(oOptions.modal);
        modalInstance.result.then(function (response) {
            var dataItem = response.data;
            oOptions.cbSuccess(dataItem);
        }, function () {
            //console.warn('modal-component dismissed at: ' + new Date());
        });
    }
    var _confirm = function (oData, cbSuccess) {
        if (oData == null) oData = {};
        if (oData.sTitle == null || oData.sTitle == undefined) oData.sTitle = _defaultTitle;

        var modalInstance = $uibModal.open({
            animation: true,
            backdrop: 'static',
            windowClass: "",
            //templateUrl: "modalLogContentTemplateScript",
            template: '<div class="modal-header">'
                        + '<h3 class="modal-title" ng-show="oParam.sTitle != null">' + oData.sTitle + '</h3>'
                    + '</div>'
                    + '<div class="modal-body">'
                        //+ 'Are you sure you want to delete the <b>' + name + '</b>?'
                        + oData.sBody
                    + '</div>'
                    + '<div class="modal-footer">'
                        + '<button class="btn btn-primary" ng-click="saveModal()">OK</button>'
                        + '<button class="btn btn-warning" ng-click="closeModal()">Cancel</button>'
                    + '</div>',
            controller: 'ConfirmModalCtrl',
            size: 'sm',
            resolve: {
                param: function () {
                    return oData;
                },
                modalOpts: function () {
                    return {};
                }
            }
        });

        modalInstance.result.then(function (response) {
            var dataItem = response.data;
            cbSuccess(dataItem);
        }, function (responseDismissed) {
            console.warn('modal-component dismissed at: ' + new Date(), responseDismissed);
        });
    }
    var _confirm2 = function (oData, cbSuccess) {
        if (oData == null) oData = {};
        if (oData.sTitle == null || oData.sTitle == undefined) oData.sTitle = _defaultTitle;
        if (oData.sType == null || oData.sType == undefined) oData.sType = 'default';//"primary", "info", "success", "warning", "error"

        var modalInstance = $uibModal.open({
            animation: true,
            backdrop: 'static',
            windowClass: 'modal-confirm2 ' + ' color-' + oData.sType,
            //templateUrl: "modalLogContentTemplateScript",
            template: '<div class="modal-body">'
                        //+ 'Are you sure you want to delete the <b>' + name + '</b>?'
                        + '<div class="modal-confirm2-img">' + '</div>'
                        + '<div class="modal-confirm2-body">'
                            + '<h3 class="modal-title" ng-show="oParam.sTitle != null">' + oData.sTitle + '</h3>'
                            + '<p>' + oData.sBody + '</p>'
                        + '</div>'                        
                    + '</div>'
                    + '<div class="modal-footer">'
                        + '<button class="btn btn-primary btn-OK" ng-click="saveModal()">' + oData.commandOk.text + '</button>'
                        + '<button class="btn btn-warning btn-cancel" ng-click="closeModal()">' + oData.commandCancel.text + '</button>'
                    + '</div>',
            controller: 'Confirm2ModalCtrl',
            size: 'md',
            resolve: {
                param: function () {
                    return oData;
                },
                modalOpts: function () {
                    return {};
                }
            }
        });

        modalInstance.result.then(function (response) {
            //var dataItem = response.data;
            cbSuccess(response);
        }, function (responseDismissed) {
            //console.warn('modal-component dismissed at: ' + new Date(), responseDismissed);
            cbSuccess(responseDismissed);
        });
    }
    var _alert = function (oData, cbSuccess) {
        if (oData == null) oData = {};
        if (oData.sTitle == null || oData.sTitle == undefined) oData.sTitle = _defaultTitle;

        var modalInstance = $uibModal.open({
            animation: true,
            backdrop: 'static',
            windowClass: "",
            //templateUrl: "modalLogContentTemplateScript",
            template: '<div class="modal-header">'
                        + '<h3 class="modal-title" ng-show="oParam.sTitle != null">' + oData.sTitle + '</h3>'
                    + '</div>'
                    + '<div class="modal-body" ng-bind-html="oParam.sBody | trustAsHtml">'
                    + '</div>'
                    + '<div class="modal-footer">'
                        + '<button class="btn btn-primary" ng-click="saveModal()">OK</button>'
                        //+ '<button class="btn btn-warning" ng-click="closeModal()">Cancel</button>'
                    + '</div>',
            controller: 'ConfirmModalCtrl',
            size: 'md',
            resolve: {
                param: function () {
                    return oData;
                },
                modalOpts: function () {
                    return {};
                }
            }
        });

        modalInstance.result.then(function (response) {
            var dataItem = response.data;
            cbSuccess(dataItem);
        }, function () {
            //console.warn('modal-component dismissed at: ' + new Date());
        });
    }

    var _loginModal = function (options)
    {
        var _defaultOption = {
            templateUrl: 'modalLoginUserTemplate.html',
            bActiveLoginTab: true
        };
        var oOptions = angular.merge(_defaultOption, options);

        _custom({
            modal: {
                size: 'md',
                windowClass: "modal-window-login-register",
                templateUrl: oOptions.templateUrl,//'modalLoginUserTemplate.html',
                resolve: {
                    param: function () {
                        return { bActiveLoginTab: oOptions.bActiveLoginTab };
                    }
                },
                controller: ['$scope', '$uibModalInstance', 'param', 'Notification', '$rootScope', 'HttpFactory', '$parse', 'vcRecaptchaService', '$window', 'FormMailFactory', function (scopeModal, $uibModalInstance, param, Notification, $rootScope, HttpFactory, $parse, vcRecaptchaService, $window, FormMailFactory) {

                    var sUrlLoginController = "Stock/ShoppingCart";
                    var oUrlLoginAction = {
                        login: sUrlLoginController + '/Login',
                        loginSocial: sUrlLoginController + '/LoginSocial',
                        saveMyAccRegister: 'Stock/WebsiteClient/SaveMyAccRegister'
                    }

                    scopeModal.oParam = param || {};

                    scopeModal.sCurrentSelectedTab = '#modalTabLogin';
                    scopeModal.oLogin = {};
                    scopeModal.oRegisterAcc = {};
                    scopeModal.Recaptcha = {};

                    //#region ScreenInitilise
                    scopeModal.initModalLoginUserTemplate = function () {
                        scopeModal.bActiveLoginTab = $rootScope.webApp.util.toBool(scopeModal.oParam.bActiveLoginTab);
                        if (scopeModal.bActiveLoginTab) {
                            scopeModal.sCurrentSelectedTab = '#modalTabLogin';
                        } else {
                            scopeModal.sCurrentSelectedTab = '#modalTabSignUp';
                        }
                        scopeModal.loadCaptcha();
                    }
                    //#endregion

                    //#region GeneralFunction
                    var _loginMyAcc = function (params, cbSuccess) {
                        var sUrl = oUrlLoginAction.login;
                        if (params.ClientSource != 'System') {
                            sUrl = oUrlLoginAction.loginSocial;
                        }
                        HttpFactory.post(params, sUrl).then(function (response) {
                            var jsonData = response.data;
                            var serverMessage = $parse('frmLoginMyAccForModal.LoginEmail.$error.serverMessage');
                            if (jsonData.ErrorMsg != "") {
                                //*** show error message ***
                                scopeModal.frmLoginMyAccForModal.LoginEmail.$setValidity("serverMessage", false);
                                serverMessage.assign(scopeModal, jsonData.ErrorMsg);
                            } else {
                                cbSuccess(response);
                            }
                        }, function () { })
                    }
                    scopeModal.sendRegisterMyAccToServer = function (cbSuccess) {
                        HttpFactory.post(scopeModal.oRegisterAcc, oUrlLoginAction.saveMyAccRegister).then(function (response) {
                            if (response.data.ResponseMessage != "") {
                                //Notification.error(response.data.ResponseMessage);
                                var serverMessage = $parse('frmRegisterMyAccForModal.RegisterPass.$error.serverMessage');
                                scopeModal.frmRegisterMyAccForModal.RegisterPass.$setValidity("serverMessage", false);
                                serverMessage.assign(scopeModal, response.data.ResponseMessage);
                                scopeModal.reloadUbsCaptcha();
                            } else {
                                cbSuccess();

                            }
                            $rootScope.webApp.util.showLoadingIcon($element, false);
                        }, function (responseError) {
                            Notification.errorStd('Unknown Error.');
                            $rootScope.webApp.util.showLoadingIcon($element, false);
                            console.error("Send Mail", responseError);
                            scopeModal.reloadUbsCaptcha();
                        });
                    }
                    scopeModal._registerMyAcc = function (cbSuccess) {
                        scopeModal.frmRegisterMyAccForModal.submitted = true;

                        if (scopeModal.frmRegisterMyAccForModal.$valid) {
                            scopeModal.oRegisterAcc.Source = 'System';

                            if (scopeModal.isUbsCaptcha == false) {
                                if ($rootScope.webApp.util.trimString($rootScope.webApp.ga.recaptchaSize) == "invisible") {
                                    scopeModal.Recaptcha.cbSuccess = cbSuccess;
                                    //*** grecaptcha.execute only works with invisible reCAPTCHA.
                                    //*** google api will call callback function "scopeModal.Recaptcha.SetWidgetId()"
                                    vcRecaptchaService.execute(scopeModal.Recaptcha.widgetId);
                                } else {
                                    scopeModal.verifyGoogleRecaptchaAndSend({ sRecaptchaResponse: scopeModal.Recaptcha.response, cbSuccess: cbSuccess });
                                }
                            } else {
                                scopeModal.sendRegisterMyAccToServer(cbSuccess);
                            }
                        }
                    }
                    //#endregion

                    //#region DOMEvent
                    scopeModal.selectTab = function (sTarget) {
                        scopeModal.sCurrentSelectedTab = sTarget;
                    }
                    scopeModal.changeLoginEmail = function () {
                        var serverMessage = $parse('frmLoginMyAccForModal.LoginEmail.$error.serverMessage');
                        if (scopeModal.frmLoginMyAccForModal.LoginEmail.$error.serverMessage) {
                            scopeModal.frmLoginMyAccForModal.LoginEmail.$setValidity("serverMessage", true);
                            serverMessage.assign(scopeModal, undefined);
                        }
                    }
                    scopeModal.changeLoginPass = function () {
                        var serverMessage = $parse('frmLoginMyAccForModal.LoginEmail.$error.serverMessage');
                        if (scopeModal.frmLoginMyAccForModal.LoginEmail.$error.serverMessage) {
                            scopeModal.frmLoginMyAccForModal.LoginEmail.$setValidity("serverMessage", true);
                            serverMessage.assign(scopeModal, undefined);
                        }
                    }
                    scopeModal.changeRegisterEmail = function () {
                        var serverMessage = $parse('frmRegisterMyAccForModal.RegisterPass.$error.serverMessage');
                        if (scopeModal.frmRegisterMyAccForModal && scopeModal.frmRegisterMyAccForModal.RegisterPass.$error.serverMessage) {
                            scopeModal.frmRegisterMyAccForModal.RegisterPass.$setValidity("serverMessage", true);
                            serverMessage.assign(scopeModal, undefined);
                        }
                    }
                    scopeModal.changeRegisterPass = function () {
                        var serverMessage = $parse('frmRegisterMyAccForModal.RegisterPass.$error.serverMessage');
                        if (scopeModal.frmRegisterMyAccForModal && scopeModal.frmRegisterMyAccForModal.RegisterPass.$error.serverMessage) {
                            scopeModal.frmRegisterMyAccForModal.RegisterPass.$setValidity("serverMessage", true);
                            serverMessage.assign(scopeModal, undefined);
                        }
                    }
                    scopeModal.dismissModal = function () {
                        $uibModalInstance.dismiss({ data: {} });
                    }
                    scopeModal.closeModal = function () {
                        $uibModalInstance.close({ data: {} });
                    }

                    scopeModal.keypressInputLogin = function (e) {
                        if (e.which === 13) {
                            scopeModal.loginMyAccForModal();
                            e.preventDefault();
                        }
                    }
                    //#endregion

                    //#region save
                    scopeModal.loginMyAccForModal = function () {
                        scopeModal.frmLoginMyAccForModal.submitted = true;
                        if (scopeModal.frmLoginMyAccForModal.$valid) {
                            var params = angular.copy(scopeModal.oLogin);
                            params.ClientSource = "System";
                            params.Password = $rootScope.webApp.util.base64Extend.encode(params.Password);
                            params.IsCreateAccount = false;
                            _loginMyAcc(params, function (response) {
                                scopeModal.dismissModal();
                                $rootScope.$broadcast('btnLoginModalLogged', response); //*** the $rootScope.$broadcast event will fire an event down the $scope.$on('btnLoginModalLogged', {}) events
                            });
                        }
                    }
                    scopeModal.loginGoogleForModal = function () {

                        var GoogleAuthFetchUserDetails = function () {
                            var currentUser = scopeModal.gauth.currentUser.get();
                            var profile = currentUser.getBasicProfile();
                            var sFullName = profile.getName();
                            var sGivenName = profile.getGivenName();
                            var sFamilyName = profile.getFamilyName();
                            if (typeof (sFullName) == "undefined") {//*** gglogin
                                sFullName = profile.getEmail().split('@')[0];
                            }
                            if (typeof (sGivenName) == "undefined") {
                                sGivenName = sFullName;
                            }
                            var params = {
                                ClientSource: "Google",
                                //IsCreateAccount: false,
                                //Password: "",
                                Email: profile.getEmail(),
                                FullName: sFullName,
                                FirstName: sGivenName,
                                LastName: sFamilyName
                            };
                            //console.warn('google login user profile', params);
                            _loginMyAcc(params, function (response) {
                                scopeModal.dismissModal();
                                $rootScope.$broadcast('btnLoginModalLogged', response);
                            });
                        }
                        if (typeof ($window.webApp.ga.appId) == "undefined") {
                            console.error("sys-ex: google app ID is undefined");
                        } else {
                            if (typeof (scopeModal.gauth) == "undefined") {
                                scopeModal.gauth = gapi.auth2.getAuthInstance();
                                if (!scopeModal.gauth.isSignedIn.get()) {
                                    scopeModal.gauth.signIn({ scope: 'profile email' }).then(function (googleUser) {
                                        //console.warn('scopeModal.gauth.signIn', googleUser);
                                        GoogleAuthFetchUserDetails();
                                    }, function (err) {
                                        console.log(err);
                                    });
                                } else {
                                    GoogleAuthFetchUserDetails();
                                }
                            }
                        }
                    }

                    scopeModal.registerMyAccForModal = function () {
                        scopeModal.frmRegisterMyAccForModal.submitted = true;
                        if (scopeModal.frmRegisterMyAccForModal.$valid) {
                            scopeModal._registerMyAcc(function () {
                                var params = {};
                                params.ClientSource = "System";
                                params.Password = $rootScope.webApp.util.base64Extend.encode(scopeModal.oRegisterAcc.Password);
                                params.Email = scopeModal.oRegisterAcc.Email;
                                params.Phone = scopeModal.oRegisterAcc.Phone;
                                params.FirstName = scopeModal.oRegisterAcc.FirstName;
                                params.LastName = scopeModal.oRegisterAcc.LastName;
                                params.Postcode = scopeModal.oRegisterAcc.Postcode;
                                params.IsCreateAccount = false;
                                //$rootScope.$broadcast('btnLoginModalRegistered', { data: params });
                                //*** auto login after registered
                                _loginMyAcc(params, function (response) {
                                    scopeModal.dismissModal();
                                    $rootScope.$broadcast('btnLoginModalLogged', response); //*** the $rootScope.$broadcast event will fire an event down the $scope.$on('btnLoginModalLogged', {}) events
                                    $rootScope.webApp.util.showLoadingIcon($element, false);
                                });
                            });
                        }
                    }
                    //scopeModal.registerMyAccOfModal = function () {
                    //    $rootScope.$broadcast('btnLoginModalRegistered', 'saved');
                    //}
                    //#endregion

                    //#region google recaptcha
                    scopeModal.loadCaptcha = function () {
                        if ($rootScope.webApp.util.isNullOrEmpty($rootScope.webApp.ga.recaptchaSiteKey)) {
                            //ubs captcha
                            scopeModal.isUbsCaptcha = true;
                            scopeModal.reloadUbsCaptcha();

                        }
                        else {
                            function __onCreateAndSuccess(response, fn) {
                                if (angular.isDefined(fn) && fn == 'create') {
                                    console.log('recap-' + fn + ' widget ' + response);
                                    //__onCreate($scope[sObjName], response);
                                    scopeModal.cbCreateRecaptcha(response)
                                } else {
                                    console.log('recap-' + fn + ' response ');
                                    //__onSuccess($scope[sObjName], response);
                                    scopeModal.cbSuccessRecaptcha(response)
                                }
                            }
                            scopeModal.isUbsCaptcha = false;
                            //google captcha
                            scopeModal.Recaptcha = {
                                response: null,//https://github.com/VividCortex/angular-recaptcha
                                widgetId: null, SetResponse: __onCreateAndSuccess, SetWidgetId: __onCreateAndSuccess,
                                //SetResponse: scopeModal.cbCreateRecaptcha,//*** I have passed the function in wrong attr name "on-create". this function should be pass in attr name "on-success"
                                //SetWidgetId: scopeModal.cbSuccessRecaptcha,//*** I have passed the function in wrong attr name "on-success". this function should be pass in attr name "on-create" 
                                cbSendSuccess: function () { },
                                //SetResponse: function (widgetId) {
                                //    //scopeModal.Recaptcha.response = response;
                                //},
                                //SetWidgetId: function (response) {
                                //    //scopeModal.Recaptcha.widgetId = widgetId;
                                //},
                                Reset: function () {
                                    vcRecaptchaService.reload(scopeModal.Recaptcha.widgetId);
                                    scopeModal.Recaptcha.response = null;
                                }
                            }
                        }
                    }

                    scopeModal.reloadUbsCaptcha = function () {
                        if ($rootScope.webApp.util.isNullOrEmpty($rootScope.webApp.ga.recaptchaSiteKey)) {
                            FormMailFactory.getUbsCaptcha({}).then(function (response) {
                                scopeModal.Recaptcha = response.data;
                            }, function (responseError) {

                            })
                        } else {
                            //console.error("Minh: ", "cannot reload ubs captcha because RecaptchaSiteKey has value");
                            scopeModal.Recaptcha.Reset();
                        }
                    }
                    scopeModal.cbSuccessRecaptcha = function (response) {
                        scopeModal.Recaptcha.response = response;
                        if ($rootScope.webApp.util.trimString($rootScope.webApp.ga.recaptchaSize) == "invisible") {
                            //*** we have checked valid form when called vcRecaptchaService.execute                    
                            scopeModal.verifyGoogleRecaptchaAndSend({ sRecaptchaResponse: response });

                        } else {
                            //*** recaptcha with checkbox: no need to call verifyGoogleRecaptcha in here. we will call verify when user clicked on submit
                        }
                    }
                    scopeModal.cbCreateRecaptcha = function (widgetId) {
                        scopeModal.Recaptcha.widgetId = widgetId;
                    }
                    scopeModal.verifyGoogleRecaptchaAndSend = function (oParam) {

                        scopeModal.oRegisterAcc.CapCode = oParam.sRecaptchaResponse;
                        scopeModal.sendRegisterMyAccToServer(oParam.cbSuccess);//validate re-captcha in server

                    }
                    //#endregion

                    scopeModal.initModalLoginUserTemplate();
                }]
            },
            cbSuccess: function () {

            }
        });
    }

    return {
        confirm: _confirm,
        confirm2: _confirm2,
        alert: _alert,
        custom: _custom,
        loginModal: _loginModal
    };
}]);


ngAWDSApp.controller('ConfirmModalCtrl', ['$scope', '$uibModalInstance', function ($scope, $uibModalInstance) {
    //*** Modal controller doesn't have: $element, init(),...***
    //var params = $scope.$resolve.params

    $scope.oParam = {};

    $scope.initModal = function () {
        $scope.oParam = angular.copy($scope.$resolve.param);
    }();//*** auto call then initModal function when the function created by the end of function has ();



    //#region Save / callback function  
    $scope.saveModal = function () {
        $uibModalInstance.close({ data: $scope.oParam });
    }
    $scope.closeModal = function () {
        $uibModalInstance.dismiss({ data: 'cancel' })
    }
    //#endregion

}]);
ngAWDSApp.controller('Confirm2ModalCtrl', ['$scope', '$uibModalInstance', function ($scope, $uibModalInstance) {
    //*** Modal controller doesn't have: $element, init(),...***
    //var params = $scope.$resolve.params

    $scope.oParam = {};

    $scope.initModal = function () {
        $scope.oParam = angular.copy($scope.$resolve.param);
    }();//*** auto call then initModal function when the function created by the end of function has ();



    //#region Save / callback function  
    $scope.saveModal = function () {
        $uibModalInstance.close({ data: { command: $scope.oParam.commandOk, param: $scope.oParam } });
    }
    $scope.closeModal = function () {
        $uibModalInstance.dismiss({ data: { command: $scope.oParam.commandCancel, param: $scope.oParam } });
    }
    //#endregion

}]);;
ngAWDSApp.factory('NotificationExtend', ['$window', '$rootScope', 'Notification', '$templateCache', '$filter', '$timeout', function ($window, $rootScope, Notification, $templateCache, $filter, $timeout) {

    var defaultOptions = {
        layoutNum: 1,
        message: null,
        title: null,
        type: 'error',//"primary", "info", "success", "warning", "error"
        delay: 3000
    };
    var getPriceQty = function (price, qty) {
        price = CNumberNull(price);
        if (price != null) {
            price = price.toFixed(2);
        }
        return price * qty;
    }

    var _getLayoutNumber = function () {
        var iTemplateNum = 1;

        if ($rootScope.webApp.ssConfig) {
            if ($rootScope.webApp.ssConfig.noti_template_num) {
                iTemplateNum = $rootScope.webApp.ssConfig.noti_template_num || 1;
            }
        }
        return iTemplateNum;
    }
    var _getLayoutNumber4Qty = function () {
        var iTemplateNum = 1;

        if ($rootScope.webApp.ssConfig) {
            if ($rootScope.webApp.ssConfig.noti_qty_template_num) {
                iTemplateNum = $rootScope.webApp.ssConfig.noti_qty_template_num || 1;
            }
        }
        return iTemplateNum;
    }

    var _notiStdWithLayoutNumber = function (msg, title, type)
    {
        var iTemplateNum = _getLayoutNumber();

        switch (iTemplateNum) {
            case 2:
                Notification.standard({ layoutNum: 2, message: msg, title: title, type: type, delay: 6000 });
                break;
            default:
                Notification.standard({ layoutNum: 1, message: msg });
                break;
        }
    }

    var _getBasketNotificationTemplate = function (oNotiItem, opt) {
        opt = opt || {};
        opt.isWishlist = opt.isWishlist || false;
        opt.isEnquiryCart = opt.isEnquiryCart || false;

        var iTemplateNum = 1;
        var sHtml = '';
        var sHtmlButtons = '';

        if ($rootScope.webApp.ssConfig) {
            if ($rootScope.webApp.ssConfig.noti_template_num) {
                iTemplateNum = $rootScope.webApp.ssConfig.noti_template_num || 1;
            }
        }
        if (opt.isWishlist) {
            var priceCal = getPriceQty(oNotiItem.Price, oNotiItem.Quantity);
            switch (iTemplateNum) {
                case 2:
                    if (opt.action == 'A') {
                        sHtml = '<div class="ui-notification custom-template notification-shoppingcart shopping-noti noti-v' + iTemplateNum + '">'
                                + '<div class="myaccount-popup color-success">'
                                    + '<div class="myaccount-popup-content">'
                                       + '<h3>Item Added to Your Wishlist</h3>'
                                       + '<p class="title ng-binding">' + oNotiItem.ItemTitle + '</p>'
                                       + (priceCal > 0 ? '<p class="price ng-binding">PRICE: ' + $filter('currency')(priceCal, "$", 2) + '</p>' : '')
                                    + '</div>'
                                + '</div>'
                            + '</div>';
                    }
                    else {
                        //remove wishlist item
                        sHtml = '<div class="ui-notification custom-template notification-shoppingcart shopping-noti noti-v' + iTemplateNum + '">'
                                + '<div class="myaccount-popup color-success">'
                                    + '<div class="myaccount-popup-content">'
                                       + '<h3>Item Removed to Your Wishlist</h3>'
                                       + '<p class="title ng-binding">' + oNotiItem.ItemTitle + '</p>'
                                    + '</div>'
                                + '</div>'
                            + '</div>';
                    }

                    break;
                default:
                    sHtml = '<div class="ui-notification custom-template notification-shoppingcart shopping-noti noti-v' + iTemplateNum + '">'
                                //+ '<a class="close-icon" ng-click="nClick()">&times;</a>'
                                + '<div class="popup-shopping">'
                                    + '<div class="img-shop"><img src="' + oNotiItem.PicPath + '" class="img-responsive"></div>'
                                    + '<div class="item-class">'
                                        + '<p class="title ng-binding">' + oNotiItem.ItemTitle + '</p>'
                                        + (priceCal > 0 ? '<p class="price ng-binding">PRICE: ' + $filter('currency')(priceCal, "$", 2) + '</p>' : '')
                                        + '<p><b>ITEM ADDED TO WISHLIST</b></p>'
                                        //+ '<p><a href="' + $rootScope.util.getUrlHasPrefix('/shopping-basket/checkout') + '">PROCEED TO CHECKOUT</a></p>'
                                    + '</div>'
                                + '</div>'
                            + '</div>';
                    break;
            }
        }
        else if (opt.isEnquiryCart) {            
            switch (iTemplateNum) {
                case 2:
                    if (opt.action == 'A') {
                        sHtml = '<div class="ui-notification custom-template notification-shoppingcart shopping-noti noti-v' + iTemplateNum + '">'
                                + '<div class="myaccount-popup color-success">'
                                    + '<div class="myaccount-popup-content">'
                                       + '<h3>Item Added to Your Enquiry</h3>'
                                       + '<p class="title ng-binding">' + oNotiItem.ItemTitle + '</p>'
                                    + '</div>'
                                + '</div>'
                            + '</div>';
                    }
                    else {
                        //remove ENQUIRY item
                        sHtml = '<div class="ui-notification custom-template notification-shoppingcart shopping-noti noti-v' + iTemplateNum + '">'
                                + '<div class="myaccount-popup color-success">'
                                    + '<div class="myaccount-popup-content">'
                                       + '<h3>Item Removed to Your Enquiry</h3>'
                                       + '<p class="title ng-binding">' + oNotiItem.ItemTitle + '</p>'
                                    + '</div>'
                                + '</div>'
                            + '</div>';
                    }

                    break;
                default:
                    sHtml = '<div class="ui-notification custom-template notification-shoppingcart shopping-noti noti-v' + iTemplateNum + '">'
                                //+ '<a class="close-icon" ng-click="nClick()">&times;</a>'
                                + '<div class="popup-shopping">'
                                    + '<div class="img-shop"><img src="' + oNotiItem.PicPath + '" class="img-responsive"></div>'
                                    + '<div class="item-class">'
                                        + '<p class="title ng-binding">' + oNotiItem.ItemTitle + '</p>'                                        
                                        + '<p><b>ITEM ADDED TO ENQUIRY</b></p>'                                        
                                    + '</div>'
                                + '</div>'
                            + '</div>';
                    break;
            }
        }
        else {
            //*** default: add to cart notification template
            switch (iTemplateNum) {
                case 2:
                    if ($rootScope.webApp.util.equalsLowerCase(oNotiItem.SalePortal, 'trade') == false) {
                        sHtmlButtons = '<a href="' + $rootScope.webApp.util.getUrlHasPrefix('/shopping-basket') + '" class="btn-1 btn-cart">Go to Cart <i></i></a>'
                                        + '<a href="' + $rootScope.webApp.util.getUrlHasPrefix('/shopping-basket/checkout') + '" class="btn-2 btn-checkout">Check Out <i></i></a>';
                    }
                    sHtmlButtons = '<div class="myaccount-btn-list">'
                                        + sHtmlButtons
                                    + '</div>';
                    sHtml = '<div class="ui-notification custom-template notification-shoppingcart shopping-noti noti-v' + iTemplateNum + '">'
                                + '<div class="myaccount-popup color-success">'
                                    + '<div class="myaccount-popup-content">'
                                       + '<h3>Item Added to Your Cart</h3>'
                                       + '<p class="title ng-binding">' + oNotiItem.ItemTitle + ' x ' + oNotiItem.Quantity + '</p>'
                                       + '<p class="price ng-binding"><b>Total</b> ' + $filter('currency')(getPriceQty(oNotiItem.Price, oNotiItem.Quantity), "$", 2) + '</p>'
                                       + sHtmlButtons
                                    + '</div>'
                                + '</div>'
                            + '</div>';
                    break;
                default:
                    sHtml = '<div class="ui-notification custom-template notification-shoppingcart shopping-noti noti-v' + iTemplateNum + '">'
                                //+ '<a class="close-icon" ng-click="nClick()">&times;</a>'
                                + '<div class="popup-shopping">'
                                    + '<div class="img-shop"><img src="' + oNotiItem.PicPath + '" class="img-responsive"></div>'
                                    + '<div class="item-class">'
                                        + '<p class="title ng-binding">' + oNotiItem.ItemTitle + '</p>'
                                        + '<p class="price ng-binding">PRICE: ' + $filter('currency')(getPriceQty(oNotiItem.Price, oNotiItem.Quantity), "$", 2) + '</p>'
                                        + '<p><b>ITEM ADDED TO CART</b></p>'
                                        + '<p><a href="' + $rootScope.webApp.util.getUrlHasPrefix('/shopping-basket/checkout') + '">PROCEED TO CHECKOUT</a></p>'
                                    + '</div>'
                                + '</div>'
                            + '</div>';
                    break;
            }

        }
        return sHtml;
    }

    Notification.standard = function (data) {
        var cOptions = angular.merge({}, defaultOptions, data);
        switch (data.layoutNum) {
            case 2:
                Notification.layout1({ message: cOptions.message, title: cOptions.title, type: cOptions.type, delay: cOptions.delay });
                break;
            case 1:
            default:
                Notification.error(cOptions.message);
                break;
        }
    }
    
    Notification.errorStd = function (msg, title) {
        _notiStdWithLayoutNumber(msg, title, 'error');
        //var iTemplateNum = _getLayoutNumber();
        //switch (iTemplateNum) {
        //    case 2:
        //        Notification.standard({ layoutNum: 2, message: msg, title: title, type: 'error', delay: 6000 });
        //        break;
        //    default:
        //        Notification.standard({ layoutNum: 1, message: msg });
        //        break;
        //}
    }
    Notification.successStd = function (msg, title) {
        _notiStdWithLayoutNumber(msg, title, 'success');
        //var iTemplateNum = _getLayoutNumber();
        //switch (iTemplateNum) {
        //    case 2:
        //        Notification.standard({ layoutNum: 2, message: msg, title: title, type: 'success', delay: 6000 });
        //        break;
        //    default:
        //        Notification.standard({ layoutNum: 1, message: msg });
        //        break;
        //}
    }
    Notification.primaryStd = function (msg, title) {
        _notiStdWithLayoutNumber(msg, title, 'primary');
        //var iTemplateNum = _getLayoutNumber();
        //switch (iTemplateNum) {
        //    case 2:
        //        Notification.standard({ layoutNum: 2, message: msg, title: title, type: 'primary', delay: 6000 });
        //        break;
        //    default:
        //        Notification.standard({ layoutNum: 1, message: msg });
        //        break;
        //}
    }
    Notification.warningStd = function (msg, title) {
        _notiStdWithLayoutNumber(msg, title, 'warning');
    }
    Notification.infoStd = function (msg, title) {
        _notiStdWithLayoutNumber(msg, title, 'info');
    }

    Notification.errorQty = function (msg)
    {
        var iTemplateNum = _getLayoutNumber4Qty();
        
        switch (iTemplateNum) {
            case 3:
                msg = "Sorry we don't have any more in stock right now.";
                sDesc = "If you would like to order more of this item, please contact us to discuss availability and restocking lead-time.";                
                Notification.standard({ layoutNum: 2, message: sDesc, title: msg, type: 'error', delay: 6000 });
                break;
            case 2:
                sDesc = 'If you would like to order more, please call us on ' + $rootScope.webApp.oWebsite.DLRPhone1 + ' to discuss availability and restocking lead-time.';
                //Notification.layout1({ message: sDesc, title: msg, type: 'error', delay: 6000 });
                Notification.standard({ layoutNum: 2, message: sDesc, title: msg, type: 'error', delay: 6000 });
                break;
            default:
                //Notification.error(msg);
                Notification.standard({ layoutNum: 1, message: msg });
                break;
        }        
    }

    Notification.errorShopping = function (msg, title) {
        var iTemplateNum = _getLayoutNumber();

        switch (iTemplateNum) {
            case 2:
                title = title || 'Unknown Error';
                
                Notification.standard({ layoutNum: 2, message: msg, title: title, type: 'error', delay: 6000 });
                break;
            default:                
                Notification.standard({ layoutNum: 1, message: msg });
                break;
        }
    }

    Notification.layout1 = function (opt)
    {
        var oOptions = angular.merge({
            title: null,
            message: null,
            delay: null,
            type: 'primary',
            closeOnClick: true
        }, opt);
        oOptions.title = oOptions.title || null;
        /*
            docs: github.com/alexcrack/angular-ui-notification/blob/master/src/angular-ui-notification.js
            template-default: <div class="ui-notification"><h3 ng-if="title" ng-bind-html="title"></h3><div class="message" ng-bind-html="message"></div></div>
        */
        var htmlStr = '<div class="ui-notification notification-extend-layout1" >'
            + '<div class="myaccount-popup-content">'
                    + '<h3 ng-if="title" ng-bind-html="title"></h3>'
                    + '<p ng-bind-html="message"></p>'
                + '</div>'
            + '</div>';

        var noti_layout1_cache = 'angular-ui-notification-layout1.html';
        if ($templateCache.get(noti_layout1_cache)) {

        } else {
            $templateCache.put(noti_layout1_cache, htmlStr);
        }
        
        Notification({
            templateUrl: noti_layout1_cache,
            title: oOptions.title,
            message: oOptions.message,
            type: oOptions.type,
            closeOnClick: oOptions.closeOnClick,
            delay: oOptions.delay, //*** defined null value to reset default notification in main
            positionX: null, //*** defined null value to reset default notification in main
            classNoti: 'color-' + oOptions.type
        });
    }

    Notification.basketNoti = function (item, opts)
    {
        //opts = {
        //    action: 'A', // add(A) | remove(R)
        //    isWishlist: false,
        //    isEnquiryCart: false
        //}

        var bBindFlowbiteToBasketNotification = false;
        if ($rootScope.webApp.ssConfig) {
            if (angular.isDefined($rootScope.webApp.ssConfig.bindFlowbiteToBasketNoti))
            {
                bBindFlowbiteToBasketNotification = $rootScope.webApp.ssConfig.bindFlowbiteToBasketNoti;
            }
        }


        if (bBindFlowbiteToBasketNotification == true) {
            
            var sFlowb_dropdown_targetEL = '';
            var sFlowb_dropdown_triggerEL = '';
            if (opts.isEnquiryCart == true) {
                if (angular.isDefined($rootScope.webApp.ssConfig.flowb_dropdown_targetEL_enquire)) {
                    sFlowb_dropdown_targetEL = $rootScope.webApp.ssConfig.flowb_dropdown_targetEL_enquire;
                    sFlowb_dropdown_triggerEL = $rootScope.webApp.ssConfig.flowb_dropdown_triggerEL_enquire;
                } else {
                    sFlowb_dropdown_targetEL = $rootScope.webApp.ssConfig.flowb_dropdown_targetEL;
                    sFlowb_dropdown_triggerEL = $rootScope.webApp.ssConfig.flowb_dropdown_triggerEL;
                }
            } else {
                sFlowb_dropdown_targetEL = $rootScope.webApp.ssConfig.flowb_dropdown_targetEL;
                sFlowb_dropdown_triggerEL = $rootScope.webApp.ssConfig.flowb_dropdown_triggerEL;
            }
            // set the dropdown menu element
            const $targetEl = document.getElementById(sFlowb_dropdown_targetEL);
            //$targetEl = document.querySelector('.' + $rootScope.webApp.ssConfig.flowb_dropdown_targetEL);

            // set the element that trigger the dropdown menu on click
            const $triggerEl = document.getElementById(sFlowb_dropdown_triggerEL);

            //// options with default values
            //const options = {
            //    placement: 'bottom',
            //    triggerType: 'click',
            //    //offsetSkidding: 0,
            //    //offsetDistance: 10,
            //    //delay: 300,
            //    ignoreClickOutsideClass: false,
            //    onHide: () => {
            //        console.log('dropdown has been hidden');
            //    },
            //    onShow: () => {
            //        console.log('dropdown has been shown');
            //    },
            //    onToggle: () => {
            //        console.log('dropdown has been toggled');
            //    },
            //};

            //// instance options object
            //const instanceOptions = {
            //    id: $rootScope.webApp.ssConfig.flowb_dropdown_targetEL,//'dropdownMenu',
            //    override: false
            //};


            /*
             * $targetEl: required
             * $triggerEl: required
             * options: optional
             * instanceOptions: optional
             */
            //const dropdown = new Dropdown($targetEl, $triggerEl, options, instanceOptions);
            //const dropdown = new Dropdown($targetEl, $triggerEl);

            const dropdown = FlowbiteInstances.getInstance('Dropdown', sFlowb_dropdown_targetEL);

            dropdown.show();

            $timeout(function () {
                dropdown.hide();
            }, $rootScope.webApp.ssConfig.flowb_dropdown_delay);

        } else {
            var sMsgNotification = _getBasketNotificationTemplate(item, opts);
            $timeout(function () {
                Notification.primary(sMsgNotification);//*** add to cart ***
            }, 1);
        }
    }

    return Notification;
}]);;
ngAWDSApp.factory("SCReviewFactory", ['HttpFactory', '$window', function (HttpFactory, $window) {

    var getUriSCReview = function (sAction) {
        return "Stock/ShoppingReview/" + sAction;
    }

    //#region get
    var getDefaultData = function (oParams) {
        return HttpFactory.post(oParams, getUriSCReview("GetDefaultSCRData"));
    }

    //#endregion

    //#region post

    var getShoppingReviews = function (oParams) {
        return HttpFactory.post(oParams, getUriSCReview("GetShoppingReviews"));
    }

    
    //#endregion

    //#region submit
    var saveReview = function (oData) {
        return HttpFactory.post(oData, getUriSCReview("SaveWriteAReview"));
    }
    //#endregion

    return {
        getDefaultData: getDefaultData,
        getShoppingReviews: getShoppingReviews,
        saveReview: saveReview
    };
}]);;
ngAWDSApp.factory("WSLUserFactory", ['HttpFactory', '$window', function (HttpFactory, $window) {

    var getUriCtrl = function (sAction) {
        return "trade/account-detail/" + sAction;
    }
    //#region get
    var getDefaultDataList = function (oParams) {
        return HttpFactory.get(oParams, getUriCtrl("GetDefaultDataList"));
    }
    var getDefaultData = function (oParams) {
        return HttpFactory.get(oParams, getUriCtrl("GetDefaultData"));
    }
    //#endregion

    //#region post
    var getRecord = function (oParams) {
        return HttpFactory.post(oParams, getUriCtrl("GetWSLCompany"));
    }
    var getFilterData = function (sAction, oParams) {
        return HttpFactory.post(oParams, getUriCtrl(sAction));
    }
    //#endregion

    //#region submit

    var saveCompany = function (oParams) {
        return HttpFactory.post(oParams, getUriCtrl("SaveWSLCompany"));
    }
    var saveUser = function (oParams) {
        return HttpFactory.post(oParams, getUriCtrl("SaveWSLClient"));
    }
    var deleteUser = function (oParams) {
        return HttpFactory.post(oParams, getUriCtrl("DeleteWSLClient"));
    }
    var reinviteUser = function (oParams) {
        return HttpFactory.post(oParams, getUriCtrl("ReInviteWSLClient"));
    }

    //#endregion

    var logout = function () {
        return HttpFactory.get({}, "Stock/ShoppingCart/Logout");
    }

    return {
        getDefaultData: getDefaultData,
        getDefaultDataList: getDefaultDataList,
        getRecord: getRecord,
        //getRecords: getRecords,
        getFilterData: getFilterData,
        saveUser: saveUser,
        deleteUser: deleteUser,
        reinviteUser: reinviteUser,
        saveCompany: saveCompany,
        logout: logout
    };
}]);;
ngAWDSApp.factory("WSPartFactory", ['HttpFactory', '$window', '$q', function (HttpFactory, $window, $q) {

    var getUriWSPart = function (sAction) {
        return "Stock/WSPart/" + sAction;
    }
    var getUriWSPartAngular = function (sAction) {
        return "Stock/WSPartAngular/" + sAction;
    }
    var getFilterData = function (sAction, oParams) {
        //return HttpFactory.post(oParams, getUriWSPartAngular(sAction));
        return HttpFactory.postWithSession(oParams, getUriWSPartAngular(sAction), 3600);//***cache to session - duration: 1 hrs
    }

    var getFilterDataWithSession = function (sAction, oParams) {
        return HttpFactory.postWithSession(oParams, getUriWSPartAngular(sAction), 3600);//***cache to session - duration: 1 hrs
    }

    //#region get
    var getDefaultData = function (oParams) {
        return HttpFactory.get(oParams, getUriWSPartAngular("GetDefaultDataV2"));
    }
    var getDefaultDataByOpts = function (oParams) {
        return HttpFactory.post(oParams, getUriWSPartAngular("GetDefaultDataByOpts"));
    }
    //#endregion

    //#region post
    
    var getPartsList = function (oParams) {
        return HttpFactory.post(oParams, getUriWSPartAngular("GetParts"));
        //return HttpFactory.postWithSession(oParams, getUriWSPartAngular("GetParts"), (15 * 60));//***cache to session - duration: 15 mins


        //var promises = [HttpFactory.post(oParams, getUriWSPartAngular("GetParts"))];
        //return $q.all(promises)
        //        .then(function (responses) {

        //            //var encodeResponse = $window.webApp.util.base64Extend.encode(angular.toJson(responses[0]));
        //            //sessionstorageFactory.set(sKeyBase64, encodeResponse);

        //            return angular.fromJson(responses[0]);
        //        },
        //            function (responsesError) {
        //                return responsesError[0];
        //            }
        //        );
    }
    var getPartFranchises = function (oParams) {
        return getFilterData("GetPartFranchises", oParams);
    }
    var getMaxPrice = function (oParams) {
        return getFilterData("GetMaxPrice", oParams);
    }
    var getPartGroups = function (oParams) {
        return getFilterData("GetPartGroups", oParams);
    }
    var getPartGroupsStartsWith = function (oParams) {
        return getFilterData("GetPartGroupsStartsWith", oParams);
    }
    var getPartMainCategoriesWithPrefix = function (oParams) {
        return getFilterData("GetMainCategoriesWithPrefix", oParams);
    }
    var getPartCategories = function (oParams) {
        return getFilterDataWithSession("GetPartCategoriesV2", oParams);
        //return getFilterData("GetPartCategoriesV2", oParams);

        ////'sessionstorageFactory', '$q', 
        //var sKey = angular.toJson({ action: 'GetPartCategoriesV2', param: oParams });
        //var sKeyBase64 = $window.webApp.util.base64Extend.encode(sKey);
        //if (sessionstorageFactory.get(sKeyBase64) != false)
        //{
        //    console.warn('Minh: ss-', angular.fromJson(sessionstorageFactory.get(sKeyBase64)));
        //    return HttpFactory.fnPromise(function () {
        //        return angular.fromJson(sessionstorageFactory.get(sKeyBase64)).data;
        //    }, {});
        //}
        //else {
        //    return $q.all([getFilterData("GetPartCategoriesV2", oParams)])
        //        .then(function (responses) {
        //                sessionstorageFactory.set(sKeyBase64, angular.toJson(responses[0]));
        //                return responses[0];
        //            },
        //            function (responsesError) {
        //                return responsesError[0];
        //            }
        //        );
        //}
    }
    var getPartCategoriesNotExtra = function (oParams)
    {
        return getFilterData("GetPartCategoriesNotExtra", oParams);
    }
    var getPartCategoriesExtra = function (oParams) {
        return getFilterData("GetPartCategoriesExtra", oParams);
    }
    var getPartCategoriesDDL = function (oParams) {
        return getFilterData("GetPartCategoriesDDL", oParams);
    }
    var getVariants = function (oParams) {
        return getFilterData("GetVariants", oParams);
    }

    var getClientDeal = function (oParams) {
        return getFilterData("GetClientDeal", oParams);
        
        //*** HTTPget has error: A potentially dangerous Request.QueryString value was detected from the client (PartNumber="...AIDO-212 &#8713;").
        //return HttpFactory.get(oParams, getUriWSPartAngular('GetClientDeal'));
    }
    //#endregion

    //#region submit
    var submitFormSearch = function (oData) {
        return HttpFactory.post(oData, getUriWSPart("FormSearch"));
    }
    var submitFormSearchByStockNumber = function (oData) {
        return HttpFactory.post(oData, getUriWSPart("FormSearchByStockNumber"));
    }
    var saveGlobalSearchOption = function (oData) {
        return HttpFactory.post(oData, getUriWSPartAngular("SaveGlobalSearchOption"));
        
    }
    //#endregion

    return {
        getDefaultData: getDefaultData,
        getDefaultDataByOpts: getDefaultDataByOpts,
        getPartsList: getPartsList,
        getPartFranchises: getPartFranchises,
        getMaxPrice: getMaxPrice,
        getPartGroups: getPartGroups,
        getFilterData: getFilterData,
        getFilterDataWithSession: getFilterDataWithSession,
        getPartGroupsStartsWith: getPartGroupsStartsWith,
        getPartCategories: getPartCategories,
        getPartMainCategoriesWithPrefix: getPartMainCategoriesWithPrefix,
        getPartCategoriesExtra: getPartCategoriesExtra,
        getPartCategoriesNotExtra: getPartCategoriesNotExtra,
        getPartCategoriesDDL: getPartCategoriesDDL,
        getClientDeal: getClientDeal,
        saveGlobalSearchOption: saveGlobalSearchOption
    };
}]);

ngAWDSApp.factory("WSPartService", ['$rootScope', '$window', 'WSPartFactory', function ($rootScope, $window, WSPartFactory) {

    var getQtyStickerValue = function (oOption)
    {
        var sVal = "";
        if (angular.isDefined(oOption.minQtyLSE) && $rootScope.webApp.util.hasVal(oOption.minQtyLSE))
        {
            //MinQtyLSE is MinQtyLowStockEnquiry
            if (oOption.qav < oOption.minQtyLSE) {
                if ((angular.isDefined(oOption.isLSEWithQAV) && oOption.isLSEWithQAV == true) && oOption.totalQty == 0) {
                    sVal = "check-availability";
                }
                else {
                    sVal = "low-stock";
                }
            } else {
                sVal = "in-stock";
            }
        }
        else
        {
            if ($rootScope.webApp.util.hasVal(oOption.totalQty) == false) return "";

            if (oOption.totalQty == 0) {
                sVal = "check-availability";
            } else if (oOption.totalQty > 0 && oOption.totalQty < 3) {
                sVal = "low-stock";
            } else if (oOption.totalQty > 2) {
                sVal = "in-stock";
            }
        }
        
        return sVal;
    }

    var getClientDeal = function (item)
    {
        return WSPartFactory.getClientDeal({ Id: item.Id, PartNumber: item.PartNumber, FranchiseCode: item.FranchiseCode }).then(function (response) {
            if (response.data != null)
            {
                var jsonData = angular.fromJson(response.data);
                //if (jsonData.HasClientDeal == true) {
                //    return jsonData;
                //}
                return jsonData;
            }            
            return {};
        }, function (responseError) {
            return responseError;
        });
    }

    return {
        getQtyStickerValue: getQtyStickerValue,
        getClientDeal: getClientDeal
    };
}]);;
ngAWDSApp.factory("WSStockFactory", ['HttpFactory', '$window', function (HttpFactory, $window) {
    
    var getUriWSStock = function (sAction) {
        return "Stock/WSStock/" + sAction;
    }
    var getUriWSStockAngular = function (sAction) {
        return "Stock/WSStockAngular/" + sAction;
    }
    //#region get
    var getDefaultDataCaravan = function (oParams) {
        return HttpFactory.get(oParams, getUriWSStockAngular("GetDefaultDataCaravan"));
    }
    var getDefaultDataCaravanByOpts = function (oParams) {
        return HttpFactory.post(oParams, getUriWSStockAngular("GetDefaultDataCaravanByOpts"));
    }
    var getDefaultDataVehicle = function (oParams) {
        return HttpFactory.get(oParams, getUriWSStockAngular("GetDefaultDataVehicle"));
    }
    var getDefaultDataMotor = function (oParams) {
        return HttpFactory.get(oParams, getUriWSStockAngular("GetDefaultDataMotor"));
    }

    var getDefaultDataCar = function (oParams) {
        return HttpFactory.get(oParams, getUriWSStockAngular("GetDefaultDataCar"));
    }
    var getDefaultDataCarByOpts = function (oParams) {
        //*** if use GET method, we need to setting the requestLimits's maxQueryString (FlyAutohaus site using this)
        return HttpFactory.post(oParams, getUriWSStockAngular("GetDefaultDataCarByOpts"));
    }
    var getDefaultDataAuctionCatalogue = function (oParams) {
        return HttpFactory.get(oParams, getUriWSStockAngular("GetDefaultDataAuctionCatalogue"));
    }
    
    var getDataFormSearch = function (oParams, FormSearchName) {
        return HttpFactory.get(oParams, getUriWSStock("GetDataFormSearch" + FormSearchName));
    }

    var getStockOptionsByFilterId = function (oParams) {
        return HttpFactory.get(oParams, getUriWSStock("GetStockOptionsByFilterId"));
    }

    var getWSStockDetail = function (VehicleId) {
        //return HttpFactory.get({ VehicleId: VehicleId }, getUriWSStockAngular("GetStockDetail"));
    }
    var getWSStockDetailV2 = function (oParams) {
        //return HttpFactory.get({ VehicleId: VehicleId, FilterId: FilterId }, getUriWSStockAngular("GetStockDetailV2"));
        return HttpFactory.get(oParams, getUriWSStockAngular("GetStockDetailV2"));
    }
    var getWSStockAndOptions = function (oParams, cbSuccess) {
        HttpFactory.get(oParams, getUriWSStockAngular("GetDefaultDataStockDetail")).then(function (response) {
            cbSuccess(response);
        }, function (responseError) {
        });
    }
    var getAuctionCatalogues = function (oParams)
    {
        return HttpFactory.get(oParams, getUriWSStockAngular("GetAuctionCatalogues"));
    }
    //#endregion

    //#region post
    var getStrattonFinance = function (oParam, cbSuccess) {
        HttpFactory.post(oParam, getUriWSStock("GetMarineAndLeisureQuoteFromStrattonFinance")).then(function (response) {
            cbSuccess(response);
        }, function (responseError) {
        });
    }
    var getStockList = function (oParams) {
        return HttpFactory.post(oParams, getUriWSStockAngular("GetStockList"));
    }
    var getStockListByAuctionId = function (oParams) {
        return HttpFactory.post(oParams, getUriWSStockAngular("GetStockListByAuctionId"));
    }
    
    var getFilterData = function (sAction, oParams) {
        //if (sAction == 'GetLengthMetricSlider' || sAction == 'GetSleepFilterSlider')
        //{
        //    return HttpFactory.post(oParams, 'current-stock/' + (sAction));// GippslandRVStock site using this, will remove this line when back ThaiLan trip
        //}
        //*** Minh::20240618::  (sAction == 'GetLengthMetricSlider' || sAction == 'GetSleepFilterSlider') moved to Areas
        return HttpFactory.post(oParams, getUriWSStockAngular(sAction));
    }
    var getMake = function (oParams) {
        return getFilterData("GetMakes", oParams);
    }
    var getModel = function (oParams) {
        return getFilterData("GetModels", oParams);
    }
    var getSeries = function (oParams) {
        return getFilterData("GetSeries", oParams);
    }
    var getVariants = function (oParams) {
        return getFilterData("GetVariants", oParams);
    }    
    //#endregion
    
    //#region submit
    var submitFormSearch = function (oData) {
        return HttpFactory.post(oData, getUriWSStock("FormSearch"));
    }
    var submitFormSearchByStockNumber = function (oData) {
        return HttpFactory.post(oData, getUriWSStock("FormSearchByStockNumber"));
    }
    //#endregion

    return {
        submitFormSearch: submitFormSearch,
        submitFormSearchByStockNumber: submitFormSearchByStockNumber,
        getDefaultDataCaravan: getDefaultDataCaravan,
        getDefaultDataCaravanByOpts: getDefaultDataCaravanByOpts,
        getDefaultDataCar: getDefaultDataCar,
        getDefaultDataCarByOpts: getDefaultDataCarByOpts,
        getDefaultDataVehicle: getDefaultDataVehicle,
        getDefaultDataMotor: getDefaultDataMotor,
        getDefaultDataAuctionCatalogue: getDefaultDataAuctionCatalogue,
        getDataFormSearch: getDataFormSearch,
        getStockOptionsByFilterId: getStockOptionsByFilterId,
        getWSStockDetail: getWSStockDetail,
        getWSStockDetailV2: getWSStockDetailV2,
        getWSStockAndOptions: getWSStockAndOptions,
        getStrattonFinance: getStrattonFinance,
        getAuctionCatalogues: getAuctionCatalogues,
        getStockList: getStockList,
        getStockListByAuctionId: getStockListByAuctionId,
        getFilterData: getFilterData,
        getMake: getMake,
        getModel: getModel,
        getSeries: getSeries,
        getVariants: getVariants
    };
}]);;
ngAWDSApp.factory("WSStockServices", ['$rootScope', 'WSStockFactory', function ($rootScope, WSStockFactory) {

    var loadCreditOneFinace = function (oStockDetail, cbSuccess) {
        var sAssertType = null;
        if (oStockDetail.Variant != null) {
            switch (oStockDetail.Variant) {
                case "caravan": case "pop top": case "poptop": case "campervan":
                    sAssertType = "caravan";
                    break;
                case "camper trailer":
                    sAssertType = "campertrailer";
                    break;
                default:
                    //sAssertType = oStockDetail.Variant;
                    sAssertType = oStockDetail.Class;
                    break;
            }
        }
        var oParam = {
            assetType: sAssertType,
            amountToFinance: oStockDetail.PriceForProcessing,
            isNew: oStockDetail.Type.toLowerCase() == "new",
            state: oStockDetail.Registration.State,
            year: oStockDetail.YearForProcessing,
            purchaseSource: "dealer"
        }
        WSStockFactory.getStrattonFinance(oParam, function (response) {
            cbSuccess(response);
        })
    }
    
    
    return {
        loadCreditOneFinace: loadCreditOneFinace
    };
}]);;
ngAWDSApp.filter('convertMeterToFeet', ['$filter', function ($filter) {
    return function (val) {
        return $filter('convertMeterToFeet2')(val, null, true, null);
    };
}]);

ngAWDSApp.filter('convertMeterToFeet2', ['$filter', function ($filter) {
    return function (val, feetUnit, hasInch, inchUnit) {
        //console.warn("Minh: convertMeterToFeet2", val, feetUnit, hasInch, inchUnit);

        if (AWDSApp.util.isNullOrEmpty(val)) return "";
        if (Number(val) < 1) return "";        
        if (AWDSApp.util.isNullOrEmpty(feetUnit)) feetUnit = '\'';//feat
        if (AWDSApp.util.isNullOrEmpty(inchUnit))
        {
            if (feetUnit == "'")
            {
                inchUnit = '"';//inch
            }            
        }

        hasInch = AWDSApp.util.toBool(hasInch);

        var lInches, sFeet, sInch;

        ////######################################### monday task 7167471900.

        //c#: lInches = (long)Math.Round((text * (double)100 / 2.54), 0);
        lInches = Math.round((val * 100 / 2.54));

        //c#: sFeet = Math.Round((double)(lInches / 12), 0) + feetUnit;
        sFeet = Math.floor((lInches / 12)) + feetUnit;
                        
        sInch = (lInches % 12) + inchUnit;
        return sFeet + " " + sInch;

        //######################################### monday task #7084066051
        ////https://stackoverflow.com/questions/33474726/how-to-convert-meters-into-feet-and-inches
        //var feet = (val / 0.3048);        
        //var tempInch = (feet - Math.trunc(feet)) / 0.08333;//**** 1(inch) / 12 = 0.08333(ft)
        //var feetInt = parseInt(feet);
        //var inchInt = Math.round(tempInch);// parseInt(temp.toFixed());
        //if (inchInt >= 12) {
        //    //*** 1 feet = 12 inch. so if inchInt > 12, feet = feet + 1
        //    //*** custom logic (monday task #7084066051):  When a length is 12” it should add 1 foot and go back to 0” Example 15’ 12” -> 16’ 0” 
        //    feetInt = feetInt + Math.round(inchInt / 12);
        //    inchInt = 0;
        //}
        //var feetStr = $filter('extNumber')(feetInt, feetUnit, 0);
        //var inchStr = "";
        //if (hasInch == true)
        //{
        //    if (inchInt == 0) inchStr = "0" + inchUnit;
        //    else inchStr = $filter('extNumber')(inchInt, inchUnit, 0);
        //}
        //var sResult = feetStr;
        //if (!AWDSApp.util.isNullOrEmpty(inchStr)) {
        //    sResult = feetStr + " " + inchStr;
        //}
        //return sResult;

        //######################################### old 
        //var inch = (feet - feetInt) * 12;
        //var sResult = $filter('extNumber')(feet, feetUnit, 0);
        //var sInch = hasInch ? $filter('extNumber')(inch, inchUnit, 0) : "";
        //if (!AWDSApp.util.isNullOrEmpty(sInch)) {
        //    sResult = sResult  + " " + sInch;
        //}
        //return sResult;
    };
}]);


ngAWDSApp.filter('convertMillimeterToFeetInch', ['$filter', function ($filter) {
    return function (val, feetUnit, hasInch, inchUnit) {
        //console.warn("Minh: convertMeterToFeet2", val, feetUnit, hasInch, inchUnit);



        if (AWDSApp.util.isNullOrEmpty(val)) return "";
        if (Number(val) < 1) return "";

        if (AWDSApp.util.isNullOrEmpty(feetUnit)) feetUnit = '\'';//feat
        if (AWDSApp.util.isNullOrEmpty(inchUnit)) inchUnit = '"';//inch
        if (AWDSApp.util.isNullOrEmpty(hasInch)) hasInch = true;//default true, show inch


        //var metter = val / 1000; //to metter
        //return $filter('convertMeterToFeet2')(metter, "'", true, '"');

        //*** www.rapidtables.com/convert/length/mm-to-feet-inch.html?x=6230

        var metre = val * 0.001;
        return $filter('convertMeterToFeet2')(metre, feetUnit, hasInch, inchUnit);

        //var length = val / 25.4;
        //var feet = parseFloat(length / 12);
        //var feetInt = parseInt(feet);
        //var inch = length - (12 * feetInt);
        ////var inchInt = parseInt(inch);
        //return $filter('extNumber')(feetInt, feetUnit, 0) + " " + $filter('extNumber')(inch, inchUnit, 0);
    };
}]);;
ngAWDSApp.filter('extCurrency', ['$filter', function ($filter) {
    return function (val, symbol, fractionSize) {
        if (AWDSApp.util.isNullOrEmpty(val)) return "";
        if (Number(val) < 1) return "";
        return $filter('currency')(val, symbol, fractionSize);
    };
}]);

ngAWDSApp.filter('extCurrencyOriginal', ['$filter', function ($filter) {
    return function (val, symbol, fractionSize) {
        if (AWDSApp.util.isNullOrEmpty(val)) val = "";
        if (AWDSApp.util.isNullOrEmpty(symbol)) symbol = "$";
        if (AWDSApp.util.isNullOrEmpty(fractionSize)) fractionSize = 2;
        
        return $filter('currency')(val, symbol, fractionSize);
    };
}]);

ngAWDSApp.filter('extCurrencyZero', ['$filter', function ($filter) {
    return function (val, symbol, fractionSize) {
        var sVal = $filter('extCurrency')(val, symbol, fractionSize);
        if (sVal == "") {
            return symbol + "0";
        }
        else {
            return sVal;
        }
    };
}]);

ngAWDSApp.directive('compile5CentRounding', ['$compile', '$rootScope', '$window', '$filter', function ($compile, $rootScope, $window, $filter) {
    return {
        restrict: 'A',
        replace: true,
        scope: {
            compile5CentRounding: '=',
            isZero: '=?' // if true, will show zero
        },
        link: function (scope, element, attrs) {
            function formatPrice(val) {
                var sResult = $rootScope.webApp.util.to5CentRounding(val);
                if (angular.isDefined($rootScope.webApp.isUnuse5CentRoundingFormat) && $rootScope.webApp.util.toBool($window.webApp.isUnuse5CentRoundingFormat) == true)
                {
                    sResult = $filter('extCurrencyOriginal')(val, null, null);
                }
                
                if ($rootScope.webApp.util.toBool(scope.isZero)) {
                    if ($rootScope.webApp.util.hasVal(sResult) == false)
                    {
                        sResult = "$0.00";
                    }
                }
                if ($window.webApp && $rootScope.webApp.util.toBool($window.webApp.isPriceSpanFormat) == true) {
                    //sResult = sResult.replace(/(\D*)(\d*\.)(\d*)/, '<span style="font-size:16px;">$1</span><span style="font-size:22px;">$2</span><span style="font-size:14px;">$3</span>');
                    var splitPrice = sResult.split('.');
                    if (splitPrice.length > 1) {
                        sResult = '<span class="sPrice-1">' + splitPrice[0] + '</span><span class="sPrice-2">.' + splitPrice[1] + '</span>';
                    } else {
                        
                    }
                    
                }
                return sResult;
            }
            scope.$watch('compile5CentRounding', function (newVal, oldVal) {

                if (angular.isDefined(newVal)) {
                    element.html(formatPrice(newVal));
                    $compile(element.contents())(scope);
                }
               
            })
        }
    }
}]);
ngAWDSApp.filter('extDate', ['$rootScope', '$filter', function ($rootScope, $filter) {
    return function (val, format, timezone) {
        //date, format, timezone
        if (AWDSApp.util.isNullOrEmpty(val)) return "";
        
        if (AWDSApp.util.isNullOrEmpty(format)) format = "dd/MM/yyyy";

        return $filter('date')(val, format, timezone);
    };
}]);
ngAWDSApp.filter('toDateStrShort', ['$rootScope', '$filter', function ($rootScope, $filter) {
    return function (sVal) {
        //date, format, timezone
        if ($rootScope.webApp.util.isNullOrEmpty(sVal)) return "";

        format = "dd/MM/yyyy";
        sVal = $rootScope.webApp.util.toDateTime(sVal);

        return $filter('date')(sVal, format, null);
    };
}]);
ngAWDSApp.filter('toDateStrLong', ['$rootScope', '$filter', function ($rootScope, $filter) {
    return function (sVal) {
        //date, format, timezone
        if ($rootScope.webApp.util.isNullOrEmpty(sVal)) return "";

        format = "dd/MM/yyyy HH:mm:ss";
        sVal = $rootScope.webApp.util.toDateTime(sVal);

        return $filter('date')(sVal, format, null);
    };
}]);

ngAWDSApp.filter('extDateNum', ['$rootScope', '$filter', function ($rootScope, $filter) {
    return function (val, format, timezone) {
        //date-number, format, timezone
        
        if ($rootScope.webApp.util.isNullOrEmpty(val)) return "";

        if ($rootScope.webApp.util.isNullOrEmpty(format)) format = "dd/MM/yyyy";

        return $filter('date')($rootScope.webApp.util.formatDateNumberToDate(val), format, timezone);
    };
}]);

ngAWDSApp.filter('extDateNumLong', ['$rootScope', '$filter', function ($rootScope, $filter) {
    return function (val, format, timezone) {
        //date-number, format, timezone
        var format = "dd/MM/yyyy HH:mm:ss";

        return $filter('extDateNum')(val, format, null);
    };
}]);

;
ngAWDSApp.filter('extNumber', ['$filter', '$rootScope', function ($filter, $rootScope) {
    return function (val, symbol, fractionSize) {
        if ($rootScope.webApp.util.isNullOrEmpty(val)) return "";
        if (Number(val) < 1) return "";
        return $filter('number')(val, fractionSize) +((symbol) ? symbol : "");
    };
}]);
ngAWDSApp.filter('extNumberZero', ['$filter', '$rootScope', function ($filter, $rootScope) {
    return function (val, symbol, fractionSize) {
        var sVal = $filter('extNumber')(val, symbol, fractionSize);
        if (sVal == "") {
            return "0" + ((symbol) ? symbol : "");
        }
        else {
            return sVal;
        }
    };
}]);

ngAWDSApp.filter('extNumberZeroWithoutComma', ['$filter', function ($filter) {
    return function (val, symbol, fractionSize) {
        var sVal = $filter('extNumberZero')(val, symbol, fractionSize);        
        return sVal.replace(/,/g, "");
    };
}]);

ngAWDSApp.filter('extNumberOrdinal', ['$filter', '$rootScope', function ($filter, $rootScope) {
    return function (val, symbol, fractionSize) {
        if ($rootScope.webApp.util.isNullOrEmpty(val)) return "";
        if (Number(val) < 1) return "";

        switch (Number(val)) {
            case 1:
            case 21:
            case 31:
                return val + "st";
            case 2:
            case 22:
                return val + "nd";
            case 3:
            case 23:
                return val + "rd";
            default:
                return val + "th";
        }
        return "";
    };
}]);

ngAWDSApp.filter('toPerson', ['$filter', '$rootScope', function ($filter, $rootScope) {
    return function (val) {
        if ($rootScope.webApp.util.isNullOrEmpty(val)) return "";
        if (Number(val) < 1) return "";
        return $filter('extNumber')(val, (Number(val) > 1 ? ' Persons' : ' Person'));
    };
}]);

ngAWDSApp.filter('toPreOwnedForVehType', ['$filter', '$rootScope', function ($filter, $rootScope) {
    return function (val) {
        if ($rootScope.webApp.util.isNullOrEmpty(val)) return "";
        if ($rootScope.webApp.util.equalsLowerCase(val, 'used')) return "Pre-Owned";        
        return val;
    };
}]);
;
ngAWDSApp.filter('sumOfVal', ['$rootScope', function ($rootScope) {
    return function (data, key1, key2) {
        return $rootScope.webApp.util.sumOfVal(data, key1, key2);
    };
}]);;
ngAWDSApp.filter('toCylinder', ['$filter', function ($filter) {
    return function (val) {
        return $filter('extNumberZeroWithoutComma')(val, ' Cyl', 0);
    };
}]);
ngAWDSApp.filter('toLongCylinder', ['$filter', function ($filter) {
    return function (val) {
        return $filter('extNumberZeroWithoutComma')(val, ' Cylinder', 0);
    };
}]);


;
ngAWDSApp.filter('toEngineSize', ['$filter', function ($filter) {
    return function (val) {
        return $filter('extNumberZeroWithoutComma')(val, 'cc', 0);
    };
}]);
ngAWDSApp.filter('toEngineSizeZero', ['$filter', function ($filter) {
    return function (val) {
        var sVal = $filter('toEngineSize')(val);

        if (sVal == "") {
            return "0cc";
        }
        else {
            return sVal;
        }
    };
}]);
;
ngAWDSApp.filter('toEngineSizeLiter', ['$filter', '$rootScope', function ($filter, $rootScope) {
    return function (val) {
        if ($rootScope.webApp.util.isNullOrEmpty(val)) return "";

        //var ltr = val / 1000;
        return $filter('extNumber')(val, ' l', 1);
    };
}]);;
ngAWDSApp.filter('toFuelTypeDescVehicle', ['$filter', '$rootScope', function ($filter, $rootScope) {
    return function (val) {

        if ($rootScope.webApp.util.isNullOrEmpty(val)) return "";
        else
        {
            var sDesc = "";
            switch (val)
            {
                case "P":
                    sDesc = "Petrol";
                    break;
                case "D":
                    sDesc = "Diesel";
                    break;
                case "U":
                    sDesc = "Unleaded";
                    break;
                case "E":
                    sDesc = "Electric";
                    break;
                case "H":
                    sDesc = "Hybrid";
                    break;
                case "G":
                    sDesc = "LPG";
                    break;
                default:
                    sDesc = val;
                    break;
            }
            return sDesc;
        }
    };
}]);;
ngAWDSApp.filter('toHorsePower', ['$filter', function ($filter) {
    return function (val) {
        var sVal = $filter('extNumberZeroWithoutComma')(val, ' hp', 0);
        if (sVal == '0 hp') return null;
        else return sVal;
    };
}]);
ngAWDSApp.filter('toHorsePowerZero', ['$filter', function ($filter) {
    return function (val) {
        var sVal = $filter('toHorsePower')(val);

        if (sVal == "") {
            return "0 hp";
        }
        else {
            return sVal;
        }
    };
}]);
;
ngAWDSApp.filter('toKilogram', ['$filter', function ($filter) {
    return function (val) {
        return $filter('extNumber')(val, ' kg', 0);
    };
}]);
ngAWDSApp.filter('toKilogramZero', ['$filter', function ($filter) {
    return function (val) {
        var sVal = $filter('toKilogram')(val);
        if (sVal == "") {
            return "0 kg";
        } else {
            return sVal;
        }
    };
}]);;
ngAWDSApp.filter('toKilometer', ['$filter', function ($filter) {
    return function (val) {
        return $filter('extNumber')(val, ' km', 0);
    };
}]);
ngAWDSApp.filter('toKilometerZero', ['$filter', function ($filter) {
    return function (val) {
        var sVal = $filter('toKilometer')(val);
        if (sVal == "") {
            return "0 km";
        }
        else {
            return sVal;
        }
    };
}]);

ngAWDSApp.filter('toHoursOdo', ['$filter', function ($filter) {
    return function (val) {
        return $filter('extNumber')(val, ' hrs', 0);
    };
}]);
ngAWDSApp.filter('toHoursOdoZero', ['$filter', function ($filter) {
    return function (val) {
        var sVal = $filter('toHoursOdo')(val);
        if (sVal == "") {
            return "0 hrs";
        }
        else {
            return sVal;
        }
    };
}]);;
ngAWDSApp.filter('toLowerCaseExt', ['$filter', '$rootScope', function ($filter, $rootScope) {
    return function (val) {
        return $rootScope.webApp.util.toLowerCaseExt(val);
    };
}]);;
ngAWDSApp.filter('toMeter', ['$filter', function ($filter) {
    return function (val) {
        return $filter('extNumber')(val, ' m', 2);
    };
}]);

ngAWDSApp.filter('toMeter2', ['$filter', function ($filter) {
    return function (val, meterUnit) {
        meterUnit = AWDSApp.util.isNullOrEmpty(meterUnit) ? "m" : meterUnit;
        return $filter('extNumber')(val, meterUnit, 2);
    };
}]);

ngAWDSApp.filter('toMeterZero', ['$filter', function ($filter) {
    return function (val, meterUnit) {
        meterUnit = AWDSApp.util.isNullOrEmpty(meterUnit) ? "m" : meterUnit;

        var sVal = $filter('toMeter2')(val, meterUnit);
        if (sVal == "")
        {
            sVal = "0" + meterUnit;
        }
        return sVal;
    };
}]);

ngAWDSApp.filter('toMeterZeroN0', ['$filter', function ($filter) {
    return function (val, meterUnit) {
        meterUnit = AWDSApp.util.isNullOrEmpty(meterUnit) ? "m" : meterUnit;

        var sVal = $filter('extNumber')(val, meterUnit, 0);
        if (sVal == "") {
            sVal = "0" + meterUnit;
        }
        return sVal;
    };
}]);;
ngAWDSApp.filter('toPrice', ['$filter', function ($filter) {
    return function (val) {
        return $filter('extCurrency')(val, '$', 0);
    };
}]);;
ngAWDSApp.filter('toPrice2', ['$filter', function ($filter) {
    return function (val) {
        return $filter('extCurrency')(val, '$', 2);
    };
}]);;
ngAWDSApp.filter('toTransmissionDescVehicle', ['$filter', '$rootScope', function ($filter, $rootScope) {
    return function (val) {

        if ($rootScope.webApp.util.isNullOrEmpty(val)) return "";
        else {
            var sDesc = "";            
            var valSplit = val.split(' ');
            var code = valSplit[valSplit.length - 1].toLocaleLowerCase();
            switch (code)
            {
                case 'man':
                    code = 'Manual';
                    break;
                case 'c':
                case 'cvt':
                    //code = "CVT";
                    code = "Auto";
                    break;
                //case 's':
                //case 'sport':
                //    code = "Semi-Auto";
                    //    break;
                case 's':
                case 'sport':
                case 'automatic':
                    code = 'Auto';
                    break;
            }
            for (var i = 0; i < valSplit.length - 1; i++) {
                sDesc += valSplit[i] + ' ';
            }
            sDesc = sDesc + code;

            //if (!val.indexOf("Manual") >= 0)
            //{
            //    if (val.indexOf("Man") >= 0) {
            //        sDesc = sDesc.replace("Man", "Manual");
            //    } else if (val.indexOf("SPEED C") >= 0) {                    
            //        sDesc = sDesc.replace("SPEED C", "SPEED AUTO");//sDesc = sDesc.replace("C", "CVT");
            //    }
            //    else if (val.indexOf("SPORT") >= 0){
            //        sDesc = sDesc.replace("SPORT", "AUTO");
            //    }
            //    else if (val.indexOf("AUTOMATIC") >= 0) {
            //        sDesc = sDesc.replace("AUTOMATIC", "AUTO");
            //    }
            //}

            
            return sDesc;
        }
    };
}]);;
ngAWDSApp.filter('toUpperFirstChar', ['$filter', '$rootScope', function ($filter, $rootScope) {
    return function (val) {
        return $rootScope.webApp.util.toUpperFirstChar(val);
    };
}]);

ngAWDSApp.filter('toDashLower', ['$filter', '$rootScope', function ($filter, $rootScope) {
    return function (val) {
        return $rootScope.webApp.util.replaceAllSpecialCharsToDashLower(val);
    };
}]);
;
ngAWDSApp.filter('trustAsResourceUrl', ['$sce', function ($sce) {
    return function (val) {
        return $sce.trustAsResourceUrl(val);
    };
}])

ngAWDSApp.filter('trustAsHtml', ['$sce', function ($sce) {
    return function (val) {
        var sDecoded = "";
        var eleDiv = angular.element('<div />');
        eleDiv.html(val);
        if (eleDiv.children().length > 0) {
            sDecoded = val;
        } else {
            sDecoded = eleDiv.text();
        }
        //var sDecoded = angular.element('<div />').html(val).text();
        return $sce.trustAsHtml(sDecoded);
    };
}])

ngAWDSApp.directive('compileDirect', ['$compile', function ($compile) {
    return {
        //restrict: 'E',
        replace: true,
        link: function (scope, element, attrs) {
            scope.$watch(
                function (scope) {
                    // watch the 'compile' expression for changes
                    return scope.$eval(attrs.compileDirect);
                },
                function (value) {
                    // when the 'compile' expression changes
                    // assign it into the current DOM
                    element.html(value);

                    // compile the new DOM and link it to the current
                    // scope.
                    // NOTE: we only compile .childNodes so that
                    // we don't get into infinite loop compiling ourselves
                    $compile(element.contents())(scope);
                }
            );
        }
    }
}]);
