/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}k.fn=k.prototype={jquery:f,constructor:k,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=k.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return k.each(this,e)},map:function(n){return this.pushStack(k.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},k.extend=k.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(k.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||k.isPlainObject(n)?n:{},i=!1,a[t]=k.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},k.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t){b(e,{nonce:t&&t.nonce})},each:function(e,t){var n,r=0;if(d(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(p,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(d(Object(e))?k.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(d(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g.apply([],a)},guid:1,support:y}),"function"==typeof Symbol&&(k.fn[Symbol.iterator]=t[Symbol.iterator]),k.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var h=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,k="sizzle"+1*new Date,m=n.document,S=0,r=0,p=ue(),x=ue(),N=ue(),A=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",$=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",F=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="<a id='"+k+"'></a><select id='"+k+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!==C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!==C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(F," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,v){var y="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[S,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[S,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[k]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace(B,"$1"));return s[k]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[S,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[k]||(e[k]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===S&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[k]&&(v=Ce(v)),y&&!y[k]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[k]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(B,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(B," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=N[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[k]?i.push(a):o.push(a);(a=N(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=S+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t===C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument===C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(S=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(S=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=k.split("").sort(D).join("")===k,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);k.find=h,k.expr=h.selectors,k.expr[":"]=k.expr.pseudos,k.uniqueSort=k.unique=h.uniqueSort,k.text=h.getText,k.isXMLDoc=h.isXML,k.contains=h.contains,k.escapeSelector=h.escape;var T=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&k(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},N=k.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var D=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1<i.call(n,e)!==r}):k.filter(n,e,r)}k.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?k.find.matchesSelector(r,e)?[r]:[]:k.find.matches(e,k.grep(t,function(e){return 1===e.nodeType}))},k.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(k(e).filter(function(){for(t=0;t<r;t++)if(k.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)k.find(e,i[t],n);return 1<r?k.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&N.test(e)?k(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(k.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&k(e);if(!N.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&k.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?k.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(k(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(k.uniqueSort(k.merge(this.get(),k(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),k.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return T(e,"parentNode")},parentsUntil:function(e,t,n){return T(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return T(e,"nextSibling")},prevAll:function(e){return T(e,"previousSibling")},nextUntil:function(e,t,n){return T(e,"nextSibling",n)},prevUntil:function(e,t,n){return T(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return"undefined"!=typeof e.contentDocument?e.contentDocument:(A(e,"template")&&(e=e.content||e),k.merge([],e.childNodes))}},function(r,i){k.fn[r]=function(e,t){var n=k.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=k.filter(t,n)),1<this.length&&(O[r]||k.uniqueSort(n),H.test(r)&&n.reverse()),this.pushStack(n)}});var R=/[^\x20\t\r\n\f]+/g;function M(e){return e}function I(e){throw e}function W(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}k.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},k.each(e.match(R)||[],function(e,t){n[t]=!0}),n):k.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){k.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return k.each(arguments,function(e,t){var n;while(-1<(n=k.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<k.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},k.extend({Deferred:function(e){var o=[["notify","progress",k.Callbacks("memory"),k.Callbacks("memory"),2],["resolve","done",k.Callbacks("once memory"),k.Callbacks("once memory"),0,"resolved"],["reject","fail",k.Callbacks("once memory"),k.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return k.Deferred(function(r){k.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,M,s),l(u,o,I,s)):(u++,t.call(e,l(u,o,M,s),l(u,o,I,s),l(u,o,M,o.notifyWith))):(a!==M&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){k.Deferred.exceptionHook&&k.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==I&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(k.Deferred.getStackHook&&(t.stackTrace=k.Deferred.getStackHook()),C.setTimeout(t))}}return k.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:M,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:M)),o[2][3].add(l(0,e,m(n)?n:I))}).promise()},promise:function(e){return null!=e?k.extend(e,a):a}},s={};return k.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=k.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(W(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)W(i[t],a(t),o.reject);return o.promise()}});var $=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;k.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&$.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},k.readyException=function(e){C.setTimeout(function(){throw e})};var F=k.Deferred();function B(){E.removeEventListener("DOMContentLoaded",B),C.removeEventListener("load",B),k.ready()}k.fn.ready=function(e){return F.then(e)["catch"](function(e){k.readyException(e)}),this},k.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--k.readyWait:k.isReady)||(k.isReady=!0)!==e&&0<--k.readyWait||F.resolveWith(E,[k])}}),k.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(k.ready):(E.addEventListener("DOMContentLoaded",B),C.addEventListener("load",B));var _=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)_(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(k(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},z=/^-ms-/,U=/-([a-z])/g;function X(e,t){return t.toUpperCase()}function V(e){return e.replace(z,"ms-").replace(U,X)}var G=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Y(){this.expando=k.expando+Y.uid++}Y.uid=1,Y.prototype={cache:function(e){var t=e[this.expando];return t||(t={},G(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[V(t)]=n;else for(r in t)i[V(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][V(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(V):(t=V(t))in r?[t]:t.match(R)||[]).length;while(n--)delete r[t[n]]}(void 0===t||k.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!k.isEmptyObject(t)}};var Q=new Y,J=new Y,K=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function ee(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Z,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:K.test(i)?JSON.parse(i):i)}catch(e){}J.set(e,t,n)}else n=void 0;return n}k.extend({hasData:function(e){return J.hasData(e)||Q.hasData(e)},data:function(e,t,n){return J.access(e,t,n)},removeData:function(e,t){J.remove(e,t)},_data:function(e,t,n){return Q.access(e,t,n)},_removeData:function(e,t){Q.remove(e,t)}}),k.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=J.get(o),1===o.nodeType&&!Q.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=V(r.slice(5)),ee(o,r,i[r]));Q.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){J.set(this,n)}):_(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=J.get(o,n))?t:void 0!==(t=ee(o,n))?t:void 0;this.each(function(){J.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){J.remove(this,e)})}}),k.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Q.get(e,t),n&&(!r||Array.isArray(n)?r=Q.access(e,t,k.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=k.queue(e,t),r=n.length,i=n.shift(),o=k._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){k.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Q.get(e,n)||Q.access(e,n,{empty:k.Callbacks("once memory").add(function(){Q.remove(e,[t+"queue",n])})})}}),k.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?k.queue(this[0],t):void 0===n?this:this.each(function(){var e=k.queue(this,t,n);k._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&k.dequeue(this,t)})},dequeue:function(e){return this.each(function(){k.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=k.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Q.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var te=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ne=new RegExp("^(?:([+-])=|)("+te+")([a-z%]*)$","i"),re=["Top","Right","Bottom","Left"],ie=E.documentElement,oe=function(e){return k.contains(e.ownerDocument,e)},ae={composed:!0};ie.getRootNode&&(oe=function(e){return k.contains(e.ownerDocument,e)||e.getRootNode(ae)===e.ownerDocument});var se=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&oe(e)&&"none"===k.css(e,"display")},ue=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];for(o in i=n.apply(e,r||[]),t)e.style[o]=a[o];return i};function le(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return k.css(e,t,"")},u=s(),l=n&&n[3]||(k.cssNumber[t]?"":"px"),c=e.nodeType&&(k.cssNumber[t]||"px"!==l&&+u)&&ne.exec(k.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)k.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,k.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ce={};function fe(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Q.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&se(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ce[s])||(o=a.body.appendChild(a.createElement(s)),u=k.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ce[s]=u)))):"none"!==n&&(l[c]="none",Q.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}k.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){se(this)?k(this).show():k(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={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,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Q.set(e[n],"globalEval",!t||Q.get(t[n],"globalEval"))}ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;var me,xe,be=/<|&#?\w+;/;function we(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))k.merge(p,o.nodeType?[o]:o);else if(be.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+k.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;k.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<k.inArray(o,r))i&&i.push(o);else if(l=oe(o),a=ve(f.appendChild(o),"script"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}me=E.createDocumentFragment().appendChild(E.createElement("div")),(xe=E.createElement("input")).setAttribute("type","radio"),xe.setAttribute("checked","checked"),xe.setAttribute("name","t"),me.appendChild(xe),y.checkClone=me.cloneNode(!0).cloneNode(!0).lastChild.checked,me.innerHTML="<textarea>x</textarea>",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t<arguments.length;t++)u[t]=arguments[t];if(s.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,s)){a=k.event.handlers.call(this,s,l),t=0;while((i=a[t++])&&!s.isPropagationStopped()){s.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!s.isImmediatePropagationStopped())s.rnamespace&&!1!==o.namespace&&!s.rnamespace.test(o.namespace)||(s.handleObj=o,s.data=o.data,void 0!==(r=((k.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,u))&&!1===(s.result=r)&&(s.preventDefault(),s.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,s),s.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<k(i,this).index(l):k.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(k.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[k.expando]?e:new k.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click",ke),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Q.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},k.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},k.Event=function(e,t){if(!(this instanceof k.Event))return new k.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?ke:Se,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&k.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[k.expando]=!0},k.Event.prototype={constructor:k.Event,isDefaultPrevented:Se,isPropagationStopped:Se,isImmediatePropagationStopped:Se,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=ke,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=ke,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=ke,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},k.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&Te.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Ce.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},k.event.addProp),k.each({focus:"focusin",blur:"focusout"},function(e,t){k.event.special[e]={setup:function(){return De(this,e,Ne),!1},trigger:function(){return De(this,e),!0},delegateType:t}}),k.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){k.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||k.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),k.fn.extend({on:function(e,t,n,r){return Ae(this,e,t,n,r)},one:function(e,t,n,r){return Ae(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,k(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Se),this.each(function(){k.event.remove(this,e,n,t)})}});var je=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/<script|<style|<link/i,Le=/checked\s*(?:[^=]|=\s*.checked.)/i,He=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n<r;n++)k.event.add(t,i,l[i][n]);J.hasData(e)&&(s=J.access(e),u=k.extend({},s),J.set(t,u))}}function Ie(n,r,i,o){r=g.apply([],r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!y.checkClone&&Le.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Ie(t,r,i,o)});if(f&&(t=(e=we(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=k.map(ve(e,"script"),Pe)).length;c<f;c++)u=e,c!==p&&(u=k.clone(u,!0,!0),s&&k.merge(a,ve(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,k.map(a,Re),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Q.access(u,"globalEval")&&k.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?k._evalUrl&&!u.noModule&&k._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")}):b(u.textContent.replace(He,""),u,l))}return n}function We(e,t,n){for(var r,i=t?k.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||k.cleanData(ve(r)),r.parentNode&&(n&&oe(r)&&ye(ve(r,"script")),r.parentNode.removeChild(r));return e}k.extend({htmlPrefilter:function(e){return e.replace(je,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Me(o[r],a[r]);else Me(e,c);return 0<(a=ve(c,"script")).length&&ye(a,!f&&ve(e,"script")),c},cleanData:function(e){for(var t,n,r,i=k.event.special,o=0;void 0!==(n=e[o]);o++)if(G(n)){if(t=n[Q.expando]){if(t.events)for(r in t.events)i[r]?k.event.remove(n,r):k.removeEvent(n,r,t.handle);n[Q.expando]=void 0}n[J.expando]&&(n[J.expando]=void 0)}}}),k.fn.extend({detach:function(e){return We(this,e,!0)},remove:function(e){return We(this,e)},text:function(e){return _(this,function(e){return void 0===e?k.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Ie(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Oe(this,e).appendChild(e)})},prepend:function(){return Ie(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Oe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(k.cleanData(ve(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return k.clone(this,e,t)})},html:function(e){return _(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!qe.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=k.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(k.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Ie(this,arguments,function(e){var t=this.parentNode;k.inArray(this,n)<0&&(k.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),k.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){k.fn[e]=function(e){for(var t,n=[],r=k(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),k(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var $e=new RegExp("^("+te+")(?!px)[a-z%]+$","i"),Fe=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},Be=new RegExp(re.join("|"),"i");function _e(e,t,n){var r,i,o,a,s=e.style;return(n=n||Fe(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||oe(e)||(a=k.style(e,t)),!y.pixelBoxStyles()&&$e.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function ze(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(u){s.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",u.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",ie.appendChild(s).appendChild(u);var e=C.getComputedStyle(u);n="1%"!==e.top,a=12===t(e.marginLeft),u.style.right="60%",o=36===t(e.right),r=36===t(e.width),u.style.position="absolute",i=12===t(u.offsetWidth/3),ie.removeChild(s),u=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s=E.createElement("div"),u=E.createElement("div");u.style&&(u.style.backgroundClip="content-box",u.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===u.style.backgroundClip,k.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),a},scrollboxSize:function(){return e(),i}}))}();var Ue=["Webkit","Moz","ms"],Xe=E.createElement("div").style,Ve={};function Ge(e){var t=k.cssProps[e]||Ve[e];return t||(e in Xe?e:Ve[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=Ue.length;while(n--)if((e=Ue[n]+t)in Xe)return e}(e)||e)}var Ye=/^(none|table(?!-c[ea]).+)/,Qe=/^--/,Je={position:"absolute",visibility:"hidden",display:"block"},Ke={letterSpacing:"0",fontWeight:"400"};function Ze(e,t,n){var r=ne.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function et(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=k.css(e,n+re[a],!0,i)),r?("content"===n&&(u-=k.css(e,"padding"+re[a],!0,i)),"margin"!==n&&(u-=k.css(e,"border"+re[a]+"Width",!0,i))):(u+=k.css(e,"padding"+re[a],!0,i),"padding"!==n?u+=k.css(e,"border"+re[a]+"Width",!0,i):s+=k.css(e,"border"+re[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function tt(e,t,n){var r=Fe(e),i=(!y.boxSizingReliable()||n)&&"border-box"===k.css(e,"boxSizing",!1,r),o=i,a=_e(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if($e.test(a)){if(!n)return a;a="auto"}return(!y.boxSizingReliable()&&i||"auto"===a||!parseFloat(a)&&"inline"===k.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===k.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+et(e,t,n||(i?"border":"content"),o,r,a)+"px"}function nt(e,t,n,r,i){return new nt.prototype.init(e,t,n,r,i)}k.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=_e(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=V(t),u=Qe.test(t),l=e.style;if(u||(t=Ge(s)),a=k.cssHooks[t]||k.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=ne.exec(n))&&i[1]&&(n=le(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(k.cssNumber[s]?"":"px")),y.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=V(t);return Qe.test(t)||(t=Ge(s)),(a=k.cssHooks[t]||k.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=_e(e,t,r)),"normal"===i&&t in Ke&&(i=Ke[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),k.each(["height","width"],function(e,u){k.cssHooks[u]={get:function(e,t,n){if(t)return!Ye.test(k.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?tt(e,u,n):ue(e,Je,function(){return tt(e,u,n)})},set:function(e,t,n){var r,i=Fe(e),o=!y.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===k.css(e,"boxSizing",!1,i),s=n?et(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-et(e,u,"border",!1,i)-.5)),s&&(r=ne.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=k.css(e,u)),Ze(0,t,s)}}}),k.cssHooks.marginLeft=ze(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(_e(e,"marginLeft"))||e.getBoundingClientRect().left-ue(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),k.each({margin:"",padding:"",border:"Width"},function(i,o){k.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+re[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(k.cssHooks[i+o].set=Ze)}),k.fn.extend({css:function(e,t){return _(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Fe(e),i=t.length;a<i;a++)o[t[a]]=k.css(e,t[a],!1,r);return o}return void 0!==n?k.style(e,t,n):k.css(e,t)},e,t,1<arguments.length)}}),((k.Tween=nt).prototype={constructor:nt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||k.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(k.cssNumber[n]?"":"px")},cur:function(){var e=nt.propHooks[this.prop];return e&&e.get?e.get(this):nt.propHooks._default.get(this)},run:function(e){var t,n=nt.propHooks[this.prop];return this.options.duration?this.pos=t=k.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):nt.propHooks._default.set(this),this}}).init.prototype=nt.prototype,(nt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=k.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){k.fx.step[e.prop]?k.fx.step[e.prop](e):1!==e.elem.nodeType||!k.cssHooks[e.prop]&&null==e.elem.style[Ge(e.prop)]?e.elem[e.prop]=e.now:k.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=nt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},k.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},k.fx=nt.prototype.init,k.fx.step={};var rt,it,ot,at,st=/^(?:toggle|show|hide)$/,ut=/queueHooks$/;function lt(){it&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(lt):C.setTimeout(lt,k.fx.interval),k.fx.tick())}function ct(){return C.setTimeout(function(){rt=void 0}),rt=Date.now()}function ft(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=re[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function pt(e,t,n){for(var r,i=(dt.tweeners[t]||[]).concat(dt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function dt(o,e,t){var n,a,r=0,i=dt.prefilters.length,s=k.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=rt||ct(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:k.extend({},e),opts:k.extend(!0,{specialEasing:{},easing:k.easing._default},t),originalProperties:e,originalOptions:t,startTime:rt||ct(),duration:t.duration,tweens:[],createTween:function(e,t){var n=k.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=V(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=k.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=dt.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(k._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return k.map(c,pt,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),k.fx.timer(k.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}k.Animation=k.extend(dt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return le(n.elem,e,ne.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(R);for(var n,r=0,i=e.length;r<i;r++)n=e[r],dt.tweeners[n]=dt.tweeners[n]||[],dt.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&se(e),v=Q.get(e,"fxshow");for(r in n.queue||(null==(a=k._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,k.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],st.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||k.style(e,r)}if((u=!k.isEmptyObject(t))||!k.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Q.get(e,"display")),"none"===(c=k.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=k.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===k.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=Q.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&fe([e],!0),p.done(function(){for(r in g||fe([e]),Q.remove(e,"fxshow"),d)k.style(e,r,d[r])})),u=pt(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?dt.prefilters.unshift(e):dt.prefilters.push(e)}}),k.speed=function(e,t,n){var r=e&&"object"==typeof e?k.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return k.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in k.fx.speeds?r.duration=k.fx.speeds[r.duration]:r.duration=k.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&k.dequeue(this,r.queue)},r},k.fn.extend({fadeTo:function(e,t,n,r){return this.filter(se).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=k.isEmptyObject(t),o=k.speed(e,n,r),a=function(){var e=dt(this,k.extend({},t),o);(i||Q.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&!1!==i&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=k.timers,r=Q.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&ut.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||k.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Q.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=k.timers,o=n?n.length:0;for(t.finish=!0,k.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),k.each(["toggle","show","hide"],function(e,r){var i=k.fn[r];k.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(ft(r,!0),e,t,n)}}),k.each({slideDown:ft("show"),slideUp:ft("hide"),slideToggle:ft("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){k.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),k.timers=[],k.fx.tick=function(){var e,t=0,n=k.timers;for(rt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||k.fx.stop(),rt=void 0},k.fx.timer=function(e){k.timers.push(e),k.fx.start()},k.fx.interval=13,k.fx.start=function(){it||(it=!0,lt())},k.fx.stop=function(){it=null},k.fx.speeds={slow:600,fast:200,_default:400},k.fn.delay=function(r,e){return r=k.fx&&k.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},ot=E.createElement("input"),at=E.createElement("select").appendChild(E.createElement("option")),ot.type="checkbox",y.checkOn=""!==ot.value,y.optSelected=at.selected,(ot=E.createElement("input")).value="t",ot.type="radio",y.radioValue="t"===ot.value;var ht,gt=k.expr.attrHandle;k.fn.extend({attr:function(e,t){return _(this,k.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){k.removeAttr(this,e)})}}),k.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?k.prop(e,t,n):(1===o&&k.isXMLDoc(e)||(i=k.attrHooks[t.toLowerCase()]||(k.expr.match.bool.test(t)?ht:void 0)),void 0!==n?null===n?void k.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=k.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(R);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),ht={set:function(e,t,n){return!1===t?k.removeAttr(e,n):e.setAttribute(n,n),n}},k.each(k.expr.match.bool.source.match(/\w+/g),function(e,t){var a=gt[t]||k.find.attr;gt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=gt[o],gt[o]=r,r=null!=a(e,t,n)?o:null,gt[o]=i),r}});var vt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;function mt(e){return(e.match(R)||[]).join(" ")}function xt(e){return e.getAttribute&&e.getAttribute("class")||""}function bt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(R)||[]}k.fn.extend({prop:function(e,t){return _(this,k.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[k.propFix[e]||e]})}}),k.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&k.isXMLDoc(e)||(t=k.propFix[t]||t,i=k.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=k.find.attr(e,"tabindex");return t?parseInt(t,10):vt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),y.optSelected||(k.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),k.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){k.propFix[this.toLowerCase()]=this}),k.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).addClass(t.call(this,e,xt(this)))});if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).removeClass(t.call(this,e,xt(this)))});if(!arguments.length)return this.attr("class","");if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])while(-1<r.indexOf(" "+o+" "))r=r.replace(" "+o+" "," ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(i,t){var o=typeof i,a="string"===o||Array.isArray(i);return"boolean"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){k(this).toggleClass(i.call(this,e,xt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=k(this),r=bt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&"boolean"!==o||((e=xt(this))&&Q.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===i?"":Q.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+mt(xt(n))+" ").indexOf(t))return!0;return!1}});var wt=/\r/g;k.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,k(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=k.map(t,function(e){return null==e?"":e+""})),(r=k.valHooks[this.type]||k.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=k.valHooks[t.type]||k.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(wt,""):null==e?"":e:void 0}}),k.extend({valHooks:{option:{get:function(e){var t=k.find.attr(e,"value");return null!=t?t:mt(k.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=k(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=k.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<k.inArray(k.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),k.each(["radio","checkbox"],function(){k.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<k.inArray(k(e).val(),t)}},y.checkOn||(k.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),y.focusin="onfocusin"in C;var Tt=/^(?:focusinfocus|focusoutblur)$/,Ct=function(e){e.stopPropagation()};k.extend(k.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,"type")?e.type:e,h=v.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!Tt.test(d+k.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[k.expando]?e:new k.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:k.makeArray(t,[e]),c=k.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,Tt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Q.get(o,"events")||{})[e.type]&&Q.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&G(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!G(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),k.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,Ct),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,Ct),k.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=k.extend(new k.Event,n,{type:e,isSimulated:!0});k.event.trigger(r,null,t)}}),k.fn.extend({trigger:function(e,t){return this.each(function(){k.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return k.event.trigger(e,t,n,!0)}}),y.focusin||k.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){k.event.simulate(r,e.target,k.event.fix(e))};k.event.special[r]={setup:function(){var e=this.ownerDocument||this,t=Q.access(e,r);t||e.addEventListener(n,i,!0),Q.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this,t=Q.access(e,r)-1;t?Q.access(e,r,t):(e.removeEventListener(n,i,!0),Q.remove(e,r))}}});var Et=C.location,kt=Date.now(),St=/\?/;k.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||k.error("Invalid XML: "+e),t};var Nt=/\[\]$/,At=/\r?\n/g,Dt=/^(?:submit|button|image|reset|file)$/i,jt=/^(?:input|select|textarea|keygen)/i;function qt(n,e,r,i){var t;if(Array.isArray(e))k.each(e,function(e,t){r||Nt.test(n)?i(n,t):qt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)qt(n+"["+t+"]",e[t],r,i)}k.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!k.isPlainObject(e))k.each(e,function(){i(this.name,this.value)});else for(n in e)qt(n,e[n],t,i);return r.join("&")},k.fn.extend({serialize:function(){return k.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=k.prop(this,"elements");return e?k.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!k(this).is(":disabled")&&jt.test(this.nodeName)&&!Dt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=k(this).val();return null==n?null:Array.isArray(n)?k.map(n,function(e){return{name:t.name,value:e.replace(At,"\r\n")}}):{name:t.name,value:n.replace(At,"\r\n")}}).get()}});var Lt=/%20/g,Ht=/#.*$/,Ot=/([?&])_=[^&]*/,Pt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Rt=/^(?:GET|HEAD)$/,Mt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Ft=E.createElement("a");function Bt(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(R)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function _t(t,i,o,a){var s={},u=t===Wt;function l(e){var r;return s[e]=!0,k.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function zt(e,t){var n,r,i=k.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&k.extend(!0,e,r),e}Ft.href=Et.href,k.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Et.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Et.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":k.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,k.ajaxSettings),t):zt(k.ajaxSettings,e)},ajaxPrefilter:Bt(It),ajaxTransport:Bt(Wt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=k.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?k(y):k.event,x=k.Deferred(),b=k.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Pt.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Et.href)+"").replace(Mt,Et.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(R)||[""],null==v.crossDomain){r=E.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Ft.protocol+"//"+Ft.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=k.param(v.data,v.traditional)),_t(It,v,t,T),h)return T;for(i in(g=k.event&&v.global)&&0==k.active++&&k.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Rt.test(v.type),f=v.url.replace(Ht,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(Lt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(St.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Ot,"$1"),o=(St.test(f)?"&":"?")+"_="+kt+++o),v.url=f+o),v.ifModified&&(k.lastModified[f]&&T.setRequestHeader("If-Modified-Since",k.lastModified[f]),k.etag[f]&&T.setRequestHeader("If-None-Match",k.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+$t+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=_t(Wt,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(k.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(k.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--k.active||k.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return k.get(e,t,n,"json")},getScript:function(e,t){return k.get(e,void 0,t,"script")}}),k.each(["get","post"],function(e,i){k[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),k.ajax(k.extend({url:e,type:i,dataType:r,data:t,success:n},k.isPlainObject(e)&&e))}}),k._evalUrl=function(e,t){return k.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){k.globalEval(e,t)}})},k.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=k(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){k(this).wrapInner(n.call(this,e))}):this.each(function(){var e=k(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){k(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){k(this).replaceWith(this.childNodes)}),this}}),k.expr.pseudos.hidden=function(e){return!k.expr.pseudos.visible(e)},k.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},k.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var Ut={0:200,1223:204},Xt=k.ajaxSettings.xhr();y.cors=!!Xt&&"withCredentials"in Xt,y.ajax=Xt=!!Xt,k.ajaxTransport(function(i){var o,a;if(y.cors||Xt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(Ut[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),k.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),k.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return k.globalEval(e),e}}}),k.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),k.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=k("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=mt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&k.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?k("<div>").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}}),k.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),k.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),k.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||k.guid++,i},k.holdReady=function(e){e?k.readyWait++:k.ready(!0)},k.isArray=Array.isArray,k.parseJSON=JSON.parse,k.nodeName=A,k.isFunction=m,k.isWindow=x,k.camelCase=V,k.type=w,k.now=Date.now,k.isNumeric=function(e){var t=k.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return k});var Qt=C.jQuery,Jt=C.$;return k.noConflict=function(e){return C.$===k&&(C.$=Jt),e&&C.jQuery===k&&(C.jQuery=Qt),k},e||(C.jQuery=C.$=k),k});
/*!
 * Bootstrap v3.4.1 (https://getbootstrap.com/)
 * Copyright 2011-2019 Twitter, Inc.
 * Licensed under the MIT license
 */
if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");!function(t){"use strict";var e=jQuery.fn.jquery.split(" ")[0].split(".");if(e[0]<2&&e[1]<9||1==e[0]&&9==e[1]&&e[2]<1||3<e[0])throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(),function(n){"use strict";n.fn.emulateTransitionEnd=function(t){var e=!1,i=this;n(this).one("bsTransitionEnd",function(){e=!0});return setTimeout(function(){e||n(i).trigger(n.support.transition.end)},t),this},n(function(){n.support.transition=function o(){var t=document.createElement("bootstrap"),e={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var i in e)if(t.style[i]!==undefined)return{end:e[i]};return!1}(),n.support.transition&&(n.event.special.bsTransitionEnd={bindType:n.support.transition.end,delegateType:n.support.transition.end,handle:function(t){if(n(t.target).is(this))return t.handleObj.handler.apply(this,arguments)}})})}(jQuery),function(s){"use strict";var e='[data-dismiss="alert"]',a=function(t){s(t).on("click",e,this.close)};a.VERSION="3.4.1",a.TRANSITION_DURATION=150,a.prototype.close=function(t){var e=s(this),i=e.attr("data-target");i||(i=(i=e.attr("href"))&&i.replace(/.*(?=#[^\s]*$)/,"")),i="#"===i?[]:i;var o=s(document).find(i);function n(){o.detach().trigger("closed.bs.alert").remove()}t&&t.preventDefault(),o.length||(o=e.closest(".alert")),o.trigger(t=s.Event("close.bs.alert")),t.isDefaultPrevented()||(o.removeClass("in"),s.support.transition&&o.hasClass("fade")?o.one("bsTransitionEnd",n).emulateTransitionEnd(a.TRANSITION_DURATION):n())};var t=s.fn.alert;s.fn.alert=function o(i){return this.each(function(){var t=s(this),e=t.data("bs.alert");e||t.data("bs.alert",e=new a(this)),"string"==typeof i&&e[i].call(t)})},s.fn.alert.Constructor=a,s.fn.alert.noConflict=function(){return s.fn.alert=t,this},s(document).on("click.bs.alert.data-api",e,a.prototype.close)}(jQuery),function(s){"use strict";var n=function(t,e){this.$element=s(t),this.options=s.extend({},n.DEFAULTS,e),this.isLoading=!1};function i(o){return this.each(function(){var t=s(this),e=t.data("bs.button"),i="object"==typeof o&&o;e||t.data("bs.button",e=new n(this,i)),"toggle"==o?e.toggle():o&&e.setState(o)})}n.VERSION="3.4.1",n.DEFAULTS={loadingText:"loading..."},n.prototype.setState=function(t){var e="disabled",i=this.$element,o=i.is("input")?"val":"html",n=i.data();t+="Text",null==n.resetText&&i.data("resetText",i[o]()),setTimeout(s.proxy(function(){i[o](null==n[t]?this.options[t]:n[t]),"loadingText"==t?(this.isLoading=!0,i.addClass(e).attr(e,e).prop(e,!0)):this.isLoading&&(this.isLoading=!1,i.removeClass(e).removeAttr(e).prop(e,!1))},this),0)},n.prototype.toggle=function(){var t=!0,e=this.$element.closest('[data-toggle="buttons"]');if(e.length){var i=this.$element.find("input");"radio"==i.prop("type")?(i.prop("checked")&&(t=!1),e.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==i.prop("type")&&(i.prop("checked")!==this.$element.hasClass("active")&&(t=!1),this.$element.toggleClass("active")),i.prop("checked",this.$element.hasClass("active")),t&&i.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var t=s.fn.button;s.fn.button=i,s.fn.button.Constructor=n,s.fn.button.noConflict=function(){return s.fn.button=t,this},s(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(t){var e=s(t.target).closest(".btn");i.call(e,"toggle"),s(t.target).is('input[type="radio"], input[type="checkbox"]')||(t.preventDefault(),e.is("input,button")?e.trigger("focus"):e.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(t){s(t.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(t.type))})}(jQuery),function(p){"use strict";var c=function(t,e){this.$element=p(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=e,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",p.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",p.proxy(this.pause,this)).on("mouseleave.bs.carousel",p.proxy(this.cycle,this))};function r(n){return this.each(function(){var t=p(this),e=t.data("bs.carousel"),i=p.extend({},c.DEFAULTS,t.data(),"object"==typeof n&&n),o="string"==typeof n?n:i.slide;e||t.data("bs.carousel",e=new c(this,i)),"number"==typeof n?e.to(n):o?e[o]():i.interval&&e.pause().cycle()})}c.VERSION="3.4.1",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(t){if(!/input|textarea/i.test(t.target.tagName)){switch(t.which){case 37:this.prev();break;case 39:this.next();break;default:return}t.preventDefault()}},c.prototype.cycle=function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(p.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(t){return this.$items=t.parent().children(".item"),this.$items.index(t||this.$active)},c.prototype.getItemForDirection=function(t,e){var i=this.getItemIndex(e);if(("prev"==t&&0===i||"next"==t&&i==this.$items.length-1)&&!this.options.wrap)return e;var o=(i+("prev"==t?-1:1))%this.$items.length;return this.$items.eq(o)},c.prototype.to=function(t){var e=this,i=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(t>this.$items.length-1||t<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){e.to(t)}):i==t?this.pause().cycle():this.slide(i<t?"next":"prev",this.$items.eq(t))},c.prototype.pause=function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&p.support.transition&&(this.$element.trigger(p.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(t,e){var i=this.$element.find(".item.active"),o=e||this.getItemForDirection(t,i),n=this.interval,s="next"==t?"left":"right",a=this;if(o.hasClass("active"))return this.sliding=!1;var r=o[0],l=p.Event("slide.bs.carousel",{relatedTarget:r,direction:s});if(this.$element.trigger(l),!l.isDefaultPrevented()){if(this.sliding=!0,n&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var h=p(this.$indicators.children()[this.getItemIndex(o)]);h&&h.addClass("active")}var d=p.Event("slid.bs.carousel",{relatedTarget:r,direction:s});return p.support.transition&&this.$element.hasClass("slide")?(o.addClass(t),"object"==typeof o&&o.length&&o[0].offsetWidth,i.addClass(s),o.addClass(s),i.one("bsTransitionEnd",function(){o.removeClass([t,s].join(" ")).addClass("active"),i.removeClass(["active",s].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger(d)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(i.removeClass("active"),o.addClass("active"),this.sliding=!1,this.$element.trigger(d)),n&&this.cycle(),this}};var t=p.fn.carousel;p.fn.carousel=r,p.fn.carousel.Constructor=c,p.fn.carousel.noConflict=function(){return p.fn.carousel=t,this};var e=function(t){var e=p(this),i=e.attr("href");i&&(i=i.replace(/.*(?=#[^\s]+$)/,""));var o=e.attr("data-target")||i,n=p(document).find(o);if(n.hasClass("carousel")){var s=p.extend({},n.data(),e.data()),a=e.attr("data-slide-to");a&&(s.interval=!1),r.call(n,s),a&&n.data("bs.carousel").to(a),t.preventDefault()}};p(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),p(window).on("load",function(){p('[data-ride="carousel"]').each(function(){var t=p(this);r.call(t,t.data())})})}(jQuery),function(a){"use strict";var r=function(t,e){this.$element=a(t),this.options=a.extend({},r.DEFAULTS,e),this.$trigger=a('[data-toggle="collapse"][href="#'+t.id+'"],[data-toggle="collapse"][data-target="#'+t.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};function n(t){var e,i=t.attr("data-target")||(e=t.attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"");return a(document).find(i)}function l(o){return this.each(function(){var t=a(this),e=t.data("bs.collapse"),i=a.extend({},r.DEFAULTS,t.data(),"object"==typeof o&&o);!e&&i.toggle&&/show|hide/.test(o)&&(i.toggle=!1),e||t.data("bs.collapse",e=new r(this,i)),"string"==typeof o&&e[o]()})}r.VERSION="3.4.1",r.TRANSITION_DURATION=350,r.DEFAULTS={toggle:!0},r.prototype.dimension=function(){return this.$element.hasClass("width")?"width":"height"},r.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var t,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(t=e.data("bs.collapse"))&&t.transitioning)){var i=a.Event("show.bs.collapse");if(this.$element.trigger(i),!i.isDefaultPrevented()){e&&e.length&&(l.call(e,"hide"),t||e.data("bs.collapse",null));var o=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[o](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var n=function(){this.$element.removeClass("collapsing").addClass("collapse in")[o](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return n.call(this);var s=a.camelCase(["scroll",o].join("-"));this.$element.one("bsTransitionEnd",a.proxy(n,this)).emulateTransitionEnd(r.TRANSITION_DURATION)[o](this.$element[0][s])}}}},r.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var t=a.Event("hide.bs.collapse");if(this.$element.trigger(t),!t.isDefaultPrevented()){var e=this.dimension();this.$element[e](this.$element[e]())[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 i=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};if(!a.support.transition)return i.call(this);this.$element[e](0).one("bsTransitionEnd",a.proxy(i,this)).emulateTransitionEnd(r.TRANSITION_DURATION)}}},r.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},r.prototype.getParent=function(){return a(document).find(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(t,e){var i=a(e);this.addAriaAndCollapsedClass(n(i),i)},this)).end()},r.prototype.addAriaAndCollapsedClass=function(t,e){var i=t.hasClass("in");t.attr("aria-expanded",i),e.toggleClass("collapsed",!i).attr("aria-expanded",i)};var t=a.fn.collapse;a.fn.collapse=l,a.fn.collapse.Constructor=r,a.fn.collapse.noConflict=function(){return a.fn.collapse=t,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(t){var e=a(this);e.attr("data-target")||t.preventDefault();var i=n(e),o=i.data("bs.collapse")?"toggle":e.data();l.call(i,o)})}(jQuery),function(a){"use strict";var r='[data-toggle="dropdown"]',o=function(t){a(t).on("click.bs.dropdown",this.toggle)};function l(t){var e=t.attr("data-target");e||(e=(e=t.attr("href"))&&/#[A-Za-z]/.test(e)&&e.replace(/.*(?=#[^\s]*$)/,""));var i="#"!==e?a(document).find(e):null;return i&&i.length?i:t.parent()}function s(o){o&&3===o.which||(a(".dropdown-backdrop").remove(),a(r).each(function(){var t=a(this),e=l(t),i={relatedTarget:this};e.hasClass("open")&&(o&&"click"==o.type&&/input|textarea/i.test(o.target.tagName)&&a.contains(e[0],o.target)||(e.trigger(o=a.Event("hide.bs.dropdown",i)),o.isDefaultPrevented()||(t.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",i)))))}))}o.VERSION="3.4.1",o.prototype.toggle=function(t){var e=a(this);if(!e.is(".disabled, :disabled")){var i=l(e),o=i.hasClass("open");if(s(),!o){"ontouchstart"in document.documentElement&&!i.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",s);var n={relatedTarget:this};if(i.trigger(t=a.Event("show.bs.dropdown",n)),t.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),i.toggleClass("open").trigger(a.Event("shown.bs.dropdown",n))}return!1}},o.prototype.keydown=function(t){if(/(38|40|27|32)/.test(t.which)&&!/input|textarea/i.test(t.target.tagName)){var e=a(this);if(t.preventDefault(),t.stopPropagation(),!e.is(".disabled, :disabled")){var i=l(e),o=i.hasClass("open");if(!o&&27!=t.which||o&&27==t.which)return 27==t.which&&i.find(r).trigger("focus"),e.trigger("click");var n=i.find(".dropdown-menu li:not(.disabled):visible a");if(n.length){var s=n.index(t.target);38==t.which&&0<s&&s--,40==t.which&&s<n.length-1&&s++,~s||(s=0),n.eq(s).trigger("focus")}}}};var t=a.fn.dropdown;a.fn.dropdown=function e(i){return this.each(function(){var t=a(this),e=t.data("bs.dropdown");e||t.data("bs.dropdown",e=new o(this)),"string"==typeof i&&e[i].call(t)})},a.fn.dropdown.Constructor=o,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=t,this},a(document).on("click.bs.dropdown.data-api",s).on("click.bs.dropdown.data-api",".dropdown form",function(t){t.stopPropagation()}).on("click.bs.dropdown.data-api",r,o.prototype.toggle).on("keydown.bs.dropdown.data-api",r,o.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",o.prototype.keydown)}(jQuery),function(a){"use strict";var s=function(t,e){this.options=e,this.$body=a(document.body),this.$element=a(t),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.fixedContent=".navbar-fixed-top, .navbar-fixed-bottom",this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};function r(o,n){return this.each(function(){var t=a(this),e=t.data("bs.modal"),i=a.extend({},s.DEFAULTS,t.data(),"object"==typeof o&&o);e||t.data("bs.modal",e=new s(this,i)),"string"==typeof o?e[o](n):i.show&&e.show(n)})}s.VERSION="3.4.1",s.TRANSITION_DURATION=300,s.BACKDROP_TRANSITION_DURATION=150,s.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},s.prototype.toggle=function(t){return this.isShown?this.hide():this.show(t)},s.prototype.show=function(i){var o=this,t=a.Event("show.bs.modal",{relatedTarget:i});this.$element.trigger(t),this.isShown||t.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(){o.$element.one("mouseup.dismiss.bs.modal",function(t){a(t.target).is(o.$element)&&(o.ignoreBackdropClick=!0)})}),this.backdrop(function(){var t=a.support.transition&&o.$element.hasClass("fade");o.$element.parent().length||o.$element.appendTo(o.$body),o.$element.show().scrollTop(0),o.adjustDialog(),t&&o.$element[0].offsetWidth,o.$element.addClass("in"),o.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:i});t?o.$dialog.one("bsTransitionEnd",function(){o.$element.trigger("focus").trigger(e)}).emulateTransitionEnd(s.TRANSITION_DURATION):o.$element.trigger("focus").trigger(e)}))},s.prototype.hide=function(t){t&&t.preventDefault(),t=a.Event("hide.bs.modal"),this.$element.trigger(t),this.isShown&&!t.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(s.TRANSITION_DURATION):this.hideModal())},s.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(t){document===t.target||this.$element[0]===t.target||this.$element.has(t.target).length||this.$element.trigger("focus")},this))},s.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(t){27==t.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},s.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},s.prototype.hideModal=function(){var t=this;this.$element.hide(),this.backdrop(function(){t.$body.removeClass("modal-open"),t.resetAdjustments(),t.resetScrollbar(),t.$element.trigger("hidden.bs.modal")})},s.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},s.prototype.backdrop=function(t){var e=this,i=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var o=a.support.transition&&i;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+i).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(t){this.ignoreBackdropClick?this.ignoreBackdropClick=!1:t.target===t.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide())},this)),o&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!t)return;o?this.$backdrop.one("bsTransitionEnd",t).emulateTransitionEnd(s.BACKDROP_TRANSITION_DURATION):t()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var n=function(){e.removeBackdrop(),t&&t()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",n).emulateTransitionEnd(s.BACKDROP_TRANSITION_DURATION):n()}else t&&t()},s.prototype.handleUpdate=function(){this.adjustDialog()},s.prototype.adjustDialog=function(){var t=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&t?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!t?this.scrollbarWidth:""})},s.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},s.prototype.checkScrollbar=function(){var t=window.innerWidth;if(!t){var e=document.documentElement.getBoundingClientRect();t=e.right-Math.abs(e.left)}this.bodyIsOverflowing=document.body.clientWidth<t,this.scrollbarWidth=this.measureScrollbar()},s.prototype.setScrollbar=function(){var t=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"";var n=this.scrollbarWidth;this.bodyIsOverflowing&&(this.$body.css("padding-right",t+n),a(this.fixedContent).each(function(t,e){var i=e.style.paddingRight,o=a(e).css("padding-right");a(e).data("padding-right",i).css("padding-right",parseFloat(o)+n+"px")}))},s.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad),a(this.fixedContent).each(function(t,e){var i=a(e).data("padding-right");a(e).removeData("padding-right"),e.style.paddingRight=i||""})},s.prototype.measureScrollbar=function(){var t=document.createElement("div");t.className="modal-scrollbar-measure",this.$body.append(t);var e=t.offsetWidth-t.clientWidth;return this.$body[0].removeChild(t),e};var t=a.fn.modal;a.fn.modal=r,a.fn.modal.Constructor=s,a.fn.modal.noConflict=function(){return a.fn.modal=t,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(t){var e=a(this),i=e.attr("href"),o=e.attr("data-target")||i&&i.replace(/.*(?=#[^\s]+$)/,""),n=a(document).find(o),s=n.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(i)&&i},n.data(),e.data());e.is("a")&&t.preventDefault(),n.one("show.bs.modal",function(t){t.isDefaultPrevented()||n.one("hidden.bs.modal",function(){e.is(":visible")&&e.trigger("focus")})}),r.call(n,s,this)})}(jQuery),function(g){"use strict";var o=["sanitize","whiteList","sanitizeFn"],a=["background","cite","href","itemtype","longdesc","poster","src","xlink:href"],t={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},r=/^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi,l=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;function u(t,e){var i=t.nodeName.toLowerCase();if(-1!==g.inArray(i,e))return-1===g.inArray(i,a)||Boolean(t.nodeValue.match(r)||t.nodeValue.match(l));for(var o=g(e).filter(function(t,e){return e instanceof RegExp}),n=0,s=o.length;n<s;n++)if(i.match(o[n]))return!0;return!1}function n(t,e,i){if(0===t.length)return t;if(i&&"function"==typeof i)return i(t);if(!document.implementation||!document.implementation.createHTMLDocument)return t;var o=document.implementation.createHTMLDocument("sanitization");o.body.innerHTML=t;for(var n=g.map(e,function(t,e){return e}),s=g(o.body).find("*"),a=0,r=s.length;a<r;a++){var l=s[a],h=l.nodeName.toLowerCase();if(-1!==g.inArray(h,n))for(var d=g.map(l.attributes,function(t){return t}),p=[].concat(e["*"]||[],e[h]||[]),c=0,f=d.length;c<f;c++)u(d[c],p)||l.removeAttribute(d[c].nodeName);else l.parentNode.removeChild(l)}return o.body.innerHTML}var m=function(t,e){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",t,e)};m.VERSION="3.4.1",m.TRANSITION_DURATION=150,m.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},sanitize:!0,sanitizeFn:null,whiteList:t},m.prototype.init=function(t,e,i){if(this.enabled=!0,this.type=t,this.$element=g(e),this.options=this.getOptions(i),this.$viewport=this.options.viewport&&g(document).find(g.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 o=this.options.trigger.split(" "),n=o.length;n--;){var s=o[n];if("click"==s)this.$element.on("click."+this.type,this.options.selector,g.proxy(this.toggle,this));else if("manual"!=s){var a="hover"==s?"mouseenter":"focusin",r="hover"==s?"mouseleave":"focusout";this.$element.on(a+"."+this.type,this.options.selector,g.proxy(this.enter,this)),this.$element.on(r+"."+this.type,this.options.selector,g.proxy(this.leave,this))}}this.options.selector?this._options=g.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},m.prototype.getDefaults=function(){return m.DEFAULTS},m.prototype.getOptions=function(t){var e=this.$element.data();for(var i in e)e.hasOwnProperty(i)&&-1!==g.inArray(i,o)&&delete e[i];return(t=g.extend({},this.getDefaults(),e,t)).delay&&"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),t.sanitize&&(t.template=n(t.template,t.whiteList,t.sanitizeFn)),t},m.prototype.getDelegateOptions=function(){var i={},o=this.getDefaults();return this._options&&g.each(this._options,function(t,e){o[t]!=e&&(i[t]=e)}),i},m.prototype.enter=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusin"==t.type?"focus":"hover"]=!0),e.tip().hasClass("in")||"in"==e.hoverState)e.hoverState="in";else{if(clearTimeout(e.timeout),e.hoverState="in",!e.options.delay||!e.options.delay.show)return e.show();e.timeout=setTimeout(function(){"in"==e.hoverState&&e.show()},e.options.delay.show)}},m.prototype.isInStateTrue=function(){for(var t in this.inState)if(this.inState[t])return!0;return!1},m.prototype.leave=function(t){var e=t instanceof this.constructor?t:g(t.currentTarget).data("bs."+this.type);if(e||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e)),t instanceof g.Event&&(e.inState["focusout"==t.type?"focus":"hover"]=!1),!e.isInStateTrue()){if(clearTimeout(e.timeout),e.hoverState="out",!e.options.delay||!e.options.delay.hide)return e.hide();e.timeout=setTimeout(function(){"out"==e.hoverState&&e.hide()},e.options.delay.hide)}},m.prototype.show=function(){var t=g.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(t);var e=g.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(t.isDefaultPrevented()||!e)return;var i=this,o=this.tip(),n=this.getUID(this.type);this.setContent(),o.attr("id",n),this.$element.attr("aria-describedby",n),this.options.animation&&o.addClass("fade");var s="function"==typeof this.options.placement?this.options.placement.call(this,o[0],this.$element[0]):this.options.placement,a=/\s?auto?\s?/i,r=a.test(s);r&&(s=s.replace(a,"")||"top"),o.detach().css({top:0,left:0,display:"block"}).addClass(s).data("bs."+this.type,this),this.options.container?o.appendTo(g(document).find(this.options.container)):o.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var l=this.getPosition(),h=o[0].offsetWidth,d=o[0].offsetHeight;if(r){var p=s,c=this.getPosition(this.$viewport);s="bottom"==s&&l.bottom+d>c.bottom?"top":"top"==s&&l.top-d<c.top?"bottom":"right"==s&&l.right+h>c.width?"left":"left"==s&&l.left-h<c.left?"right":s,o.removeClass(p).addClass(s)}var f=this.getCalculatedOffset(s,l,h,d);this.applyPlacement(f,s);var u=function(){var t=i.hoverState;i.$element.trigger("shown.bs."+i.type),i.hoverState=null,"out"==t&&i.leave(i)};g.support.transition&&this.$tip.hasClass("fade")?o.one("bsTransitionEnd",u).emulateTransitionEnd(m.TRANSITION_DURATION):u()}},m.prototype.applyPlacement=function(t,e){var i=this.tip(),o=i[0].offsetWidth,n=i[0].offsetHeight,s=parseInt(i.css("margin-top"),10),a=parseInt(i.css("margin-left"),10);isNaN(s)&&(s=0),isNaN(a)&&(a=0),t.top+=s,t.left+=a,g.offset.setOffset(i[0],g.extend({using:function(t){i.css({top:Math.round(t.top),left:Math.round(t.left)})}},t),0),i.addClass("in");var r=i[0].offsetWidth,l=i[0].offsetHeight;"top"==e&&l!=n&&(t.top=t.top+n-l);var h=this.getViewportAdjustedDelta(e,t,r,l);h.left?t.left+=h.left:t.top+=h.top;var d=/top|bottom/.test(e),p=d?2*h.left-o+r:2*h.top-n+l,c=d?"offsetWidth":"offsetHeight";i.offset(t),this.replaceArrow(p,i[0][c],d)},m.prototype.replaceArrow=function(t,e,i){this.arrow().css(i?"left":"top",50*(1-t/e)+"%").css(i?"top":"left","")},m.prototype.setContent=function(){var t=this.tip(),e=this.getTitle();this.options.html?(this.options.sanitize&&(e=n(e,this.options.whiteList,this.options.sanitizeFn)),t.find(".tooltip-inner").html(e)):t.find(".tooltip-inner").text(e),t.removeClass("fade in top bottom left right")},m.prototype.hide=function(t){var e=this,i=g(this.$tip),o=g.Event("hide.bs."+this.type);function n(){"in"!=e.hoverState&&i.detach(),e.$element&&e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),t&&t()}if(this.$element.trigger(o),!o.isDefaultPrevented())return i.removeClass("in"),g.support.transition&&i.hasClass("fade")?i.one("bsTransitionEnd",n).emulateTransitionEnd(m.TRANSITION_DURATION):n(),this.hoverState=null,this},m.prototype.fixTitle=function(){var t=this.$element;(t.attr("title")||"string"!=typeof t.attr("data-original-title"))&&t.attr("data-original-title",t.attr("title")||"").attr("title","")},m.prototype.hasContent=function(){return this.getTitle()},m.prototype.getPosition=function(t){var e=(t=t||this.$element)[0],i="BODY"==e.tagName,o=e.getBoundingClientRect();null==o.width&&(o=g.extend({},o,{width:o.right-o.left,height:o.bottom-o.top}));var n=window.SVGElement&&e instanceof window.SVGElement,s=i?{top:0,left:0}:n?null:t.offset(),a={scroll:i?document.documentElement.scrollTop||document.body.scrollTop:t.scrollTop()},r=i?{width:g(window).width(),height:g(window).height()}:null;return g.extend({},o,a,r,s)},m.prototype.getCalculatedOffset=function(t,e,i,o){return"bottom"==t?{top:e.top+e.height,left:e.left+e.width/2-i/2}:"top"==t?{top:e.top-o,left:e.left+e.width/2-i/2}:"left"==t?{top:e.top+e.height/2-o/2,left:e.left-i}:{top:e.top+e.height/2-o/2,left:e.left+e.width}},m.prototype.getViewportAdjustedDelta=function(t,e,i,o){var n={top:0,left:0};if(!this.$viewport)return n;var s=this.options.viewport&&this.options.viewport.padding||0,a=this.getPosition(this.$viewport);if(/right|left/.test(t)){var r=e.top-s-a.scroll,l=e.top+s-a.scroll+o;r<a.top?n.top=a.top-r:l>a.top+a.height&&(n.top=a.top+a.height-l)}else{var h=e.left-s,d=e.left+s+i;h<a.left?n.left=a.left-h:d>a.right&&(n.left=a.left+a.width-d)}return n},m.prototype.getTitle=function(){var t=this.$element,e=this.options;return t.attr("data-original-title")||("function"==typeof e.title?e.title.call(t[0]):e.title)},m.prototype.getUID=function(t){for(;t+=~~(1e6*Math.random()),document.getElementById(t););return t},m.prototype.tip=function(){if(!this.$tip&&(this.$tip=g(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},m.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},m.prototype.enable=function(){this.enabled=!0},m.prototype.disable=function(){this.enabled=!1},m.prototype.toggleEnabled=function(){this.enabled=!this.enabled},m.prototype.toggle=function(t){var e=this;t&&((e=g(t.currentTarget).data("bs."+this.type))||(e=new this.constructor(t.currentTarget,this.getDelegateOptions()),g(t.currentTarget).data("bs."+this.type,e))),t?(e.inState.click=!e.inState.click,e.isInStateTrue()?e.enter(e):e.leave(e)):e.tip().hasClass("in")?e.leave(e):e.enter(e)},m.prototype.destroy=function(){var t=this;clearTimeout(this.timeout),this.hide(function(){t.$element.off("."+t.type).removeData("bs."+t.type),t.$tip&&t.$tip.detach(),t.$tip=null,t.$arrow=null,t.$viewport=null,t.$element=null})},m.prototype.sanitizeHtml=function(t){return n(t,this.options.whiteList,this.options.sanitizeFn)};var e=g.fn.tooltip;g.fn.tooltip=function i(o){return this.each(function(){var t=g(this),e=t.data("bs.tooltip"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.tooltip",e=new m(this,i)),"string"==typeof o&&e[o]())})},g.fn.tooltip.Constructor=m,g.fn.tooltip.noConflict=function(){return g.fn.tooltip=e,this}}(jQuery),function(n){"use strict";var s=function(t,e){this.init("popover",t,e)};if(!n.fn.tooltip)throw new Error("Popover requires tooltip.js");s.VERSION="3.4.1",s.DEFAULTS=n.extend({},n.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>'}),((s.prototype=n.extend({},n.fn.tooltip.Constructor.prototype)).constructor=s).prototype.getDefaults=function(){return s.DEFAULTS},s.prototype.setContent=function(){var t=this.tip(),e=this.getTitle(),i=this.getContent();if(this.options.html){var o=typeof i;this.options.sanitize&&(e=this.sanitizeHtml(e),"string"===o&&(i=this.sanitizeHtml(i))),t.find(".popover-title").html(e),t.find(".popover-content").children().detach().end()["string"===o?"html":"append"](i)}else t.find(".popover-title").text(e),t.find(".popover-content").children().detach().end().text(i);t.removeClass("fade top bottom left right in"),t.find(".popover-title").html()||t.find(".popover-title").hide()},s.prototype.hasContent=function(){return this.getTitle()||this.getContent()},s.prototype.getContent=function(){var t=this.$element,e=this.options;return t.attr("data-content")||("function"==typeof e.content?e.content.call(t[0]):e.content)},s.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var t=n.fn.popover;n.fn.popover=function e(o){return this.each(function(){var t=n(this),e=t.data("bs.popover"),i="object"==typeof o&&o;!e&&/destroy|hide/.test(o)||(e||t.data("bs.popover",e=new s(this,i)),"string"==typeof o&&e[o]())})},n.fn.popover.Constructor=s,n.fn.popover.noConflict=function(){return n.fn.popover=t,this}}(jQuery),function(s){"use strict";function n(t,e){this.$body=s(document.body),this.$scrollElement=s(t).is(document.body)?s(window):s(t),this.options=s.extend({},n.DEFAULTS,e),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",s.proxy(this.process,this)),this.refresh(),this.process()}function e(o){return this.each(function(){var t=s(this),e=t.data("bs.scrollspy"),i="object"==typeof o&&o;e||t.data("bs.scrollspy",e=new n(this,i)),"string"==typeof o&&e[o]()})}n.VERSION="3.4.1",n.DEFAULTS={offset:10},n.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},n.prototype.refresh=function(){var t=this,o="offset",n=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),s.isWindow(this.$scrollElement[0])||(o="position",n=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var t=s(this),e=t.data("target")||t.attr("href"),i=/^#./.test(e)&&s(e);return i&&i.length&&i.is(":visible")&&[[i[o]().top+n,e]]||null}).sort(function(t,e){return t[0]-e[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},n.prototype.process=function(){var t,e=this.$scrollElement.scrollTop()+this.options.offset,i=this.getScrollHeight(),o=this.options.offset+i-this.$scrollElement.height(),n=this.offsets,s=this.targets,a=this.activeTarget;if(this.scrollHeight!=i&&this.refresh(),o<=e)return a!=(t=s[s.length-1])&&this.activate(t);if(a&&e<n[0])return this.activeTarget=null,this.clear();for(t=n.length;t--;)a!=s[t]&&e>=n[t]&&(n[t+1]===undefined||e<n[t+1])&&this.activate(s[t])},n.prototype.activate=function(t){this.activeTarget=t,this.clear();var e=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',i=s(e).parents("li").addClass("active");i.parent(".dropdown-menu").length&&(i=i.closest("li.dropdown").addClass("active")),i.trigger("activate.bs.scrollspy")},n.prototype.clear=function(){s(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var t=s.fn.scrollspy;s.fn.scrollspy=e,s.fn.scrollspy.Constructor=n,s.fn.scrollspy.noConflict=function(){return s.fn.scrollspy=t,this},s(window).on("load.bs.scrollspy.data-api",function(){s('[data-spy="scroll"]').each(function(){var t=s(this);e.call(t,t.data())})})}(jQuery),function(r){"use strict";var a=function(t){this.element=r(t)};function e(i){return this.each(function(){var t=r(this),e=t.data("bs.tab");e||t.data("bs.tab",e=new a(this)),"string"==typeof i&&e[i]()})}a.VERSION="3.4.1",a.TRANSITION_DURATION=150,a.prototype.show=function(){var t=this.element,e=t.closest("ul:not(.dropdown-menu)"),i=t.data("target");if(i||(i=(i=t.attr("href"))&&i.replace(/.*(?=#[^\s]*$)/,"")),!t.parent("li").hasClass("active")){var o=e.find(".active:last a"),n=r.Event("hide.bs.tab",{relatedTarget:t[0]}),s=r.Event("show.bs.tab",{relatedTarget:o[0]});if(o.trigger(n),t.trigger(s),!s.isDefaultPrevented()&&!n.isDefaultPrevented()){var a=r(document).find(i);this.activate(t.closest("li"),e),this.activate(a,a.parent(),function(){o.trigger({type:"hidden.bs.tab",relatedTarget:t[0]}),t.trigger({type:"shown.bs.tab",relatedTarget:o[0]})})}}},a.prototype.activate=function(t,e,i){var o=e.find("> .active"),n=i&&r.support.transition&&(o.length&&o.hasClass("fade")||!!e.find("> .fade").length);function s(){o.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),t.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),n?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu").length&&t.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),i&&i()}o.length&&n?o.one("bsTransitionEnd",s).emulateTransitionEnd(a.TRANSITION_DURATION):s(),o.removeClass("in")};var t=r.fn.tab;r.fn.tab=e,r.fn.tab.Constructor=a,r.fn.tab.noConflict=function(){return r.fn.tab=t,this};var i=function(t){t.preventDefault(),e.call(r(this),"show")};r(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',i).on("click.bs.tab.data-api",'[data-toggle="pill"]',i)}(jQuery),function(l){"use strict";var h=function(t,e){this.options=l.extend({},h.DEFAULTS,e);var i=this.options.target===h.DEFAULTS.target?l(this.options.target):l(document).find(this.options.target);this.$target=i.on("scroll.bs.affix.data-api",l.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",l.proxy(this.checkPositionWithEventLoop,this)),this.$element=l(t),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};function i(o){return this.each(function(){var t=l(this),e=t.data("bs.affix"),i="object"==typeof o&&o;e||t.data("bs.affix",e=new h(this,i)),"string"==typeof o&&e[o]()})}h.VERSION="3.4.1",h.RESET="affix affix-top affix-bottom",h.DEFAULTS={offset:0,target:window},h.prototype.getState=function(t,e,i,o){var n=this.$target.scrollTop(),s=this.$element.offset(),a=this.$target.height();if(null!=i&&"top"==this.affixed)return n<i&&"top";if("bottom"==this.affixed)return null!=i?!(n+this.unpin<=s.top)&&"bottom":!(n+a<=t-o)&&"bottom";var r=null==this.affixed,l=r?n:s.top;return null!=i&&n<=i?"top":null!=o&&t-o<=l+(r?a:e)&&"bottom"},h.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(h.RESET).addClass("affix");var t=this.$target.scrollTop(),e=this.$element.offset();return this.pinnedOffset=e.top-t},h.prototype.checkPositionWithEventLoop=function(){setTimeout(l.proxy(this.checkPosition,this),1)},h.prototype.checkPosition=function(){if(this.$element.is(":visible")){var t=this.$element.height(),e=this.options.offset,i=e.top,o=e.bottom,n=Math.max(l(document).height(),l(document.body).height());"object"!=typeof e&&(o=i=e),"function"==typeof i&&(i=e.top(this.$element)),"function"==typeof o&&(o=e.bottom(this.$element));var s=this.getState(n,t,i,o);if(this.affixed!=s){null!=this.unpin&&this.$element.css("top","");var a="affix"+(s?"-"+s:""),r=l.Event(a+".bs.affix");if(this.$element.trigger(r),r.isDefaultPrevented())return;this.affixed=s,this.unpin="bottom"==s?this.getPinnedOffset():null,this.$element.removeClass(h.RESET).addClass(a).trigger(a.replace("affix","affixed")+".bs.affix")}"bottom"==s&&this.$element.offset({top:n-t-o})}};var t=l.fn.affix;l.fn.affix=i,l.fn.affix.Constructor=h,l.fn.affix.noConflict=function(){return l.fn.affix=t,this},l(window).on("load",function(){l('[data-spy="affix"]').each(function(){var t=l(this),e=t.data();e.offset=e.offset||{},null!=e.offsetBottom&&(e.offset.bottom=e.offsetBottom),null!=e.offsetTop&&(e.offset.top=e.offsetTop),i.call(t,e)})})}(jQuery);/**
	* Resources
	* Trilogi Ecommerce http://trilogi.com/
	*
	* Copyright (C)2015 Trilogi Ecommerce S.L.
	* Licence: ???
	*
	* Requires: jQuery.js
	* 
	* Date: 2015-05-04
	*/

/**
	* Search a object position from an Array by abject key and its value
	* @param  {string} key   Object's key
	* @param  {string} value Value of key
	* @return {integer}      position in array. 
	*/
Array.prototype.objectSearch = function(key, value){
		for (var i=0; i < this.length; i++)
				if (typeof this[i] === "object" && this[i][key] == value) return i;
		return -1;
};

function readCookie(k){
		return(document.cookie.match('(^|; )'+k+'=([^;]*)')||0)[2]
};

/**
	* Shortcut getElementBy Id for DOM only on document
	* @param {string} a id
	*/
window.E = function(a){
		return document.getElementById(a);
};

/**
	* Advanced query Selector. 
	* Allows search multiple items and restrict for specified element on DOM.
	*
	* @params: Allows 3 params. See examples
	*
	* @examples *
	* F('span');                   // Returns one (first) span on document
	* F('span', true);             // Returns NodeLsit of all span on document
	* F('span', container);        // Returns one (first) span on container
	* F('span', container, true);  // Returns NodeList of span on container
	*/
window.F = function(){
		var qry = arguments[0] || "";
		var all = false;
		var domE = document;

		if (!qry) return null;

		if(arguments.length == 2 && typeof(arguments[1]) === 'boolean')
				all = arguments[1];
		else if(arguments.length == 2 && typeof(arguments[1]) === 'object')
				domE = arguments[1];
		else if(arguments.length == 3){
				domE = arguments[1];
				all = arguments[2];
		}

		return domE[all?'querySelectorAll':'querySelector'](qry);
};

/**
	* Shortcut for console.log
	*/
window.log = window.console? console.log : function(){};

/**
	* Detects bootstrap
	*/
window.hasBootstrap = function(){
		return typeof $().modal === 'function';
};

/**
	* Move browser to top of page
	* @requires jQuery
	*/
window.toTop = function(){
			$('body,html').animate({scrollTop: 0}, 'slow');
};

/**
	* @class Params encoder for URL
	* 
	* @method addParameter, add parameter to object
	* @method getParameters, return encoded parameters
	* @method clear, clean paramters
	*
	* @property {array} parameters
	*/
window.urlParameterEncoder = function() {
		this.addParameter=function(a,b){
				this.parameters.push(a+"="+b);return this;
		};
		this.getParameters=function(c){
				return (!c||c.toUpperCase()!="POST"? "?" : "") + this.parameters.join('&');
		};
		this.clear=function(){
				this.parameters=[];
		};
		this.clear();
};

	// 20160420BVCM-01
 /**
  * Number.prototype.format((n, x, s, c, p, r)
  * 
  * @param integer n: length of decimal
  * @param integer x: length of whole part
  * @param mixed   s: sections delimiter
  * @param mixed   c: decimal delimiter
  * @param boolean p: symbol position: true->front, false->rear
  * @param boolean r: if enabled remove right zeros
  */
 Number.prototype.formatAsPrice = function(n, x, s, c, p, r) {

     var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
         num = this.toFixed(Math.max(0, ~~n)),
         sep = '%%',
         formatted,
         numericPrice,
         symbol = '<span class="currencySymbol">' + settings.currencies['currency' + settings.currencyId].SYMBOL + '</span>';

     num = num.replace('.', sep).replace(new RegExp(re, 'g'), '$&' + s);

     numericPrice = num.replace(sep, '.');

     num = num.split('%%');

     formatted = '<span content="' + numericPrice + '" class="integerPrice">' + num[0]+'</span>';

     if (n > 0) {
     		var dec = num[1];
     		if (r && Number(dec) > 0){
     				// dec = dec.toString();
     				dec = (dec[1] == 0) ? dec[0] : dec;
     				formatted += '<span class="decimalPrice">' + c + dec + '</span>';  
     		} else if (!r){
     				formatted += '<span class="decimalPrice">' + c + dec + '</span>';  
     		}
     }

     if (p) {
         formatted = symbol + formatted;
     } else {
         formatted = formatted + symbol;
     }

     return formatted;

 };

 outputFormattedCurrency = function(price) {
    
     switch (settings.currencyFormat) {
         /*TODO: create all cases*/
         case "$___,___,___,__0.00":
             price = price.formatAsPrice(2, 3, ',', '.', true);
             break;
         case "___,___,___,__0.00$":
             price = price.formatAsPrice(2, 3, ',', '.', false);
             break;
         case "$___.___.___.__0,00":
             price = price.formatAsPrice(2, 3, '.', ',', true);
             break;
         case "___.___.___.__0,00$":
             price = price.formatAsPrice(2, 3, '.', ',', false);
             break;
         case "0 00$":
             price = price.formatAsPrice(2, 0, '', ' ', false);
             break;
         case "$0 00":
             price = price.formatAsPrice(2, 0, '', ' ', true);
             break;
         case "0$":
             price = price.formatAsPrice(0, 0, '', '', false);
             break;
         case "$0":
             price = price.formatAsPrice(0, 0, '', '', true);
             break;
         case "0 __$":
             price = price.formatAsPrice(2, 0, '', ' ', false, true);
             break;
         case "$0 __":
             price = price.formatAsPrice(2, 0, '', ' ', true, true);
             break;
         case "$___,___,___,__0.__":
             price = price.formatAsPrice(2, 3, ',', '.', false, true);
             break;
         case "___,___,___,__0.__$":
             price = price.formatAsPrice(2, 3, ',', '.', false, true);
             break;
         case "$___.___.___.__0,__":
             price = price.formatAsPrice(2, 3, '.', ',', true, true);
             break;
         case "___.___.___.__0,__$":
             price = price.formatAsPrice(2, 3, '.', ',', false, true);
             break;
         default:
             price = price.formatAsPrice(2, 3, ',', '.', false);
     };
     return price;
 }



Object.getLength = function(obj){return Object.keys(obj).length;};


/**
	* Get style on DOM elements
	* @param  {String} style    Style property
	* @param  {object} elements Optional, default: ALL
	* @return {array}           Array of values from style property on elements.
	*/
window.getStyles = function(style, elements){
		if (!elements) elements = F('*',true);
		var result = [];
		for (var i=0; i < elements.length; i++){
				var $el = $(elements[i]);
				if ($el.css(style)) result.push($el.css(style));
		}
		return result;
};


/**
	* Load web fonrs
	* @param  {string} basePath base path to fonts
	*/
window.loadWebFonts = function(basePath) {
		// Get all font-family parameters for all elements in the document and init other stuff
		var allFonts = getStyles('font-family'),
						baseFonts = ['monospace', 'sans-serif', 'serif', 'cursive', 'helvetica neue', 'fontawesome'],
						webFonts = [],
						cssCode = '';

		// Create an array of unique font families
		allFonts.forEach(function(fonts) {
				fonts.split(',').forEach(function(font) {
						font = font.trim().replace(/'|"/g, '').toLowerCase();

						if(webFonts.indexOf(font) == -1 && baseFonts.indexOf(font) == -1)
								webFonts.push(font);
				});
		});

		if(webFonts.length) {
				// Define font types depending on the client browser
				if (navigator.userAgent.indexOf("Safari") > 0){
						var extension = '.ttf', format = 'truetype';
				}
				else if(navigator.userAgent.indexOf("MSIE") > 0){
								var extension = '.eot', format = 'eot';
				}
				else{
								var extension = '.woff', format = 'woff';
				}

				/* Init font detector by Lalit Patel (http://www.lalit.org/lab/javascript-css-font-detect) */
				var testString = 'mmmmmmmmmmlli',
								testSize = '72px',
								defaultWidth = {},
								defaultHeight = {},
								h = document.getElementsByTagName("body")[0],
								s = document.createElement("span");

				s.style.visibility = 'hidden';
				s.style.fontSize = testSize;
				s.innerHTML = testString;

				for(var index in baseFonts) {
						s.style.fontFamily = baseFonts[index];
						h.appendChild(s);
						defaultWidth[baseFonts[index]] = s.offsetWidth;
						defaultHeight[baseFonts[index]] = s.offsetHeight;
						h.removeChild(s);
				}

				detectFont = function(font) {
						var detected = false;

						for(var index in baseFonts) {
								s.style.fontFamily = font + ',' + baseFonts[index];
								h.appendChild(s);
								var matched = (s.offsetWidth != defaultWidth[baseFonts[index]] || s.offsetHeight != defaultHeight[baseFonts[index]]);
								h.removeChild(s);
								detected = detected || matched;
						}

						return detected;
				};
				/* End font detector by Lalit Patel */

				// Add bootstrap glyphicon when htmlFramework is bootstrap
				if (htmlFramework == 'bootstrap')
						cssCode += '@font-face { font-family: "Glyphicons Halflings";src: url("' + basePath + 'glyphicons-halflings-regular' + extension +'") format("' + format + '"); font-style: normal; font-weight: normal; }\n';

				// Create @font-face declarations for every unique font not detected on the client browser/system
				webFonts.forEach(function(font) {
						if(!detectFont(font))
								cssCode += '@font-face { font-family:"' + font + '"; src:url("'+ basePath + font.replace(/ /g, '-') + extension + '") format("' + format + '"); font-style: normal; font-weight: normal; }\n';
				});


				// Finally, if there's any new @font-face declarations add them to the document
				if(cssCode.length) {
						if (navigator.userAgent.indexOf("Chrome") > 0)
								cssCode = '@media screen { ' + cssCode + ' }';

						var head = document.head || document.getElementsByTagName('head')[0],
										style = document.createElement('style');

						style.type = 'text/css';
						head.appendChild(style);

						if(style.styleSheet) // Workaround for IE
								style.styleSheet.cssText = cssCode;
						else
								style.appendChild(document.createTextNode(cssCode));
				}
		}
};

//determines if a variable is defined an not null
$.defined = function(a){

		if(typeof a === 'undefined')
				return false;
		if(a == null)
				return false;
		return true;

};/*!
 * Fluid Library v1.0.2 | (C) 2019 TLG Commerce | License
 */
/**
 * Fluid JavaScript Library 
 * 
 * @file
 * 
 * @version v1.0.2
 * @author TLG Commerce http://tlgcommerce.com
 * @requires jQuery.js
 * @date 2019-04-15
 */
;
/**
 * Fluid Main
 * @namespace Fluid
 */
var Fluid = window.Fluid = {};

/**
 * Fluid Version
 * @property {string} VERSION Fluid version
 * @memberOf Fluid
 */
Fluid.VERSION = '0.0.1';

/**
 * Fluid Validate Form Configuration
 */
Fluid.validateFormConf = {
  borderColorOnError : '',
  addValidClassOnAll : true,
  scrollToTopOnError : false
};
Fluid.validateFormConf.onError = function ($form) {
  $('.form-message').removeClass('alert alert-success alert-danger').text('');
  if (Fluid.validateFormConf.scrollToTopOnError){
    $('html, body').animate({
      scrollTop: ($('.has-error').offset().top)
    },500);
  }
};

/**
 * Fluid Main Config
 */
Fluid.config = {
  showModalBasket: true,
  showModalComparerBasket: true,
  notify: {
    type : 'notes'
  },
  notifyMode : true
};
Fluid.notifyConf = Fluid.config.notify;

// Fluid Require files
// -----------------------------------------------------------------------------
Fluid.require = {
  /**
   * Fluid.require.css
   * @param  {string} source Path to source
   * @return {void}
   */
  css : function(source){
    var cssfile = document.createElement("link");
    
    cssfile.setAttribute("rel", "stylesheet");
    cssfile.setAttribute("type", "text/css");
    cssfile.setAttribute("href", source);

    if (typeof cssfile!="undefined")
      document.getElementsByTagName("head")[0].appendChild(cssfile);
  },

  /**
   * Fluid.require.js
   * @param  {string} source Path to source
   * @param  {object} options
   * @return {void}
   */
  js : function(source, load){
    // Prepare load
    if (!load) load = function(){};

    // Call
    $.getScript(source, load);
  },

  cachedJs : function( url, options ) {
 
    // Allow user to set any option except for dataType, cache, and url
    options = $.extend( options || {}, {
      dataType: "script",
      cache: true,
      url: url
    });
   
    // Use $.ajax() since it is more flexible than $.getScript
    // Return the jqXHR object so we can chain callbacks
    return jQuery.ajax( options );
  }
};
// FI Fluid Require files ------------------------------------------------------

/**
 * @method Fluid.extend
 * @memberOf Fluid
 *
 * @description
 * This function extends the mixin's functions into our "Class"
 * 
 * Clona un element i el retorna amb les propietats que s'han volgut modificar. 
 * Ideal per a crear objectes Tipus nous
 * 
 * @param  {object} protoProps   Prototype data
 * @param  {object} staticProps  Static properties
 * @return {object} returns      variable
 */
Fluid.extend = function(protoProps, staticProps) {
  var parent = this;
  var child;

  if (protoProps && protoProps.hasOwnProperty('constructor'))
    child = protoProps.constructor;
  else
    child = function(){return parent.apply(this, arguments);};
  
  $.extend(child, parent);
  var Surrogate = function(){ this.constructor = child; };
  Surrogate.prototype = parent.prototype;
  child.prototype = new Surrogate;
  if (protoProps) $.extend(child.prototype, protoProps, staticProps);
  child.__super__ = parent.prototype;

  return child;
};


/**
 * Generate unique integer id (valid only on navigator "request")
 * @param  {number} prefix Prefix name for id
 * @return {string}        Returns uniqueId
 */
Fluid.idCounter = 0;
Fluid.objPrefixes = {};
Fluid.uniqueId = function(prefix) {
  if (prefix in Fluid.objPrefixes)
    Fluid.objPrefixes[prefix]++;
  else
    Fluid.objPrefixes[prefix] = 1;

  // var id = ++Fluid.idCounter + '';
  var id = Fluid.objPrefixes[prefix] + '';
  return prefix ? prefix + id : id;
};

Fluid.carryMethod = function(path, carry) {
  if (!path)
    return false;

  carry = carry || window;
  var arrCall = path.split(".");

  for (var i = 0; i < arrCall.length; i++) {
    if (!carry[arrCall[i]])
      return false;
    
    if (typeof carry[arrCall[i]] === 'function')
      return carry[arrCall[i]];

    carry = carry[arrCall[i]];
  }
  return false;
}

Fluid.pluginEvents = [];

/**
 * @property {object} Fluid.resources It has main prototyping functions 
 * @memberOf Fluid
 */
Fluid.resources = {
  initialize : function(){},

  /**
   * Return parent object (pseudo super)
   * @return {Object} 
   */
  parent : function(){return this.constructor.__super__;},

  /**
   * Super Call
   * @param {string} method Name of method to call
   * @param {any} "noname" Others params are accepted
   * @return {void} Call method directly
   */
  superForm : function(method){
    // Prevent call this method without arguments
    if (!method) return;

    // Get all arguments without the first (method)
    var args = Array.prototype.slice.call(arguments, 1);

    // Get main "class" (super constructor)
    var obj = this.constructor.__super__;

    // Invoke method if exists and is a function
    if(obj && $.isFunction(obj[method]))
      obj[method].apply(this, args);
  },

  /**
   * Trigger Events
   * @param  {String} triggerName Function added on "addEvent" or "addTrigger"
   * @param  {"MULTIPLE"} *       Multiple params... it are not required
   * @return {Boolean}
   */
  trigger : function(triggerName) {
    var result = false;

    // Get function
    var functionTrigger = this["custom_" + triggerName];

    // Arguments
    var args = Array.prototype.slice.call(arguments, 1);

    // Call function
    if(this && $.isFunction(functionTrigger)){
      result = true;
      functionTrigger.apply(this, args);
    }

    return result;
  },

  /**
   * Add Plugin Listener
   * @param  {string} listener Listener name 
   * @param  {Function}  fn   Function to call
   * @return {Boolean}
   */
  addPluginListener : function(listener, method, force) {

    var allowedListeners = ["onAddProduct","onProductClick","setPaymentSystem","setShippingSection","deleteProduct", "beforeSubmitEndOrder", "initializePaymentsBefore", "initializePaymentsCallback"];
    if (allowedListeners.indexOf(listener) < 0)
      return false;

    if (!$.isFunction(method))
      return false;

    if (Fluid.pluginEvents.indexOf(listener) < 0) {
      Fluid.pluginEvents.push(listener);
      Fluid.pluginEvents[listener] = [];
    }

    forceLoad = force || false;
    avt = avoidTrackings || false;
    avoid = forceLoad ? false : avt;
    if (!avoid)
      Fluid.pluginEvents[listener].push(method);
    return true;
  },

  /**
   * Plugin Listener
   * @param  {string} listener Listener name 
   * @param  {"MULTIPLE"} *       Multiple params... it are not required
   */
  pluginListener : function(listener) {

    var allowedListeners = ["onAddProduct","onProductClick","setPaymentSystem","setShippingSection","deleteProduct", "beforeSubmitEndOrder", "initializePaymentsBefore", "initializePaymentsCallback"];
    if (allowedListeners.indexOf(listener) < 0)
      return false;

    if (!Fluid.pluginEvents[listener] || Fluid.pluginEvents.length == 0)
      return false;

    var args = Array.prototype.slice.call(arguments, 1);

    Fluid.pluginEvents[listener].forEach(function(el, index){
      if ($.isFunction(el))
        el.apply(this, args);
    });
  }
};

/**
 * Fluid.Form
 * @class Fluid.Form
 * @memberOf Fluid
 *
 * @param {object} form DOM form
 */
Fluid.Form = function(form){
 //Main vars
  this.name = this.name || 'form';

  //DOM Basic Elements
  this.el = {
    form : form,
    $form : $(form),
  };

  if (this.el.form){
    // Get message container
    this.el.$message = this.el.$form.children('.form-message');

    if (!this.el.$message.length)
      this.el.$message = $('<div />', {
        "class":"form-message"
      }).prependTo(this.el.$form);
    
    // Add Submit event
    if (this.submit)
      this.el.$form.on('submit', this.submit.bind(this));

    // Find Reload captcha and add it an event
    var reloadCaptchas = this.el.$form.find('img.reloadCaptchaImage');

    if (reloadCaptchas.length){
      this.el.$reloadCaptcha = $(reloadCaptchas[0]);
      var captchaData = this.el.$reloadCaptcha.data('captcha');
      this.el.$reloadCaptcha.on('click', this.reloadCaptcha.bind(this, captchaData.position, captchaData.id, captchaData.length));
    }

  }

  //INITIALIZE
  this.initialize.apply(this, [form] );
};

//Extend Public Methods on Fluid.Form
$.extend(true, Fluid.Form.prototype, Fluid.resources,{
  submit : function(event){

    //Get method, continue default event
    if (this.el.form.method.toLowerCase() == 'get')
      return;

    event.preventDefault();

    //Validate form
    if (!this.el.$form.isValid()) return false;

    if (this.el.$form.data("fluidFormdata")) {
      this.postFormData(event);
      return;
    }
    
    //Get form data
    var arrDataForm = this.el.$form.serializeArray();

    //Fills dataForm
    this.dataForm = {};
    for (var i = 0; i < arrDataForm.length; i++){
      if(!(arrDataForm[i].name in this.dataForm))
        this.dataForm[arrDataForm[i].name] = [];

      this.dataForm[arrDataForm[i].name].push(arrDataForm[i].value);
    }

    for (var i in this.dataForm)
      this.dataForm[i] = this.dataForm[i].join();

    //Avoid mutiple submit
    this.el.$form.find('button[type="submit"], input[type="submit"]').attr('disabled',true);

    //Post
    if (this.el.form.method.toLowerCase() == 'post')
      $.post(this.el.form.action, JSON.stringify(this.dataForm), this.onReceive.bind(this), "json")
        .fail(this.onFail.bind(this))
        .always(this.onComplete(this));
  },  

  onFail : function(error){
    // Allow submit
    this.el.$form.find('button[type=submit], input[type=submit]').attr('disabled',false);

    // Callback
    if (this.callback && typeof this.callback === 'function')
      this.callback(error.responseJSON);
  },

  onReceive : function(result){
    // Allow submit
    this.el.$form.find('button[type=submit], input[type=submit]').attr('disabled', false);

    // Callback
    if (this.callback && typeof this.callback === 'function')
      this.callback(result);
  },

  onComplete : function(result){
    // Allow submit
    //this.el.$form.find('button[type=submit], input[type=submit]').attr('disabled', false);
  },

  reloadCaptcha : function(position, element, length){
    if (!this.el.imageCaptcha)
      this.el.imageCaptcha = F('#' + element, this.el.form);

    var objParams = new urlParameterEncoder()
      .addParameter('position',position)
      .addParameter('length',length);

    $.get('/user/reloadCaptcha' + objParams.getParameters(), this.reloadCaptchaCallback.bind(this));
  },

  reloadCaptchaCallback : function(data){
    this.el.imageCaptcha.src = data
  },

  callback : function(result){
    if (typeof result === 'undefined')
      return;

    if (!result.response) {
      var message = result.errorDetail? result.errorDetail : 'Error';
      var success = 0;
    }
    else {
      var message = result.response.MESSAGE;
      var success = result.response.SUCCESS? result.response.SUCCESS : 0;
    }
    this.el.$message.text(message);

    if (success){
      this.el.$message
        .removeClass('alert-danger')
        .addClass('alert alert-success');
    }
    else
      this.el.$message
        .removeClass('alert-success') 
        .addClass('alert alert-danger');
  },

  showMessage : function(message, type, notifyMode){
    if (!type) type = 'danger';
    if (typeof notifyMode !== "boolean") notifyMode = Fluid.config.notifyMode;
    if (notifyMode) Fluid.notify(message, {type:type});
    else this.el.$message.html(message).removeClass('alert-danger alert-success alert-info').addClass('alert alert-'+type); // always remove classes previously
  },

  postFormData: function(event){
    event.preventDefault();

    //Get form data
    var arrDataForm = this.el.$form.serializeArray();

    //Create FormData
    var formData = new FormData(this.el.$form[0]);
    for (var i = 0; i < arrDataForm.length; i++) {
      formData.append(arrDataForm[i].name, arrDataForm[i].value);
    }

    //Check input files length and accept formats.
    var isValidFormInput = true;
    this.el.$form.find("input:file").each(function(index, el){
      if (el.files.length > 0) {
        var suffixes = $(el).data('fluidAccept');
        joinedSuffixes = suffixes.split(',').join('|');
        var re = new RegExp(".*\.(" + joinedSuffixes + ")", "i");
        if (!re.test(el.value)) {
          isValidFormInput = false
          this.showMessage(languageSheet.VALIDEXTENSIONS + ' ' + suffixes.split(',').join(', '))
        }
        maxFileSize = $(el).data('fluidMaxSize');
        if (el.files[0].size/(1024*1024) > maxFileSize) {
          isValidFormInput = false
          this.showMessage(languageSheet.VALIDSIZE + ' ' + maxFileSize +'Mb')
        }
        formData.append(el.name, el.files[0], el.value);
      }

    }.bind(this));

    if (!isValidFormInput) 
      return;

    var callback = this.onReceive.bind(this);

    $.ajax({
      url: this.el.form.action,
      data: formData,
      async: true,
      mimeType: 'multipart/form-data',
      processData: false,
      contentType: false,
      type:'POST',
      success: function(data) {
        callback($.parseJSON(data));
      }
    });   
  }
});

/**
 * Extend Fluid Form for create "superClass"
 */
Fluid.Form.extend = Fluid.extend;

/**
 * @method  Fluid.Form.addMethod
 * @memberOf Fluid.Form
 * @description Add Methods to Form
 * 
 * @param {string} name     Name of method
 * @param {function()} method Function
 * @return {boolean}
 */
Fluid.Form.addMethod = function(name, method){
  if (typeof name !== 'string' || typeof method !== 'function') return false;
  this.prototype["custom_"+name] = method;
  return true;
};

/* Others methods that do the same */
Fluid.Form.addEvent = Fluid.Form.addMethod;
Fluid.Form.addListener = Fluid.Form.addMethod

/**
 * UserForm Resources
 * It has userForm prototyping functions for userForm & userAddressBookForm
 * @property {object} Fluid.userFormResources 
 * @memberOf Fluid
 */
Fluid.userFormResources = {

  /**
   * Ensures this.prefix is filled
   * @return {void}
   */
  getPrefix : function(){
    this.prefix = this.prefix || 'user';
  },

  /**
   * Show fields and prepare validation for different kinds of view, particular
   * business or freelance.
   * @param {number} userType            1:particular, 2:business, 3:freelance
   * @param {array} formFields           array of fields
   * @param {object} fieldsMainContainer DOM container
   */
  setFormFields : function(userType, formFields, fieldsMainContainer){
    // Ensures prefix exists
    this.getPrefix();

    // Initialize vars
    var i, formField, $container, $currentFieldsContainer, fieldInformation, 
        dataValidation, $countriesSelector;


    // Define userType 
    // Set DOM data only when form is userForm or is userAddressBookForm
    if (this.prefix == 'user' || this.prefix == 'userAddressBook') {
      this.el.$form.data('userType', userType);
      if(this.prefix == 'userAddressBook')
        this.el.$userAddressBookTypeField.val(userType);
      else
        this.el.$userTypeField.val(userType);
    }
    // Otherwise, forces userType=1
    else {
      userType = 1;
    }
    this.userType = userType;


    // Remove required fields
    this.removeRequiredFields(formFields, fieldsMainContainer);

    // Destroying  help block
    fieldsMainContainer.find('span.help-block').remove();

    // Destroying old blocks
    fieldsMainContainer.find('div.'+this.prefix+'FormFields').remove();

    // Creating a new fields block
    $currentFieldsContainer = $('<div />', {
      'class':'formFields '+this.prefix+'FormFields'
    }).appendTo(fieldsMainContainer);

    // Iterate formFields
    for(i = 0; i < formFields[userType].length; i++) {

      //Get field information
      fieldInformation = formFields[userType][i];

      // Discriminate "BLOCK"
      if(fieldInformation.name.toUpperCase() == 'BLOCK') {
        $currentFieldsContainer = $('<div />', {
          'class':'formFields '+this.prefix+'FormFields'
        }).appendTo(fieldsMainContainer);
      }
      else {
        // Get DOM elements
        formField = F('#'+this.prefix+fieldInformation.name+'Field');
        $container = $('#'+this.prefix+'Field'+fieldInformation.name+'Container');

        // Check field exists and is required
        if(formField && fieldInformation.required){
          dataValidation = this.setValidationData($(formField), true);
          $(formField).data('validation', dataValidation); //Add validation
          formField.setAttribute('data-validation', dataValidation);
        }

        // Check container exists
        if($container) {
          $container.show();
          $countriesSelector = $('#'+this.prefix+'FieldCountryContainer .countriesSelector');

          if ($countriesSelector.length && $.inArray(fieldInformation.name, ["State","City","Zip"]) >= 0)
            $countriesSelector.append($container);
          else
            $currentFieldsContainer.append($container);
          
          if(fieldInformation.required)
            $container.find('span.required').show();
        }
      } 
    }

    //Country Fields
    if (this.countryUserFields && this.countryUserFields['country'])
      this.setCountryFormFields(this.countryUserFields['country'].state,'country');
  },

  /**
   * Prepare country fields
   * @memberOf Fluid.UserForm
   * @param {number} state     1: visible 0:hidden
   * @param {string} fieldName Name of field
   */
  setCountryFormFields : function(state, fieldName){
    // Check arguments
    if (!fieldName) return;
    if (!state) state = 0; // state 1: visible - 0: hidden

    // Ensures prefix exists
    this.getPrefix();
    
    if (this.countryUserFields) {
      this.countryUserFields[fieldName].state = state;

      if (this.countryUserFields[fieldName].formFields) {
        var countryUserFields = this.countryUserFields[fieldName].formFields;
        for (var i = 0; i < countryUserFields.length; i++) {
          var fieldContainer = F('#'+this.prefix+'Field'+countryUserFields[i]+'Container');
          if (fieldContainer)
            fieldContainer.style.display = state? 'block' : 'none';
        }
      }   
    }
  },

  /**
   * Remove required fields, for each view
   * @memberOf Fluid.UserForm
   * @param  {array} formFields           array of fields
   * @param  {object} fieldsMainContainer DOM element
   */
  removeRequiredFields : function(formFields, fieldsMainContainer){
    // Ensures prefix exists
    this.getPrefix();

    // Init vars
    var i, dataValidation, formField, $formField, $container;

    for (i = 0; i < formFields[0].length; i++) {
      formField = F('#'+this.prefix+formFields[0][i]+'Field');
      $formField = $(formField);
      $container = $('#'+this.prefix+'Field'+formFields[0][i]+'Container');

      if(formField){
        dataValidation = this.setValidationData($formField, false);
        $formField.data('validation', dataValidation);
        formField.setAttribute('data-validation', dataValidation);
        $formField.removeClass('error').css({'borderColor': ''});
      }

      if($container) {
        $container.hide();
        //moving fields
        fieldsMainContainer.append($container);
        $container.find('span.required').hide();
      }
    };
  },

  /**
   * setValidationData
   * @param {object} $formField jQuery DOM Element
   * @param {boolean} required  set required field
   */
  setValidationData : function($formField, required){
    var i, dataValidation, arrElements, arrValidation;

    dataValidation = $formField.data('validation') || "";
    arrElements = ["email", "phone", "vat", "idcard"];
    arrValidation = required? ["required"] : [];

    for (i = 0; i < arrElements.length; i++)
      if (dataValidation.toLowerCase().indexOf(arrElements[i]) >= 0)
        arrValidation.push(arrElements[i]);

    return arrValidation.join(",");
  },

  /**
   * Select Postal Code Callback
   * @param  {String}   type     userInfo | shippingAddress
   * @param  {Function} callback 
   * @return {void}
   */
  selectPostalCodeCallback : function(type, callback){
    if (!$.isFunction(callback))
      return;

    // Type: userInfo | shippingAddress | addressBook
    if (type === 'userInfo')
      localizeEvents.selectPostalCode = callback.bind(this);
    else if (type === 'shippingAddress')
      localizeEvents.selectShippingPostalCode = callback.bind(this);
    else if (type === 'addressBook')
      localizeEvents.selectAddressBookPostalCode = callback.bind(this);
  }
};

/**
 * @class Fluid.MiniBasketClass
 * @memberOf Fluid
 */
Fluid.MiniBasketClass = function(){
  this.el = {};

  this.events = {
    before : null,
    callback : null
  };

  //INITIALIZE
  this.initialize.apply(this);
};

//Extend Public Methods on Fluid.MiniBasketClass
$.extend(true, Fluid.MiniBasketClass.prototype, {
  /**
   * Initialize minibasket
   * @memberOf Fluid.MiniBasketClass
   */
  initialize : function(){
    this.el.$container = $("#miniBasket");
    this.el.$miniBasketContent = this.el.$container.find('#miniBasketContent');
    this.data = this.el.$miniBasketContent.data('minibasket');

    // Add Event
    this.el.$container.on('click',"[data-minibasket-delete]", function(event){
      event.stopPropagation();
      this.deleteItem($(event.currentTarget).data("minibasketDelete"));
    }.bind(this));

    this.initializeQuantityElements();
  },

  initializeQuantityElements : function() {
    try {
      this.el.$container.find('input[data-fluid-quantity]').quantity();
    }
    catch(err) {
      // Pray God's will call quantity plugin
    }

    this.el.quantityElements = this.el.$container.find('input.basketQuantity:text');
    
    // Select box
    if (!this.el.quantityElements.length)
      this.el.quantityElements = this.el.$container.find('select.basketQuantity');

    this.el.quantityElements.on('click', function(ev){
      ev.stopPropagation();
    });

    this.el.quantityElements.on('change', this.onChangeQuantity.bind(this) );
  },

  exists : function() {
    return typeof this.data === 'object';
  },
  
  /**
   * Add events for customize the shop performance
   * @memberOf Fluid.MiniBasketClass
   * @param {String}   name Name of type of function
   * @param {Function} fn   Function to call
   */
  addEvent : function(name, fn){
    if ((name == 'before' || name == 'callback') && fn && typeof fn === 'function')
      this.events[name] = fn;
  },

  /**
  * Change quantity
  * @memberOf Fluid.CheckoutForm
  * @param  {object} eventData
  */
  onChangeQuantity:function(eventData) {
    //Call before
    this.before();

    var data = {};
    data[eventData.currentTarget.name] = eventData.currentTarget.value;

    var qtText = 'quantity-';
    try {
      var inputData = JSON.parse(eventData.currentTarget.name.substring(qtText.length));
      var prodCombinationInput = $('form.buyForm input[data-fluid-product-hash="'+ inputData.productHash +'"]').get(0);
    } catch(e) {
      // not valid JSON
    }

    if(prodCombinationInput){
      var itemForm = prodCombinationInput.closest('form');

      itemForm.module.updateCombinationsFields([inputData.productHash], eventData.currentTarget.value);
      itemForm.module.updateCombinationsFormType();
    }

    $.ajax({
      url: '/minibasket/recalculate/',
      type: 'POST',
      dataType: 'json',
      data: JSON.stringify(data)
    })
    .done(this.oneStepCheckoutRefresh.bind(this))
    .always(this.reload.bind(this));
  },

  /**
   * Refresh minibasket view
   * @memberOf Fluid.MiniBasketClass
   */
  reload : function(callback){
    //Call before
    this.before();

    // force reload changing minibasket data on checkout
    var bodyClasses = $('body').attr('class')
    if($('form.basketForm').length && (bodyClasses.indexOf('fluidContent-basket') != -1 || bodyClasses.indexOf('fluidContent-paymentAndShipping') != -1)){
      $('html,body').animate({ scrollTop: 0 }, 'slow', function(){window.location.reload();} );
    }
    
    //No cache param
    var ncParam = 'nc=' + Math.floor(100 + Math.random() * 899);

    //Action
    if (!this.el.$container) 
      this.el.$container = $("#miniBasket");

    this.el.$container.load('/minibasket?nc='+ncParam+' #miniBasketContent', this.loadComplete.bind(this, callback));
  },

  /**
   * Delete product from minibasket
   * @memberOf Fluid.MiniBasketClass
   * @param  {number} position Product position from minibasket
   */
  deleteItem : function(position){

    //Call before
    this.before();

    //No cache param
    var ncParam = 'nc=' + Math.floor(100 + Math.random() * 899);
    this.deleteProduct = position;

    //Reload minibasket
    if (!this.el.container) this.el.container = $("#miniBasket");
    this.el.container.load('/minibasket?deleteProduct='+this.deleteProduct+'&'+ncParam+' #miniBasketContent', function(){
      this.oneStepCheckoutRefresh();
      this.loadComplete();
    }.bind(this));
  },

  /**
   * Hide minibasket
   * @memberOf Fluid.MiniBasketClass
   * @todo Please, implement this function
   */
  hide : function(){
    //TODO Hide minibasket
  },

  /**
   * Event trigger before post to server
   * @memberOf Fluid.MiniBasketClass
   */
  before : function(){
    if (!this.el.container) 
      this.el.container = $("#miniBasket");

    // Add loadingClass
    this.el.$container.addClass('miniBasketLoading');

    if (this.events.before && typeof this.events.before === 'function')
      this.events.before.bind(this)();
  },

  /**
   * Callback function
   * @memberOf Fluid.MiniBasketClass
   */
  loadComplete : function(callback){
    if (this.el.$container && this.el.$container.hasClass('miniBasketLoading'))
      this.el.$container.removeClass('miniBasketLoading');

    this.el.$miniBasketContent = this.el.$container.find('#miniBasketContent');
    this.data = this.el.$miniBasketContent.data('minibasket');

    var saveBasketForm = this.el.$miniBasketContent.find('form');
    if(saveBasketForm && saveBasketForm.data('fluidForm') == 'saveBasketForm')
      new Fluid.saveBasketForm(saveBasketForm[0]);

    //  Callbacks
    if (this.events.callback && typeof this.events.callback === 'function')
      this.events.callback.bind(this)();

    Fluid.initializeCountdowns();
    Fluid.basketExpiration.checkNewExpirationDate();

    if(this.deleteProduct && this.deleteProduct.length){
      var hashes = this.deleteProduct.split('-');
      this.deleteProduct = '';

      var prodCombinationInput = $('form.buyForm input[data-fluid-product-hash="'+ hashes[0] +'"]').get(0);
      if(prodCombinationInput){
        var itemForm = prodCombinationInput.closest('form');

        itemForm.module.updateCombinationsFields(hashes, 0);
        itemForm.module.updateCombinationsFormType();
      }
    }

    this.initializeQuantityElements();

    if (callback && typeof callback === 'function'){
      callback();
    }
  },

  /**
   * On Recieve
   * @memberOf Fluid.MiniBasketClass
   */
  onReceive : function(result){
    if (!this.el.container) 
      this.el.container = $("#miniBasket");

    this.el.container.replaceWith(result);
      
    //Update this.el.container
    this.el.container = $("#miniBasket");

    if (this.events.callback && typeof this.events.callback === 'function')
      this.events.callback(result);
  },

  oneStepCheckoutRefresh : function(){
    if (this.oneStepCheckoutCallback && typeof this.oneStepCheckoutCallback === 'function')
      this.oneStepCheckoutCallback(this);
  }
});

// Generate miniBasket Object
/**
 * Fluid.miniBasket
 * @type {Fluid.MiniBasketClass}
 */
Fluid.miniBasket = new Fluid.MiniBasketClass();

/**
 * @class Fluid.comparerBasketClass
 * @memberOf Fluid
 */
Fluid.comparerBasketClass = function(){
  this.nameId = "#comparerBasket",
  this.nameContentId = "#comparerBasketContent",
  this.nameContentLayerId = "#comparerBasketLayer",
  this.el = {};

  this.events = {
    before : null,
    callback : null
  };

  //INITIALIZE
  this.initialize.apply(this);
};

//Extend Public Methods on Fluid.comparerBasketClass
$.extend(true, Fluid.comparerBasketClass.prototype, {
  /**
   * Initialize comparerBasket
   * @memberOf Fluid.comparerBasketClass
   */
  initialize : function(){
    this.el.$container = $(this.nameId);
    this.el.$comparerBasketContent = this.el.$container.find(this.nameContentId);

    // Add Event
    this.el.$container.on('click',"[data-comparer-basket-delete]", function(event){
      event.stopPropagation();
      this.deleteItem($(event.currentTarget).data("comparerBasketDelete"));
    }.bind(this));
  },

  /**
   * Add events for customize the shop performance
   * @memberOf Fluid.comparerBasketClass
   * @param {String}   name Name of type of function
   * @param {Function} fn   Function to call
   */
  addEvent : function(name, fn){
    var boolCheckEventName = (name == 'before' || name == 'callback' || name == "beforeReloadBadge" || name == "callbackReloadBadge");
    if (boolCheckEventName && fn && typeof fn === 'function')
      this.events[name] = fn;
  },

  /**
   * Refresh notificationComparer view
   * @memberOf Fluid.comparerBasketClass
   */
  reload : function(){
    //Call before
    this.before();

    // Reload Container
    if (!this.el.$container) this.el.$container = $(this.nameId);

    this.el.$container.load('/comparerBasket ' + this.nameId, this.loadComplete.bind(this));
  },

  /**
   * Refresh notificationComparer view
   * @memberOf Fluid.comparerBasketClass
   */
  reloadBadge : function(intQtItems){    
    //Actions
    if (this.events.beforeReloadBadge && typeof this.events.beforeReloadBadge === 'function')
      this.events.beforeReloadBadge.bind(this)(intQtItems);

    $("#comparerNotificationBasket").find(".badge").html(intQtItems);

    if (this.events.callbackReloadBadge && typeof this.events.callbackReloadBadge === 'function')
      this.events.callbackReloadBadge.bind(this)(intQtItems);
  },

  /**
   * Delete product from notificationComparer
   * @memberOf Fluid.comparerBasketClass
   * @param  {number} position Product position from minibasket
   */
  deleteItem : function(productId){
    //Call before
    this.before();

    //Reload minibasket
    if (!this.el.$container) this.el.$container = $(this.nameId);
    this.el.$container.load('/comparerBasket?productId=' + productId + " " + this.nameContentId, this.loadComplete.bind(this));
  },

  /**
   * Display comparerbasket
   * @memberOf Fluid.comparerBasketClass
   */
  display : function(){
    //TODO Hide minibasket
    $(this.nameContentLayerId).addClass('open');
  },

  /**
   * Hide comparerbasket
   * @memberOf Fluid.comparerBasketClass
   */
  hide : function(){
    //TODO Hide comparerbasket
    $(this.nameContentLayerId).removeClass('open');
  },

  /**
   * Event trigger before post to server
   * @memberOf Fluid.comparerBasketClass
   */
  before : function(){
    if (!this.el.$container) this.el.$container = $(this.nameId);

    if (this.events.before && typeof this.events.before === 'function')
      this.events.before.bind(this)();
  },

  /**
   * Callback function
   * @memberOf Fluid.comparerBasketClass
   */
  loadComplete : function(){
    this.el.$comparerBasketContent = this.el.$container.find(this.nameContentId);

    // var intItemsCount = this.el.$comparerBasketContent.find("[data-comparer-basket-delete]").length;
    var intItemsCount = $("#comparerNotificationBasket").data("comparerBasketItems");
    this.reloadBadge(intItemsCount);

    if (this.events.callback && typeof this.events.callback === 'function')
      this.events.callback.bind(this)();
  }
});

// Generate comparerBasket Object
/**
 * Fluid.comparerBasket
 * @type {Fluid.comparerBasketClass}
 */
Fluid.comparerBasket = new Fluid.comparerBasketClass();


Fluid.setConfirmOrder = function(element){
  $el = $(element);
  var data = $el.data('fluidConfirmorder');
  
  $el.load('/checkout/setConfirmOrder/?'+data, {}, function(result, status, xhrResponse){} );
}

Fluid.initializeIncrementCounter = function(){  
  var listIds = [];
  $('[data-fluid-incrementCounter-data]').each(function(){
    var info = $(this).data("fluid-incrementcounter-data")
    switch(info.type){
      case 1: //take all id's to count the impressions
        if(!listIds.hasOwnProperty(info.item)){
          listIds[info.item] = info.id + ","
        }
        else{
          listIds[info.item] += info.id + ","
        }
        break;

      case 2: //add the event click to count the clicks and redirect to a URL
        $(this).on('click mousedown', function(e){
          e.preventDefault();
          if(e.type == 'mousedown' && e.which == 1){//to prevent double event and double click counter
            return;
          }
          var redirect = 0;
          if( e.which == 1 ) { //only redirect if the click is with the left mouse button
            redirect = 1;
          }
          var url = "/incrementCounter/" + info.type + "/" + info.id + "/" + info.item + "/" + redirect + "?target=" + encodeURIComponent($(this).attr("href"));
          
          if(redirect){
            $(location).attr('href',url);  
          }
          else{
            $.get(url, function(){});//get doing ajax to don't reload the nav
          }
        });
        break;

      default:
    }
  });
  
  for (var key in listIds){
    if(listIds.hasOwnProperty(key) && listIds[key].length){
      Fluid.objIncrementCounter(1, listIds[key], key);
    }
  }
}

Fluid.initializeCountdowns = function(){

  if(!('localServerOffsetTime' in settings))
    settings.localServerOffsetTime = moment().unix() - moment(settings.serverTime).unix();

  // Initialize Product Count Down
  $('[data-fluid-countdown]').each(function(index, element) {
    new Fluid.productCountDown(element.id);
  });

  $(document.body).removeClass('basket-check-availability');
  $('[data-lock-countdown]').each(function(index, element) {
    if(!element.basketLockCountDown)
      element.basketLockCountDown = new Fluid.basketLockCountDown(element);
  });

  $('[data-basket-expires]').each(function(index, element) {
    if(!element.basketCountDown)
      element.basketCountDown = new Fluid.basketCountDown(element);
  });

}

/**
 * Fluid jQuery Interactor.
 * Generate plugin for DOM interactions
 * 
 * @method Fluid.fn
 * @memberOf Fluid
 *
 * @param {string} name Name of plugin
 * @param {object} o Object of plugin
 * 
 * @example
 *    //Create plugin:
 *    Fluid.fn('pluginName',{
 *      options : {
 *        enableAnimations : true,
 *      },
 *      Constructor : function(element, options){
 *
 *        //Public methods
 *        this.init = function() { // it is not necessary
 *          //initialize
 *        };
 *
 *        // This public method, also removes his dataset.
 *        this.destroy = function() {
 *          element.remove();
 *        };
 *        this.clean = function() {
 *          element.html('');
 *        };
 *
 *        //Private methods
 *        function _dummy(){
 *          //I will return nothing.
 *        };
 *      }
 *    });
 *
 *    // Initialize
 *    $('#element').pluginName();
 *
 *    // Destroy or call other public methods
 *    $('#element').pluginName('destroy'[, func arguments]);
 */
Fluid.fn = function(name, o) {
  ;(function($) {

    o.options = $.extend(o.options, {});

    if (!o.Constructor || typeof o.Constructor !== 'function'){
      throw 'Constructor is not defined!';
      return;
    }
  
    //Create plugin
    $.fn[name] = function(options) {

      //Clone object
      // Object Deep copy (Also you can use JSON.parse(JSON.stringify(o.options))); but then you'll lose the functions
      var defaults = $.extend(true, {}, o.options);

      // method calling
      if( typeof options === 'string') {
        var args = Array.prototype.slice.call(arguments, 1);
        var res;
        this.each(function() {
          var obj = $.data(this, name);
          if(obj && $.isFunction(obj[options])) {
            var r = obj[options].apply(obj, args);
            if(res === undefined) res = r;
            if(options == 'destroy') $.removeData(this, name);
          }
          else if(obj && obj[options]) res = obj[options];
        });
        if(res !== undefined) return res;

        return this;
      }
      options = $.extend(defaults, options || {});
        
      this.each(function(i, _element) {
        var element = $(_element);
        // Object Deep copy (Also you can use JSON.parse(JSON.stringify(options))); but then you'll lose the functions
        var obj = new o.Constructor(element,  $.extend(true, {}, options));

        element.data(name, obj);

        if (obj.init && typeof obj.init === 'function')
          obj.init();
      });
      return this;
    };
  })(jQuery);
};

/**
 * @class  Fluid.Queue (FIFO)
 * @memberOf Fluid
 */
Fluid.Queue = function(){
  /**
   * lst Variable List
   * @type {Array}
   */
  var lst = [];

  /**
   * Returns queue
   * @return {Array}
   */
  this.getQueue = function(){
    return lst;
  };

  /**
   * Cleans queue
   * @return {Boolean}
   */
  this.clear = function(){
    lst = [];
    return true;
  };

  /**
   * Enqueues item to list
   * @param  {any} item
   * @return {Boolean}


  for (var i=0; i<length; i++)

  auxLst.push({item:item, priority:priority});



   */
  this.enqueue = function(item, priority){
    if(priority == null) priority = 0;

    if(lst.length){
      var auxLst = [];

      while (this.size()){
        if(lst[0].priority > priority){
          break;
        }

        auxLst.push(lst.shift());
      }

      auxLst.push({item:item, priority:priority});

      for (var i=0; i>lst.length; i++){
        auxLst.push(lst[i]);
      }

      lst = auxLst;
    }else{
      lst.push({item:item, priority:priority});
    }

    return true;
  };

  /**
   * Dequeues item from list and returns it
   * @return {any}
   */
  this.dequeue = function(){
    return lst.pop();
  };

  /**
   * Destacks item from list and returns it
   * @return {any}
   */
  this.destack = function(){
    return lst.shift();
  };

  /**
   * Iterate queue without dequeue it. Each item is lanched by callback
   * @param  {Function} c Callback function
   * @return {void}
   */
  this.iterate = function(c){
    if (c && typeof c === 'function')
      for (var i = 0; i < lst.length; i++)
        c(lst[i].item);
  };

  /**
   * Returns size of list
   * @return {Integer}
   */
  this.size = function(){
    return lst.length;
  };
};

/**
 * Create Queue object to queue functions for call on domready
 * @type {Fluid.Queue}
 */
Fluid.initQueue = new Fluid.Queue();

/**
 * Call queued functions on document ready
 */

$(document).ready(function() {
  while (Fluid.initQueue.size()) {
    Fluid.initQueue.destack().item.apply();
  }
});

//------------------------------------------------------------------------------
// FI. No afegir res al final del document. Posem-ho a on toqui :)
//------------------------------------------------------------------------------
;/**
 *  Classes que extenen de Fluid.Form
 */

/**
 * @class Fluid.PackBuyForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.PackBuyForm = Fluid.Form.extend({
  name : 'PackBuyForm',
  options : {},
  visibleStock : 0,
  /**
   * Initialize
   * @memberOf Fluid.BuyForm
   */
  initialize:function(form){

    if(this.el.form.initialized)
      return;
    
    this.el.form.initialized = true;

    this.trigger('initializeBefore');

    this.data = JSON.parse(this.el.$form.attr("data-pack"));
    this.quantityField = this.el.$form.find('input[data-fluid-field="quantity"]').get(0);
    this.alternativeImageField = this.el.$form.find('input[data-fluid-field="alternativeImage"]').get(0);
    this.vinculatedProductsField = this.el.$form.find('input[data-fluid-field="vinculatedProducts"]').get(0);

    this.el.$buyFormSubmit = this.el.$form.find('button[type="submit"]');

    this.callback = this.callback.bind(this);

  },

  getFormData:function(){
    return {
      id:this.data.id,
      quantity:this.quantityField ? this.quantityField.value : 1,
      alternativeImage:this.alternativeImageField ? this.alternativeImageField.value : '',
      vinculatedProducts:this.vinculatedProductsField ? this.vinculatedProductsField.value : ''
    };
  },

  submit : function(event) {
    event.preventDefault();

    // Before trigger
    this.trigger('submitBefore', event);

    if(!this.el.$form.isValid())
      return false;

    $.post('/basket/addPack/', JSON.stringify([this.getFormData()]), this.callback , 'json');

    // Disable buy button
    this.el.$buyFormSubmit.prop('disabled', true);

    // Callback trigger
    this.trigger('submitCallback', event);
  },

  callback:function(result){

    // Reload minibasket
    Fluid.miniBasket.reload();
    // Enable buy button
    this.el.$buyFormSubmit.prop('disabled', false);

    if(window.TEA && result.response.basket)
      TEA.updateBasket(result.response.basket);

    if (Fluid.config.showModalBasket && (settings.isMobile == 1 || window.innerWidth < 992)){
      var buttonClass = htmlFramework == 'bootstrap' ? ' btn btn-default btn-block' : 'modalBasketEndOrderButton';
      var submitButtonClass = htmlFramework == 'bootstrap' ? ' btn-primary' : '';
      var localPath = (settings && settings.checkoutPath)? settings.checkoutPath : "/checkout/basket";
      var modalContent = '';
      if(result.response.stockLock){
        modalContent += '<div class="basketCountdown" data-basket-expires=\'{"expires":'+result.response.stockLock.expires+'}\'><div class="active">'+languageSheet.LOCKEDSTOCKREMAININGTIME+'</div><div class="expired">'+languageSheet.LOCKEDSTOCKEXPIREDTIME+'</div></div>';
      }
      modalContent += '<div id="modalBasketButtons"><a href="' + localPath + '" class="modalBasketEndOrder' + buttonClass + submitButtonClass + '">'+ languageSheet.BASKETENDORDER + '</a><a data-dismiss="modal" class="modalBasketContinueShopping' + buttonClass + '">' + languageSheet.BASKETCONTINUESHOPPING + '</a><a href="/user" class="modalBasketMyAccount' + buttonClass + '">' + languageSheet.MYACCOUNT + '</a></div>'

      this.el.$buyFormSubmit.box({
        uid : 'mobileBasketModal',
        source: modalContent,
        showFooter : false,
        triggerOnClick : false,
        type : 'text'
      });
    }
  }
});

/**
 * @class Fluid.BuyForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 * @description Form extended from Fluid.Form
 */
Fluid.BuyForm = Fluid.Form.extend({
  name : 'buyForm',
  options : {},
  visibleStock : 0,
  /**
   * Initialize
   * @memberOf Fluid.BuyForm
   */
  initialize:function(form){

    if(this.el.form.initialized)
      return;
    
    this.el.form.initialized = true;
    this.el.form.module = this;

    this.data = JSON.parse(this.el.$form.attr("data-product"));
    this.quantityField = this.el.$form.find('input[data-fluid-field="quantity"]').get(0);
    this.alternativeImageField = this.el.$form.find('input[data-fluid-field="alternativeImage"]').get(0);
    this.vinculatedProductsField = this.el.$form.find('input[data-fluid-field="vinculatedProducts"]').get(0);
    this.addVinculated = this.el.$form.find('input[data-fluid-field="addVinculated"]').get(0);
    this.disallowGrid = $(this.el.$form.find('input[name="disallowGrid"]').get(0)).val();
    if(!this.disallowGrid){
      this.disallowGrid = false;
    }

    // Before trigger
    this.trigger('initializeBefore');

    if (!this.quantityField){
      this.quantityField = this.el.$form.find('input[name=quantity]').get(0);
    }else{
      this.quantityField = this.el.$form.find('select[name=quantity]').get(0);
    }

    this.el.$priceByQuantityBox = this.el.$form.find('div.priceByQuantity');
    /*adding 1 unit prices to price by quantity*/
    this.data.priceByQuantity.unshift({from:1, optionValueId:0, basePrice:this.data.definition.productBasePrice, retailPrice:this.data.definition.productRetailPrice});

    // Stock Alerts
    var productSubscribe = $('#productSubscribeStock' + this.data.id);

    //20160701BVFL-01
    if (!this.stockSubscriptionForm && productSubscribe.length > 0) {
      this.stockSubscriptionForm = {};
      this.stockSubscriptionForm.$htmlModule = productSubscribe;
      this.stockSubscriptionForm.$form = productSubscribe.find('Form');
      this.stockSubscriptionForm.data = this.stockSubscriptionForm.$form.data('productStock');
    }

    this.productAvailabilities = [];
    if(this.data.availabilityId && productAvailabilities['availability'+this.data.availabilityId])
      this.productAvailabilities = productAvailabilities['availability'+this.data.availabilityId];
    
    this.el.$productOptionAttachment = this.el.$form.find('div.fluidProductOptionAttachment');

    this.callback = this.callback.bind(this);
    this.initOptions();

    // Init trigger
    this.trigger('init');

    // Wishlist 
    this.el.$wishlist = this.el.$form.find('[data-wishlist]');
    if (this.el.$wishlist)
      this.wishlist(); // Initialize

    // Delete wishlist item
    this.el.$wishlistItems = this.el.$form.find('[data-wishlist-item]');
    if (this.el.$wishlistItems.length)
      this.el.$wishlistItems.on('click', this.deleteWishlistItem.bind(this));

    // available discounts
    this.el.$availableDiscounts = this.el.$form.find('button.productDiscountsButton');
    if (this.el.$availableDiscounts)
      this.el.$availableDiscounts.on('click', this.availableDiscounts.bind(this));

    //Init calendar
    //$(this.el.form).find('input[rel="calendarField"]').ionDatePicker();

    var dateFields = this.el.$form.find('div[data-datetimepicker]').each(function(index,el) {
      var $calendar = $(el);

      // Options
      var language = $calendar.data('language');
      var format = $calendar.data('format');
      var startDate = $calendar.data('startdate');
      var endDate = $calendar.data('enddate');

      $calendar.datetimepicker({
        locale : language ? language : 'en',
        format : format ? format : 'DD/MM/YYYY',
        startDate : startDate,
        endDate : endDate
      });

    });

    // Callback trigger
    this.trigger('initializeCallback');

    //Pseudo Buttons
    this.el.$pseudoSubmits = this.el.$form.find('[data-fluid-formButton="addSpecialProduct"]');
    this.el.$pseudoSubmits.on('click', function(e){
      e.preventDefault();
      this.custom_callback = function(){
       $('html,body').animate({ scrollTop: 0 }, 'slow', function(){ window.location.reload(); });
      }
      this.submit(e);
    }.bind(this));

    this.el.$ePointsSubmits = this.el.$form.find('[data-fluid-formButton="ePointsPurchase"]');
    this.el.$ePointsSubmits.on('click', [this], function(e){
      e.preventDefault();

      this.ePointId = $(e.currentTarget).data('fluidEpointspurchase').ePointId;
      this.submit(e);
    }.bind(this));

    if (typeof pgSDK != "undefined") {
      try {
        pgSDK.simulator.reload(pgid);
      } catch (err) {}
    }
  },

  /**
   * Init options
   * @memberOf Fluid.BuyForm
   */
  initOptions:function() {
    // Before trigger
    this.trigger('initOptionsBefore');

    // get combination grid quantity inputs
    this.el.$gridCombinations = this.el.$form.find('input[data-fluid-product-hash][name^=quantity-]');

    if(this.el.$productOptionAttachment.length)
      this.attachmentFields(this.el.$productOptionAttachment);
  
    this.el.$gridOption = this.el.$form.find('[data-fluid-grid-options]');
    if(this.el.$gridOption.length){
      var num = this.el.$gridOption.data('fluid-grid-options');

      if (num == 1){
        this.el.gridOptionsIds = [this.el.$gridOption.data('fluid-product-option').id];
        this.el.gridOptionValues1 = this.el.$form.find('.gridOptionsInfo').data('grid-options1');

      } else {
         this.el.gridOptionsIds = [this.el.$gridOption.data('fluid-product-option').id1,this.el.$gridOption.data('fluid-product-option').id2];
         this.el.gridOptionValues1 = this.el.$form.find('.gridOptionsInfo').data('grid-options1');
         this.el.gridOptionValues2 = this.el.$form.find('.gridOptionsInfo').data('grid-options2');
      }
    }

    this.el.$options = this.el.$form.find('select.productOptionSelectValue, input.productOptionRadioValue, input.productOptionCheckboxValue, input.productOptionBooleanValue, input.productOptionTextValue, textarea.productOptionLongTextValue, input.productOptionDateValue');
    this.el.$options.change(this.changeOption.bind(this));

    this.el.$form.find('img.productOptionValueImage').each( function(a,b){
      $(this).click(function(a,b,c){
        $(a.target).parent('label').click();
      });
    });

    if (typeof this.quantityField === 'undefined') {
      this.quantityField = this.el.$form.find('select[name=quantity]').get(0);
    }

    $(this.quantityField).change(this.changeQuantity.bind(this)); // Change event quantity

    /*getting required options*/
    this.requiredOptions = [];
    this.requiredGridOptions = [];
    for (var option in this.data.options) {
      if (this.data.options[option].required) {
        if ([10].indexOf(this.data.options[option].valueType) > -1) {
          this.requiredOptions.push(this.data.options[option].id);
        } else {
          var showAsGrid = this.data.options[option].showAsGrid && !this.disallowGrid;
          if ([3,4,5,6,7].indexOf(this.data.options[option].valueType) > -1 && !showAsGrid)
            this.requiredOptions.push(this.data.options[option].id);
          else if ([3,4,5,6,7].indexOf(this.data.options[option].valueType) > -1 && showAsGrid)
            this.requiredGridOptions.push(this.data.options[option].id);
        }
      }
      /*adding 1 unit prices to price by quantity*/
      for (var key in this.data.options[option].values) {
        var optionValue = this.data.options[option].values[key];
        this.data.priceByQuantity.unshift({from:1, optionValueId:optionValue.id, basePrice:optionValue.basePrice, retailPrice:optionValue.retailPrice});
      }
    }

    if (this.el.$gridOption.length != 0) {
      //When there are grid options
      this.el.$gridOptions = this.el.$form.find('input.productGridQuantityValue');
      this.el.$gridOptions.change(this.changeGridOption.bind(this));

      this.el.$options.change(this.changeGridOption.bind(this));
    }

    if (this.el.$gridCombinations.length != 0){
      //When there are grid combinations
      if(this.quantityField)
        this.quantityField.remove();

      this.el.$gridCombinations.change(this.changeGridCombinations.bind(this));
      this.el.$gridCombinationsType = this.el.$form.find('input[name=gridCombinationsType]');
    }

    this.onChange(true);

    this.el.$form.find('input.productOptionRadioValue:checked').parent('div.productOptionRadioValue').addClass('productOptionSelected');
    this.el.$form.find('input.productOptionCheckboxValue:checked').parent('div.productOptionCheckboxValue').addClass('productOptionSelected');

    // Callback trigger
    this.trigger('initOptionsCallback');
  },

  /**
   * Change grid options
   * @memberOf Fluid.BuyForm
   * @param  {object} eventData 
   */
  changeGridOption:function(eventData) {
    this.trigger('changeOptionBefore');

    // Callback trigger
    this.trigger('changeOptionCallback', eventData.target);

    this.onChange();
  },

  /**
   * Change grid combinations
   * @memberOf Fluid.BuyForm
   * @param  {object} eventData 
   */
  changeGridCombinations:function(eventData) {
    this.trigger('changeCombinationBefore');

    // Callback trigger
    this.trigger('changeCombinationCallback', eventData.target);

    this.onChange();
  },

  /**
   * Change options
   * @memberOf Fluid.BuyForm
   * @param  {object} eventData 
   */
  changeOption:function(eventData) {
    // Before trigger
    this.trigger('changeOptionBefore');

    if( $(eventData.target).hasClass('productOptionRadioValue') )
    {
      $(eventData.target).parents('div.productOptionValues').find('div.productOptionRadioValue').removeClass('productOptionSelected');
      $(eventData.target).parent('div.productOptionRadioValue').addClass('productOptionSelected');
    }

    if( $(eventData.target).hasClass('productOptionCheckboxValue') )
    {
      if(eventData.target.checked)
        $(eventData.target).parent('div.productOptionCheckboxValue').addClass('productOptionSelected');
      else
        $(eventData.target).parent('div.productOptionCheckboxValue').removeClass('productOptionSelected');
    }

    if( $(eventData.target).hasClass('productOptionAttachmentValue') )
      this.uploadFile(eventData.target);

    // Callback trigger
    this.trigger('changeOptionCallback', eventData.target);

    this.onChange(true);
  },

  /**
   * Change quantity
   * @memberOf Fluid.BuyForm
   * @param  {object} eventData
   */
  changeQuantity:function(eventData) {

    var quantityValue = $(this.quantityField).val();
    // Before trigger
    this.trigger('changeQuantityBefore');

    this.quantityField.value = quantityValue;

    // Callback trigger
    this.trigger('changeQuantityCallback', {quantity:quantityValue});

    this.onChange(true);
  },

  /**
   * Get form values
   * @memberOf Fluid.BuyForm
   */
  getFormValues:function() {
    var formValues;

    if (this.el.$options.length) { /*product detail (options in form)*/
      formValues = this.el.$options.serializeArray();
    } else { /*list of products (default options selection)*/

      formValues = [];
      var selectedOptions = [];

      /*getting first available combination*/
      if (settings.stockManagement && this.data.definition.stockManagement) {
        for (var key in this.data.stocks) {
          if (this.data.stocks[key] > 0) {
            var optionValues = key.split('_');
            if (optionValues.length == 1) {
              break;
            }
            optionValues = optionValues[1].split('-');

            for (var i=0; i<optionValues.length; i++) {
              for (var option in this.data.options) {
                if (this.data.options[option].values['id'+optionValues[i]]) { /*found option + value*/
                  var showAsGrid = this.data.options[option].showAsGrid && !this.disallowGrid;
                  if (!showAsGrid) {
                    formValues.push( {name:'optionValue'+this.data.options[option].id, value:optionValues[i]} );
                    selectedOptions.push(this.data.options[option].id);
                  }
                }
              }
            }
            break;
          }
        }
      }

      var requiredOptions = [];
      for (var i=0; i<this.requiredOptions.length; i++) {
        if (selectedOptions.indexOf(this.requiredOptions[i]) == -1) {
          requiredOptions.push(this.requiredOptions[i]);
        }
      }

      for (var i=0; i<requiredOptions.length; i++) {
        for (var value in this.data.options['id'+requiredOptions[i]].values) {
          formValues.push( {name:'optionValue'+requiredOptions[i], value:this.data.options['id'+requiredOptions[i]].values[value].id} );
          break;
        }
      }
    }

    if (this.el.$productOptionAttachment.length) {
      var attachedFile = this.el.$form.find('input.productOptionAttachmentValue,input:hidden').serializeArray();
      for(var i=0; i<attachedFile.length; i++) 
        formValues.push(attachedFile[i]);
    }

    return formValues;
  },

  updateEpointsView : function(price) {
    if ($('#productEpointsLayer').length == 0) return;

    var updateEpointsViewCallback = function (response) {
        $('#productEpointsLayer').html(response);
    };

    var getProductEpointsURL = '/product/' + this.data.id + '/epoints/';
    $.post(getProductEpointsURL, JSON.stringify({productPrice:price}), updateEpointsViewCallback, 'html');
  },

  updateButton : function(button, properties) {
    button.removeClass('selectOption notAvailable reserve buy notEnoughEpoints');
    button.addClass(properties.className);
    button.prop('disabled', properties.disabled);
    button.data( 'buyFormSubmitName', properties.name);

    if (button.data('showlabel') == 1) button.html(properties.name);
    else button.html("");
  },

  updateChatBasket : function(data) {
    
    if(!window.objChat) return;
    else if(!objChat.updateBasket) return;
    else if(!data.response) return;

    objChat.updateBasket(data.response);
  },

  /**
   * On change
   * @memberOf Fluid.BuyForm
   */
  getPagaMasTarde : function(price, productId) {
    if ($('#buyForm' + productId + ' .PmtSimulator').length && !isNaN(price)) {

      var simulatorPVP = $('#buyForm' + productId + ' .simulatorPVP');
      if (simulatorPVP.html() == price) {
        return;
      }

      simulatorPVP.html(price);
      $('#buyForm' + productId + ' .PmtSimulator').attr('data-pmt-amount',price);

      if (typeof pgSDK != "undefined") {
        try {
          pgSDK.simulator.update(pgid);
        } catch (err) {}
      }
    }
  },

  updateSequra : function(price, productId) {
    if (price <= 0)
      return false;

    $('#buyForm' + productId + ' .sequra-promotion-widget').attr('data-amount', Math.round(price * 100) );
    if (typeof Sequra != "undefined") {
      try {
        Sequra.refreshComponents();
      } catch (err) {}
    }
  },

  updateAplazame : function(price, productId) {
    if (price <= 0)
      return false;

    $('#buyForm' + productId + ' .aplazame-widget').attr('data-amount', Math.round(price * 100) );
  },  

  /**
   * On change
   * @memberOf Fluid.BuyForm
   */
  onChange: function(baseStockForSubscription) {
    var selectedOptions = [];
    var selectedValues = [];
    var selectedStockValues = [];
    var optionId, optionValueId, currentOption;
    var baseStockForSubscription = baseStockForSubscription || false;

    // Before trigger
    this.trigger('onChangeBefore', formValues);

    this.setOptionRestrictions();

    var formValues = this.getFormValues();
    var quantityValue = $(this.quantityField).val();

    if(!quantityValue) quantityValue = 1;

    var validateCombinationStock = true;

    if (this.el.$gridCombinations.length != 0) {
      validateCombinationStock = false;
    }
    else if (this.el.$gridOptions) {
      var gridOptions = [];
      var totalQty = 0;
      validateCombinationStock = false;
      for(var i=0; i<this.el.$gridOptions.length; i++) {
        var $e = $(this.el.$gridOptions[i]);
        var qty = $e.val();
        gridOptions.push($e.attr('name'));
        if ($.isNumeric(qty) && qty > 0)
          totalQty += qty;

      }
    }

    for(var i=0; i<formValues.length; i++) {
      optionId = formValues[i].name.replace('optionValue', '');
      optionValueId = formValues[i].value;
      currentOption = this.data.options['id'+optionId];
      if (currentOption && Object.getLength(currentOption.values)) {
        var showAsGrid = currentOption.showAsGrid && !this.disallowGrid;

        if (showAsGrid) // set quantity to 0 if some option is in grid
          quantityValue = 0;

        if (currentOption.values['id'+optionValueId] && !showAsGrid) {
          selectedOptions.push(parseInt(optionId));
          selectedValues.push(currentOption.values['id'+optionValueId]);
          selectedValues[selectedValues.length-1].uniquePrice = currentOption.uniquePrice;
          if (currentOption.combinable)
            selectedStockValues.push( parseInt(optionValueId) );
        }
      } else {
        selectedOptions.push(parseInt(optionId));
      }
    }

    selectedStockValues = selectedStockValues.sort( function(a, b) {return a-b} ).join('-');

    var requiredOptions = [];
    for (var i=0; i<this.requiredOptions.length; i++) {
      if (selectedOptions.indexOf(this.requiredOptions[i]) == -1) {
        if(!this.el.$form.find('.productOption'+this.requiredOptions[i]).hasClass('_restricted_')) {/*checking if option is restricted*/
          requiredOptions.push(this.requiredOptions[i]);
        }
      }
    }

    var basePrice = this.data.definition.productBasePrice, retailPrice = this.data.definition.productRetailPrice, price = 0;
    var alternativeBasePrice = this.data.definition.productAlternativeBasePrice, alternativeRetailPrice = this.data.definition.productAlternativeRetailPrice, alternativePrice = 0;

    var epointsPrices = JSON.parse(JSON.stringify(this.data.pricesByEpoints)); // get the base ePoints prices

    var quantityMultiplier = 1;

    if(requiredOptions.length || !this.el.$options.length){ /*set default product prices when options are missing*/
      basePrice = this.data.definition.basePrice;
      retailPrice = this.data.definition.retailPrice;
      alternativeBasePrice = this.data.definition.alternativeBasePrice;
      alternativeRetailPrice = this.data.definition.alternativeRetailPrice;

      for(var k=0; k<epointsPrices.length; k++) epointsPrices[k].price = epointsPrices[k].minEpointsPrice;

    }else{
      for(var i=0; i<selectedValues.length; i++)
      {
        if(selectedValues[i].looseUnits){ quantityMultiplier = selectedValues[i].looseUnits; }
        if(!selectedValues[i].uniquePrice)
        {
          basePrice+=selectedValues[i].basePrice;
          retailPrice+=selectedValues[i].retailPrice;
          alternativeBasePrice+=selectedValues[i].alternativeBasePrice;
          alternativeRetailPrice+=selectedValues[i].alternativeRetailPrice;
        }

        for(var j=0; j<selectedValues[i].pricesByEpoints.length; j++){
          for(var k=0; k<epointsPrices.length; k++){
            if(selectedValues[i].pricesByEpoints[j].ePointId == epointsPrices[k].ePointId){
              epointsPrices[k].price += selectedValues[i].pricesByEpoints[j].price;
              break;
            }
          }
        }
      }
    }

    quantityValue *= quantityMultiplier; // for loose options

    var stock = 999999999, lockedStock=0, backorderPrevision = 999999999, combinationFound = true, combinationId = 0, stockKeys = [], backorderKeys = [], sku = "", ean = "";
    var stockMatch = 'WH[0-9]+_';

    var availableWarehouses = '';
    var warehouseStructures = warehousesStructures.map( function(el){return el.warehousesStructureId} );
    if(warehouseStructures.length) {
      availableWarehouses = warehouseStructures.join('|');
    }

    if(settings.catalogStockByWarehouse && settings.warehouseIdStock){
      var warehouseStructures = warehousesStructures.filter( function(el){return el.warehouseId==settings.warehouseIdStock} ).map( function(el){return el.warehousesStructureId} );
      if(warehouseStructures.length) {
        availableWarehouses = warehouseStructures.join('|');
      }
      else {
        stockMatch = 'NM_'; //no match
      }
    }

    if(stockMatch != 'NM_' && availableWarehouses.length > 0) {
      stockMatch = '(' + availableWarehouses + ')+_';
    }

    if (validateCombinationStock) {

      for (var key in this.data.combinations) {
        if ( key.match('PC_'+selectedStockValues+'$') ) {
          sku = this.data.combinations[key].sku;
          ean = this.data.combinations[key].ean;
          combinationId = this.data.combinations[key].id;
          break;
        }
      }

      if (settings.stockManagement && this.data.definition.stockManagement) {
        stock = 0, backorderPrevision = 0, combinationFound = false;

        for (var key in this.data.stocks) {
          if ( key.match(stockMatch+selectedStockValues+'$') ) {
            if(stockKeys.indexOf(key) == -1) stockKeys.push(key); // Collect used stock keys
            stock += this.data.stocks[key];
            combinationFound = true;
          }
        }

        // adding stock previsions
        for (i=0;i<this.data.stockPrevisions.length;i++){
          var key = this.data.stockPrevisions[i].warehousesStructureId;
          if ( key.match(stockMatch+selectedStockValues+'$') ) {
            if(stockKeys.indexOf(key) == -1) stockKeys.push(key); // Collect used stock keys
            stock += this.data.stockPrevisions[i].stock;
            combinationFound = true;
          }
        }

        // adding backorder previsions
        for (i=0;i<this.data.backorderPrevisions.length;i++){
          var key = this.data.backorderPrevisions[i].warehousesStructureId;
          if ( key.match(stockMatch+selectedStockValues+'$') ) {
            if(backorderKeys.indexOf(key) == -1) backorderKeys.push(key); // Collect used backorder stock keys
            backorderPrevision += this.data.backorderPrevisions[i].stock;
          }
        }

        if (!combinationFound) stock = -1;
      }

      if(combinationId && combinationId in this.data.stockLocks){
        lockedStock = this.data.stockLocks[combinationId].totalQuantity;
        lockedStockExpiration = this.data.stockLocks[combinationId].expirations[0];
      }

    }

    // Stock Alerts
    if (this.stockSubscriptionForm && (this.stockSubscriptionForm.hasOwnProperty('data') && typeof this.stockSubscriptionForm.data !== 'undefined') && this.stockSubscriptionForm.data.hasOwnProperty('stockId')) {
      this.stockSubscriptionForm.data.stockId = selectedStockValues;
      this.stockSubscriptionForm.$form.data('productStock', this.stockSubscriptionForm.data);

    } else {
      if(!window.productStocks) window.productStocks = {};

      window.productStocks[this.data.id] = selectedStockValues;
    }

    /*converting currencies*/
    if(settings.defaultCurrencyId != settings.currencyId) {
      // now, this prices will be converted from database
      /*
      var defaultCurrency = settings.currencies['currency'+settings.defaultCurrencyId];
      var selectedCurrency = settings.currencies['currency'+settings.currencyId];

      basePrice = parseFloat( (basePrice/defaultCurrency.USDVALUE*selectedCurrency.USDVALUE).toFixed(2) );
      alternativeBasePrice = parseFloat( (alternativeBasePrice/defaultCurrency.USDVALUE*selectedCurrency.USDVALUE).toFixed(2) );
      retailPrice = parseFloat( (retailPrice/defaultCurrency.USDVALUE*selectedCurrency.USDVALUE).toFixed(2) );
      alternativeRetailPrice = parseFloat( (alternativeRetailPrice/defaultCurrency.USDVALUE*selectedCurrency.USDVALUE).toFixed(2) );
      */
      basePrice = parseFloat( basePrice.toFixed(2) );
      alternativeBasePrice = parseFloat( alternativeBasePrice.toFixed(2) );
      retailPrice = parseFloat( retailPrice.toFixed(2) );
      alternativeRetailPrice = parseFloat( alternativeRetailPrice.toFixed(2) );
    }

    if (this.data.definition.sale && basePrice > retailPrice /**&& retailPrice > 0**/) {
      price = retailPrice;
      alternativePrice = alternativeRetailPrice;
      this.el.$form.find('.product-basePrice').show();
      this.el.$form.find('.product-alternativeBasePrice').show();
      this.el.$form.find('.product-saving').show();
      var saving = basePrice-retailPrice;
      this.el.$form.find('.product-saving .price').html( outputFormattedCurrency(saving) );
      this.el.$form.find('.product-saving .percent').html( (saving*100/basePrice).toFixed(0) );
    }
    else {
      price = basePrice;
      alternativePrice = alternativeBasePrice;
      this.el.$form.find('.product-basePrice').hide();
      this.el.$form.find('.product-alternativeBasePrice').hide();
      this.el.$form.find('.product-saving').hide();
    }

    this.el.$form.find('.product-price .price').html( outputFormattedCurrency(price) );
    this.el.$form.find('.product-alternativePrice .price').html( outputFormattedCurrency(alternativePrice) );
    this.el.$form.find('.product-basePrice .price').html( outputFormattedCurrency(basePrice) );
    this.el.$form.find('.product-alternativeBasePrice .price').html( outputFormattedCurrency(alternativeBasePrice) );

    if (stock >= 0) {
      this.el.$form.find('.product-stock .stock').html(stock);
      if (stock > 0) {
        this.el.$form.find('.product-stock').removeClass('no-stock').addClass('stock-ok').show();
        if (stock == 1) {
          this.el.$form.find('.product-stock .stock').html(stock);
          this.el.$form.find('.stockText').html(languageSheet.STOCKSINGULAR.replace("%stock%", stock));
        }
        else {
          this.el.$form.find('.product-stock .stock').html(stock);
          this.el.$form.find('.stockText').html(languageSheet.STOCKPLURAL.replace("%stock%", stock));
        }
      }
      else {
        this.el.$form.find('.product-stock').removeClass('stock-ok').addClass('no-stock').show();
        this.el.$form.find('.stockText').html(languageSheet.STOCKNONE.replace("%stock%", stock));
      }
    }
    else {
      this.el.$form.find('.product-stock').hide();
    }

    if (sku.length > 0) 
      this.el.$form.find('.product-combinations-sku').html(sku);

    if (ean.length > 0) 
      this.el.$form.find('.product-combinations-ean').html(ean);
   

    /*getting availability interval*/
    var availabilityInterval;
    for (var i=this.productAvailabilities.length-1; i>-1; i--) {
      if ( this.productAvailabilities[i].stock < stock)
        break;
      availabilityInterval = this.productAvailabilities[i];
    }
    /*printing availability*/
    if (availabilityInterval) {
      this.el.$form.find('.product-stock .availabilityImage').html('<img src="'+availabilityInterval.image+'" onerror="$(this).detach();" />');
      this.el.$form.find('.product-stock .availabilityName').html(availabilityInterval.name);
      this.el.$form.find('.product-stock .availabilityDescription').html(availabilityInterval.description);
    }
    else {
      this.el.$form.find('.product-stock .availabilityImage').hide();
      this.el.$form.find('.product-stock .availabilityName').hide();
      this.el.$form.find('.product-stock .availabilityDescription').hide();
    }

    // Buy Button properties
    var buyButtonProps = {};
    var displaySubscription = null;

    if('countdown' in this)
      this.countdown.destroy();
    
    this.el.$form.find('.fluidStockLock').removeClass('visible');
    this.el.$form.find('.fluidStockLockText').empty();

    var lsBUY = languageSheet.BUY;
    if(this.el.$gridCombinationsType && this.el.$gridCombinationsType.val() == 'update'){
      lsBUY = languageSheet.UPDATE;
    }

    if (requiredOptions.length) {
      buyButtonProps.className = 'selectOption';
      buyButtonProps.name = languageSheet.SELECTOPTION.replace('%option%', this.data.options['id'+requiredOptions[0]].name);
      buyButtonProps.disabled = true;
      displaySubscription = 'none';
    }
    else if (!validateCombinationStock && totalQty==0) { // grid options
      buyButtonProps.className = 'selectOption';
      buyButtonProps.name = languageSheet.SELECTOPTION.replace('%option%', this.data.options['id'+this.requiredGridOptions[0]].name);
      buyButtonProps.disabled = true;
      displaySubscription = 'none';
    }
    else if(this.data.definition.onRequest){ // onRequest products will be always available
      buyButtonProps.className = 'buy';
      buyButtonProps.name = lsBUY;
      buyButtonProps.disabled = false;
      displaySubscription = 'none';
    }
    else if (stock < 0) {
      buyButtonProps.className = 'notAvailable';
      buyButtonProps.name = languageSheet.NOTAVAILABLE;
      buyButtonProps.disabled = true;
      displaySubscription = 'none';
    }
    else if (stock == 0 || quantityValue > stock) {
      if(settings.reserveAllowed && this.data.definition.backorder){
        if((this.data.definition.backorder == 2 && (backorderPrevision+stock) >= quantityValue) || (this.data.definition.backorder == 1 || this.data.definition.backorder == 3)){ // allow reserve
          buyButtonProps.className = 'reserve';
          buyButtonProps.name = languageSheet.RESERVE;
          buyButtonProps.disabled = false;
        }else{ // disallow reserve
          buyButtonProps.className = 'notAvailable';
          buyButtonProps.name = languageSheet.NOTAVAILABLE;
          buyButtonProps.disabled = true;

          if (baseStockForSubscription && stock == 0)
            displaySubscription = 'block';
          else
            displaySubscription = 'none';
        }

        if (baseStockForSubscription && stock == 0)
          displaySubscription = 'block';
        else
          displaySubscription = 'none';

      }
      else {

        buyButtonProps.className = 'notAvailable';
        buyButtonProps.name = languageSheet.NOTAVAILABLE;
        buyButtonProps.disabled = true;
        
        if (baseStockForSubscription && stock == 0)
          displaySubscription = 'block';
        else
          displaySubscription = 'none';
      }
    }
    else if(stock-lockedStock <= 0){
      buyButtonProps.className = 'notAvailable reserved';
      buyButtonProps.name = languageSheet.STOCKRESERVED;
      buyButtonProps.disabled = true;
      displaySubscription = 'none';

      this.el.$form.find('.fluidStockLock').addClass('visible');
      if(lockedStockExpiration){
        this.countdown = new Fluid.combinationCountDown({endDate:lockedStockExpiration.expires, quantity:lockedStockExpiration.quantity});
        this.el.$form.find('.fluidStockLockText').append( this.countdown.$container );
      }
      else{
        this.el.$form.find('.fluidStockLockText').append( languageSheet.STOCKRESERVEDUSERTEXT );
      }

    }
    else {
      buyButtonProps.className = 'buy';
      buyButtonProps.name = lsBUY;
      buyButtonProps.disabled = false;
      displaySubscription = 'none';
    }

    this.el.$buyFormSubmit = this.el.$form.find('button[type="submit"]');
    this.updateButton(this.el.$buyFormSubmit, buyButtonProps);

    // show ePoints prices
    for(var i=0; i<epointsPrices.length; i++){
      var priceElement = this.el.$form.find('.product-epointsPrice.product-epointsPrice-'+epointsPrices[i].ePointId);
      if(priceElement) priceElement.html(epointsPrices[i].price >= 0 ? epointsPrices[i].price : 0);

      additionalBuyFormSubmit = this.el.$form.find('button[type="submit"].ePointsBuyFormSubmit' + epointsPrices[i].ePointId);
      // disable button
      if((!this.data.userEpoints || !this.data.userEpoints['ePoint_'+epointsPrices[i].ePointId] || !this.data.userEpoints['ePoint_'+epointsPrices[i].ePointId].AVAILABLE)
        || (additionalBuyFormSubmit && !additionalBuyFormSubmit.attr('disabled') && (epointsPrices[i].price <= 0 || this.data.userEpoints['ePoint_'+epointsPrices[i].ePointId].AVAILABLE < (epointsPrices[i].price * quantityValue)))
      ){
        this.updateButton(additionalBuyFormSubmit, {className:'notEnoughEpoints', name:(epointsPrices[i].price <= 0 ? languageSheet.NOTAVAILABLE : languageSheet.NOTENOUGHEPOINTS.replace(/%%/g, '%').replace('%ePoints%', epointsPrices[i].name)), disabled:true});
      }
    }

    this.enabledButtons = this.el.$buyFormSubmit.filter(':enabled');

    if (this.stockSubscriptionForm) this.stockSubscriptionForm.$htmlModule.css('display', displaySubscription);

    this.updateEpointsView(price);

    this.updatePriceByQuantity(selectedValues);

    var offsetContainer = this.el.$form.find('.productOffsetMessage').get(0), stcStockOffset = {};

    if(offsetContainer && stockKeys.length && warehousesStructures.length){
      $(offsetContainer).html('');

      var acumulatedStock = 0, offsetDays = 0, requestOffset = 0, previsionDate = new Date(), productData = this.data;

      if(this.data.definition.onRequest)
        requestOffset = this.data.definition.onRequestDays;

      $.each(warehousesStructures, function(i, wStructure){
        for(i=0;i<stockKeys.length;i++){
          if(stockKeys[i].indexOf(wStructure.warehousesStructureId) != -1){ // we're using stock of this warehouse
            stcStockOffset[stockKeys[i]] = wStructure.offsetDays;
            if(productData.stocks[stockKeys[i]]){
              acumulatedStock += productData.stocks[stockKeys[i]];
              if(wStructure.offsetDays > offsetDays)
                offsetDays = wStructure.offsetDays;
            }
          }
          if(acumulatedStock >= quantityValue){
            return false; // left loop
          }
      
        }
      });
      previsionDate.setDate(previsionDate.getDate()+offsetDays);

      if(acumulatedStock < quantityValue){ // We need to use the previsions
        var auxPrevisionDate = new Date();
        productData.stockPrevisions.sort(function(a,b){ return new Date(a.incomingDate) > new Date(b.incomingDate) }) // sort the previsions by the incoming date

        $.each(productData.stockPrevisions, function(i, prevision){
          for(i=0;i<stockKeys.length;i++){
            if(stockKeys[i].indexOf(prevision.warehousesStructureId) != -1 && prevision.stock > 0){
              acumulatedStock += prevision.stock;
              offsetDays = stcStockOffset[prevision.warehousesStructureId] || offsetDays;
              auxPrevisionDate = new Date(prevision.incomingDate);
            }
            if(acumulatedStock >= quantityValue){
              return false; // left loop
            }
          }
        });
        auxPrevisionDate.setDate(auxPrevisionDate.getDate()+offsetDays);

        if(auxPrevisionDate > previsionDate)
          previsionDate = auxPrevisionDate;
      }

      if(acumulatedStock < quantityValue && settings.reserveAllowed && this.data.definition.backorder){ // We need to use the backorder previsions if we have them
        var auxPrevisionDate = new Date();
        productData.backorderPrevisions.sort(function(a,b){ return new Date(a.incomingDate) > new Date(b.incomingDate) }) // sort the previsions by the incoming date

        $.each(productData.backorderPrevisions, function(i, prevision){
          for(i=0;i<backorderKeys.length;i++){
            if(backorderKeys[i].indexOf(prevision.warehousesStructureId) != -1 && prevision.stock > 0){
              acumulatedStock += prevision.stock;
              offsetDays = stcStockOffset[prevision.warehousesStructureId] || offsetDays;
              auxPrevisionDate = new Date(prevision.incomingDate);
            }
            if(acumulatedStock >= quantityValue){
              return false; // left loop
            }
          }
        });
        auxPrevisionDate.setDate(auxPrevisionDate.getDate()+offsetDays);

        if(auxPrevisionDate > previsionDate)
          previsionDate = auxPrevisionDate;
      }

      if(acumulatedStock >= quantityValue && previsionDate.setHours(0,0,0,0) > new Date().setHours(0,0,0,0)){
        var formattedDate = moment(previsionDate).format(settings.dateFormat.toUpperCase());
        $(offsetContainer).html(languageSheet.WAREHOUSEOFFSETMESSAGE.replace('%offsetDays%', formattedDate).replace('%previsionDate%', formattedDate));
      }
      else if(acumulatedStock < quantityValue && requestOffset)
        $(offsetContainer).html(languageSheet.ONREQUESTPRODUCTMESSAGE.replace('%days%', requestOffset));

    }

    // Callback Pmt if exists
    if (settings.showTaxInclude == 0)
      var sendPrice = alternativePrice * quantityValue;
    else
      var sendPrice = price * quantityValue;

    this.getPagaMasTarde(sendPrice, this.data.id);
    
    this.updateSequra(sendPrice, this.data.id);

    this.updateAplazame(sendPrice, this.data.id);

    if(this.data.restrictions && this.data.restrictions.length)
    {
      this.setOptionRestrictions();
    }

    // Callback trigger
    this.trigger('onChangeCallback', {price:price, basePrice:basePrice, requiredOptions:requiredOptions, selectedOptions:selectedOptions, stock:stock, quantity:quantityValue});
  },

  setOptionRestrictions:function() {
    var form = this.el.$form;

    var getField = function(valueId)
    {
      return form.find('*[value='+valueId+']');
    };
    var getChecked = function(valueId)
    {
      var field = getField(valueId).first();

      return field.length ? field[0].checked || field[0].selected : false;
    };
    var disableField = function(valueId)
    {
      var field = getField(valueId);
      var ind,i,k;

      if(!field)
        return;

      field.addClass('_restricted_').attr('disabled',1).css('display','none').removeAttr('checked');

      if(field.parents('tr.productOptionValueTable').length == 1){
        field.parents('tr.productOptionValueTable').css('display','none').removeClass('productOptionSelected');
      }
      else if(field[0].tagName.toLowerCase()!='option')
        parentNode = field.parent('.productOptionValue').css('display','none').removeClass('productOptionSelected');
    };

    var disableOption = function(optionId)
    {
      var option = form.find('.productOption'+optionId)

      option.addClass('_restricted_').css('display','none');

      option.find('select').addClass('_restricted_').attr('disabled',1).attr('selectedIndex',-1);
      //option.find('option').addClass('_restricted_').attr('disabled',1).attr('selected',0);
      option.find('input.productOptionRadioValue').addClass('_restricted_').attr('disabled',1).removeAttr('checked').parent('.productOptionRadioValue').removeClass('productOptionSelected');
    };

    /*reset all options*/
    form.find('._restricted_').removeClass('_restricted_').removeAttr('disabled').css('display','').css('display','').each(
      function(index, field){
        if(field.tagName.toLowerCase()!='option')
        {
          $(field).parent('.productOptionValue').css('display','');
          if($(field).parents('tr.productOptionValueTable').length == 1){
            $(field).parents('tr.productOptionValueTable').css('display','');
      }
        }
      }
    );

    if(this.data.restrictionsMain && this.data.restrictionsMain.length)
    {

      for(var ind=0; ind<this.data.restrictionsMain.length; ind++)
      {
        var restriction = this.data.restrictionsMain[ind];

        if(!getChecked(restriction.MAIN))
          continue;

        for(i=0; i<restriction.OPTIONS.length; i++)
          disableOption(restriction.OPTIONS[i]);

        for(i=0; i<restriction.VALUES.length; i++)
          disableField(restriction.VALUES[i]);

      }

      var anyChecked = 0;
      form.find('.productOption').each(
        function(index,div)
        {
          div = $(div)
          var someChecked = div.find(':checked');
          if(!someChecked.length)
          {
            var somethingChecked = div.find(':enabled').first();
            somethingChecked.prop('checked', 1).attr('selected', 1).parent('.productOptionRadioValue, .productOptionCheckboxValue').addClass('productOptionSelected');
            anyChecked += somethingChecked.length;
          }
        }
      );
      if(anyChecked)
        this.onChange();
      
    }

    if(this.data.restrictions && this.data.restrictions.length)
    {
      for(i=0; i<this.data.restrictions.length; i++)
      {
        var limitation = this.data.restrictions[i];

        var matching = [], noMatching = [];

        for(k=0; k<limitation.length; k++)
        {
          var valueId = limitation[k];
          
          if( getChecked(valueId) )
            matching.push(valueId);
          else
            noMatching.push(valueId);
        }

        if(noMatching.length  == 1)
          disableField(noMatching[0]);
      }
    }

  },

  updatePriceByQuantity:function(selectedOptions) {
    if (!this.el.$priceByQuantityBox.length)
      return;

    selectedOptions = selectedOptions.map( function(i) {return i.id;} );

    this.el.$priceByQuantityBox.html('').hide();

    var prices = this.getPrices(selectedOptions);

    var table = '<table>';

    var pricesArray = new Array();
    for (var key in prices)
      pricesArray.push({from:prices[key].from, retailPrice:prices[key].retailPrice, basePrice:prices[key].basePrice});

    if (pricesArray.length < 2)
      return;

    for (var i=0; i<pricesArray.length; i++) {
      switch(2)/*TODO*/ {
        case 2:
          if (i == pricesArray.length-1)
            label = languageSheet.MORETHANNUNITS.replace('%n%', pricesArray[i].from-1 );
          else if (i == 0 && pricesArray[i+1].from == 2)
            label = languageSheet.ONEUNIT.replace('%n%', pricesArray[i].from);
          else if (i == 0)
            label = languageSheet.FROMNTOMUNITS.replace('%n%', 1).replace('%m%', pricesArray[i+1].from-1);
          else if (pricesArray[i].from+1 == pricesArray[i+1].from)
            label = languageSheet.NUNITS.replace('%n%', pricesArray[i].from);
          else
            label = languageSheet.FROMNTOMUNITS.replace('%n%', pricesArray[i].from).replace('%m%', pricesArray[i+1].from-1);
          break;
        default:
          label = languageSheet.MORETHANNUNITS.replace('%n%', pricesArray[i].from);
      }

      var price = pricesArray[i].basePrice;
      if (this.data.definition.sale && pricesArray[i].basePrice > pricesArray[i].retailPrice && pricesArray[i].retailPrice != 0)
        price = pricesArray[i].retailPrice;

      table += '<tr><td>'+label+'</td><td class="priceColumn">'+outputFormattedCurrency(price)+'</td></tr>';

    }

    table += '</table>';

    this.el.$priceByQuantityBox.html(table).show();

  },

  getPrices:function( optionValues ) {
    optionValues = optionValues || [];
    optionValues.unshift(0);

    var prices = {};

    for (var i=0; i<this.data.priceByQuantity.length; i++) {
      var priceData = this.data.priceByQuantity[i];

      if ( optionValues.indexOf(priceData.optionValueId) > -1 ) {
        prices['p'+priceData.from] = prices['p'+priceData.from] || {from:priceData.from, basePrice:0, retailPrice:0};
      }
    }

    for (var key in prices) {
      for (var i=0; i<optionValues.length; i++) {
        var interval = this.getPriceInterval(prices[key].from, optionValues[i]);
        prices[key].basePrice += interval.basePrice;
        prices[key].retailPrice += interval.retailPrice;
      }
    }

    return prices;
  },

  getPriceInterval:function(from, optionValueId) {
    for (var i=this.data.priceByQuantity.length-1; i>-1 ; i--) {
      if (this.data.priceByQuantity[i].from > from)
        continue;

      if (this.data.priceByQuantity[i].optionValueId != optionValueId)
        continue;

      return this.data.priceByQuantity[i];
    }

    return {from:from, basePrice:0, retailPrice:0};
  },

  /**
   * Get form data
   * @memberOf Fluid.BuyForm
   */
  getFormData:function() {
    var formValues = this.getFormValues();
    var options = {}, optionsArray = [];

    for(var i=0; i<formValues.length; i++) {
      if(!options[formValues[i].name])
        options[formValues[i].name] = [];
      options[formValues[i].name].push(formValues[i].value);
    }
    
    for(var option in options)
      optionsArray.push( {id:option.replace('optionValue', ''), values:options[option]} );    

    if (typeof this.quantityField === 'undefined'){
      this.quantityField = this.el.$form.find('select[name=quantity]').get(0);
    }

    var response =  {
      id:this.data.id,
      quantity:this.quantityField ? this.quantityField.value : this.data.definition.minOrderQuantity || 1,
      options:optionsArray,
      alternativeImage:this.alternativeImageField ? this.alternativeImageField.value : '',
      vinculatedProducts:this.vinculatedProductsField ? this.vinculatedProductsField.value : '',
      addVinculated:this.addVinculated ? this.addVinculated.value : false
    };

    if(this.ePointId){ // ePoints purchase
      response.ePointId = this.ePointId;
      this.ePointId = null;
    }

    if (this.el.$gridOption.length > 0) {
      response.gridValues = {};
      this.el.$gridOptions.each(function(i,e) {
        var val = $(e).val();
        if (val.length == 0) val = 0;
        response.gridValues[$(e).attr('name')] = val;
      });

      response.gridOptionsIds = this.el.gridOptionsIds;
      response.gridOptionValues1 = this.el.gridOptionValues1;

      if (this.el.gridOptionValues2) {
        response.gridOptionValues2 = this.el.gridOptionValues2;
      }
    }

    if (this.el.$gridCombinations.length > 0) {
      response.gridCombinationsValues = {};
      this.el.$gridCombinations.each(function(i,e) {
        response.gridCombinationsValues[$(e).attr('name')] = parseInt($(e).val());
      });
    }

    return response;
  },

  /**
   * Submit event
   * @memberOf Fluid.BuyForm
   * @param {object} event
   */
  submit : function(event) {
    event.preventDefault();

    // Before trigger
    this.trigger('submitBefore', event);

    if(!this.formIsValid())
      return false;

    var data = this.getFormData();

    // Before submit
    this.pluginListener('onAddProduct', event, data);

    // Send form
    $.post('/basket/addProduct/', JSON.stringify([data]), this.callback , 'json');

    // Disable buy button
    this.el.$buyFormSubmit.prop('disabled', true);

    // Callback trigger
    this.trigger('submitCallback', event);
  },

  formIsValid : function() {
    if(!this.el.$form.isValid())
      return false;

    if (this.el.$gridCombinationsType && this.el.$gridCombinationsType.val() == 'buy') {
      var sumCombination = 0;
      this.el.$gridCombinations.each(function(i,e) {
        sumCombination += parseInt($(e).val());
      });
      if (sumCombination === 0)
        return false;
    }

    return true;
  },

  /**
   * Callback
   * @memberOf Fluid.BuyForm
   */
  callback:function(result) {

    //refresh chat
    this.updateChatBasket(result);

    // Callback trigger
    this.trigger('callbackBefore', result.response);

    var bodyClasses = $('body').attr('class')
    if(this.addVinculated && this.addVinculated.value.toString() == "true" && (bodyClasses.indexOf('fluidContent-basket') != -1 || bodyClasses.indexOf('fluidContent-paymentAndShipping') != -1)){
      $('html,body').animate({ scrollTop: 0 }, 'slow', function(){window.location.reload();} );
    }

    // Reload minibasket
    Fluid.miniBasket.reload();

    if(window.TEA && result.response.basket)
      TEA.updateBasket(result.response.basket);

    //reload OSC if buying from OSC
    switch(location.pathname){
      case '/checkout':
      case '/checkout/oneStepCheckout':
        fluidOneStepCheckout.moduleCalls('refreshModule');
    }

    // Enable buy button
    this.enabledButtons.prop('disabled', false);

    if (this.el.$gridCombinations.length > 0) {
      var qtText = 'quantity-';

      this.el.$gridCombinations.each(function(i,e) {
        var $e = $(e);

        var inputData = JSON.parse($e.attr('name').substring(qtText.length));
        this.updateCombinationsFields([inputData.productHash], parseInt($e.val()));
      }.bind(this));

      totalProdsInBasket = this.getCombinationsFormTotalQuantity();

      this.updateCombinationsFormType(totalProdsInBasket);
    }

    // Callback trigger
    this.trigger('callback', result.response);

    if (Fluid.config.showModalBasket && (settings.isMobile == 1 || window.innerWidth < 992)){
      var buttonClass = htmlFramework == 'bootstrap' ? ' btn btn-default btn-block' : 'modalBasketEndOrderButton';
      var submitButtonClass = htmlFramework == 'bootstrap' ? ' btn-primary' : '';
      var localPath = (settings && settings.checkoutPath)? settings.checkoutPath : "/checkout/basket";
      var modalContent = '';
      if(result.response.stockLock){
        modalContent += '<div class="basketCountdown" data-basket-expires=\'{"expires":"'+result.response.stockLock.expires+'"}\'><div class="active">'+languageSheet.LOCKEDSTOCKREMAININGTIMEPOPUP+'</div><div class="expired">'+languageSheet.LOCKEDSTOCKEXPIREDTIMEPOPUP+'</div></div>';
      }
      modalContent += '<div id="modalBasketButtons"><a href="' + localPath + '" class="modalBasketEndOrder' + buttonClass + submitButtonClass + '">'+ languageSheet.BASKETENDORDER + '</a><a data-dismiss="modal" class="modalBasketContinueShopping' + buttonClass + '">' + languageSheet.BASKETCONTINUESHOPPING + '</a><a href="/user" class="modalBasketMyAccount' + buttonClass + '">' + languageSheet.MYACCOUNT + '</a></div>'

      this.el.$buyFormSubmit.box({
        uid : 'mobileBasketModal',
        source: modalContent,
        showFooter : false,
        triggerOnClick : false,
        type : 'text'
      });
    }
  },

  /**
   * updateCombinationsFields method
   * @memberOf Fluid.BuyForm
   * @param {array} hashes
   * @param {numeric} value
   */
  updateCombinationsFields : function(hashes, value){
    if(hashes.length){
      $('[id="buyForm' + this.data.id + '"]').each(function(index, buyForm) {
        var qtText = 'quantity-';

        if(buyForm.module.el.$gridCombinations.length){
          buyForm.module.el.$gridCombinations.each(function(index, inputCombination) {
            var $inputCombination = $(inputCombination);
            var hash = $inputCombination.data("fluidProductHash");

            if($.inArray(hash, hashes) != -1){
              var inputData = JSON.parse($inputCombination.attr('name').substring(qtText.length));
              inputData.quantity = value;

              $inputCombination.attr('name', qtText + JSON.stringify(inputData));
              $inputCombination.val(value);
            }
          });
        }
      });
    }
  },

  /**
   * getCombinationsFormTotalQuantity method
   * @memberOf Fluid.BuyForm
   */
  getCombinationsFormTotalQuantity : function(){
    var totalQuantity = 0;

    this.el.$gridCombinations.each(function(i,e) {
      totalQuantity += parseInt($(e).val());
    });

    return totalQuantity;
  },

  /**
   * updateCombinationsFormType method
   * @memberOf Fluid.BuyForm
   * @param {numeric} totalProdsInBasket
   */
  updateCombinationsFormType : function(totalProdsInBasket){
    var getCombinationsFormType = function(totalProdsInBasket){
      if(totalProdsInBasket > 0)
        return 'update';

      return 'buy';
    }

    if(totalProdsInBasket == null){
      totalProdsInBasket = this.getCombinationsFormTotalQuantity($('#buyForm' + this.data.id).get(0));
    }

    $('[id="buyForm' + this.data.id + '"]').each(function(index, buyForm) {
      if(buyForm.module.el.$gridCombinationsType){
        buyForm.module.el.$gridCombinationsType.val(getCombinationsFormType(totalProdsInBasket));
        buyForm.module.onChange();
      }
    });
  },

  wishlist: function() {

    // Before trigger
    this.trigger('wishlistBefore');

    var $this = this.el.$wishlist;
    var type = $this.data('wishlist');

    switch(type) {
      case 'accountRequired':
        $this.box({
          uid : 'wishlistAccountRequiredModal',
          showFooter : false,
          source : '<div class="question wishlistQuestion fluidWishlist"><div class="questionText wishlistQuestionText">'+languageSheet.WISHLISTACCOUNTREQUIRED+'</div><div class="questionButtons"><input type="button" class="btn pull-left questionButton questionButtonLeft wishlistQuestionButton" id="wishlistQuestionButton1" value="'+languageSheet.NO+'"  data-dismiss="modal" /><input type="button" class="btn btn-primary pull-right questionButton questionButtonRight wishlistQuestionButton" id="wishlistQuestionButton2" value="'+languageSheet.YES+'" onclick="location.href=\'/user\';" /></div></div>',
          type : 'text',
          showClose : false,
          size : 'small',
          callback : 'wishlistAccountRequired'
        });
        break;

      case 'setWishlist':
        var data = $this.data('wishlistData');

        $this.on('click', function(event) {
          $this.attr('disabled', 'disabled');
          var data = $this.data('wishlistData');
          var typeSetWishlist = data.type;

          /*blueknow*/
          if (data.type == 'add' && window.BlueknowTracker)
            BlueknowTracker.trackExamined(data.itemId);

          if (data.type == 'add')
            data.type = 'remove';
          else
            data.type = 'add';

          // Post
          $.post(
            '/user/setWishlist/',
            JSON.stringify({type: typeSetWishlist, itemId:data.itemId, itemType:data.itemType}),
            this.wishlistCallback.bind(this, data, $this),
          "json");

        }.bind(this));

        break;
    }
  },

  wishlistCallback: function(data, $this, dataResult, textStatus, xhr) {
    $this.removeAttr('disabled');

    if (dataResult.response && dataResult.response.SUCCESS) {
      var isInput = $this[0].nodeName.toLowerCase() == "input";

      //Update data
      $this.data('wishlistData', data);

      // Classes and label
      if (data.type == 'remove') {
        var label = data.labelAdded;
        $this.addClass('wishlistButtonAdded wishlistButtonRemove');

        this.showMessage(languageSheet.WISHLISTADDED, 'success');
      }
      else {
        var label = data.labelRemoved;
        $this.removeClass('wishlistButtonAdded wishlistButtonRemove');
        this.showMessage(languageSheet.WISHLISTDELETED, 'danger');
      }

      // Change label
      if (data.showLabel) {
        if (isInput)
          $this.val(label);
        else
          $this.text(label);
      }
    }

    // Callback trigger
    this.trigger('wishlistCallback', data, $this, dataResult, textStatus, xhr);
  },

  deleteWishlistItem: function(event) {
    event.preventDefault();

    // Before trigger
    this.trigger('deleteWishlistItemBefore');

    $.post('/user/setWishlist/', JSON.stringify({type:'remove', itemId:this.data.id, itemType:1}), this.deleteWishlistItemCallback.bind(this), "json");
  },

  deleteWishlistItemCallback: function(data, textStatus, xhr) {
    // Callback trigger
    if (!this.trigger('deleteWishlistItemBefore')) {
      window.location.reload();
    }
  },

  availableDiscounts: function(event) {
    event.preventDefault();

    var $this = this.el.$availableDiscounts;
    
    $this.attr('disabled', 'disabled');
    // Before trigger
    this.trigger('availableDiscountsBefore');

    $this.box({
      uid: 'modalAvailableDiscounts',
      triggerOnClick: false,
      showFooter: false,
      source: '/product/discounts/',
      type: 'url',
      params: {productId:this.data.id}
    });

    $this.removeAttr('disabled');
  },

  attachmentFields: function(element){
    var me=this;
    this.target = element;

    var parentDiv = this.target.parents('div.productOption').get(0);
    this.targetOptionId = $(parentDiv).data('fluidProductOption').id;

    if(!this.target) return;

    this.options = {};
    this.options = JSON.parse(element.attr("data-options"));

    if(this.options.minValues > this.options.maxValues) {
      var aux = this.options.maxValues;
      this.options.maxValues = this.options.minValues;
      this.options.minValues = aux;
    }

    if(this.options.maxValues == 0) this.options.maxValues = 100;

    this.fieldName = element.attr("data-optionValue");

    this.createUploadField = function(){
      if (me.options.maxValues > 0 && me.target.parent().find('div.productOptionAttachedValue').length >= me.options.maxValues) {
        this.showMessage(languageSheet.VALIDMAX + ' ' + me.options.maxValues, 'danger');
        return;
      } else {
        var div = $('<div/>', {
            class:me.options.className,
            style:'position: absolute; top: 0; right: 0; cursor: pointer; opacity: .01;'
        }).appendTo(me.target);
        var input = $('<input/>', {
            type:'file',
            class:me.options.className,
            autocomplete:'off',
        }).on('change', me.changeOption.bind(this)).appendTo(div); //To enable changeOption events, 'change' redirects to changeOption instead to uploadFile directly
      }
    }

    this.deleteFile = function(field){
      field.remove();
      if (me.options.maxValues > me.target.parent().find('div.productOptionAttachedValue').length) {
        me.createUploadField();
      }
      if (me.options.minValues == 0 || me.options.minValues > me.target.parent().find('div.productOptionAttachedValue').length) { // re-add the option as required
        me.requiredOptions.push(me.targetOptionId);
        me.onChange();
      }
    }

    this.uploadFile = function(field){
      field.setAttribute('name', 'file');

      var id = "frame" + new Date().getMilliseconds();
      var frame = $('<iframe/>', {
        id: id,
        frameborder: 'no',
        name: id,
        style: 'width: 0px; height: 0px; display: none;'
      });
      frame.on('load', function() {
        var content = frame.contents().find('pre').html();
        if (!content) {
          return;
        }
        var result = $.parseJSON(content);
        me.target.removeClass('attachmentUploading');

        var attachedFiles = $('<div/>', {
          class: me.options.attachedClassName,
        }).appendTo(me.target.parent());

        var deleteDiv = $('<div/>', {
          class:me.options.deleteIconClass,
        }).on('click', function(){ me.deleteFile($(this).parent()); }).appendTo(attachedFiles);
        var filenameDiv = $('<div/>', {
          class:'attachmentFilename',
        }).html(result.response.ORIGINALFILE).appendTo(attachedFiles);
        var hiddenField = $('<input/>', {
          type:'hidden', 
          name:me.fieldName,
          value:result.response.FILE
        }).appendTo(deleteDiv);

        me.createUploadField();

        if (me.options.minValues <= me.target.parent().find('div.productOptionAttachedValue').length) { // remove the option as required
          me.requiredOptions = me.requiredOptions.filter(function(id) { return id != me.targetOptionId; });
          me.onChange();
        }

      });

      var form = $('<form/>', {
        action:'/fileUpload/upload', 
        method:'post', 
        enctype:'multipart/form-data', 
        target:id, 
        styles:'width: 0px; height: 0px; display: none;' 
      });

      frame.appendTo(document.body);
      form.appendTo(document.body);
      $(field).appendTo(form);
      me.target.addClass('attachmentUploading');
      form.submit();
    }
    this.createUploadField();

  },

  //Private methods
  // For discriminate private methods from public methods, I propose
  // to put an underscore "_" at the begining. Ex: _privateDummyFunction()

  // --- EMPTY,
});

/**
 * @class Fluid.BuyGiftForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 * @description Form extended from Fluid.Form
 */
Fluid.BuyGiftForm = Fluid.Form.extend({
  name : 'buyGiftForm',
  options : {},
  visibleStock : 0,
  /**
   * Initialize
   * @memberOf Fluid.BuyGiftForm
   */
  initialize: function(form) {
    this.data = JSON.parse(this.el.$form.attr("data-product"));

    this.quantityField = this.el.$form.find('input[data-fluid-field="quantity"]').get(0);

    // Before trigger
    this.trigger('initializeBefore');

    this.productAvailabilities = [];
    if (this.data.availabilityId && productAvailabilities['availability'+this.data.availabilityId])
      this.productAvailabilities = productAvailabilities['availability'+this.data.availabilityId];

    this.callback = this.callback.bind(this);
    this.initOptions();

    // Callback trigger
    this.trigger('initializeCallback');
  },

  /**
   * Initialize options
   * @memberOf Fluid.BuyGiftForm
   * @param  {object} eventData
   */
  initOptions: function() {
    // Before trigger
    this.trigger('initOptionsBefore');

    this.el.$buyGiftFormSubmit = this.el.$form.find('button[type="submit"]');
    this.el.$options = this.el.$form.find('input.productOptionRadioValue, select.productOptionSelectValue, input.productOptionCheckboxValue, input.productOptionBooleanValue, input.productOptionTextValue, textarea.productOptionLongTextValue');
    this.el.$options.change(this.changeOption.bind(this));

    if (this.quantityField)
      $(this.quantityField).change(this.changeQuantity.bind(this));

    /*getting required options*/
    this.requiredOptions = [];
    for (var option in this.data.options) {
      if ( [3,5,7].indexOf(this.data.options[option].valueType) > -1 ) {
        this.requiredOptions.push( this.data.options[option].id );
      }
    }

    this.onChange();

    this.el.$form.find('input.productOptionRadioValue:checked').parent('div.productOptionRadioValue').addClass('productOptionSelected');

    // Callback trigger
    this.trigger('initOptionsCallback');
  },

  /**
   * Change quantity
   * @memberOf Fluid.BuyGiftForm
   * @param  {object} eventData
   */
  changeQuantity: function(eventData) {
    var quantityValue = $(this.quantityField).val();

    // Before trigger
    this.trigger('changeQuantityBefore');

    this.onChange();

    // Callback trigger
    this.trigger('changeQuantityCallback', {quantity:quantityValue});
  },

  /**
   * Change option
   * @memberOf Fluid.BuyGiftForm
   * @param  {object} eventData
   */
  changeOption: function(eventData) {

    // Before trigger
    this.trigger('changeOptionBefore');

    if ( $(eventData.target).hasClass('productOptionRadioValue') ) {
      $(eventData.target).parents('div.productOptionValues').find('div.productOptionRadioValue').removeClass('productOptionSelected');
      $(eventData.target).parent('div.productOptionRadioValue').addClass('productOptionSelected');
    }

    // Callback trigger
    this.trigger('changeOptionCallback', eventData.target);

    this.onChange();
  },

  /**
   * On change
   * @memberOf Fluid.BuyGiftForm
   */
  onChange: function() {

    var selectedOptions = [];
    var selectedValues = [];
    var selectedStockValues = [];
    var optionId, optionValueId;

    var formValues = this.getFormValues();
    var quantityValue = $(this.quantityField).val();

    // Before trigger
    this.trigger('onChangeBefore', formValues);

    selectedOptions = [];
    for(var i=0; i<formValues.length; i++) {
      optionId = formValues[i].name.replace('optionValue', '');
      optionValueId = formValues[i].value;
      if( Object.getLength(this.data.options['id'+optionId].values) ) {
        if( this.data.options['id'+optionId].values['id'+optionValueId] ) {
          selectedOptions.push(parseInt(optionId));
          selectedValues.push( this.data.options['id'+optionId].values['id'+optionValueId] );
          if( this.data.options['id'+optionId].combinable )
            selectedStockValues.push( parseInt(optionValueId) );
        }
      }
      else {
        selectedOptions.push(parseInt(optionId));
      }
    }
    selectedStockValues = selectedStockValues.sort( function(a, b){return a-b} ).join('-');
    
    var requiredOptions = [];
    for(var i=0; i<this.requiredOptions.length; i++)
      if( selectedOptions.indexOf(this.requiredOptions[i]) == -1 )
        requiredOptions.push(this.requiredOptions[i]);
    
    var stock = 999999999, combinationFound = true;
    if(settings.stockManagement && this.data.definition.stockManagement) {
      stock = 0;
      combinationFound = false;
      for(var key in this.data.stocks) {
        if( key.match('WH[0-9]+_'+selectedStockValues+'$') )
        {
          stock += this.data.stocks[key];
          combinationFound = true;
        }
      }
      if(!combinationFound)
        stock = -1;  
    }

    if(stock >= 0) {
      this.el.$form.find('.product-stock .stock').html(stock);
      if(stock > 0)
        this.el.$form.find('.product-stock').removeClass('no-stock').addClass('stock-ok').show();
      else
        this.el.$form.find('.product-stock').removeClass('stock-ok').addClass('no-stock').show();
    }
    else {
      this.el.$form.find('.product-stock').hide();
    }

    /*getting availability interval*/
    var availabilityInterval;
    for(var i=this.productAvailabilities.length-1; i>-1; i--) {
      if( this.productAvailabilities[i].stock < stock)
        break;
      availabilityInterval = this.productAvailabilities[i];
    }
    
    // Buy Button properties
    var buyButtonProps = {};
    if( requiredOptions.length ) {
      buyButtonProps.className = 'selectOption';
      buyButtonProps.name = languageSheet.SELECTOPTION.replace('%option%', this.data.options['id'+requiredOptions[0]].name);
      buyButtonProps.disabled = true;
    }
    else if(stock < 0) {
      buyButtonProps.className = 'notAvailable';
      buyButtonProps.name = languageSheet.NOTAVAILABLE;
      buyButtonProps.disabled = true;
    }
    else if(stock == 0 || quantityValue > stock) {
      buyButtonProps.className = 'notAvailable';
      buyButtonProps.name = languageSheet.NOTAVAILABLE;
      buyButtonProps.disabled = true;
    }
    else {
      buyButtonProps.className = 'add';
      buyButtonProps.name = languageSheet.ADDGIFTTOCART;
      buyButtonProps.disabled = false;
    }

    this.el.$buyGiftFormSubmit.removeClass('selectOption notAvailable reserve buy');
    this.el.$buyGiftFormSubmit.addClass(buyButtonProps.className);
    this.el.$buyGiftFormSubmit.prop('disabled', buyButtonProps.disabled);
    this.el.$buyGiftFormSubmit.data( 'buyFormSubmitName', buyButtonProps.name);

    if (this.el.$buyGiftFormSubmit.data('showlabel') == 1)
      this.el.$buyGiftFormSubmit.html(buyButtonProps.name);
    else
      this.el.$buyGiftFormSubmit.html("");

    // Callback trigger
    this.trigger('onChangeCallback');
  },

  /**
   * Get form data
   * @memberOf Fluid.BuyGiftForm
   */
  getFormData: function() {
    var discountName = this.el.$form.data('fluidDiscountName');
    if (typeof discountName === 'undefined')
      discountName = '';

    var formValues = this.getFormValues();
    var options = {}, optionsArray = [];

    for (var i=0; i<formValues.length; i++) {
      if (!options[formValues[i].name])
        options[formValues[i].name] = [];
      options[formValues[i].name].push(formValues[i].value);
    }

    for (var option in options)
      optionsArray.push( {id:option.replace('optionValue', ''), values:options[option]} );

    return {
      id:this.data.id,
      sku:this.data.sku,
      quantity:this.quantityField ? this.quantityField.value : 1,
      discount:discountName,
      options:optionsArray
    };
  },

  /**
   * Get form values
   * @memberOf Fluid.BuyGiftForm
   */
  getFormValues:function() {
    var formValues;

    if (this.el.$options.length) {
      formValues = this.el.$options.serializeArray();
    }
    else {
      formValues = [];
      var selectedOptions = [];

      if (settings.stockManagement && this.data.definition.stockManagement) {
        for (var key in this.data.stocks) {
          if (this.data.stocks[key] > 0) {
            var optionValues = key.split('_');
            if (optionValues.length == 1)
              break;
            optionValues = optionValues[1].split('-');

            for (var i=0; i<optionValues.length; i++) {
              for (var option in this.data.options) {
                if (this.data.options[option].values['id'+optionValues[i]]) {
                  formValues.push( {name:'optionValue'+this.data.options[option].id, value:optionValues[i]} );
                  selectedOptions.push(this.data.options[option].id);
                }
              }
            }

            break;
          }
        }
      }

      var requiredOptions = [];
      for (var i=0; i<this.requiredOptions.length; i++)
        if ( selectedOptions.indexOf(this.requiredOptions[i]) == -1 )
          requiredOptions.push(this.requiredOptions[i]);

      for (var i=0; i<requiredOptions.length; i++) {
        for (var value in this.data.options['id'+requiredOptions[i]].values) {
          formValues.push( {name:'optionValue'+requiredOptions[i], value:this.data.options['id'+requiredOptions[i]].values[value].id} );
          break;
        }
      }

    }

    return formValues;
  },

  /**
   * Submit event
   * @memberOf Fluid.BuyGiftForm
   * @param {object} event
   */
  submit: function(event) {
    event.preventDefault();

    // Before trigger
    this.trigger('submitBefore', event);

    if (!this.el.$form.isValid())
      return false;

    $.post('/basket/addGift/', JSON.stringify([this.getFormData()]), this.callback, 'json');
    // Disable buy button
    this.el.$buyGiftFormSubmit.prop('disabled', true);

    // Callback trigger
    this.trigger('submitCallback', event);
  },

  /**
   * Callback
   * @memberOf Fluid.BuyGiftForm
   */
  callback: function(result) {
    // Before trigger
    this.trigger('callbackBefore');

    // Enable buy button
    this.el.$buyGiftFormSubmit.prop('disabled', false);

    if (result.statusCode == 200 && result.response.ADDED == 0)
      location.reload();

    // Callback trigger
    this.trigger('callback');
  }
});

/**
 * @class Fluid.LoginForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.LoginForm = Fluid.Form.extend({
  name : 'loginForm',
  initialize : function(){
    var fluidVerifyUser = this.el.$form.data('fluidVerifyUser');
    var fluidSendVerifyUser = this.el.$form.data('fluidSendVerifyUser');
    var fluidSendedMessage = this.el.$form.data('fluidSendedMessage');

    if(fluidVerifyUser || fluidSendVerifyUser){

      var modalId = 'modalVerifyUser';
      var modalClass = 'verifyUser';

      var message = languageSheet.LBLGENERICWAITFOREMAILVERIFICATION;

      if(fluidVerifyUser){
        if(fluidVerifyUser == 'sms')
          message = languageSheet.LBLGENERICWAITFOREMAILANDSMSVERIFICATION;

      }else if(fluidSendVerifyUser){
        modalId = 'modalSendVerifyUser';
        modalClass = 'sendVerifyUser';

        if(fluidSendVerifyUser == 'sms')
          message = languageSheet.LBLGENERICWAITFOREMAILANDSMSVERIFICATION;

      }

      if(fluidSendedMessage == -1) // SMS limit reached
        message = languageSheet.LBLGENERICVERIFYMAILLIMITREACHED;
      else if(fluidSendedMessage <= 0) // Error sending SMS / SMS not sended
        message = languageSheet.LBLGENERICVERIFYMAILERROR;

      var boxMainDiv = $('<div />', {
        'class':'question ' + modalId + ' ' + modalClass,
        html: '<div class="questionText '+modalClass+'Text">'+message+'</div>'
      });
      $('div#userVerifyAccountFormContainer form#verifyAccountForm').appendTo(boxMainDiv);

      boxMainDiv.box({
        uid : modalId,
        showFooter : false,
        type : 'html',
        size : 'medium',
        triggerOnClick:false
      });
    }
  },

  callback : function(result) {
    if (this.trigger('callbackSubsitute') || this.trigger('callbackSubstitute', result)) {
      return;
    }

    // Before trigger
    this.trigger('callbackBefore', result);

    if (!result.response) {
      this.showMessage(result.errorDetail? result.errorDetail : 'Error', 'danger');
    }
    else {
      if (result.response.LOGGEDIN) {
        if (typeof window.BrainSINSTrackedUser == 'undefined') {
          window.BrainSINSTrackedUser = 0;
        }
        /*REPORT TO BRAINSINS USER LOGGED*/
        if (window.BrainSINSTracker && result.response.HASBRAINSINS && window.BrainSINSTrackedUser == 0) {
          if (result.response.SUBSCRIBED) {
            BrainSINSTracker.trackEMailNewsletter( $('userLoginEmailField').value, result.response.SUBSCRIBED, result.response.LANG );
            //BrainSINSTracker.trackEMail($('userLoginEmailField').value);
          } else {
            /*NOT SUBSCRIBED*/
            BrainSINSTracker.trackEMailNewsletter( $('userLoginEmailField').value, 0 , result.response.LANG );
            //BrainSINSTracker.trackEMail($('userLoginEmailField').value);
          }
        }
        var redirectURL = [location.protocol, '//', location.host, location.pathname].join('');
        if (result.response.REDIRECT) {
          var redirectPath = [location.protocol, '//', location.host];
          if (result.response.REDIRECT.charAt(0) !== "/") {
            redirectPath.push("/");
          }
          redirectPath.push(result.response.REDIRECT);
          redirectURL = redirectPath.join('');
        }
        window.location = redirectURL;
      } else {
        this.showMessage(result.response.MESSAGE, 'danger');
      }
    }
    // Callback trigger
    this.trigger('callback', result);
  }
});

/**
 * @class Fluid.DeleteWishListForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.DeleteWishListForm = Fluid.Form.extend({
  name: 'deleteWishListForm',
  options: {},
  initialize: function(form) {

    // Before trigger
    this.trigger('initOptionsBefore');

    this.initElements();

    // Callback trigger
    this.trigger('initializeCallback');

  },
  initElements: function() {

    // Before trigger
    this.trigger('initOptionsBefore');

    this.el.$submit = this.el.$form.find('button[type="submit"]');
    this.el.$options = this.el.$form.find('input[type="checkbox"]');

    // Callback trigger
    this.trigger('initOptionsCallback');

  },
  getFormValues: function() {

    // Before trigger
    this.trigger('getFormValuesBefore');

    formValues = [];
    if (this.el.$options.length) {
      this.el.$options.each(function (i, obj) {
        if (obj.checked)
          formValues.push(obj.value);
      });
    }

    // Callback trigger
    this.trigger('getFormValuesCallback');

    return formValues;
  },
  getFormData: function() {
    return {
      productIdList:this.getFormValues(),
    };
  },
  submit: function (event) {

    // Before trigger
    this.trigger('submitBefore');

    event.preventDefault();

    var formData = this.getFormData()

    // 20160506BVFL-01
    if (formData.productIdList.length > 0) {
      $.post('/user/deleteWishlist', JSON.stringify(formData), this.callback.bind(this), "json");
      this.el.$submit.prop('disabled', true);
    }


    // Before trigger
    this.trigger('submitCallback');
  },
  callback : function (result) {

    this.el.$submit.prop('disabled', false);

    if (!result.response) return;

    // Reload
    window.location = '/user/wishlist';
  }
});

/**
 * @class Fluid.productSubscribeStockForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.ProductSubscribeStockForm = Fluid.Form.extend({
  name: 'productSubscribeStockForm',
  options: {},
  initialize: function(form) {

    // Before trigger
    this.trigger('initOptionsBefore');

    this.data = this.el.$form.data('productStock');
    this.initElements();

    // Callback trigger
    this.trigger('initializeCallback');

    $.validate(Fluid.validateFormConf);
  },
  initElements: function() {

    // Callback trigger
    this.trigger('initOptionsBefore');

    this.el.$submit = this.el.$form.find('input[type="submit"]');
    this.el.userEmail = F('input[type="text"]', this.el.form);
    this.el.agreement = F('input[type="checkbox"]', this.el.form);

    // Callback trigger
    this.trigger('initOptionsCallback');

  },
  getFormValues: function() {

    // Before trigger
    this.trigger('getFormValuesBefore');

    var dataProductStock = $('#' + this.el.form.id).data('productStock');

    formValues = {};
    formValues.userEmail = this.el.userEmail.value;
    formValues.agreement = this.el.agreement.checked;
    formValues.stockId = dataProductStock.stockId;
    formValues.productId = dataProductStock.productId;

    // Callback trigger
    this.trigger('getFormValuesCallback');

    delete dataProductStock;

    return formValues;
  },
  getFormData: function() {
    var formDataValues = this.getFormValues();
    return {
      stockId:formDataValues.stockId,
      productId:formDataValues.productId,
      userMail:formDataValues.userEmail,
      agreeement:formDataValues.agreement,
    };
  },
  submit: function (event) {
    event.preventDefault();

    // Before trigger
    this.trigger('submitBefore');

    if (!this.el.$form.isValid())
      return false;

    this.el.$submit.prop('disabled', true);

    var formData = this.getFormData();

    $.post('/product/subscribe/stock', JSON.stringify(formData), this.callback.bind(this), "json")

    // Callback trigger
    this.trigger('submitCallback');
  },
  callback : function (result) {

    this.el.$submit.prop('disabled', false);

    if (!result.response) return;
    this.showMessage(result.response.MESSAGE, result.response.SENT == 1 ? 'success' : 'danger');
    
    // Callback trigger
    this.trigger('callback', result);

  }
});

/**
 * @class Fluid.SponsorshipForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.SponsorshipForm = Fluid.Form.extend({
  name: 'sponsorshipForm',
  emails: {},
  initialize: function(form) {

    // Before trigger
    this.trigger('initOptionsBefore');

    this.initElements();

    // Callback trigger
    this.trigger('initializeCallback');
  },
  initElements: function() {

    // Before trigger
    this.trigger('initOptionsBefore');

    this.el.$submit = this.el.$form.find('button[type="submit"]');
    this.el.$emails = this.el.$form.find('input[type="text"]');
    this.el.$message = this.el.$form.children('.form-message');

    // Callback trigger
    this.trigger('initOptionsCallback');
  },
  callback : function (result) {

    if (!result || result.statusCode != 200) return;

    this.el.$submit.prop('disabled', false);
    this.showMessage(result.response.MESSAGE, result.response.SENT == 1 ? 'success' : 'danger');
  }
});

Fluid.CustomTagAttachment = function(container){

  this.init = function(container){
    this.$container = $(container);
    this.ct = this.$container.data('ct');
    this.$textInput = this.$container.find('input');
    this.$uploadButton = $('<span class="button upload">').attr("title", languageSheet.UPLOADFILE).tooltip().appendTo(this.$container);
    this.$fileInput = $('<input type="file" name="file">').appendTo(this.$uploadButton);

    this.$viewButton = $('<span class="button view">').attr("title", languageSheet.VIEW).tooltip().click(this.viewFile.bind(this));
    this.$deleteButton = $('<span class="button delete">').attr("title", languageSheet.DELETE).tooltip().click(this.clear.bind(this));
    this.$ct =  $('<input type="hidden" name="ct">').val(this.ct);

    this.addEvents();
    this.draw();
  };

  this.draw = function(){
    if( this.$textInput.val() ){
      this.$container.addClass("full");
      this.$deleteButton.appendTo(this.$container);
      this.$viewButton.appendTo(this.$container);
    }
    else{
      this.$container.removeClass("full");
      this.$deleteButton.detach().tooltip('hide');
      this.$viewButton.detach().tooltip('hide');
    }
    this.$fileInput.appendTo(this.$uploadButton);
  };

  this.addEvents = function(){
    this.$fileInput.change( this.onChange.bind(this) );
  };

  this.viewFile = function(){
    window.open("/user/ct/"+this.ct);
  };

  this.onChange = function(){
    this.uploadFile();
  };

  this.clear = function(){
    this.$textInput.val("");
    this.draw();
  };

  this.uploadFile = function(){
    this.$uploadButton.tooltip('hide');
    var id = new Date().getMilliseconds();
    var frame = $('<iframe/>', {id:id, frameborder:'no', name:id, style:'width: 0px; height: 0px; display: none;'});
    var form = $('<form/>', {action:'/user/ct', method:'post', enctype:'multipart/form-data', target:id, styles:'width: 0px; height: 0px; display: none;'});
    this.$ct.appendTo(form)
    frame.appendTo(document.body);
    form.appendTo(document.body);
    frame.on('load', this.onFileUploaded.bind(this, frame) );
    this.$fileInput.appendTo(form);
    this.$container.addClass('uploading');
    form.submit();
  };

  this.onFileUploaded = function(frame){
    this.$container.removeClass('uploading');
    result = $.parseJSON(frame.get(0).contentWindow.document.body.innerText);
    if(result.statusCode == 200 && result.response.SUCCEEDED)
      this.$textInput.val(result.response.FILE);
    this.draw();
  };

  this.init(container);

}

/**
 * @class Fluid.UserForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.UserForm = Fluid.Form.extend({
  name : 'userForm',
  userType : 1,

  /**
   * Used for get DOM elements
   * @type {String}
   */
  prefix : 'user',

  /**
   * Initialize form method
   * @memberOf Fluid.UserForm
   * @return {void}
   */
  initialize : function() {

    var sendVerifyMail = this.el.$form.find('input[name="sendVerifyMail"]').val();
    var verifiedAccount = this.el.$form.find('input[name="verifiedAccount"]').val();

    if(sendVerifyMail || verifiedAccount){

      var message = languageSheet.LBLGENERICWAITFOREMAILVERIFICATION;

      if(sendVerifyMail == 2)
        message = languageSheet.LBLGENERICWAITFOREMAILANDSMSVERIFICATION
      else if(verifiedAccount)
        message = languageSheet.LBLVERIFYEMAILSUCCEED;

      var boxMainDiv = $('<div />', {
        'class':'question modalVerifyUser verifyUser',
        html: '<div class="questionText verifyUserText">'+message+'</div>'
      });

      if(sendVerifyMail)
        $('div#userVerifyAccountFormContainer form#verifyAccountForm').appendTo(boxMainDiv);

      boxMainDiv.box({
        uid : 'modalVerifyUser',
        showFooter : false,
        type : 'html',
        size : 'medium',
        triggerOnClick:false
      });

    }

    //Get Elements
    this.el.userTypes = F('input[type="radio"][name="userType"]', this.el.form, true);
    this.el.userTabTypes = F('a[role="tab"]', this.el.form, true);
    this.el.$userFields = $('#userFormFieldsContainer');
    this.el.$shippingFields = $('#shippingAddressFormFieldsContainer');
    this.el.$shippingAddressContainer = $('#shippingAddressContainer');
    this.el.useShippingAddress = F('#useShippingAddress');
    this.el.useShippingAddressBook = F('#useShippingAddressBook');
    this.el.checkCreateAccount = F('input[type="checkbox"][name="signIn"]', this.el.form);
    this.el.$signInFormField = this.el.$form.find('.signInFormFieldsContainer');
    this.el.$userTypeField = this.el.$form.find('input#userTypeField');

    // Get message container
    this.el.$message = this.el.$form.children('.form-message');

    if (!this.el.$message.length)
      this.el.$message = $('<div />', {
        "class":"form-message"
      }).prependTo(this.el.$form);

    // initialize calendar
    //$(this.el.form).find('input[rel="calendarField"]').ionDatePicker();

    var dateFields = this.el.$form.find('div[data-datetimepicker]').each(function(index,el) {
      var $calendar = $(el);

      // Options
      var language = $calendar.data('language');
      var format = $calendar.data('format');
      var startDate = $calendar.data('startdate');
      var endDate = $calendar.data('enddate');

      $calendar.datetimepicker({
        locale : language? language : 'en',
        format : format? format : 'DD/MM/YYYY',
        startDate : startDate,
        endDate : endDate
      });
    });

    //Define Form Fields
    this.formFields = {};
    if (this.el.$userFields)
      this.formFields.userFields = this.el.$userFields.data('formFields');

    if (this.el.$shippingFields)
      this.formFields.shippingFields = this.el.$shippingFields.data('formFields');

    //Set userType
    //this.userType = this.el.$form.data('userType');
    this.userType = this.el.$userTypeField.length ? this.el.$userTypeField.val() : this.el.$form.data('userType');


    //Add events (bootstrap or others)
    if (window.htmlFramework == "bootstrap") {
      for (var i = 0; i < this.el.userTabTypes.length; i ++) {
        var ev = {target:{value:$(this.el.userTabTypes[i]).data('value')}};
        this.el.userTabTypes[i].addEventListener('click',
          this.setUserFormFields.bind(this,ev)
        );
        $(this.el.userTabTypes[i]).tab();
      }
    } else {
      for (var i = 0; i < this.el.userTypes.length; i ++) {
        this.el.userTypes[i].addEventListener('click',
          this.setUserFormFields.bind(this)
        );
      }
    }

    // Shipping address
    if (this.el.useShippingAddress) {
      this.el.useShippingAddress.addEventListener('click',
        this.toggleShippingAddress.bind(this)
      );
    }

    // Shipping address Book
    if (this.el.useShippingAddressBook) {
      this.el.useShippingAddressBook.addEventListener('click',
        this.toggleShippingAddressBook.bind(this)
      );
    }

    // Create account
    if (this.el.checkCreateAccount) {
      // Get Required elements
      this.createAccountRequiredElements = this.el.$signInFormField.find('input.required');

      // Event
      this.el.checkCreateAccount.addEventListener('click',
        this.toggleCreateAccount.bind(this)
      );
    }

    //Initialize view
    this.setUserFormFields();

    // 20160608DBCM-01
    this.el.$editable = this.el.$form.find('input[name="editable"]');

    this.el.$form.find('div.addressUserField').each(function(idx, el){
      setAddressCompleted($(el));
    });

    this.el.$form.find('.attachment').each(function(idx, el){new Fluid.CustomTagAttachment(el);});

    if (this.el.$editable && this.el.$editable.attr('value') == 0)
      this.disableForm();

  },

  /**
   * Disable user form
   * @memberOf Fluid.UserForm
   * @param {object} ev event type
   */
  disableForm : function() {
    // Disable all elements from form.
    this.el.$form.find('input:not([name="editable"], [name="callback"], [name="formContext"])').prop('disabled', 'disabled').addClass('disabled');
    this.el.$form.find('select').prop('disabled', 'disabled').addClass('disabled');
    this.el.$form.find('[data-fluid-function="editAddressBook"]').remove();
    this.el.$form.find('[data-fluid-function="addAddressBook"]').remove();
    // Destroy action buttons from form
    this.el.$form.find('.legalTextLinks').remove();
    this.el.$form.find('.basketButtons').remove();
  },

  /**
   * Prepare visible and required User fields
   * @memberOf Fluid.UserForm
   * @param {object} ev event type
   */
  setUserFormFields : function(ev) {
    //Get userType
    if (!this.userType || ev && ev.target.value)
      this.userType = ev.target.value;

    this.setFormFields(this.userType, this.formFields.userFields, this.el.$userFields);

    if (this.formFields.shippingFields && this.el.$shippingFields) {
      this.setFormFields(this.userType, this.formFields.shippingFields, this.el.$shippingFields);
      if(this.el.useShippingAddress && !this.el.useShippingAddress.checked)
        this.removeRequiredFields(this.formFields.shippingFields, this.el.$shippingFields);
    }

    // Initialize Validation form
    $.validate(Fluid.validateFormConf);
  },

  /**
   * Show/hide shipping address
   * @memberOf Fluid.UserForm
   * @param  {object} ev Triggered event
   */
  toggleShippingAddress : function(ev){
    if (ev.target.checked) {
      this.setFormFields(this.userType, this.formFields.shippingFields, this.el.$shippingFields);
      this.el.$shippingFields.show();

      if (typeof settings != 'undefined' &&  $('#userShippingCountryField') && $('#userCountryField')) {
        if (settings.forceBillingAddressCountry && $('#userFieldShippingCountryContainer .countriesSelector') && $('#userCountryField option:selected').val() != $('#userShippingCountryField option:selected').val() ) {
          $('#userShippingCountryField').find('option').remove().end().append($('<option>', {value:$('#userCountryField option:selected').val()}).text($("#userCountryField option:selected").text()));
          loadSubcountries($('#userCountryField option:selected').val(), 0, $('#userShippingCountryField').attr('data-field'), 'shippingCountry', 'userField');
        }
      }
    }
    else{
      this.el.$shippingFields.hide();
      this.removeRequiredFields(this.formFields.shippingFields, this.el.$shippingFields);
    }
  },
  /**
   * Show/hide shipping adress book section
   * @memberOf Fluid.UserForm
   * @param  {object} ev Triggered event
   */
  toggleShippingAddressBook : function(ev){
    if (ev.target.checked) {
      this.el.$shippingAddressContainer.show();
      $(useShippingAddress).attr('value', 1);
    }
    else{
      this.el.$shippingAddressContainer.hide();
      $(useShippingAddress).attr('value', 0);
    }
  },
  /**
   * Show/hide create account
   * @memberOf Fluid.UserForm
   * @param  {object} ev Triggered event
   */
  toggleCreateAccount : function(ev){
    if (ev.target.checked){
      this.el.$signInFormField.show();
      this.createAccountRequiredElements.each((function(index, el) {
        var dataValidation = this.setValidationData($(el), true);
        $(el).data('validation', dataValidation);
        el.setAttribute('data-validation', dataValidation);
      }).bind(this));
    }
    else {
      this.el.$signInFormField.hide();
      this.createAccountRequiredElements.each((function(index, el) {
        var dataValidation = this.setValidationData($(el), false);
        $(el).data('validation', dataValidation);
        el.setAttribute('data-validation', dataValidation);
      }).bind(this));
    }
    // RE-Initialize Validation form
    $.validate(Fluid.validateFormConf);
  },

  /**
   * setValidationData
   * @param {object} $formField jQuery DOM Element
   * @param {boolean} required  set required field
   */
  setValidationData : function($formField, required){
    var dataValidation = $formField.data('validation') || "";
    var dataValidationTypes = $formField.data('validationTypes');
    var arrDataValidationTypes = [];

    if (dataValidationTypes && typeof dataValidationTypes == 'object')
      for (var key in dataValidationTypes)
        arrDataValidationTypes.push(dataValidationTypes[key].toLowerCase());
    else
      var arrDataValidationTypes = [];
  
    var arrElements = arrDataValidationTypes.concat(["email", "phone", "vat", "vat_es"]);

    var arrValidation = required? ["required"] : [];
    for (var j = 0; j < arrElements.length; j++) {
      if (dataValidation.toLowerCase().indexOf(arrElements[j]) >= 0)
        arrValidation.push(arrElements[j]);
    };
    return arrValidation.join(",");
  },

  /**
   * Callback function. Redirects on success or show error message
   * @memberOf Fluid.UserForm
   * @param  {object}   result object from JSON response
   */
  callback : function(result) {
    
    this.el.$form.find('button[type="submit"], input[type="submit"]').attr('disabled',true);
    // Before trigger
    this.trigger('callbackBefore', result);

    if (result.response) result = result.response;

    if (!result) {
      var message = result.errorDetail || languageSheet.ERROR;
      var success = 0;
    } else {
      var message = result.MESSAGE || languageSheet.SAVED;
      var success = result.SUCCESS || 0;
    }


    if (success) {
      this.showMessage(message, 'success');

      if (result.REDIRECT && (result.hasOwnProperty("REDIRECTMODE") && result.REDIRECTMODE != false)){
        window.location = result.REDIRECT;
        return;
      }

    } else {
      var mainAddressError = false, shippingAddressError = false;

      if (result.CODE && (result.CODE == "UF4" || result.CODE == "TLG0100007")) {
        message = languageSheet.USERADDRESSERROR;
        mainAddressError = true;
      } else if (result.CODE && (result.CODE == "USF4" || result.CODE == "TLG0100008")) {
        message = languageSheet.USERADDRESSERROR;
        shippingAddressError = true;
      } else if (result.CODE && result.CODE == "TLG0100009") {
        message = languageSheet.USERADDRESSCOUNTRYERROR;
      }

      this.el.$form.find('input[name="billingAddress"]').parent('div.billingAddress').removeClass('has-error');
      this.el.$form.find('input[name="shippingAddress"]').parent('div.shippingAddress').removeClass('has-error');

      if(mainAddressError)
        this.el.$form.find('input[name="billingAddress"]:checked').parent('div.billingAddress').addClass('has-error');
      else if(shippingAddressError)
        this.el.$form.find('input[name="shippingAddress"]:checked').parent('div.shippingAddress').addClass('has-error');

      this.showMessage(message, 'danger');
      if (result.CODE && result.CODE == "TLG1004") {
        new Fluid.VinculateSocialAccountEmailPopupForm();
      }

    }
    this.el.$form.find('button[type="submit"], input[type="submit"]').attr('disabled', false);
    // Callback trigger
    this.trigger('callback', result);
  },

  /**
   * Callback function. Redirects on success or show error message
   * @memberOf Fluid.UserForm
   * @param  {object} form
   */
  validateAdditionalShippings: function(form) {
    if (form.find('input[name="useShippingAddress"]').attr('value') == 1 && form.find('input[name="shippingAddress"]').length == 0) {
      this.showMessage(languageSheet.INSERTONEADDRESS, 'danger');
      return false;
    }
    return true;
  },

  /**
   * Submit form
   * @memberOf Fluid.UserForm
   * @param  {Object} event
   */
  submit: function(event) {

    // Checking if this shop has multiples adress book
    if (this.el.$form.find('input[name="billingAddress"]').length>0)
      if (!this.validateAdditionalShippings(this.el.$form))
        return false;

    this.superForm('submit', event);
  }
}, Fluid.userFormResources);

/**
 * @class Fluid.userAddressBookForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.userAddressBookForm = Fluid.Form.extend({
  name : 'userAddressBookForm',

  /**
   * Used for get DOM elements
   * @type {String}
   */
  prefix : 'userAddressBook',
  userType : 1,

  /**
   * Initialize form method
   * @memberOf Fluid.userAddressBookForm
   * @return {void}
   */
  initialize : function(){
    //Get Elements
    this.el.$userAddressBookFields = $('#userAddressBookFormFieldsContainer');

    // Visible fields
    if (this.el.form.visibleFields) {
      this.visibleFields = this.el.form.visibleFields;
    } else {
      this.visibleFields = {
        billing: ["name","address"],
        shipping: ["name","address"]
      };
    }

    /* User type in addresBook */
    this.el.userTypes = F('input[type="radio"][name="userType"]', this.el.form, true);
    this.el.userTabTypes = F('a[role="tab"]', this.el.form, true);
    this.el.$userAddressBookTypeField = this.el.$form.find('input#userAddressBookTypeField');
    this.userType = this.el.$userAddressBookTypeField.length ? this.el.$userAddressBookTypeField.val() : this.el.$form.data('userType');

    //Add events (bootstrap or others)
    if(window.htmlFramework == "bootstrap"){
      for(var i=0; i<this.el.userTabTypes.length; i++){
        var ev = {target:{value:$(this.el.userTabTypes[i]).data('value')}};
        this.el.userTabTypes[i].addEventListener('click',
          this.setUserAddressBookFormFields.bind(this,ev)
        );
        $(this.el.userTabTypes[i]).tab();
      }
    }else{
      for(vari=0; i<this.el.userTypes.length; i++){
        this.el.userTypes[i].addEventListener('click',
          this.setUserAddressBookFormFields.bind(this)
        );
      }
    }

    /*
    if (window.htmlFramework == "bootstrap") {
      for (var i = 0; i < this.el.userTabTypes.length; i ++) {
        var ev = {target:{value:$(this.el.userTabTypes[i]).data('value')}};
        this.el.userTabTypes[i].addEventListener('click',
          this.setUserFormFields.bind(this,ev)
        );
        $(this.el.userTabTypes[i]).tab();
      }
    } else {
      for (var i = 0; i < this.el.userTypes.length; i ++) {
        this.el.userTypes[i].addEventListener('click',
          this.setUserFormFields.bind(this)
        );
      }
    }
    */

    /* User type in addresBook */

    // Get message container
    this.el.$message = this.el.$form.children('.form-message');

    if (!this.el.$message.length)
      this.el.$message = $('<div />', {
        "class":"form-message"
      }).prependTo(this.el.$form);

    // initialize calendar
    //$(this.el.form).find('input[rel="calendarField"]').ionDatePicker();
    
    var dateFields = this.el.$form.find('div[data-datetimepicker]').each(function(index,el){
      var $calendar = $(el);
      // Options
      var language = $calendar.data('language');
      var format = $calendar.data('format');
      var startDate = $calendar.data('startdate');
      var endDate = $calendar.data('enddate');
      
      $calendar.datetimepicker({
        locale : language? language : 'en',
        format : format? format : 'DD/MM/YYYY',
        startDate : startDate,
        endDate : endDate
      });
    });

    //Define Form Fields
    this.formFields = {};
    if (this.el.$userAddressBookFields)
      this.formFields.userAddressBookFields = this.el.$userAddressBookFields.data('formFields');

    //Initialize view
    this.setUserAddressBookFormFields();
  },

  /**
   * Prepare visible and required User fields
   * @memberOf Fluid.UserAddressBookForm
   * @param {object} ev event type
   */
  setUserAddressBookFormFields : function(ev){
    //Get userType
    if (!this.userType || ev && ev.target.value)
      this.userType = ev.target.value;

    this.setFormFields(this.userType, this.formFields.userAddressBookFields, this.el.$userAddressBookFields);

    this.el.$form.find('div.addressUserField').each(function(idx, el){
      setAddressCompleted($(el));
    });

    // Initialize Validation form
    $.validate(Fluid.validateFormConf);
  },

  /**
   * Callback function. Redirects on success or show error message
   * @memberOf Fluid.userAddressBookForm
   * @param  {object}   result object from JSON response
   */  
  callback: function(result){

    var actionType = result.response.TYPE == 1 ? 'billing' : 'shipping';
    var classType = result.response.TYPE == 1 ? '.billing' : '.shipping';
    var nameType = result.response.TYPE == 1 ? 'billingAddress' : 'shippingAddress';

    /** 
      display mode:
      1) popup
      2) accordion form
     */

    // Getting display mode
    this.mode = 1; 
    // Detail information into box address item.
    var showAddressInformation = $('#showAddressInformation').attr('value')

    if (this.el.$form.find('input[name="mode"]').length > 0)
      this.mode = this.el.$form.find('input[name="mode"]').attr('value');

    // Getting Target
    if (this.mode == 2)
      var $target = $('#'+actionType+'Target');

    // Before trigger
    this.trigger('callbackBefore', result);

    // Default action
    if (typeof result === 'undefined')
      return;
    if (!result.response) {
      var message = result.errorDetail? result.errorDetail : 'Error';
      var success = 0;
    } else {
      var message = result.response.MESSAGE;
      var success = result.response.SUCCESS ? result.response.SUCCESS : 0;
    }

    /**
      @callback types:
      1) redirect to page.
      2) update elements on current page.
     */
    if (success) {
      if (result.response.CALLBACK == 2) {
        if (this.mode == 1)
          $(addressBookFormModal).modal('hide');
        else
          $target.remove();
        
        this.showMessage(languageSheet.LBLGENERICUSERADDRESSBOOKSAVEDATA, 'success');

        // Updating elements related with selected address by action response.
        if (result.response.ACTION === 'updated') 
            $(classType).find('label[name="'+nameType+'_'+result.response.SAVEDID+'"]').html(result.response.ALIAS);
        else if (result.response.ACTION === 'added')
        {
          var item = '<div id="addressBookContainer_'+result.response.SAVEDID+'" class="addressBook '+nameType+'">';
              item+= '<input type="radio" name="'+nameType+'" id="'+nameType+'_'+result.response.SAVEDID+'" value="'+result.response.SAVEDID+'" />';
              item+= '<label for="'+nameType+'_'+result.response.SAVEDID+'" name="'+nameType+'_'+result.response.SAVEDID+'" class="field">'+result.response.ALIAS+'</label>';
              item+= '</div>';
              $item = $(item);
          $('<a />', {
            'html' : languageSheet.EDITADDRESS,
          }).data('fluidData',{'mode':this.mode,'id':result.response.SAVEDID, 'type':result.response.TYPE}).on('click', Fluid.dataEvents.editAddressBook).appendTo($item);
          $item.appendTo(classType+' .content');
          if (showAddressInformation)
            $('<div>', {'class':'box '+nameType+'Box'}).appendTo($item);
        }                

        $('#'+nameType+'_'+result.response.SAVEDID).prop('checked', true);        
        if (showAddressInformation) {
          var $box = $('#addressBookContainer_'+result.response.SAVEDID).find('.'+nameType+'Box');
          $box.html('');

          for (var i = 0; i < this.visibleFields[actionType].length; i++) {
            var fieldName = this.visibleFields[actionType][i];
            switch(this.visibleFields[actionType][i]) {
              case "name": 
                if (result.response.NAME) {
                  $('<div />', {'class':'field name', html:result.response.NAME}).appendTo($box);
                }
                break;

              case "address":
                var $address = $('<div />', {'class':'field address'}); 
                if (result.response.ADDRESS)
                  $('<span />', {'class':'address', html:result.response.ADDRESS}).appendTo($address);
                if (result.response.CITY)
                  $('<span />', {'class':'city', html:result.response.CITY}).appendTo($address);
                if (result.response.STATE)
                  $('<span />', {'class':'state', html:result.response.STATE}).appendTo($address);
                if (result.response.ZIP)
                  $('<span />', {'class':'zip', html:result.response.ZIP}).appendTo($address);
                if (result.response.COUNTRY)
                  $('<span />', {'class':'country', html:result.response.COUNTRY}).appendTo($address);
                $address.appendTo($box);
                break;

              case "nif":
                if (result.response.NIF) {
                  $('<div />', {'class':'field nif', html:result.response.NIF}).appendTo($box);
                }
                break;
              case "phone":
                if (result.response.PHONE) {
                  $('<div />', {'class':'field phone', html:result.response.PHONE}).appendTo($box);
                }
                break;
              case "mobile":
                if (result.response.MOBILE) {
                  $('<div />', {'class':'field mobile', html:result.response.MOBILE}).appendTo($box);
                }
                break;
            }
          }

          $(classType).find('span.notAvailableAddress').remove();
        }
      }
      else {
        var strCurrentURL = [location.protocol, '//', location.host, location.pathname].join('');
        window.location = (result.response.REDIRECT || strCurrentURL);        
      }
    }
    else{ this.showMessage(message, 'danger'); }

    // Callback trigger
    this.trigger('callback', result);
  }
}, Fluid.userFormResources);   

/**
 * @class Fluid.ContactForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.ContactForm = Fluid.Form.extend({
  name : 'contactForm',
  callback : function(result){
    this.message = "";
    this.success = 0;

    if (!result.response) {
      this.message = (result.errorDetail? result.errorDetail : 'Error');
      this.success = 0;
    } else {
      this.message = result.response.MESSAGE;
      this.success = (result.response.SUCCESS? result.response.SUCCESS : 0);
    }

    this.showMessage(this.message,this.success?'success':'danger');
    this.trigger('callback');
  },

  onComplete: function(result) { }
});

/**
 * @class Fluid.ChangePasswordForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.ChangePasswordForm = Fluid.Form.extend({
  name : 'changePasswordForm',
  callback : function(result) {
    this.showMessage(result.response.MESSAGE, result.response.SUCCEEDED && result.response.SUCCEEDED == 1 ? 'success' : 'danger');

    if(result.response.SUCCEEDED && result.response.SUCCEEDED == 1)
      setTimeout(function() {window.location = '/user';}, 3000);
  }
});

/**
 * @class Fluid.ConfirmAccountForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.ConfirmAccountForm = Fluid.Form.extend({
  name : 'confirmAccountForm',
  callback : function(result) {
    this.showMessage(result.response.MESSAGE, result.response.SUCCEEDED && result.response.SUCCEEDED == 1 ? 'success' : 'danger');

    if(result.response.SUCCEEDED && result.response.SUCCEEDED == 1)
      setTimeout(function() {window.location = '/user';}, 5000);
  }
});

/**
 * @class Fluid.LostPasswordForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.LostPasswordForm = Fluid.Form.extend({
  name : 'lostPasswordForm',
  callback : function(result) {

    if (!this.trigger('callback', result.response)) {
      this.showMessage(result.response.MESSAGE, result.response.SUCCESS && result.response.SUCCESS == 1 ? 'success' : 'danger');

      if(result.response.REDIRECT)
        setTimeout(function() {window.location = result.response.REDIRECT;}, 3000);
    }
  }
});

/**
 * @class Fluid.DeleteAccountForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.DeleteAccountForm = Fluid.Form.extend({
  name : 'deleteAccountForm',
  callback : function(result) {
    this.showMessage(result.response.MESSAGE, result.response.SUCCEEDED && result.response.SUCCEEDED == 1 ? 'success' : 'danger');
    if(result.response.SUCCEEDED && result.response.SUCCEEDED == 1)
      setTimeout(function(){ window.location='/logout'; }, 1000);
  }
});

/**
 * @class Fluid.SearchForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 *
 * @TODO get name page from SEO url
 */
Fluid.SearchForm = Fluid.Form.extend({
  name : 'searchForm',
  initialize: function() {
    // Doofinder

    var doofinderOptions = this.el.$form.data('doofinderOptions');
    var doofinderSearchUrl = this.el.$form.data('doofinderUrl');
    var doofinderVersion = this.el.$form.data('doofinderVersion');

    if (typeof doofinderOptions === "object" && !$.isEmptyObject(doofinderOptions) && typeof window.doofinder !== 'object') {
      if (!window.doofinder) window.doofinder={};
      
      if (doofinderVersion == "fullscreen") {            
        window.dfFullscreenLayers = [doofinderOptions];
        //convert callback string to functions with eval function
        if(window.dfFullscreenLayers.length && typeof window.dfFullscreenLayers[0].callbacks != 'undefined'){
          jQuery.each(window.dfFullscreenLayers[0].callbacks, function(field,val) {
            window.dfFullscreenLayers[0].callbacks[field] = eval('(' + val + ')');
          });              
        }
      } else {
        window.dfClassicLayers = [doofinderOptions];
      }

      doofinder.doofinderLoaded = false;
      doofinder.loadDoofinder = function() {
        var doofinderSrc = doofinderSearchUrl;
        Fluid.require.js(doofinderSrc);
      };
      doofinder.loadDoofinder();
    }
  },
  submit : function(event,el) {
    event.preventDefault();


    // Initialize and set vars
    var action = '/search';
    var data = {};
    var arrDataForm = this.el.$form.serializeArray();
    //Set The minCharacters to 3. If it's diferent we change it, if not....HARDCODED :)
    var minCharacters =3;
    var minCharacters = this.el.$form.data('mincharacters');

    //Fills dataForm
    for (var i = 0; i < arrDataForm.length; i++) {
      if (arrDataForm[i].name == 'searchCriteria') {
        if (arrDataForm[i].value.length < minCharacters && !arrDataForm[i].value.match('[^\x00-\x7F]'))
          return false;

        data.searchCriteria = arrDataForm[i].value;

        //Escape Replace slashes and percents
        //action = '/search/'+ escape(arrDataForm[i].value)
        //  .replace(/\//g, "__2F")
        //  .replace(/\./g, "__2E")
        //  .replace(/\+/g, "__2B")
        //  .replace(/%/g, "__");
      } else {
        data[arrDataForm[i].name] = arrDataForm[i].value;
      }
    }
    //Get the data form values. We have empty values but we want to fill it perhaps that.

        data.searchproducts = this.el.$form.data('searchproducts');
        data.searchcategories = this.el.$form.data('searchcategories');
        data.searchblog = this.el.$form.data('searchblog');
        data.searchpages = this.el.$form.data('searchpages');
        data.searchnews = this.el.$form.data('searchnews');
        data.minCharacters = minCharacters;
    //  20160922DMFLD.0042

    // Location
    window.location = action + (!$.isEmptyObject(data)? '?' + $.param(data):'');

    // Return false...
    return false;
  }
});

/**
 * @class  Fluid.ProductAddCommentForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.ProductAddCommentForm = Fluid.Form.extend({
  initialize : function() {
    // Rating
    this.maxRating = 5;
    this.minRating = 0;
    this.rating();
  },
  rating : function() {
    this.el.$vote = this.el.$form.find('input[name="vote"]');
    this.el.$rating = this.el.$form.find('.productRateValorationContainer');
    this.el.$ratingText = this.el.$form.find('.Valoration > span');

    this.vote = parseFloat(this.el.$vote.val());
    if (this.vote > this.maxRating) this.vote = this.maxRating;
    if (this.vote < this.minRating) this.vote = this.minRating;

    // Create class
    this.el.$rating.addClass('fluidRating');

    // Rating text
    this.el.$ratingText.text(this.vote);

    // Add span
    var strStars = ""
    for (var i = 0; i < this.maxRating; i++) {
      starClass = i < this.maxRating - this.vote? 'inactive' : '';
      strStars += '<span rel="'+i+'" class="'+starClass+'"></span>';
    }
    this.el.$rating.html(strStars);

    // Event click
    this.el.$rating.find('span').click(function(event) {
      // Get Position
      var starPosition = parseInt($(event.currentTarget).attr('rel'));

      // Update view
      this.el.$rating.find('span').removeClass('inactive');
      for (var i = 0; i < starPosition; i++)
        $(this.el.$rating.find('span')[i]).addClass('inactive');

      // Update this.vote
      this.vote = Math.abs(starPosition-this.maxRating);
      this.el.$vote.val(this.vote);
      this.el.$ratingText.text(this.vote);

    }.bind(this));
  }//,
  //callback : function(result) {
  //}
});

/**
 * @class Fluid.CheckoutForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.CheckoutForm = Fluid.Form.extend({
  name : "checkoutForm",
  options : {},

  initialize : function() {

    // Before trigger
    this.trigger('initializeBefore');

    //Initialize quantity elements
    this.el.quantityElements = this.el.$form.find('input.basketQuantity:text');
    this.el.quantityElements.change( this.onChangeQuantity.bind(this) );

    //Initialize options elements
    this.initOptions();

    //Check native number type on input is valid
    /* Temporally commented. It needs improve view
    if (Modernizr.inputtypes.number) {
      this.el.quantityElements.each(function(index, el) {
        el.type = "number";
        el.setAttribute("min", 1);
      });
    }
    */

    // Continue shopping and Clean basket
    this.el.basketButtons = F("#basketClear,#basketContinueShopping", this.el.form, true);
    for (var i = 0; i < this.el.basketButtons.length; i++)
      this.el.basketButtons[i].addEventListener('click', this.buttonSubmit.bind(this));

    //Initialize Discount Code (if exist)
    this.el.discountCodeButton = $("input#discountCodeButton");
    this.el.discountCodeField = $("input#discountCodeField");
    if (this.el.discountCodeButton && this.el.discountCodeField) {
      this.el.discountCodeButton.click(this.onClickDiscountCodeButton.bind(this));
      this.el.discountCodeField.keypress(this.onKeypressDiscountCodeField.bind(this));
    }
    //  20160922DMFLD.0042
    //Binding click event on each trash icon once a giftCode has been added.
    var deleteBalanceCodes = $('span.deleteBalanceCode');

    deleteBalanceCodes.each(function(index,el) {
      $(el).on('click',this.deleteDiscountCode.bind(this, el.value, el));
    }.bind(this));
    //End Binding Click Event
    // ./ 20160922DMFLD.0042

    //Remove title of removeDiscountsSection if no elements. 
    var numElementos = $('.ticketCodesGroup .outputDiscountName').length;
    if(numElementos == 0){
      $('.ticketCodesTitle').remove();
    }

    // Disable warehouses, we enable if it is necessary
    var warehouseElements = $('input.basketSelectorPickUp');
      warehouseElements.each(function(index, el) {
        $(el).on('click', this.setWarehouse.bind(this, el.value, el));
        el.disabled = true;
    }.bind(this));

    //Payment and Shipping
    //Payment
    Fluid.resources.pluginListener('initializePaymentsBefore', this.el.$form, true);

    this.el.paymentSystemSelectors = $('input.paymentSystemSelector:radio');
    //this.el.paymentSystemSelectors.click();
    this.el.paymentSystemSelectors.each(function(index, el) {
      el.addEventListener('click', this.setPaymentSystem.bind(this, el.value));
    }.bind(this));

    Fluid.resources.pluginListener('initializePaymentsCallback', this.el.$form, true);

    //Shipping
    this.el.shippingSection = $('input.shippingTypeSelector:radio');

    this.el.shippingSection.each(function(index, el) {
      el.addEventListener('click', this.setShippingSection.bind(this, el.value, el));

      if (el.checked && $(el).data('pickup') == 1) {
        var warehouseElements = $('input[name="pickUpWarehouse_'+el.value+'"]');
        warehouseElements.each(function(index, el) {
          el.disabled = false;
          $(el).on('click');
        }.bind(this));
      }


    }.bind(this));
   //Fapiao required field if checkbox is checked
      if ($("#inputFapiaoActived").is(":checked")) {
        $('#inputInvoicenameFapiao').attr('data-validation','required');
        $('#selectInvoicenameFapiao').attr('data-validation','required');


      } else { 
        $('#inputInvoicenameFapiao').attr('data-validation','');
        $('#selectInvoicenameFapiao').attr('data-validation','');
      }


     // initialize calendar. Ex: Used by orderCustomTag 
    var dateFields = this.el.$form.find('div[data-datetimepicker]').each(function(index,el) {
      var $calendar = $(el);

      // Options
      var language = $calendar.data('language');
      var format = $calendar.data('format');
      var startDate = $calendar.data('startdate');
      var endDate = $calendar.data('enddate');
      var daysOfWeekDisabled = $calendar.data('daysofweekdisabled');

      /* prevent undefined problem */
      if (typeof(startDate)=='undefined'){
        startDate=0;
      }
      if (typeof(endDate)=='undefined'){
        endDate=0;
      }

       //Init calendar object
      var calendarObject={
        locale : language? language : 'en',
        format : format? format : 'DD/MM/YYYY',
        daysOfWeekDisabled : daysOfWeekDisabled? eval(daysOfWeekDisabled) : eval('')
      };

      /* Calendar init. Note: We can add another else and allow only an startDate or and endDate. Now is only allowed both together. */
      if ((isNaN(startDate) && startDate.length > 0) && (isNaN(endDate) && endDate.length > 0)){
        /* Preparing max and min date. This prevents problems with the no verification with logicommerce */
        var newStartDate = moment(startDate,format);
        var newEndDate = moment(endDate,format);
          
        if (newStartDate > newEndDate){
          calendarObject.minDate = newEndDate;
          calendarObject.maxDate = newStartDate;
        }else{
          calendarObject.minDate = newStartDate;
          calendarObject.maxDate = newEndDate;
        }
        
      }
      else if (isNaN(startDate) && startDate.length > 0 )
        calendarObject.minDate = moment(startDate, format);
      else if (isNaN(endDate) && endDate.length > 0 )
        calendarObject.maxDate = moment(endDate, format);

      //Fill the object with current values
      $calendar.datetimepicker(calendarObject);
    });
    
    // Callback trigger
    this.trigger('initializeCallback');

    // Binding event for send action in post.
    var self = this;
    this.el.$form.find('button[type="submit"], input[type="submit"]').on('click', self.onSubmit.bind(self));
  },

  /**
   * Init options
   * @memberOf Fluid.CheckoutForm
   */
  initOptions:function() {

    // Before trigger
    this.trigger('initOptionsBefore');

    this.el.$options = this.el.$form.find('select.productOptionSelectValue, input.productOptionCheckboxValue, input.productOptionBooleanValue, input.productOptionTextValue, textarea.productOptionLongTextValue');
    this.el.$options.change( this.onChangeOption.bind(this) );

    // Callback trigger
    this.trigger('initOptionsCallback');

  },

  /**
   * Change options
   * @memberOf Fluid.CheckoutForm
   * @param  {object} eventData
   */
  onChangeOption:function(eventData) {
    // Change Option trigger
    if (!this.trigger('onChangeOption')) {
      // Before trigger
      this.trigger('onChangeOptionBefore');

      this.showChangeMessage();

      // Callback trigger
      this.trigger('onChangeOptionCallback');
    }
  },

  /**
  * Change quantity
  * @memberOf Fluid.CheckoutForm
  * @param  {object} eventData
  */
  onChangeQuantity:function(eventData) {
    // Change Option trigger
    if (!this.trigger('onChangeOption')) {
      // Before trigger
      this.trigger('onChangeOptionBefore');

      this.showChangeMessage();

      // Callback trigger
      this.trigger('onChangeOptionCallback');
    }
  },

  showChangeMessage:function() {
    var objCheckoutForm = $($('form[data-fluid-form="' + this.name + '"] .form-message').get(0));
    objCheckoutForm.addClass("alert alert-info");
    objCheckoutForm.html(languageSheet.CHANGEOPTIONBASKET);
  },

  onSubmit: function(event) {
    $(event.target).attr('disabled', true);
    event.preventDefault();
    if (this.el.$form.isValid()) {
      $('<input />',{
        type : "hidden",
        name : $(event.target).attr('name'),
        value : 1
      }).appendTo(this.el.$form);

      //Plugin Listener
      Fluid.resources.pluginListener('beforeSubmitEndOrder', event, this.el.$form, false);
    
      if(!this.el.$form.preventSubmit)
        this.el.form.submit();      
    } else $(event.target).attr('disabled', false);
  },
  /*submit : function(event) {
    if (!this.el.$form.isValid()) {
      event.preventDefault();
      return false;
    }
    // Copy submit element into hidden before disable it.
    $('<input />',{
      type : "hidden",
      name : this.el.$form.find('button[type="submit"]:focus, input[type="submit"]:focus').attr('name'),
      value : 1
    }).appendTo(this.el.$form);
    this.el.$form.find('button[type="submit"], input[type="submit"]').attr('disabled', true);
    return true;
  },*/

  onClickDiscountCodeButton:function(responseText, responseXML) {
    var field = $('#discountCodeField');
    this.addDiscountCode(field.val());
  },

  onKeypressDiscountCodeField:function(event) {
    if (event.keyCode == 13) {
      var field = $('#discountCodeField');
      this.addDiscountCode(field.val());
      return false;
    }
  },



  addDiscountCode:function(code) {
    if (code.length > 0) {
      //AJAX CALLBACK FUNCTION 
      var callbackAddDiscountCode = (function (data) {
        if (data.statusCode != 200)
          return false;

        if (data.response.CODE != 0 && data.response.CODE != 1 && data.response.CODE != 5)
          this.showMessage(data.response.MESSAGE, 'danger');
        else {
          if (data.response.CODE == 0){
            this.showMessage(languageSheet.ONESTEPCHECKOUTDISCOUNTADDED, 'success');
          }
          else if (data.response.CODE == 5){ //Affiliate Success Code
            this.showMessage(languageSheet.CANAPPLYAFFILIATECODE, 'success');
          }
          else{
            this.showMessage(languageSheet.ONESTEPCHECKOUTDISCOUNTADDEDUNDERCONDITIONS, 'success');
          }

          setTimeout(function() {location.reload();}, 3000);


        }
      }).bind(this);
      
      //Prepare the values to be sent to the controller. The code is sent always but maybe the other params doesn't exist. We can also do jsonToSend.code = escape(code);
      var jsonToSend ={"code":encodeURI(code)};

      //Check if the activateAffiliate param is defined and has value
      var $activateAffiliate = $('#activateAffiliate');
    
      if (typeof $activateAffiliate != 'undefined'){
        jsonToSend.activateAffiliate = $activateAffiliate.val();
      }
    
      //Check if the overWritteCurrentAffiliate param is defined and has value
      var $overwriteCurrentAffiliate = $('#overwriteCurrentAffiliate');
      if (typeof $overwriteCurrentAffiliate != 'undefined'){
        jsonToSend.overwriteCurrentAffiliate = $overwriteCurrentAffiliate.val();
      }

      //AJAX CALL
      $.post('/basket/addDiscountCode/', JSON.stringify(jsonToSend), callbackAddDiscountCode, 'json');
    }
  },
  // 20160922DMFLD.0042
  deleteDiscountCode: function(id,el) {
    // Capturamos todo el elemento fluidData (es DOM HTML)
    var a = $(el).data('fluidData');
     $.post('/basket/removeDiscountCodes/', JSON.stringify({"code":escape(a.discountId),"discountType":escape(a.discountType)}), function(data){
      //NOTA: Ara mateix arribem aqui enviant les dades bé a la funció dita. ARA BE! NO FUNCIONA LA FUNCIO FLUID!!!
     if (data.deletedId != 0)
       location.reload();
  
       //Maybe an else with a popup with a message error ????? Pendent to implement
     }, 'json'); 
  }, // ./20160922DMFLD.0042
  buttonSubmit : function(event) {
    // Create action hidden field
    var $hiddenField = $('<input />',{
      type : "hidden",
      name : event.target.name,
      value : 1
    }).appendTo(this.el.$form);
    this.el.form.submit();
  },

  recalculateBasket : function() {    // Create action hidden field
    var $hiddenField = $('<input />',{
      type : "hidden",
      name : 'ACTION3',
      value : 1
    }).appendTo(this.el.$form);
    this.el.form.submit();
  },

  setPaymentSystem : function(id) {

    // Serach input[name="action"]
    var $inputAction = this.el.$form.find('input[name="action"]');

    if ($inputAction.length)
      $inputAction.val(5);
    else
      $('<input />',{type:'hidden',name:'action',value:5}).appendTo(this.el.$form);

    Fluid.resources.pluginListener('setPaymentSystem', {}, {id:id}, false);

    //Submit
    this.el.form.submit();
  },

  setShippingSection : function(id, el) {
    this.el.$form.find('.basketSelectorPickUp').removeClass('basketSelectorPickUpVisible');
    var $el = $(el);

    $el.on('off');

    //Prepare warehouses
    if (settings.pickup) {
      if ($el.data('pickup') == 1) {
        var selectionType = $el.data('selectiontype');

        if (selectionType === "modal") {
          // Modal selection type
          if ($el.data('boxuid'))
            $el.box('openBox');
          else {
            $el.box({
              uid: 'modalSelectWarehouse',
              triggerOnClick: false,
              showFooter: false,
              source: '/checkout/selectWarehouse/' + $el.val(),
              type: 'url',
              callback : 'warehouses'
            });
          }
        } else {
          // Basic selection type
          var warehouseElements = $('input[name="pickUpWarehouse_'+el.value+'"]');
          $el.parent().find('.basketSelectorPickUp').addClass('basketSelectorPickUpVisible');
          warehouseElements.each(function(index, item) {
            item.disabled = false;
            $(item).on('click');
          }.bind(this));
        }

        return true;
      }
      else { 
        var warehouseElements = $('input.basketSelectorPickUp');
        warehouseElements.each(function(index, item) {
          item.disabled = true;
          item.checked = false;
          $(item).on('off');
        }.bind(this));

        // Search input[name="warehouse"]
        var $inputWarehouse = this.el.$form.find('input[name="warehouse"]');
        if ($inputWarehouse.length)
          $inputWarehouse.val(-1);
        else 
          $('<input />',{type:'hidden',name:'warehouse',value:-1}).appendTo(this.el.$form);
      }
    }

    setFormAction(this.el.$form);

    Fluid.resources.pluginListener('setShippingSection', {}, {id:id}, false);

    //Submit
    this.el.form.submit();
  },

  setWarehouse : function(id, el) {

    // Serach input[name="warehouse"]
    var $inputWarehouse = this.el.$form.find('input[name="warehouse"]');
    if ($inputWarehouse.length)
      $inputWarehouse.val(id);
    else
      $('<input />',{type:'hidden',name:'warehouse',value:id}).appendTo(this.el.$form);

    setFormAction(this.el.$form);

    //Submit
    this.el.form.submit();
  },

  reload : function() {
    //TODO reload (?)
    //location.reload();
  }
});

/**
 * @class Fluid.AffiliateOrdersForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 *
 * @TODO get name page from SEO url
 */
Fluid.AffiliateOrdersForm = Fluid.Form.extend({ //buyForm - $.post
  name : 'affiliateOrdersForm',
  initialize : function() {
    // initialize calendar
    //$(this.el.$form).find('input[rel="calendarField"]').ionDatePicker();

   // return;

    //var $calendarStartDate = this.el.$form.find('input[name="startDate"]');
    //var $calendarEndDate = this.el.$form.find('input[name="endDate"]');
    var $calendarStartDate = this.el.$form.find('div[data-datetimePicker="startDate"]');
    var $calendarEndDate = this.el.$form.find('div[data-datetimePicker="endDate"]');

    $calendarStartDate.datetimepicker({
      format : 'DD/MM/YYYY' //FIXME: Use custom format!
    });

    $calendarEndDate.datetimepicker({
      //useCurrent: false, //Important! See issue #1075
      format : 'DD/MM/YYYY' //FIXME: Use custom format!
    });
    $calendarStartDate.on("dp.change", function (e) {
      $calendarEndDate.data("DateTimePicker").minDate(e.date);
    });
    $calendarEndDate.on("dp.change", function (e) {
      $calendarStartDate.data("DateTimePicker").maxDate(e.date);
    });
  },
  submit : function(event) {
    event.preventDefault();

    // Initialize and set vars
    var data = {};
    var arrDataForm = this.el.$form.serializeArray();

    //Fills dataForm
    for (var i = 0; i < arrDataForm.length; i++) {
      if (arrDataForm[i].name == 'searchCriteria') {
        if (arrDataForm[i].value.length < 3)
          return false;
        action = '/search/'+ escape(arrDataForm[i].value).split("%").join("__");
      } else {
        data[arrDataForm[i].name] = arrDataForm[i].value;
      }
    }

    var affiliateOrdersFormCallback = function (response) {
        $('#affiliateOrders').html(response);
    };

    var affiliateOrdersURL = '/user/affiliateOrders';
    $.post(affiliateOrdersURL, JSON.stringify(data), affiliateOrdersFormCallback, 'html');

    return false;
  }
});

/**
 * @class Fluid.NewsletterFormPopup
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.NewsletterPopupForm = Fluid.Form.extend({
  mode: 0,
  name : 'newsletterPopupForm',
  popupName: 'newsletterModal',
  includedPopupName: 'newsletterPopupContainerTooltip',
  includedPopupMarkName: 'newsletterPopupMark',
  cookiePopupName: 'NEWSLETTERPOPUPALERT',
  initialize: function () {

    this.el.email = F('input[name="email"]', this.el.form);
    this.el.agreement = F('input[name="agreement"]', this.el.form);

    this.el.$message = this.el.$form.children('.form-message');
     //Save the cookie expiration time into THIS superVar.
     this.cookieExpireTime = this.el.$form.data('cookieexpiretime');
    var objNewsletterPopup = $(E(this.popupName));
    if ( objNewsletterPopup.length == 1 ) {
      this.el.popup = objNewsletterPopup;
      if (typeof this.cookieExpireTime != 'undefined') {
        if (this.cookieExpireTime!=0) {
          var timeToExpireInHours = this.cookieExpireTime;
          Cookies(this.cookiePopupName,0, {path:'/', expires:timeToExpireInHours});
        } else {
          Cookies(this.cookiePopupName,0, {path:'/'});
        }
      }

    }
    else {
      this.el.popupInclusted = $(E(this.includedPopupName));
      this.el.popupMark = $(E(this.includedPopupMarkName));
    }

    $.validate(Fluid.validateFormConf);
  },
  callback: function (response) {
    if (response.statusCode == 200) {
      if (response.response.SUCCESS == 1) {
        this.el.$message.text('').removeClass('alert-danger');

        if (typeof this.el.popup !== 'undefined') {
          this.el.popup.modal('hide');
        } else {
          this.el.popupInclusted.css('display','none');
          this.el.popupMark.css('display','none');
        }

        Fluid.notify(response.response.MESSAGE, {type:'success', title:'Newsletter'});
      } else {
        this.el.$message.text(response.response.MESSAGE).addClass('alert alert-danger');
      }
    }
  }
});
/**
 * @class Fluid.CustomersForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 *
 * @TODO get name page from SEO url
 */
Fluid.CustomersForm = Fluid.Form.extend({ //buyForm - $.post
  name : 'customersForm',
  initialize : function() {
    var $searchCriteria = this.el.$form.find('input[name="name"]');
  },
  submit : function(event) {
    event.preventDefault();

    // Initialize and set vars
    var data = {};
    var arrDataForm = this.el.$form.serializeArray();

    //Fills dataForm
    for (var i = 0; i < arrDataForm.length; i++) {
      data[arrDataForm[i].name] = arrDataForm[i].value;
    }

    var customersFormCallback = function (response) {
      $('#userCustomers').html(response);
      $('[data-fluid-event]').dataEvent();
    };

    var customersURL = '/user/salesAgent/customers';
    $.post(customersURL, JSON.stringify(data), customersFormCallback, 'html');

    return false;
  }
});

/**
 * Fluid Shipping Prices
 *
 * @description Prepare data to send for calulate shipping
 *              price and prints the result
 * @author Francesc Requesens
 * @version 1 - 2015-09-15
 *
 */
Fluid.shippingPrices = Fluid.Form.extend({
  name : 'shippingPrices',
  options : {},
  initialize:function(form) {
    // Initialize vars
    this.data = this.el.$form.data('fluidShippingcalculator');
    this.el.$submit = this.el.$form.find('button#btnShippingCalculator');
    this.el.$country = this.el.$form.find('select');
    this.el.$zip = this.el.$form.find('input:text');
    this.el.$resultContainer = this.el.$form.find('div#basketShippingCalculatorResponse');

    //Add submit event
    this.el.$submit.on('click', this.submit.bind(this));

    this.el.$zip.on('keypress', function(event) {
      if (event.keyCode == 13) {
        event.preventDefault();
        this.submit();
      }
    }.bind(this));
  },
  submit:function() {
    // Get data
    this.data.countryId = parseInt(this.el.$country.val());
    this.data.zip = this.el.$zip.val();

    // Clean container
    this.el.$resultContainer.html('');

    // Post
    $.post('/checkout/shippingPrices', JSON.stringify(this.data), this.callback.bind(this), "json");
  },
  callback:function(result) {
    // Callback trigger
    this.trigger('callback');

    if (result.response.SUCCESS)
      this.el.$resultContainer.html(result.response.MESSAGE);
    else
      this.showMessage(result.response.MESSAGE, 'danger');
  }
});

/**
 * Fluid Product Comments
 *
 * @description Makes AJAX calls so that comments are dinamically when the orderBy select input changes
 * @author Borja
 * @version 1 - 2015-09-23
 *
 */
Fluid.productComments = Fluid.Form.extend({
  name : 'productComments',
  options : {},
  initialize:function(form) {

    // Initialize vars
    var container = $('#productCommentDivContainerResults');
    var input = $('#commentOrderBy')[0];
    var prodId = $('.showCommentsOrderBy input[name="id"]').val();
    var orderBy = null;

    // Add event listener to selector
    input.addEventListener('change', function(select) {
      var orderBy = this.value;

      // Get request to /products/:prodId/comments -> controllerSnippets.controllerSnippetsRenderComments()
      $.get('/products/'+prodId+'/comments?orderby='+orderBy+'', function(response) {
        if (response.length > 0) {
          // Replace current content with html from AJAX request
          $(container).find('.productRateCommentsContaienr').replaceWith($(response));
        }

      }, "html");

    });

  }
});

/**
 * Fluid Order Refund
 *
 * @description Order Refund Form
 * @version 1 - 2015-10-08
 *
 */
Fluid.OrderRefundForm = Fluid.Form.extend({
  name : 'orderRefundForm',
  elementId : 'requestFormModal',
  options : {},
  initialize: function(form) {

    // Before trigger
    this.trigger('initializeBefore');

    this.initOptions();

    // Callback trigger
    this.trigger('initializeCallback');
  },

  initOptions:function() {
    // Before trigger
    this.trigger('initOptionsBefore');

    this.submitted = false;

    this.el.$submit = this.el.$form.find('input[type="submit"]');

    this.el.$tableRefund = this.el.$form.find('table');

    this.el.$checkbox = this.el.$form.find('input.basketQuantity');
    this.el.$checkbox.change(this.changeInput.bind(this));

    this.el.$input = this.el.$form.find('input[type=checkbox]');
    this.el.$input.click(this.clickCheckBox.bind(this));

    if ( this.el.$form.find('.basketAdditionalInformation') )
      this.el.$additionalInformation = this.el.$form.find('.basketAdditionalInformation');

    // Callback trigger
    this.trigger('initOptionsCallback');
  },

  clickCheckBox:function(eventData) {
    // Before trigger
    this.trigger('clickCheckBoxBefore');

    var objCheckbox = $(eventData.target);
    var strInputId =  '#' + $(eventData.target).attr("name") + 'quantity';
    var strReasonsId =  '#' + $(eventData.target).attr("name") + 'reason';
    var objInput = $(strInputId);
    var objReasons = $(strReasonsId);

    if (objCheckbox.prop("checked")) {
      objInput.prop('disabled', false);
      if (objReasons.length)
        objReasons.prop('disabled', false);
    } else {
      objInput.prop('disabled', true);
      if (objReasons.length)
        objReasons.prop('disabled', true);
    }

    // Callback trigger
    this.trigger('clickCheckBoxCallback');

  },

  changeInput:function(eventData) {
    // Before trigger
    this.trigger('initOptionsBefore');

    var objInput = $(eventData.target),
        dataInput = objInput.data('fluidProduct');

    if ( isNaN(objInput.val()) || objInput.val() < 1 || objInput.val() > dataInput.maxquantity) {
      objInput.val(dataInput.maxquantity);
    }

    // Callback trigger
    this.trigger('changeInputCallback');
  },

  submit : function(event) {
    //Get method, continue default event
    if (this.el.form.method == 'get') return;

    this.el.$submit.prop('disabled', true);

    event.preventDefault();

    //Validate form
    if (!this.el.$form.isValid()) return false;

    //Get form data
    var arrDataForm = this.el.$form.serializeArray();

    //Fills dataForm
    this.dataForm = {};
    for (var i = 0; i < arrDataForm.length; i++)
      this.dataForm[arrDataForm[i].name] = arrDataForm[i].value;

    //Avoid mutiple submit
    this.el.$form.find('button[type="submit"], input[type="submit"]').attr('disabled',true);

    this.submitted = true;

    //Post
    if (this.el.form.method == 'post')
      $.post(this.el.form.action, JSON.stringify(this.dataForm), this.onReceive.bind(this), "json")
        .fail(this.onFail.bind(this))
        .always(this.onComplete(this));
  },

  hasBeenSubmitted : function() {
    return this.submitted;
  },

  callback : function(result) {
    this.el.$submit.prop('disabled', false);

    if (typeof result === 'undefined') return;

    if (!result.response) {
      var message = result.errorDetail ? result.errorDetail : 'Error';
      var success = 0;
    } else {
      var message = result.response.MESSAGE;
      var success = result.response.CODE ? result.response.CODE : 0;
    }

    this.showMessage(message, success ? 'success' : 'danger');
    var productsData = [];

    if ( success ) {
      var $products = this.el.$form.find('input[type=checkbox]:checked').parents('tr');
      $products.each( function(index, obj) {
        var $obj = $(obj);
        var $inputQuantity = $obj.find('input:not([type="hidden"]).basketQuantity');
        var $inputReason = $obj.find('select.basketReason');
        var $ckeckbox = $obj.find('input[type=checkbox]');
        var dataInputQuantity = $inputQuantity.data('fluidProduct');

        productsData.push ({ id:dataInputQuantity.productId, quantity:$inputQuantity.val(), previousPrice:dataInputQuantity.previousPrice, price:dataInputQuantity.price });

        if ( $inputQuantity.val() == dataInputQuantity.maxquantity ) {
          $obj.parents('tbody')
            .find('input[type=hidden][value=pack' + $ckeckbox.val() + ']')
            .parents('tr')
            .each(function(indexPack, objPack) {
              $(objPack).remove();
            });

          $obj.remove();
        } else {
          $ckeckbox.prop('checked', false);
          dataInputQuantity.maxquantity -= parseInt($inputQuantity.val());
          $inputQuantity.prop('disabled', true).val(dataInputQuantity.maxquantity);
          $inputReason.prop('disabled', true).val(-1);
          $inputQuantity.data('fluidProduct', dataInputQuantity);
        }
      });
    }

    if (this.el.$tableRefund.find('tbody tr').length === 0) {
      this.reloadPage();
    }

    // Callback trigger
    this.trigger('submitFormCallback', result, this, productsData);
  },

  reloadPage : function() {
    location.reload();
  }
});

/**
 * Fluid  Unsubscribe Stock Alert
 *
 * @description Unsubscribe Stock Alert Form
 * @version 1 - 2015-10-13
 *
 */
Fluid.UnsubscribeStockAlertForm = Fluid.Form.extend({
  name : 'unsubscribeStockAlertForm',
  initialize: function(form) {

    // Before trigger
    this.trigger('initializeBefore');

    this.initSubmitButtons();

    // Callback trigger
    this.trigger('initializeCallback');

  },
  initSubmitButtons: function() {
    this.el.$buttons = this.el.$form.find('button');
    this.el.$buttons.click(this.submit.bind(this));
  },
  submit: function(event) {
    event.preventDefault();

    var objButton = $(event.target),
        strStockId = objButton.data("fluidStockAlertId");

    $.post(this.el.$form.prop("action"), JSON.stringify({"stockAlertId": strStockId}), this.onReceive.bind(this), 'json');
  },
  onReceive: function(result) {

    if (result.response.DELETEALERTID !== 0) {
      this.el.$form.find('tr[data-fluid-stock-alert-id=' + result.response.DELETEALERTID.toString() + ']').fadeOut("slow", function() { this.remove() });
    }

    // Callback
    if (this.callback && typeof this.callback === 'function') {
      this.callback(result);
    }
  }
});

/**
 * Fluid Remove Stock Alert Form
 *
 * @description Fluid Remove Stock Alert Form
 * @version 1 - 2015-10-13
 *
 */
Fluid.RemoveStockAlertForm = Fluid.Form.extend({
  name : 'removeStockAlertForm',
  options : {},
  initialize: function(form) {

  },
  callback : function(result) {

  }
});

/**
 * @class Fluid.blogCommentForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.blogCommentForm = Fluid.Form.extend({
  name : 'blogCommentForm',
  initialize: function(form) {
    this.el.$checkbox = this.el.$form.find('input[type=checkbox]');
    this.el.$email = this.el.$form.find('.blogEmail');

    if (this.el.$checkbox) {
      this.el.$checkbox.click(this.toggleSubscription.bind(this));
    }

    $.validate(Fluid.validateFormConf);
  },
  toggleSubscription: function(ev) {
    if (ev.target.checked) {
      this.el.$email.show();
      this.el.$email.find('input').data('validation', 'required,email');
    }
    else {
      this.el.$email.hide();
      this.el.$email.find('input').data('validation', '');
    }
  },
  callback: function(result) {
    if (typeof result === 'undefined') return;

    if (!result.response) {
      var message = result.errorDetail? result.errorDetail : 'Error';
      var success = 0;
    } else {
      var message = result.response.MESSAGE;
      var success = result.response.SENT ? result.response.SENT : 0;
    }

    this.showMessage(message, success ? 'success' : 'danger');

    if(success) {
      this.el.$form.find('textarea[name=comment]').val('');
    }
  }
});

/**
 * @class Fluid.blogSubscriptionForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.blogSubscriptionForm = Fluid.Form.extend({
  name : 'blogSubscriptionForm',
  callback: function(result) {
    if (typeof result === 'undefined')
      return;

    if (!result.response) {
      var message = result.errorDetail? result.errorDetail : 'Error';
      var success = 0;
    } else {
      var message = result.response.MESSAGE;
      var success = result.response.SUBSCRIBED ? result.response.SUBSCRIBED : 0;
    }

    this.showMessage(message, success ? 'success' : 'danger');

    if (success) {
      this.el.$form.find(':not(.form-message)').remove();
    }
  }
});

Fluid.FilterForm = Fluid.Form.extend({
  name:'filterForm',
  initialize: function(form) {

    this.el.$form.find('input.customTagsFilterElement').click( this.click );
  },
  click:function() {
    var el = $(this).parent('div.customTagsFilterElement');

    if (this.checked)
      el.addClass('checked');
    else
      el.removeClass('checked');
  }
});

Fluid.productsFilter = Fluid.Form.extend({
  name:'productsFilter',
  initialize: function(form) {
    if (this.el.$form.data('autosubmit')) {
      var self = this;
      this.el.$form.on('change', self.submit.bind(self));
    }
    var $slider = this.el.$form.find('input.slider');

    if ($slider.length > 0) {
     $slider.each(function(e){
     
       this.sliderData = $(this).data('slide');

       this.sliderData.from = Math.floor(this.sliderData.from);
       this.sliderData.to = Math.ceil(this.sliderData.to);
     });
    } else if ($('.pricesFilterBlock').length > 0) {
      //has prices and not slider
      this.$categories = this.el.$form.find('.categoriesFilterBlock');

      if (this.$categories.length > 0) {
        this.categories = this.getSelectedCategories();
      }
    }
  },
  getSelectedCategories: function() {
    var categories = [],
        $select = this.$categories.find('select');

    if ($select.length > 0) {
      categories = [$select.val()];
    } else {

      this.$categories.find('input:checked').each(function(i,e) {
        categories.push($(e).val());
      });
    }

    return categories.join();
  },
  submit: function(event) {

    if (this.$slider) {
      var values = this.$slider.attr('value').split(';');
      if (values[0] == this.sliderData.from && values[1] == this.sliderData.to) {
        this.$slider.remove();
      }
    } else{
      if (this.categories) {

        var filteredCategories = this.getSelectedCategories();

        if (this.categories !== filteredCategories) {
          this.el.$form.find('.maxPrice, .minPrice, *[name=priceRange]').each(function(i,e) {
            $(e).attr('name', '');
          });
        }
      }
    }

    if (this.el.$form.data('autosubmit')) {
      this.el.form.submit();
    }

  }
});

/**
 * @class Fluid.comparerCustomTagsForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.ComparerCustomTagsForm = Fluid.Form.extend({
  name : 'comparerCustomTagsForm',
  cookieComparerCustomTags : 'COMPARERCUSTOMTAGS',
  initialize: function(form) {
    this.el.$form.find("button#comparerSubmit").on('click', this.buttonSubmit.bind(this));
  },
  isValid: function() {
    this.el.$checkbox = this.el.$form.find('input[type=checkbox]:checked');
    this.el.$message.removeClass("alert alert-success alert-danger").html("");

    if (this.el.$checkbox.length == 0) {
      this.showMessage(languageSheet.COMPARERMOBILEFORMCUSTOMTAGS_ERROR1, 'danger');
      return false;
    }
    return true;
  },
  buttonSubmit : function(event) {
    if (this.isValid()) {
      this.el.form.submit();
    }
  },
});

/**
 * @class Fluid.customForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.CustomForm = Fluid.Form.extend({
  name : 'customForm',
  initialize: function(form) {
    var uid = this.el.$form.data('uid');

    if (!window.customForms) window.customForms = {};
    window.customForms[uid] = this;
  }
});
Fluid.customForm = Fluid.CustomForm; // Compatibility mode

/**
 * @class Fluid.pollForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.PollForm = Fluid.Form.extend({
  name : 'pollForm',
  initialize: function(form) {
    this.initQuestions();

    var objPoll = this.el.$form.data('fluidPoll');
    this.pollId = objPoll.id;
    this.pollShowResults = objPoll.showResults;
  },
  initQuestions: function(form) {
    // Before trigger
    this.trigger('initOptionsBefore');

    this.el.$responses = this.el.$form.find('input.pollQuestionRadioResponse, input.pollQuestionCheckboxResponse');
    this.el.$responses.change(this.changeResponse.bind(this));

    this.el.$form.find('input.pollQuestionRadioResponse:checked').parent('div.pollQuestionRadioResponse').addClass('pollQuestionSelected');
    this.el.$form.find('input.pollQuestionCheckboxResponse:checked').parent('div.pollQuestionCheckboxResponse').addClass('pollQuestionSelected');

    // this.el.$form.find('div.pollQuestionResponse > input:hidden').removeAttr('data-validation');
    this.el.$form.find('div.pollQuestion:hidden input, div.pollQuestion:hidden textarea').removeAttr('data-validation'); // remove validations over everything that is hidden

    this.onChange();

    // Callback trigger
    this.trigger('initOptionsCallback');
  },
  changeResponse:function(eventData) {
    // Before trigger
    this.trigger('changeOptionBefore');

    if ($(eventData.target).hasClass('pollQuestionRadioResponse')) {
      $(eventData.target).parents('div.pollQuestionRadioResponses').find('div.pollQuestionRadioResponse').removeClass('pollQuestionSelected');
      $(eventData.target).parent('div.pollQuestionRadioResponse').addClass('pollQuestionSelected');

    }else if ($(eventData.target).hasClass('pollQuestionCheckboxResponse')) {
      if (eventData.target.checked)
        $(eventData.target).parent('div.pollQuestionCheckboxResponse').addClass('pollQuestionSelected');

      else
        $(eventData.target).parent('div.pollQuestionCheckboxResponse').removeClass('pollQuestionSelected');
    }

    this.onChange();

    // Callback trigger
    this.trigger('changeOptionCallback', eventData.target);
  },
  onChange: function() {
    for (i=0; i<this.el.$responses.length; i++)
      if (this.el.$responses[i].checked)
        this.showPollSubquestions(this.el.$responses[i]);
  },
  showPollSubquestions: function(el) {

    var variables = $.parseJSON($(el).attr('data-fluid-poll')) || new Array();
    var hideList = variables.hideList || new Array();
    var questionId = variables.id || 0;

    for (var i=0; i<hideList.length; i++) {
      var subquestion = this.el.$form.find('div#pollQuestion_' + hideList[i]);

      if (subquestion) {
        subquestion.hide();
        subquestion.find('input:hidden, textarea').removeAttr('data-validation');
      }

    }

    if (questionId) {
      var element = this.el.$form.find('div#pollQuestion_' + questionId);

      if (element) {
        element.find('input:hidden, textarea').attr('data-validation', 'required');
        element.css('display', '');
      }

    }
  },
  submit : function(event) {
    //Get method, continue default event
    if (this.el.form.method.toLowerCase() == 'get') return;

    event.preventDefault();

    //Validate form
    if (!this.el.$form.isValid()) return false;

    //Get form data
    var arrDataForm = this.el.$form.find('[type="hidden"], :not(:hidden)').serializeArray(); //avoid hidden answers

    //Fills dataForm
    this.dataForm = {};
    for (var i = 0; i < arrDataForm.length; i++) {
      if (!(arrDataForm[i].name in this.dataForm))
        this.dataForm[arrDataForm[i].name] = [];

      this.dataForm[arrDataForm[i].name].push(arrDataForm[i].value);
    }

    for (var i in this.dataForm)
      this.dataForm[i] = this.dataForm[i].join();

    //Avoid mutiple submit
    this.el.$form.find('button[type="submit"], input[type="submit"]').attr('disabled',true);

    //Post
    if (this.el.form.method.toLowerCase() == 'post')
      $.post(this.el.form.action, JSON.stringify(this.dataForm), this.onReceive.bind(this), "json")
        .fail(this.onFail.bind(this))
        .always(this.onComplete(this));
  },

  callback : function(result) {

    if (this.pollShowResults != 0) {
      this.el.$form.load('/snippets/pollsResults/poll_' + this.pollId);
    } else {

      this.el.$message.html($('<div/>').html(result.response.MESSAGE).text()); // trick for return the HTML formatted

      if (result.response.SUCCESS && result.response.SUCCESS == 1)
        this.el.$message.addClass('alert alert-success');
      else
        this.el.$message.addClass('alert alert-danger');
    }

  }
});

/**
 * @class Fluid.DeletePaymentCardForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.DeletePaymentCardForm = Fluid.Form.extend({
  name : 'DeletePaymentCardForm',
  callback: function(result) {
    if (!this.trigger('callbackSubsitute', result)) {
      // Before trigger
      this.trigger('callbackBefore', result);

      // Default action
      if (typeof result === 'undefined')
        return;

      if (!result.response) {
        var message = result.errorDetail? result.errorDetail : 'Error';
        var success = 0;
      } else {
        var message = result.response.MESSAGE;
        var success = result.response.SUCCESS ? result.response.SUCCESS : 0;
      }

      if (success)
        window.location.reload();
      else
        this.showMessage(message, 'danger');

      // Callback trigger
      this.trigger('callback', result);
    }
  }
});


/**
 * @class Fluid.CountrySelectorForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.CountrySelectorForm = Fluid.Form.extend({
  name : 'countrySelectorForm',
  popupName: '#selectCountryPopup',
  cookiePopupName: 'COUNTRYSELECTORPOPUP',

  initialize: function(form) {

    if (this.el.form.initialized) return;

    this.levels = this.el.$form.data('levels');

     if (this.levels > 0) {
        this.onChange();
        this.el.$form.on('mouseenter','.countriesSelector', this.onChange.bind(this));
     }

     //Save the cookie expiration time into THIS superVar.
     this.cookieExpireTime = this.el.$form.data('cookieexpiretime');

    var objCountryPopup = $('#selectCountryPopup');

    if (objCountryPopup.length == 1) {
      this.el.popup = objCountryPopup;
      /*Cookies(this.cookiePopupName,0, {path:'/', duration:0});*/
    } else {
      this.el.popupInclusted = $(E(this.includedPopupName));
      this.el.popupMark = $(E(this.includedPopupMarkName));
    }

    this.el.form.initialized = true;
    this.trigger('initializeBefore');
    this.callback = this.callback.bind(this);

  },

  onChange: function() {

    var selects = this.el.$form.find('select:not([name="languagesSelector"])');
    if (this.levels == 1) {
      selects.attr('onchange', "");
    } else if (selects.length >= this.levels - 1 ) {
      var last = $(selects[this.levels - 1]);

      if (last.length) {
        last.attr('onchange', '');
      }

      // dirty fix
      if ($(selects[this.levels]).length > 0) {
        $(selects[this.levels]).remove();
      }
    }

  },
  submit: function(event) {
    //Setting cookie if not exist only when the user click submit. if we put it into the init section or onLoad the cookie, with f5 we can bypass the "coockie restriction" because
    //it's defined without enter the information.
    if (typeof this.cookieExpireTime != 'undefined') {
      if (this.cookieExpireTime!=0) {
        var timeToExpireInHours = this.cookieExpireTime/24;
        Cookies(this.cookiePopupName,0, {path:'/', expires:timeToExpireInHours});
      } else {
        Cookies(this.cookiePopupName,0, {path:'/'});
      }
    }
    // After set the cookie we call the super element function submit to submit the form.
    this.superForm('submit', event);
  },

  callback: function (response) {

    //This variable is for the Fluid Tag attribute internalRedirectUrl (/home,/categories/.....)
    var internalRedirectUrl = $('#internalRedirectUrl').val();
    // If isset in the Fluid Tag countrySelector we need to concatenate with the internalRedirectUrl. ATENTION! If a externalRedirectUrl is set, externalRedirectUrl WINS!
    var languageURL = $('select[name="languagesSelector"]').val();
    // If the externalRedirectUrl attribute in fluid tag is defined this redirect wins! Now is not IMPLEMENTED
    var externalRedirectUrl = $('#externalRedirectUrl').val();
    // We save the url to get the correct url in case the user comes to http://home.com/pants and not to http://home.com directly
    var urlComeFrom = window.location.href;

    // en languageURL si esta seleccionado el tag showLanguages=true en el tag devuelve: http://1135.igd.development/es  , por ejemplo.


   var resultOfTypeOfPageValidation = this.internalRedirectUrlValidator(internalRedirectUrl);

   if (typeof response !== 'undefined') {
     if (response.statusCode == 200) {

        if (response.response.SUCCESS == 1) {
         //NOT USED YET. ALREADY PREPARED IF A CLIENT ASK FOR IT
          if (externalRedirectUrl!=null && externalRedirectUrl.length >0) {
            window.location.href = externalRedirectUrl;
            return;

          } else if (languageURL!=null && languageURL.length>0) {
            if (internalRedirectUrl != null && internalRedirectUrl.length > 0 && resultOfTypeOfPageValidation==true)
              window.location.href = languageURL + internalRedirectUrl;
            else
              window.location.href = languageURL;
            return;

          } else if (internalRedirectUrl != null && internalRedirectUrl.length > 0 && resultOfTypeOfPageValidation==true) {
           window.location.href = internalRedirectUrl;
           return;

          } else { window.location.href=urlComeFrom; }

        } else { window.location.href=urlComeFrom; }

        if (typeof this.el.popup !== 'undefined') {
          this.el.popup.modal('hide');
        }

      } else {
        this.showMessage(response.response.MESSAGE, 'danger');
      }

    }

  },

  externalRedirectUrlValidator: function (urlToValidate) {
    var myRegExp =/^(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}) {3})(?!127(?:\.\d{1,3}) {3})(?!169\.254(?:\.\d{1,3}) {2})(?!192\.168(?:\.\d{1,3}) {2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}) {2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])) {2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i;

    if (!myRegExp.test(urlToValidate)) {
      return false;
    } else {
      return true;
    }
  },

  internalRedirectUrlValidator: function (urlToValidate) {
    var myRegExp =/^[\/][\w]+/gmi;

    if (!myRegExp.test(urlToValidate)) {
      return false;
    } else {
      return true;
    }
  }
});

/**
 * @class Fluid.saveBasketForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.saveBasketForm = Fluid.Form.extend({
  name:'saveBasketForm',
  callback: function (response) {

    if (response.statusCode == 200) {
      if (response.response.SUCCESS == 1) {
        Fluid.notify(languageSheet.SAVED, {type:'success', title: languageSheet.basket});
      } else {
        this.showMessage(languageSheet.errorTitle, 'danger');
      }
    }
  }
});

/**
 * @class Fluid.verifyAccountForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.verifyAccountForm = Fluid.Form.extend({
  name:'verifyAccountForm',
  /**
   * initialize
   * @memberOf Fluid.verifyAccountForm
   */
  initialize:function(form){
    var sendSMSLink = this.el.$form.find('a.sendSMSLink');

    sendSMSLink.on('click', function(event) {
      var email = this.el.$form.find('input[name="email"]').val();
      var id = this.el.$form.find('input[name="id"]').val();

      if(!(email && email.length) && !id){
        var message = languageSheet.INCORRECTEMAIL;
        if(id)
          message = languageSheet.USERVERIFYERROR;

        Fluid.notify(message, {type:'danger', title: languageSheet.VERIFICATIONCODE});
      }else
        $.post(
          '/user/action/sendVerificationMessage',
          JSON.stringify({email:email,id:id}),
          "json"
        ).always(this.sendSMSCallback);

    }.bind(this));
  },

  /**
   * sendSMSCallback
   * @memberOf Fluid.verifyAccountForm
   */
  sendSMSCallback: function(response) {
    if(response.responseJSON) //403
      var data = response.responseJSON;
    else //200
      var data = response;

    var message = languageSheet.INVALIDEMAIL;
    var type = 'danger';
    if(data.response){
      message = data.response.MESSAGE;
      type = data.response.SUCCESS >= 1 ? 'success' : 'danger';
    }

    if(data.statusCode == 200 || data.statusCode == 403){ // valid status codes
      Fluid.notify(message, {type:type, title: languageSheet.RESENDSMS});
    }
  },

  /**
   * callback
   * @memberOf Fluid.verifyAccountForm
   */
  callback:function(response){
    if(response.statusCode == 200 || response.statusCode == 403){ // valid status codes
      Fluid.notify(response.response.MESSAGE, {type:response.response.SUCCESS >= 1 ? 'success' : 'danger', title: languageSheet.VERIFICATIONCODE});

      if(response.response.DIRECTVALIDATION && !response.response.SUCCESS)
        setTimeout(function(){ window.location = '/user/verifyAccount'; }, 3000);
      else if(response.response.SUCCESS)
        setTimeout(function(){ window.location = '/user'; }, 3000);
    }
  }
});

/**
 * @class Fluid.addRecommendedBasket
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.addRecommendedBasket = Fluid.Form.extend({
  name:'addRecommendedBasket',
  /**
   * initialize
   * @memberOf Fluid.addRecommendedBasket
   */
  initialize:function(form){
    this.setViewedButton = this.el.$form.find('button[type="button"].addRecommendedBasketSetViewed');
    this.addButton = this.el.$form.find('button[type="submit"].addRecommendedBasketFormSubmit');
    this.data = this.el.$form.data('recommendedBasket');

    this.setViewedButton.on('click', function(event) {
      this.setViewedButton.prop('disabled', true);
      $.post("/user/recommendedBaskets/setViewed", JSON.stringify({id:this.data.id,viewed:this.data.viewed}), "json").always(this.setViewedCallback.bind(this));
    }.bind(this));

  },

  /**
   * setViewedCallback
   * @memberOf Fluid.addRecommendedBasket
   */
  setViewedCallback: function(response) {
    if(response.responseJSON) //403
      var data = response.responseJSON;
    else //200
      var data = response;

    // if success
    this.data.viewed = !this.data.viewed;
    var spanBaskets = $('span.userPanelAlert.userPanelRecommendedBasketsAlert');
    var spanBasketsValue = parseInt($(spanBaskets).html());
    if(isNaN(spanBasketsValue))
      spanBasketsValue = 0;

    if(this.data.viewed){
      this.setViewedButton.text(languageSheet.SETRECOMMENDEDBASKETUNVIEWED);
      if(spanBasketsValue == 1)
        $(spanBaskets).text('');
      else
        $(spanBaskets).text(spanBasketsValue-1);
    }
    else{
      this.setViewedButton.text(languageSheet.SETRECOMMENDEDBASKETVIEWED);
      $(spanBaskets).text(spanBasketsValue+1);
    }

    this.showMessage(data.response.MESSAGE, data.response.CHANGED == 0 ? 'danger' : 'success');
    this.setViewedButton.prop('disabled', false);
  },

  /**
   * submit
   * @memberOf Fluid.addRecommendedBasket
   */
  submit : function(event) {
    event.preventDefault();

    // Before trigger
    this.trigger('submitBefore', event);

    if(!this.el.$form.isValid())
      return false;

    $.post('/basket/addRecommendedBasket/', JSON.stringify({ id:this.data.id }), this.callback.bind(this) , 'json');

    // Disable buy button
    this.addButton.prop('disabled', true);

    // Callback trigger
    this.trigger('submitCallback', event);
  },

  /**
   * callback
   * @memberOf Fluid.addRecommendedBasket
   */
   callback:function(result){

    // Reload minibasket
    Fluid.miniBasket.reload();

    // Enable buy button
    this.addButton.prop('disabled', false);

    if (Fluid.config.showModalBasket && (settings.isMobile == 1 || window.innerWidth < 992)){
      var buttonClass = htmlFramework == 'bootstrap' ? ' btn btn-default btn-block' : 'modalBasketEndOrderButton';
      var submitButtonClass = htmlFramework == 'bootstrap' ? ' btn-primary' : '';
      var localPath = (settings && settings.checkoutPath)? settings.checkoutPath : "/checkout/basket";
      var modalContent = '';
      if(result.response.stockLock){
        modalContent += '<div class="basketCountdown" data-basket-expires=\'{"expires":'+result.response.stockLock.expires+'}\'><div class="active">'+languageSheet.LOCKEDSTOCKREMAININGTIME+'</div><div class="expired">'+languageSheet.LOCKEDSTOCKEXPIREDTIME+'</div></div>';
      }
      modalContent += '<div id="modalBasketButtons"><a href="' + localPath + '" class="modalBasketEndOrder' + buttonClass + submitButtonClass + '">'+ languageSheet.BASKETENDORDER + '</a><a data-dismiss="modal" class="modalBasketContinueShopping' + buttonClass + '">' + languageSheet.BASKETCONTINUESHOPPING + '</a><a href="/user" class="modalBasketMyAccount' + buttonClass + '">' + languageSheet.MYACCOUNT + '</a></div>'

      this.addButton.box({
        uid : 'mobileBasketModal',
        source: modalContent,
        showFooter : false,
        triggerOnClick : false,
        type : 'text'
      });
    }
  }
});

/**
 * @class Fluid.incidenceForm
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.incidenceForm = Fluid.Form.extend({
  name:'incidenceForm',
  /**
   * callback
   * @memberOf Fluid.incidenceForm
   */
  callback:function(response){
    Fluid.notify(response.response.MESSAGE, {type:response.response.SUCCESS == 1 ? 'success' : 'danger', title: languageSheet.INCIDENCES});

    if(response.response.SUCCESS != 1)
      setTimeout(function(){ window.location.reload(); }, 1500);
  }
});

Fluid.VinculateSocialAccountEmailPopupForm = Fluid.Form.extend({
  initialize:function(){

    this.el = {};
    this.el.$form = $('<form action="/user/vinculateSocialAccountEmail/" method="POST"></form>');
    this.el.form = this.el.$form[0];

    var modalContent = '';
    modalContent += '<div class="vinculateSocialAccountEmailTitle">' + languageSheet.VINCULATESOCIALTITLE + '</div>';
    modalContent += '<div class="vinculateSocialAccountEmailInputContainer form-group"><input class="form-control" type="password" name="password"></div>';
    modalContent += '<div class="vinculateSocialAccountEmailSubmitContainer"><button type="submit" class="btn btn-primary" id="vinculateSocialAccountEmailSubmit">' + languageSheet.VINCULATESOCIALSEND + '</button></div>';

    this.el.$form.append($(modalContent));
    this.el.$form.on('submit', this.submit.bind(this));

    this.el.$form.box({
      uid : 'vinculateSocialAccountEmailPopupModal',
      source: this.el.$form,
      showFooter : false,
      triggerOnClick : false,
      type : 'text'
    });

  },
  callback:function(response){
    if(response.response.SUCCESS == 1){
      this.showMessage(response.response.MESSAGE, 'success');
      setTimeout(function() {location.reload();}, 3000);
    } else {
      this.showMessage(response.response.MESSAGE, 'danger');
    }
  }
});

/**
 * @class Fluid.ConfirmAgeFormPopup
 * @memberOf Fluid
 * @extends {Fluid.Form}
 */
Fluid.ConfirmAgePopupForm = Fluid.Form.extend({
  mode: 0,
  name : 'confirmAgePopup',
  popupName: 'confirmAgePopupModal',
  includedPopupName: 'confirmAgePopupContainerTooltip',
  includedPopupMarkName: 'confirmAgePopupMark',
  cookiePopupName: 'CONFIRMAGEPOPUPALERT',
  initialize: function () {
    var objConfirmAgePopup = $(E(this.popupName));

    if ( objConfirmAgePopup.length == 1 ) {
      this.el.popup = objConfirmAgePopup;

      var redirectUrl =$('#redirecturl').val();
      this.el.popup[0].setAttribute('data-redirecturl', redirectUrl != 'undefined' ? redirectUrl : '');
      //Bind cancel action
      this.el.popup.on('hidden.bs.modal', function(){
       
        if (typeof this.getAttribute('data-redirecturl') !== 'undefined' && this.getAttribute('data-redirecturl').length > 0){
          window.location.href = this.getAttribute('data-redirecturl');
        }else{
          location.reload();
        }

      });
    }else {
      this.el.popupInclusted = $(E(this.includedPopupName));
      this.el.popupMark = $(E(this.includedPopupMarkName));
    }

    $.validate(Fluid.validateFormConf);
  },
  callback: function (response) {
    this.cookieExpireTime = this.el.$form.data('cookieexpiretime');

    if (this.cookieExpireTime!=0) {
      var timeToExpireInHours = this.cookieExpireTime;
      Cookies(this.cookiePopupName,1, {path:'/', expires:timeToExpireInHours});
    } else {
      Cookies(this.cookiePopupName,1, {path:'/'});
    }

      location.reload();

  }
});

Fluid.newsletterForm = Fluid.Form.extend({
  name: 'newletterForm',
  callback: function(response){
    this.superForm('callback', response);
    this.trigger('callback', response);
  }
});

/******************************/
/*        UTILS               */
/******************************/
var setFormAction = function(form){
  var value = 5;
  if ($('body').hasClass('fluidContent-paymenytAndShipping'))
    value = 5;
  else if ($('body').hasClass('fluidContent-basket'))
    value = 3;
  else if ($('body').hasClass('fluidContent-warehouses'))
    value = 5;

  // Serach input[name="action"]
  var $inputAction = form.find('input[name="action"]');
  if ($inputAction.length)
    $inputAction.val(value);
  else
    $('<input />',{type:'hidden',name:'action',value:value}).appendTo(form);
}// Mètodes útils de Fluid (Afegir-ne si cal)
// -----------------------------------------------------------------------------

/**
 * Creates modal (large)
 * "Aspalusnant"
 * 
 * @TODO Now it uses BOOTSTRAP component. It will be necessary use "own" modal 
 *       component when theme hasn't bootstrap.
 */
Fluid.fn("box", {
  options : {
    uid : null,
    showFooter : true,
    showClose : true,
    source : null,
    type : null,
    triggerOnClick : true,
    params : false,
    transition : '',
    modalClass : '',
    verticalPosition : 'default', // default | center
    backdrop : true, // "static"  (prevent close modal with a click outside modal)
    keyboard : true, //false (prevent close with esc key)
    size : 'large',  // large | medium | small
    callback : null
  },
  Constructor : function(element, options){

    // Initialize and prepare variables
    var type = options.type || element.data("fluidModalType");

    if (typeof element.data("fluidModalShowfooter") !== "undefined")
      options.showFooter = element.data("fluidModalShowfooter");

    if (typeof element.data("fluidModalSize") !== "undefined")
      options.size = element.data("fluidModalSize");

    if (typeof element.data("fluidModalTransition") !== "undefined")
      options.transition = element.data("fluidModalTransition");

    if (typeof element.data("fluidModalTriggeronclick") === "boolean")
      options.triggerOnClick = element.data("fluidModalTriggeronclick");

    if (typeof element.data("fluidModalVerticalposition") !== "undefined")
      options.verticalPosition = element.data("fluidModalVerticalposition");

    var modalSize = '';
    switch (options.size) {
      case 'small': modalSize = ' modal-sm'; break;
      case 'large': modalSize = ' modal-lg'; break;
    };

    // UID
    if (typeof element.data("fluidModalUid") !== "undefined")
      var uid = element.data("fluidModalUid");
    else
      var uid = options.uid || String.fromCharCode(65+Math.floor(Math.random()*26))+Date.now();
    
    // Initialize function
    this.init = function() {

      // Get Data
      var source = options.source || element.data("fluidModal");

      // Containers
      var $box = this.box = _createBox();
      var $container = $($box.find('div.fluidModalContainer')[0]);
      var $close = $($box.find('button.close')[0]);

      // Callback event
      var callback = options.callback || element.data("fluidModalCallback");

      // Add target
      element.data('target', "#"+uid);
      
      // Open (load data)
      if (options.triggerOnClick) {
        element.click(function(event){
          event.preventDefault();
          _trigger(type, source, $container, $box, callback);
        });
      }
      else {
        _trigger(type, source, $container, $box, callback);
        this.dataTrigger = {
          type: type, 
          source: source, 
          container: $container, 
          box: $box, 
          callback: callback
        }
      }

      element.data('boxuid', uid);

      // Close (clean)
      $box.on("hidden.bs.modal", function(ev){
        $container.html("");
      });
    };

    this.close = function(){
      this.box.modal('hide');
    };

    this.openBox = function() {
      if (this.dataTrigger) {
        var data = this.dataTrigger;
        _trigger(data.type,data.source,data.container,data.box,data.callback);
      }
    };

    function _createBox(){
      var $body = $('body');
      var $box = $body.children('div.fluidModal#'+uid);

      // Vertical Position classNames
      var vpClass = { dialog : '', content : '', body : '', footer : ''};
      if (options.verticalPosition == 'center')
        vpClass = {
          dialog : 'modal-dialog-vpc',
          content : 'modal-content-vpc',
          body : 'modal-body-vpc',
          footer : 'modal-footer-vpc'
        };

      // Check box exists
      if (!$box.length){
        // Create box
        var box = '<div id="'+uid+'" class="fluidModal modal fade ' + options.transition + ' ' +(type == 'video'? 'fluidModalVideo': '')+' '+ options.modalClass + '" tabindex="-1" role="dialog" aria-hidden="true">';
            box+= '<div class="modal-dialog '+vpClass.dialog+' '+modalSize+'">';
            box+= '<div class="modal-content '+vpClass.content+'">';
            box+= '<div class="modal-body '+vpClass.body+'">';

        if (options.showClose && options.backdrop !="static"){
            box+= '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>';
        }
            box+= '<div class="fluidModalContainer"></div>';

        if (type != "video" && options.showFooter && options.backdrop !="static") {
            box+= '<div class="modal-footer '+vpClass.footer+'">';
            box+= '<button type="button" class="btn btn-default fluidModalClose" data-dismiss="modal">'+languageSheet.CLOSE+'</button>';
            box+= '</div>';
        }
            box+= '</div></div></div></div></div>';

        $body.append(box);
        $box = $body.children('div.fluidModal#'+uid);
        $box.on('hide.bs.modal', function(){
          if(window.TEA)
            TEA.quickView.close(true);
        });
      }
      return $box;
    };

    function _trigger(type, source, $container, $box, callback){
      var modalOptions = {show:true, keyboard:options.keyboard, backdrop:options.backdrop};
      switch(type){
        case "video":
          //Prepare reponsive view with video
          var str = '<div class="fluidModalVideoContent">'+source+'</div>';
          $container.html(str);
          $box.modal(modalOptions);
          _callback(callback, element, $box);
          break;

        case "internal":
        case "text":
          $container.html(source);
          $box.modal(modalOptions);
          _callback(callback, element, $box);
          break;

        case "html":
          $container.html(element);
          $box.modal(modalOptions);
          _callback(callback, element, $box);
          break;

        case "image":
          $container.html('<img class="fluidModalImage" src="'+source+'" alt="" title="" />');
          $box.modal(modalOptions);
          _callback(callback, element, $box);
          break;

        case "url":
        default:
          var intTimeStamp = new Date().getTime();
          source += ((source.indexOf("?") > 0)? "&" : "?") + "noCache=" + intTimeStamp;
          $container.load(source, options.params, function(){
            if($container.html().length > 1){
              $box.modal(modalOptions);
              $container.ready(function(){
                _callback(callback, element, $box);
              });
            }
          });
          break;
      }
    };

    function _callback(callback, element, $box){
      if (!callback) return;
      if (typeof callback === 'function')
        callback(element, $box);
      else if (typeof Fluid.modalCallbacks[callback] === 'function')
        Fluid.modalCallbacks[callback](element, $box);
    }
  }
});

/**
 * Modal callbacks. 
 * This functions will be called when a modal has been loaded.
 * @type {Object}
 */
Fluid.modalCallbacks = {
  /**
   * Wishlist delete callback.
   * on development
   * @param  {object} element button that calls modal
   * @param  {object} modal   modal DOM element
   */
  modalProductForm : function(element, modal){
    // Initialize form
    var form = new Fluid.BuyForm(modal.find('form')[0]);
  },
  wishlistDeleteCallback : function(element, modal){

    new Fluid.DeleteWishListForm(E('deleteWishlistForm'));
    
    //Find checkboxes
    modal.find('input[type="checkbox"]').on('click', function(){
      var $label = $(this).parent().parent();
      if (this.checked)
        $label.addClass('active');
      else
        $label.removeClass('active');
    });
  },
  wishlistSendCallback : function(element, modal){
    var form = Fluid.Form.extend({
      submit : function(event){
        event.preventDefault();

        // Clean message
        this.el.$message.text('').removeClass('alert-danger');

        // Control one product at least is selected
        if(!this.el.$form.find('input[name="productIdList"]:checked').length){
          this.el.$message.text(languageSheet.SENDWISHLISTSELECTPRODUCTERROR);
          this.el.$message.addClass('alert alert-danger');
          return false;
        }

        // Call submit from parent class
        this.superForm('submit', event);
      },
      callback : function(result){
        if (!result.response) {
          var message = result.errorDetail? result.errorDetail : 'Error';
          var success = 0;
        }
        else {
          var message = result.response.MESSAGE? result.response.MESSAGE : 'DONE';
          var success = result.response.SUCCESS? result.response.SUCCESS : 0;
        }
        this.el.$message.text(message);

        if (success){
          this.el.$message
            .removeClass('alert-danger')
            .addClass('alert alert-success');

          setTimeout(function(){
            modal.modal('hide');
          }, 3000);
        }
        else
          this.el.$message.addClass('alert alert-danger');
      }
    });
    $.validate(Fluid.validateFormConf);
    var objForm = new form(modal.find('form')[0]);


    //Find checkboxes
    modal.find('input[type="checkbox"]').on('click', function(){
      var $label = $(this).parent().parent();
      if (this.checked)
        $label.addClass('active');
      else
        $label.removeClass('active');
    });
  },
  recommendCallback : function(element, modal){
    // Initlialize validate
    //Clone conf 
    var conf = $.extend(true, {}, Fluid.validateFormConf, {
      form: modal.find('form')
    });
    
    $.validate(conf);

    modal.find('[data-fluid-modal]').box();


    // Form class
    var form = Fluid.Form.extend({
      callback : function(result){
        if (!result.response) {
          var message = result.errorDetail? result.errorDetail : 'Error';
          var success = 0;
        }
        else {
          var message = result.response.MESSAGE? result.response.MESSAGE : 'DONE';
          var success = result.response.SUCCESS? result.response.SUCCESS : 0;
        }
        this.el.$message.text(message);

        if (success){
          this.el.$message
            .removeClass('alert-danger')
            .addClass('alert alert-success');

          // Close modal
          setTimeout(function(){
            modal.modal('hide');
          }, 4000);
        }
        else
          this.el.$message.addClass('alert alert-danger');
      }
    });
    var objForm = new form(modal.find('form')[0]);
  },
  productContactCallback : function(element, modal){
    // Initlialize validate
    $.validate({
      form: modal.find('form')
    });

    modal.find('[data-fluid-modal]').box();

    // Form
    var form = Fluid.Form.extend({
      callback : function(result){
        if (!result.response) {
          var message = result.errorDetail? result.errorDetail : 'Error';
          var success = 0;
        }
        else {
          var message = result.response.MESSAGE? result.response.MESSAGE : 'DONE';
          var success = result.response.SUCCESS? result.response.SUCCESS : 0;
        }
        this.el.$message.text(message);

        if (success){
          this.el.$message
            .removeClass('alert-danger')
            .addClass('alert alert-success');

          setTimeout(function(){
            modal.modal('hide');
          }, 4000);
        }
        else
          this.el.$message.addClass('alert alert-danger');
      }
    });
    var objForm = new form(modal.find('form')[0]);
  },
  warehouses: function(element, modal){ 
    var loadMaps = function(){
      $(modal).find('[data-fluid-event]').dataEvent({
        callback: function(){
          $(modal).find('form').each(function(index, form) {
            var dataFluidForm = $(form).data('fluidForm');
            if (Fluid[dataFluidForm]){
              new Fluid[dataFluidForm](form);
              return;
            }
          });
        }
      });
    };

    if (!Fluid.dataEvents.loadMapsJs)
      Fluid.require.js("/common/js/fluid/v1/fluid.maps.js", loadMaps);
    else 
      loadMaps();
  },
  orderRefundCallback: function (element, modal) {
    modal.on('hidden.bs.modal', function () {
      if (modal.form.hasBeenSubmitted())
        location.reload();
    });
    modal.form = new Fluid.OrderRefundForm(F('#orderRefundForm'));
  },
  newsletterPopup: function (element, modal){},
  selectCountryPopup: function (element, modal){
    // Call Country selector
    new Fluid.CountrySelectorForm( $(modal).find('form')[0]);
  },
  confirmAgePopupFormCallback:function(element,modal){
    new Fluid.ConfirmAgePopupForm($(modal).find('form')[0]);
  },
  selectMapKind: function (element, modal){
    // Call Country selector
    new Fluid.SelectMapKindForm( $(modal).find('form')[0]);
  },
  modalUserAddressBook: function(element, modal) {
    var objData = element.data("fluidData");
    var objUserAddressBookForm = F('#userAddressBookForm');
    objUserAddressBookForm.visibleFields = objData.visiblefields;
    new Fluid.userAddressBookForm(objUserAddressBookForm);
  },
  newsletterCustomRegistration: function(element,modal){
    var objUserForm = F('#userForm');
    new Fluid.UserForm(objUserForm);
  },
  stockLockPopup:function(element, modal){
    Fluid.initializeCountdowns();
    modal.find('[data-fluid-event]').dataEvent();
  },
  incidenceFormCallback:function(element, modal){
    new Fluid.incidenceForm(modal.find('form')[0]);
  },
  settingsUserLostPasswordCallback:function(element, modal){
    new Fluid.LostPasswordForm(modal.find('form')[0]);
  }
};

Fluid.basketCountDown = function(element){
  
  element = $(element);

  var $elActive = element.find('.active');

  options = {
    container:$elActive
    ,endDate:element.data('basket-expires').expires
    ,callback:function(){
      element.removeClass('active').addClass('expired');
    }
  };
  element.addClass('active');

  return new Fluid.countDown(options);
}

Fluid.basketLockCountDown = function(element){
  
  element = $(element);

  options = {
    container:element
    ,endDate:element.data('lock-countdown').expires
    ,callback:function(){
      $(document.body).addClass('basket-check-availability');

      var dummy = $('<span/>');
      var button = $('<button></button>').html(languageSheet.LOCKEDSTOCKCHECKAVAILABILITY).attr('data-fluid-event', 'click').attr('data-fluid-function', 'updateBasket').attr('data-data', '{"action":"recalculate"}').appendTo(dummy);

      element.html( languageSheet.LOCKEDSTOCKCHECKPRODUCTAVAILABILITY.replace(/%name%/gi, element.data('lock-countdown').productName).replace(/%button%/gi, dummy.html()) );
      element.find('[data-fluid-event]').dataEvent();
    }
  };

  return new Fluid.countDown(options);
}

Fluid.combinationCountDown = function(params){

  var container = $("<span></span>");
  var options = {
    endDate:params.endDate
    ,template:languageSheet.STOCKRESERVEDTEXT.replace(/%units%/gi, params.quantity)
    ,container:container
    ,callback:function(){
      if( $(document.body).hasClass('fluidContent-product') )
        location.reload();
      else
        container.html(languageSheet.LOCKEDSTOCKRELOADNEEDED);
    }
  }

  return new Fluid.countDown(options);

}

Fluid.countDown = function(options){

  this.init = function(){
    if (typeof moment === "undefined") { console.error("Moment JS library doesn't exist"); return; }
    
    //this.startDate = moment(options.startDate).unix();
    this.endDate = moment(options.endDate).unix();
    this.callback = options.callback || (function(){ this.$container.remove(); }).bind(this);
    //this.offset = moment().unix() - this.startDate;
    this.offset = settings.localServerOffsetTime;

    this.$container = options.container || $("<span></span>");
    this.template = options.template || this.$container.html() || "%hours%:%minutes%:%seconds%";

    this.interval = setInterval(this.draw.bind(this), 1000);
    this.draw();
  }

  this.draw = function(){
    var JSDate = moment().unix() - this.offset;
    var currentDate = this.endDate - JSDate;

    if(currentDate < 0){
      this.destroy();
      this.callback();
      return;
    }

    var stcTimeObj = this.formatTime(currentDate);

    this.$container.html(this.template.replace(/%days%/gi, stcTimeObj.days).replace(/%hours%/gi, stcTimeObj.hours).replace(/%minutes%/gi, stcTimeObj.minutes).replace(/%seconds%/gi, stcTimeObj.seconds));
  }

  this.formatTime = function(ms){
    var two = function(x){return ((x>9)?"":"0")+x}

    var response = {};
    response.days = parseInt(ms/60/60/24);
    response.hours = two(parseInt(ms/60/60)%24);
    response.minutes = two(parseInt(ms/60)%60);
    response.seconds = two(parseInt(ms)%60);
    
    return response;
  }

  this.destroy = function(){
    clearInterval(this.interval);
  }

  this.init();

}

/**
 * Fluid Count Down [ 20151111DAFL-03 ]
 */
Fluid.productCountDown = function(element) {
  this.init(element);
};

Fluid.objIncrementCounter = function(type, listIds, item) { //type 1 = view, type 2 = click
  $.ajax({type: "POST", url: '/incrementCounter', data: JSON.stringify('{"type": '+type+', "listIds": "'+listIds+'", "item": "'+item+'" }'), dataType: "JSON" });
};

$.extend(true, Fluid.productCountDown.prototype, {

  counter:0,
  template: null,
  elementId: null,
  categoryId: null,
  callbackType: 1,

  limit: null,
  offset: null,
  endDate: null,
  startDate: null,

  init: function (element) {
    if (typeof moment === "undefined") { console.error("Moment JS library doesn't exist"); return; }

    var objElement = $('#' + element);
    if (!objElement) return;

    var dataOptions = objElement.data("fluidCountdown");
    if (typeof dataOptions !== "object" || !"STARTDATE" in dataOptions || !"ENDDATE" in dataOptions || !"TEMPLATE" in dataOptions) return;

    if ("CALLBACKTYPE" in dataOptions) this.callbackType = dataOptions.CALLBACKTYPE;
    if (this.callbackType == 2 && "CATEGORYID" in dataOptions) this.categoryId = dataOptions.CATEGORYID;

    var objStartDate = moment(dataOptions.STARTDATE,'YYYYMMDDhhmmss');
    var objEndDate = moment(dataOptions.ENDDATE,'YYYYMMDDhhmmss');

    // Get time difference between client and server
    this.elementId = element;
    this.template = dataOptions.TEMPLATE;

    this.startDate = objStartDate.unix();
    this.endDate = objEndDate.unix();

    this.offset = moment().unix() - this.startDate;
    this.limit = this.endDate;

    objElement.innerHTML='';

    delete objElement, objStartDate, objEndDate;

    var _this = this;
    setTimeout(function () { _this.showTime() }, 1);
  },
  showTime: function() {
    var JSDate = moment().unix() - this.offset;
    var currentDate = this.limit - JSDate;

    if(currentDate < 0) {
      switch (this.callbackType) {
        case 1:
          location.reload();
          break;
        case 2:
          location.href = '/categories/' + this.categoryId.toString();
          break;
      }
      return;
    }
  
    var stcTimeObj = this.formatTime(currentDate);
  
    var objElement = $('#' + this.elementId);
    objElement.html(this.template.replace(/%days%/gi, stcTimeObj.days).replace(/%hours%/gi, stcTimeObj.hours).replace(/%minutes%/gi, stcTimeObj.minutes).replace(/%seconds%/gi, stcTimeObj.seconds));

    delete JSDate, currentDate, stcTimeObj, objElement;

    var _this = this;
    setTimeout(function() { _this.showTime() }, 1000);
  },
  formatTime: function (ms) {
    var two = function(x){return ((x>9)?"":"0")+x}

    var response = {};
    response.days = parseInt(ms/60/60/24);
    response.hours = two(parseInt(ms/60/60)%24);
    response.minutes = two(parseInt(ms/60)%60);
    response.seconds = two(parseInt(ms)%60);
    
    return response;
  }
});

/**
 * Fluid Data Events. Call functions from Fluid.dataEvents
 */
Fluid.fn("dataEvent", {
  Constructor: function(element, options){
    var strElementEvent = element.data("fluidEvent");
    var strElementFunction = element.data("fluidFunction");

    if ( typeof Fluid.dataEvents[strElementFunction] !== "function" )
      return;

    switch(strElementEvent){
      case "click":
        element.click( Fluid.dataEvents[strElementFunction].bind(this) );
        break;
      case "keypress":
        element.keypress( Fluid.dataEvents[strElementFunction].bind(this) );
        break;
      case "change":
        element.on('change', Fluid.dataEvents[strElementFunction].bind(this) );
        break;
      case "load":
        Fluid.dataEvents[strElementFunction](element, options);
        break;
    }
    // Reseting event to avoid duplicate triggers.
    element.data("fluidEvent", null);
  },
});

/**
 * Data Events Object.
 * @type {Object}
 */
Fluid.dataEvents = {};
Fluid.dataEvents.viewOrder = function(e) {
  var objData = $(e.target).data("fluidData");

  var documentType = objData.documentType || 1;
  var documentPath = 'order/', name = 'viewOrder', properties = 'menubar=1,resizable=1,scrollbars=1,width=800,height=600';

  if(documentType == 2)
    documentPath = 'deliveryNote/';
  else if(documentType == 4)
    documentPath = 'invoice/';
  else if(documentType == 10)
    documentPath = 'refund/';
  else if(documentType == 20)
    documentPath = 'refundInvoice/';
  else if(documentType == 21)
    documentPath = 'refundRequest/';
  else if(documentType == 101)
    documentPath = 'orderToSupplier/';

  if(objData.pdf) name = '_blank', properties = '';

  window.open('//'+location.host+/orders/+documentPath + objData.orderId + '/'+ objData.token + '/' + objData.pdf + '/', name, properties);
};

Fluid.dataEvents.getRefund = function(e){
  var objData = $(e.target).data("fluidData");
  
  var urlRefundForm = '//'+location.host+'/orders/refund/' + objData.orderId + '/'+ objData.token + '/';
  var modalRefundForm = $.fn.box({
    uid: 'refundFormModal', 
    source: urlRefundForm,
    showFooter: false, 
    triggerOnClick: false, 
    type:'url'
  });
};
Fluid.dataEvents.changeCurrency = function(e){
  e.preventDefault();

  var objData = $(e.target).data("fluidData");

  var currencyCallback = function(data){
    if (data.response.ERROR == 0)
      location.reload();
  };

  $.post('/currency/' + objData.currencyId, JSON.stringify([]), currencyCallback, 'json');

  return false;
};
Fluid.dataEvents.addProduct = function(e){
  e.preventDefault();

  var formData = e.currentTarget.form.dataElement;

  formData.custom_callback = function(){
    window.location.reload();
  }
  formData.submit(e);
};
Fluid.dataEvents.toggleBlogAnswer = function(e){
  var objData = $(e.target).data("fluidData");
  this.container = $(e.target).parent('.answer').children('.answerForm'+objData.id);

  if(this.container.find('form').length){
    this.container.toggle();
  }else{
    $.ajax({
      url: '/blog/actions/addReplyForm/',
      type: 'post',
      data: JSON.stringify(objData),
      success: (function(result){
        this.container.html(result).toggle(); // fill the content
        new Fluid.blogCommentForm(this.container.find('form').get(0)); // initialize the comment form
      }).bind(this)
    });
  }
};

Fluid.dataEvents.viewMoreRefundRequests = function(e) {  
  var objData = $(e.target).data("fluidData");

  if ( $('.' + objData.idRefundRequests).css('display') === "none" ) {
    $('.' + objData.idRefundRequests).css('display', 'table-row').addClass('refundRequestsGroupOpened');
    $(e.target).addClass('caret-reversed');
  } 
  else {
    $('.' + objData.idRefundRequests).css('display', 'none').removeClass('refundRequestsGroupOpened');
    $(e.target).removeClass('caret-reversed');
  }
};

Fluid.dataEvents.viewMoreRefunds = function(e) {  
  var objData = $(e.target).data("fluidData");

  if ( $('.' + objData.idRefunds).css('display') === "none" ) {
    $('.' + objData.idRefunds).css('display', 'table-row').addClass('refundGroupOpened');
    $(e.target).addClass('caret-reversed');
  } 
  else {
    $('.' + objData.idRefunds).css('display', 'none').removeClass('refundGroupOpened');
    $(e.target).removeClass('caret-reversed');
  }  
};

Fluid.dataEvents.viewMoreRefundInvoices = function(e) {  
  var objData = $(e.target).data("fluidData");

  if ( $('.' + objData.idRefundInvoices).css('display') === "none" ) {
    $('.' + objData.idRefundInvoices).css('display', 'table-row').addClass('refundGroupOpened');
    $(e.target).addClass('caret-reversed');
  } 
  else {
    $('.' + objData.idRefundInvoices).css('display', 'none').removeClass('refundGroupOpened');
    $(e.target).removeClass('caret-reversed');
  }  
};

Fluid.dataEvents.addProductToComparer = function(e) {
  var objData = $(e.target).data("fluidComparerData"),
      strComparerTriggerInit = $(e.target).data("fluidComparerTriggerInit"),
      strComparerTriggerCallback = $(e.target).data("fluidComparerTriggerCallback");
      blnAutorefresh = $(e.target).data("fluidComparerAutorefresh");

  // Call the init function if is defined
  if (typeof strComparerTriggerInit !== "undefined" && strComparerTriggerInit.length && window[strComparerTriggerInit]) {
    window[strComparerTriggerInit](objData);
  }
  
  var strProductId = objData.productId;
  
  var addProductToComparerCallback = function (data) {
    if ("statusCode" in data && data.statusCode == 200) {
      if (!("response" in data) || !("CODE" in data.response)) {
        return;
      }

      if (blnAutorefresh) {
        location.reload();
        return;
      }

      var notifyType = ((data.response.CODE > 0) ? "success" : "danger"),
          btnComparerClassToAdd = "comparerProductButtonAdded",
          strNotificationComparerLayer = "#comparerBasketLayer";

      if (data.response.CODE == 1) {
        $(e.target).removeClass(btnComparerClassToAdd);
      } else if (data.response.CODE == 2) {
        $(e.target).addClass(btnComparerClassToAdd);
      }

      if ("comparerBasket" in Fluid && data.response.CODE > 0) {
        Fluid.comparerBasket.reload();
      }

      $("#comparerNotificationBasket").data("comparerBasketItems",data.response.ITEMS);

      if (data.response.CODE == 2 && Fluid.config.showModalComparerBasket && (settings.isMobile == 1 || window.innerWidth < 992) ) {
        var buttonClass = htmlFramework == 'bootstrap' ? ' btn btn-default btn-block' : 'modalComparerButton';
        var submitButtonClass = htmlFramework == 'bootstrap' ? ' btn-primary' : '';
        var modalContent = '<div id="modalComparer"><span>' + languageSheet.COMPARER_STATUS3 + '</span><a href="/comparer/products" class="' + buttonClass + submitButtonClass + ' ModalComparerSeeProducts">'+ languageSheet.COMPARERMODAL_SEECOMPARER + '</a><a data-dismiss="modal" class="' + buttonClass + ' ModalComparerContinue">' + languageSheet.COMPARERMODAL_CONTINUE + '</a></div>';

        $("body").box({
          uid : 'mobileBasketModal',
          source: modalContent,
          showFooter : false,
          triggerOnClick : false,
          type : 'text'
        });
      } else {
        Fluid.notify(data.response.MESSAGE, {"type":notifyType});
      }

      // Call the init function if is defined
      if (typeof strComparerTriggerCallback !== "undefined" && strComparerTriggerCallback.length && window[strComparerTriggerCallback]) {
        window[strComparerTriggerCallback](objData, data);
      }
    }
  };

  $.post('/comparer/addProduct/', JSON.stringify({"productId":strProductId}), addProductToComparerCallback, 'json'); 
};
Fluid.dataEvents.setPaymentSystemToken = function(e) {  
  var objData = $(e.target).data("fluidData");

  $('.paymentSystemToken').removeClass('selected');
  $(e.target).parent().parent().addClass('selected');
  if (objData.token.length) {
    $('#paymentReference').val(objData.token);
    $('.tokenize').find('input').prop('checked',false);
    $('.tokenize').find('input').prop('disabled',true);
  } else {
    $('#paymentReference').val('');
    $('.tokenize').find('input').prop('checked',true);
    $('.tokenize').find('input').prop('disabled',false);
  }
};

/**
 * Fluid Events: address book module
 */
Fluid.dataEvents.addAddressBook = function(e) {
  e.preventDefault();
  var objData = $(e.target).data("fluidData")
     , userId = objData.userId
     , mode = objData.mode, type = objData.type
     , visibleFields = objData.visibleFields
     , addressBookForm = '//'+location.host+'/user/addressBook/popup/'+type;

  // switching mode
  switch (mode) {
    // popup
    case 1:
      $(e.target).box({
        uid: 'addressBookFormModal', 
        source: addressBookForm,
        showFooter: false, 
        triggerOnClick: false, 
        type:'url',
        callback: 'modalUserAddressBook'
      });
    break;

    // toggle-form
    case 2:
      var nameType = type == 1 ? 'billing' : 'shipping',
          $target  = $('#'+nameType+'Target');

      if ($target.length)
        $target.remove();
      else
      {
        $target = $('<div>', {
          id : nameType+'Target'
        });

        $.post(addressBookForm, {}, function(data) 
        { 
          $(data).appendTo($target);
          $target.appendTo($('#'+nameType+'AddressContainer'));
          //$target.show();
          var $form = F('#userAddressBookForm');
          $form.visibleFields = visibleFields;
          new Fluid.userAddressBookForm($form);
          $('<input type="hidden" name="mode" value="'+mode+'" />').appendTo($form);
        });   
      }
    break;
  }
};
Fluid.dataEvents.editAddressBook = function(e) {
  e.preventDefault();
  var objData   = $(e.target).data("fluidData")
         , id   = objData.id
         , mode = objData.mode
         , type = objData.type
         , addressBookForm = '//'+location.host+'/user/addressBook/popup/'+type+'/'+id+'/'
         , nameType = type == 1 ? 'billing' : 'shipping'
         , visibleFields = objData.visibleFields
         , $target  = $('#'+nameType+'Target');

  // selecting radio
  $('#'+nameType+'Address_'+id).prop('checked',true);

  // switching mode
  switch (mode) {
    // open popup
    case 1:
      $(e.target).box({
        uid: 'addressBookFormModal', 
        source: addressBookForm,
        showFooter: false, 
        triggerOnClick: false, 
        type:'url',
        callback: 'modalUserAddressBook'
      });
    break;
    // toggle-form
    case 2:        
      if ($target.length)
        $target.remove();
      else
      {
        $target = $('<div>', {
          id : nameType+'Target'
        });

        $.post(addressBookForm, {}, function(data) 
        { 
          $(data).appendTo($target);
          $('#'+'addressBookContainer_'+id).after($target);
          //$target.show();
          var $form = F('#userAddressBookForm');
          $form.visibleFields = visibleFields;
          new Fluid.userAddressBookForm($form);
          $('<input type="hidden" name="mode" value="'+mode+'" />').appendTo($form);
        });   
      }      
    break;
  }

};
Fluid.dataEvents.editUserAddressBook = function(e) {
  var objData = $(e.target).data("fluidData"), addressBookId = objData.id, type = objData.type;
  location.href = '/user/addressBook/edit/'+type+'/'+addressBookId;
};
Fluid.dataEvents.deleteAddressBook = function(e) {
  var objData = $(e.target).data("fluidData"), addressBookId = objData.id, defaultAddress = objData.default, type = objData.type;

  //if (defaultAddress == 1 && type == 1)
  if (defaultAddress == 1)
  {
    Fluid.notify(languageSheet.CANTDELETEDEFAULTADDRESS, {type:"danger"});
    return false;
  }

  // Are you sure?
  var deleteAddressBookCallback = function(data)
  {
    if ("statusCode" in data && data.statusCode == 200) 
    {
      if (!("response" in data) || !("SUCCEEDED" in data.response)) 
        return;
      if (data.response.SUCCEEDED == 1)
      {$("div").find('[data-id='+addressBookId+']').remove(); Fluid.notify(data.response.MESSAGE, {"type":"success"});}
      else
        Fluid.notify(data.response.MESSAGE, {"type":"danger"});
    }
  };  
  $.post('/user/deleteAddressBook/', JSON.stringify({"id":addressBookId}), deleteAddressBookCallback, 'json'); 
};
Fluid.dataEvents.setDefaultAddressBook = function(e) {
  var objData = $(e.target).data("fluidData"), addressBookId = objData.id, defaultAddress = objData.default, type = objData.type;

  var setDefaultAddressBookCallback = function(data)
  {
    if ("statusCode" in data && data.statusCode == 200) 
    {
      if (!("response" in data) || !("SUCCEEDED" in data.response)) 
        return;

      if (data.response.SUCCEEDED == 1)
      { 
        //$('#addressBookContainer .well').find('.default').remove();
        //$('#addressBookContainer .well').removeClass('defaultAddress');
        $('#addressBookContainer .well').each(function(index, element){
          $element = $(element);
          if ($element.attr('data-id') != addressBookId)
          {
            var tempId = $element.attr('data-id'), tempType = $element.attr('data-type'), tempDefault = $element.attr('data-default');
            if (type == tempType)
            {
              $element.find('.default').remove();
              $element.removeClass('defaultAddress');
              if ($element.find('.adressSetAsDefault').length==0){
                $('<button />', {
                  'html' : languageSheet.DELETEADDRESS,
                  'class' : 'addressBookAction adressBookDelete btn btn-default'
                }).data('fluidData',{'id':tempId, 'type':tempType, 'default':tempDefault}).on('click', Fluid.dataEvents.deleteAddressBook).prependTo($element.find('.buttons'));
                $('<button />', {
                  'html' : languageSheet.SETADDRESSASDEFAULT,
                  'class' : 'addressBookAction adressSetAsDefault btn btn-default'
                }).data('fluidData',{'id':tempId, 'type':tempType, 'default':tempDefault}).on('click', Fluid.dataEvents.setDefaultAddressBook).appendTo($element.find('.buttons'));
              }
            }
          }
        });
        $(e.target.parentNode).find('.adressBookDelete').remove();
        $(e.target).remove();
        $('<div />', {'class':'default','html':languageSheet.DEFAULTADDRESS+'</div>'}).insertBefore($($("div").find('[data-id='+addressBookId+']')).children()[0]);
        $("div").find('[data-id='+addressBookId+']').addClass('defaultAddress');

        Fluid.notify(data.response.MESSAGE, {"type":"success"});        
      }
      else
        Fluid.notify(data.response.MESSAGE, {"type":"danger"});
    }
  };
  $.post('/user/setDefaultAddressBook/', JSON.stringify({"id":addressBookId}), setDefaultAddressBookCallback, 'json');
};

// 20160524AVHCMFL-01
Fluid.dataEvents.externalConnectionLogin = function(e) {
  e.preventDefault();

  var legalCheck = $(e.currentTarget).parent('div.socialLoginCheck').find("input[name='agreement']").get(0);

  if(legalCheck && !$(legalCheck).is(":hidden") && !$(legalCheck).is(":checked")){
    $(legalCheck.parentNode)
      .removeClass('has-success')
      .addClass('has-error')
      .find('span.form-error').remove().end()
      .append('<span class="help-block form-error">'+$(legalCheck).data("validationErrorMsg")+'</span>');

    return false;
  }else{
    if(legalCheck) $(legalCheck.parentNode).removeClass('has-error').addClass('has-success').find('span.form-error').remove();

    var externalConnectionData = $(e.currentTarget).data("fluidData");
    var externalConnection = externalConnectionData.externalConnection;
    var externalConnectionHeight = externalConnectionData.windowHeight ? externalConnectionData.windowHeight : 450;
    var externalConnectionWidth = externalConnectionData.windowWidth ? externalConnectionData.windowWidth : 400;
    window.open('/user/oauth/' + externalConnection, externalConnection + 'LoginPopup', 'height='+externalConnectionHeight+',width='+externalConnectionWidth+',scrollbars=yes,resizable=yes');
  }

};

// 20160608DBCM-01
Fluid.dataEvents.setCustomer = function(e) {
  var userId = $(e.target).data("fluidData").id;
  var setCustomerCallback = function(data)
  {
    if (data.response.REDIRECT)
      location.href = '/user';
    else
      Fluid.notify(data.response.MESSAGE, {"type":"danger"});
  }; 
  $.post('/user/salesAgent/setCustomer/', JSON.stringify({"userId":userId}), setCustomerCallback, 'json');
};

Fluid.dataEvents.setBasketFapiao = function(e) {
 if ($("#inputFapiaoActived").is(":checked")){
  
  $('#inputInvoicenameFapiao').attr('data-validation','required');
   $('#selectInvoicenameFapiao').attr('data-validation','required');
  $("#fapiaoContent").show();

 }else{

  $('#inputInvoicenameFapiao').attr('data-validation','');
   $('#selectInvoicenameFapiao').attr('data-validation','');
  $("#fapiaoContent").hide();
 }
};

Fluid.dataEvents.updateBasket = function(e){
  var data = $(e.delegateTarget).data('data');

  switch(location.pathname)
  {
    case '/checkout':
    case '/checkout/oneStepCheckout':
      var callback = function(){
        fluidOneStepCheckout.moduleCalls('refreshModule');
        if (Fluid.hasOwnProperty('miniBasket'))
          Fluid.miniBasket.reload();
      }
      break;
    default:
      var callback = function(){location.reload();};
  }

  $.post('/basket/updateBasket/', JSON.stringify(data), callback, 'json');
};

Fluid.dataEvents.actionShipperIntegration = function(e){
  var data = {};
  data.orderId = $(e.delegateTarget).attr('data-orderId');
  data.action = $(e.delegateTarget).attr('data-action');
  data.refund = $(e.delegateTarget).attr('data-refund');

  var callback = function(data){
    //fluidOneStepCheckout.moduleCalls('refreshModule');
    //location.reload();
    if (data.response.error == 1)
      Fluid.notify(data.response.message, {"type":"danger"});
    else
      Fluid.notify(data.response.message, {"type":"success"});
  }

  $.post('/orders/shipperIntegration/', JSON.stringify(data), callback, 'json');

};

Fluid.dataEvents.incidenceForm = function(e){
  e.preventDefault();
  var data = $(e.currentTarget).data('fluidData');

  //show answer/create popup
  $(e.target).box({
  // this.warningBox = $('<span/>').appendTo($(document.body)).box({
    uid:'popupIncidenceForm',
    source:'/snippets/incidenceForm' + (data ? ('?' + $.param(data)) : ''),
    showFooter:false,
    type:'url',
    callback:'incidenceFormCallback',
    triggerOnClick:false
  });
};

Fluid.dataEvents.downloadIncidenceAttachment = function(e){
  e.preventDefault();
  var data = $(e.currentTarget).data('fluidData'), attachment = '', token = '';

  if(data.attachment) attachment = data.attachment;
  if(data.token) token = data.token;

  var newWindow = window.open('//'+location.host+'/user/incidenceAttachment/'+ encodeURIComponent(attachment) +'/'+ token +'/', '_blank');
  newWindow.window.onload = function(){ // Manually close the window. Useful when the attachment doesn't exist anymore
      newWindow.window.close();
  }
};

Fluid.dataEvents.onProductClick = function(e){
  var data = {};
  data.productId = $(e.delegateTarget).attr('data-id');

  Fluid.resources.pluginListener('onProductClick', e, data);
};

Fluid.dataEvents.link = function(e, options){
  e.preventDefault();

  var objData = $(e.target).data("fluidData");
  if (!objData.href) return false;

  window.location = objData.href;
};

/**
 * Fluid Quantity number.
 */
Fluid.fn("quantity", {
  Constructor : function(element, options){
    this.fieldName = Fluid.uniqueId(element.data('fluidQuantity'));
    this.init = function(){

      this.minValue = element.attr('min') || 1;
      this.maxValue = element.attr('max') || 999999999;
      this.multipleFrom = parseInt(element.attr('multipleFrom')) || 1;
      this.multipleValue = parseInt(element.attr('multipleValue')) || 1;

      // Create vars
      this.$container = $('<div />',{'class': 'input-group'});
      this.$minus = $('<span />',{'class': 'input-group-btn'});
      this.$plus = $('<span />',{'class': 'input-group-btn'});

      this.$minusBtn = $('<button />',{
        type: 'button',
        'class': 'btn btn-default btn-number',
        'data-type' : 'minus',
        'data-field' : this.fieldName,
        html : '<span class="glyphicon glyphicon-minus"></span>'
      }).appendTo(this.$minus).click(this.clickBtn.bind(this));

      this.$plusBtn = $('<button />',{
        type: 'button',
        'class': 'btn btn-default btn-number',
        'data-type' : 'plus',
        'data-field' : this.fieldName,
        html : '<span class="glyphicon glyphicon-plus"></span>'
      }).appendTo(this.$plus).click(this.clickBtn.bind(this));

      // Add name attribute if element does not have it...
      if (!element[0].hasAttribute('name')){
        element.attr({name: this.fieldName});
      }

      // Prepare element
      element
        .attr({type: 'text'})
        .addClass('form-control input-number')
        .after(this.$container)
        .change(this.changeField.bind(this))
        .focus(this.focusField.bind(this));

      // Prevents to relaunch init
      element.removeAttr('data-fluid-quantity');

      // Append $container
      this.$container
        .append(this.$minus)
        .append(element)
        .append(this.$plus);

    };
    this.destroy = function(){
      this.$container.after(element);
      this.$container.remove();
    };
    this.clickBtn = function(e){
      e.preventDefault();

      var $this = $(e.currentTarget);

      var type = $this.attr('data-type');
      var currentVal = parseInt(element.val());
      var difference = parseInt(currentVal) + parseInt(this.multipleValue);
      difference = difference % this.multipleValue;

      if (!isNaN(currentVal)) {
        if(type == 'minus') {
          if(currentVal > this.minValue){
            if(this.multipleValue > 1){ // Apply multiple logic
              if(difference != 0)
                var value = currentVal - difference;
              else
                var value = (currentVal - this.multipleValue) - difference;

              if(value < this.multipleFrom && currentVal > this.multipleFrom)
                element.val(this.multipleFrom).change();
              else if(value >= this.minValue)
                if(this.multipleFrom < value)
                  element.val(value).change();
                else
                  element.val(currentVal - 1).change();
              else
                element.val(currentVal - 1).change();

            }else
              element.val(currentVal - 1).change();
          }
          if(parseInt(element.val()) == this.minValue)
            $this.attr('disabled', true);
        }
        else if(type == 'plus') {
          if(currentVal < this.maxValue){
            if(this.multipleValue > 1){ // Apply multiple logic
              var value = (currentVal + this.multipleValue) - difference;

              if(value <= this.maxValue)
                if(this.multipleFrom <= value && (currentVal+1) > this.multipleFrom)
                  element.val(value).change();
                else
                  element.val(currentVal + 1).change();
            }else
              element.val(currentVal + 1).change();

          }
          if(parseInt(element.val()) == this.maxValue)
            $this.attr('disabled', true);
        }
      }
      else
        element.val(0);
    };
    this.focusField = function(){
      element.data('oldValue', element.val());
      this.oldValue = element.val();
    };
    this.changeField = function(){
      var valueCurrent = parseInt(element.val());

      if(valueCurrent >= this.minValue)
        this.$minusBtn.removeAttr('disabled')
      else{
        console.log('Sorry, the minimum value was reached');
        element.val(this.oldValue);
      }

      if(valueCurrent <= this.maxValue)
        this.$plusBtn.removeAttr('disabled')
      else {
        console.log('Sorry, the maximum value was reached');
        element.val(this.oldValue);
      }
    }
  }
});

/**
 * Fluid notify
 */
;(function($) {

  Fluid.fn('notify', {
    options : {
      type: 'info',
      speed: 500,
      delay: 3000,
      easing: 'swing',
      effect: 'fade',
      removeIcon: '<span>x</span>'
    },
    Constructor : function(element, options){
      var notify = this;
      
      /** 
       * Initialize
       */
      notify.init = function(){

        // Force view when the view is mobile
        if (settings && settings.isMobile) options.type = 'info';
        
        element
          .addClass('fluidNotify fluidNotify-' + options.type);

        // Creates a notification notes counter so each notification can be identified
        notify.notes = 0;
      }
      
      /**
       * Show
       * Create a new notification
       *
       * @param message {String} Contains the message for the notification
       * @param opts {Object} Contains the settings for the notification
       */
      notify.show = function(opts) {

        var opts = $.extend({
          id: 'note-' + notify.notes++,
          type: false,
          title: false,
          message: '',
          sticky: false,
          speed: options.speed,
          delay: options.delay,
          easing: options.easing,
          effect: options.effect,
          icon: false,
          removeIcon: options.removeIcon,
        }, opts);



        // New notification is created
        var $note = $('<div />', {
          'class' : 'note '+ opts.id + (opts.type? ' note-'+opts.type : '')
        });

        // Icon is attached to the new notification if one is specified
        if (opts.icon){
          $('<span />', {
            'class': 'icon',
            html: $(opts.icon)
          }).appendTo($note);
        }

        // Add remove button for the notification
        $('<button />', {
          type: 'button',
          'class': 'remove',
          html: $(opts.removeIcon)
        }).appendTo($note);

        // New content container is created for the notification
        $content = $('<div>', {
          'class': 'content'
        });

        // Add a notification title if one is specified
        if (opts.title) {
          $('<strong />', {
            'class' : 'title',
            html: opts.title
          }).appendTo($content);
        }

        // Notification message is added to the content container
        $content.append(opts.message);

        // Content container is added to the notification
        $note.append($content);

        // Notification is added to the notification parent container
        element.prepend($note);

        // Ignore the close timer if the notification is a sticky
        if (!opts.sticky) {
          // Create a new close timer for the notification
          var noteTimer = new closeTimer($note, opts);

          // Pause the close timer if the mouse is over the notification
          element.on('mouseover', '.' + opts.id, function() {
            noteTimer.pause();
          });

          // Resume the close timer from the paused position when the mouse is moved away from the notification
          element.on('mouseout', '.' + opts.id, function() {
            noteTimer.resume();
          });
        }

        // Remove the notification if the remove button has been clicked
        element.on('click', '.remove', function() {
          $(this).closest('.note').animate({
            'opacity': 0
          }, opts.speed, opts.easing).slideUp( opts.speed, function() {
            $(this).remove();
          });
        });
      };

      /**
       * Close
       * Closes the notification using the option effect
       *
       * @param content {Object} Contains the element that needs to be closed & removed
       * @param opts    {Object} Contains all the options associated with the particular notification
       */
      notify.close = function(content, opts) {
        // Determine which effect was specified and use run the appropriate close code
        switch (opts.effect) {
          case 'fade':
            content.animate({
              'opacity': 0
            }, opts.speed, opts.easing).slideUp(opts.speed, function() {
              $(this).remove();
            });
            break;

          case 'slide':
            content.slideToggle(opts.speed, function() {
              $(this).remove();
            });
            break;

          default:
            content.toggle(opts.speed, function() {
              $(this).remove();
            });
            break;
        }
      };

      /**
       * Close Timer (private)
       * Takes in an element and its options to create a timeout function to close the notification
       *
       * @param element {Object} Contains the element that needs to be closed
       * @param opts    {Object} Contains all the options associated with the particular notification
       */
      function closeTimer(content, opts) {
        // Creates a unique id, start and remaining time using the option's delay var
        var timerId, start, remaining = opts.delay;

        // Pause function that clears the timeout and determines what the remaining time before the close is
        this.pause = function() {
          window.clearTimeout( timerId );
          remaining -= new Date() - start;
        };

        // Resume function starts the timeout function which will fire the close prototype function
        this.resume = function() {
          start = new Date();
          timerId = window.setTimeout( function() {
            notify.close(content, opts);
          }, remaining );
        };

        // 3, 2, 1 ... START!
        this.resume();
      };
    }
  });


  Fluid.initQueue.enqueue(function(){
    var notifyElement = $('#fluidNotify').notify(Fluid.config.notify);
    Fluid.notify = function(message, opts){
      notifyElement.notify('show', $.extend({message : message}, opts));
    };
  });
})(jQuery);

Fluid.basketExpiration = {
  expirationTimeout:0
  ,expirationPopupTimeout:0
  ,warningPopupTimeout:0
  ,initialized:false
  ,init:function(){
    if(this.initialized)
      return;

    if(!('basketLock' in settings))
      return;

    this.initialized = true;

    if( $('[data-basket-stock-lock]').length )
      this.checkNewExpirationDate();
    else
      this.setExpirationDate(settings.basketLock.basketExpires);
    
  }
  ,setExpirationDate:function(expDate){
    if(!this.initialized)
      return;

    var remainingSeconds = moment(expDate).add(settings.localServerOffsetTime, 'seconds').diff( moment(), 'seconds');

    clearTimeout(this.expirationTimeout);
    clearTimeout(this.expirationPopupTimeout);
    clearTimeout(this.warningPopupTimeout);

    this.expirationTimeout = setTimeout(this.expireBasket, remainingSeconds*1000);

    if(settings.basketLock.expiredPopup && remainingSeconds > 0){
      this.expirationPopupTimeout = setTimeout(this.adviceExpireBasket, remainingSeconds*1000);
    }

    if(settings.basketLock.warningMinutes){
      remainingWarningSeconds = remainingSeconds - settings.basketLock.warningMinutes*60;
      if(remainingWarningSeconds > 0){
        window.warningPopupTimeout = setTimeout(this.warnExpireBasket, remainingWarningSeconds*1000);
      }
    }

  }
  ,checkNewExpirationDate:function(){
    var stockLockData = $('[data-basket-stock-lock]').data('basket-stock-lock');
    if(!stockLockData)
      return;

    Fluid.basketExpiration.setExpirationDate(stockLockData.expires);

    var expires = moment(stockLockData.expires).unix();

    $('[data-basket-expires]').each(function(index, element) {
      if(element.basketCountDown)
        element.basketCountDown.endDate = expires;
    });
  }
  ,expireBasket:function(){
    $(document.body).addClass('basket-expired');
    $('[data-basket-expired="remove"]').remove();
  }
  ,adviceExpireBasket:function(){
    //hide warning popup
    if(this.warningBox){
      this.warningBox.box('close').remove();
    }
    //show expiration popup
    this.warningBox = $('<span/>').appendTo($(document.body)).box( {uid:'popupBasketExpired', source:'/snippets/basketExpired', showFooter:false, type:'url', callback:'stockLockPopup', triggerOnClick:false } );
  }
  ,warnExpireBasket:function(){
    this.warningBox = $('<span/>').appendTo($(document.body)).box( {uid:'popupWarningBasketExpires', source:'/snippets/basketExpiresWarning', showFooter:false, type:'url', callback:'stockLockPopup', triggerOnClick:false } );
  }

};
/**
 * Initialize forms and validators
 * @param  {Object} wrap     jQuery Object
 * @param  {Boolean} isModal
 */
Fluid.initializeForms = function(wrap, isModal) {
  var wrap = wrap || $(document);

  // Initialize Forms
  wrap.find('form').each(function(index, form) {
    form.isModal = isModal;
    var dataFluidForm = $(this).data('fluidForm');

    if(form.initialized) return;

    if (Fluid[dataFluidForm]){
      new Fluid[dataFluidForm](form);
      return;
    }

    switch(dataFluidForm){
      case 'packBuyForm': new Fluid.PackBuyForm(form); break;
      case 'buyForm': new Fluid.BuyForm(form); break;
      case 'buyGiftForm': new Fluid.BuyGiftForm(form); break;
      case 'changePasswordForm': new Fluid.ChangePasswordForm(form); break;
      case 'confirmAccountForm': new Fluid.ConfirmAccountForm(form); break;
      case 'lostPasswordForm': new Fluid.LostPasswordForm(form); break;
      case 'loginForm': new Fluid.LoginForm(form); break;
      case 'userForm': new Fluid.UserForm(form); break;
      case 'checkoutForm': new Fluid.CheckoutForm(form); break;
      case 'oneStepCheckout': fluidOneStepCheckout = new Fluid.OneStepCheckout(form); break;
      case 'contactForm': new Fluid.ContactForm(form); break;
      case 'deleteAccount': new Fluid.DeleteAccountForm(form); break;
      case 'searchForm': new Fluid.SearchForm(form); break;
      case 'productAddCommentForm': new Fluid.ProductAddCommentForm(form); break;
      case 'affiliateOrdersForm': new Fluid.AffiliateOrdersForm(form); break;
      case 'deleteWishListForm': new Fluid.DeleteWishListForm(form); break;
      case 'productSubscribeStockForm': new Fluid.ProductSubscribeStockForm(form); break;
      case 'sponsorshipForm': new Fluid.SponsorshipForm(form); break;
      case 'orderRefundForm': new Fluid.OrderRefundForm(form); break;
      case 'unsubscribeStockAlertForm': new Fluid.UnsubscribeStockAlertForm(form); break;
      case 'comparerCustomTagsForm': new Fluid.ComparerCustomTagsForm(form); break;
      case 'filterForm': new Fluid.FilterForm(form); break;
      case 'customForm': new Fluid.CustomForm(form); break;
      case 'pollForm': new Fluid.PollForm(form); break;
      case 'customersForm': new Fluid.CustomersForm(form); break;
      case 'productsFilter': new Fluid.productsFilter(form); break;
      case 'countrySelectorForm': new Fluid.CountrySelectorForm(form); break;
      case 'confirmAgePopupForm': new Fluid.ConfirmAgePopupForm(form); break;
      default: if(!$(this).data('fluidFormIgnore')) new Fluid.Form(form); break;
    }
  });
}

/**
 * This functions initialize Fluid components
 * @memberOf Fluid
 */
Fluid.initQueue.enqueue(function(){

  // Initialize Form Validator - http://formvalidator.net
  $.validate(Fluid.validateFormConf);

  //Initialize click and view object counter
  Fluid.initializeIncrementCounter();

  //Initialize countdowns before forms. buyForm requires this
  Fluid.initializeCountdowns();

  Fluid.basketExpiration.init();


  // Initialize Forms
  Fluid.initializeForms();

  // Initialize Modals
  $('[data-fluid-modal]').box();

  // Initialize Slideboxes
  if (typeof $.fn.slideBox === 'function')
    $('[data-fluid-slidebox]').slideBox();

  // Initialize Quantity Fields
  $('input[data-fluid-quantity]').quantity();

  // Initialize Data events
  $('[data-fluid-event]').dataEvent();

  // shippingcalculator
  $('[data-fluid-shippingcalculator]').each(function(index, el) {
    new Fluid.shippingPrices(el);
  });

  // Initialize confirm Order
  $('[data-fluid-confirmOrder]').each(function(index, element) {
    Fluid.setConfirmOrder(element);
  });

});"use strict";
Fluid.events = {

    callbacks: {},
    scroll: {},
    resize: {},
    scroll_rates: [],
    resize_rates: [],

    addEvent: function(name, config) {
        var self = this,
            event = (config.event && (config.event === 'scroll' || config.event === 'resize')) ? config.event : false,
            method = config.method || false,
            rate = config.rate || 50,
            trailing = (typeof config.trailing === 'boolean') ? config.trailing : false;

        if (!event || !method) {
            throw "Bad formed event config in config.json events";
        }

        //register debounce/throttle function 
        self[event][name] = $[method].apply($[method], [rate, trailing, function() { $(window).trigger(name); }]);

        //create event callbacks array
        self.callbacks[name] = [];

        //save rate
        self[event + '_rates'].push({ rate: rate, name: name });

    },
    addCallback: function(event, cb, args) {
        // prevent fails if callback array doesn't exist i.e. the event has not been defined in config.json
        if (!Array.isArray(Fluid.events.callbacks[event])) return;
        Fluid.events.callbacks[event].push([cb, args]);

    },
    removeCallback: function(event, cb) {
         var self = this,
             arr = self.callbacks[event];

        if (Array.isArray(arr)) {
            arr.forEach(function(e, i) {
                if (e[0] === cb) {
                    arr.splice(i, 1);

                }
            });
        } else {
            return false;
        }
    },
    getMinimumRate: function(event) {
        //select minimum rate for updating scrollTop and Window size, and add corresponding callback depending on event
        var self = this;
        //extract rates array 
        var rates = self[event + '_rates'].map(function(ev) {
            return ev.rate;
        });
        //extract events array 
        var events = self[event + '_rates'].map(function(ev) {
            return ev.name;
        });

        if (rates.length === 0) {
            return -1;
        }

        var min = rates[0];
        var minIndex = 0;

        for (var i = 1; i < rates.length; i++) {
            if (rates[i] < min) {
                minIndex = i;
                min = rates[i];
            }
        }

        self.addCallback(events[minIndex], self[event + '_cb'].bind(self));
        return true;
    },

    resize_cb: function() {
        //get window size
        this.windowWidth = document.documentElement.clientWidth;
        this.windowHeight = document.documentElement.clientHeight;
    },
    scroll_cb: function() {
        //get scrollTop
        this.scrollTop = $(this.scrollContainer).scrollTop();
    },
    init: function() {
        //if there's no events config defined do not initialize
        if (typeof settings.events !== 'object' || typeof settings.events.setup !== 'object') {
            return;
        }

        var self = this;

        self.scrollContainer = settings.events.scrollContainer || window;

        //add events from config JSON
        Object.keys(settings.events.setup).forEach(function(name) {
            self.addEvent(name, settings.events.setup[name]);
        });

        self.getMinimumRate('scroll');
        self.getMinimumRate('resize');

        self.resize_cb();
        self.scroll_cb();

        // attach a listener to scroll controll
        $(self.scrollContainer).on('scroll', function() {
            Object.keys(Fluid.events.scroll).forEach(function(key) {
                Fluid.events.scroll[key]();
            });
        });
        // attach a listener to window resize
        $(window).on('resize', function() {
            Object.keys(Fluid.events.resize).forEach(function(key) {
                Fluid.events.resize[key]();
            });
        });

        //execute callbacks array on each callback
        Object.keys(Fluid.events.callbacks).forEach(function(key) {
            $(window).on(key, function() {
                Fluid.events.callbacks[key].forEach(function(cb) {
                    //cb[0] = function, cb[1], args array
                    if (typeof cb[0] !== 'undefined' && typeof cb[0] == 'function') {
                        cb[0].apply(cb[0], cb[1]);
                    }
                });
            });

        });
    }
};

Fluid.initQueue.enqueue(function(){Fluid.events.init();});
;(function($) {
  
  'use strict';

  Fluid.fn("fluidScroll", {
    options : {
      baseUrl: "",
      autoTrigger: true,
      launchBase: true,
      dataType: "html",
      loadingHtml: '<div>Loading...</div>',
      loadingClass: "fluid-scroll-isLoading",
      wrapper: "div",
      callback: false,
      padding: 100,
      debug: false
    },
    Constructor : function(element, options){
      var self = this;
      var $window, $document, loading, request, loadingHtml;
      
      self.init = function(){
        debug('info', options);
        $window = $(window);
        $document = $(document);
        loadingHtml = '<div class="fluid-scroll-loading">' + options.loadingHtml + '</div>';

        if (options.autoTrigger)
          self.initScroll();
      };

      self.initScroll = function(){
        setNextUrl();
        setLoading(false);

        if (options.launchBase)
          scroll(true);

        $window.scroll(scroll.bind(self,false));
      };

      function scroll(ignorePosition){
        if (!canLoad(ignorePosition))
          return;

        setLoading(true);
        var $wrapper = prepareWrapper();
        
        request = getData(getNextUrl());

        request.done(function(data, status, jqXHR){
          debug('info', 'request.done', arguments);
          onLoad($wrapper, data, status, jqXHR);
        });

        request.fail(function(){
          debug('error', 'request.fail', arguments);
          $wrapper.remove();
        });        
      }

      function getData(url){
        return $.ajax({
          url: url,
          dataType: options.dataType,
          method: "GET"
        });
      }

      function canLoad(ignorePosition){
        if (isLoading() || !getNextUrl()) 
          return false;
        
        if (ignorePosition) 
          return true;
        
        return $window.scrollTop() >= $document.height() - $window.height() - options.padding;
      }

      function isLoading(){
        return loading;
      }

      function setLoading(status){
        loading = status;
        if (status)
          element.addClass(options.loadingClass);
        else
          element.removeClass(options.loadingClass);
      }

      function onLoad($wrapper, data, status, jqXHR){
        setLoading(false);

        if (status == "success") {
          var nextUrl = $(data).data('fluidScrollNextpage');

          if (!nextUrl)
            nextUrl = jqXHR.getResponseHeader('fluid-nextPage');

          setNextUrl(nextUrl);
          $wrapper.html(data);
        }
        else
          $wrapper.remove();

        if (options.callback && typeof options.callback === 'function')
          options.callback(element, $wrapper, data, status, jqXHR);
      }

      function setNextUrl(nextUrl){
        if (!nextUrl && !self.hasOwnProperty('nextUrl'))
          nextUrl = options.baseUrl || element.data('fluidScroll');
        else if (typeof nextUrl === "object")
          nextUrl = nextUrl.data('nexturl');
        
        self.nextUrl = nextUrl;
      }
      this.setNextUrl = setNextUrl;

      function getNextUrl(){
        return self.nextUrl? self.nextUrl : "";
      }

      function prepareWrapper(){
        var wrapperTag = "<" + (options.wrapper || div) + "/>" ;
        var $wrapper = $(wrapperTag, {"html": loadingHtml}).appendTo(element);
        return $wrapper;
      }

      function debug(dbg){
        if (options.debug && typeof console === 'object' && (typeof dbg === 'object' || typeof console[dbg] === 'function')) {
          if (typeof dbg === 'object') {
            var args = [];
            for (var prop in dbg) {
              if (typeof console[prop] === 'function') {
                args = (dbg[prop].length) ? dbg[prop] : [dbg[prop]];
                console[prop].apply(console, args);
              } else {
                console.log.apply(console, args);
              }
            }
          } else {
            console[dbg].apply(console, Array.prototype.slice.call(arguments, 1));
          }
        }
      }
    }
  });

  Fluid.initQueue.enqueue(function() {
    $('[data-fluid-scroll]').each(function(index, el) {
      var $el = $(el);
      var baseUrl = $el.data('fluidScroll');

      if (!baseUrl) return;
      
      $el.fluidScroll({
        baseUrl: baseUrl,
        launchBase: $el.data('fluidScrollLaunchbase') || true,
        autoTrigger: $el.data('fluidScrollAutotrigger') || true,
        padding: $el.data('fluidScrollPadding'),
        debug: $el.data('fluidScrollDebug'),
        dataType: $el.data('fluidScrollDatatype'),
        loadingHtml: $el.data('fluidScrollLoadinghtml'),
        loadingClass: $el.data('fluidScrollLoadingclass'),
        wrapper: $el.data('fluidScrollWrapper'),
        callback: Fluid.carryMethod($el.data('fluidScrollCallback'))
      });
    });

  });
})(jQuery);


patata = {
  poma : {
    pera: function(element, wrapper, data){
      //element.fluidScroll("setNextUrl", 'aaaaagh');
      Fluid.initializeForms(wrapper);
    }
  }
}/**
 * One Step Checkout
 * 
 * @description One Step Checkout JS module
 * @author Solutions Trilogi
 * @version 2.0 2016-11-22
 *
 * @TODO: Allowing multiple modules with identical types
 * 
 *
 * Config properties example
 * -------------------------------
 * Fluid.oneStepCheckoutConfig = {
 *   emailInputDelay: 600,
 *   notifyMode: true
 * };
 * 
 */

Fluid.OneStepCheckout = Fluid.Form.extend({
  name : 'oneStepCheckout',
  options : {},
  tracking : [],

  /**
   * DataModules defines each module and its interactions
   * @type {Object}
   */
  dataModules : {
    basket : {
      autoRefresh: true, 
      initializeMethod: 'initializeBasket',
      modulesToRefresh: [
        'basket',
        'buttons',
        'discounts',
        'gifts',
        'payments',
        'shippings',
        'amountFreeShipping',
        'discountPrediction'
      ]
    },
    buttons: {
      autoRefresh: true, 
      initializeMethod: 'initializeButtons'
    },
    comments: {},
    userForm : {
      initializeMethod: 'initializeUserForm',
      createAccount: true,
      modulesToRefresh: [
        'basket',
        'buttons',
        'discounts',
        'gifts',
        'payments',
        'shippings',
        'amountFreeShipping',
        'discountPrediction'
      ]
    },
    discounts: {
      autoRefresh: true,
      initializeMethod: 'initializeDiscounts'
    },
    amountfreeshipping: {
      autoRefresh: true,
       initializeMethod: 'initializeAmountFreeShipping'
    },
    //ePoints: {},
    gifts: {
      autoRefresh: true,
      modulesToRefresh: [
        'basket',
        'buttons',
        'discounts',
        'gifts',
        'payments',
        'shippings',
        'amountFreeShipping'
      ]
    },
    payments: {
      autoRefresh: true, 
      initializeMethod: 'initializePayments',
      modulesToRefresh: [
        'basket',
        'buttons',
        'discounts',
        'gifts',
        'payments',
        'shippings',
        'amountFreeShipping'
      ]

    },
    shippings: {
      autoRefresh: true, 
      initializeMethod: 'initializeShippings',
      modulesToRefresh: [
        'basket',
        'buttons',
        'discounts',
        'gifts',
        'payments',
        'shippings',
        'amountFreeShipping'
      ]
    },
    legalCheck: {
      initializeMethod: 'initializeLegalCheck'
    },
    discountPrediction: {
      autoRefresh: true,
      initializeMethod: 'initializeDiscountPrediction'
    },
    miniBasket: {
      autoRefresh: true,
      initializeMethod: 'initializeMiniBasket'
    }
  },

  /**
   * AdditionalContent defines each content, located outside OSC form
   * @type {Object}
   */
  additionalContent : {
    selectableGifts: {
      autoRefresh: true,
      initializeMethod: 'initializeSelectableGifts'
    },
    specialProducts: {
      autoRefresh: true,
      initializeMethod: 'initializeSpecialProducts'
    },
    discountPrediction: {
      autoRefresh: true,
      initializeMethod: 'initializeDiscountPrediction'
    },
    vinculatedProducts: {
      autoRefresh: true,
      initializeMethod: 'initializeVinculatedProducts'
    }
  },

  /**
   * This flag allows edit
   * @type {Boolean}
   */
  userVerified : false,

  /**
   * This flag controllers end order
   * @type {Boolean}
   */
  endOrder : undefined,

  /**
   * Determines delay to launch validation in input email
   * @type {Number}
   */
  emailInputDelay : 500,

  /**
   * Control email to prevent multiple validation in same value
   * @type {String}
   */
  emailInputValue : "",

  /**
   * Determines if messages are shown as Notify or message
   * @type {Boolean}
   */
  notifyMode : Fluid.notifyMode,

  moduleCallsStatus : {},


  // Initialize methods
  // ---------------------------------------------------------------------------

  /**
   * Initialize Object
   * @memberOf Fluid.OneStepCheckout
   */
  initialize : function(){
    // Set Config
    if (Fluid.hasOwnProperty('oneStepCheckoutConfig')){
      if (Fluid.oneStepCheckoutConfig.hasOwnProperty('emailInputDelay') && 
          typeof Fluid.oneStepCheckoutConfig.emailInputDelay === 'number')
        this.emailInputDelay = Fluid.oneStepCheckoutConfig.emailInputDelay;
      
      if (Fluid.oneStepCheckoutConfig.hasOwnProperty('notifyMode') && 
          typeof Fluid.oneStepCheckoutConfig.notifyMode === 'boolean')
        this.notifyMode = Fluid.oneStepCheckoutConfig.notifyMode;
    }


    // Before trigger
    this.trigger('initializeBefore');

    // MiniBasket module
    this.initializeMiniBasket();

    // Modules
    this.el.$form.find('[data-fluid-checkout]').each(function(index, el) {
      var $el = $(el);
      var key = $el.data('fluidCheckout');
      var module = this.dataModules[key];

      // Set module
      // If module does not exist, maybe it is custom module
      if (!module){
        // Custom Module
        var moduleProperties = $el.data('fluidCheckoutProperties');
        if ($.isPlainObject(moduleProperties)){
          module = moduleProperties;

          // RegisterModule
          this.dataModules[key] = module;
        }
      }

      // Initialize
      if (module) {
        module.active = true;
        module.el = $el;
        module.params = $el.data('fluidCheckoutParams');

        // Initialize module
        if (module.initializeMethod && $.isFunction(this[module.initializeMethod]))
          this[module.initializeMethod](module);
      }
    }.bind(this));

    // Additional content (outside form)
    $('div[data-fluid-oscac]').each(function(index, el) {
      var $el = $(el);
      var key = $el.data('fluidOscac');
      var content = this.additionalContent[key];

      // Initialize
      if (content) {
        content.active = true;
        content.el = $el;

        // Initialize content
        if (content.initializeMethod && $.isFunction(this[content.initializeMethod]))
          this[content.initializeMethod](content);
      }
    }.bind(this));

    // Helper Login Modal
    Fluid.modalCallbacks.oneStepCheckoutLogin = function($button, $box) {
      var loginForm = new Fluid.LoginForm($box.find('form')[0]);
      var inputEmail = $box.find(('#userLoginEmailField'));
      var inputPassword = $box.find(('#userLoginPasswordField'));
      var delaySetFocus = 510; 

      // Login form callback
      loginForm.callback = function(result){
        if (!this.trigger('loginFormCallbackSubstitute', result)) {
          this.trigger('loginFormCallback', result);
          this.setTracking('loginForm');

          if (result.response.LOGGEDIN) {
            if(typeof window.BrainSINSTrackedUser == 'undefined')
              window.BrainSINSTrackedUser = 0;

            /*REPORT TO BRAINSINS USER LOGGED*/
            if(result.response.HASBRAINSINS && window.BrainSINSTrackedUser == 0) {
              if(result.response.SUBSCRIBED)
                BrainSINSTracker.trackEMailNewsletter( $('#userLoginEmailField').val(), result.response.SUBSCRIBED, result.response.LANG );
              else
                BrainSINSTracker.trackEMailNewsletter( $('#userLoginEmailField').val(), 0 , result.response.LANG );

              window.BrainSINSTrackedUser = 1;
            }
            window.location.reload();
            $box.modal('hide');
          }
          else {
            loginForm.el.$message.html(result.response.MESSAGE)
              .addClass('alert alert-danger');
          }
        }
      }.bind(this);

      // Set input email
      if (this.loginEmailValue) {
        inputEmail.val(this.loginEmailValue);
        this.loginEmailValue = "";
        setTimeout(function(){inputPassword.focus()},delaySetFocus);
      }
      else
        setTimeout(function(){inputEmail.focus()},delaySetFocus);
    }.bind(this);


    // Edit callback method on BuyForm
    Fluid.BuyForm.prototype.callback = function(data){

      // Check status
      if (data.statusCode != 200){
        //Hide loading manually
        this.moduleCalls('loadingIndicator', false);
        this.notify(languageSheet.ONESTEPCHECKOUTPRODUCTADDEDERROR, 'error')
        return false;
      }

      if (data.response && data.response.ADDED){
        // Call notify
        this.notify(languageSheet.ONESTEPCHECKOUTPRODUCTADDED, 'success');

        // Refresh modules
        this.moduleCalls('refreshModule');
      }
      else {
        //Hide loading manually
        this.moduleCalls('loadingIndicator', false);
        this.notify(languageSheet.ONESTEPCHECKOUTPRODUCTADDEDERROR, 'error');
      }
    }.bind(this);

    // Callback
    this.trigger('initializeCallback');

    this.trigger('onLoad');

    // Clean unload
    this.el.$form.removeClass('unload');

    // initialize calendar. Ex: Used by orderCustomTag 
    var dateFields = this.el.$form.find('div[data-datetimepicker]').each(function(index,el) {
      var $calendar = $(el);

      // Options
      var language = $calendar.data('language');
      var format = $calendar.data('format');
      var startDate = $calendar.data('startdate');
      var endDate = $calendar.data('enddate');
      var daysOfWeekDisabled = $calendar.data('daysofweekdisabled');

      /* prevent undefined problem */
      if (typeof(startDate)=='undefined'){
        startDate=0;
      }
      if (typeof(endDate)=='undefined'){
        endDate=0;
      }

      /* Preparing max and min date. This prevents problems with the no verification with logicommerce */
       //Init calendar object
      var calendarObject={
        locale : language? language : 'en',
        format : format? format : 'DD/MM/YYYY',
      };

      /* Calendar init. Note: We can add another else and allow only an startDate or and endDate. Now is only allowed both together. */
      if ((isNaN(startDate) && startDate.length > 0) && (isNaN(endDate) && endDate.length > 0)){
        /* Preparing max and min date. This prevents problems with the no verification with logicommerce */
        var newStartDate = moment(startDate,format);
        var newEndDate = moment(endDate,format);
          
        if (newStartDate > newEndDate){
          calendarObject.minDate = newEndDate;
          calendarObject.maxDate = newStartDate;
        }else{
          calendarObject.minDate = newStartDate;
          calendarObject.maxDate = newEndDate;
        }
        
      }
      else if (isNaN(startDate) && startDate.length > 0 )
        calendarObject.minDate = moment(startDate, format);
      else if (isNaN(endDate) && endDate.length > 0 )
        calendarObject.maxDate = moment(endDate, format);

      if (startDate != 0 || endDate != 0) {
        calendarObject.daysOfWeekDisabled = daysOfWeekDisabled? eval(daysOfWeekDisabled) : eval('');
      }

      /* Fill the object with current values */
      $calendar.datetimepicker(calendarObject);
      
    });
    return;
  },

  /**
   * Initialize Buttons
   * @memberOf Fluid.OneStepCheckout
   * @param  {Object} module
   */
  initializeButtons : function(module) {
    // Call trigger
    this.trigger('initializeButtonsBefore');
    
    // Submit
    this.submitButton = module.el.find('button#basketEndOrder');

    // User error code
    this.userErrorCode = module.el.find('input[name="userErrorCode"]');
    this.validateAddressBook();

    // Enable or disable submit
    if (typeof this.endOrder === 'boolean')
      this.submitButton[0].disabled = !this.endOrder;

    // Call trigger
    this.trigger('initializeButtonsCallback');
    return;
  },

  /**
   * Initialize Basket
   * @memberOf Fluid.OneStepCheckout
   * @param  {Object} module
   */
  initializeBasket : function(module) {
    // Before trigger
    this.trigger('initializeBasketBefore');

    // Delete products
    module.el.find('[data-fluid-basketdeleteproduct]').click(this.deleteProduct.bind(this));

    // Delete discounts
    module.el.find('[data-fluid-basketdeletediscount]').click(this.deleteDiscount.bind(this));

    // Quantity
    var quantityElements = module.el.find('input.basketQuantity:text,select.basketQuantity');
    quantityElements
      .change(this.onChangeOption.bind(this))
      .keypress(function(event){
        if (event.keyCode == 13) {
          event.preventDefault();
          this.onChangeOption(event);
        }
      }.bind(this));

    // Initialize Quantity Fields if it is required
    module.el.find('input[data-fluid-quantity]').quantity();
    module.el.find('select[data-fluid-quantity]').quantity();

    // Options
    var optionsElements = module.el.find('select.productOptionSelectValue, input.productOptionCheckboxValue, input.productOptionBooleanValue, input.productOptionTextValue');
    optionsElements.change(this.onChangeOption.bind(this));

    // Epoints
    //  - Button click
    module.el.find('.basketRecalculateEPoints').click(this.recalculateEpoints.bind(this));

    // Prevent submit form on ENTER key
    module.el.find('input[type="text"]').keypress(function(event) {
      /* Act on the event */
      if (event.keyCode == 13)
        return false;
    });

    Fluid.initializeCountdowns();
    Fluid.basketExpiration.checkNewExpirationDate();
   
    // Callback
    this.trigger('initializeBasketCallback');
  },

  initializeMiniBasket: function(module){
    var key = 'miniBasket';
    module = module || this.dataModules[key];

    if (!module.active) {
      Fluid.miniBasket.oneStepCheckoutCallback = function(){
        // Call to refresh
        this.moduleCalls('refreshModule');
      }.bind(this);
      module.active = true;

      return;
    }

    if (Fluid.hasOwnProperty(key)){
      if (Fluid.miniBasket.exists()) {
        // Refresh minibasket
        Fluid.miniBasket.reload(function(){
          this.moduleCallDone('refreshModule', key, function(){
            this.trigger('onLoad');
          }.bind(this));
        }.bind(this));
      }
      else {
        this.moduleCallDone('refreshModule', key, function(){
          this.trigger('onLoad');
        }.bind(this));
      }
    }
  },

  /**
   * Initialize userForm
   * @memberOf Fluid.OneStepCheckout
   * @param  {Object} module
   */
  initializeUserForm : function(module) {

    // Initialize Data events
    module.el.find('[data-fluid-event]').dataEvent();

    // Add trigger to surrogate function, or "call" before/after
    this.trigger('initializeUserFormBefore');

    // Call Fluid.UserForm
    var userFormElement = module.el.find('.userForm ')[0];
    this.userForm = new Fluid.UserForm(userFormElement);

    var $signInCheckbox = module.el.find('[name="signIn"]');

    // Check email input
    this.inputEmail = this.userForm.el.$form.find('#userEmailField')[0];

    // Turn off data-validation on email
    this.restoreUserFormValidation();

    // Own email validation
    this.userForm.el.$form.find('#userEmailField').on('keyup change', function(event){
      // Get element
      var inputEmail = event.target;

      // Set value if it changes
      if (this.emailInputValue == inputEmail.value)
        return;

      // Clear email time out. (It prevents multiple calls to server)
      if (this.emailInputTimeout)
        clearTimeout(this.emailInputTimeout);

      // Add loading
      $(inputEmail.parentNode).addClass('fieldLoading');

      // Get value
      this.emailInputValue = inputEmail.value;

      // Validate email - Exit if is invalid.
      if (!this.isValid('email', inputEmail.value)) {
        $(inputEmail.parentNode)
          .removeClass('has-success')
          .addClass('has-error')
          .find('span.form-error').remove().end()
          .append('<span class="help-block form-error">'+languageSheet['badEmail']+'</span>');
        return;
      }

      // Clean error
      $(inputEmail.parentNode)
        .removeClass('has-error')
        .addClass('has-success')
        .find('span.form-error').remove();

      // Fill dataForm
      this.fillDataForm(this.dataModules.userForm);

      // Timeout Email input
      this.emailInputTimeout = setTimeout(function(){
        this.recalculateBasket(this.dataModules.userForm, true, function(response){
          // Clean loading
          $(inputEmail.parentNode).removeClass('fluidLoading');
        }.bind(this));
      }.bind(this), this.emailInputDelay);
    }.bind(this)); 

    // Recalculate basket on select Postal Code
    this.userForm.selectPostalCodeCallback('userInfo', function(){
      this.recalculateBasket(module, true, this.restoreUserFormValidation.bind(this));
    }.bind(this));

    this.userForm.selectPostalCodeCallback('shippingAddress', function(){
      this.recalculateBasket(module, true, this.restoreUserFormValidation.bind(this));
    }.bind(this));

    // Use shipping adress call on change
    this.el.$form.find('#useShippingAddress').on('change', function(){
      this.recalculateBasket(module, true, this.restoreUserFormValidation.bind(this));
    }.bind(this));

    if(htmlFramework == "bootstrap"){
      this.userForm.el.$form.find('#userBirthDateFieldContainer').on('dp.change', function(event){
        if (event.target.outerHTML.indexOf("required") >= 0){
          event.target.name = 'birthDay';
          if( this.validateFilledUserForm(function(){},event) == true ){
            this.recalculateBasket(module, true, this.restoreUserFormValidation.bind(this));
          }
        }
      }.bind(this));      
    }

    // Create Account check control
    if(!module.createAccount && $signInCheckbox[0].checked)
      $signInCheckbox.click();

    // Sign in checkbox event
    $signInCheckbox.click(function(event){
      module.createAccount = event.target.checked;

      // Call recalculate basket if email input is filled and valid
      if (this.inputEmail.value.length && this.isValid('email', this.inputEmail.value))
        this.recalculateBasket(module, true);
    }.bind(this));

    // Login box call
    this.el.$form.find('[data-fluid-checkout-login]').each(function(index, el) {
      var $el = $(el);

      $el.box({
        type: 'url',
        source : $el.data('fluidCheckoutLogin'),
        params: $el.data('fluidCheckoutLoginParams'),
        showFooter: false,
        callback : 'oneStepCheckoutLogin',
        uid: 'oneStepCheckoutLogin'
      });
    }.bind(this));

    // On every change in input form it is necessary control userForm is filled
    this.el.$form.on('change', this.validateFilledUserForm.bind(this, function(){
      this.recalculateBasket(module, true);
    }.bind(this)));

    // AddressBook callbacks
    // Shipping address Book
    if (this.userForm.el.useShippingAddressBook)
      this.userForm.el.useShippingAddressBook.addEventListener('change', function() {
        this.recalculateBasket(module, true, this.restoreUserFormValidation.bind(this));
      }.bind(this));

    module.el.find('input:radio[name="shippingAddress"],input:radio[name="billingAddress"]').on('change', function() {
      this.recalculateBasket(module, true, this.restoreUserFormValidation.bind(this));
    }.bind(this));

    // Call 
    Fluid.userAddressBookForm.addMethod('callbackBefore', function(result){
      this.userForm.el.$form.find('.blockAddressBook').addClass('loading');
    }.bind(this));

    Fluid.userAddressBookForm.addMethod('callback', function(result){
      if (result.response && result.response.SUCCESS) {
        // Start radio button listener 
        this.userForm.el.$form.find('div.addressBook > input:radio[value="' + result.response.SAVEDID + '"]').on('change', function() {
          this.recalculateBasket(module, true, this.restoreUserFormValidation.bind(this));
        }.bind(this));

        // Recalculate basket AFTER inserting the new address
        this.recalculateBasket(module, true, this.restoreUserFormValidation.bind(this));
      }
    }.bind(this));

    // Callback
    this.trigger('initializeUserFormCallback');
  },

  /**
   * Initialize shippings
   * @memberOf Fluid.OneStepCheckout
   * @param  {Object} module
   */
  initializeShippings : function(module) {
    // Trigger
    this.trigger('initializeShippingsBefore');

    // Disable warehouses, we enable if it is necessary
    var warehouseElements = module.el.find('input.basketSelectorPickUp');
      warehouseElements.each(function(index, el) {
        $(el).on('click', this.setWarehouse.bind(this));
        el.disabled = true;
    }.bind(this));

    //Shipping
    this.el.shippingSection = module.el.find('input.shippingTypeSelector:radio');
    this.el.shippingSection.each(function(index, el) {
      el.addEventListener('click', this.setShippingSection.bind(this, el));
      
      if (el.checked && $(el).data('pickup') == 1){
        var warehouseElements = module.el.find('input[name="pickUpWarehouse_'+el.value+'"]');
        warehouseElements.each(function(index, el) {
          el.disabled = false;
          $(el).on('click');
        }.bind(this));
      }
    }.bind(this));

    // Trigger
    this.trigger('initializeShippingsCallback');
  },

  /**
   * Initialize Payments
   * @memberOf Fluid.OneStepCheckout
   * @param  {Object} module
   */
  initializePayments : function(module) {
    // Call trigger
    this.trigger('initializePaymentsBefore');

    //Plugin Listener
    Fluid.resources.pluginListener('initializePaymentsBefore', this.el.$form, true);
    
    module.el.find('[data-fluid-event]').dataEvent();
    this.el.paymentSystemSelectors = module.el.find('input.paymentSystemSelector:radio');
    this.el.paymentSystemSelectors.each(function(index, el) {
      el.addEventListener('click', this.setPaymentSystem.bind(this));
    }.bind(this));
    if (typeof pgSDK != "undefined") {
      try {
        pgSDK.simulator.reloadAll();
      } catch (err) {}
    }

    // Call trigger
    this.trigger('initializePaymentsCallback');

    //Plugin Listener
    Fluid.resources.pluginListener('initializePaymentsCallback', this.el.$form, true);
  },

  /**
   * Initialize discounts
   * @memberOf Fluid.OneStepCheckout
   * @param  {Object} module
   * @return {void}
   */
  initializeDiscounts : function(module) {
    // Call trigger
    this.trigger('initializeDiscountsBefore');

    // Get input element
    this.el.$discountCode = module.el.find('input#discountCodeField');

    // Prevent auto submit on Enter key and call addDiscount
    this.el.$discountCode.keypress(function(event){
      if (event.keyCode === 13) {
        event.preventDefault();
        this.addDiscount();
      }
    }.bind(this));
    //Binding click event on each trash icon once a giftCode has been added.
    $('span.deleteBalanceCode').each(function(index,el){
      $(el).on('click',this.deleteDiscountCode.bind(this, el.value, el));
    }.bind(this));
    // Set discount action
    this.el.$form.find('input#discountCodeButton').click(this.addDiscount.bind(this));
    //Remove title of removeDiscountsSection if no elements. 
    var numElementos = $('.ticketCodesGroup .outputDiscountName').length;
    if(numElementos == 0){
      $('.ticketCodesTitle').remove();
    }

    // Call trigger
    this.trigger('initializeDiscountsCallback');

  },

  initializeDiscountPrediction : function(module) {
    module.el.find('[data-fluid-event]').dataEvent();

    module.el.find('[data-fluid-form="buyForm"]').each(function(index,form){
      if(!form.initialized)
        new Fluid.BuyForm(form);
    });
  },

  /**
   * Initialize Legal check
   * @memberOf Fluid.OneStepCheckout
   * @param  {Object} module
   * @return {void}
   */
  initializeLegalCheck : function(module) {
    // If module does not exist, get it from dataModules
    if (!module)
      module = this.dataModules.legalCheck;
    
    // Pass when module is not active
    if (!module.active) return;

    // Call trigger
    this.trigger('initializeLegalCheckBefore');

    // Find checkbox
    if (!module.elCheckbox)
      module.elCheckbox = module.el.find('input[name="agreement"]');

    // This field is always required
    module.elCheckbox[0].setAttribute('data-validation', 'required');

    // Event when it changes
    // This call enables/disables submitButton if it can
    module.elCheckbox.on('click', function(event){
      // Submit
      if (!this.submitButton)
        this.submitButton = this.dataModules.buttons.el.find('button#basketEndOrder');

      var endOrder = event.target.checked && (this.endOrder || this.submitButton.data('endorder'));

      // Enable or disable submit
      this.submitButton[0].disabled = !endOrder;
      
    }.bind(this));

    // Call trigger
    this.trigger('initializeLegalCheckCallback');
  },

  //AmountFreeShipping  module
  initializeAmountFreeShipping : function(module) {
    // If module does not exist, get it from dataModules
      // Call trigger
    this.trigger('initializeAmountFreeShippingBefore');

    // Call trigger
    this.trigger('initializeAmountFreeShippingCallback');
  },
  // Additional content functions
  /**
   * Initialize SelectableGifts content
   * @memberOf Fluid.OneStepCheckout
   * @param  {Object} content
   * @return {void}
   */
  initializeSelectableGifts : function(content) {
    // Call trigger
    this.trigger('initializeSelectableGiftsBefore');

    if (content.needToRefresh) {
      content.el.find('form').each(function(index, form) {
        var dataFluidForm = $(this).data('fluidForm');
        switch(dataFluidForm){
          case 'buyGiftForm': new Fluid.BuyGiftForm(form); break;
        }
      });
    }
    else {
      // Rewrite callback
      Fluid.BuyGiftForm.prototype.callback = function(result){
        if (result.statusCode == 200 && result.response.ADDED == 0)
          this.moduleCalls('refreshModule');
      }.bind(this);
    }
    content.needToRefresh = true;

    // Call trigger
    this.trigger('initializeSelectableGiftsCallback');
  },

  /**
   * Initialize SpecialProducts content
   * @memberOf Fluid.OneStepCheckout
   * @param  {Object} content
   * @return {void}
   */
  initializeSpecialProducts : function(content) {
    // Call trigger
    this.trigger('initializeSpecialBefore');

    if (content.needToRefresh)
      content.el.find('form').each(function(index, form) {
        var dataFluidForm = $(this).data('fluidForm');
        switch(dataFluidForm){
          case 'buyForm': new Fluid.BuyForm(form); break;
        }
      });
    content.needToRefresh = true;

    // Call trigger
    this.trigger('initializeSpecialCallback');
  },

  /**
   * Initialize VinculatedProducts content
   * @memberOf Fluid.OneStepCheckout
   * @param  {Object} content
   * @return {void}
   */
  initializeVinculatedProducts : function(content) {
    // Call trigger
    this.trigger('initializeVinculatedBefore');

    if (content.needToRefresh)
      content.el.find('form').each(function(index, form) {
        var dataFluidForm = $(this).data('fluidForm');
        switch(dataFluidForm){
          case 'buyForm': new Fluid.BuyForm(form); break;
        }
      });
    content.needToRefresh = true;

    // Call trigger
    this.trigger('initializeVinculatedCallback');
  },

  // Object methods
  // ---------------------------------------------------------------------------
  
  /**
   * Call functions for each active and autoRefresh module
   * @memberOf Fluid.OneStepCheckout
   * @param  {Function} callback Internal function from THIS
   * @params {[any]}    Array of arguments
   */
  moduleCalls : function(callback) {
    // Get function
    var functionCallback = this[callback];

    // Check function 
    if (!$.isFunction(functionCallback))
      return;

    // Arguments
    var args = Array.prototype.slice.call(arguments, 1);

    // Loop modules
    for (var key in this.dataModules){
      var module = this.dataModules[key];

      // Discriminate inactive, forbidden callbacks and more (U__U!)
      if (module.active && (
          callback == 'loadingIndicator' && module.autoRefresh ||
          callback == 'refreshModule' && module.autoRefresh ||
          callback == 'lockModule')
        )
      {
        // Array key and module
        var moduleArr = [key, module];

        this.moduleCallStart(callback, key);

        // Call function
        functionCallback.apply(this, moduleArr.concat(args));
      }
    }

    // Additional content
    for (var key in this.additionalContent){
      var content = this.additionalContent[key];

      // Discriminate inactive, forbidden callbacks and more (U__U!)
      if (content.active && (
          callback == 'loadingIndicator' && content.autoRefresh ||
          callback == 'refreshModule' && content.autoRefresh ||
          callback == 'lockModule')
        )
      {
        this.moduleCallStart(callback, key);

        // Call function
        functionCallback.apply(this, [key, content].concat(args));
      }
    }
  },

  moduleCallStart : function(type, name) {
    if (!this.moduleCallsStatus[type])
      this.moduleCallsStatus[type] = {};

    this.moduleCallsStatus[type][name] = true;
    return true;
  },

  moduleCallDone : function(type, name, lastCallback) {
    if (!this.moduleCallsStatus[type])
      return false;

    if (this.moduleCallsStatus[type].hasOwnProperty(name) && this.moduleCallsStatus[type][name])
      delete this.moduleCallsStatus[type][name];

    if (lastCallback && typeof lastCallback === 'function') {
      for (var key in this.moduleCallsStatus[type])
        if (this.moduleCallsStatus[type][key])
          return false;
      
      lastCallback();
    }
    return true;
  },

  /**
   * Define module is loading or not
   * @memberOf Fluid.OneStepCheckout
   * @param  {string} key    Module name
   * @param  {Object} module Module object
   * @param  {Boolean} show  Shows or hides loading
   */
  loadingIndicator : function(key, module, show){
    // Ensure module exists
    if (!module || typeof(module) !== 'object') module = this.dataModules[key];

    // Check module is active
    if (!module.active || !module.hasOwnProperty('el')) return;

    if (show)
      module.el.addClass('loading');
    else
      module.el.removeClass('loading');
  },  

  /**
   * Define if  module is blocked or not
   * @memberOf Fluid.OneStepCheckout
   * @param  {string} key    Module name
   * @param  {Object} module Module object
   * @param  {Boolean} show  Shows or hides loading
   */
  lockModule : function(key, module, blocked, forceChange){
    // Ensure module exists
    if (!module || typeof(module) !== 'object') module = this.dataModules[key];

    // Check module is active
    if (!module.active) return;

    if (blocked)
      module.el.addClass('blocked');
    else
      module.el.removeClass('blocked');
  },

  /**
   * Tracking movements on One Step Checkout
   * @memberOf Fluid.OneStepCheckout
   * @param {string} moduleName Name of actions
   */
  setTracking : function(moduleName){
    this.tracking.push(moduleName);
    this.trigger('tracking', moduleName, this.tracking);
  },

  // Interaction methods
  // ---------------------------------------------------------------------------

  /**
   * Change options
   * @memberOf Fluid.OneStepCheckout
   * @param  {object} event 
   */
  onChangeOption : function(event) {
    //Set Tracking
    this.setTracking('changeOption');

    if (!this.trigger('onChangeOption')) {
      this.trigger('onChangeOptionBefore');
      this.recalculateBasket(this.dataModules.basket);
      this.trigger('onChangeOptionCallback', event.target);
    }
  },

  /**
   * Delete product
   * @memberOf Fluid.OneStepCheckout
   * @param  {object} event 
   */
  deleteProduct : function(event) {
    var position = $(event.currentTarget).data('fluidBasketdeleteproduct');

    //Show loading
    this.moduleCalls('loadingIndicator', true);

    //Set Tracking
    this.setTracking('deleteProduct');

    // Fill data in order to send dataForm to POST. This case is not the best
    // way and it is implemented to Ecoceutics multiple comments.
    this.fillDataForm('basket');    

    //Post
    this.request('/checkout/oneStepCheckout/', 'POST', {deleteProduct: position, dataForm: this.dataForm}, function(data){

      // Check status
      if (data.statusCode != 200){
        //Hide loading manually
        this.moduleCalls('loadingIndicator', false);
        this.notify(languageSheet.ONESTEPCHECKOUTPRODUCTDELETEDERROR, 'error');
        return false;
      }

      if (data.response && data.response.DELETED){
        // Control totalItems in basket.
        // If we have not any items, reload page
        if (data.response.hasOwnProperty('TOTALITEMS') && data.response.TOTALITEMS == 0){
          window.location = '/checkout/oneStepCheckout';
          return;
        }

        // Call notify
        this.notify(languageSheet.ONESTEPCHECKOUTPRODUCTDELETED, 'success');

        // Refresh modules
        this.moduleCalls('refreshModule');
      }
      else {
        //Hide loading manually
        this.moduleCalls('loadingIndicator', false);
        this.notify(languageSheet.ONESTEPCHECKOUTPRODUCTDELETEDERROR, 'error');
      }
    }.bind(this));
  },

  /**
   * Delete discount (GIFT)
   * @memberOf Fluid.OneStepCheckout
   * @param  {object} event 
   */
  deleteDiscount : function(event) {
    // Prevent default
    event.preventDefault();

    //Set Tracking
    this.setTracking('deleteDiscount');

    // get Item
    var discountData = $(event.currentTarget).data('fluidBasketdeletediscount');

    // Is gift
    if (discountData.hasOwnProperty('giftId')) {
      discountData.deleteGift = 1;
    }

    //Show loading
    this.moduleCalls('loadingIndicator', true);

    //Post
    this.request('/checkout/oneStepCheckout/', 'POST', discountData, function(data){

      // Check status
      if (data.statusCode != 200){
        //Hide loading manually
        this.moduleCalls('loadingIndicator', false);
        this.notify(languageSheet.ONESTEPCHECKOUTPRODUCTDELETEDERROR, 'error')
        return false;
      }

      if (data.response && data.response.DELETED){
        // Call notify
        this.notify(languageSheet.ONESTEPCHECKOUTPRODUCTDELETED, 'success');

        // Refresh modules
        this.moduleCalls('refreshModule');
      }
      else {
        //Hide loading manually
        this.moduleCalls('loadingIndicator', false);
        this.notify(languageSheet.ONESTEPCHECKOUTPRODUCTDELETEDERROR, 'error');
      }
    }.bind(this));
  },
  /**
   * Set payment system
   * @memberOf Fluid.OneStepCheckout
   */
  setPaymentSystem : function(ev) {

    //Set Tracking
    this.setTracking('setPaymentSystem');

    //Plugin Listener
    Fluid.resources.pluginListener('setPaymentSystem', ev, {id:ev.target.value}, true);

    //Calls recalculate
    this.recalculateBasket(this.dataModules.payments);

    if(window.TEA)
      window.TEA.send({type:'setPayment', targetType:'setPayment', targetId:ev.originalTarget.value});
  },

  /**
   * Set shipping section
   * @memberOf Fluid.OneStepCheckout
   * @param {Object} el Dom element 
   */
  setShippingSection : function(el) {
    this.el.$form.find('.basketSelectorPickUp').removeClass('basketSelectorPickUpVisible');
    var $el = $(el);
    //Prepare warehouses
    if (settings.pickup) {
      if ($el.data('pickup') == 1){

        var selectionType = $el.data('selectiontype');
        if(selectionType === "modal" ){
          // Modal selection type
          if($el.data('boxuid'))
            $el.box('openBox');
          else {
            $el.box({
              uid: 'modalSelectWarehouse',
              triggerOnClick: false,
              showFooter: false,
              source: '/checkout/selectWarehouse/' + $el.val(),
              type: 'url',
              callback : 'warehouses'
            });
            $('#modalSelectWarehouse').off('hidden.bs.modal');
            $('#modalSelectWarehouse').on('hidden.bs.modal', function () {
              this.recalculateBasket(this.dataModules.shippings);
              if ($(".warehouseSelected").length) {
                $("#spanWarehouseNotSelected").remove();
                $("#basketEndOrder").removeAttr("disabled");
              } 
              else if (!($("#spanWarehouseNotSelected").length))
                  $(".basketSelector.shippingSelector[data-shipper='2']")
                    .append("<span id='spanWarehouseNotSelected'>" + languageSheet.SELECTWAREHOUSES + "</span>")
            }.bind(this));
          }
        }
        else {
          // Basic selection type
          var warehouseElements = $('input[name="pickUpWarehouse_'+el.value+'"]');
          $el.parent().find('.basketSelectorPickUp').addClass('basketSelectorPickUpVisible');
          warehouseElements.each(function(index, item) {
            item.disabled = false;
            $(item).on('click');
          }.bind(this));
        }

        return true;
      }
      else { 
        var warehouseElements = $('input.basketSelectorPickUp');
        warehouseElements.each(function(index, item) {
          item.disabled = true;
          item.checked = false;
          $(item).on('off');
        }.bind(this));

        // Search input[name="warehouse"]
        var $inputWarehouse = this.el.$form.find('input[name="warehouse"]');
        if ($inputWarehouse.length)
          $inputWarehouse.val(-1);
        else 
          $('<input />',{type:'hidden',name:'warehouse',value:-1}).appendTo(this.el.$form);
      }
    }

    //Set Tracking
    this.setTracking('setShippingSection');

    //Plugin Listener
    Fluid.resources.pluginListener('setShippingSection', el, {id:el.value}, true);

    //Recalculate
    this.recalculateBasket(this.dataModules.shippings);

    if(window.TEA)
      window.TEA.send({type:'setShipping', targetType:'setShipping', targetId:el.value});
  },

  /**
   * Set warehouse
   * @memberOf Fluid.OneStepCheckout
   */
  setWarehouse : function(event) {

    //Set Tracking
    this.setTracking('setWarehouse');

    //Calls recalculate
    this.recalculateBasket(this.dataModules.shippings);
  },

  /**
   * Add discount
   * @memberOf Fluid.OneStepCheckout
   */
  addDiscount : function() {

    // If discountCode element does not exist, ends method.
    if (!this.el.$discountCode)
      return;

    var code = this.el.$discountCode.val();

    if (code.length > 0) {

      //Show loading
      this.moduleCalls('loadingIndicator', true);

      //Set Tracking
      this.setTracking('addDiscount');

      //Prepare the values to be sent to the controller. The code is sent always 
      //but maybe the other params doesn't exist. We can also do jsonToSend.code = escape(code);
      var jsonToSend ={"code":escape(code)};

      //Check if the activateAffiliate param is defined and has value
      var $activateAffiliate = $('#activateAffiliate');
    
      if (typeof $activateAffiliate != 'undefined'){
        jsonToSend.activateAffiliate = $activateAffiliate.val();
      }
    
      //Check if the overWritteCurrentAffiliate param is defined and has value
      var $overwriteCurrentAffiliate = $('#overwriteCurrentAffiliate');
      if (typeof $overwriteCurrentAffiliate != 'undefined'){
        jsonToSend.overwriteCurrentAffiliate = $overwriteCurrentAffiliate.val();
      }
      // Post
      $.post('/basket/addDiscountCode/', JSON.stringify(jsonToSend), function (data) {

        // Check status
        if (data.statusCode != 200){
          //Hide loading manually
          this.moduleCalls('loadingIndicator', false);
          return false; // TODO: Show error to user
        }

        // added one new correct number (1). 
        // 0 means that the code is accepted; 
        // 1 means that the code is accepted but under some conditions
        if  ( (data.response.CODE != 0) && (data.response.CODE != 1) && (data.response.CODE != 5)) {
          //Hide loading manually
          this.moduleCalls('loadingIndicator', false);
          this.notify(data.response.MESSAGE, 'danger');
        }
        else {
          this.moduleCalls('loadingIndicator', false);

          // Clean input text
          this.el.$discountCode.val("");

          // Refresh checkout
          this.moduleCalls('refreshModule');

          if (data.response.CODE == 0){
            this.showMessage(languageSheet.ONESTEPCHECKOUTDISCOUNTADDED, 'success');
          }
          else if (data.response.CODE == 5){ //Affiliate Success Code
            this.showMessage(languageSheet.CANAPPLYAFFILIATECODE, 'success');
          }
          else{
            this.showMessage(languageSheet.ONESTEPCHECKOUTDISCOUNTADDEDUNDERCONDITIONS, 'success');
          }
        }
      }.bind(this), 'json'); 
    }
  },

  /** 
   * Delete Discount Code
   * @param  {Integer} id
   * @param  {DomObject} el
   * @return {void}
   * @memberOf Fluid.OneStepCheckout
   */
  deleteDiscountCode: function(id,el){
    // Capturamos todo el elemento fluidData (es DOM HTML)
    var data = $(el).data('fluidData');
    data = {
      code:escape(data.discountId),
      discountType:escape(data.discountType)
    };

    $.post('/basket/removeDiscountCodes/', JSON.stringify(data), function(result){
      //NOTA: Ara mateix arribem aqui enviant les dades bé a la funció dita. 
      if (result.deletedId != 0) {
        // Refresh checkout
        this.moduleCalls('refreshModule');
      }
     }.bind(this), 'json'); 
  },

  // Connection methods
  // ---------------------------------------------------------------------------

  /**
   * Refresh Module. 
   * Call initialize functions and loadingModule[false] when ends call
   * @memberOf Fluid.OneStepCheckout
   * @param  {string} key    Module name
   * @param  {Object} module Module object
   * @param {Boolean} force Reload module event without autorefresh
   */
  refreshModule : function(key, module, force) {
 
    // Ensure module exists
    if (!module || typeof(module) !== 'object') module = this.dataModules[key];

    // Show loading
    this.loadingIndicator(key, module, true);

    // Get url
    var url = '/checkout/oneStepCheckout/' + (module.template? 'snippet/' + module.template : key);

    // Call load
    if (module.hasOwnProperty('el')) {
      module.el.load(url, module.params, function(data) {

        // Hide loading
        this.loadingIndicator(key, module, false);

        // Initialize form (each module)
        if (module.initializeMethod && $.isFunction(this[module.initializeMethod]))
          this[module.initializeMethod](module);

        // Clean module calls and trigger function when it removes the last
        this.moduleCallDone('refreshModule', key, function(){
          this.trigger('onLoad');
        }.bind(this));

      }.bind(this));
    }
    else if (module.initializeMethod && $.isFunction(this[module.initializeMethod])) {
      this[module.initializeMethod](module);
    }
  },

  /**
   * Recalculate basket
   * @memberOf Fluid.OneStepCheckout
   */
  recalculateBasket : function(module, preventUserRefresh, callback){

    // Prevent invalid or undefined functions
    preventUserRefresh = preventUserRefresh || false;
    callback = callback || function(){};
    if (typeof preventUserRefresh === 'function'){
      callback = preventUserRefresh;
      preventUserRefresh = false;
    }

    // Surrogate function trigger
    if (this.trigger('recalculateBasket')) {
      return;
    }

    // Before trigger
    this.trigger('recalculateBasketBefore');

    // Show loading
    this.moduleCalls('loadingIndicator', true);

    // Avoid mutiple submit
    this.el.$form.find('button[type=submit]').attr('disabled',true);

    // Fill dataForm
    this.fillDataForm(module);

    // Avoid recaluclate user when is a userForm who triggers the method
    this.dataForm.recalculateUser = !preventUserRefresh;
    
    // Post
    this.request('/checkout/oneStepCheckout/', 'POST', this.dataForm, function(result){
      var response = result.response? result.response : result;

      // Control user for verify it
      if(module && module.initializeMethod == 'initializeUserForm'){
        
        //Internal callback
        if (callback && typeof callback === 'function')
          callback(response);

        // On error - Call notify TODO (??)
        if (!response.STATUS) {}

        if (response.USER){
          //this.initializeLegalCheck();

          if (!response.USER.SUCCESS){
            this.moduleCalls('loadingIndicator', false);

            // Message "no selector or email check"
            if(!preventUserRefresh){
              var message = response.USER.MESSAGE? response.USER.MESSAGE : '__USER NOT VERIFIED__';
              this.notify(message, 'danger');
            }
            return false;
          }
        }
      }

      // Refresh modules
      this.moduleCalls('refreshModule');

    }.bind(this));

    // Callback trigger
    this.trigger('recalculateBasketCallback');
  },

  /**
   * Clear basket
   * @memberOf Fluid.OneStepCheckout
   */
  clearBasket : function() {

    //Show loading
    this.moduleCalls('loadingIndicator', true);

    //Set Tracking
    this.setTracking('clearBasket');

    //Post
    $.post('/checkout/oneStepCheckout/', JSON.stringify({clear: true}), function(data){
      if (data.response && data.response.REDIRECT)
        window.location = data.response.REDIRECT;
    }, "json");
  },

  /**
   * Recalculate epoints
   * @memberOf Fluid.OneStepCheckout
   * @param  {Object} event Click event
   * @return {void}
   */
  recalculateEpoints : function(event) {
    event.preventDefault();

    //Set Tracking
    this.setTracking('recalculateEpoints');

    this.recalculateBasket(this.dataModules.basket);
    return true;
  },
  
  /**
   * Reload captcha pseudo-event
   * @memberOf Fluid.OneStepCheckout
   */
  reloadCaptchaClick : function() {
    var module = this.dataModules.userForm;
    if (module.active)
      module.el.find('img.reloadCaptchaImage').click();
  },

  /**
   * Submit one step checkout form
   * @memberOf Fluid.OneStepCheckout
   * @return {void}
   */
  submit : function(ev) {
    //Validate form
    if (!this.el.$form.isValid(document.documentElement.lang || "en", Fluid.validateFormConf)) return false;

    // trick to avoid Firefox and safari "back-button cache"
    window.onbeforeunload = (function() {});
    // disallow submit form to avoid multi-submit
    this.submitButton[0].disabled = true;

    //Plugin Listener
    Fluid.resources.pluginListener('beforeSubmitEndOrder', ev, this.el.$form, true);

    // Trigger
    this.trigger('beforeSubmit');

    // Tracking
    this.setTracking('endOrder');

    // Add hidden inputs
    $('<input />',{type:'hidden', name:'ACTION10',value:1}).appendTo(this.el.$form);
    $('<input />',{type:'hidden', name:'oneStepCheckout',value:1}).appendTo(this.el.$form);

    // Submit form
    if(!this.el.$form.preventSubmit)
      this.el.form.submit();

    return;
  },

  /**
   * Fills dataForm Object with form fields values in this.dataForm
   * @memberOf Fluid.OneStepCheckout
   * @param  {Object} module Use it to discrimine userForm Module
   * @return {Object}        Returns dataForm.
   */
  fillDataForm: function(module) {
    // Clean dataForm
    this.dataForm = {};

    //Get form data
    var arrDataForm = this.el.$form.find(':not(.userForm *)').serializeArray();
    var arrDataUserForm = this.el.$form.find(':not(:not(.userForm *))').serializeArray();
    var arrAddress = ['state','city','zip','shippingstate','shippingcity','shippingzip'];
    var noFillFields = ['captchaCode','captchaPosition'];

    // Fill with fields
    for (var i = 0; i < arrDataForm.length; i++) {
      if (this.dataForm[arrDataForm[i].name] && !isNaN(this.dataForm[arrDataForm[i].name]) && !isNaN(arrDataForm[i].value)) {
        this.dataForm[arrDataForm[i].name] = parseInt(this.dataForm[arrDataForm[i].name]) + parseInt(arrDataForm[i].value);
      }
      else {
        this.dataForm[arrDataForm[i].name] = arrDataForm[i].value;
      }
    }

    var userDataForm = {};

    if(module && module.initializeMethod == 'initializeUserForm'){
      for (var i = 0; i < arrDataUserForm.length; i++) {
        if(noFillFields.indexOf(arrDataUserForm[i].name) >= 0)
          continue;
        if (arrDataUserForm[i].value.length || arrAddress.indexOf(arrDataUserForm[i].name.toLowerCase()) > -1)
          userDataForm[arrDataUserForm[i].name] = arrDataUserForm[i].value;
      }
    }

    this.dataForm.userForm = userDataForm;

    return this.dataForm;
  },

  /**
   * Call to server
   * @memberOf Fluid.OneStepCheckout
   * @param  {string}    url      Route to call
   * @param  {string}    method   GET or POST
   * @param  {Object}    data     Data to send
   * @param  {Boolean}   async    Set call type (default: true)
   * @param  {Function}  callback Function to call when finishes
   * @return {any}
   */
  request: function(url, method, data, async, callback) {
    if (typeof async == 'function'){
      callback = async;
      async = true;
    }

    $.ajax({
      url: url,
      type: method,
      async: async,
      contentType : 'application/json',
      dataType: 'json',
      data: JSON.stringify(data),
    })
    .done(function(result, status, xhr) {
      if (result.hasOwnProperty('response'))
        this.responseActions(result.response);
    }.bind(this))
    .fail(function() {
      // Error. TODO: notify!
    })
    .always(callback.bind(this));
  },

  /**
   * Do action with error code recieved
   * @memberOf Fluid.OneStepCheckout
   * @param  {Object} response Response object from ajax call
   * @return {void}
   */
  responseActions: function(response){
    this.validateAddressBook();

    // Set this.submitButton enabled/disabled
    if (response.hasOwnProperty('ENDORDER'))
      this.endOrder = response.ENDORDER;

    if (response.STATUS != 0) return;

    // Registered email
    if (response.CODE == 'TLG1003' && this.hasOwnProperty('inputEmail')) {
      // Set error on parent
      var $spanError = $('<span />', {
        'class': 'help-block form-error',
        text: response.MESSAGE
      });

      $(this.inputEmail.parentNode)
        .removeClass('has-success')
        .addClass('has-error')
        .find('span.form-error').remove().end()
        .append($spanError);

      // - Link to open modal
      var $loginLink = this.dataModules.userForm.el.find('[data-fluid-checkout-login]').first();
      if ($loginLink.length){
        $('<a />', {
          'class': 'emailErrorLoginCall',
          html : languageSheet.ONESTEPCHECKOUTLOGIN,
          click: function(){
            this.loginEmailValue = this.emailInputValue || "";
            $loginLink.trigger('click');
          }.bind(this)
        }).appendTo($spanError);
      }
    }

    if (response.CODE == 'TLG1004' && this.hasOwnProperty('inputEmail')) {
      new Fluid.VinculateSocialAccountEmailPopupForm();
    }
    else if (response.CODE == 'LF8') { // Captcha
      this.reloadCaptchaClick();
    }
  },

  validateAddressBook : function(){
    this.userForm.el.$form.find('input[name="billingAddress"]').parent('div.billingAddress').removeClass('has-error');
    this.userForm.el.$form.find('input[name="shippingAddress"]').parent('div.shippingAddress').removeClass('has-error');
    this.userForm.el.$form.find('#useShippingAddressBook').prevAll().removeClass('has-error');

    if(this.userErrorCode != null){
      if (this.userErrorCode.val() == "TLG0100007")
        this.userForm.el.$form.find('input[name="billingAddress"]:checked').parent('div.billingAddress').addClass('has-error');
      else if (this.userErrorCode.val() == "TLG0100008")
        this.userForm.el.$form.find('input[name="shippingAddress"]:checked').parent('div.shippingAddress').addClass('has-error');
      else if (this.userErrorCode.val() == "No_shipTo") {
        var item = (typeof this.userForm.el.$form.find('#useShippingAddressBook')[0] !== 'undefined') ? this.userForm.el.$form.find('#useShippingAddressBook')[0] : this.userForm.el.$form.find('#useShippingAddress')[0];
        if (item.checked) {  
          this.userForm.el.$form.find(item).prevAll().addClass('has-error');
          this.notify(languageSheet.NOTAVAILABLEADDRESS, 'danger', true);
        }
      }
    }
  },

  // Utils
  /**
   * Restore user data-validation.
   * It is necessary because localize.js or others forces validation init
   * @return {Void}
   */
  restoreUserFormValidation : function(){
    // Get element and call off method
    this.userForm.el.$form.find('#userEmailField').off('blur');
    this.userForm.el.$form.find('.blockAddressBook').removeClass('loading');
  },

  /**
   * Validate values
   * @memberOf Fluid.OneStepCheckout
   * @param  {String}  type email,number...
   * @param  {Any}  str
   * @return {Boolean}
   */
  isValid: function(type, value) {
    if (type == 'number')
      return !isNaN(value)
    if (type == 'email')
      return $.formUtils.validators.validate_email.validatorFunction(value);
    else
      return false
  },

  /**
   * Show messages & notifications
   * @memberOf Fluid.OneStepCheckout
   * @param  {String} message    Message to show
   * @param  {String} type       Type of notify: danger,warning,info,success
   * @param  {Bolean} notifyMode If it is passed force manually notify mode
   * @return {Void}
   */
  notify: function(message, type, notifyMode) {
    type = type || 'danger';

    if (typeof notifyMode !== "boolean") 
      notifyMode = this.notifyMode;

    if (notifyMode) Fluid.notify(message, {type:type});
    else this.el.$message.html(message).addClass('alert alert-'+type);
  },

  /**
   * This method check all required inputs in userForm ars filled and returns 
   * Also, when all required inputs are filled, call a function if it is passed.
   * @param  {Function} callback Call this function when inputs are filled
   * @param  {Object}   event    To get the triggerer
   * @return {Boolean}           Result
   */
  validateFilledUserForm : function(callback, event) {

    // Check arguments
    var targetName = event? event.target.name : '';
    if (typeof callback !== 'function') callback = function(){};

    // Set variables
    var i, item, inputBelongsToUserForm;

    // Get input data
    this.fillDataForm(this.dataModules.userForm);

    // Flag that determines if changed input belongs to form
    inputBelongsToUserForm = false;

    // User form
    // Loop every item in user form fields 
    for (i = 0; i < this.userForm.formFields.userFields[this.userForm.userType].length; i++) {
      item = this.userForm.formFields.userFields[this.userForm.userType][i];

      //name exceptions
      item.name = item.name == 'BirthDate' ? 'birthDay' : item.name;
      item.name = item.name == 'vatId' ? 'vat' : item.name;
      item.name = item.name == 'Captcha' ? 'captchaCode' : item.name;

      // Check unrequired items and auto trigger inputs
      if (!item.hasOwnProperty('required') || !item.hasOwnProperty('name') || !item.required || 
          //['country','state','zip','city','email'].indexOf(item.name.toLowerCase()) >= 0) {
          ['country','email'].indexOf(item.name.toLowerCase()) >= 0) {
        
        // When we change an unrequired input it is not necessary recalculate basket
        if(targetName.toLowerCase() == item.name.toLowerCase())
          return false;

        // Otherwise, jump to next iteration
        continue;
      }

      // If required input is not filled, we do not call to recalculate
        if (!this.dataForm.userForm.hasOwnProperty(item.name)){
          // Ignore state, city and zip because in some cases are not required
          if(['state','city','zip'].indexOf(item.name.toLowerCase()) == -1)
            return false;
        }
        else if (!this.dataForm.userForm[item.name].length)
          return false;

      // Does input belong to userForm?
      if (targetName.toLowerCase() == item.name.toLowerCase())
        inputBelongsToUserForm = true;
    }

    // User shipping form - Only if it is requested (via checkbox)
    // When addressBook is active, shippingFields property is undefined, we 
    // can use it to determine userForm is addressBook or not
    if (this.userForm.formFields.hasOwnProperty('shippingFields') &&
      typeof this.userForm.formFields.shippingFields !== 'undefined' &&
      this.dataForm.userForm.hasOwnProperty('useShippingAddress') && 
      this.dataForm.userForm.useShippingAddress){

      // Loop every item in user shipping form fields 
      for (i = 0; i < this.userForm.formFields.shippingFields[1].length; i++) {
        item = this.userForm.formFields.shippingFields[1][i];

        // Check unrequired items and auto trigger inputs
        if (!item.hasOwnProperty('required') || !item.hasOwnProperty('name') ||  !item.required || 
            //['shippingcountry', 'shippingcity','shippingstate','shippingzip'].indexOf(item.name.toLowerCase()) >= 0) {
            ['shippingcountry'].indexOf(item.name.toLowerCase()) >= 0) {

          // When we change an unrequired input it is not necessary recalculate basket
          if(targetName.toLowerCase() == item.name.toLowerCase())
            return false;

          // Otherwise, jump to next iteration
          continue;
        }

        // If required input is not filled, we do not call to recalculate
        if (!this.dataForm.userForm.hasOwnProperty(item.name)){
          // Ignore state, city and zip because in some cases are not required
          if(['shippingstate','shippingcity','shippingzip'].indexOf(item.name.toLowerCase()) == -1)
            return false;
        }
        else if (!this.dataForm.userForm[item.name].length)
          return false;

        // Does input belong to userForm?
        if (targetName.toLowerCase() == item.name.toLowerCase())
          inputBelongsToUserForm = true;
      }
    }

    // Exit when input changed does not belong to userForm
    if (!inputBelongsToUserForm)
      return false;

    // Callback
    if (typeof callback === 'function')
      callback();

    return true;
  }
});!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";var e,i;function c(){return e.apply(null,arguments)}function o(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function u(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function l(e){return void 0===e}function h(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function d(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function f(e,t){var n,s=[];for(n=0;n<e.length;++n)s.push(t(e[n],n));return s}function m(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function _(e,t){for(var n in t)m(t,n)&&(e[n]=t[n]);return m(t,"toString")&&(e.toString=t.toString),m(t,"valueOf")&&(e.valueOf=t.valueOf),e}function y(e,t,n,s){return Tt(e,t,n,s,!0).utc()}function g(e){return null==e._pf&&(e._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null,rfc2822:!1,weekdayMismatch:!1}),e._pf}function v(e){if(null==e._isValid){var t=g(e),n=i.call(t.parsedDateParts,function(e){return null!=e}),s=!isNaN(e._d.getTime())&&t.overflow<0&&!t.empty&&!t.invalidMonth&&!t.invalidWeekday&&!t.weekdayMismatch&&!t.nullInput&&!t.invalidFormat&&!t.userInvalidated&&(!t.meridiem||t.meridiem&&n);if(e._strict&&(s=s&&0===t.charsLeftOver&&0===t.unusedTokens.length&&void 0===t.bigHour),null!=Object.isFrozen&&Object.isFrozen(e))return s;e._isValid=s}return e._isValid}function p(e){var t=y(NaN);return null!=e?_(g(t),e):g(t).userInvalidated=!0,t}i=Array.prototype.some?Array.prototype.some:function(e){for(var t=Object(this),n=t.length>>>0,s=0;s<n;s++)if(s in t&&e.call(this,t[s],s,t))return!0;return!1};var r=c.momentProperties=[];function w(e,t){var n,s,i;if(l(t._isAMomentObject)||(e._isAMomentObject=t._isAMomentObject),l(t._i)||(e._i=t._i),l(t._f)||(e._f=t._f),l(t._l)||(e._l=t._l),l(t._strict)||(e._strict=t._strict),l(t._tzm)||(e._tzm=t._tzm),l(t._isUTC)||(e._isUTC=t._isUTC),l(t._offset)||(e._offset=t._offset),l(t._pf)||(e._pf=g(t)),l(t._locale)||(e._locale=t._locale),0<r.length)for(n=0;n<r.length;n++)l(i=t[s=r[n]])||(e[s]=i);return e}var t=!1;function M(e){w(this,e),this._d=new Date(null!=e._d?e._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===t&&(t=!0,c.updateOffset(this),t=!1)}function k(e){return e instanceof M||null!=e&&null!=e._isAMomentObject}function S(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function D(e){var t=+e,n=0;return 0!==t&&isFinite(t)&&(n=S(t)),n}function a(e,t,n){var s,i=Math.min(e.length,t.length),r=Math.abs(e.length-t.length),a=0;for(s=0;s<i;s++)(n&&e[s]!==t[s]||!n&&D(e[s])!==D(t[s]))&&a++;return a+r}function Y(e){!1===c.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+e)}function n(i,r){var a=!0;return _(function(){if(null!=c.deprecationHandler&&c.deprecationHandler(null,i),a){for(var e,t=[],n=0;n<arguments.length;n++){if(e="","object"==typeof arguments[n]){for(var s in e+="\n["+n+"] ",arguments[0])e+=s+": "+arguments[0][s]+", ";e=e.slice(0,-2)}else e=arguments[n];t.push(e)}Y(i+"\nArguments: "+Array.prototype.slice.call(t).join("")+"\n"+(new Error).stack),a=!1}return r.apply(this,arguments)},r)}var s,O={};function T(e,t){null!=c.deprecationHandler&&c.deprecationHandler(e,t),O[e]||(Y(t),O[e]=!0)}function b(e){return e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}function x(e,t){var n,s=_({},e);for(n in t)m(t,n)&&(u(e[n])&&u(t[n])?(s[n]={},_(s[n],e[n]),_(s[n],t[n])):null!=t[n]?s[n]=t[n]:delete s[n]);for(n in e)m(e,n)&&!m(t,n)&&u(e[n])&&(s[n]=_({},s[n]));return s}function P(e){null!=e&&this.set(e)}c.suppressDeprecationWarnings=!1,c.deprecationHandler=null,s=Object.keys?Object.keys:function(e){var t,n=[];for(t in e)m(e,t)&&n.push(t);return n};var W={};function C(e,t){var n=e.toLowerCase();W[n]=W[n+"s"]=W[t]=e}function H(e){return"string"==typeof e?W[e]||W[e.toLowerCase()]:void 0}function R(e){var t,n,s={};for(n in e)m(e,n)&&(t=H(n))&&(s[t]=e[n]);return s}var U={};function F(e,t){U[e]=t}function L(e,t,n){var s=""+Math.abs(e),i=t-s.length;return(0<=e?n?"+":"":"-")+Math.pow(10,Math.max(0,i)).toString().substr(1)+s}var N=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,G=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,V={},E={};function I(e,t,n,s){var i=s;"string"==typeof s&&(i=function(){return this[s]()}),e&&(E[e]=i),t&&(E[t[0]]=function(){return L(i.apply(this,arguments),t[1],t[2])}),n&&(E[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),e)})}function A(e,t){return e.isValid()?(t=j(t,e.localeData()),V[t]=V[t]||function(s){var e,i,t,r=s.match(N);for(e=0,i=r.length;e<i;e++)E[r[e]]?r[e]=E[r[e]]:r[e]=(t=r[e]).match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"");return function(e){var t,n="";for(t=0;t<i;t++)n+=b(r[t])?r[t].call(e,s):r[t];return n}}(t),V[t](e)):e.localeData().invalidDate()}function j(e,t){var n=5;function s(e){return t.longDateFormat(e)||e}for(G.lastIndex=0;0<=n&&G.test(e);)e=e.replace(G,s),G.lastIndex=0,n-=1;return e}var Z=/\d/,z=/\d\d/,$=/\d{3}/,q=/\d{4}/,J=/[+-]?\d{6}/,B=/\d\d?/,Q=/\d\d\d\d?/,X=/\d\d\d\d\d\d?/,K=/\d{1,3}/,ee=/\d{1,4}/,te=/[+-]?\d{1,6}/,ne=/\d+/,se=/[+-]?\d+/,ie=/Z|[+-]\d\d:?\d\d/gi,re=/Z|[+-]\d\d(?::?\d\d)?/gi,ae=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,oe={};function ue(e,n,s){oe[e]=b(n)?n:function(e,t){return e&&s?s:n}}function le(e,t){return m(oe,e)?oe[e](t._strict,t._locale):new RegExp(he(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(e,t,n,s,i){return t||n||s||i})))}function he(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var de={};function ce(e,n){var t,s=n;for("string"==typeof e&&(e=[e]),h(n)&&(s=function(e,t){t[n]=D(e)}),t=0;t<e.length;t++)de[e[t]]=s}function fe(e,i){ce(e,function(e,t,n,s){n._w=n._w||{},i(e,n._w,n,s)})}var me=0,_e=1,ye=2,ge=3,ve=4,pe=5,we=6,Me=7,ke=8;function Se(e){return De(e)?366:365}function De(e){return e%4==0&&e%100!=0||e%400==0}I("Y",0,0,function(){var e=this.year();return e<=9999?""+e:"+"+e}),I(0,["YY",2],0,function(){return this.year()%100}),I(0,["YYYY",4],0,"year"),I(0,["YYYYY",5],0,"year"),I(0,["YYYYYY",6,!0],0,"year"),C("year","y"),F("year",1),ue("Y",se),ue("YY",B,z),ue("YYYY",ee,q),ue("YYYYY",te,J),ue("YYYYYY",te,J),ce(["YYYYY","YYYYYY"],me),ce("YYYY",function(e,t){t[me]=2===e.length?c.parseTwoDigitYear(e):D(e)}),ce("YY",function(e,t){t[me]=c.parseTwoDigitYear(e)}),ce("Y",function(e,t){t[me]=parseInt(e,10)}),c.parseTwoDigitYear=function(e){return D(e)+(68<D(e)?1900:2e3)};var Ye,Oe=Te("FullYear",!0);function Te(t,n){return function(e){return null!=e?(xe(this,t,e),c.updateOffset(this,n),this):be(this,t)}}function be(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function xe(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&De(e.year())&&1===e.month()&&29===e.date()?e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),Pe(n,e.month())):e._d["set"+(e._isUTC?"UTC":"")+t](n))}function Pe(e,t){if(isNaN(e)||isNaN(t))return NaN;var n,s=(t%(n=12)+n)%n;return e+=(t-s)/12,1===s?De(e)?29:28:31-s%7%2}Ye=Array.prototype.indexOf?Array.prototype.indexOf:function(e){var t;for(t=0;t<this.length;++t)if(this[t]===e)return t;return-1},I("M",["MM",2],"Mo",function(){return this.month()+1}),I("MMM",0,0,function(e){return this.localeData().monthsShort(this,e)}),I("MMMM",0,0,function(e){return this.localeData().months(this,e)}),C("month","M"),F("month",8),ue("M",B),ue("MM",B,z),ue("MMM",function(e,t){return t.monthsShortRegex(e)}),ue("MMMM",function(e,t){return t.monthsRegex(e)}),ce(["M","MM"],function(e,t){t[_e]=D(e)-1}),ce(["MMM","MMMM"],function(e,t,n,s){var i=n._locale.monthsParse(e,s,n._strict);null!=i?t[_e]=i:g(n).invalidMonth=e});var We=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Ce="January_February_March_April_May_June_July_August_September_October_November_December".split("_");var He="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_");function Re(e,t){var n;if(!e.isValid())return e;if("string"==typeof t)if(/^\d+$/.test(t))t=D(t);else if(!h(t=e.localeData().monthsParse(t)))return e;return n=Math.min(e.date(),Pe(e.year(),t)),e._d["set"+(e._isUTC?"UTC":"")+"Month"](t,n),e}function Ue(e){return null!=e?(Re(this,e),c.updateOffset(this,!0),this):be(this,"Month")}var Fe=ae;var Le=ae;function Ne(){function e(e,t){return t.length-e.length}var t,n,s=[],i=[],r=[];for(t=0;t<12;t++)n=y([2e3,t]),s.push(this.monthsShort(n,"")),i.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(s.sort(e),i.sort(e),r.sort(e),t=0;t<12;t++)s[t]=he(s[t]),i[t]=he(i[t]);for(t=0;t<24;t++)r[t]=he(r[t]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+s.join("|")+")","i")}function Ge(e){var t;if(e<100&&0<=e){var n=Array.prototype.slice.call(arguments);n[0]=e+400,t=new Date(Date.UTC.apply(null,n)),isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e)}else t=new Date(Date.UTC.apply(null,arguments));return t}function Ve(e,t,n){var s=7+t-n;return-((7+Ge(e,0,s).getUTCDay()-t)%7)+s-1}function Ee(e,t,n,s,i){var r,a,o=1+7*(t-1)+(7+n-s)%7+Ve(e,s,i);return a=o<=0?Se(r=e-1)+o:o>Se(e)?(r=e+1,o-Se(e)):(r=e,o),{year:r,dayOfYear:a}}function Ie(e,t,n){var s,i,r=Ve(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+Ae(i=e.year()-1,t,n):a>Ae(e.year(),t,n)?(s=a-Ae(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function Ae(e,t,n){var s=Ve(e,t,n),i=Ve(e+1,t,n);return(Se(e)-s+i)/7}I("w",["ww",2],"wo","week"),I("W",["WW",2],"Wo","isoWeek"),C("week","w"),C("isoWeek","W"),F("week",5),F("isoWeek",5),ue("w",B),ue("ww",B,z),ue("W",B),ue("WW",B,z),fe(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=D(e)});function je(e,t){return e.slice(t,7).concat(e.slice(0,t))}I("d",0,"do","day"),I("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),I("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),I("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),I("e",0,0,"weekday"),I("E",0,0,"isoWeekday"),C("day","d"),C("weekday","e"),C("isoWeekday","E"),F("day",11),F("weekday",11),F("isoWeekday",11),ue("d",B),ue("e",B),ue("E",B),ue("dd",function(e,t){return t.weekdaysMinRegex(e)}),ue("ddd",function(e,t){return t.weekdaysShortRegex(e)}),ue("dddd",function(e,t){return t.weekdaysRegex(e)}),fe(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:g(n).invalidWeekday=e}),fe(["d","e","E"],function(e,t,n,s){t[s]=D(e)});var Ze="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var ze="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var $e="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var qe=ae;var Je=ae;var Be=ae;function Qe(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=y([2e3,1]).day(t),s=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(s),o.push(i),u.push(r),l.push(s),l.push(i),l.push(r);for(a.sort(e),o.sort(e),u.sort(e),l.sort(e),t=0;t<7;t++)o[t]=he(o[t]),u[t]=he(u[t]),l[t]=he(l[t]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Xe(){return this.hours()%12||12}function Ke(e,t){I(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function et(e,t){return t._meridiemParse}I("H",["HH",2],0,"hour"),I("h",["hh",2],0,Xe),I("k",["kk",2],0,function(){return this.hours()||24}),I("hmm",0,0,function(){return""+Xe.apply(this)+L(this.minutes(),2)}),I("hmmss",0,0,function(){return""+Xe.apply(this)+L(this.minutes(),2)+L(this.seconds(),2)}),I("Hmm",0,0,function(){return""+this.hours()+L(this.minutes(),2)}),I("Hmmss",0,0,function(){return""+this.hours()+L(this.minutes(),2)+L(this.seconds(),2)}),Ke("a",!0),Ke("A",!1),C("hour","h"),F("hour",13),ue("a",et),ue("A",et),ue("H",B),ue("h",B),ue("k",B),ue("HH",B,z),ue("hh",B,z),ue("kk",B,z),ue("hmm",Q),ue("hmmss",X),ue("Hmm",Q),ue("Hmmss",X),ce(["H","HH"],ge),ce(["k","kk"],function(e,t,n){var s=D(e);t[ge]=24===s?0:s}),ce(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),ce(["h","hh"],function(e,t,n){t[ge]=D(e),g(n).bigHour=!0}),ce("hmm",function(e,t,n){var s=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s)),g(n).bigHour=!0}),ce("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s,2)),t[pe]=D(e.substr(i)),g(n).bigHour=!0}),ce("Hmm",function(e,t,n){var s=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s))}),ce("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=D(e.substr(0,s)),t[ve]=D(e.substr(s,2)),t[pe]=D(e.substr(i))});var tt,nt=Te("Hours",!0),st={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Ce,monthsShort:He,week:{dow:0,doy:6},weekdays:Ze,weekdaysMin:$e,weekdaysShort:ze,meridiemParse:/[ap]\.?m?\.?/i},it={},rt={};function at(e){return e?e.toLowerCase().replace("_","-"):e}function ot(e){var t=null;if(!it[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=tt._abbr,require("./locale/"+e),ut(t)}catch(e){}return it[e]}function ut(e,t){var n;return e&&((n=l(t)?ht(e):lt(e,t))?tt=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),tt._abbr}function lt(e,t){if(null===t)return delete it[e],null;var n,s=st;if(t.abbr=e,null!=it[e])T("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=it[e]._config;else if(null!=t.parentLocale)if(null!=it[t.parentLocale])s=it[t.parentLocale]._config;else{if(null==(n=ot(t.parentLocale)))return rt[t.parentLocale]||(rt[t.parentLocale]=[]),rt[t.parentLocale].push({name:e,config:t}),null;s=n._config}return it[e]=new P(x(s,t)),rt[e]&&rt[e].forEach(function(e){lt(e.name,e.config)}),ut(e),it[e]}function ht(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return tt;if(!o(e)){if(t=ot(e))return t;e=[e]}return function(e){for(var t,n,s,i,r=0;r<e.length;){for(t=(i=at(e[r]).split("-")).length,n=(n=at(e[r+1]))?n.split("-"):null;0<t;){if(s=ot(i.slice(0,t).join("-")))return s;if(n&&n.length>=t&&a(i,n,!0)>=t-1)break;t--}r++}return tt}(e)}function dt(e){var t,n=e._a;return n&&-2===g(e).overflow&&(t=n[_e]<0||11<n[_e]?_e:n[ye]<1||n[ye]>Pe(n[me],n[_e])?ye:n[ge]<0||24<n[ge]||24===n[ge]&&(0!==n[ve]||0!==n[pe]||0!==n[we])?ge:n[ve]<0||59<n[ve]?ve:n[pe]<0||59<n[pe]?pe:n[we]<0||999<n[we]?we:-1,g(e)._overflowDayOfYear&&(t<me||ye<t)&&(t=ye),g(e)._overflowWeeks&&-1===t&&(t=Me),g(e)._overflowWeekday&&-1===t&&(t=ke),g(e).overflow=t),e}function ct(e,t,n){return null!=e?e:null!=t?t:n}function ft(e){var t,n,s,i,r,a=[];if(!e._d){var o,u;for(o=e,u=new Date(c.now()),s=o._useUTC?[u.getUTCFullYear(),u.getUTCMonth(),u.getUTCDate()]:[u.getFullYear(),u.getMonth(),u.getDate()],e._w&&null==e._a[ye]&&null==e._a[_e]&&function(e){var t,n,s,i,r,a,o,u;if(null!=(t=e._w).GG||null!=t.W||null!=t.E)r=1,a=4,n=ct(t.GG,e._a[me],Ie(bt(),1,4).year),s=ct(t.W,1),((i=ct(t.E,1))<1||7<i)&&(u=!0);else{r=e._locale._week.dow,a=e._locale._week.doy;var l=Ie(bt(),r,a);n=ct(t.gg,e._a[me],l.year),s=ct(t.w,l.week),null!=t.d?((i=t.d)<0||6<i)&&(u=!0):null!=t.e?(i=t.e+r,(t.e<0||6<t.e)&&(u=!0)):i=r}s<1||s>Ae(n,r,a)?g(e)._overflowWeeks=!0:null!=u?g(e)._overflowWeekday=!0:(o=Ee(n,s,i,r,a),e._a[me]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(r=ct(e._a[me],s[me]),(e._dayOfYear>Se(r)||0===e._dayOfYear)&&(g(e)._overflowDayOfYear=!0),n=Ge(r,0,e._dayOfYear),e._a[_e]=n.getUTCMonth(),e._a[ye]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=a[t]=s[t];for(;t<7;t++)e._a[t]=a[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[ge]&&0===e._a[ve]&&0===e._a[pe]&&0===e._a[we]&&(e._nextDay=!0,e._a[ge]=0),e._d=(e._useUTC?Ge:function(e,t,n,s,i,r,a){var o;return e<100&&0<=e?(o=new Date(e+400,t,n,s,i,r,a),isFinite(o.getFullYear())&&o.setFullYear(e)):o=new Date(e,t,n,s,i,r,a),o}).apply(null,a),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[ge]=24),e._w&&void 0!==e._w.d&&e._w.d!==i&&(g(e).weekdayMismatch=!0)}}var mt=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,_t=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,yt=/Z|[+-]\d\d(?::?\d\d)?/,gt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],vt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],pt=/^\/?Date\((\-?\d+)/i;function wt(e){var t,n,s,i,r,a,o=e._i,u=mt.exec(o)||_t.exec(o);if(u){for(g(e).iso=!0,t=0,n=gt.length;t<n;t++)if(gt[t][1].exec(u[1])){i=gt[t][0],s=!1!==gt[t][2];break}if(null==i)return void(e._isValid=!1);if(u[3]){for(t=0,n=vt.length;t<n;t++)if(vt[t][1].exec(u[3])){r=(u[2]||" ")+vt[t][0];break}if(null==r)return void(e._isValid=!1)}if(!s&&null!=r)return void(e._isValid=!1);if(u[4]){if(!yt.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),Yt(e)}else e._isValid=!1}var Mt=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;function kt(e,t,n,s,i,r){var a=[function(e){var t=parseInt(e,10);{if(t<=49)return 2e3+t;if(t<=999)return 1900+t}return t}(e),He.indexOf(t),parseInt(n,10),parseInt(s,10),parseInt(i,10)];return r&&a.push(parseInt(r,10)),a}var St={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Dt(e){var t,n,s,i=Mt.exec(e._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s\s*/,"").replace(/\s\s*$/,""));if(i){var r=kt(i[4],i[3],i[2],i[5],i[6],i[7]);if(t=i[1],n=r,s=e,t&&ze.indexOf(t)!==new Date(n[0],n[1],n[2]).getDay()&&(g(s).weekdayMismatch=!0,!(s._isValid=!1)))return;e._a=r,e._tzm=function(e,t,n){if(e)return St[e];if(t)return 0;var s=parseInt(n,10),i=s%100;return(s-i)/100*60+i}(i[8],i[9],i[10]),e._d=Ge.apply(null,e._a),e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),g(e).rfc2822=!0}else e._isValid=!1}function Yt(e){if(e._f!==c.ISO_8601)if(e._f!==c.RFC_2822){e._a=[],g(e).empty=!0;var t,n,s,i,r,a,o,u,l=""+e._i,h=l.length,d=0;for(s=j(e._f,e._locale).match(N)||[],t=0;t<s.length;t++)i=s[t],(n=(l.match(le(i,e))||[])[0])&&(0<(r=l.substr(0,l.indexOf(n))).length&&g(e).unusedInput.push(r),l=l.slice(l.indexOf(n)+n.length),d+=n.length),E[i]?(n?g(e).empty=!1:g(e).unusedTokens.push(i),a=i,u=e,null!=(o=n)&&m(de,a)&&de[a](o,u._a,u,a)):e._strict&&!n&&g(e).unusedTokens.push(i);g(e).charsLeftOver=h-d,0<l.length&&g(e).unusedInput.push(l),e._a[ge]<=12&&!0===g(e).bigHour&&0<e._a[ge]&&(g(e).bigHour=void 0),g(e).parsedDateParts=e._a.slice(0),g(e).meridiem=e._meridiem,e._a[ge]=function(e,t,n){var s;if(null==n)return t;return null!=e.meridiemHour?e.meridiemHour(t,n):(null!=e.isPM&&((s=e.isPM(n))&&t<12&&(t+=12),s||12!==t||(t=0)),t)}(e._locale,e._a[ge],e._meridiem),ft(e),dt(e)}else Dt(e);else wt(e)}function Ot(e){var t,n,s,i,r=e._i,a=e._f;return e._locale=e._locale||ht(e._l),null===r||void 0===a&&""===r?p({nullInput:!0}):("string"==typeof r&&(e._i=r=e._locale.preparse(r)),k(r)?new M(dt(r)):(d(r)?e._d=r:o(a)?function(e){var t,n,s,i,r;if(0===e._f.length)return g(e).invalidFormat=!0,e._d=new Date(NaN);for(i=0;i<e._f.length;i++)r=0,t=w({},e),null!=e._useUTC&&(t._useUTC=e._useUTC),t._f=e._f[i],Yt(t),v(t)&&(r+=g(t).charsLeftOver,r+=10*g(t).unusedTokens.length,g(t).score=r,(null==s||r<s)&&(s=r,n=t));_(e,n||t)}(e):a?Yt(e):l(n=(t=e)._i)?t._d=new Date(c.now()):d(n)?t._d=new Date(n.valueOf()):"string"==typeof n?(s=t,null===(i=pt.exec(s._i))?(wt(s),!1===s._isValid&&(delete s._isValid,Dt(s),!1===s._isValid&&(delete s._isValid,c.createFromInputFallback(s)))):s._d=new Date(+i[1])):o(n)?(t._a=f(n.slice(0),function(e){return parseInt(e,10)}),ft(t)):u(n)?function(e){if(!e._d){var t=R(e._i);e._a=f([t.year,t.month,t.day||t.date,t.hour,t.minute,t.second,t.millisecond],function(e){return e&&parseInt(e,10)}),ft(e)}}(t):h(n)?t._d=new Date(n):c.createFromInputFallback(t),v(e)||(e._d=null),e))}function Tt(e,t,n,s,i){var r,a={};return!0!==n&&!1!==n||(s=n,n=void 0),(u(e)&&function(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var t;for(t in e)if(e.hasOwnProperty(t))return!1;return!0}(e)||o(e)&&0===e.length)&&(e=void 0),a._isAMomentObject=!0,a._useUTC=a._isUTC=i,a._l=n,a._i=e,a._f=t,a._strict=s,(r=new M(dt(Ot(a))))._nextDay&&(r.add(1,"d"),r._nextDay=void 0),r}function bt(e,t,n,s){return Tt(e,t,n,s,!1)}c.createFromInputFallback=n("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(e){e._d=new Date(e._i+(e._useUTC?" UTC":""))}),c.ISO_8601=function(){},c.RFC_2822=function(){};var xt=n("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=bt.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:p()}),Pt=n("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=bt.apply(null,arguments);return this.isValid()&&e.isValid()?this<e?this:e:p()});function Wt(e,t){var n,s;if(1===t.length&&o(t[0])&&(t=t[0]),!t.length)return bt();for(n=t[0],s=1;s<t.length;++s)t[s].isValid()&&!t[s][e](n)||(n=t[s]);return n}var Ct=["year","quarter","month","week","day","hour","minute","second","millisecond"];function Ht(e){var t=R(e),n=t.year||0,s=t.quarter||0,i=t.month||0,r=t.week||t.isoWeek||0,a=t.day||0,o=t.hour||0,u=t.minute||0,l=t.second||0,h=t.millisecond||0;this._isValid=function(e){for(var t in e)if(-1===Ye.call(Ct,t)||null!=e[t]&&isNaN(e[t]))return!1;for(var n=!1,s=0;s<Ct.length;++s)if(e[Ct[s]]){if(n)return!1;parseFloat(e[Ct[s]])!==D(e[Ct[s]])&&(n=!0)}return!0}(t),this._milliseconds=+h+1e3*l+6e4*u+1e3*o*60*60,this._days=+a+7*r,this._months=+i+3*s+12*n,this._data={},this._locale=ht(),this._bubble()}function Rt(e){return e instanceof Ht}function Ut(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Ft(e,n){I(e,0,0,function(){var e=this.utcOffset(),t="+";return e<0&&(e=-e,t="-"),t+L(~~(e/60),2)+n+L(~~e%60,2)})}Ft("Z",":"),Ft("ZZ",""),ue("Z",re),ue("ZZ",re),ce(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=Nt(re,e)});var Lt=/([\+\-]|\d\d)/gi;function Nt(e,t){var n=(t||"").match(e);if(null===n)return null;var s=((n[n.length-1]||[])+"").match(Lt)||["-",0,0],i=60*s[1]+D(s[2]);return 0===i?0:"+"===s[0]?i:-i}function Gt(e,t){var n,s;return t._isUTC?(n=t.clone(),s=(k(e)||d(e)?e.valueOf():bt(e).valueOf())-n.valueOf(),n._d.setTime(n._d.valueOf()+s),c.updateOffset(n,!1),n):bt(e).local()}function Vt(e){return 15*-Math.round(e._d.getTimezoneOffset()/15)}function Et(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}c.updateOffset=function(){};var It=/^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,At=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function jt(e,t){var n,s,i,r=e,a=null;return Rt(e)?r={ms:e._milliseconds,d:e._days,M:e._months}:h(e)?(r={},t?r[t]=e:r.milliseconds=e):(a=It.exec(e))?(n="-"===a[1]?-1:1,r={y:0,d:D(a[ye])*n,h:D(a[ge])*n,m:D(a[ve])*n,s:D(a[pe])*n,ms:D(Ut(1e3*a[we]))*n}):(a=At.exec(e))?(n="-"===a[1]?-1:1,r={y:Zt(a[2],n),M:Zt(a[3],n),w:Zt(a[4],n),d:Zt(a[5],n),h:Zt(a[6],n),m:Zt(a[7],n),s:Zt(a[8],n)}):null==r?r={}:"object"==typeof r&&("from"in r||"to"in r)&&(i=function(e,t){var n;if(!e.isValid()||!t.isValid())return{milliseconds:0,months:0};t=Gt(t,e),e.isBefore(t)?n=zt(e,t):((n=zt(t,e)).milliseconds=-n.milliseconds,n.months=-n.months);return n}(bt(r.from),bt(r.to)),(r={}).ms=i.milliseconds,r.M=i.months),s=new Ht(r),Rt(e)&&m(e,"_locale")&&(s._locale=e._locale),s}function Zt(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function zt(e,t){var n={};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function $t(s,i){return function(e,t){var n;return null===t||isNaN(+t)||(T(i,"moment()."+i+"(period, number) is deprecated. Please use moment()."+i+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),n=e,e=t,t=n),qt(this,jt(e="string"==typeof e?+e:e,t),s),this}}function qt(e,t,n,s){var i=t._milliseconds,r=Ut(t._days),a=Ut(t._months);e.isValid()&&(s=null==s||s,a&&Re(e,be(e,"Month")+a*n),r&&xe(e,"Date",be(e,"Date")+r*n),i&&e._d.setTime(e._d.valueOf()+i*n),s&&c.updateOffset(e,r||a))}jt.fn=Ht.prototype,jt.invalid=function(){return jt(NaN)};var Jt=$t(1,"add"),Bt=$t(-1,"subtract");function Qt(e,t){var n=12*(t.year()-e.year())+(t.month()-e.month()),s=e.clone().add(n,"months");return-(n+(t-s<0?(t-s)/(s-e.clone().add(n-1,"months")):(t-s)/(e.clone().add(n+1,"months")-s)))||0}function Xt(e){var t;return void 0===e?this._locale._abbr:(null!=(t=ht(e))&&(this._locale=t),this)}c.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",c.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Kt=n("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){return void 0===e?this.localeData():this.locale(e)});function en(){return this._locale}var tn=126227808e5;function nn(e,t){return(e%t+t)%t}function sn(e,t,n){return e<100&&0<=e?new Date(e+400,t,n)-tn:new Date(e,t,n).valueOf()}function rn(e,t,n){return e<100&&0<=e?Date.UTC(e+400,t,n)-tn:Date.UTC(e,t,n)}function an(e,t){I(0,[e,e.length],0,t)}function on(e,t,n,s,i){var r;return null==e?Ie(this,s,i).year:((r=Ae(e,s,i))<t&&(t=r),function(e,t,n,s,i){var r=Ee(e,t,n,s,i),a=Ge(r.year,0,r.dayOfYear);return this.year(a.getUTCFullYear()),this.month(a.getUTCMonth()),this.date(a.getUTCDate()),this}.call(this,e,t,n,s,i))}I(0,["gg",2],0,function(){return this.weekYear()%100}),I(0,["GG",2],0,function(){return this.isoWeekYear()%100}),an("gggg","weekYear"),an("ggggg","weekYear"),an("GGGG","isoWeekYear"),an("GGGGG","isoWeekYear"),C("weekYear","gg"),C("isoWeekYear","GG"),F("weekYear",1),F("isoWeekYear",1),ue("G",se),ue("g",se),ue("GG",B,z),ue("gg",B,z),ue("GGGG",ee,q),ue("gggg",ee,q),ue("GGGGG",te,J),ue("ggggg",te,J),fe(["gggg","ggggg","GGGG","GGGGG"],function(e,t,n,s){t[s.substr(0,2)]=D(e)}),fe(["gg","GG"],function(e,t,n,s){t[s]=c.parseTwoDigitYear(e)}),I("Q",0,"Qo","quarter"),C("quarter","Q"),F("quarter",7),ue("Q",Z),ce("Q",function(e,t){t[_e]=3*(D(e)-1)}),I("D",["DD",2],"Do","date"),C("date","D"),F("date",9),ue("D",B),ue("DD",B,z),ue("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),ce(["D","DD"],ye),ce("Do",function(e,t){t[ye]=D(e.match(B)[0])});var un=Te("Date",!0);I("DDD",["DDDD",3],"DDDo","dayOfYear"),C("dayOfYear","DDD"),F("dayOfYear",4),ue("DDD",K),ue("DDDD",$),ce(["DDD","DDDD"],function(e,t,n){n._dayOfYear=D(e)}),I("m",["mm",2],0,"minute"),C("minute","m"),F("minute",14),ue("m",B),ue("mm",B,z),ce(["m","mm"],ve);var ln=Te("Minutes",!1);I("s",["ss",2],0,"second"),C("second","s"),F("second",15),ue("s",B),ue("ss",B,z),ce(["s","ss"],pe);var hn,dn=Te("Seconds",!1);for(I("S",0,0,function(){return~~(this.millisecond()/100)}),I(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),I(0,["SSS",3],0,"millisecond"),I(0,["SSSS",4],0,function(){return 10*this.millisecond()}),I(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),I(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),I(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),I(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),I(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),C("millisecond","ms"),F("millisecond",16),ue("S",K,Z),ue("SS",K,z),ue("SSS",K,$),hn="SSSS";hn.length<=9;hn+="S")ue(hn,ne);function cn(e,t){t[we]=D(1e3*("0."+e))}for(hn="S";hn.length<=9;hn+="S")ce(hn,cn);var fn=Te("Milliseconds",!1);I("z",0,0,"zoneAbbr"),I("zz",0,0,"zoneName");var mn=M.prototype;function _n(e){return e}mn.add=Jt,mn.calendar=function(e,t){var n=e||bt(),s=Gt(n,this).startOf("day"),i=c.calendarFormat(this,s)||"sameElse",r=t&&(b(t[i])?t[i].call(this,n):t[i]);return this.format(r||this.localeData().calendar(i,this,bt(n)))},mn.clone=function(){return new M(this)},mn.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=Gt(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=H(t)){case"year":r=Qt(this,s)/12;break;case"month":r=Qt(this,s);break;case"quarter":r=Qt(this,s)/3;break;case"second":r=(this-s)/1e3;break;case"minute":r=(this-s)/6e4;break;case"hour":r=(this-s)/36e5;break;case"day":r=(this-s-i)/864e5;break;case"week":r=(this-s-i)/6048e5;break;default:r=this-s}return n?r:S(r)},mn.endOf=function(e){var t;if(void 0===(e=H(e))||"millisecond"===e||!this.isValid())return this;var n=this._isUTC?rn:sn;switch(e){case"year":t=n(this.year()+1,0,1)-1;break;case"quarter":t=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":t=n(this.year(),this.month()+1,1)-1;break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":t=n(this.year(),this.month(),this.date()+1)-1;break;case"hour":t=this._d.valueOf(),t+=36e5-nn(t+(this._isUTC?0:6e4*this.utcOffset()),36e5)-1;break;case"minute":t=this._d.valueOf(),t+=6e4-nn(t,6e4)-1;break;case"second":t=this._d.valueOf(),t+=1e3-nn(t,1e3)-1;break}return this._d.setTime(t),c.updateOffset(this,!0),this},mn.format=function(e){e||(e=this.isUtc()?c.defaultFormatUtc:c.defaultFormat);var t=A(this,e);return this.localeData().postformat(t)},mn.from=function(e,t){return this.isValid()&&(k(e)&&e.isValid()||bt(e).isValid())?jt({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},mn.fromNow=function(e){return this.from(bt(),e)},mn.to=function(e,t){return this.isValid()&&(k(e)&&e.isValid()||bt(e).isValid())?jt({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},mn.toNow=function(e){return this.to(bt(),e)},mn.get=function(e){return b(this[e=H(e)])?this[e]():this},mn.invalidAt=function(){return g(this).overflow},mn.isAfter=function(e,t){var n=k(e)?e:bt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf())},mn.isBefore=function(e,t){var n=k(e)?e:bt(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf())},mn.isBetween=function(e,t,n,s){var i=k(e)?e:bt(e),r=k(t)?t:bt(t);return!!(this.isValid()&&i.isValid()&&r.isValid())&&("("===(s=s||"()")[0]?this.isAfter(i,n):!this.isBefore(i,n))&&(")"===s[1]?this.isBefore(r,n):!this.isAfter(r,n))},mn.isSame=function(e,t){var n,s=k(e)?e:bt(e);return!(!this.isValid()||!s.isValid())&&("millisecond"===(t=H(t)||"millisecond")?this.valueOf()===s.valueOf():(n=s.valueOf(),this.clone().startOf(t).valueOf()<=n&&n<=this.clone().endOf(t).valueOf()))},mn.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},mn.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},mn.isValid=function(){return v(this)},mn.lang=Kt,mn.locale=Xt,mn.localeData=en,mn.max=Pt,mn.min=xt,mn.parsingFlags=function(){return _({},g(this))},mn.set=function(e,t){if("object"==typeof e)for(var n=function(e){var t=[];for(var n in e)t.push({unit:n,priority:U[n]});return t.sort(function(e,t){return e.priority-t.priority}),t}(e=R(e)),s=0;s<n.length;s++)this[n[s].unit](e[n[s].unit]);else if(b(this[e=H(e)]))return this[e](t);return this},mn.startOf=function(e){var t;if(void 0===(e=H(e))||"millisecond"===e||!this.isValid())return this;var n=this._isUTC?rn:sn;switch(e){case"year":t=n(this.year(),0,1);break;case"quarter":t=n(this.year(),this.month()-this.month()%3,1);break;case"month":t=n(this.year(),this.month(),1);break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":t=n(this.year(),this.month(),this.date());break;case"hour":t=this._d.valueOf(),t-=nn(t+(this._isUTC?0:6e4*this.utcOffset()),36e5);break;case"minute":t=this._d.valueOf(),t-=nn(t,6e4);break;case"second":t=this._d.valueOf(),t-=nn(t,1e3);break}return this._d.setTime(t),c.updateOffset(this,!0),this},mn.subtract=Bt,mn.toArray=function(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]},mn.toObject=function(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}},mn.toDate=function(){return new Date(this.valueOf())},mn.toISOString=function(e){if(!this.isValid())return null;var t=!0!==e,n=t?this.clone().utc():this;return n.year()<0||9999<n.year()?A(n,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):b(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",A(n,"Z")):A(n,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},mn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e="moment",t="";this.isLocal()||(e=0===this.utcOffset()?"moment.utc":"moment.parseZone",t="Z");var n="["+e+'("]',s=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",i=t+'[")]';return this.format(n+s+"-MM-DD[T]HH:mm:ss.SSS"+i)},mn.toJSON=function(){return this.isValid()?this.toISOString():null},mn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},mn.unix=function(){return Math.floor(this.valueOf()/1e3)},mn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},mn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},mn.year=Oe,mn.isLeapYear=function(){return De(this.year())},mn.weekYear=function(e){return on.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},mn.isoWeekYear=function(e){return on.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},mn.quarter=mn.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},mn.month=Ue,mn.daysInMonth=function(){return Pe(this.year(),this.month())},mn.week=mn.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},mn.isoWeek=mn.isoWeeks=function(e){var t=Ie(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},mn.weeksInYear=function(){var e=this.localeData()._week;return Ae(this.year(),e.dow,e.doy)},mn.isoWeeksInYear=function(){return Ae(this.year(),1,4)},mn.date=un,mn.day=mn.days=function(e){if(!this.isValid())return null!=e?this:NaN;var t,n,s=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(t=e,n=this.localeData(),e="string"!=typeof t?t:isNaN(t)?"number"==typeof(t=n.weekdaysParse(t))?t:null:parseInt(t,10),this.add(e-s,"d")):s},mn.weekday=function(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")},mn.isoWeekday=function(e){if(!this.isValid())return null!=e?this:NaN;if(null==e)return this.day()||7;var t,n,s=(t=e,n=this.localeData(),"string"==typeof t?n.weekdaysParse(t)%7||7:isNaN(t)?null:t);return this.day(this.day()%7?s:s-7)},mn.dayOfYear=function(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")},mn.hour=mn.hours=nt,mn.minute=mn.minutes=ln,mn.second=mn.seconds=dn,mn.millisecond=mn.milliseconds=fn,mn.utcOffset=function(e,t,n){var s,i=this._offset||0;if(!this.isValid())return null!=e?this:NaN;if(null==e)return this._isUTC?i:Vt(this);if("string"==typeof e){if(null===(e=Nt(re,e)))return this}else Math.abs(e)<16&&!n&&(e*=60);return!this._isUTC&&t&&(s=Vt(this)),this._offset=e,this._isUTC=!0,null!=s&&this.add(s,"m"),i!==e&&(!t||this._changeInProgress?qt(this,jt(e-i,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,c.updateOffset(this,!0),this._changeInProgress=null)),this},mn.utc=function(e){return this.utcOffset(0,e)},mn.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Vt(this),"m")),this},mn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=Nt(ie,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},mn.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?bt(e).utcOffset():0,(this.utcOffset()-e)%60==0)},mn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},mn.isLocal=function(){return!!this.isValid()&&!this._isUTC},mn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},mn.isUtc=Et,mn.isUTC=Et,mn.zoneAbbr=function(){return this._isUTC?"UTC":""},mn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},mn.dates=n("dates accessor is deprecated. Use date instead.",un),mn.months=n("months accessor is deprecated. Use month instead",Ue),mn.years=n("years accessor is deprecated. Use year instead",Oe),mn.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),mn.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!l(this._isDSTShifted))return this._isDSTShifted;var e={};if(w(e,this),(e=Ot(e))._a){var t=e._isUTC?y(e._a):bt(e._a);this._isDSTShifted=this.isValid()&&0<a(e._a,t.toArray())}else this._isDSTShifted=!1;return this._isDSTShifted});var yn=P.prototype;function gn(e,t,n,s){var i=ht(),r=y().set(s,t);return i[n](r,e)}function vn(e,t,n){if(h(e)&&(t=e,e=void 0),e=e||"",null!=t)return gn(e,t,n,"month");var s,i=[];for(s=0;s<12;s++)i[s]=gn(e,s,n,"month");return i}function pn(e,t,n,s){t=("boolean"==typeof e?h(t)&&(n=t,t=void 0):(t=e,e=!1,h(n=t)&&(n=t,t=void 0)),t||"");var i,r=ht(),a=e?r._week.dow:0;if(null!=n)return gn(t,(n+a)%7,s,"day");var o=[];for(i=0;i<7;i++)o[i]=gn(t,(i+a)%7,s,"day");return o}yn.calendar=function(e,t,n){var s=this._calendar[e]||this._calendar.sameElse;return b(s)?s.call(t,n):s},yn.longDateFormat=function(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.replace(/MMMM|MM|DD|dddd/g,function(e){return e.slice(1)}),this._longDateFormat[e])},yn.invalidDate=function(){return this._invalidDate},yn.ordinal=function(e){return this._ordinal.replace("%d",e)},yn.preparse=_n,yn.postformat=_n,yn.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return b(i)?i(e,t,n,s):i.replace(/%d/i,e)},yn.pastFuture=function(e,t){var n=this._relativeTime[0<e?"future":"past"];return b(n)?n(t):n.replace(/%s/i,t)},yn.set=function(e){var t,n;for(n in e)b(t=e[n])?this[n]=t:this["_"+n]=t;this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},yn.months=function(e,t){return e?o(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||We).test(t)?"format":"standalone"][e.month()]:o(this._months)?this._months:this._months.standalone},yn.monthsShort=function(e,t){return e?o(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[We.test(t)?"format":"standalone"][e.month()]:o(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},yn.monthsParse=function(e,t,n){var s,i,r;if(this._monthsParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],s=0;s<12;++s)r=y([2e3,s]),this._shortMonthsParse[s]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[s]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:"MMM"===t?-1!==(i=Ye.call(this._shortMonthsParse,a))?i:-1!==(i=Ye.call(this._longMonthsParse,a))?i:null:-1!==(i=Ye.call(this._longMonthsParse,a))?i:-1!==(i=Ye.call(this._shortMonthsParse,a))?i:null}.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;s<12;s++){if(i=y([2e3,s]),n&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(i,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(i,"").replace(".","")+"$","i")),n||this._monthsParse[s]||(r="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[s]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===t&&this._longMonthsParse[s].test(e))return s;if(n&&"MMM"===t&&this._shortMonthsParse[s].test(e))return s;if(!n&&this._monthsParse[s].test(e))return s}},yn.monthsRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsStrictRegex:this._monthsRegex):(m(this,"_monthsRegex")||(this._monthsRegex=Le),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},yn.monthsShortRegex=function(e){return this._monthsParseExact?(m(this,"_monthsRegex")||Ne.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(m(this,"_monthsShortRegex")||(this._monthsShortRegex=Fe),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},yn.week=function(e){return Ie(e,this._week.dow,this._week.doy).week},yn.firstDayOfYear=function(){return this._week.doy},yn.firstDayOfWeek=function(){return this._week.dow},yn.weekdays=function(e,t){var n=o(this._weekdays)?this._weekdays:this._weekdays[e&&!0!==e&&this._weekdays.isFormat.test(t)?"format":"standalone"];return!0===e?je(n,this._week.dow):e?n[e.day()]:n},yn.weekdaysMin=function(e){return!0===e?je(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin},yn.weekdaysShort=function(e){return!0===e?je(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort},yn.weekdaysParse=function(e,t,n){var s,i,r;if(this._weekdaysParseExact)return function(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=y([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"dddd"===t?-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:"ddd"===t?-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:null:-1!==(i=Ye.call(this._minWeekdaysParse,a))?i:-1!==(i=Ye.call(this._weekdaysParse,a))?i:-1!==(i=Ye.call(this._shortWeekdaysParse,a))?i:null}.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(i=y([2e3,1]).day(s),n&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(i,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(i,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(i,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[s]||(r="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[s]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[s].test(e))return s;if(n&&"ddd"===t&&this._shortWeekdaysParse[s].test(e))return s;if(n&&"dd"===t&&this._minWeekdaysParse[s].test(e))return s;if(!n&&this._weekdaysParse[s].test(e))return s}},yn.weekdaysRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(m(this,"_weekdaysRegex")||(this._weekdaysRegex=qe),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},yn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(m(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Je),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},yn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(m(this,"_weekdaysRegex")||Qe.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(m(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Be),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},yn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},yn.meridiem=function(e,t,n){return 11<e?n?"pm":"PM":n?"am":"AM"},ut("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===D(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),c.lang=n("moment.lang is deprecated. Use moment.locale instead.",ut),c.langData=n("moment.langData is deprecated. Use moment.localeData instead.",ht);var wn=Math.abs;function Mn(e,t,n,s){var i=jt(t,n);return e._milliseconds+=s*i._milliseconds,e._days+=s*i._days,e._months+=s*i._months,e._bubble()}function kn(e){return e<0?Math.floor(e):Math.ceil(e)}function Sn(e){return 4800*e/146097}function Dn(e){return 146097*e/4800}function Yn(e){return function(){return this.as(e)}}var On=Yn("ms"),Tn=Yn("s"),bn=Yn("m"),xn=Yn("h"),Pn=Yn("d"),Wn=Yn("w"),Cn=Yn("M"),Hn=Yn("Q"),Rn=Yn("y");function Un(e){return function(){return this.isValid()?this._data[e]:NaN}}var Fn=Un("milliseconds"),Ln=Un("seconds"),Nn=Un("minutes"),Gn=Un("hours"),Vn=Un("days"),En=Un("months"),In=Un("years");var An=Math.round,jn={ss:44,s:45,m:45,h:22,d:26,M:11};var Zn=Math.abs;function zn(e){return(0<e)-(e<0)||+e}function $n(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n=Zn(this._milliseconds)/1e3,s=Zn(this._days),i=Zn(this._months);t=S((e=S(n/60))/60),n%=60,e%=60;var r=S(i/12),a=i%=12,o=s,u=t,l=e,h=n?n.toFixed(3).replace(/\.?0+$/,""):"",d=this.asSeconds();if(!d)return"P0D";var c=d<0?"-":"",f=zn(this._months)!==zn(d)?"-":"",m=zn(this._days)!==zn(d)?"-":"",_=zn(this._milliseconds)!==zn(d)?"-":"";return c+"P"+(r?f+r+"Y":"")+(a?f+a+"M":"")+(o?m+o+"D":"")+(u||l||h?"T":"")+(u?_+u+"H":"")+(l?_+l+"M":"")+(h?_+h+"S":"")}var qn=Ht.prototype;return qn.isValid=function(){return this._isValid},qn.abs=function(){var e=this._data;return this._milliseconds=wn(this._milliseconds),this._days=wn(this._days),this._months=wn(this._months),e.milliseconds=wn(e.milliseconds),e.seconds=wn(e.seconds),e.minutes=wn(e.minutes),e.hours=wn(e.hours),e.months=wn(e.months),e.years=wn(e.years),this},qn.add=function(e,t){return Mn(this,e,t,1)},qn.subtract=function(e,t){return Mn(this,e,t,-1)},qn.as=function(e){if(!this.isValid())return NaN;var t,n,s=this._milliseconds;if("month"===(e=H(e))||"quarter"===e||"year"===e)switch(t=this._days+s/864e5,n=this._months+Sn(t),e){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(t=this._days+Math.round(Dn(this._months)),e){case"week":return t/7+s/6048e5;case"day":return t+s/864e5;case"hour":return 24*t+s/36e5;case"minute":return 1440*t+s/6e4;case"second":return 86400*t+s/1e3;case"millisecond":return Math.floor(864e5*t)+s;default:throw new Error("Unknown unit "+e)}},qn.asMilliseconds=On,qn.asSeconds=Tn,qn.asMinutes=bn,qn.asHours=xn,qn.asDays=Pn,qn.asWeeks=Wn,qn.asMonths=Cn,qn.asQuarters=Hn,qn.asYears=Rn,qn.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*D(this._months/12):NaN},qn._bubble=function(){var e,t,n,s,i,r=this._milliseconds,a=this._days,o=this._months,u=this._data;return 0<=r&&0<=a&&0<=o||r<=0&&a<=0&&o<=0||(r+=864e5*kn(Dn(o)+a),o=a=0),u.milliseconds=r%1e3,e=S(r/1e3),u.seconds=e%60,t=S(e/60),u.minutes=t%60,n=S(t/60),u.hours=n%24,o+=i=S(Sn(a+=S(n/24))),a-=kn(Dn(i)),s=S(o/12),o%=12,u.days=a,u.months=o,u.years=s,this},qn.clone=function(){return jt(this)},qn.get=function(e){return e=H(e),this.isValid()?this[e+"s"]():NaN},qn.milliseconds=Fn,qn.seconds=Ln,qn.minutes=Nn,qn.hours=Gn,qn.days=Vn,qn.weeks=function(){return S(this.days()/7)},qn.months=En,qn.years=In,qn.humanize=function(e){if(!this.isValid())return this.localeData().invalidDate();var t,n,s,i,r,a,o,u,l,h,d,c=this.localeData(),f=(n=!e,s=c,i=jt(t=this).abs(),r=An(i.as("s")),a=An(i.as("m")),o=An(i.as("h")),u=An(i.as("d")),l=An(i.as("M")),h=An(i.as("y")),(d=r<=jn.ss&&["s",r]||r<jn.s&&["ss",r]||a<=1&&["m"]||a<jn.m&&["mm",a]||o<=1&&["h"]||o<jn.h&&["hh",o]||u<=1&&["d"]||u<jn.d&&["dd",u]||l<=1&&["M"]||l<jn.M&&["MM",l]||h<=1&&["y"]||["yy",h])[2]=n,d[3]=0<+t,d[4]=s,function(e,t,n,s,i){return i.relativeTime(t||1,!!n,e,s)}.apply(null,d));return e&&(f=c.pastFuture(+this,f)),c.postformat(f)},qn.toISOString=$n,qn.toString=$n,qn.toJSON=$n,qn.locale=Xt,qn.localeData=en,qn.toIsoString=n("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",$n),qn.lang=Kt,I("X",0,0,"unix"),I("x",0,0,"valueOf"),ue("x",se),ue("X",/[+-]?\d+(\.\d{1,3})?/),ce("X",function(e,t,n){n._d=new Date(1e3*parseFloat(e,10))}),ce("x",function(e,t,n){n._d=new Date(D(e))}),c.version="2.24.0",e=bt,c.fn=mn,c.min=function(){return Wt("isBefore",[].slice.call(arguments,0))},c.max=function(){return Wt("isAfter",[].slice.call(arguments,0))},c.now=function(){return Date.now?Date.now():+new Date},c.utc=y,c.unix=function(e){return bt(1e3*e)},c.months=function(e,t){return vn(e,t,"months")},c.isDate=d,c.locale=ut,c.invalid=p,c.duration=jt,c.isMoment=k,c.weekdays=function(e,t,n){return pn(e,t,n,"weekdays")},c.parseZone=function(){return bt.apply(null,arguments).parseZone()},c.localeData=ht,c.isDuration=Rt,c.monthsShort=function(e,t){return vn(e,t,"monthsShort")},c.weekdaysMin=function(e,t,n){return pn(e,t,n,"weekdaysMin")},c.defineLocale=lt,c.updateLocale=function(e,t){if(null!=t){var n,s,i=st;null!=(s=ot(e))&&(i=s._config),(n=new P(t=x(i,t))).parentLocale=it[e],it[e]=n,ut(e)}else null!=it[e]&&(null!=it[e].parentLocale?it[e]=it[e].parentLocale:null!=it[e]&&delete it[e]);return it[e]},c.locales=function(){return s(it)},c.weekdaysShort=function(e,t,n){return pn(e,t,n,"weekdaysShort")},c.normalizeUnits=H,c.relativeTimeRounding=function(e){return void 0===e?An:"function"==typeof e&&(An=e,!0)},c.relativeTimeThreshold=function(e,t){return void 0!==jn[e]&&(void 0===t?jn[e]:(jn[e]=t,"s"===e&&(jn.ss=t-1),!0))},c.calendarFormat=function(e,t){var n=e.diff(t,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},c.prototype=mn,c.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},c});!function(a){"use strict";if("function"==typeof define&&define.amd)define(["jquery","moment"],a);else if("object"==typeof exports)module.exports=a(require("jquery"),require("moment"));else{if("undefined"==typeof jQuery)throw"bootstrap-datetimepicker requires jQuery to be loaded first";if("undefined"==typeof moment)throw"bootstrap-datetimepicker requires Moment.js to be loaded first";a(jQuery,moment)}}(function(a,b){"use strict";if(!b)throw new Error("bootstrap-datetimepicker requires Moment.js to be loaded first");var c=function(c,d){var e,f,g,h,i,j,k,l={},m=!0,n=!1,o=!1,p=0,q=[{clsName:"days",navFnc:"M",navStep:1},{clsName:"months",navFnc:"y",navStep:1},{clsName:"years",navFnc:"y",navStep:10},{clsName:"decades",navFnc:"y",navStep:100}],r=["days","months","years","decades"],s=["top","bottom","auto"],t=["left","right","auto"],u=["default","top","bottom"],v={up:38,38:"up",down:40,40:"down",left:37,37:"left",right:39,39:"right",tab:9,9:"tab",escape:27,27:"escape",enter:13,13:"enter",pageUp:33,33:"pageUp",pageDown:34,34:"pageDown",shift:16,16:"shift",control:17,17:"control",space:32,32:"space",t:84,84:"t",delete:46,46:"delete"},w={},x=function(){return void 0!==b.tz&&void 0!==d.timeZone&&null!==d.timeZone&&""!==d.timeZone},y=function(a){var c;return c=void 0===a||null===a?b():b.isDate(a)||b.isMoment(a)?b(a):x()?b.tz(a,j,d.useStrict,d.timeZone):b(a,j,d.useStrict),x()&&c.tz(d.timeZone),c},z=function(a){if("string"!=typeof a||a.length>1)throw new TypeError("isEnabled expects a single character string parameter");switch(a){case"y":return i.indexOf("Y")!==-1;case"M":return i.indexOf("M")!==-1;case"d":return i.toLowerCase().indexOf("d")!==-1;case"h":case"H":return i.toLowerCase().indexOf("h")!==-1;case"m":return i.indexOf("m")!==-1;case"s":return i.indexOf("s")!==-1;default:return!1}},A=function(){return z("h")||z("m")||z("s")},B=function(){return z("y")||z("M")||z("d")},C=function(){var b=a("<thead>").append(a("<tr>").append(a("<th>").addClass("prev").attr("data-action","previous").append(a("<span>").addClass(d.icons.previous))).append(a("<th>").addClass("picker-switch").attr("data-action","pickerSwitch").attr("colspan",d.calendarWeeks?"6":"5")).append(a("<th>").addClass("next").attr("data-action","next").append(a("<span>").addClass(d.icons.next)))),c=a("<tbody>").append(a("<tr>").append(a("<td>").attr("colspan",d.calendarWeeks?"8":"7")));return[a("<div>").addClass("datepicker-days").append(a("<table>").addClass("table-condensed").append(b).append(a("<tbody>"))),a("<div>").addClass("datepicker-months").append(a("<table>").addClass("table-condensed").append(b.clone()).append(c.clone())),a("<div>").addClass("datepicker-years").append(a("<table>").addClass("table-condensed").append(b.clone()).append(c.clone())),a("<div>").addClass("datepicker-decades").append(a("<table>").addClass("table-condensed").append(b.clone()).append(c.clone()))]},D=function(){var b=a("<tr>"),c=a("<tr>"),e=a("<tr>");return z("h")&&(b.append(a("<td>").append(a("<a>").attr({href:"#",tabindex:"-1",title:d.tooltips.incrementHour}).addClass("btn").attr("data-action","incrementHours").append(a("<span>").addClass(d.icons.up)))),c.append(a("<td>").append(a("<span>").addClass("timepicker-hour").attr({"data-time-component":"hours",title:d.tooltips.pickHour}).attr("data-action","showHours"))),e.append(a("<td>").append(a("<a>").attr({href:"#",tabindex:"-1",title:d.tooltips.decrementHour}).addClass("btn").attr("data-action","decrementHours").append(a("<span>").addClass(d.icons.down))))),z("m")&&(z("h")&&(b.append(a("<td>").addClass("separator")),c.append(a("<td>").addClass("separator").html(":")),e.append(a("<td>").addClass("separator"))),b.append(a("<td>").append(a("<a>").attr({href:"#",tabindex:"-1",title:d.tooltips.incrementMinute}).addClass("btn").attr("data-action","incrementMinutes").append(a("<span>").addClass(d.icons.up)))),c.append(a("<td>").append(a("<span>").addClass("timepicker-minute").attr({"data-time-component":"minutes",title:d.tooltips.pickMinute}).attr("data-action","showMinutes"))),e.append(a("<td>").append(a("<a>").attr({href:"#",tabindex:"-1",title:d.tooltips.decrementMinute}).addClass("btn").attr("data-action","decrementMinutes").append(a("<span>").addClass(d.icons.down))))),z("s")&&(z("m")&&(b.append(a("<td>").addClass("separator")),c.append(a("<td>").addClass("separator").html(":")),e.append(a("<td>").addClass("separator"))),b.append(a("<td>").append(a("<a>").attr({href:"#",tabindex:"-1",title:d.tooltips.incrementSecond}).addClass("btn").attr("data-action","incrementSeconds").append(a("<span>").addClass(d.icons.up)))),c.append(a("<td>").append(a("<span>").addClass("timepicker-second").attr({"data-time-component":"seconds",title:d.tooltips.pickSecond}).attr("data-action","showSeconds"))),e.append(a("<td>").append(a("<a>").attr({href:"#",tabindex:"-1",title:d.tooltips.decrementSecond}).addClass("btn").attr("data-action","decrementSeconds").append(a("<span>").addClass(d.icons.down))))),h||(b.append(a("<td>").addClass("separator")),c.append(a("<td>").append(a("<button>").addClass("btn btn-primary").attr({"data-action":"togglePeriod",tabindex:"-1",title:d.tooltips.togglePeriod}))),e.append(a("<td>").addClass("separator"))),a("<div>").addClass("timepicker-picker").append(a("<table>").addClass("table-condensed").append([b,c,e]))},E=function(){var b=a("<div>").addClass("timepicker-hours").append(a("<table>").addClass("table-condensed")),c=a("<div>").addClass("timepicker-minutes").append(a("<table>").addClass("table-condensed")),d=a("<div>").addClass("timepicker-seconds").append(a("<table>").addClass("table-condensed")),e=[D()];return z("h")&&e.push(b),z("m")&&e.push(c),z("s")&&e.push(d),e},F=function(){var b=[];return d.showTodayButton&&b.push(a("<td>").append(a("<a>").attr({"data-action":"today",title:d.tooltips.today}).append(a("<span>").addClass(d.icons.today)))),!d.sideBySide&&B()&&A()&&b.push(a("<td>").append(a("<a>").attr({"data-action":"togglePicker",title:d.tooltips.selectTime}).append(a("<span>").addClass(d.icons.time)))),d.showClear&&b.push(a("<td>").append(a("<a>").attr({"data-action":"clear",title:d.tooltips.clear}).append(a("<span>").addClass(d.icons.clear)))),d.showClose&&b.push(a("<td>").append(a("<a>").attr({"data-action":"close",title:d.tooltips.close}).append(a("<span>").addClass(d.icons.close)))),a("<table>").addClass("table-condensed").append(a("<tbody>").append(a("<tr>").append(b)))},G=function(){var b=a("<div>").addClass("bootstrap-datetimepicker-widget dropdown-menu"),c=a("<div>").addClass("datepicker").append(C()),e=a("<div>").addClass("timepicker").append(E()),f=a("<ul>").addClass("list-unstyled"),g=a("<li>").addClass("picker-switch"+(d.collapse?" accordion-toggle":"")).append(F());return d.inline&&b.removeClass("dropdown-menu"),h&&b.addClass("usetwentyfour"),z("s")&&!h&&b.addClass("wider"),d.sideBySide&&B()&&A()?(b.addClass("timepicker-sbs"),"top"===d.toolbarPlacement&&b.append(g),b.append(a("<div>").addClass("row").append(c.addClass("col-md-6")).append(e.addClass("col-md-6"))),"bottom"===d.toolbarPlacement&&b.append(g),b):("top"===d.toolbarPlacement&&f.append(g),B()&&f.append(a("<li>").addClass(d.collapse&&A()?"collapse in":"").append(c)),"default"===d.toolbarPlacement&&f.append(g),A()&&f.append(a("<li>").addClass(d.collapse&&B()?"collapse":"").append(e)),"bottom"===d.toolbarPlacement&&f.append(g),b.append(f))},H=function(){var b,e={};return b=c.is("input")||d.inline?c.data():c.find("input").data(),b.dateOptions&&b.dateOptions instanceof Object&&(e=a.extend(!0,e,b.dateOptions)),a.each(d,function(a){var c="date"+a.charAt(0).toUpperCase()+a.slice(1);void 0!==b[c]&&(e[a]=b[c])}),e},I=function(){var b,e=(n||c).position(),f=(n||c).offset(),g=d.widgetPositioning.vertical,h=d.widgetPositioning.horizontal;if(d.widgetParent)b=d.widgetParent.append(o);else if(c.is("input"))b=c.after(o).parent();else{if(d.inline)return void(b=c.append(o));b=c,c.children().first().after(o)}if("auto"===g&&(g=f.top+1.5*o.height()>=a(window).height()+a(window).scrollTop()&&o.height()+c.outerHeight()<f.top?"top":"bottom"),"auto"===h&&(h=b.width()<f.left+o.outerWidth()/2&&f.left+o.outerWidth()>a(window).width()?"right":"left"),"top"===g?o.addClass("top").removeClass("bottom"):o.addClass("bottom").removeClass("top"),"right"===h?o.addClass("pull-right"):o.removeClass("pull-right"),"static"===b.css("position")&&(b=b.parents().filter(function(){return"static"!==a(this).css("position")}).first()),0===b.length)throw new Error("datetimepicker component should be placed within a non-static positioned container");o.css({top:"top"===g?"auto":e.top+c.outerHeight(),bottom:"top"===g?b.outerHeight()-(b===c?0:e.top):"auto",left:"left"===h?b===c?0:e.left:"auto",right:"left"===h?"auto":b.outerWidth()-c.outerWidth()-(b===c?0:e.left)})},J=function(a){"dp.change"===a.type&&(a.date&&a.date.isSame(a.oldDate)||!a.date&&!a.oldDate)||c.trigger(a)},K=function(a){"y"===a&&(a="YYYY"),J({type:"dp.update",change:a,viewDate:f.clone()})},L=function(a){o&&(a&&(k=Math.max(p,Math.min(3,k+a))),o.find(".datepicker > div").hide().filter(".datepicker-"+q[k].clsName).show())},M=function(){var b=a("<tr>"),c=f.clone().startOf("w").startOf("d");for(d.calendarWeeks===!0&&b.append(a("<th>").addClass("cw").text("#"));c.isBefore(f.clone().endOf("w"));)b.append(a("<th>").addClass("dow").text(c.format("dd"))),c.add(1,"d");o.find(".datepicker-days thead").append(b)},N=function(a){return d.disabledDates[a.format("YYYY-MM-DD")]===!0},O=function(a){return d.enabledDates[a.format("YYYY-MM-DD")]===!0},P=function(a){return d.disabledHours[a.format("H")]===!0},Q=function(a){return d.enabledHours[a.format("H")]===!0},R=function(b,c){if(!b.isValid())return!1;if(d.disabledDates&&"d"===c&&N(b))return!1;if(d.enabledDates&&"d"===c&&!O(b))return!1;if(d.minDate&&b.isBefore(d.minDate,c))return!1;if(d.maxDate&&b.isAfter(d.maxDate,c))return!1;if(d.daysOfWeekDisabled&&"d"===c&&d.daysOfWeekDisabled.indexOf(b.day())!==-1)return!1;if(d.disabledHours&&("h"===c||"m"===c||"s"===c)&&P(b))return!1;if(d.enabledHours&&("h"===c||"m"===c||"s"===c)&&!Q(b))return!1;if(d.disabledTimeIntervals&&("h"===c||"m"===c||"s"===c)){var e=!1;if(a.each(d.disabledTimeIntervals,function(){if(b.isBetween(this[0],this[1]))return e=!0,!1}),e)return!1}return!0},S=function(){for(var b=[],c=f.clone().startOf("y").startOf("d");c.isSame(f,"y");)b.push(a("<span>").attr("data-action","selectMonth").addClass("month").text(c.format("MMM"))),c.add(1,"M");o.find(".datepicker-months td").empty().append(b)},T=function(){var b=o.find(".datepicker-months"),c=b.find("th"),g=b.find("tbody").find("span");c.eq(0).find("span").attr("title",d.tooltips.prevYear),c.eq(1).attr("title",d.tooltips.selectYear),c.eq(2).find("span").attr("title",d.tooltips.nextYear),b.find(".disabled").removeClass("disabled"),R(f.clone().subtract(1,"y"),"y")||c.eq(0).addClass("disabled"),c.eq(1).text(f.year()),R(f.clone().add(1,"y"),"y")||c.eq(2).addClass("disabled"),g.removeClass("active"),e.isSame(f,"y")&&!m&&g.eq(e.month()).addClass("active"),g.each(function(b){R(f.clone().month(b),"M")||a(this).addClass("disabled")})},U=function(){var a=o.find(".datepicker-years"),b=a.find("th"),c=f.clone().subtract(5,"y"),g=f.clone().add(6,"y"),h="";for(b.eq(0).find("span").attr("title",d.tooltips.prevDecade),b.eq(1).attr("title",d.tooltips.selectDecade),b.eq(2).find("span").attr("title",d.tooltips.nextDecade),a.find(".disabled").removeClass("disabled"),d.minDate&&d.minDate.isAfter(c,"y")&&b.eq(0).addClass("disabled"),b.eq(1).text(c.year()+"-"+g.year()),d.maxDate&&d.maxDate.isBefore(g,"y")&&b.eq(2).addClass("disabled");!c.isAfter(g,"y");)h+='<span data-action="selectYear" class="year'+(c.isSame(e,"y")&&!m?" active":"")+(R(c,"y")?"":" disabled")+'">'+c.year()+"</span>",c.add(1,"y");a.find("td").html(h)},V=function(){var a,c=o.find(".datepicker-decades"),g=c.find("th"),h=b({y:f.year()-f.year()%100-1}),i=h.clone().add(100,"y"),j=h.clone(),k=!1,l=!1,m="";for(g.eq(0).find("span").attr("title",d.tooltips.prevCentury),g.eq(2).find("span").attr("title",d.tooltips.nextCentury),c.find(".disabled").removeClass("disabled"),(h.isSame(b({y:1900}))||d.minDate&&d.minDate.isAfter(h,"y"))&&g.eq(0).addClass("disabled"),g.eq(1).text(h.year()+"-"+i.year()),(h.isSame(b({y:2e3}))||d.maxDate&&d.maxDate.isBefore(i,"y"))&&g.eq(2).addClass("disabled");!h.isAfter(i,"y");)a=h.year()+12,k=d.minDate&&d.minDate.isAfter(h,"y")&&d.minDate.year()<=a,l=d.maxDate&&d.maxDate.isAfter(h,"y")&&d.maxDate.year()<=a,m+='<span data-action="selectDecade" class="decade'+(e.isAfter(h)&&e.year()<=a?" active":"")+(R(h,"y")||k||l?"":" disabled")+'" data-selection="'+(h.year()+6)+'">'+(h.year()+1)+" - "+(h.year()+12)+"</span>",h.add(12,"y");m+="<span></span><span></span><span></span>",c.find("td").html(m),g.eq(1).text(j.year()+1+"-"+h.year())},W=function(){var b,c,g,h=o.find(".datepicker-days"),i=h.find("th"),j=[],k=[];if(B()){for(i.eq(0).find("span").attr("title",d.tooltips.prevMonth),i.eq(1).attr("title",d.tooltips.selectMonth),i.eq(2).find("span").attr("title",d.tooltips.nextMonth),h.find(".disabled").removeClass("disabled"),i.eq(1).text(f.format(d.dayViewHeaderFormat)),R(f.clone().subtract(1,"M"),"M")||i.eq(0).addClass("disabled"),R(f.clone().add(1,"M"),"M")||i.eq(2).addClass("disabled"),b=f.clone().startOf("M").startOf("w").startOf("d"),g=0;g<42;g++)0===b.weekday()&&(c=a("<tr>"),d.calendarWeeks&&c.append('<td class="cw">'+b.week()+"</td>"),j.push(c)),k=["day"],b.isBefore(f,"M")&&k.push("old"),b.isAfter(f,"M")&&k.push("new"),b.isSame(e,"d")&&!m&&k.push("active"),R(b,"d")||k.push("disabled"),b.isSame(y(),"d")&&k.push("today"),0!==b.day()&&6!==b.day()||k.push("weekend"),J({type:"dp.classify",date:b,classNames:k}),c.append('<td data-action="selectDay" data-day="'+b.format("L")+'" class="'+k.join(" ")+'">'+b.date()+"</td>"),b.add(1,"d");h.find("tbody").empty().append(j),T(),U(),V()}},X=function(){var b=o.find(".timepicker-hours table"),c=f.clone().startOf("d"),d=[],e=a("<tr>");for(f.hour()>11&&!h&&c.hour(12);c.isSame(f,"d")&&(h||f.hour()<12&&c.hour()<12||f.hour()>11);)c.hour()%4===0&&(e=a("<tr>"),d.push(e)),e.append('<td data-action="selectHour" class="hour'+(R(c,"h")?"":" disabled")+'">'+c.format(h?"HH":"hh")+"</td>"),c.add(1,"h");b.empty().append(d)},Y=function(){for(var b=o.find(".timepicker-minutes table"),c=f.clone().startOf("h"),e=[],g=a("<tr>"),h=1===d.stepping?5:d.stepping;f.isSame(c,"h");)c.minute()%(4*h)===0&&(g=a("<tr>"),e.push(g)),g.append('<td data-action="selectMinute" class="minute'+(R(c,"m")?"":" disabled")+'">'+c.format("mm")+"</td>"),c.add(h,"m");b.empty().append(e)},Z=function(){for(var b=o.find(".timepicker-seconds table"),c=f.clone().startOf("m"),d=[],e=a("<tr>");f.isSame(c,"m");)c.second()%20===0&&(e=a("<tr>"),d.push(e)),e.append('<td data-action="selectSecond" class="second'+(R(c,"s")?"":" disabled")+'">'+c.format("ss")+"</td>"),c.add(5,"s");b.empty().append(d)},$=function(){var a,b,c=o.find(".timepicker span[data-time-component]");h||(a=o.find(".timepicker [data-action=togglePeriod]"),b=e.clone().add(e.hours()>=12?-12:12,"h"),a.text(e.format("A")),R(b,"h")?a.removeClass("disabled"):a.addClass("disabled")),c.filter("[data-time-component=hours]").text(e.format(h?"HH":"hh")),c.filter("[data-time-component=minutes]").text(e.format("mm")),c.filter("[data-time-component=seconds]").text(e.format("ss")),X(),Y(),Z()},_=function(){o&&(W(),$())},aa=function(a){var b=m?null:e;if(!a)return m=!0,g.val(""),c.data("date",""),J({type:"dp.change",date:!1,oldDate:b}),void _();if(a=a.clone().locale(d.locale),x()&&a.tz(d.timeZone),1!==d.stepping)for(a.minutes(Math.round(a.minutes()/d.stepping)*d.stepping).seconds(0);d.minDate&&a.isBefore(d.minDate);)a.add(d.stepping,"minutes");R(a)?(e=a,f=e.clone(),g.val(e.format(i)),c.data("date",e.format(i)),m=!1,_(),J({type:"dp.change",date:e.clone(),oldDate:b})):(d.keepInvalid?J({type:"dp.change",date:a,oldDate:b}):g.val(m?"":e.format(i)),J({type:"dp.error",date:a,oldDate:b}))},ba=function(){var b=!1;return o?(o.find(".collapse").each(function(){var c=a(this).data("collapse");return!c||!c.transitioning||(b=!0,!1)}),b?l:(n&&n.hasClass("btn")&&n.toggleClass("active"),o.hide(),a(window).off("resize",I),o.off("click","[data-action]"),o.off("mousedown",!1),o.remove(),o=!1,J({type:"dp.hide",date:e.clone()}),g.blur(),f=e.clone(),l)):l},ca=function(){aa(null)},da=function(a){return void 0===d.parseInputDate?(!b.isMoment(a)||a instanceof Date)&&(a=y(a)):a=d.parseInputDate(a),a},ea={next:function(){var a=q[k].navFnc;f.add(q[k].navStep,a),W(),K(a)},previous:function(){var a=q[k].navFnc;f.subtract(q[k].navStep,a),W(),K(a)},pickerSwitch:function(){L(1)},selectMonth:function(b){var c=a(b.target).closest("tbody").find("span").index(a(b.target));f.month(c),k===p?(aa(e.clone().year(f.year()).month(f.month())),d.inline||ba()):(L(-1),W()),K("M")},selectYear:function(b){var c=parseInt(a(b.target).text(),10)||0;f.year(c),k===p?(aa(e.clone().year(f.year())),d.inline||ba()):(L(-1),W()),K("YYYY")},selectDecade:function(b){var c=parseInt(a(b.target).data("selection"),10)||0;f.year(c),k===p?(aa(e.clone().year(f.year())),d.inline||ba()):(L(-1),W()),K("YYYY")},selectDay:function(b){var c=f.clone();a(b.target).is(".old")&&c.subtract(1,"M"),a(b.target).is(".new")&&c.add(1,"M"),aa(c.date(parseInt(a(b.target).text(),10))),A()||d.keepOpen||d.inline||ba()},incrementHours:function(){var a=e.clone().add(1,"h");R(a,"h")&&aa(a)},incrementMinutes:function(){var a=e.clone().add(d.stepping,"m");R(a,"m")&&aa(a)},incrementSeconds:function(){var a=e.clone().add(1,"s");R(a,"s")&&aa(a)},decrementHours:function(){var a=e.clone().subtract(1,"h");R(a,"h")&&aa(a)},decrementMinutes:function(){var a=e.clone().subtract(d.stepping,"m");R(a,"m")&&aa(a)},decrementSeconds:function(){var a=e.clone().subtract(1,"s");R(a,"s")&&aa(a)},togglePeriod:function(){aa(e.clone().add(e.hours()>=12?-12:12,"h"))},togglePicker:function(b){var c,e=a(b.target),f=e.closest("ul"),g=f.find(".in"),h=f.find(".collapse:not(.in)");if(g&&g.length){if(c=g.data("collapse"),c&&c.transitioning)return;g.collapse?(g.collapse("hide"),h.collapse("show")):(g.removeClass("in"),h.addClass("in")),e.is("span")?e.toggleClass(d.icons.time+" "+d.icons.date):e.find("span").toggleClass(d.icons.time+" "+d.icons.date)}},showPicker:function(){o.find(".timepicker > div:not(.timepicker-picker)").hide(),o.find(".timepicker .timepicker-picker").show()},showHours:function(){o.find(".timepicker .timepicker-picker").hide(),o.find(".timepicker .timepicker-hours").show()},showMinutes:function(){o.find(".timepicker .timepicker-picker").hide(),o.find(".timepicker .timepicker-minutes").show()},showSeconds:function(){o.find(".timepicker .timepicker-picker").hide(),o.find(".timepicker .timepicker-seconds").show()},selectHour:function(b){var c=parseInt(a(b.target).text(),10);h||(e.hours()>=12?12!==c&&(c+=12):12===c&&(c=0)),aa(e.clone().hours(c)),ea.showPicker.call(l)},selectMinute:function(b){aa(e.clone().minutes(parseInt(a(b.target).text(),10))),ea.showPicker.call(l)},selectSecond:function(b){aa(e.clone().seconds(parseInt(a(b.target).text(),10))),ea.showPicker.call(l)},clear:ca,today:function(){var a=y();R(a,"d")&&aa(a)},close:ba},fa=function(b){return!a(b.currentTarget).is(".disabled")&&(ea[a(b.currentTarget).data("action")].apply(l,arguments),!1)},ga=function(){var b,c={year:function(a){return a.month(0).date(1).hours(0).seconds(0).minutes(0)},month:function(a){return a.date(1).hours(0).seconds(0).minutes(0)},day:function(a){return a.hours(0).seconds(0).minutes(0)},hour:function(a){return a.seconds(0).minutes(0)},minute:function(a){return a.seconds(0)}};return g.prop("disabled")||!d.ignoreReadonly&&g.prop("readonly")||o?l:(void 0!==g.val()&&0!==g.val().trim().length?aa(da(g.val().trim())):m&&d.useCurrent&&(d.inline||g.is("input")&&0===g.val().trim().length)&&(b=y(),"string"==typeof d.useCurrent&&(b=c[d.useCurrent](b)),aa(b)),o=G(),M(),S(),o.find(".timepicker-hours").hide(),o.find(".timepicker-minutes").hide(),o.find(".timepicker-seconds").hide(),_(),L(),a(window).on("resize",I),o.on("click","[data-action]",fa),o.on("mousedown",!1),n&&n.hasClass("btn")&&n.toggleClass("active"),I(),o.show(),d.focusOnShow&&!g.is(":focus")&&g.focus(),J({type:"dp.show"}),l)},ha=function(){return o?ba():ga()},ia=function(a){var b,c,e,f,g=null,h=[],i={},j=a.which,k="p";w[j]=k;for(b in w)w.hasOwnProperty(b)&&w[b]===k&&(h.push(b),parseInt(b,10)!==j&&(i[b]=!0));for(b in d.keyBinds)if(d.keyBinds.hasOwnProperty(b)&&"function"==typeof d.keyBinds[b]&&(e=b.split(" "),e.length===h.length&&v[j]===e[e.length-1])){for(f=!0,c=e.length-2;c>=0;c--)if(!(v[e[c]]in i)){f=!1;break}if(f){g=d.keyBinds[b];break}}g&&(g.call(l,o),a.stopPropagation(),a.preventDefault())},ja=function(a){w[a.which]="r",a.stopPropagation(),a.preventDefault()},ka=function(b){var c=a(b.target).val().trim(),d=c?da(c):null;return aa(d),b.stopImmediatePropagation(),!1},la=function(){g.on({change:ka,blur:d.debug?"":ba,keydown:ia,keyup:ja,focus:d.allowInputToggle?ga:""}),c.is("input")?g.on({focus:ga}):n&&(n.on("click",ha),n.on("mousedown",!1))},ma=function(){g.off({change:ka,blur:blur,keydown:ia,keyup:ja,focus:d.allowInputToggle?ba:""}),c.is("input")?g.off({focus:ga}):n&&(n.off("click",ha),n.off("mousedown",!1))},na=function(b){var c={};return a.each(b,function(){var a=da(this);a.isValid()&&(c[a.format("YYYY-MM-DD")]=!0)}),!!Object.keys(c).length&&c},oa=function(b){var c={};return a.each(b,function(){c[this]=!0}),!!Object.keys(c).length&&c},pa=function(){var a=d.format||"L LT";i=a.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,function(a){var b=e.localeData().longDateFormat(a)||a;return b.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,function(a){return e.localeData().longDateFormat(a)||a})}),j=d.extraFormats?d.extraFormats.slice():[],j.indexOf(a)<0&&j.indexOf(i)<0&&j.push(i),h=i.toLowerCase().indexOf("a")<1&&i.replace(/\[.*?\]/g,"").indexOf("h")<1,z("y")&&(p=2),z("M")&&(p=1),z("d")&&(p=0),k=Math.max(p,k),m||aa(e)};if(l.destroy=function(){ba(),ma(),c.removeData("DateTimePicker"),c.removeData("date")},l.toggle=ha,l.show=ga,l.hide=ba,l.disable=function(){return ba(),n&&n.hasClass("btn")&&n.addClass("disabled"),g.prop("disabled",!0),l},l.enable=function(){return n&&n.hasClass("btn")&&n.removeClass("disabled"),g.prop("disabled",!1),l},l.ignoreReadonly=function(a){if(0===arguments.length)return d.ignoreReadonly;if("boolean"!=typeof a)throw new TypeError("ignoreReadonly () expects a boolean parameter");return d.ignoreReadonly=a,l},l.options=function(b){if(0===arguments.length)return a.extend(!0,{},d);if(!(b instanceof Object))throw new TypeError("options() options parameter should be an object");return a.extend(!0,d,b),a.each(d,function(a,b){if(void 0===l[a])throw new TypeError("option "+a+" is not recognized!");l[a](b)}),l},l.date=function(a){if(0===arguments.length)return m?null:e.clone();if(!(null===a||"string"==typeof a||b.isMoment(a)||a instanceof Date))throw new TypeError("date() parameter must be one of [null, string, moment or Date]");return aa(null===a?null:da(a)),l},l.format=function(a){if(0===arguments.length)return d.format;if("string"!=typeof a&&("boolean"!=typeof a||a!==!1))throw new TypeError("format() expects a string or boolean:false parameter "+a);return d.format=a,i&&pa(),l},l.timeZone=function(a){if(0===arguments.length)return d.timeZone;if("string"!=typeof a)throw new TypeError("newZone() expects a string parameter");return d.timeZone=a,l},l.dayViewHeaderFormat=function(a){if(0===arguments.length)return d.dayViewHeaderFormat;if("string"!=typeof a)throw new TypeError("dayViewHeaderFormat() expects a string parameter");return d.dayViewHeaderFormat=a,l},l.extraFormats=function(a){if(0===arguments.length)return d.extraFormats;if(a!==!1&&!(a instanceof Array))throw new TypeError("extraFormats() expects an array or false parameter");return d.extraFormats=a,j&&pa(),l},l.disabledDates=function(b){if(0===arguments.length)return d.disabledDates?a.extend({},d.disabledDates):d.disabledDates;if(!b)return d.disabledDates=!1,_(),l;if(!(b instanceof Array))throw new TypeError("disabledDates() expects an array parameter");return d.disabledDates=na(b),d.enabledDates=!1,_(),l},l.enabledDates=function(b){if(0===arguments.length)return d.enabledDates?a.extend({},d.enabledDates):d.enabledDates;if(!b)return d.enabledDates=!1,_(),l;if(!(b instanceof Array))throw new TypeError("enabledDates() expects an array parameter");return d.enabledDates=na(b),d.disabledDates=!1,_(),l},l.daysOfWeekDisabled=function(a){if(0===arguments.length)return d.daysOfWeekDisabled.splice(0);if("boolean"==typeof a&&!a)return d.daysOfWeekDisabled=!1,_(),l;if(!(a instanceof Array))throw new TypeError("daysOfWeekDisabled() expects an array parameter");if(d.daysOfWeekDisabled=a.reduce(function(a,b){return b=parseInt(b,10),b>6||b<0||isNaN(b)?a:(a.indexOf(b)===-1&&a.push(b),a)},[]).sort(),d.useCurrent&&!d.keepInvalid){for(var b=0;!R(e,"d");){if(e.add(1,"d"),31===b)throw"Tried 31 times to find a valid date";b++}aa(e)}return _(),l},l.maxDate=function(a){if(0===arguments.length)return d.maxDate?d.maxDate.clone():d.maxDate;if("boolean"==typeof a&&a===!1)return d.maxDate=!1,_(),l;"string"==typeof a&&("now"!==a&&"moment"!==a||(a=y()));var b=da(a);if(!b.isValid())throw new TypeError("maxDate() Could not parse date parameter: "+a);if(d.minDate&&b.isBefore(d.minDate))throw new TypeError("maxDate() date parameter is before options.minDate: "+b.format(i));return d.maxDate=b,d.useCurrent&&!d.keepInvalid&&e.isAfter(a)&&aa(d.maxDate),f.isAfter(b)&&(f=b.clone().subtract(d.stepping,"m")),_(),l},l.minDate=function(a){if(0===arguments.length)return d.minDate?d.minDate.clone():d.minDate;if("boolean"==typeof a&&a===!1)return d.minDate=!1,_(),l;"string"==typeof a&&("now"!==a&&"moment"!==a||(a=y()));var b=da(a);if(!b.isValid())throw new TypeError("minDate() Could not parse date parameter: "+a);if(d.maxDate&&b.isAfter(d.maxDate))throw new TypeError("minDate() date parameter is after options.maxDate: "+b.format(i));return d.minDate=b,d.useCurrent&&!d.keepInvalid&&e.isBefore(a)&&aa(d.minDate),f.isBefore(b)&&(f=b.clone().add(d.stepping,"m")),_(),l},l.defaultDate=function(a){if(0===arguments.length)return d.defaultDate?d.defaultDate.clone():d.defaultDate;if(!a)return d.defaultDate=!1,l;"string"==typeof a&&(a="now"===a||"moment"===a?y():y(a));var b=da(a);if(!b.isValid())throw new TypeError("defaultDate() Could not parse date parameter: "+a);if(!R(b))throw new TypeError("defaultDate() date passed is invalid according to component setup validations");return d.defaultDate=b,(d.defaultDate&&d.inline||""===g.val().trim())&&aa(d.defaultDate),l},l.locale=function(a){if(0===arguments.length)return d.locale;if(!b.localeData(a))throw new TypeError("locale() locale "+a+" is not loaded from moment locales!");return d.locale=a,e.locale(d.locale),f.locale(d.locale),i&&pa(),o&&(ba(),ga()),l},l.stepping=function(a){return 0===arguments.length?d.stepping:(a=parseInt(a,10),(isNaN(a)||a<1)&&(a=1),d.stepping=a,l)},l.useCurrent=function(a){var b=["year","month","day","hour","minute"];if(0===arguments.length)return d.useCurrent;if("boolean"!=typeof a&&"string"!=typeof a)throw new TypeError("useCurrent() expects a boolean or string parameter");if("string"==typeof a&&b.indexOf(a.toLowerCase())===-1)throw new TypeError("useCurrent() expects a string parameter of "+b.join(", "));return d.useCurrent=a,l},l.collapse=function(a){if(0===arguments.length)return d.collapse;if("boolean"!=typeof a)throw new TypeError("collapse() expects a boolean parameter");return d.collapse===a?l:(d.collapse=a,o&&(ba(),ga()),l)},l.icons=function(b){if(0===arguments.length)return a.extend({},d.icons);if(!(b instanceof Object))throw new TypeError("icons() expects parameter to be an Object");return a.extend(d.icons,b),o&&(ba(),ga()),l},l.tooltips=function(b){if(0===arguments.length)return a.extend({},d.tooltips);if(!(b instanceof Object))throw new TypeError("tooltips() expects parameter to be an Object");return a.extend(d.tooltips,b),o&&(ba(),ga()),l},l.useStrict=function(a){if(0===arguments.length)return d.useStrict;if("boolean"!=typeof a)throw new TypeError("useStrict() expects a boolean parameter");return d.useStrict=a,l},l.sideBySide=function(a){if(0===arguments.length)return d.sideBySide;if("boolean"!=typeof a)throw new TypeError("sideBySide() expects a boolean parameter");return d.sideBySide=a,o&&(ba(),ga()),l},l.viewMode=function(a){if(0===arguments.length)return d.viewMode;if("string"!=typeof a)throw new TypeError("viewMode() expects a string parameter");if(r.indexOf(a)===-1)throw new TypeError("viewMode() parameter must be one of ("+r.join(", ")+") value");return d.viewMode=a,k=Math.max(r.indexOf(a),p),L(),l},l.toolbarPlacement=function(a){if(0===arguments.length)return d.toolbarPlacement;if("string"!=typeof a)throw new TypeError("toolbarPlacement() expects a string parameter");if(u.indexOf(a)===-1)throw new TypeError("toolbarPlacement() parameter must be one of ("+u.join(", ")+") value");return d.toolbarPlacement=a,o&&(ba(),ga()),l},l.widgetPositioning=function(b){if(0===arguments.length)return a.extend({},d.widgetPositioning);if("[object Object]"!=={}.toString.call(b))throw new TypeError("widgetPositioning() expects an object variable");if(b.horizontal){if("string"!=typeof b.horizontal)throw new TypeError("widgetPositioning() horizontal variable must be a string");if(b.horizontal=b.horizontal.toLowerCase(),t.indexOf(b.horizontal)===-1)throw new TypeError("widgetPositioning() expects horizontal parameter to be one of ("+t.join(", ")+")");d.widgetPositioning.horizontal=b.horizontal}if(b.vertical){if("string"!=typeof b.vertical)throw new TypeError("widgetPositioning() vertical variable must be a string");if(b.vertical=b.vertical.toLowerCase(),s.indexOf(b.vertical)===-1)throw new TypeError("widgetPositioning() expects vertical parameter to be one of ("+s.join(", ")+")");d.widgetPositioning.vertical=b.vertical}return _(),l},l.calendarWeeks=function(a){if(0===arguments.length)return d.calendarWeeks;if("boolean"!=typeof a)throw new TypeError("calendarWeeks() expects parameter to be a boolean value");return d.calendarWeeks=a,_(),l},l.showTodayButton=function(a){if(0===arguments.length)return d.showTodayButton;if("boolean"!=typeof a)throw new TypeError("showTodayButton() expects a boolean parameter");return d.showTodayButton=a,o&&(ba(),ga()),l},l.showClear=function(a){if(0===arguments.length)return d.showClear;if("boolean"!=typeof a)throw new TypeError("showClear() expects a boolean parameter");return d.showClear=a,o&&(ba(),ga()),l},l.widgetParent=function(b){if(0===arguments.length)return d.widgetParent;if("string"==typeof b&&(b=a(b)),null!==b&&"string"!=typeof b&&!(b instanceof a))throw new TypeError("widgetParent() expects a string or a jQuery object parameter");return d.widgetParent=b,o&&(ba(),ga()),l},l.keepOpen=function(a){if(0===arguments.length)return d.keepOpen;if("boolean"!=typeof a)throw new TypeError("keepOpen() expects a boolean parameter");return d.keepOpen=a,l},l.focusOnShow=function(a){if(0===arguments.length)return d.focusOnShow;if("boolean"!=typeof a)throw new TypeError("focusOnShow() expects a boolean parameter");return d.focusOnShow=a,l},l.inline=function(a){if(0===arguments.length)return d.inline;if("boolean"!=typeof a)throw new TypeError("inline() expects a boolean parameter");return d.inline=a,l},l.clear=function(){return ca(),l},l.keyBinds=function(a){return 0===arguments.length?d.keyBinds:(d.keyBinds=a,l)},l.getMoment=function(a){return y(a)},l.debug=function(a){if("boolean"!=typeof a)throw new TypeError("debug() expects a boolean parameter");return d.debug=a,l},l.allowInputToggle=function(a){if(0===arguments.length)return d.allowInputToggle;if("boolean"!=typeof a)throw new TypeError("allowInputToggle() expects a boolean parameter");return d.allowInputToggle=a,l},l.showClose=function(a){if(0===arguments.length)return d.showClose;if("boolean"!=typeof a)throw new TypeError("showClose() expects a boolean parameter");return d.showClose=a,l},l.keepInvalid=function(a){if(0===arguments.length)return d.keepInvalid;if("boolean"!=typeof a)throw new TypeError("keepInvalid() expects a boolean parameter");
return d.keepInvalid=a,l},l.datepickerInput=function(a){if(0===arguments.length)return d.datepickerInput;if("string"!=typeof a)throw new TypeError("datepickerInput() expects a string parameter");return d.datepickerInput=a,l},l.parseInputDate=function(a){if(0===arguments.length)return d.parseInputDate;if("function"!=typeof a)throw new TypeError("parseInputDate() sholud be as function");return d.parseInputDate=a,l},l.disabledTimeIntervals=function(b){if(0===arguments.length)return d.disabledTimeIntervals?a.extend({},d.disabledTimeIntervals):d.disabledTimeIntervals;if(!b)return d.disabledTimeIntervals=!1,_(),l;if(!(b instanceof Array))throw new TypeError("disabledTimeIntervals() expects an array parameter");return d.disabledTimeIntervals=b,_(),l},l.disabledHours=function(b){if(0===arguments.length)return d.disabledHours?a.extend({},d.disabledHours):d.disabledHours;if(!b)return d.disabledHours=!1,_(),l;if(!(b instanceof Array))throw new TypeError("disabledHours() expects an array parameter");if(d.disabledHours=oa(b),d.enabledHours=!1,d.useCurrent&&!d.keepInvalid){for(var c=0;!R(e,"h");){if(e.add(1,"h"),24===c)throw"Tried 24 times to find a valid date";c++}aa(e)}return _(),l},l.enabledHours=function(b){if(0===arguments.length)return d.enabledHours?a.extend({},d.enabledHours):d.enabledHours;if(!b)return d.enabledHours=!1,_(),l;if(!(b instanceof Array))throw new TypeError("enabledHours() expects an array parameter");if(d.enabledHours=oa(b),d.disabledHours=!1,d.useCurrent&&!d.keepInvalid){for(var c=0;!R(e,"h");){if(e.add(1,"h"),24===c)throw"Tried 24 times to find a valid date";c++}aa(e)}return _(),l},l.viewDate=function(a){if(0===arguments.length)return f.clone();if(!a)return f=e.clone(),l;if(!("string"==typeof a||b.isMoment(a)||a instanceof Date))throw new TypeError("viewDate() parameter must be one of [string, moment or Date]");return f=da(a),K(),l},c.is("input"))g=c;else if(g=c.find(d.datepickerInput),0===g.length)g=c.find("input");else if(!g.is("input"))throw new Error('CSS class "'+d.datepickerInput+'" cannot be applied to non input element');if(c.hasClass("input-group")&&(n=0===c.find(".datepickerbutton").length?c.find(".input-group-addon"):c.find(".datepickerbutton")),!d.inline&&!g.is("input"))throw new Error("Could not initialize DateTimePicker without an input element");return e=y(),f=e.clone(),a.extend(!0,d,H()),l.options(d),pa(),la(),g.prop("disabled")&&l.disable(),g.is("input")&&0!==g.val().trim().length?aa(da(g.val().trim())):d.defaultDate&&void 0===g.attr("placeholder")&&aa(d.defaultDate),d.inline&&ga(),l};return a.fn.datetimepicker=function(b){b=b||{};var d,e=Array.prototype.slice.call(arguments,1),f=!0,g=["destroy","hide","show","toggle"];if("object"==typeof b)return this.each(function(){var d,e=a(this);e.data("DateTimePicker")||(d=a.extend(!0,{},a.fn.datetimepicker.defaults,b),e.data("DateTimePicker",c(e,d)))});if("string"==typeof b)return this.each(function(){var c=a(this),g=c.data("DateTimePicker");if(!g)throw new Error('bootstrap-datetimepicker("'+b+'") method was called on an element that is not using DateTimePicker');d=g[b].apply(g,e),f=d===g}),f||a.inArray(b,g)>-1?this:d;throw new TypeError("Invalid arguments for DateTimePicker: "+b)},a.fn.datetimepicker.defaults={timeZone:"",format:!1,dayViewHeaderFormat:"MMMM YYYY",extraFormats:!1,stepping:1,minDate:!1,maxDate:!1,useCurrent:!0,collapse:!0,locale:b.locale(),defaultDate:!1,disabledDates:!1,enabledDates:!1,icons:{time:"glyphicon glyphicon-time",date:"glyphicon glyphicon-calendar",up:"glyphicon glyphicon-chevron-up",down:"glyphicon glyphicon-chevron-down",previous:"glyphicon glyphicon-chevron-left",next:"glyphicon glyphicon-chevron-right",today:"glyphicon glyphicon-screenshot",clear:"glyphicon glyphicon-trash",close:"glyphicon glyphicon-remove"},tooltips:{today:"Go to today",clear:"Clear selection",close:"Close the picker",selectMonth:"Select Month",prevMonth:"Previous Month",nextMonth:"Next Month",selectYear:"Select Year",prevYear:"Previous Year",nextYear:"Next Year",selectDecade:"Select Decade",prevDecade:"Previous Decade",nextDecade:"Next Decade",prevCentury:"Previous Century",nextCentury:"Next Century",pickHour:"Pick Hour",incrementHour:"Increment Hour",decrementHour:"Decrement Hour",pickMinute:"Pick Minute",incrementMinute:"Increment Minute",decrementMinute:"Decrement Minute",pickSecond:"Pick Second",incrementSecond:"Increment Second",decrementSecond:"Decrement Second",togglePeriod:"Toggle Period",selectTime:"Select Time"},useStrict:!1,sideBySide:!1,daysOfWeekDisabled:!1,calendarWeeks:!1,viewMode:"days",toolbarPlacement:"default",showTodayButton:!1,showClear:!1,showClose:!1,widgetPositioning:{horizontal:"auto",vertical:"auto"},widgetParent:null,ignoreReadonly:!1,keepOpen:!1,focusOnShow:!0,inline:!1,keepInvalid:!1,datepickerInput:".datepickerinput",keyBinds:{up:function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")?this.date(b.clone().subtract(7,"d")):this.date(b.clone().add(this.stepping(),"m"))}},down:function(a){if(!a)return void this.show();var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")?this.date(b.clone().add(7,"d")):this.date(b.clone().subtract(this.stepping(),"m"))},"control up":function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")?this.date(b.clone().subtract(1,"y")):this.date(b.clone().add(1,"h"))}},"control down":function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")?this.date(b.clone().add(1,"y")):this.date(b.clone().subtract(1,"h"))}},left:function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")&&this.date(b.clone().subtract(1,"d"))}},right:function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")&&this.date(b.clone().add(1,"d"))}},pageUp:function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")&&this.date(b.clone().subtract(1,"M"))}},pageDown:function(a){if(a){var b=this.date()||this.getMoment();a.find(".datepicker").is(":visible")&&this.date(b.clone().add(1,"M"))}},enter:function(){this.hide()},escape:function(){this.hide()},"control space":function(a){a&&a.find(".timepicker").is(":visible")&&a.find('.btn[data-action="togglePeriod"]').click()},t:function(){this.date(this.getMoment())},delete:function(){this.clear()}},debug:!1,allowInputToggle:!1,disabledTimeIntervals:!1,disabledHours:!1,enabledHours:!1,viewDate:!1},a.fn.datetimepicker});/*!
 * jQuery throttle / debounce - v1.1 - 3/7/2010
 * http://benalman.com/projects/jquery-throttle-debounce-plugin/
 * 
 * Copyright (c) 2010 "Cowboy" Ben Alman
 * Dual licensed under the MIT and GPL licenses.
 * http://benalman.com/about/license/
 */

// Script: jQuery throttle / debounce: Sometimes, less is more!
//
// *Version: 1.1, Last updated: 3/7/2010*
// 
// Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
// GitHub       - http://github.com/cowboy/jquery-throttle-debounce/
// Source       - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
// (Minified)   - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
// 
// About: License
// 
// Copyright (c) 2010 "Cowboy" Ben Alman,
// Dual licensed under the MIT and GPL licenses.
// http://benalman.com/about/license/
// 
// About: Examples
// 
// These working examples, complete with fully commented code, illustrate a few
// ways in which this plugin can be used.
// 
// Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
// Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
// 
// About: Support and Testing
// 
// Information about what version or versions of jQuery this plugin has been
// tested with, what browsers it has been tested in, and where the unit tests
// reside (so you can test it yourself).
// 
// jQuery Versions - none, 1.3.2, 1.4.2
// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
// Unit Tests      - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
// 
// About: Release History
// 
// 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
//       executed later than they should. Reworked a fair amount of internal
//       logic as well.
// 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
//       from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
//       no_trailing throttle parameter and debounce functionality.
// 
// Topic: Note for non-jQuery users
// 
// jQuery isn't actually required for this plugin, because nothing internal
// uses any jQuery methods or properties. jQuery is just used as a namespace
// under which these methods can exist.
// 
// Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
// when this plugin is loaded, the method described below will be created in
// the `Cowboy` namespace. Usage will be exactly the same, but instead of
// $.method() or jQuery.method(), you'll need to use Cowboy.method().

(function(window,undefined){
  '$:nomunge'; // Used by YUI compressor.
  
  // Since jQuery really isn't required for this plugin, use `jQuery` as the
  // namespace only if it already exists, otherwise use the `Cowboy` namespace,
  // creating it if necessary.
  var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
    
    // Internal method reference.
    jq_throttle;
  
  // Method: jQuery.throttle
  // 
  // Throttle execution of a function. Especially useful for rate limiting
  // execution of handlers on events like resize and scroll. If you want to
  // rate-limit execution of a function to a single time, see the
  // <jQuery.debounce> method.
  // 
  // In this visualization, | is a throttled-function call and X is the actual
  // callback execution:
  // 
  // > Throttled with `no_trailing` specified as false or unspecified:
  // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
  // > X    X    X    X    X    X        X    X    X    X    X    X
  // > 
  // > Throttled with `no_trailing` specified as true:
  // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
  // > X    X    X    X    X             X    X    X    X    X
  // 
  // Usage:
  // 
  // > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
  // > 
  // > jQuery('selector').bind( 'someevent', throttled );
  // > jQuery('selector').unbind( 'someevent', throttled );
  // 
  // This also works in jQuery 1.4+:
  // 
  // > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
  // > jQuery('selector').unbind( 'someevent', callback );
  // 
  // Arguments:
  // 
  //  delay - (Number) A zero-or-greater delay in milliseconds. For event
  //    callbacks, values around 100 or 250 (or even higher) are most useful.
  //  no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
  //    true, callback will only execute every `delay` milliseconds while the
  //    throttled-function is being called. If no_trailing is false or
  //    unspecified, callback will be executed one final time after the last
  //    throttled-function call. (After the throttled-function has not been
  //    called for `delay` milliseconds, the internal counter is reset)
  //  callback - (Function) A function to be executed after delay milliseconds.
  //    The `this` context and all arguments are passed through, as-is, to
  //    `callback` when the throttled-function is executed.
  // 
  // Returns:
  // 
  //  (Function) A new, throttled, function.
  
  $.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
    // After wrapper has stopped being called, this timeout ensures that
    // `callback` is executed at the proper times in `throttle` and `end`
    // debounce modes.
    var timeout_id,
      
      // Keep track of the last time `callback` was executed.
      last_exec = 0;
    
    // `no_trailing` defaults to falsy.
    if ( typeof no_trailing !== 'boolean' ) {
      debounce_mode = callback;
      callback = no_trailing;
      no_trailing = undefined;
    }
    
    // The `wrapper` function encapsulates all of the throttling / debouncing
    // functionality and when executed will limit the rate at which `callback`
    // is executed.
    function wrapper() {
      var that = this,
        elapsed = +new Date() - last_exec,
        args = arguments;
      
      // Execute `callback` and update the `last_exec` timestamp.
      function exec() {
        last_exec = +new Date();
        callback.apply( that, args );
      };
      
      // If `debounce_mode` is true (at_begin) this is used to clear the flag
      // to allow future `callback` executions.
      function clear() {
        timeout_id = undefined;
      };
      
      if ( debounce_mode && !timeout_id ) {
        // Since `wrapper` is being called for the first time and
        // `debounce_mode` is true (at_begin), execute `callback`.
        exec();
      }
      
      // Clear any existing timeout.
      timeout_id && clearTimeout( timeout_id );
      
      if ( debounce_mode === undefined && elapsed > delay ) {
        // In throttle mode, if `delay` time has been exceeded, execute
        // `callback`.
        exec();
        
      } else if ( no_trailing !== true ) {
        // In trailing throttle mode, since `delay` time has not been
        // exceeded, schedule `callback` to execute `delay` ms after most
        // recent execution.
        // 
        // If `debounce_mode` is true (at_begin), schedule `clear` to execute
        // after `delay` ms.
        // 
        // If `debounce_mode` is false (at end), schedule `callback` to
        // execute after `delay` ms.
        timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
      }
    };
    
    // Set the guid of `wrapper` function to the same of original callback, so
    // it can be removed in jQuery 1.4+ .unbind or .die by using the original
    // callback as a reference.
    if ( $.guid ) {
      wrapper.guid = callback.guid = callback.guid || $.guid++;
    }
    
    // Return the wrapper function.
    return wrapper;
  };
  
  // Method: jQuery.debounce
  // 
  // Debounce execution of a function. Debouncing, unlike throttling,
  // guarantees that a function is only executed a single time, either at the
  // very beginning of a series of calls, or at the very end. If you want to
  // simply rate-limit execution of a function, see the <jQuery.throttle>
  // method.
  // 
  // In this visualization, | is a debounced-function call and X is the actual
  // callback execution:
  // 
  // > Debounced with `at_begin` specified as false or unspecified:
  // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
  // >                          X                                 X
  // > 
  // > Debounced with `at_begin` specified as true:
  // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
  // > X                                 X
  // 
  // Usage:
  // 
  // > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
  // > 
  // > jQuery('selector').bind( 'someevent', debounced );
  // > jQuery('selector').unbind( 'someevent', debounced );
  // 
  // This also works in jQuery 1.4+:
  // 
  // > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
  // > jQuery('selector').unbind( 'someevent', callback );
  // 
  // Arguments:
  // 
  //  delay - (Number) A zero-or-greater delay in milliseconds. For event
  //    callbacks, values around 100 or 250 (or even higher) are most useful.
  //  at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
  //    unspecified, callback will only be executed `delay` milliseconds after
  //    the last debounced-function call. If at_begin is true, callback will be
  //    executed only at the first debounced-function call. (After the
  //    throttled-function has not been called for `delay` milliseconds, the
  //    internal counter is reset)
  //  callback - (Function) A function to be executed after delay milliseconds.
  //    The `this` context and all arguments are passed through, as-is, to
  //    `callback` when the debounced-function is executed.
  // 
  // Returns:
  // 
  //  (Function) A new, debounced, function.
  
  $.debounce = function( delay, at_begin, callback ) {
    return callback === undefined
      ? jq_throttle( delay, at_begin, false )
      : jq_throttle( delay, callback, at_begin !== false );
  };
  
})(this);/** File generated by Grunt -- do not modify
 *  JQUERY-FORM-VALIDATOR
 *
 *  @version 2.3.26
 *  @website http://formvalidator.net/
 *  @author Victor Jonsson, http://victorjonsson.se
 *  @license MIT
 */
!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){!function(a,b){"use strict";function c(b){b&&"custom"===b.errorMessagePosition&&"function"==typeof b.errorMessageCustom&&(a.formUtils.warn("Use of deprecated function errorMessageCustom, use config.submitErrorMessageCallback instead"),b.submitErrorMessageCallback=function(a,c){b.errorMessageCustom(a,b.language.errorTitle,c,b)})}function d(b){if(b.errorMessagePosition&&"object"==typeof b.errorMessagePosition){a.formUtils.warn("Deprecated use of config parameter errorMessagePosition, use config.submitErrorMessageCallback instead");var c=b.errorMessagePosition;b.errorMessagePosition="top",b.submitErrorMessageCallback=function(){return c}}}function e(b){var c=b.find("[data-validation-if-checked]");c.length&&a.formUtils.warn('Detected use of attribute "data-validation-if-checked" which is deprecated. Use "data-validation-depends-on" provided by module "logic"'),c.on("beforeValidation",function(){var c=a(this),d=c.valAttr("if-checked"),e=a('input[name="'+d+'"]',b),f=e.is(":checked"),g=(a.formUtils.getValue(e)||"").toString(),h=c.valAttr("if-checked-value");(!f||h&&h!==g)&&c.valAttr("skipped",!0)})}a.fn.validateForm=function(b,c){return a.formUtils.warn("Use of deprecated function $.validateForm, use $.isValid instead"),this.isValid(b,c,!0)},a(window).on("validatorsLoaded formValidationSetup",function(b,f,g){f||(f=a("form")),c(g),d(g),e(f)})}(a),function(a){"use strict";var b={resolveErrorMessage:function(a,b,c,d,e){var f=d.validationErrorMsgAttribute+"-"+c.replace("validate_",""),g=a.attr(f);return g||(g=a.attr(d.validationErrorMsgAttribute),g||(g="function"!=typeof b.errorMessageKey?e[b.errorMessageKey]:e[b.errorMessageKey(d)],g||(g=b.errorMessage))),g},getParentContainer:function(b){if(b.valAttr("error-msg-container"))return a(b.valAttr("error-msg-container"));var c=b.parent();if(!c.hasClass("form-group")&&!c.closest("form").hasClass("form-horizontal")){var d=c.closest(".form-group");if(d.length)return d.eq(0)}return c},applyInputErrorStyling:function(a,b){a.addClass(b.errorElementClass).removeClass("valid"),this.getParentContainer(a).addClass(b.inputParentClassOnError).removeClass(b.inputParentClassOnSuccess),""!==b.borderColorOnError&&a.css("border-color",b.borderColorOnError)},applyInputSuccessStyling:function(a,b){a.addClass("valid"),this.getParentContainer(a).addClass(b.inputParentClassOnSuccess)},removeInputStylingAndMessage:function(a,c){a.removeClass("valid").removeClass(c.errorElementClass).css("border-color","");var d=b.getParentContainer(a);if(d.removeClass(c.inputParentClassOnError).removeClass(c.inputParentClassOnSuccess),"function"==typeof c.inlineErrorMessageCallback){var e=c.inlineErrorMessageCallback(a,!1,c);e&&e.html("")}else d.find("."+c.errorMessageClass).remove()},removeAllMessagesAndStyling:function(c,d){if("function"==typeof d.submitErrorMessageCallback){var e=d.submitErrorMessageCallback(c,d);e&&e.html("")}else c.find("."+d.errorMessageClass+".alert").remove();c.find("."+d.errorElementClass+",.valid").each(function(){b.removeInputStylingAndMessage(a(this),d)})},setInlineMessage:function(b,c,d){this.applyInputErrorStyling(b,d);var e,f=document.getElementById(b.attr("name")+"_err_msg"),g=!1,h=function(d){a.formUtils.$win.trigger("validationErrorDisplay",[b,d]),d.html(c)},i=function(){var f=!1;g.find("."+d.errorMessageClass).each(function(){return this.inputReferer===b[0]?(f=a(this),!1):void 0}),f?c?h(f):f.remove():""!==c&&(e=a('<div class="'+d.errorMessageClass+' alert"></div>'),h(e),e[0].inputReferer=b[0],g.prepend(e))};if(f)a.formUtils.warn("Using deprecated element reference "+f.id),g=a(f),i();else if("function"==typeof d.inlineErrorMessageCallback){if(g=d.inlineErrorMessageCallback(b,c,d),!g)return;i()}else{var j=this.getParentContainer(b);e=j.find("."+d.errorMessageClass+".help-block"),0===e.length&&(e=a("<span></span>").addClass("help-block").addClass(d.errorMessageClass),e.appendTo(j)),h(e)}},setMessageInTopOfForm:function(b,c,d,e){var f='<div class="{errorMessageClass} alert alert-danger"><strong>{errorTitle}</strong><ul>{fields}</ul></div>',g=!1;if("function"!=typeof d.submitErrorMessageCallback||(g=d.submitErrorMessageCallback(b,c,d))){var h={errorTitle:e.errorTitle,fields:"",errorMessageClass:d.errorMessageClass};a.each(c,function(a,b){h.fields+="<li>"+b+"</li>"}),a.each(h,function(a,b){f=f.replace("{"+a+"}",b)}),g?g.html(f):b.children().eq(0).before(a(f))}}};a.formUtils=a.extend(a.formUtils||{},{dialogs:b})}(a),function(a,b,c){"use strict";var d=0;a.fn.validateOnBlur=function(b,c){var d=this,e=this.find("*[data-validation]");return e.each(function(){var e=a(this);if(e.is("[type=radio]")){var f=d.find('[type=radio][name="'+e.attr("name")+'"]');f.bind("blur.validation",function(){e.validateInputOnBlur(b,c,!0,"blur")}),c.validateCheckboxRadioOnClick&&f.bind("click.validation",function(){e.validateInputOnBlur(b,c,!0,"click")})}}),e.bind("blur.validation",function(){a(this).validateInputOnBlur(b,c,!0,"blur")}),c.validateCheckboxRadioOnClick&&this.find("input[type=checkbox][data-validation],input[type=radio][data-validation]").bind("click.validation",function(){a(this).validateInputOnBlur(b,c,!0,"click")}),this},a.fn.validateOnEvent=function(b,c){var d="FORM"===this[0].nodeName?this.find("*[data-validation-event]"):this;return d.each(function(){var d=a(this),e=d.valAttr("event");e&&d.unbind(e+".validation").bind(e+".validation",function(d){9!==(d||{}).keyCode&&a(this).validateInputOnBlur(b,c,!0,e)})}),this},a.fn.showHelpOnFocus=function(b){return b||(b="data-validation-help"),this.find(".has-help-txt").valAttr("has-keyup-event",!1).removeClass("has-help-txt"),this.find("textarea,input").each(function(){var c=a(this),e="jquery_form_help_"+ ++d,f=c.attr(b);f&&c.addClass("has-help-txt").unbind("focus.help").bind("focus.help",function(){var b=c.parent().find("."+e);0===b.length&&(b=a("<span />").addClass(e).addClass("help").addClass("help-block").text(f).hide(),c.after(b)),b.fadeIn()}).unbind("blur.help").bind("blur.help",function(){a(this).parent().find("."+e).fadeOut("slow")})}),this},a.fn.validate=function(b,c,d){var e=a.extend({},a.formUtils.LANG,d||{});this.each(function(){var d=a(this),f=d.closest("form").get(0).validationConfig||{};d.one("validation",function(a,c){"function"==typeof b&&b(c,this,a)}),d.validateInputOnBlur(e,a.extend({},f,c||{}),!0)})},a.fn.willPostponeValidation=function(){return(this.valAttr("suggestion-nr")||this.valAttr("postpone")||this.hasClass("hasDatepicker"))&&!b.postponedValidation},a.fn.validateInputOnBlur=function(c,d,e,f){if(a.formUtils.eventType=f,this.willPostponeValidation()){var g=this,h=this.valAttr("postpone")||200;return b.postponedValidation=function(){g.validateInputOnBlur(c,d,e,f),b.postponedValidation=!1},setTimeout(function(){b.postponedValidation&&b.postponedValidation()},h),this}c=a.extend({},a.formUtils.LANG,c||{}),a.formUtils.dialogs.removeInputStylingAndMessage(this,d);var i=this,j=i.closest("form"),k=a.formUtils.validateInput(i,c,d,j,f);return e&&i.unbind("keyup.validation"),k.shouldChangeDisplay&&(k.isValid?a.formUtils.dialogs.applyInputSuccessStyling(i,d):a.formUtils.dialogs.setInlineMessage(i,k.errorMsg,d)),!k.isValid&&e&&i.bind("keyup.validation",function(b){9!==b.keyCode&&a(this).validateInputOnBlur(c,d,!1,"keyup")}),this},a.fn.valAttr=function(a,b){return b===c?this.attr("data-validation-"+a):b===!1||null===b?this.removeAttr("data-validation-"+a):(a=a.length>0?"-"+a:"",this.attr("data-validation"+a,b))},a.fn.isValid=function(b,c,d){if(a.formUtils.isLoadingModules){var e=this;return setTimeout(function(){e.isValid(b,c,d)},200),null}c=a.extend({},a.formUtils.defaultConfig(),c||{}),b=a.extend({},a.formUtils.LANG,b||{}),d=d!==!1,a.formUtils.errorDisplayPreventedWhenHalted&&(delete a.formUtils.errorDisplayPreventedWhenHalted,d=!1),a.formUtils.isValidatingEntireForm=!0,a.formUtils.haltValidation=!1;var f=function(b,e){a.inArray(b,h)<0&&h.push(b),i.push(e),e.attr("current-error",b),d&&a.formUtils.dialogs.applyInputErrorStyling(e,c)},g=[],h=[],i=[],j=this,k=function(b,d){return"submit"===d||"button"===d||"reset"===d?!0:a.inArray(b,c.ignore||[])>-1};if(d&&a.formUtils.dialogs.removeAllMessagesAndStyling(j,c),j.find("input,textarea,select").filter(':not([type="submit"],[type="button"])').each(function(){var d=a(this),e=d.attr("type"),h="radio"===e||"checkbox"===e,i=d.attr("name");if(!k(i,e)&&(!h||a.inArray(i,g)<0)){h&&g.push(i);var l=a.formUtils.validateInput(d,b,c,j,"submit");l.isValid?l.isValid&&l.shouldChangeDisplay&&(d.valAttr("current-error",!1),a.formUtils.dialogs.applyInputSuccessStyling(d,c)):f(l.errorMsg,d)}}),"function"==typeof c.onValidate){var l=c.onValidate(j);a.isArray(l)?a.each(l,function(a,b){f(b.message,b.element)}):l&&l.element&&l.message&&f(l.message,l.element)}return a.formUtils.isValidatingEntireForm=!1,!a.formUtils.haltValidation&&i.length>0?(d&&("top"===c.errorMessagePosition?a.formUtils.dialogs.setMessageInTopOfForm(j,h,c,b):a.each(i,function(b,d){a.formUtils.dialogs.setInlineMessage(d,d.attr("current-error"),c)}),c.scrollToTopOnError&&a.formUtils.$win.scrollTop(j.offset().top-20)),!1):(!d&&a.formUtils.haltValidation&&(a.formUtils.errorDisplayPreventedWhenHalted=!0),!a.formUtils.haltValidation)},a.fn.restrictLength=function(b){return new a.formUtils.lengthRestriction(this,b),this},a.fn.addSuggestions=function(b){var c=!1;return this.find("input").each(function(){var d=a(this);c=a.split(d.attr("data-suggestions")),c.length>0&&!d.hasClass("has-suggestions")&&(a.formUtils.suggest(d,c,b),d.addClass("has-suggestions"))}),this}}(a,window),function(a){"use strict";a.formUtils=a.extend(a.formUtils||{},{isLoadingModules:!1,loadedModules:{},loadModules:function(b,c,d){if(a.formUtils.isLoadingModules)return void setTimeout(function(){a.formUtils.loadModules(b,c,d)},10);var e=!1,f=function(b,c){var f=a.split(b),g=f.length,h=function(){g--,0===g&&(a.formUtils.isLoadingModules=!1,d&&e&&"function"==typeof d&&d())};g>0&&(a.formUtils.isLoadingModules=!0);var i="?_="+(new Date).getTime(),j=document.getElementsByTagName("head")[0]||document.getElementsByTagName("body")[0];a.each(f,function(b,d){if(d=a.trim(d),0===d.length)h();else{var f=c+d+(".js"===d.slice(-3)?"":".js"),g=document.createElement("SCRIPT");f in a.formUtils.loadedModules?h():(a.formUtils.loadedModules[f]=1,e=!0,g.type="text/javascript",g.onload=h,g.src=f+(".dev.js"===f.slice(-7)?i:""),g.onerror=function(){a.formUtils.warn("Unable to load form validation module "+f)},g.onreadystatechange=function(){"complete"!==this.readyState&&"loaded"!==this.readyState||(h(),this.onload=null,this.onreadystatechange=null)},j.appendChild(g))}})};if(c)f(b,c);else{var g=function(){var c=!1;return a('script[src*="form-validator"]').each(function(){return c=this.src.substr(0,this.src.lastIndexOf("/"))+"/","/"===c&&(c=""),!1}),c!==!1?(f(b,c),!0):!1};g()||a(g)}}})}(a),function(a){"use strict";a.split=function(b,c){if("function"!=typeof c){if(!b)return[];var d=[];return a.each(b.split(c?c:/[,|\-\s]\s*/g),function(b,c){c=a.trim(c),c.length&&d.push(c)}),d}b&&a.each(b.split(/[,|\-\s]\s*/g),function(b,d){return d=a.trim(d),d.length?c(d,b):void 0})},a.validate=function(b){var c=a.extend(a.formUtils.defaultConfig(),{form:"form",validateOnEvent:!1,validateOnBlur:!0,validateCheckboxRadioOnClick:!0,showHelpOnFocus:!0,addSuggestions:!0,modules:"",onModulesLoaded:null,language:!1,onSuccess:!1,onError:!1,onElementValidate:!1});if(b=a.extend(c,b||{}),b.lang&&"en"!==b.lang){var d="lang/"+b.lang+".js";b.modules+=b.modules.length?","+d:d}a(b.form).each(function(c,d){d.validationConfig=b;var e=a(d);e.trigger("formValidationSetup",[e,b]),e.find(".has-help-txt").unbind("focus.validation").unbind("blur.validation"),e.removeClass("has-validation-callback").unbind("submit.validation").unbind("reset.validation").find("input[data-validation],textarea[data-validation]").unbind("blur.validation"),e.bind("submit.validation",function(c){var d=a(this),e=function(){return c.stopImmediatePropagation(),!1};if(a.formUtils.haltValidation)return e();if(a.formUtils.isLoadingModules)return setTimeout(function(){d.trigger("submit.validation")},200),e();var f=d.isValid(b.language,b);if(a.formUtils.haltValidation)return e();if(!f||"function"!=typeof b.onSuccess)return f||"function"!=typeof b.onError?f?!0:e():(b.onError(d),e());var g=b.onSuccess(d);return g===!1?e():void 0}).bind("reset.validation",function(){a.formUtils.dialogs.removeAllMessagesAndStyling(e,b)}).addClass("has-validation-callback"),b.showHelpOnFocus&&e.showHelpOnFocus(),b.addSuggestions&&e.addSuggestions(),b.validateOnBlur&&(e.validateOnBlur(b.language,b),e.bind("html5ValidationAttrsFound",function(){e.validateOnBlur(b.language,b)})),b.validateOnEvent&&e.validateOnEvent(b.language,b)}),""!==b.modules&&a.formUtils.loadModules(b.modules,!1,function(){"function"==typeof b.onModulesLoaded&&b.onModulesLoaded();var c="string"==typeof b.form?a(b.form):b.form;a.formUtils.$win.trigger("validatorsLoaded",[c,b])})}}(a),function(a,b){"use strict";var c=a(b);a.formUtils=a.extend(a.formUtils||{},{$win:c,defaultConfig:function(){return{ignore:[],errorElementClass:"error",borderColorOnError:"#b94a48",errorMessageClass:"form-error",validationRuleAttribute:"data-validation",validationErrorMsgAttribute:"data-validation-error-msg",errorMessagePosition:"inline",errorMessageTemplate:{container:'<div class="{errorMessageClass} alert alert-danger">{messages}</div>',messages:"<strong>{errorTitle}</strong><ul>{fields}</ul>",field:"<li>{msg}</li>"},scrollToTopOnError:!0,dateFormat:"yyyy-mm-dd",addValidClassOnAll:!1,decimalSeparator:".",inputParentClassOnError:"has-error",inputParentClassOnSuccess:"has-success",validateHiddenInputs:!1,inlineErrorMessageCallback:!1,submitErrorMessageCallback:!1}},validators:{},_events:{load:[],valid:[],invalid:[]},haltValidation:!1,isValidatingEntireForm:!1,addValidator:function(a){var b=0===a.name.indexOf("validate_")?a.name:"validate_"+a.name;void 0===a.validateOnKeyUp&&(a.validateOnKeyUp=!0),this.validators[b]=a},warn:function(a){"console"in b?"function"==typeof b.console.warn?b.console.warn(a):"function"==typeof b.console.log&&b.console.log(a):alert(a)},getValue:function(a,b){var c=b?b.find(a):a;if(c.length>0){var d=c.eq(0).attr("type");return"radio"===d||"checkbox"===d?c.filter(":checked").val():c.val()}return!1},validateInput:function(b,c,d,e,f){d=d||a.formUtils.defaultConfig(),c=c||a.formUtils.LANG;var g=this.getValue(b);b.valAttr("skipped",!1).one("beforeValidation",function(){(b.attr("disabled")||!b.is(":visible")&&!d.validateHiddenInputs)&&b.valAttr("skipped",1)}).trigger("beforeValidation",[g,d,c]);var h="true"===b.valAttr("optional"),i=!g&&h,j=b.attr(d.validationRuleAttribute),k=!0,l="",m={isValid:!0,shouldChangeDisplay:!0,errorMsg:""};if(!j||i||b.valAttr("skipped"))return m.shouldChangeDisplay=d.addValidClassOnAll,m;var n=b.valAttr("ignore");return n&&a.each(n.split(""),function(a,b){g=g.replace(new RegExp("\\"+b),"")}),a.split(j,function(h){0!==h.indexOf("validate_")&&(h="validate_"+h);var i=a.formUtils.validators[h];if(!i)throw new Error('Using undefined validator "'+h+'". Maybe you have forgotten to load the module that "'+h+'" belongs to?');return"validate_checkbox_group"===h&&(b=e.find('[name="'+b.attr("name")+'"]:eq(0)')),("keyup"!==f||i.validateOnKeyUp)&&(k=i.validatorFunction(g,b,d,c,e)),k?void 0:(l=a.formUtils.dialogs.resolveErrorMessage(b,i,h,d,c),!1)}," "),k===!1?(b.trigger("validation",!1),m.errorMsg=l,m.isValid=!1,m.shouldChangeDisplay=!0):null===k?m.shouldChangeDisplay=!1:(b.trigger("validation",!0),m.shouldChangeDisplay=!0),"function"==typeof d.onElementValidate&&null!==l&&d.onElementValidate(m.isValid,b,e,l),b.trigger("afterValidation",[m,f]),m},parseDate:function(b,c,d){var e,f,g,h,i=c.replace(/[a-zA-Z]/gi,"").substring(0,1),j="^",k=c.split(i||null);if(a.each(k,function(a,b){j+=(a>0?"\\"+i:"")+"(\\d{"+b.length+"})"}),j+="$",d){var l=[];a.each(b.split(i),function(a,b){1===b.length&&(b="0"+b),l.push(b)}),b=l.join(i)}if(e=b.match(new RegExp(j)),null===e)return!1;var m=function(b,c,d){for(var e=0;e<c.length;e++)if(c[e].substring(0,1)===b)return a.formUtils.parseDateInt(d[e+1]);return-1};return g=m("m",k,e),f=m("d",k,e),h=m("y",k,e),2===g&&f>28&&(h%4!==0||h%100===0&&h%400!==0)||2===g&&f>29&&(h%4===0||h%100!==0&&h%400===0)||g>12||0===g?!1:this.isShortMonth(g)&&f>30||!this.isShortMonth(g)&&f>31||0===f?!1:[h,g,f]},parseDateInt:function(a){return 0===a.indexOf("0")&&(a=a.replace("0","")),parseInt(a,10)},isShortMonth:function(a){return a%2===0&&7>a||a%2!==0&&a>7},lengthRestriction:function(b,c){var d=parseInt(c.text(),10),e=0,f=function(){var a=b.val().length;if(a>d){var f=b.scrollTop();b.val(b.val().substring(0,d)),b.scrollTop(f)}e=d-a,0>e&&(e=0),c.text(e)};a(b).bind("keydown keyup keypress focus blur",f).bind("cut paste",function(){setTimeout(f,100)}),a(document).bind("ready",f)},numericRangeCheck:function(b,c){var d=a.split(c),e=parseInt(c.substr(3),10);return 1===d.length&&-1===c.indexOf("min")&&-1===c.indexOf("max")&&(d=[c,c]),2===d.length&&(b<parseInt(d[0],10)||b>parseInt(d[1],10))?["out",d[0],d[1]]:0===c.indexOf("min")&&e>b?["min",e]:0===c.indexOf("max")&&b>e?["max",e]:["ok"]},_numSuggestionElements:0,_selectedSuggestion:null,_previousTypedVal:null,suggest:function(b,d,e){var f={css:{maxHeight:"150px",background:"#FFF",lineHeight:"150%",textDecoration:"underline",overflowX:"hidden",overflowY:"auto",border:"#CCC solid 1px",borderTop:"none",cursor:"pointer"},activeSuggestionCSS:{background:"#E9E9E9"}},g=function(a,b){var c=b.offset();a.css({width:b.outerWidth(),left:c.left+"px",top:c.top+b.outerHeight()+"px"})};e&&a.extend(f,e),f.css.position="absolute",f.css["z-index"]=9999,b.attr("autocomplete","off"),0===this._numSuggestionElements&&c.bind("resize",function(){a(".jquery-form-suggestions").each(function(){var b=a(this),c=b.attr("data-suggest-container");g(b,a(".suggestions-"+c).eq(0))})}),this._numSuggestionElements++;var h=function(b){var c=b.valAttr("suggestion-nr");a.formUtils._selectedSuggestion=null,a.formUtils._previousTypedVal=null,a(".jquery-form-suggestion-"+c).fadeOut("fast")};return b.data("suggestions",d).valAttr("suggestion-nr",this._numSuggestionElements).unbind("focus.suggest").bind("focus.suggest",function(){a(this).trigger("keyup"),a.formUtils._selectedSuggestion=null}).unbind("keyup.suggest").bind("keyup.suggest",function(){var c=a(this),d=[],e=a.trim(c.val()).toLocaleLowerCase();if(e!==a.formUtils._previousTypedVal){a.formUtils._previousTypedVal=e;var i=!1,j=c.valAttr("suggestion-nr"),k=a(".jquery-form-suggestion-"+j);if(k.scrollTop(0),""!==e){var l=e.length>2;a.each(c.data("suggestions"),function(a,b){var c=b.toLocaleLowerCase();return c===e?(d.push("<strong>"+b+"</strong>"),i=!0,!1):void((0===c.indexOf(e)||l&&c.indexOf(e)>-1)&&d.push(b.replace(new RegExp(e,"gi"),"<strong>$&</strong>")))})}i||0===d.length&&k.length>0?k.hide():d.length>0&&0===k.length?(k=a("<div></div>").css(f.css).appendTo("body"),b.addClass("suggestions-"+j),k.attr("data-suggest-container",j).addClass("jquery-form-suggestions").addClass("jquery-form-suggestion-"+j)):d.length>0&&!k.is(":visible")&&k.show(),d.length>0&&e.length!==d[0].length&&(g(k,c),k.html(""),a.each(d,function(b,d){a("<div></div>").append(d).css({overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",padding:"5px"}).addClass("form-suggest-element").appendTo(k).click(function(){c.focus(),c.val(a(this).text()),c.trigger("change"),h(c)})}))}}).unbind("keydown.validation").bind("keydown.validation",function(b){var c,d,e=b.keyCode?b.keyCode:b.which,g=a(this);if(13===e&&null!==a.formUtils._selectedSuggestion){if(c=g.valAttr("suggestion-nr"),d=a(".jquery-form-suggestion-"+c),d.length>0){var i=d.find("div").eq(a.formUtils._selectedSuggestion).text();g.val(i),g.trigger("change"),h(g),b.preventDefault()}}else{c=g.valAttr("suggestion-nr"),d=a(".jquery-form-suggestion-"+c);var j=d.children();if(j.length>0&&a.inArray(e,[38,40])>-1){38===e?(null===a.formUtils._selectedSuggestion?a.formUtils._selectedSuggestion=j.length-1:a.formUtils._selectedSuggestion--,a.formUtils._selectedSuggestion<0&&(a.formUtils._selectedSuggestion=j.length-1)):40===e&&(null===a.formUtils._selectedSuggestion?a.formUtils._selectedSuggestion=0:a.formUtils._selectedSuggestion++,a.formUtils._selectedSuggestion>j.length-1&&(a.formUtils._selectedSuggestion=0));var k=d.innerHeight(),l=d.scrollTop(),m=d.children().eq(0).outerHeight(),n=m*a.formUtils._selectedSuggestion;return(l>n||n>l+k)&&d.scrollTop(n),j.removeClass("active-suggestion").css("background","none").eq(a.formUtils._selectedSuggestion).addClass("active-suggestion").css(f.activeSuggestionCSS),b.preventDefault(),!1}}}).unbind("blur.suggest").bind("blur.suggest",function(){h(a(this))}),b},LANG:{errorTitle:"Form submission failed!",requiredField:"This is a required field",requiredFields:"You have not answered all required fields",badTime:"You have not given a correct time",badEmail:"You have not given a correct e-mail address",badTelephone:"You have not given a correct phone number",badSecurityAnswer:"You have not given a correct answer to the security question",badDate:"You have not given a correct date",lengthBadStart:"The input value must be between ",lengthBadEnd:" characters",lengthTooLongStart:"The input value is longer than ",lengthTooShortStart:"The input value is shorter than ",notConfirmed:"Input values could not be confirmed",badDomain:"Incorrect domain value",badUrl:"The input value is not a correct URL",badCustomVal:"The input value is incorrect",andSpaces:" and spaces ",badInt:"The input value was not a correct number",badSecurityNumber:"Your social security number was incorrect",badUKVatAnswer:"Incorrect UK VAT Number",badUKNin:"Incorrect UK NIN",badUKUtr:"Incorrect UK UTR Number",badStrength:"The password isn't strong enough",badNumberOfSelectedOptionsStart:"You have to choose at least ",badNumberOfSelectedOptionsEnd:" answers",badAlphaNumeric:"The input value can only contain alphanumeric characters ",badAlphaNumericExtra:" and ",wrongFileSize:"The file you are trying to upload is too large (max %s)",wrongFileType:"Only files of type %s is allowed",groupCheckedRangeStart:"Please choose between ",groupCheckedTooFewStart:"Please choose at least ",groupCheckedTooManyStart:"Please choose a maximum of ",groupCheckedEnd:" item(s)",badCreditCard:"The credit card number is not correct",badCVV:"The CVV number was not correct",wrongFileDim:"Incorrect image dimensions,",imageTooTall:"the image can not be taller than",imageTooWide:"the image can not be wider than",imageTooSmall:"the image was too small",min:"min",max:"max",imageRatioNotAccepted:"Image ratio is not be accepted",badBrazilTelephoneAnswer:"The phone number entered is invalid",badBrazilCEPAnswer:"The CEP entered is invalid",badBrazilCPFAnswer:"The CPF entered is invalid",badPlPesel:"The PESEL entered is invalid",badPlNip:"The NIP entered is invalid",badPlRegon:"The REGON entered is invalid",badreCaptcha:"Please confirm that you are not a bot"}})}(a,window),function(a){a.formUtils.addValidator({name:"email",validatorFunction:function(b){var c=b.toLowerCase().split("@"),d=c[0],e=c[1];if(d&&e){if(0===d.indexOf('"')){var f=d.length;if(d=d.replace(/\"/g,""),d.length!==f-2)return!1}return a.formUtils.validators.validate_domain.validatorFunction(c[1])&&0!==d.indexOf(".")&&"."!==d.substring(d.length-1,d.length)&&-1===d.indexOf("..")&&!/[^\w\+\.\-\#\-\_\~\!\$\&\'\(\)\*\+\,\;\=\:]/.test(d)}return!1},errorMessage:"",errorMessageKey:"badEmail"}),a.formUtils.addValidator({name:"domain",validatorFunction:function(a){return a.length>0&&a.length<=253&&!/[^a-zA-Z0-9]/.test(a.slice(-2))&&!/[^a-zA-Z0-9]/.test(a.substr(0,1))&&!/[^a-zA-Z0-9\.\-]/.test(a)&&1===a.split("..").length&&a.split(".").length>1},errorMessage:"",errorMessageKey:"badDomain"}),a.formUtils.addValidator({name:"required",validatorFunction:function(b,c,d,e,f){switch(c.attr("type")){case"checkbox":return c.is(":checked");case"radio":return f.find('input[name="'+c.attr("name")+'"]').filter(":checked").length>0;default:return""!==a.trim(b)}},errorMessage:"",errorMessageKey:function(a){return"top"===a.errorMessagePosition||"function"==typeof a.errorMessagePosition?"requiredFields":"requiredField"}}),a.formUtils.addValidator({name:"length",validatorFunction:function(b,c,d,e){var f=c.valAttr("length"),g=c.attr("type");if(void 0===f)return alert('Please add attribute "data-validation-length" to '+c[0].nodeName+" named "+c.attr("name")),!0;var h,i="file"===g&&void 0!==c.get(0).files?c.get(0).files.length:b.length,j=a.formUtils.numericRangeCheck(i,f);switch(j[0]){case"out":this.errorMessage=e.lengthBadStart+f+e.lengthBadEnd,h=!1;break;case"min":this.errorMessage=e.lengthTooShortStart+j[1]+e.lengthBadEnd,h=!1;break;case"max":this.errorMessage=e.lengthTooLongStart+j[1]+e.lengthBadEnd,h=!1;break;default:h=!0}return h},errorMessage:"",errorMessageKey:""}),a.formUtils.addValidator({name:"url",validatorFunction:function(b){var c=/^(https?|ftp):\/\/((((\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])(\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])(\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/(((\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/((\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|\[|\]|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#(((\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i;if(c.test(b)){var d=b.split("://")[1],e=d.indexOf("/");return e>-1&&(d=d.substr(0,e)),a.formUtils.validators.validate_domain.validatorFunction(d)}return!1},errorMessage:"",errorMessageKey:"badUrl"}),a.formUtils.addValidator({name:"number",validatorFunction:function(a,b,c){if(""!==a){var d,e,f=b.valAttr("allowing")||"",g=b.valAttr("decimal-separator")||c.decimalSeparator,h=!1,i=b.valAttr("step")||"",j=!1,k=b.attr("data-sanitize")||"",l=k.match(/(^|[\s])numberFormat([\s]|$)/i);if(l){if(!window.numeral)throw new ReferenceError("The data-sanitize value numberFormat cannot be used without the numeral library. Please see Data Validation in http://www.formvalidator.net for more information.");a.length&&(a=String(numeral().unformat(a)))}if(-1===f.indexOf("number")&&(f+=",number"),-1===f.indexOf("negative")&&0===a.indexOf("-"))return!1;if(f.indexOf("range")>-1&&(d=parseFloat(f.substring(f.indexOf("[")+1,f.indexOf(";"))),e=parseFloat(f.substring(f.indexOf(";")+1,f.indexOf("]"))),h=!0),""!==i&&(j=!0),","===g){if(a.indexOf(".")>-1)return!1;a=a.replace(",",".")}if(""===a.replace(/[0-9-]/g,"")&&(!h||a>=d&&e>=a)&&(!j||a%i===0))return!0;if(f.indexOf("float")>-1&&null!==a.match(new RegExp("^([0-9-]+)\\.([0-9]+)$"))&&(!h||a>=d&&e>=a)&&(!j||a%i===0))return!0}return!1},errorMessage:"",errorMessageKey:"badInt"}),a.formUtils.addValidator({name:"alphanumeric",validatorFunction:function(b,c,d,e){var f="^([a-zA-Z0-9",g="]+)$",h=c.valAttr("allowing"),i="";if(h){i=f+h+g;var j=h.replace(/\\/g,"");j.indexOf(" ")>-1&&(j=j.replace(" ",""),j+=e.andSpaces||a.formUtils.LANG.andSpaces),this.errorMessage=e.badAlphaNumeric+e.badAlphaNumericExtra+j}else i=f+g,this.errorMessage=e.badAlphaNumeric;return new RegExp(i).test(b)},errorMessage:"",errorMessageKey:""}),a.formUtils.addValidator({name:"custom",validatorFunction:function(a,b){var c=new RegExp(b.valAttr("regexp"));return c.test(a)},errorMessage:"",errorMessageKey:"badCustomVal"}),a.formUtils.addValidator({name:"date",validatorFunction:function(b,c,d){var e=c.valAttr("format")||d.dateFormat||"yyyy-mm-dd",f="false"===c.valAttr("require-leading-zero");return a.formUtils.parseDate(b,e,f)!==!1},errorMessage:"",errorMessageKey:"badDate"}),a.formUtils.addValidator({name:"checkbox_group",validatorFunction:function(b,c,d,e,f){var g=!0,h=c.attr("name"),i=a('input[type=checkbox][name^="'+h+'"]',f),j=i.filter(":checked").length,k=c.valAttr("qty");if(void 0===k){var l=c.get(0).nodeName;alert('Attribute "data-validation-qty" is missing from '+l+" named "+c.attr("name"))}var m=a.formUtils.numericRangeCheck(j,k);switch(m[0]){case"out":this.errorMessage=e.groupCheckedRangeStart+k+e.groupCheckedEnd,g=!1;break;case"min":this.errorMessage=e.groupCheckedTooFewStart+m[1]+e.groupCheckedEnd,g=!1;break;case"max":this.errorMessage=e.groupCheckedTooManyStart+m[1]+e.groupCheckedEnd,g=!1;break;default:g=!0}if(!g){var n=function(){i.unbind("click",n),i.filter("*[data-validation]").validateInputOnBlur(e,d,!1,"blur")};i.bind("click",n)}return g}})}(a)});/**
 * jQuery Form Validator Module: VAT
 * ------------------------------------------------
 * Created by TLG Commerce
 * Version: 0.2 - 2017-06-19
 * Version: 0.1 - 2016-06-06
 *
 * Adds validators for VATs:
 * - vatES (Spain)
 *
 */
(function ($) {

  'use strict';
  /**
   * Basic VAT module
   */
  $.formUtils.addValidator({
    name: 'vat',
    validatorFunction: function(value, $elem, conf, language, $form){
      var validationTypes = $elem.data('validationTypes');
      var $country = $form.find("select.__selectCountry__");
      var countryId = $country.length? $country.val() : settings.countryId;

      // Without countryId we can not validate
      if (!countryId && validationTypes.hasOwnProperty(countryId) && $.formUtils.vatValidators.hasOwnProperty(validationTypes[countryId])) {
        return true;
      }
      return $.formUtils.vatValidators[validationTypes[countryId]](value, $elem, conf, language, $form);
    },
    errorMessage : '',
    errorMessageKey: 'badVat'
  });

  /**
   * Basic IDCard module
   */
  $.formUtils.addValidator({
    name: 'idcard',
    validatorFunction: function(value, $elem, conf, language, $form){
      var validationTypes = $elem.data('validationTypes');
      var $country = $form.find("select.__selectCountry__");
      var countryId = $country.length? $country.val() : settings.countryId;

      // Without countryId we can not validate
      if (!countryId || !validationTypes.hasOwnProperty(countryId) || !$.formUtils.idCardValidators.hasOwnProperty(validationTypes[countryId])) {
        return true;
      }
      return $.formUtils.idCardValidators[validationTypes[countryId]](value, $elem, conf, language, $form);
    },
    errorMessage : '',
    errorMessageKey: 'badIdCard'
  });


  /**
   * idCard modules
   */
  $.formUtils.idCardValidators = {
    "es" : function(value, $elem, conf, language, $form) {
      if (value.length)
        return validateNIF(value); // Allow empty values
      else
        return true;

      function validateNIF(value){
        var lettersList='TRWAGMYFPDXBNJZSQVHLCKE';

        value = value.toUpperCase(); 

        // Prepare Value
        var firstChar = value.substr(0,1);

        if (/^[X]{1}/.test( firstChar ))
           value = value.replace('X','0')
        if (/^[Y]{1}/.test( firstChar ))
           value = value.replace('Y','1')
        if (/^[Z]{1}/.test( firstChar ))
           value = value.replace('Z','2')

        var modNum = value.substr(0,value.length-1) % 23;

        // Validate Format
        if (!/\d\d\d\d\d\d\d\d[A-Z]$/g.exec(value)) 
          return false;

        // Get Letter 
        var letter = value.substr(value.length-1, 1);

        return lettersList.substring(modNum, modNum+1) == letter;
      }
    }
  };

  /**
   * VAT modules
   */
  $.formUtils.vatValidators = {
    "es" : function(value, $elem, conf, language, $form) {
      if (value.length)
        return validateCIF(value); // Allow empty values
      else
        return true;

      function validateCIF(cif) {
        if (!cif || cif.length !== 9) {
          return false;
        }

        var letters = ['J', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'];
        var digits = cif.substr(1, cif.length - 2);
        var letter = cif.substr(0, 1);
        var control = cif.substr(cif.length - 1);
        var sum = 0;
        var i;
        var digit;

        if (!letter.match(/[ABCDEFGHJNPQRSUVW]/)) {
          if (letter.match(/[XYZ]/) || letter.match(/[0-9]/))
            return $.formUtils.idCardValidators.es(cif);
          else
            return false;
        }

        for (i = 0; i < digits.length; ++i) {
          digit = parseInt(digits[i]);

          if (isNaN(digit))
            return false;

          if (i % 2 === 0) {
            digit *= 2;
            if (digit > 9)
              digit = parseInt(digit / 10) + (digit % 10);
            sum += digit;
          } else
            sum += digit;
        }
        sum %= 10;
        if (sum !== 0)
          digit = 10 - sum;
        else
          digit = sum;

        if (letter.match(/[ABEH]/))
          return String(digit) === control;
        
        if (letter.match(/[NPQRSW]/))
          return letters[digit] === control;                

        return String(digit) === control || letters[digit] === control;
      }

      function validatePassport(value){
        if (value.length < 29) 
          return false;

        var passport_no = value.substr(0,9);
        var passport_no_cs = value.substr(9,1);
        var date_of_birth = value.substr(13,6);
        var date_of_birth_cs = value.substr(19,1);
        var date_of_expiry = value.substr(21,6);
        var date_of_expiry_cs = value.substr(27,1);
        var all_numbers =  passport_no + passport_no_cs + date_of_birth + date_of_birth_cs + date_of_expiry + date_of_expiry_cs;
        var all_numbers_cs = value.substr(value.length-1,1);

        if (checkSum(passport_no) - passport_no_cs != 0) 
          return false;
        if (checkSum(date_of_birth) - date_of_birth_cs != 0) 
          return false;
        if (checkSum(date_of_expiry) - date_of_expiry_cs != 0) 
          return false;
        if (checkSum(all_numbers) - all_numbers_cs != 0) 
          return false;

        return true;
      }

      function checkSum(s) {
        var c, i, sum = 0;
        var multiplikator = [7,3,1];
        var mult = 0;

        for(i=0; i<s.length; i++) {
          c = s.substr(i,1);
          if (isNaN(c)) return -1;
          sum += c * multiplikator[mult];
          mult = ++mult % 3;
        }
        return sum % 10;
      }
    }
  };
     
})(jQuery);

/**
 *  Based on http://gsgd.co.uk/sandbox/jquery/easing/
 */
jQuery.extend( jQuery.easing, {
  def: 'easeOutQuad',
  swing: function (x, t, b, c, d) {
    return jQuery.easing[jQuery.easing.def](x, t, b, c, d);
  },
  easeInQuad: function (x, t, b, c, d) {
    return c*(t/=d)*t + b;
  },
  easeOutQuad: function (x, t, b, c, d) {
    return -c *(t/=d)*(t-2) + b;
  },
  easeInOutQuad: function (x, t, b, c, d) {
    if ((t/=d/2) < 1) return c/2*t*t + b;
    return -c/2 * ((--t)*(t-2) - 1) + b;
  },
  easeInCubic: function (x, t, b, c, d) {
    return c*(t/=d)*t*t + b;
  },
  easeOutCubic: function (x, t, b, c, d) {
    return c*((t=t/d-1)*t*t + 1) + b;
  },
  easeInOutCubic: function (x, t, b, c, d) {
    if ((t/=d/2) < 1) return c/2*t*t*t + b;
    return c/2*((t-=2)*t*t + 2) + b;
  },
  easeInQuart: function (x, t, b, c, d) {
    return c*(t/=d)*t*t*t + b;
  },
  easeOutQuart: function (x, t, b, c, d) {
    return -c * ((t=t/d-1)*t*t*t - 1) + b;
  },
  easeInOutQuart: function (x, t, b, c, d) {
    if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
    return -c/2 * ((t-=2)*t*t*t - 2) + b;
  },
  easeInQuint: function (x, t, b, c, d) {
    return c*(t/=d)*t*t*t*t + b;
  },
  easeOutQuint: function (x, t, b, c, d) {
    return c*((t=t/d-1)*t*t*t*t + 1) + b;
  },
  easeInOutQuint: function (x, t, b, c, d) {
    if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
    return c/2*((t-=2)*t*t*t*t + 2) + b;
  },
  easeInSine: function (x, t, b, c, d) {
    return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
  },
  easeOutSine: function (x, t, b, c, d) {
    return c * Math.sin(t/d * (Math.PI/2)) + b;
  },
  easeInOutSine: function (x, t, b, c, d) {
    return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
  },
  easeInExpo: function (x, t, b, c, d) {
    return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
  },
  easeOutExpo: function (x, t, b, c, d) {
    return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
  },
  easeInOutExpo: function (x, t, b, c, d) {
    if (t==0) return b;
    if (t==d) return b+c;
    if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
    return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
  },
  easeInCirc: function (x, t, b, c, d) {
    return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
  },
  easeOutCirc: function (x, t, b, c, d) {
    return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
  },
  easeInOutCirc: function (x, t, b, c, d) {
    if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
    return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
  },
  easeInElastic: function (x, t, b, c, d) {
    var s=1.70158;var p=0;var a=c;
    if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
    if (a < Math.abs(c)) { a=c; var s=p/4; }
    else var s = p/(2*Math.PI) * Math.asin (c/a);
    return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
  },
  easeOutElastic: function (x, t, b, c, d) {
    var s=1.70158;var p=0;var a=c;
    if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
    if (a < Math.abs(c)) { a=c; var s=p/4; }
    else var s = p/(2*Math.PI) * Math.asin (c/a);
    return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
  },
  easeInOutElastic: function (x, t, b, c, d) {
    var s=1.70158;var p=0;var a=c;
    if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
    if (a < Math.abs(c)) { a=c; var s=p/4; }
    else var s = p/(2*Math.PI) * Math.asin (c/a);
    if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
    return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
  },
  easeInBack: function (x, t, b, c, d, s) {
    if (s == undefined) s = 1.70158;
    return c*(t/=d)*t*((s+1)*t - s) + b;
  },
  easeOutBack: function (x, t, b, c, d, s) {
    if (s == undefined) s = 1.70158;
    return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
  },
  easeInOutBack: function (x, t, b, c, d, s) {
    if (s == undefined) s = 1.70158; 
    if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
    return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
  },
  easeInBounce: function (x, t, b, c, d) {
    return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
  },
  easeOutBounce: function (x, t, b, c, d) {
    if ((t/=d) < (1/2.75)) {
      return c*(7.5625*t*t) + b;
    } else if (t < (2/2.75)) {
      return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
    } else if (t < (2.5/2.75)) {
      return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
    } else {
      return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
    }
  },
  easeOutBounceBig: function (x, t, b, c, d) {
    if ((t/=d) < (1/2.75)) {
      return c*(7.5625*t*t) + b;
    } else if (t < (2/2.75)) {
      return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
    } else if (t < (2.5/2.75)) {
      return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
    } else if (t < (3/2.75)){
      return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
    } else {
      return c*(7.5625*(t-=(2,8125/2.75))*t + .9984375) + b;
    }
  },
  easeInOutBounce: function (x, t, b, c, d) {
    if (t < d/2) return jQuery.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
    return jQuery.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
  }
});/*!
 * JavaScript Cookie v2.0.3
 * https://github.com/js-cookie/js-cookie
 *
 * Copyright 2006, 2015 Klaus Hartl & Fagner Brack
 * Released under the MIT license
 */
(function (factory) {
	if (typeof define === 'function' && define.amd) {
		define(factory);
	} else if (typeof exports === 'object') {
		module.exports = factory();
	} else {
		var _OldCookies = window.Cookies;
		var api = window.Cookies = factory();
		api.noConflict = function () {
			window.Cookies = _OldCookies;
			return api;
		};
	}
}(function () {
	function extend () {
		var i = 0;
		var result = {};
		for (; i < arguments.length; i++) {
			var attributes = arguments[ i ];
			for (var key in attributes) {
				result[key] = attributes[key];
			}
		}
		return result;
	}

	function init (converter) {
		function api (key, value, attributes) {
			var result;

			// Write

			if (arguments.length > 1) {
				attributes = extend({
					path: '/'
				}, api.defaults, attributes);

				if (typeof attributes.expires === 'number') {
					var expires = new Date();
					expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
					attributes.expires = expires;
				}

				try {
					result = JSON.stringify(value);
					if (/^[\{\[]/.test(result)) {
						value = result;
					}
				} catch (e) {}

				value = encodeURIComponent(String(value));
				value = value.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);

				key = encodeURIComponent(String(key));
				key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
				key = key.replace(/[\(\)]/g, escape);

				return (document.cookie = [
					key, '=', value,
					attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE
					attributes.path    && '; path=' + attributes.path,
					attributes.domain  && '; domain=' + attributes.domain,
					attributes.secure ? '; secure' : ''
				].join(''));
			}

			// Read

			if (!key) {
				result = {};
			}

			// To prevent the for loop in the first place assign an empty array
			// in case there are no cookies at all. Also prevents odd result when
			// calling "get()"
			var cookies = document.cookie ? document.cookie.split('; ') : [];
			var rdecode = /(%[0-9A-Z]{2})+/g;
			var i = 0;

			for (; i < cookies.length; i++) {
				var parts = cookies[i].split('=');
				var name = parts[0].replace(rdecode, decodeURIComponent);
				var cookie = parts.slice(1).join('=');

				if (cookie.charAt(0) === '"') {
					cookie = cookie.slice(1, -1);
				}

				try {
					cookie = converter && converter(cookie, name) || cookie.replace(rdecode, decodeURIComponent);

					if (this.json) {
						try {
							cookie = JSON.parse(cookie);
						} catch (e) {}
					}

					if (key === name) {
						result = cookie;
						break;
					}

					if (!key) {
						result[name] = cookie;
					}
				} catch (e) {}
			}

			return result;
		}

		api.get = api.set = api;
		api.getJSON = function () {
			return api.apply({
				json: true
			}, [].slice.call(arguments));
		};
		api.defaults = {};

		api.remove = function (key, attributes) {
			api(key, '', extend(attributes, {
				expires: -1
			}));
		};

		api.withConverter = init;

		return api;
	}

	return init();
}));
// Simple JavaScript Templating
// John Resig - http://ejohn.org/ - MIT Licensed
(function(){
  var cache = {};
  
  this.tmpl = function tmpl(str, data){
    // Figure out if we're getting a template, or if we need to
    // load the template - and be sure to cache the result.
    var fn = !/\W/.test(str) ?
      cache[str] = cache[str] ||
        tmpl(document.getElementById(str).innerHTML) :
      
      // Generate a reusable function that will serve as a template
      // generator (and which will be cached).
      new Function("obj",
        "var p=[],print=function(){p.push.apply(p,arguments);};" +
        
        // Introduce the data as local variables using with(){}
        "with(obj){p.push('" +
        
        // Convert the template into pure JavaScript
        str
          .replace(/[\r\t\n]/g, " ")
          .split("<%").join("\t")
          .replace(/((^|%>)[^\t]*)'/g, "$1\r")
          .replace(/\t=(.*?)%>/g, "',$1,'")
          .split("\t").join("');")
          .split("%>").join("p.push('")
          .split("\r").join("\\'")
      + "');}return p.join('');");
    
    // Provide some basic currying to the user
    return data ? fn( data ) : fn;
  };
})();


/**
 * draggable - Class allows to make any element draggable
 * 
 * Written by
 * Egor Khmelev (hmelyoff@gmail.com)
 *
 * Licensed under the MIT (MIT-LICENSE.txt).
 *
 * @author Egor Khmelev
 * @version 0.1.0-BETA ($Id$)
 * 
 **/

(function( $ ){

  function Draggable(){
    this._init.apply( this, arguments );
  };

  Draggable.prototype.oninit = function(){
    
  };
  
  Draggable.prototype.events = function(){
    
  };
  
  Draggable.prototype.onmousedown = function(){
    this.ptr.css({ position: "absolute" });
  };
  
  Draggable.prototype.onmousemove = function( evt, x, y ){
    this.ptr.css({ left: x, top: y });
  };
  
  Draggable.prototype.onmouseup = function(){
    
  };

  Draggable.prototype.isDefault = {
    drag: false,
    clicked: false,
    toclick: true,
    mouseup: false
  };

  Draggable.prototype._init = function(){
    if( arguments.length > 0 ){
      this.ptr = $(arguments[0]);
      this.outer = $(".draggable-outer");

      this.is = {};
      $.extend( this.is, this.isDefault );

      var _offset = this.ptr.offset();
      this.d = {
        left: _offset.left,
        top: _offset.top,
        width: this.ptr.width(),
        height: this.ptr.height()
      };

      this.oninit.apply( this, arguments );

      this._events();
    }
  };
  
  Draggable.prototype._getPageCoords = function( event ){
    if( event.targetTouches && event.targetTouches[0] ){
      return { x: event.targetTouches[0].pageX, y: event.targetTouches[0].pageY };
    } else
      return { x: event.pageX, y: event.pageY };
  };
  
  Draggable.prototype._bindEvent = function( ptr, eventType, handler ){
    var self = this;

    if( this.supportTouches_ )
      ptr.get(0).addEventListener( this.events_[ eventType ], handler, false );
    
    else
      ptr.bind( this.events_[ eventType ], handler );
  };
  
  Draggable.prototype._events = function(){
    var self = this;

    this.supportTouches_ = 'ontouchend' in document;
    this.events_ = {
      "click": this.supportTouches_ ? "touchstart" : "click",
      "down": this.supportTouches_ ? "touchstart" : "mousedown",
      "move": this.supportTouches_ ? "touchmove" : "mousemove",
      "up"  : this.supportTouches_ ? "touchend" : "mouseup"
    };

    this._bindEvent( $( document ), "move", function( event ){
      if( self.is.drag ){
        event.stopPropagation();
        event.preventDefault();
        self._mousemove( event );
      }
    });
    this._bindEvent( $( document ), "down", function( event ){
      if( self.is.drag ){
        event.stopPropagation();
        event.preventDefault();
      }
    });
    this._bindEvent( $( document ), "up", function( event ){
      self._mouseup( event );
    });
    
    this._bindEvent( this.ptr, "down", function( event ){
      self._mousedown( event );
      return false;
    });
    this._bindEvent( this.ptr, "up", function( event ){
      self._mouseup( event );
    });
    
    this.ptr.find("a")
      .click(function(){
        self.is.clicked = true;

        if( !self.is.toclick ){
          self.is.toclick = true;
          return false;
        }
      })
      .mousedown(function( event ){
        self._mousedown( event );
        return false;
      });

    this.events();
  };
  
  Draggable.prototype._mousedown = function( evt ){
    this.is.drag = true;
    this.is.clicked = false;
    this.is.mouseup = false;

    var _offset = this.ptr.offset();
    var coords = this._getPageCoords( evt );
    this.cx = coords.x - _offset.left;
    this.cy = coords.y - _offset.top;

    $.extend(this.d, {
      left: _offset.left,
      top: _offset.top,
      width: this.ptr.width(),
      height: this.ptr.height()
    });

    if( this.outer && this.outer.get(0) ){
      this.outer.css({ height: Math.max(this.outer.height(), $(document.body).height()), overflow: "hidden" });
    }

    this.onmousedown( evt );
  };
  
  Draggable.prototype._mousemove = function( evt ){
    this.is.toclick = false;
    var coords = this._getPageCoords( evt );
    this.onmousemove( evt, coords.x - this.cx, coords.y - this.cy );
  };
  
  Draggable.prototype._mouseup = function( evt ){
    var oThis = this;

    if( this.is.drag ){
      this.is.drag = false;

      if( this.outer && this.outer.get(0) ){

        if( $.browser.mozilla ){
          this.outer.css({ overflow: "hidden" });
        } else {
          this.outer.css({ overflow: "visible" });
        }

        if( $.browser.msie && $.browser.version == '6.0' ){
         this.outer.css({ height: "100%" });
        } else {
         this.outer.css({ height: "auto" });
        }  
      }

      this.onmouseup( evt );
    }
  };
  
  window.Draggable = Draggable;

})( jQuery );



/**
 * jquery.dependClass - Attach class based on first class in list of current element
 * 
 * Written by
 * Egor Khmelev (hmelyoff@gmail.com)
 *
 * Licensed under the MIT (MIT-LICENSE.txt).
 *
 * @author Egor Khmelev
 * @version 0.1.0-BETA ($Id$)
 * 
 **/

(function($) {
  $.baseClass = function(obj){
    obj = $(obj);
    return obj.get(0).className.match(/([^ ]+)/)[1];
  };
  
  $.fn.addDependClass = function(className, delimiter){
    var options = {
      delimiter: delimiter ? delimiter : '-'
    }
    return this.each(function(){
      var baseClass = $.baseClass(this);
      if(baseClass)
        $(this).addClass(baseClass + options.delimiter + className);
    });
  };

  $.fn.removeDependClass = function(className, delimiter){
    var options = {
      delimiter: delimiter ? delimiter : '-'
    }
    return this.each(function(){
      var baseClass = $.baseClass(this);
      if(baseClass)
        $(this).removeClass(baseClass + options.delimiter + className);
    });
  };

  $.fn.toggleDependClass = function(className, delimiter){
    var options = {
      delimiter: delimiter ? delimiter : '-'
    }
    return this.each(function(){
      var baseClass = $.baseClass(this);
      if(baseClass)
        if($(this).is("." + baseClass + options.delimiter + className))
          $(this).removeClass(baseClass + options.delimiter + className);
        else
          $(this).addClass(baseClass + options.delimiter + className);
    });
  };

})(jQuery);



/**
 * jquery.slider - Slider ui control in jQuery
 * 
 * Written by
 * Egor Khmelev (hmelyoff@gmail.com)
 *
 * Licensed under the MIT (MIT-LICENSE.txt).
 *
 * @author Egor Khmelev
 * @version 1.1.0-RELEASE ($Id$)
 * 
 * Dependencies
 * 
 * jQuery (http://jquery.com)
 * jquery.numberformatter (http://code.google.com/p/jquery-numberformatter/)
 * tmpl (http://ejohn.org/blog/javascript-micro-templating/)
 * jquery.dependClass
 * draggable
 * 
 **/

(function( $ ) {
  
  function isArray( value ){
    if( typeof value == "undefined" ) return false;
    
    if (value instanceof Array || (!(value instanceof Object) &&
         (Object.prototype.toString.call((value)) == '[object Array]') ||
         typeof value.length == 'number' &&
         typeof value.splice != 'undefined' &&
         typeof value.propertyIsEnumerable != 'undefined' &&
         !value.propertyIsEnumerable('splice')
        )) {
      return true;
    }
    
    return false;
  }

	$.slider = function( node, settings ){
	  var jNode = $(node);
	  if( !jNode.data( "jslider" ) )
	    jNode.data( "jslider", new jSlider( node, settings ) );
	  
	  return jNode.data( "jslider" );
	};
	
	$.fn.slider = function( action, opt_value ){
	  var returnValue, args = arguments;
	  
	  function isDef( val ){
	    return val !== undefined;
	  };

	  function isDefAndNotNull( val ){
      return val != null;
	  };
	  
		this.each(function(){
		  var self = $.slider( this, action );
		  
		  // do actions
		  if( typeof action == "string" ){
		    switch( action ){
		      case "value":
		        if( isDef( args[ 1 ] ) && isDef( args[ 2 ] ) ){
		          var pointers = self.getPointers();
		          if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){
		            pointers[0].set( args[ 1 ] );
		            pointers[0].setIndexOver();
		          }
		          
		          if( isDefAndNotNull( pointers[1] ) && isDefAndNotNull( args[2] ) ){
		            pointers[1].set( args[ 2 ] );
		            pointers[1].setIndexOver();
		          }
		        }
		        
		        else if( isDef( args[ 1 ] ) ){
		          var pointers = self.getPointers();
		          if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){
		            pointers[0].set( args[ 1 ] );
		            pointers[0].setIndexOver();
		          }
		        }
		        
		        else
  		        returnValue = self.getValue();

		        break;

		      case "prc":
		        if( isDef( args[ 1 ] ) && isDef( args[ 2 ] ) ){
		          var pointers = self.getPointers();
		          if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){
		            pointers[0]._set( args[ 1 ] );
		            pointers[0].setIndexOver();
		          }

		          if( isDefAndNotNull( pointers[1] ) && isDefAndNotNull( args[2] ) ){
		            pointers[1]._set( args[ 2 ] );
		            pointers[1].setIndexOver();
		          }
		        }

		        else if( isDef( args[ 1 ] ) ){
		          var pointers = self.getPointers();
		          if( isDefAndNotNull( pointers[0] ) && isDefAndNotNull( args[1] ) ){
		            pointers[0]._set( args[ 1 ] );
		            pointers[0].setIndexOver();
		          }
		        }

		        else
  		        returnValue = self.getPrcValue();

		        break;

  		    case "calculatedValue":
  		      var value = self.getValue().split(";");
  		      returnValue = "";
  		      for (var i=0; i < value.length; i++) {
  		        returnValue += (i > 0 ? ";" : "") + self.nice( value[i] );
  		      };
  		      
  		      break;
  		      
  		    case "skin":
		        self.setSkin( args[1] );

  		      break;
		    };
		  
		  }
		  
		  // return actual object
		  else if( !action && !opt_value ){
		    if( !isArray( returnValue ) )
		      returnValue = [];

		    returnValue.push( self );
		  }
		});
		
		// flatten array just with one slider
		if( isArray( returnValue ) && returnValue.length == 1 )
		  returnValue = returnValue[ 0 ];
		
		return returnValue || this;
	};
  
  var OPTIONS = {

    settings: {
      from: 1,
      to: 10,
      step: 1,
      smooth: true,
      limits: true,
      round: 0,
      format: { format: "#,##0.##" },
      value: "5;7",
      dimension: ""
    },
    
    className: "jslider",
    selector: ".jslider-",

    template: tmpl(
      '<span class="<%=className%>">' +
        '<table><tr><td>' +
          '<div class="<%=className%>-bg">' +
            '<i class="l"></i><i class="f"></i><i class="r"></i>' +
            '<i class="v"></i>' +
          '</div>' +

          '<div class="<%=className%>-pointer"></div>' +
          '<div class="<%=className%>-pointer <%=className%>-pointer-to"></div>' +
        
          '<div class="<%=className%>-label"><span><%=settings.from%></span></div>' +
          '<div class="<%=className%>-label <%=className%>-label-to"><span><%=settings.to%></span><%=settings.dimension%></div>' +

          '<div class="<%=className%>-value"><span></span><%=settings.dimension%></div>' +
          '<div class="<%=className%>-value <%=className%>-value-to"><span></span><%=settings.dimension%></div>' +
          
          '<div class="<%=className%>-scale"><%=scale%></div>'+

        '</td></tr></table>' +
      '</span>'
    )
    
  };

  function jSlider(){
  	return this.init.apply( this, arguments );
  };

  jSlider.prototype.init = function( node, settings ){
    this.settings = $.extend(true, {}, OPTIONS.settings, settings ? settings : {});
    
    // obj.sliderHandler = this;
    this.inputNode = $( node ).hide();
    						
		this.settings.interval = this.settings.to-this.settings.from;
		this.settings.value = this.inputNode.attr("value");
		
		if( this.settings.calculate && $.isFunction( this.settings.calculate ) )
		  this.nice = this.settings.calculate;

		if( this.settings.onstatechange && $.isFunction( this.settings.onstatechange ) )
		  this.onstatechange = this.settings.onstatechange;

    this.is = {
      init: false
    };
		this.o = {};

    this.create();
  };
  
  jSlider.prototype.onstatechange = function(){
    
  };
  
  jSlider.prototype.create = function(){
    var $this = this;
    
    this.domNode = $( OPTIONS.template({
      className: OPTIONS.className,
      settings: {
        from: this.nice( this.settings.from ),
        to: this.nice( this.settings.to ),
        dimension: this.settings.dimension
      },
      scale: this.generateScale()
    }) );
    
    this.inputNode.after( this.domNode );
    this.drawScale();
    
    // set skin class
    if( this.settings.skin && this.settings.skin.length > 0 )
      this.setSkin( this.settings.skin );

		this.sizes = {
		  domWidth: this.domNode.width(),
		  domOffset: this.domNode.offset()
		};

    // find some objects
    $.extend(this.o, {
      pointers: {},
      labels: {
        0: {
          o: this.domNode.find(OPTIONS.selector + "value").not(OPTIONS.selector + "value-to")
        },
        1: {
          o: this.domNode.find(OPTIONS.selector + "value").filter(OPTIONS.selector + "value-to")
        }
      },
      limits: {
        0: this.domNode.find(OPTIONS.selector + "label").not(OPTIONS.selector + "label-to"),
        1: this.domNode.find(OPTIONS.selector + "label").filter(OPTIONS.selector + "label-to")
      }
    });

    $.extend(this.o.labels[0], {
      value: this.o.labels[0].o.find("span")
    });

    $.extend(this.o.labels[1], {
      value: this.o.labels[1].o.find("span")
    });

    
    if( !$this.settings.value.split(";")[1] ){
      this.settings.single = true;
      this.domNode.addDependClass("single");
    }

    if( !$this.settings.limits )
      this.domNode.addDependClass("limitless");

    this.domNode.find(OPTIONS.selector + "pointer").each(function( i ){
      var value = $this.settings.value.split(";")[i];
      if( value ){
        $this.o.pointers[i] = new jSliderPointer( this, i, $this );

        var prev = $this.settings.value.split(";")[i-1];
        if( prev && new Number(value) < new Number(prev) ) value = prev;

        value = value < $this.settings.from ? $this.settings.from : value;
        value = value > $this.settings.to ? $this.settings.to : value;
      
        $this.o.pointers[i].set( value, true );
      }
    });
    
    this.o.value = this.domNode.find(".v");
    this.is.init = true;
    
    $.each(this.o.pointers, function(i){
      $this.redraw(this);
    });
    
    (function(self){
      $(window).resize(function(){
        self.onresize();
      });
    })(this);

  };
  
  jSlider.prototype.setSkin = function( skin ){
    if( this.skin_ )
      this.domNode.removeDependClass( this.skin_, "_" );

    this.domNode.addDependClass( this.skin_ = skin, "_" );
  };
  
  jSlider.prototype.setPointersIndex = function( i ){
    $.each(this.getPointers(), function(i){
      this.index( i );
    });
  };
  
  jSlider.prototype.getPointers = function(){
    return this.o.pointers;
  };
  
  jSlider.prototype.generateScale = function(){
    if( this.settings.scale && this.settings.scale.length > 0 ){
      var str = "";
      var s = this.settings.scale;
      var prc = Math.round((100/(s.length-1))*10)/10;
      for( var i=0; i < s.length; i++ ){
        str += '<span style="left: ' + i*prc + '%">' + ( s[i] != '|' ? '<ins>' + s[i] + '</ins>' : '' ) + '</span>';
      };
      return str;
    } else return "";

    return "";
  };
  
  jSlider.prototype.drawScale = function(){
    this.domNode.find(OPTIONS.selector + "scale span ins").each(function(){
      $(this).css({ marginLeft: -$(this).outerWidth()/2 });
    });
  };
  
  jSlider.prototype.onresize = function(){
    var self = this;
		this.sizes = {
		  domWidth: this.domNode.width(),
		  domOffset: this.domNode.offset()
		};

    $.each(this.o.pointers, function(i){
      self.redraw(this);
    });
  };
  
  jSlider.prototype.update = function(){
    this.onresize();
    this.drawScale();
  };
  
  jSlider.prototype.limits = function( x, pointer ){
	  // smooth
	  if( !this.settings.smooth ){
	    var step = this.settings.step*100 / ( this.settings.interval );
	    x = Math.round( x/step ) * step;
	  }
	  
	  var another = this.o.pointers[1-pointer.uid];
	  if( another && pointer.uid && x < another.value.prc ) x = another.value.prc;
	  if( another && !pointer.uid && x > another.value.prc ) x = another.value.prc;

    // base limit
	  if( x < 0 ) x = 0;
	  if( x > 100 ) x = 100;
	  
    return Math.round( x*10 ) / 10;
  };
  
  jSlider.prototype.redraw = function( pointer ){
    if( !this.is.init ) return false;
    
    this.setValue();
    
    // redraw range line
    if( this.o.pointers[0] && this.o.pointers[1] )
      this.o.value.css({ left: this.o.pointers[0].value.prc + "%", width: ( this.o.pointers[1].value.prc - this.o.pointers[0].value.prc ) + "%" });

    this.o.labels[pointer.uid].value.html(
      this.nice(
        pointer.value.origin
      )
    );
    
    // redraw position of labels
    this.redrawLabels( pointer );

  };
  
  jSlider.prototype.redrawLabels = function( pointer ){

    function setPosition( label, sizes, prc ){
  	  sizes.margin = -sizes.label/2;

      // left limit
      label_left = sizes.border + sizes.margin;
      if( label_left < 0 )
        sizes.margin -= label_left;

      // right limit
      if( sizes.border+sizes.label / 2 > self.sizes.domWidth ){
        sizes.margin = 0;
        sizes.right = true;
      } else
        sizes.right = false;
        
      label.o.css({ left: prc + "%", marginLeft: sizes.margin, right: "auto" });
      if( sizes.right ) label.o.css({ left: "auto", right: 0 });
      return sizes;
    }

    var self = this;
	  var label = this.o.labels[pointer.uid];
	  var prc = pointer.value.prc;

	  var sizes = {
	    label: label.o.outerWidth(),
	    right: false,
	    border: ( prc * this.sizes.domWidth ) / 100
	  };

    if( !this.settings.single ){
      // glue if near;
      var another = this.o.pointers[1-pointer.uid];
    	var another_label = this.o.labels[another.uid];

      switch( pointer.uid ){
        case 0:
          if( sizes.border+sizes.label / 2 > another_label.o.offset().left-this.sizes.domOffset.left ){
            another_label.o.css({ visibility: "hidden" });
        	  another_label.value.html( this.nice( another.value.origin ) );

          	label.o.css({ visibility: "visible" });

          	prc = ( another.value.prc - prc ) / 2 + prc;
          	if( another.value.prc != pointer.value.prc ){
          	  label.value.html( this.nice(pointer.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(another.value.origin) );
            	sizes.label = label.o.outerWidth();
            	sizes.border = ( prc * this.sizes.domWidth ) / 100;
            }
          } else {
          	another_label.o.css({ visibility: "visible" });
          }
          break;

        case 1:
          if( sizes.border - sizes.label / 2 < another_label.o.offset().left - this.sizes.domOffset.left + another_label.o.outerWidth() ){
            another_label.o.css({ visibility: "hidden" });
        	  another_label.value.html( this.nice(another.value.origin) );

          	label.o.css({ visibility: "visible" });

          	prc = ( prc - another.value.prc ) / 2 + another.value.prc;
          	if( another.value.prc != pointer.value.prc ){
          	  label.value.html( this.nice(another.value.origin) + "&nbsp;&ndash;&nbsp;" + this.nice(pointer.value.origin) );
            	sizes.label = label.o.outerWidth();
            	sizes.border = ( prc * this.sizes.domWidth ) / 100;
            }
          } else {
            another_label.o.css({ visibility: "visible" });
          }
          break;
      }
    }

    sizes = setPosition( label, sizes, prc );
    
    /* draw second label */
    if( another_label ){
      var sizes = {
  	    label: another_label.o.outerWidth(),
  	    right: false,
  	    border: ( another.value.prc * this.sizes.domWidth ) / 100
  	  };
      sizes = setPosition( another_label, sizes, another.value.prc );
    }
	  
    this.redrawLimits();
  };
  
  jSlider.prototype.redrawLimits = function(){
	  if( this.settings.limits ){

      var limits = [ true, true ];

      for( key in this.o.pointers ){

        if( !this.settings.single || key == 0 ){
        
      	  var pointer = this.o.pointers[key];
          var label = this.o.labels[pointer.uid];
          var label_left = label.o.offset().left - this.sizes.domOffset.left;

      	  var limit = this.o.limits[0];
          if( label_left < limit.outerWidth() )
            limits[0] = false;

      	  var limit = this.o.limits[1];
      	  if( label_left + label.o.outerWidth() > this.sizes.domWidth - limit.outerWidth() )
      	    limits[1] = false;
      	}

      };

      for( var i=0; i < limits.length; i++ ){
        if( limits[i] )
          this.o.limits[i].fadeIn("fast");
        else
          this.o.limits[i].fadeOut("fast");
      };

	  }
  };
  
  jSlider.prototype.setValue = function(){
    var value = this.getValue();
    this.inputNode.attr( "value", value );
    this.onstatechange.call( this, value );
  };

  jSlider.prototype.getValue = function(){
    if(!this.is.init) return false;
    var $this = this;
    
    var value = "";
    $.each( this.o.pointers, function(i){
      if( this.value.prc != undefined && !isNaN(this.value.prc) ) value += (i > 0 ? ";" : "") + $this.prcToValue( this.value.prc );
    });
    return value;
  };

  jSlider.prototype.getPrcValue = function(){
    if(!this.is.init) return false;
    var $this = this;
    
    var value = "";
    $.each( this.o.pointers, function(i){
      if( this.value.prc != undefined && !isNaN(this.value.prc) ) value += (i > 0 ? ";" : "") + this.value.prc;
    });
    return value;
  };
  
  jSlider.prototype.prcToValue = function( prc ){

	  if( this.settings.heterogeneity && this.settings.heterogeneity.length > 0 ){
  	  var h = this.settings.heterogeneity;

  	  var _start = 0;
  	  var _from = this.settings.from;

  	  for( var i=0; i <= h.length; i++ ){
  	    if( h[i] ) var v = h[i].split("/");
  	    else       var v = [100, this.settings.to];
  	    
  	    v[0] = new Number(v[0]);
  	    v[1] = new Number(v[1]);
  	      
  	    if( prc >= _start && prc <= v[0] ) {
  	      var value = _from + ( (prc-_start) * (v[1]-_from) ) / (v[0]-_start);
  	    }

  	    _start = v[0];
  	    _from = v[1];
  	  };

	  } else {
      var value = this.settings.from + ( prc * this.settings.interval ) / 100;
	  }

    return this.round( value );
  };
  
	jSlider.prototype.valueToPrc = function( value, pointer ){  	  
	  if( this.settings.heterogeneity && this.settings.heterogeneity.length > 0 ){
  	  var h = this.settings.heterogeneity;

  	  var _start = 0;
  	  var _from = this.settings.from;

  	  for (var i=0; i <= h.length; i++) {
  	    if(h[i]) var v = h[i].split("/");
  	    else     var v = [100, this.settings.to];
  	    v[0] = new Number(v[0]); v[1] = new Number(v[1]);
  	      
  	    if(value >= _from && value <= v[1]){
  	      var prc = pointer.limits(_start + (value-_from)*(v[0]-_start)/(v[1]-_from));
  	    }

  	    _start = v[0]; _from = v[1];
  	  };

	  } else {
  	  var prc = pointer.limits((value-this.settings.from)*100/this.settings.interval);
	  }

	  return prc;
	};
  
	jSlider.prototype.round = function( value ){
    value = Math.round( value / this.settings.step ) * this.settings.step;
		if( this.settings.round ) value = Math.round( value * Math.pow(10, this.settings.round) ) / Math.pow(10, this.settings.round);
		else value = Math.round( value );
		return value;
	};
	
	jSlider.prototype.nice = function( value ){
		value = value.toString().replace(/,/gi, ".").replace(/ /gi, "");;

		if( $.formatNumber ){
		  return $.formatNumber( new Number(value), this.settings.format || {} ).replace( /-/gi, "&minus;" );
		}
		  
		else {
		  return new Number(value);
		}
	};

  
  function jSliderPointer(){
  	Draggable.apply( this, arguments );
  }
  jSliderPointer.prototype = new Draggable();
  
  jSliderPointer.prototype.oninit = function( ptr, id, _constructor ){
    this.uid = id;
    this.parent = _constructor;
    this.value = {};
    this.settings = this.parent.settings;
  };
  
  jSliderPointer.prototype.onmousedown = function(evt){
	  this._parent = {
	    offset: this.parent.domNode.offset(),
	    width: this.parent.domNode.width()
	  };
	  this.ptr.addDependClass("hover");
	  this.setIndexOver();
	};

	jSliderPointer.prototype.onmousemove = function( evt, x ){
	  var coords = this._getPageCoords( evt );
	  this._set( this.calc( coords.x ) );
	};
	
	jSliderPointer.prototype.onmouseup = function( evt ){
	  if( this.parent.settings.callback && $.isFunction(this.parent.settings.callback) )
	    this.parent.settings.callback.call( this.parent, this.parent.getValue() );
	    
	  this.ptr.removeDependClass("hover");
	};
	
	jSliderPointer.prototype.setIndexOver = function(){
	  this.parent.setPointersIndex( 1 );
	  this.index( 2 );
	};
	
	jSliderPointer.prototype.index = function( i ){
	  this.ptr.css({ zIndex: i });
	};
	
	jSliderPointer.prototype.limits = function( x ){
	  return this.parent.limits( x, this );
	};
	
	jSliderPointer.prototype.calc = function(coords){
	  var x = this.limits(((coords-this._parent.offset.left)*100)/this._parent.width);
	  return x;
	};

	jSliderPointer.prototype.set = function( value, opt_origin ){
	  this.value.origin = this.parent.round(value);
	  this._set( this.parent.valueToPrc( value, this ), opt_origin );
	};
	
	jSliderPointer.prototype._set = function( prc, opt_origin ){
	  if( !opt_origin )
	    this.value.origin = this.parent.prcToValue(prc);

	  this.value.prc = prc;
		this.ptr.css({ left: prc + "%" });
	  this.parent.redraw(this);
	};
  
})(jQuery);

//20160803BVCM-01
$(document).ready(function(){
  $('.slider').each(function(index, element){

      $element = $(element);
      var data = $element.data('slide');
      if (data){
        /* Check if exists to prevent crashes */
        var exists = false;
        try { data.dimension; exists = true;} catch(e) {}

        if (!exists || typeof data.dimension === 'undefined') {
          data.dimension = settings.currencies['currency'+settings.currencyId].SYMBOL;
        }

        data.step = 1;
        var values = $element.attr('value').split(';');
        values[0] = Math.floor(values[0]);
        values[1] = Math.ceil(values[1]);
        $element.attr('value', values.join(";"));
        
        if(data.from >= 0 && data.to > 0){
          data.from = Math.floor(data.from);
          data.to = Math.ceil(data.to);   
          $element.attr('data-slide', JSON.stringify(data));
          data.callback=function(a,b){ this.inputNode.change() };
          $element.slider(data);  
        }
      }
    });
});(function($,window){"use strict";$.formUtils.addValidator({name:"spamcheck",validatorFunction:function(val,$el,config){var attr=$el.valAttr("captcha");return attr===val},errorMessage:"",errorMessageKey:"badSecurityAnswer"});$.formUtils.addValidator({name:"confirmation",validatorFunction:function(value,$el,config,language,$form){var conf="",confInputName=$el.valAttr("confirm")||$el.attr("name")+"_confirmation",confInput=$form.find('input[name="'+confInputName+'"]').eq(0);if(confInput){conf=confInput.val()}else{alert('Could not find an input with name "'+confInputName+'"')}return value===conf},errorMessage:"",errorMessageKey:"notConfirmed"});var creditCards={amex:[15,15],diners_club:[14,14],cjb:[16,16],laser:[16,19],visa:[16,16],mastercard:[16,16],maestro:[12,19],discover:[16,16]},checkOnlyAmex=false,allowsAmex=false;$.formUtils.addValidator({name:"creditcard",validatorFunction:function(value,$el,config,language,$form){var allowing=$.split($el.valAttr("allowing")||"");allowsAmex=$.inArray("amex",allowing)>-1;checkOnlyAmex=allowsAmex&&allowing.length==1;if(allowing.length>0){var hasValidLength=false;$.each(allowing,function(i,cardName){if(cardName in creditCards){if(value.length>=creditCards[cardName][0]&&value.length<=creditCards[cardName][1]){hasValidLength=true;return false}}else if(window.console){console.warn('Use of unknown credit card "'+cardName+'"')}});if(!hasValidLength)return false}if(value.replace(new RegExp("[0-9]","g"),"")!==""){return false}var checkSum=0;$.each(value.split("").reverse(),function(i,digit){digit=parseInt(digit,10);if(i%2===0){checkSum+=digit}else{digit*=2;if(digit<10){checkSum+=digit}else{checkSum+=digit-9}}});return checkSum%10===0},errorMessage:"",errorMessageKey:"badCreditCard"});$.formUtils.addValidator({name:"cvv",validatorFunction:function(val){if(val.replace(/[0-9]/g,"")===""){val=val+"";if(checkOnlyAmex){return val.length==4}else if(allowsAmex){return val.length==3||val.length==4}else{return val.length==3}}return false},errorMessage:"",errorMessageKey:"badCVV"});$.formUtils.addValidator({name:"strength",validatorFunction:function(val,$el,conf){var requiredStrength=$el.valAttr("strength")||2;if(requiredStrength&&requiredStrength>3)requiredStrength=3;return $.formUtils.validators.validate_strength.calculatePasswordStrength(val)>=requiredStrength},errorMessage:"",errorMessageKey:"badStrength",calculatePasswordStrength:function(password){if(password.length<4){return 0}var score=0;var checkRepetition=function(pLen,str){var res="";for(var i=0;i<str.length;i++){var repeated=true;for(var j=0;j<pLen&&j+i+pLen<str.length;j++){repeated=repeated&&str.charAt(j+i)==str.charAt(j+i+pLen)}if(j<pLen){repeated=false}if(repeated){i+=pLen-1;repeated=false}else{res+=str.charAt(i)}}return res};score+=password.length*4;score+=(checkRepetition(1,password).length-password.length)*1;score+=(checkRepetition(2,password).length-password.length)*1;score+=(checkRepetition(3,password).length-password.length)*1;score+=(checkRepetition(4,password).length-password.length)*1;if(password.match(/(.*[0-9].*[0-9].*[0-9])/)){score+=5}if(password.match(/(.*[!,@,#,$,%,^,&,*,?,_,~].*[!,@,#,$,%,^,&,*,?,_,~])/)){score+=5}if(password.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/)){score+=10}if(password.match(/([a-zA-Z])/)&&password.match(/([0-9])/)){score+=15}if(password.match(/([!,@,#,$,%,^,&,*,?,_,~])/)&&password.match(/([0-9])/)){score+=15}if(password.match(/([!,@,#,$,%,^,&,*,?,_,~])/)&&password.match(/([a-zA-Z])/)){score+=15}if(password.match(/^\w+$/)||password.match(/^\d+$/)){score-=10}if(score<0){score=0}if(score>100){score=100}if(score<20){return 0}else if(score<40){return 1}else if(score<=60){return 2}else{return 3}},strengthDisplay:function($el,options){var config={fontSize:"12pt",padding:"4px",bad:"Very bad",weak:"Weak",good:"Good",strong:"Strong"};if(options){$.extend(config,options)}$el.bind("keyup",function(){var val=$(this).val(),$parent=typeof config.parent=="undefined"?$(this).parent():$(config.parent),$displayContainer=$parent.find(".strength-meter"),strength=$.formUtils.validators.validate_strength.calculatePasswordStrength(val),css={background:"pink",color:"#FF0000",fontWeight:"bold",border:"red solid 1px",borderWidth:"0px 0px 4px",display:"inline-block",fontSize:config.fontSize,padding:config.padding},text=config.bad;if($displayContainer.length==0){$displayContainer=$("<span></span>");$displayContainer.addClass("strength-meter").appendTo($parent)}if(!val){$displayContainer.hide()}else{$displayContainer.show()}if(strength==1){text=config.weak}else if(strength==2){css.background="lightyellow";css.borderColor="yellow";css.color="goldenrod";text=config.good}else if(strength>=3){css.background="lightgreen";css.borderColor="darkgreen";css.color="darkgreen";text=config.strong}$displayContainer.css(css).text(text)})}});var requestServer=function(serverURL,$element,val,conf,callback){var reqParams=$element.valAttr("req-params")||$element.data("validation-req-params")||{},handleResponse=function(response,callback){if(response.valid){$element.valAttr("backend-valid","true")}else{$element.valAttr("backend-invalid","true");if(response.message)$element.attr(conf.validationErrorMsgAttribute,response.message)}if(!$element.valAttr("has-keyup-event")){$element.valAttr("has-keyup-event","1").bind("keyup change",function(evt){if(evt.keyCode!=9&&evt.keyCode!=16){$(this).valAttr("backend-valid",false).valAttr("backend-invalid",false)}})}callback()};if(!reqParams)reqParams={};if(typeof reqParams=="string"){reqParams=$.parseJSON(reqParams)}reqParams[$element.valAttr("param-name")||$element.attr("name")]=val;$.ajax({url:serverURL,type:"POST",cache:false,data:reqParams,dataType:"json",error:function(error,err){handleResponse({valid:false,message:"Connection failed with status: "+error.statusText},callback);return false},success:function(response){handleResponse(response,callback)}})},disableFormSubmit=function(){return false};$.formUtils.addValidator({name:"server",validatorFunction:function(val,$el,conf,lang,$form){var backendValid=$el.valAttr("backend-valid"),backendInvalid=$el.valAttr("backend-invalid"),serverURL=document.location.href;if($el.valAttr("url")){serverURL=$el.valAttr("url")}else if("serverURL"in conf){serverURL=conf.backendUrl}if(backendValid)return true;else if(backendInvalid)return false;else if($.formUtils.eventType=="keyup")return null;if($.formUtils.isValidatingEntireForm){$form.bind("submit",disableFormSubmit).addClass("validating-server-side").addClass("on-blur");$el.addClass("validating-server-side");$.formUtils.haltValidation=true;requestServer(serverURL,$el,val,conf,function(){$form.removeClass("validating-server-side").removeClass("on-blur").get(0).onsubmit=function(){};$form.unbind("submit",disableFormSubmit);$el.removeClass("validating-server-side");$el.valAttr("value-length",val.length);$.formUtils.haltValidation=false;$form.trigger("submit")});return null}else{$form.addClass("validating-server-side");$el.addClass("validating-server-side");requestServer(serverURL,$el,val,conf,function(){$form.removeClass("validating-server-side");$el.removeClass("validating-server-side");$el.trigger("blur")});return null}},errorMessage:"",errorMessageKey:"badBackend",validateOnKeyUp:false});$.fn.displayPasswordStrength=function(conf){new $.formUtils.validators.validate_strength.strengthDisplay(this,conf);return this}})(jQuery,window);
/* state 1: visible - 0: hidden */
function setCountryFormFields(state, fieldName) {
  if (!fieldName) return;
  if (!state) state = 0;
  
  if (window.countryUserFields) {
    window.countryUserFields[fieldName].state = state;

    if (window.countryUserFields[fieldName].formFields) {
      var countryUserFields = window.countryUserFields[fieldName].formFields;
      for (var i=0; i < countryUserFields.length; i++) {
        var fieldContainer = F('#userField'+ countryUserFields[i]+'Container');
        if (fieldContainer) {
          if (state) fieldContainer.style.display='block';
          else fieldContainer.style.display='none';
        }
      }
    }   
  }
};
 
function loadCountry(countryId, uniqueId, fieldName, className, inputType) {
  if (!inputType) inputType = 0;

  if (inputType == 1) {
    setCountryFormFields(1, fieldName);
    var container = $('#countriesSelectorContainer_'+uniqueId).parent('.userFormFields').find('.availableCountries');
    container.set('html', 'loading...<input type="text" class="required" value="" style="border:none; width:1px; height:1px; display:inline; padding:0px; margin:0px;" />');
    var parameterEncoder = new urlParameterEncoder()
      .addParameter('countryId', countryId)
      .addParameter('fieldName', fieldName)
      .addParameter('className', className)
      .addParameter('uniqueId',uniqueId)
      .addParameter('countryManualInput', 1)
      .addParameter('htmlFramework', window.htmlFramework);
    container.load('/templates/common/users/subcountriesSelector.cfm' + parameterEncoder.getParameters());
  }
  else {
    setCountryFormFields(0, fieldName);
    var container = $('countriesSelectorContainer_'+uniqueId);
    container.getParent('.userFormFields').getElements('.countryManualInputFields').destroy();
    container.set('html', 'loading...<input type="text" class="required" value="" style="border:none; width:1px; height:1px; display:inline; padding:0px; margin:0px;" />');
    var parameterEncoder = new urlParameterEncoder()
      .addParameter('countryId',countryId)
      .addParameter('subcountryId',0)
      .addParameter('fieldName',fieldName)
      .addParameter('className',className)
      .addParameter('uniqueId', uniqueId);
    container.load('/templates/common/users/subcountriesSelector.cfm'+parameterEncoder.getParameters());
  }
};

function loadSubcountries(countryId, subcountryId, uniqueId, fieldName, className, storedCountryId, showSubselects) {
  var $container = $('#countriesSelectorContainer_'+uniqueId);
  var $parent = $container.closest('.addressUserField');

  updateAddressDataBlock($parent);

  var $manualTab = $parent.find('[href^="#countryManualTab"]');
  var $suggestTab = $parent.find('[href^="#countrySuggestTab"]');

  // Control argument showSubselects
  if (arguments.length < 6) var showSubselects = 1;

  if(countryId.length == 0 || subcountryId.length == 0) {
    $container.html("");
    localizeCallbacks(fieldName);
    $manualTab.hide();
    $suggestTab.hide();
    if(subcountryId.length == 0) return;
  }

  if(subcountryId == 0 && countryId.length == 0) {
    $container.html("");
    $('#subcountriesSearch_'+uniqueId).html("");
    localizeCallbacks(fieldName);
    $manualTab.hide();
    $suggestTab.hide();
    return;
  }

  if (fieldName == 'country' && settings.forceBillingAddressCountry && $('#useShippingAddress').prop('checked') == true && $('#userShippingCountryField'))
  {
    if ($('#userFieldShippingCountryContainer .countriesSelector'))
    {
      $('#userShippingCountryField').find('option').remove().end().append($('<option>', {value:countryId}).text($("#userCountryField option[value='"+countryId+"']").text()));
      loadSubcountries(countryId, 0, $('#userShippingCountryField').attr('data-field'), 'shippingCountry', 'userField');      
    }
  }

  $container.closest('div.userFormFields').find('.countryManualInputFields').remove();
  $container.html('loading...<input type="text" class="required" value="" style="border:none; width:1px; height:1px; display:inline; padding:0px; margin:0px;" />');

  var userType = $container.closest('form').data('userType');

  var parameterEncoder = new urlParameterEncoder()
    .addParameter('countryId',countryId)
    .addParameter('subcountryId',subcountryId)
    .addParameter('fieldName',fieldName)
    .addParameter('className',className)
    .addParameter('uniqueId', uniqueId)
    .addParameter('onlyNextLevel', true)
    .addParameter('showSubselects', showSubselects)
    .addParameter('htmlFramework', window.htmlFramework)
    .addParameter('userType', userType);

  $container.load('/user/subcountriesSelector/' + parameterEncoder.getParameters(), function(){
    validateCountryFields(fieldName);
    localizeCallbacks(fieldName);
    setAddressCompleted($parent);
  });

  if(!subcountryId) {
    $manualTab.show();
    $suggestTab.show();

    parameterEncoder.addParameter('itemId',countryId)
      .addParameter('onlyNextLevel', true);

    $('#subcountriesSearch_'+uniqueId).html('').load('/user/subcountriesSearch/' + parameterEncoder.getParameters(), function() {
      if($('#subcountriesSearch_'+uniqueId).html() == '') {
        $manualTab.tab('show');
        $suggestTab.hide();
      }
    });
  }
};

function loadPostalCodes(element, countryId, value, uniqueId, fieldName, className, exec) {
  var container = F('#postalCodes_'+uniqueId);

  if(exec) {
    var parameterEncoder = new urlParameterEncoder()
      .addParameter('countryId',countryId)
      .addParameter('zip',value)
      .addParameter('uniqueId',uniqueId)
      .addParameter('fieldName',fieldName)
      .addParameter('className',className)
      .addParameter('width', $(element).parent().width())
      .addParameter('htmlFramework', window.htmlFramework);

    //Get
    $(container).load('/user/postalCodesSelector/'+encodeURI(parameterEncoder.getParameters()));
  }

  else if(value.length > 2) {
    if(container.timeout) clearTimeout(container.timeout);
    if(container.innerHTML.length < 30) container.innerHTML = '<div />';

    if(container.connect && container.connect.request.readyState != 0 && container.connect.request.readyState != 4)
      loadPostalCodes(element, countryId, value, uniqueId, fieldName, className, true)
    else
      container.timeout = setTimeout(function(){
        loadPostalCodes(element, countryId, value, uniqueId, fieldName, className, true);
      }, 400);
  }
  else {
    container.innerHTML = '';
  }
};

function selectPostalCode(countryId, subcountryId, uniqueId, fieldName, className) {
  var field = F('#zipField_'+uniqueId);
  var container = F('#countriesSelectorContainer_'+uniqueId);
  var selectorContainer = F('#postalCodes_'+uniqueId);

  validateCountryFields(fieldName);
  var $parent = $(field).closest('.addressUserField');

  selectorContainer.innerHTML = '';
  if (field.classList.contains('zipOrCitySearch')) {
    field.value = '';
    $parent.find('[href^="#countryManualTab"]').tab('show');
  }
  else {
    field.value = languageSheet.ZIPORCITY;
  }

  var parameterEncoder = new urlParameterEncoder()
    .addParameter('countryId',countryId)
    .addParameter('subcountryId',subcountryId)
    .addParameter('fieldName',fieldName)
    .addParameter('className',className);

  container.innerHTML = 'loading...<input type="text" class="required" value="" style="border:none; width:1px; height:1px; display:inline; padding:0px; margin:0px;" />';

  //Get
  $(container).load('/user/selectPostalCode/'+parameterEncoder.getParameters(), function(){
    localizeCallbacks(fieldName);
    if ($parent) {
      setAddressCompleted($parent);
    }
  });
};

function updateAddressDataBlock(parent) {
  var $container = parent.find('.addressBlockDetails');
  var $addressFields = getAddressFields(parent);

  $container.html("");

  $addressFields.each(function(index, el) {
    $addressBlock = $('<div />');
    if (index === 0) {
      $addressBlock.addClass('firstAddressBlock');
    }
    else if (index === ($addressFields.length - 1)) {
      $addressBlock.addClass('lastAddressBlock');
    }
    $addressBlock.addClass('addressBlock').addClass('addressBlock' + (index+1));

    var val = $(el).text();
    if (!val) {
      val = $(el).val();
    }

    $addressBlock.html(val);

    $addressBlock.appendTo($container);
  });
}

function setAddressCompleted(parent) {
  parent.removeClass('address-complete');

  var completed = true;

  getAddressFields(parent).each(function(index, el) {
    if (!$(el).val()) {
      completed = false;
      return;
    }
  });

  if (completed) {
    parent.addClass('address-complete');
  }

  updateAddressDataBlock(parent);
}

function resetCountrySelector(parent) {
  parent.find('select[name$="ountry_1"]').change(); // to avoid case-sensitive "c/C" of "country" selector
  setAddressCompleted(parent);
}

function getAddressFields(parent) {
  return parent.find('select > option:selected, input.userField').not(".subcountrySearchField");
}

var localizeEvents = {
  selectPostalCode : function(){},
  selectShippingPostalCode : function(){},
  selectAddressBookPostalCode : function(){}
};

function localizeCallbacks(fieldName){
  if (fieldName == 'country')
    localizeEvents.selectPostalCode();
  else if (fieldName == 'shippingCountry')
    localizeEvents.selectShippingPostalCode();
  else if (fieldName == 'addressBookCountry')
    localizeEvents.selectAddressBookPostalCode();
}

$(document).click(function(event) {
  if(!$(event.target).closest('.subcountrySearch').length) {
    if($('.citiesSelector').is(":visible"))
        $('.citiesSelector').html("")
  }
});

function validateCountryFields (fieldName){
  // Initialize Validation form
  if (Fluid)
    $.validate(Fluid.validateFormConf);
}

function onChangeCountry(countryId, uniqueId, fieldName, className, showSubselects) {

  // Control argument showSubselects
  if (arguments.length < 5) var showSubselects = 1;

  if (fieldName == 'country' && settings.forceBillingAddressCountry && $('#useShippingAddress').prop('checked') == true && $('#userShippingCountryField')) {
    if ($('#userFieldShippingCountryContainer .countriesSelector')) {
      $('#userShippingCountryField').find('option').remove().end().append($('<option>', {value:countryId}).text($("#userCountryField option[value='"+countryId+"']").text()));
      loadSubcountries(countryId, 0, $('#userShippingCountryField').attr('data-field'), 'shippingCountry', 'userField');      
    }
  }
  else {
    loadSubcountries(countryId, 0, uniqueId, fieldName, className, 0, showSubselects);
  }
}

/* ------------------------------------------------------------------------------*/
/* ------------------------------------------------------------------------------*/
/* ------------------------------------------------------------------------------*/
function onChangeCountryFlTgCountrySelector(countryId, uniqueId, fieldName, className, showSubselects) {

  // Control argument showSubselects
  if (arguments.length < 5) var showSubselects = 1;

  if (fieldName == 'country' && settings.forceBillingAddressCountry && $('#useShippingAddress').prop('checked') == true && $('#userShippingCountryField')) {
    if ($('#userFieldShippingCountryContainer .countriesSelector')) {
      $('#userShippingCountryField').find('option').remove().end().append($('<option>', {value:countryId}).text($("#userCountryField option[value='"+countryId+"']").text()));
      loadSubcountriesFlTgCountrySelector(countryId, 0, $('#userShippingCountryField').attr('data-field'), 'shippingCountry', 'userField');      
    }
  }
  else {
    loadSubcountriesFlTgCountrySelector(countryId, 0, uniqueId, fieldName, className, 0, showSubselects);
  }
}

function loadSubcountriesFlTgCountrySelector(countryId, subcountryId, uniqueId, fieldName, className, storedCountryId, showSubselects) {
  var $container = $('#countriesSelectorContainer_'+uniqueId);

  // Control argument showSubselects
  if (arguments.length < 6) var showSubselects = 1;

  if(subcountryId.length == 0) {
    $container.html("");
    localizeCallbacks(fieldName);
    return;
  }
  
  if(subcountryId == 0 && countryId.length == 0) {
    $container.html("");
    $('#subcountriesSearch_'+uniqueId).html("");
    localizeCallbacks(fieldName);
    return;
  }

  if (fieldName == 'country' && settings.forceBillingAddressCountry && $('#useShippingAddress').prop('checked') == true && $('#userShippingCountryField')) {
    if ($('#userFieldShippingCountryContainer .countriesSelector')) {
      $('#userShippingCountryField').find('option').remove().end().append($('<option>', {value:countryId}).text($("#userCountryField option[value='"+countryId+"']").text()));
      loadSubcountriesFlTgCountrySelector(countryId, 0, $('#userShippingCountryField').attr('data-field'), 'shippingCountry', 'userField');      
    }
  }

  $container.closest('div.userFormFields').find('.countryManualInputFields').remove();
  $container.html('loading...<input type="text" class="required" value="" style="border:none; width:1px; height:1px; display:inline; padding:0px; margin:0px;" />');

  var parameterEncoder = new urlParameterEncoder()
    .addParameter('countryId',countryId)
    .addParameter('subcountryId',subcountryId)
    .addParameter('fieldName',fieldName)
    .addParameter('className',className)
    .addParameter('uniqueId', uniqueId)
    .addParameter('onlyNextLevel', true)
    .addParameter('showSubselects', showSubselects)
    .addParameter('htmlFramework', window.htmlFramework);

  $container.load('/user/countrySelectorSubcountriesSelector/' + parameterEncoder.getParameters(), function(){
    validateCountryFields(fieldName);
    localizeCallbacks(fieldName);
  });

  if(!subcountryId) {
    parameterEncoder
      .addParameter('itemId',countryId)
      .addParameter('onlyNextLevel', true);

    $('#subcountriesSearch_'+uniqueId).html('').load('/user/countrySelectorSubcountriesSearch/' + parameterEncoder.getParameters());
  }
};

function onFocusNoSelectZip(input) {
  $(input).closest('div.subcountrySearchField').removeClass('has-error');
}
function onBlurNoSelectZip(input) {
  $(input).val('');
  if(!$(input).closest('.addressUserField').hasClass('address-complete')) {
    $(input).closest('div.subcountrySearchField').addClass('has-error');
  }
}
$('.countrySelectMode a[href*="#countrySuggestTab"]').on('hide.bs.tab', function(){
  var id = $(this).attr('href');
  $(id).find('div.subcountrySearchField').removeClass('has-error');
});
$('.addressUserField:visible').not('.address-complete').each(function(index, el) {
    var $selectCountry = $(el).find('.__selectCountry__');
    if ($selectCountry.length && $selectCountry.val().length > 0) {
        if (parseInt($(el).find('[id^="countrySuggestTab"] [type="hidden"][name$="ountry"]').val()) === -1) {
            $(el).find('[href^="#countryManualTab"]').hide().tab('show');
            $(el).find('[href^="#countrySuggestTab"]').hide();
        }
    }
});
