1/*! 2 * Webflow: Front-end site library 3 * @license MIT 4 * Inline scripts may access the api using an async handler: 5 * var Webflow = Webflow || []; 6 * Webflow.push(readyFunction); 7 */ 8(function () { 9 'use strict'; 10 11 function __commonjs(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } 12 13 /*! 14 * tram.js v0.8.2-global 15 * Cross-browser CSS3 transitions in JavaScript 16 * https://github.com/bkwld/tram 17 * MIT License 18 */ 19 window.tram=function(a){function b(a,b){var c=new M.Bare;return c.init(a,b)}function c(a){return a.replace(/[A-Z]/g,function(a){return"-"+a.toLowerCase()})}function d(a){var b=parseInt(a.slice(1),16),c=b>>16&255,d=b>>8&255,e=255&b;return[c,d,e]}function e(a,b,c){return"#"+(1<<24|a<<16|b<<8|c).toString(16).slice(1)}function f(){}function g(a,b){j("Type warning: Expected: ["+a+"] Got: ["+typeof b+"] "+b)}function h(a,b,c){j("Units do not match ["+a+"]: "+b+", "+c)}function i(a,b,c){if(void 0!==b&&(c=b),void 0===a)return c;var d=c;return $.test(a)||!_.test(a)?d=parseInt(a,10):_.test(a)&&(d=1e3*parseFloat(a)),0>d&&(d=0),d===d?d:c}function j(a){U.debug&&window&&window.console.warn(a)}function k(a){for(var b=-1,c=a?a.length:0,d=[];++b<c;){var e=a[b];e&&d.push(e)}return d}var l=function(a,b,c){function d(a){return"object"==typeof a}function e(a){return"function"==typeof a}function f(){}function g(h,i){function j(){var a=new k;return e(a.init)&&a.init.apply(a,arguments),a}function k(){}i===c&&(i=h,h=Object),j.Bare=k;var l,m=f[a]=h[a],n=k[a]=j[a]=new f;return n.constructor=j,j.mixin=function(b){return k[a]=j[a]=g(j,b)[a],j},j.open=function(a){if(l={}
19,e(a)?l=a.call(j,n,m,j,h):d(a)&&(l=a),d(l))for(var c in l)b.call(l,c)&&(n[c]=l[c]);return e(n.init)||(n.init=h),j},j.open(i)}return g}("prototype",{}.hasOwnProperty),m={ease:["ease",function(a,b,c,d){var e=(a/=d)*a,f=e*a;return b+c*(-2.75*f*e+11*e*e+-15.5*f+8*e+.25*a)}],"ease-in":["ease-in",function(a,b,c,d){var e=(a/=d)*a,f=e*a;return b+c*(-1*f*e+3*e*e+-3*f+2*e)}],"ease-out":["ease-out",function(a,b,c,d){var e=(a/=d)*a,f=e*a;return b+c*(.3*f*e+-1.6*e*e+2.2*f+-1.8*e+1.9*a)}],"ease-in-out":["ease-in-out",function(a,b,c,d){var e=(a/=d)*a,f=e*a;return b+c*(2*f*e+-5*e*e+2*f+2*e)}],linear:["linear",function(a,b,c,d){return c*a/d+b}],"ease-in-quad":["cubic-bezier(0.550, 0.085, 0.680, 0.530)",function(a,b,c,d){return c*(a/=d)*a+b}],"ease-out-quad":["cubic-bezier(0.250, 0.460, 0.450, 0.940)",function(a,b,c,d){return-c*(a/=d)*(a-2)+b}],"ease-in-out-quad":["cubic-bezier(0.455, 0.030, 0.515, 0.955)",function(a,b,c,d){return(a/=d/2)<1?c/2*a*a+b:-c/2*(--a*(a-2)-1)+b}],"ease-in-cubic":["cubic-bezier(0.550, 0.055, 0.675, 0.190)",function(a,b,c,d){return c*(a/=d)*a*a+b}],"ease-out-cubic":["cubic-bezier(0.215, 0.610, 0.355, 1)",function(a,b,c,d){return c*((a=a/d-1)*a*a+1)+b}],"ease-in-out-cubic":["cubic-bezier(0.645, 0.045, 0.355, 1)",function(a,b,c,d){return(a/=d/2)<1?c/2*a*a*a+b:c/2*((a-=2)*a*a+2)+b}],"ease-in-quart":["cubic-bezier(0.895, 0.030, 0.685, 0.220)",function(a,b,c,d){return c*(a/=d)*a*a*a+b}],"ease-out-quart":["cubic-bezier(0.165, 0.840, 0.440, 1)",function(a,b,c,d){return-c*((a=a/d-1)*a*a*a-1)+b}],"ease-in-out-quart":["cubic-bezier(0.770, 0, 0.175, 1)",function(a,b,c,d){return(a/=d/2)<1?c/2*a*a*a*a+b:-c/2*((a-=2)*a*a*a-2)+b}],"ease-in-quint":["cubic-bezier(0.755, 0.050, 0.855, 0.060)",function(a,b,c,d){return c*(a/=d)*a*a*a*a+b}],"ease-out-quint":["cubic-bezier(0.230, 1, 0.320, 1)",function(a,b,c,d){return c*((a=a/d-1)*a*a*a*a+1)+b}],"ease-in-out-quint":["cubic-bezier(0.860, 0, 0.070, 1)",function(a,b,c,d){return(a/=d/2)<1?c/2*a*a*a*a*a+b:c/2*((a-=2)*a*a*a*a+2)+b}],"ease-in-sine":["cubic-bezier(0.470, 0, 0.745, 0.715)",function(a,b,c,d){return-c*Math.cos(a/d*(Math.PI/2))+c+b}],"ease-out-sine":["cubic-bezier(0.390, 0.575, 0.565, 1)",function(a,b,c,d){return c*Math.sin(a/d*(Math.PI/2))+b}],"ease-in-out-sine":["cubic-bezier(0.445, 0.050, 0.550, 0.950)",function(a,b,c,d){return-c/2*(Math.cos(Math.PI*a/d)-1)+b}],"ease-in-expo":["cubic-bezier(0.950, 0.050, 0.795, 0.035)",function(a,b,c,d){return 0===a?b:c*Math.pow(2,10*(a/d-1))+b}],"ease-out-expo":["cubic-bezier(0.190, 1, 0.220, 1)",function(a,b,c,d){return a===d?b+c:c*(-Math.pow(2,-10*a/d)+1)+b}],"ease-in-out-expo":["cubic-bezier(1, 0, 0, 1)",function(a,b,c,d){return 0===a?b:a===d?b+c:(a/=d/2)<1?c/2*Math.pow(2,10*(a-1))+b:c/2*(-Math.pow(2,-10*--a)+2)+b}],"ease-in-circ":["cubic-bezier(0.600, 0.040, 0.980, 0.335)",function(a,b,c,d){return-c*(Math.sqrt(1-(a/=d)*a)-1)+b}],"ease-out-circ":["cubic-bezier(0.075, 0.820, 0.165, 1)",function(a,b,c,d){return c*Math.sqrt(1-(a=a/d-1)*a)+b}],"ease-in-out-circ":["cubic-bezier(0.785, 0.135, 0.150, 0.860)",function(a,b,c,d){return(a/=d/2)<1?-c/2*(Math.sqrt(1-a*a)-1)+b:c/2*(Math.sqrt(1-(a-=2)*a)+1)+b}],"ease-in-back":["cubic-bezier(0.600, -0.280, 0.735, 0.045)",function(a,b,c,d,e){return void 0===e&&(e=1.70158),c*(a/=d)*a*((e+1)*a-e)+b}],"ease-out-back":["cubic-bezier(0.175, 0.885, 0.320, 1.275)",function(a,b,c,d,e){return void 0===e&&(e=1.70158),c*((a=a/d-1)*a*((e+1)*a+e)+1)+b}],"ease-in-out-back":["cubic-bezier(0.680, -0.550, 0.265, 1.550)",function(a,b,c,d,e){return void 0===e&&(e=1.70158),(a/=d/2)<1?c/2*a*a*(((e*=1.525)+1)*a-e)+b:c/2*((a-=2)*a*(((e*=1.525)+1)*a+e)+2)+b}]},n={"ease-in-back":"cubic-bezier(0.600, 0, 0.735, 0.045)","ease-out-back":"cubic-bezier(0.175, 0.885, 0.320, 1)","ease-in-out-back":"cubic-bezier(0.680, 0, 0.265, 1)"},o=document,p=window,q="bkwld-tram",r=/[\-\.0-9]/g,s=/[A-Z]/,t="number",u=/^(rgb|#)/,v=/(em|cm|mm|in|pt|pc|px)$/,w=/(em|cm|mm|in|pt|pc|px|%)$/,x=/(deg|rad|turn)$/,y="unitless",z=/(all|none) 0s ease 0s/,A=/^(width|height)$/,B=" ",C=o.createElement("a"),D=["Webkit","Moz","O","ms"],E=["-webkit-","-moz-","-o-","-ms-"],F=function(a){if
19(a in C.style)return{dom:a,css:a};var b,c,d="",e=a.split("-");for(b=0;b<e.length;b++)d+=e[b].charAt(0).toUpperCase()+e[b].slice(1);for(b=0;b<D.length;b++)if(c=D[b]+d,c in C.style)return{dom:c,css:E[b]+a}},G=b.support={bind:Function.prototype.bind,transform:F("transform"),transition:F("transition"),backface:F("backface-visibility"),timing:F("transition-timing-function")};if(G.transition){var H=G.timing.dom;if(C.style[H]=m["ease-in-back"][0],!C.style[H])for(var I in n)m[I][0]=n[I]}var J=b.frame=function(){var a=p.requestAnimationFrame||p.webkitRequestAnimationFrame||p.mozRequestAnimationFrame||p.oRequestAnimationFrame||p.msRequestAnimationFrame;return a&&G.bind?a.bind(p):function(a){p.setTimeout(a,16)}}(),K=b.now=function(){var a=p.performance,b=a&&(a.now||a.webkitNow||a.msNow||a.mozNow);return b&&G.bind?b.bind(a):Date.now||function(){return+new Date}}(),L=l(function(b){function d(a,b){var c=k((""+a).split(B)),d=c[0];b=b||{};var e=Y[d];if(!e)return j("Unsupported property: "+d);if(!b.weak||!this.props[d]){var f=e[0],g=this.props[d];return g||(g=this.props[d]=new f.Bare),g.init(this.$el,c,e,b),g}}function e(a,b,c){if(a){var e=typeof a;if(b||(this.timer&&this.timer.destroy(),this.queue=[],this.active=!1),"number"==e&&b)return this.timer=new S({duration:a,context:this,complete:h}),void(this.active=!0);if("string"==e&&b){switch(a){case"hide":o.call(this);break;case"stop":l.call(this);break;case"redraw":p.call(this);break;default:d.call(this,a,c&&c[1])}return h.call(this)}if("function"==e)return void a.call(this,this);if("object"==e){var f=0;u.call(this,a,function(a,b){a.span>f&&(f=a.span),a.stop(),a.animate(b)},function(a){"wait"in a&&(f=i(a.wait,0))}),t.call(this),f>0&&(this.timer=new S({duration:f,context:this}),this.active=!0,b&&(this.timer.complete=h));var g=this,j=!1,k={};J(function(){u.call(g,a,function(a){a.active&&(j=!0,k[a.name]=a.nextStyle)}),j&&g.$el.css(k)})}}}function f(a){a=i(a,0),this.active?this.queue.push({options:a}):(this.timer=new S({duration:a,context:this,complete:h}),this.active=!0)}function g(a){return this.active?(this.queue.push({options:a,args:arguments}),void(this.timer.complete=h)):j("No active transition timer. Use start() or wait() before then().")}function h(){if(this.timer&&this.timer.destroy(),this.active=!1,this.queue.length){var a=this.queue.shift();e.call(this,a.options,!0,a.args)}}function l(a){this.timer&&this.timer.destroy(),this.queue=[],this.active=!1;var b;"string"==typeof a?(b={},b[a]=1):b="object"==typeof a&&null!=a?a:this.props,u.call(this,b,v),t.call(this)}function m(a){l.call(this,a),u.call(this,a,w,x)}function n(a){"string"!=typeof a&&(a="block"),this.el.style.display=a}function o(){l.call(this),this.el.style.display="none"}function p(){this.el.offsetHeight}function r(){l.call(this),a.removeData(this.el,q),this.$el=this.el=null}function t(){var a,b,c=[];this.upstream&&c.push(this.upstream);for(a in this.props)b=this.props[a],b.active&&c.push(b.string);c=c.join(","),this.style!==c&&(this.style=c,this.el.style[G.transition.dom]=c)}function u(a,b,e){var f,g,h,i,j=b!==v,k={};for(f in a)h=a[f],f in Z?(k.transform||(k.transform={}),k.transform[f]=h):(s.test(f)&&(f=c(f)),f in Y?k[f]=h:(i||(i={}),i[f]=h));for(f in k){if(h=k[f],g=this.props[f],!g){if(!j)continue;g=d.call(this,f)}b.call(this,g,h)}e&&i&&e.call(this,i)}function v(a){a.stop()}function w(a,b){a.set(b)}function x(a){this.$el.css(a)}function y(a,c){b[a]=function(){return this.children?A.call(this,c,arguments):(this.el&&c.apply(this,arguments),this)}}function A(a,b){var c,d=this.children.length;for(c=0;d>c;c++)a.apply(this.children[c],b);return this}b.init=function(b){if(this.$el=a(b),this.el=this.$el[0],this.props={},this.queue=[],this.style="",this.active=!1,U.keepInherited&&!U.fallback){var c=W(this.el,"transition");c&&!z.test(c)&&(this.upstream=c)}G.backface&&U.hideBackface&&V(this.el,G.backface.css,"hidden")},y("add",d),y("start",e),y("wait",f),y("then",g),y("next",h),y("stop",l),y("set",m),y("show",n),y("hide",o),y("redraw",p),y("destroy",r)}),M=l(L,function(b){function c(b,c){var d=a.data(b,q)||a.data(b,q,new L.Bare);return d.el||d.init(b),c?d.start(c):d}b.init=function(b,d){var e=a(b);if(!e.length)return this;if(1===e.length)return c(e[0],d);var f=[];return e.each(function(a,b){f.push(c(b,d))}),this.children=f,this}}),N=l(function(a){function b(){var a=this.get();this.update("auto");var b=this.get();return this.update(a),b}function c(a,b,c){return void 0!==b&&(c=b),a in m?a:c}function d(a){var b=/rgba?\((\d+),\s*(\d+),\s*(\d+)/.exec(a);return(b?e(b[1],b[2],b[3]):a).replace(/#(\w)(\w)(\w)$/,"#$1$1$2$2$3$3")}var f={duration:500,ease:"ease",delay:0};a.init=function(a,b,d,e){this.$el=a,this.el=a[0];var g=b[0];d[2]&&(g=d[2]),X[g]&&(g=X[g]),this.name=g,this.type=d[1],this.duration=i(b[1],this.duration,f.duration),this.ease=c(b[2],this.ease,f.ease),this.delay=i(b[3],this.delay,f.delay),this.span=this.duration+this.delay,this.active=!1,this.nextStyle=null,this.auto=A.test(this.name),this.unit=e.unit||this.unit||U.defaultUnit,this.angle=e.angle||this.angle||U.defaultAngle,U.fallback||e.fallback?this.animate=this.fallback:(this.animate=this.transition,this.string=this.name+B+this.duration+"ms"+("ease"!=this.ease?B+m[this.ease][0]:"")+(this.delay?B+this.delay+"ms":""))},a.set=function(a){a=this.convert(a,this.type),this.update(a),this.redraw()},a.transition=function(a){this.active=!0,a=this.convert(a,this.type),this.auto&&("auto"==this.el.style[this.name]&&(this.update(this.get()),this.redraw()),"auto"==a&&(a=b.call(this))),this.nextStyle=a},a.fallback=function(a){var c=this.el.style[this.name]||this.convert(this.get(),this.type);a=this.convert(a,this.type),this.auto&&("auto"==c&&(c=this.convert(this.get(),this.type)),"auto"==a&&(a=b.call(this))),this.tween=new R({from:c,to:a,duration:this.duration,delay:this.delay,ease:this.ease,update:this.update,context:this})},a.get=function(){return W(this.el,this.name)},a.update=function(a){V(this.el,this.name,a)},a.stop=function(){(this.active||this.nextStyle)&&(this.active=!1,this.nextStyle=null,V(this.el,this.name,this.get()));var a=this.tween;a&&a.context&&a.destroy()},a.convert=function(a,b){if("auto"==a&&this.auto)return a;var c,e="number"==typeof a,f="string"==typeof a;switch(b){case t:if(e)return a;
19if(f&&""===a.replace(r,""))return+a;c="number(unitless)";break;case u:if(f){if(""===a&&this.original)return this.original;if(b.test(a))return"#"==a.charAt(0)&&7==a.length?a:d(a)}c="hex or rgb string";break;case v:if(e)return a+this.unit;if(f&&b.test(a))return a;c="number(px) or string(unit)";break;case w:if(e)return a+this.unit;if(f&&b.test(a))return a;c="number(px) or string(unit or %)";break;case x:if(e)return a+this.angle;if(f&&b.test(a))return a;c="number(deg) or string(angle)";break;case y:if(e)return a;if(f&&w.test(a))return a;c="number(unitless) or string(unit or %)"}return g(c,a),a},a.redraw=function(){this.el.offsetHeight}}),O=l(N,function(a,b){a.init=function(){b.init.apply(this,arguments),this.original||(this.original=this.convert(this.get(),u))}}),P=l(N,function(a,b){a.init=function(){b.init.apply(this,arguments),this.animate=this.fallback},a.get=function(){return this.$el[this.name]()},a.update=function(a){this.$el[this.name](a)}}),Q=l(N,function(a,b){function c(a,b){var c,d,e,f,g;for(c in a)f=Z[c],e=f[0],d=f[1]||c,g=this.convert(a[c],e),b.call(this,d,g,e)}a.init=function(){b.init.apply(this,arguments),this.current||(this.current={},Z.perspective&&U.perspective&&(this.current.perspective=U.perspective,V(this.el,this.name,this.style(this.current)),this.redraw()))},a.set=function(a){c.call(this,a,function(a,b){this.current[a]=b}),V(this.el,this.name,this.style(this.current)),this.redraw()},a.transition=function(a){var b=this.values(a);this.tween=new T({current:this.current,values:b,duration:this.duration,delay:this.delay,ease:this.ease});var c,d={};for(c in this.current)d[c]=c in b?b[c]:this.current[c];this.active=!0,this.nextStyle=this.style(d)},a.fallback=function(a){var b=this.values(a);this.tween=new T({current:this.current,values:b,duration:this.duration,delay:this.delay,ease:this.ease,update:this.update,context:this})},a.update=function(){V(this.el,this.name,this.style(this.current))},a.style=function(a){var b,c="";for(b in a)c+=b+"("+a[b]+") ";return c},a.values=function(a){var b,d={};return c.call(this,a,function(a,c,e){d[a]=c,void 0===this.current[a]&&(b=0,~a.indexOf("scale")&&(b=1),this.current[a]=this.convert(b,e))}),d}}),R=l(function(b){function c(a){1===n.push(a)&&J(g)}function g(){var a,b,c,d=n.length;if(d)for(J(g),b=K(),a=d;a--;)c=n[a],c&&c.render(b)}function i(b){var c,d=a.inArray(b,n);d>=0&&(c=n.slice(d+1),n.length=d,c.length&&(n=n.concat(c)))}function j(a){return Math.round(a*o)/o}function k(a,b,c){return e(a[0]+c*(b[0]-a[0]),a[1]+c*(b[1]-a[1]),a[2]+c*(b[2]-a[2]))}var l={ease:m.ease[1],from:0,to:1};b.init=function(a){this.duration=a.duration||0,this.delay=a.delay||0;var b=a.ease||l.ease;m[b]&&(b=m[b][1]),"function"!=typeof b&&(b=l.ease),this.ease=b,this.update=a.update||f,this.complete=a.complete||f,this.context=a.context||this,this.name=a.name;var c=a.from,d=a.to;void 0===c&&(c=l.from),void 0===d&&(d=l.to),this.unit=a.unit||"","number"==typeof c&&"number"==typeof d?(this.begin=c,this.change=d-c):this.format(d,c),this.value=this.begin+this.unit,this.start=K(),a.autoplay!==!1&&this.play()},b.play=function(){this.active||(this.start||(this.start=K()),this.active=!0,c(this))},b.stop=function(){this.active&&(this.active=!1,i(this))},b.render=function(a){var b,c=a-this.start;if(this.delay){if(c<=this.delay)return;c-=this.delay}if(c<this.duration){var d=this.ease(c,0,1,this.duration);return b=this.startRGB?k(this.startRGB,this.endRGB,d):j(this.begin+d*this.change),this.value=b+this.unit,void this.update.call(this.context,this.value)}b=this.endHex||this.begin+this.change,this.value=b+this.unit,this.update.call(this.context,this.value),this.complete.call(this.context),this.destroy()},b.format=function(a,b){if(b+="",a+="","#"==a.charAt(0))return this.startRGB=d(b),this.endRGB=d(a),this.endHex=a,this.begin=0,void(this.change=1);if(!this.unit){var c=b.replace(r,""),e=a.replace(r,"");c!==e&&h("tween",b,a),this.unit=c}b=parseFloat(b),a=parseFloat(a),this.begin=this.value=b,this.change=a-b},b.destroy=function(){this.stop(),this.context=null,this.ease=this.update=this.complete=f};var n=[],o=1e3}),S=l(R,function(a){a.init=function(a){this.duration=a.duration||0,this.complete=a.complete||f,this.context=a.context,this.play()},a.render=function(a){var b=a-this.start;b<this.duration||(this.complete.call(this.context),this.destroy())}}),T=l(R,function(a,b){a.init=function(a){this.context=a.context,this.update=a.update,this.tweens=[],this.current=a.current;var b,c;for(b in a.values)c=a.values[b],this.current[b]!==c&&this.tweens.push(new R({n
19ame:b,from:this.current[b],to:c,duration:a.duration,delay:a.delay,ease:a.ease,autoplay:!1}));this.play()},a.render=function(a){var b,c,d=this.tweens.length,e=!1;for(b=d;b--;)c=this.tweens[b],c.context&&(c.render(a),this.current[c.name]=c.value,e=!0);return e?void(this.update&&this.update.call(this.context)):this.destroy()},a.destroy=function(){if(b.destroy.call(this),this.tweens){var a,c=this.tweens.length;for(a=c;a--;)this.tweens[a].destroy();this.tweens=null,this.current=null}}}),U=b.config={debug:!1,defaultUnit:"px",defaultAngle:"deg",keepInherited:!1,hideBackface:!1,perspective:"",fallback:!G.transition,agentTests:[]};b.fallback=function(a){if(!G.transition)return U.fallback=!0;U.agentTests.push("("+a+")");var b=new RegExp(U.agentTests.join("|"),"i");U.fallback=b.test(navigator.userAgent)},b.fallback("6.0.[2-5] Safari"),b.tween=function(a){return new R(a)},b.delay=function(a,b,c){return new S({complete:b,duration:a,context:c})},a.fn.tram=function(a){return b.call(null,this,a)};var V=a.style,W=a.css,X={transform:G.transform&&G.transform.css},Y={color:[O,u],background:[O,u,"background-color"],"outline-color":[O,u],"border-color":[O,u],"border-top-color":[O,u],"border-right-color":[O,u],"border-bottom-color":[O,u],"border-left-color":[O,u],"border-width":[N,v],"border-top-width":[N,v],"border-right-width":[N,v],"border-bottom-width":[N,v],"border-left-width":[N,v],"border-spacing":[N,v],"letter-spacing":[N,v],margin:[N,v],"margin-top":[N,v],"margin-right":[N,v],"margin-bottom":[N,v],"margin-left":[N,v],padding:[N,v],"padding-top":[N,v],"padding-right":[N,v],"padding-bottom":[N,v],"padding-left":[N,v],"outline-width":[N,v],opacity:[N,t],top:[N,w],right:[N,w],bottom:[N,w],left:[N,w],"font-size":[N,w],"text-indent":[N,w],"word-spacing":[N,w],width:[N,w],"min-width":[N,w],"max-width":[N,w],height:[N,w],"min-height":[N,w],"max-height":[N,w],"line-height":[N,y],"scroll-top":[P,t,"scrollTop"],"scroll-left":[P,t,"scrollLeft"]},Z={};G.transform&&(Y.transform=[Q],Z={x:[w,"translateX"],y:[w,"translateY"],rotate:[x],rotateX:[x],rotateY:[x],scale:[t],scaleX:[t],scaleY:[t],skew:[x],skewX:[x],skewY:[x]}),G.transform&&G.backface&&(Z.z=[w,"translateZ"],Z.rotateZ=[x],Z.scaleZ=[t],Z.perspective=[v]);var $=/ms/,_=/s|\./;return a.tram=b}(window.jQuery); 20 21 var require$$0$1 = {}; 22 23 var underscoreCustom = __commonjs(function (module) { 24 // Include tram for frame-throttling 25 var $ = window.$; 26 var tram = require$$0$1 && $.tram; 27 28 /*eslint-disable */ 29 30 /*! 31 * Webflow._ (aka) Underscore.js 1.6.0 (custom build) 32 * _.each 33 * _.map 34 * _.find 35 * _.filter 36 * _.any 37 * _.contains 38 * _.delay 39 * _.defer 40 * _.throttle (webflow) 41 * _.debounce 42 * _.keys 43 * _.has 44 * _.now 45 * 46 * http://underscorejs.org 47 * (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 48 * Underscore may be freely distributed under the MIT license. 49 * @license MIT 50 */ 51 module.exports = (function() { 52 var _ = {}; 53 54 // Current version. 55 _.VERSION = '1.6.0-Webflow'; 56 57 // Establish the object that gets returned to break out of a loop iteration. 58 var breaker = {}; 59 60 // Save bytes in the minified (but not gzipped) version: 61 var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; 62 63 // Create quick reference variables for speed access to core prototypes. 64 var 65 push = ArrayProto.push, 66 slice = ArrayProto.slice, 67 concat = ArrayProto.concat, 68 toString = ObjProto.toString, 69 hasOwnProperty = ObjProto.hasOwnProperty; 70 71 // All **ECMAScript 5** native function implementations that we hope to use 72 // are declared here. 73 var 74 nativeForEach = ArrayProto.forEach, 75 nativeMap = ArrayProto.map, 76 nativeReduce = ArrayProto.reduce, 77 nativeReduceRight = ArrayProto.reduceRight, 78 nativeFilter = ArrayProto.filter, 79 nativeEvery = ArrayProto.every, 80 nativeSome = ArrayProto.some, 81 nativeIndexOf = ArrayProto.indexOf, 82 nativeLastIndexOf = ArrayProto.lastIndexOf, 83 nativeIsArray = Array.isArray, 84 nativeKeys = Object.keys, 85 nativeBind = FuncProto.bind; 86 87 // Collection Functions 88 // -------------------- 89 90 // The cornerstone, an `each` implementation, aka `forEach`. 91 // Handles objects with the built-in `forEach`, arrays, and raw objects.
92 // Delegates to **ECMAScript 5**'s native `forEach` if available. 93 var each = _.each = _.forEach = function(obj, iterator, context) { 94 /* jshint shadow:true */ 95 if (obj == null) return obj; 96 if (nativeForEach && obj.forEach === nativeForEach) { 97 obj.forEach(iterator, context); 98 } else if (obj.length === +obj.length) { 99 for (var i = 0, length = obj.length; i < length; i++) { 100 if (iterator.call(context, obj[i], i, obj) === breaker) return; 101 } 102 } else { 103 var keys = _.keys(obj); 104 for (var i = 0, length = keys.length; i < length; i++) { 105 if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; 106 } 107 } 108 return obj; 109 }; 110 111 // Return the results of applying the iterator to each element. 112 // Delegates to **ECMAScript 5**'s native `map` if available. 113 _.map = _.collect = function(obj, iterator, context) { 114 var results = []; 115 if (obj == null) return results; 116 if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); 117 each(obj, function(value, index, list) { 118 results.push(iterator.call(context, value, index, list)); 119 }); 120 return results; 121 }; 122 123 // Return the first value which passes a truth test. Aliased as `detect`. 124 _.find = _.detect = function(obj, predicate, context) { 125 var result; 126 any(obj, function(value, index, list) { 127 if (predicate.call(context, value, index, list)) { 128 result = value; 129 return true; 130 } 131 }); 132 return result; 133 }; 134 135 // Return all the elements that pass a truth test. 136 // Delegates to **ECMAScript 5**'s native `filter` if available. 137 // Aliased as `select`. 138 _.filter = _.select = function(obj, predicate, context) { 139 var results = []; 140 if (obj == null) return results; 141 if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); 142 each(obj, function(value, index, list) { 143 if (predicate.call(context, value, index, list)) results.push(value); 144 }); 145 return results; 146 }; 147 148 // Determine if at least one element in the object matches a truth test. 149 // Delegates to **ECMAScript 5**'s native `some` if available. 150 // Aliased as `any`. 151 var any = _.some = _.any = function(obj, predicate, context) { 152 predicate || (predicate = _.identity); 153 var result = false; 154 if (obj == null) return result; 155 if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); 156 each(obj, function(value, index, list) { 157 if (result || (result = predicate.call(context, value, index, list))) return breaker; 158 }); 159 return !!result; 160 }; 161 162 // Determine if the array or object contains a given value (using `===`). 163 // Aliased as `include`. 164 _.contains = _.include = function(obj, target) { 165 if (obj == null) return false; 166 if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; 167 return any(obj, function(value) { 168 return value === target; 169 }); 170 }; 171 172 // Function (ahem) Functions 173 // -------------------- 174 175 // Delays a function for the given number of milliseconds, and then calls 176 // it with the arguments supplied. 177 _.delay = function(func, wait) { 178 var args = slice.call(arguments, 2); 179 return setTimeout(function(){ return func.apply(null, args); }, wait); 180 }; 181 182 // Defers a function, scheduling it to run after the current call stack has 183 // cleared. 184 _.defer = function(func) { 185 return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); 186 }; 187 188 // Returns a function, that, when invoked, will only be triggered once every 189 // browser animation frame - using tram's requestAnimationFrame polyfill. 190 _.throttle = function(func) { 191 var wait, args, context; 192 return function() { 193 if (wait) return; 194 wait = true; 195 args = arguments; 196 context = this; 197 tram.frame(function() { 198 wait = false;
199 func.apply(context, args); 200 }); 201 }; 202 }; 203 204 // Returns a function, that, as long as it continues to be invoked, will not 205 // be triggered. The function will be called after it stops being called for 206 // N milliseconds. If `immediate` is passed, trigger the function on the 207 // leading edge, instead of the trailing. 208 _.debounce = function(func, wait, immediate) { 209 var timeout, args, context, timestamp, result; 210 211 var later = function() { 212 var last = _.now() - timestamp; 213 if (last < wait) { 214 timeout = setTimeout(later, wait - last); 215 } else { 216 timeout = null; 217 if (!immediate) { 218 result = func.apply(context, args); 219 context = args = null; 220 } 221 } 222 }; 223 224 return function() { 225 context = this; 226 args = arguments; 227 timestamp = _.now(); 228 var callNow = immediate && !timeout; 229 if (!timeout) { 230 timeout = setTimeout(later, wait); 231 } 232 if (callNow) { 233 result = func.apply(context, args); 234 context = args = null; 235 } 236 237 return result; 238 }; 239 }; 240 241 // Object Functions 242 // ---------------- 243 244 // Fill in a given object with default properties. 245 _.defaults = function(obj) { 246 if (!_.isObject(obj)) return obj; 247 for (var i = 1, length = arguments.length; i < length; i++) { 248 var source = arguments[i]; 249 for (var prop in source) { 250 if (obj[prop] === void 0) obj[prop] = source[prop]; 251 } 252 } 253 return obj; 254 }; 255 256 // Retrieve the names of an object's properties. 257 // Delegates to **ECMAScript 5**'s native `Object.keys` 258 _.keys = function(obj) { 259 if (!_.isObject(obj)) return []; 260 if (nativeKeys) return nativeKeys(obj); 261 var keys = []; 262 for (var key in obj) if (_.has(obj, key)) keys.push(key); 263 return keys; 264 }; 265 266 // Shortcut function for checking if an object has a given property directly 267 // on itself (in other words, not on a prototype). 268 _.has = function(obj, key) { 269 return hasOwnProperty.call(obj, key); 270 }; 271 272 // Is a given variable an object? 273 _.isObject = function(obj) { 274 return obj === Object(obj); 275 }; 276 277 // Utility Functions 278 // ----------------- 279 280 // A (possibly faster) way to get the current timestamp as an integer. 281 _.now = Date.now || function() { return new Date().getTime(); }; 282 283 // By default, Underscore uses ERB-style template delimiters, change the 284 // following template settings to use alternative delimiters. 285 _.templateSettings = { 286 evaluate : /<%([\s\S]+?)%>/g, 287 interpolate : /<%=([\s\S]+?)%>/g, 288 escape : /<%-([\s\S]+?)%>/g 289 }; 290 291 // When customizing `templateSettings`, if you don't want to define an 292 // interpolation, evaluation or escaping regex, we need one that is 293 // guaranteed not to match. 294 var noMatch = /(.)^/; 295 296 // Certain characters need to be escaped so that they can be put into a 297 // string literal. 298 var escapes = { 299 "'": "'", 300 '\\': '\\', 301 '\r': 'r', 302 '\n': 'n', 303 '\u2028': 'u2028', 304 '\u2029': 'u2029' 305 }; 306 307 var escaper = /\\|'|\r|\n|\u2028|\u2029/g; 308 309 var escapeChar = function(match) { 310 return '\\' + escapes[match]; 311 }; 312 313 // JavaScript micro-templating, similar to John Resig's implementation. 314 // Underscore templating handles arbitrary delimiters, preserves whitespace, 315 // and correctly escapes quotes within interpolated code. 316 // NB: `oldSettings` only exists for backwards compatibility. 317 _.template = function(text, settings, oldSettings) { 318 if (!settings && oldSettings) settings = oldSettings; 319 settings = _.defaults({}, settings, _.templateSettings); 320 321 // Combine delimiters into one regular expression via alternation. 322 var matcher = RegExp([ 323 (settings.escape || noMatch).source,
324 (settings.interpolate || noMatch).source, 325 (settings.evaluate || noMatch).source 326 ].join('|') + '|$', 'g'); 327 328 // Compile the template source, escaping string literals appropriately. 329 var index = 0; 330 var source = "__p+='"; 331 text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { 332 source += text.slice(index, offset).replace(escaper, escapeChar); 333 index = offset + match.length; 334 335 if (escape) { 336 source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; 337 } else if (interpolate) { 338 source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; 339 } else if (evaluate) { 340 source += "';\n" + evaluate + "\n__p+='"; 341 } 342 343 // Adobe VMs need the match returned to produce the correct offest. 344 return match; 345 }); 346 source += "';\n"; 347 348 // If a variable is not specified, place data values in local scope. 349 if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; 350 351 source = "var __t,__p='',__j=Array.prototype.join," + 352 "print=function(){__p+=__j.call(arguments,'');};\n" + 353 source + 'return __p;\n'; 354 355 try { 356 var render = new Function(settings.variable || 'obj', '_', source); 357 } catch (e) { 358 e.source = source; 359 throw e; 360 } 361 362 var template = function(data) { 363 return render.call(this, data, _); 364 }; 365 366 // Provide the compiled source as a convenience for precompilation. 367 var argument = settings.variable || 'obj'; 368 template.source = 'function(' + argument + '){\n' + source + '}'; 369 370 return template; 371 }; 372 373 // Export underscore 374 return _; 375 }()); 376 377 /* eslint-enable */ 378 }); 379 380 var require$$1 = (underscoreCustom && typeof underscoreCustom === 'object' && 'default' in underscoreCustom ? underscoreCustom['default'] : underscoreCustom); 381 382 var webflowLib = __commonjs(function (module) { 383 /** 384 * Webflow: Core site library 385 */ 386 387 var Webflow = {}; 388 var modules = {}; 389 var primary = []; 390 var secondary = window.Webflow || []; 391 var $ = window.jQuery; 392 var $win = $(window); 393 var $doc = $(document); 394 var isFunction = $.isFunction; 395 var _ = Webflow._ = require$$1; 396 var tram = require$$0$1 && $.tram; 397 var domready = false; 398 var destroyed = false; 399 var Modernizr = window.Modernizr; 400 tram.config.hideBackface = false; 401 tram.config.keepInherited = true; 402 403 /** 404 * Webflow.define - Define a named module 405 * @param {string} name 406 * @param {function} factory 407 * @param {object} options 408 * @return {object} 409 */ 410 Webflow.define = function(name, factory, options) { 411 if (modules[name]) unbindModule(modules[name]); 412 var instance = modules[name] = factory($, _, options) || {}; 413 bindModule(instance); 414 return instance; 415 }; 416 417 /** 418 * Webflow.require - Require a named module 419 * @param {string} name 420 * @return {object} 421 */ 422 Webflow.require = function(name) { 423 return modules[name]; 424 }; 425 426 function bindModule(module) { 427 // If running in Webflow app, subscribe to design/preview events 428 if (Webflow.env()) { 429 isFunction(module.design) && $win.on('__wf_design', module.design); 430 isFunction(module.preview) && $win.on('__wf_preview', module.preview); 431 } 432 // Subscribe to front-end destroy event 433 isFunction(module.destroy) && $win.on('__wf_destroy', module.destroy); 434 // Look for ready method on module 435 if (module.ready && isFunction(module.ready)) { 436 addReady(module); 437 } 438 } 439 440 function addReady(module) { 441 // If domready has already happened, run ready method 442 if (domready) { 443 module.ready(); 444 return; 445 } 446 // Otherwise add ready method to the primary queue (only once) 447 if (_.contains(primary, module.ready)) return; 448 primary.push(module.ready); 449 } 450 451 function unbindModule(module) { 452 // Unsubscribe module from window events 453 isFunction(module.design) && $win.off('__wf_design', module.design); 454 isFunction(module.preview) && $win.off('__wf_preview', module.preview); 455 isFunction(module.destroy) && $win.off('__wf_destroy', module.destroy); 456 // Remove ready method from primary queue 457 if (module.ready && isFunction(module.ready)) { 458 removeReady(module); 459 } 460 } 461 462 function removeReady(module) { 463 primary = _.filter(primary, function(readyFn) { 464 return readyFn !== module.ready; 465 });
466 } 467 468 /** 469 * Webflow.push - Add a ready handler into secondary queue 470 * @param {function} ready Callback to invoke on domready 471 */ 472 Webflow.push = function(ready) { 473 // If domready has already happened, invoke handler 474 if (domready) { 475 isFunction(ready) && ready(); 476 return; 477 } 478 // Otherwise push into secondary queue 479 secondary.push(ready); 480 }; 481 482 /** 483 * Webflow.env - Get the state of the Webflow app 484 * @param {string} mode [optional] 485 * @return {boolean} 486 */ 487 Webflow.env = function(mode) { 488 var designFlag = window.__wf_design; 489 var inApp = typeof designFlag !== 'undefined'; 490 if (!mode) return inApp; 491 if (mode === 'design') return inApp && designFlag; 492 if (mode === 'preview') return inApp && !designFlag; 493 if (mode === 'slug') return inApp && window.__wf_slug; 494 if (mode === 'editor') return window.WebflowEditor; 495 if (mode === 'test') return false || window.__wf_test; 496 if (mode === 'frame') return window !== window.top; 497 }; 498 499 // Feature detects + browser sniffs ಠ_ಠ500 var userAgent = navigator.userAgent.toLowerCase(); 501 var appVersion = navigator.appVersion.toLowerCase(); 502 var touch = Webflow.env.touch = ('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch; 503 var chrome = Webflow.env.chrome = /chrome/.test(userAgent) && /Google/.test(navigator.vendor) && parseInt(appVersion.match(/chrome\/(\d+)\./)[1], 10); 504 var ios = Webflow.env.ios = Modernizr && Modernizr.ios; 505 Webflow.env.safari = /safari/.test(userAgent) && !chrome && !ios; 506 507 // Maintain current touch target to prevent late clicks on touch devices 508 var touchTarget; 509 // Listen for both events to support touch/mouse hybrid devices 510 touch && $doc.on('touchstart mousedown', function(evt) { 511 touchTarget = evt.target; 512 }); 513 514 /** 515 * Webflow.validClick - validate click target against current touch target 516 * @param {HTMLElement} clickTarget Element being clicked 517 * @return {Boolean} True if click target is valid (always true on non-touch) 518 */ 519 Webflow.validClick = touch ? function(clickTarget) { 520 return clickTarget === touchTarget || $.contains(clickTarget, touchTarget); 521 } : function() { return true; }; 522 523 /** 524 * Webflow.resize, Webflow.scroll - throttled event proxies 525 */ 526 var resizeEvents = 'resize.webflow orientationchange.webflow load.webflow'; 527 var scrollEvents = 'scroll.webflow ' + resizeEvents; 528 Webflow.resize = eventProxy($win, resizeEvents); 529 Webflow.scroll = eventProxy($win, scrollEvents); 530 Webflow.redraw = eventProxy(); 531 532 // Create a proxy instance for throttled events 533 function eventProxy(target, types) { 534 535 // Set up throttled method (using custom frame-based _.throttle) 536 var handlers = []; 537 var proxy = {}; 538 proxy.up = _.throttle(function(evt) { 539 _.each(handlers, function(h) { h(evt); }); 540 }); 541 542 // Bind events to target 543 if (target && types) target.on(types, proxy.up); 544 545 /** 546 * Add an event handler 547 * @param {function} handler 548 */ 549 proxy.on = function(handler) { 550 if (typeof handler !== 'function') return; 551 if (_.contains(handlers, handler)) return; 552 handlers.push(handler); 553 }; 554 555 /** 556 * Remove an event handler 557 * @param {function} handler 558 */ 559 proxy.off = function(handler) { 560 // If no arguments supplied, clear all handlers 561 if (!arguments.length) { 562 handlers = []; 563 return; 564 } 565 // Otherwise, remove handler from the list 566 handlers = _.filter(handlers, function(h) { 567 return h !== handler; 568 }); 569 }; 570 571 return proxy; 572 } 573 574 // Webflow.location - Wrap window.location in api 575 Webflow.location = function(url) { 576 window.location = url; 577 }; 578 579 if (Webflow.env()) { 580 // Webflow.location - Re-route location change to trigger an event 581 Webflow.location = function(url) { 582 window.dispatchEvent(new CustomEvent('__wf_location', { detail: url })); 583 }; 584 } 585 586 // Webflow.ready - Call primary and secondary handlers 587 Webflow.ready = function() { 588 domready = true; 589 590 // Restore modules after destroy 591 if (destroyed) { 592 restoreModules();
593 594 // Otherwise run primary ready methods 595 } else { 596 _.each(primary, callReady); 597 } 598 599 // Run secondary ready methods 600 _.each(secondary, callReady); 601 602 // Trigger resize 603 Webflow.resize.up(); 604 }; 605 606 function callReady(readyFn) { 607 isFunction(readyFn) && readyFn(); 608 } 609 610 function restoreModules() { 611 destroyed = false; 612 _.each(modules, bindModule); 613 } 614 615 /** 616 * Webflow.load - Add a window load handler that will run even if load event has already happened 617 * @param {function} handler 618 */ 619 var deferLoad; 620 Webflow.load = function(handler) { 621 deferLoad.then(handler); 622 }; 623 624 function bindLoad() { 625 // Reject any previous deferred (to support destroy) 626 if (deferLoad) { 627 deferLoad.reject(); 628 $win.off('load', deferLoad.resolve); 629 } 630 // Create deferred and bind window load event 631 deferLoad = new $.Deferred(); 632 $win.on('load', deferLoad.resolve); 633 } 634 635 // Webflow.destroy - Trigger a destroy event for all modules 636 Webflow.destroy = function(options) { 637 options = options || {}; 638 destroyed = true; 639 $win.triggerHandler('__wf_destroy'); 640 641 // Allow domready reset for tests 642 if (options.domready != null) { 643 domready = options.domready; 644 } 645 646 // Unbind modules 647 _.each(modules, unbindModule); 648 649 // Clear any proxy event handlers 650 Webflow.resize.off(); 651 Webflow.scroll.off(); 652 Webflow.redraw.off(); 653 654 // Clear any queued ready methods 655 primary = []; 656 secondary = []; 657 658 // If load event has not yet fired, replace the deferred 659 if (deferLoad.state() === 'pending') bindLoad(); 660 }; 661 662 // Listen for domready 663 $(Webflow.ready); 664 665 // Listen for window.onload and resolve deferred 666 bindLoad(); 667 668 // Export commonjs module 669 module.exports = window.Webflow = Webflow; 670 }); 671 672 var require$$0 = (webflowLib && typeof webflowLib === 'object' && 'default' in webflowLib ? webflowLib['default'] : webflowLib); 673 674 var webflowBrand = __commonjs(function (module) { 675 /** 676 * Webflow: Brand pages on the subdomain 677 */ 678 679 var Webflow = require$$0; 680 681 Webflow.define('brand', module.exports = function($) { 682 var api = {}; 683 var $html = $('html'); 684 var $body = $('body'); 685 var namespace = '.w-webflow-badge'; 686 var location = window.location; 687 var isPhantom = /PhantomJS/i.test(navigator.userAgent); 688 var brandElement; 689 690 // ----------------------------------- 691 // Module methods 692 693 api.ready = function() { 694 var shouldBrand = $html.attr('data-wf-status'); 695 var publishedDomain = $html.attr('data-wf-domain') || ''; 696 if (/\.webflow\.io$/i.test(publishedDomain) && location.hostname !== publishedDomain) { 697 shouldBrand = true; 698 } 699 if (shouldBrand && !isPhantom) { 700 brandElement = brandElement || createBadge(); 701 ensureBrand(); 702 setTimeout(ensureBrand, 500); 703 } 704 }; 705 706 function createBadge() { 707 var $brand = $('<a class="w-webflow-badge"></a>') 708 .attr('href', 'https://webflow.com?utm_campaign=brandjs'); 709 710 var $logoArt = $('<img>') 711 .attr('src', 'https://d1otoma47x30pg.cloudfront.net/img/webflow-badge-icon.60efbf6ec9.svg') 712 .css({ 713 marginRight: '8px', 714 width: '16px', 715 }); 716 717 var $logoText = $('<img>') 718 .attr('src', 'https://d1otoma47x30pg.cloudfront.net/img/webflow-badge-text.6faa6a38cd.svg'); 719 720 $brand.append($logoArt, $logoText); 721 return $brand[0]; 722 } 723 724 function ensureBrand() { 725 var found = $body.children(namespace); 726 var match = found.length && found.get(0) === brandElement; 727 var inEditor = Webflow.env('editor'); 728 if (match) { 729 // Remove brand when Editor is active 730 if (inEditor) { 731 found.remove(); 732 } 733 // Exit early, brand is in place 734 return; 735 } 736 // Remove any invalid brand elements 737 if (found.length) { 738 found.remove(); 739 } 740 // Append the brand (unless Editor is active) 741 if (!inEditor) { 742 $body.append(brandElement); 743 } 744 } 745 746 // Export module 747 return api; 748 }); 749 }); 750 751 var webflowEdit = __commonjs(function (module) { 752 /** 753 * Webflow: Editor loader 754 */ 755 756 var Webflow = require$$0; 757 758 Webflow.define('edit', module.exports = function($, _, options) { 759 options = options || {}; 760 761 // Exit early in test env or when inside an iframe 762 if (Webflow.env('test') || Webflow.env('frame')) { 763 // Allow test fixtures to continue 764 if (!options.fixture) { 765 return {exit: 1}; 766 } 767 } 768 769 var api = {}; 770 var $win = $(window); 771 var $html = $(document.documentElement); 772 var location = document.location; 773 var hashchange = 'hashchange'; 774 var loaded; 775 var loadEditor = options.load || load; 776 var hasLocalStorage = false; 777 778 try { 779 // Check localStorage for editor data 780 hasLocalStorage = localStorage && localStorage.getItem && localStorage.getItem('WebflowEditor'); 781 } catch (e) { 782 // SecurityError: browser storage has been disabled 783 } 784 785 if (hasLocalStorage) { 786 loadEditor(); 787 788 } else if (location.search) { 789 // Check url query for `edit` parameter or any url ending in `?edit` 790 if (/[?&](edit)(?:[=&?]|$)/.test(location.search) || /\?edit$/.test(location.href)) { 791 loadEditor(); 792 } 793 794 } else {
795 // Check hash fragment to support `#hash?edit` 796 $win.on(hashchange, checkHash).triggerHandler(hashchange); 797 } 798 799 function checkHash() { 800 if (loaded) return; 801 // Load editor when hash contains `?edit` 802 if (/\?edit/.test(location.hash)) loadEditor(); 803 } 804 805 function load() { 806 loaded = true; 807 // Predefine global immediately to benefit Webflow.env 808 window.WebflowEditor = true; 809 $win.off(hashchange, checkHash); 810 $.ajax({ 811 url: cleanSlashes("https://editor-api.webflow.com" + '/api/editor/view'), 812 data: { siteId: $html.attr('data-wf-site') }, 813 xhrFields: { withCredentials: true }, 814 dataType: 'json', 815 crossDomain: true, 816 success: success 817 }); 818 } 819 820 function success(data) { 821 if (!data) { 822 console.error('Could not load editor data'); 823 return; 824 } 825 getScript(prefix(data.scriptPath), function () { 826 window.WebflowEditor(data); 827 }); 828 } 829 830 function getScript(url, done) { 831 $.ajax({ type: 'GET', url: url, dataType: 'script', cache: true }).then(done, error); 832 } 833 834 function error(jqXHR, textStatus, errorThrown) { 835 console.error('Could not load editor script: ' + textStatus); 836 throw errorThrown; 837 } 838 839 function prefix(url) { 840 return (url.indexOf('//') >= 0) ? url : cleanSlashes("https://editor-api.webflow.com" + url); 841 } 842 843 function cleanSlashes(url) { 844 return url.replace(/([^:])\/\//g, '$1/'); 845 } 846 847 // Export module 848 return api; 849 }); 850 }); 851 852 var xdomainMin = __commonjs(function (module) { 853 /*! 854 * jQuery-ajaxTransport-XDomainRequest - v1.0.3 855 * 2014-12-16 WEBFLOW - Removed UMD wrapper 856 * https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest 857 * Copyright (c) 2014 Jason Moon (@JSONMOON) 858 * @license MIT (/blob/master/LICENSE.txt) 859 */ 860 module.exports=function($){if($.support.cors||!$.ajaxTransport||!window.XDomainRequest){return}var httpRegEx=/^https?:\/\//i;var getOrPostRegEx=/^get|post$/i;var sameSchemeRegEx=new RegExp("^"+location.protocol,"i");$.ajaxTransport("* text html xml json",function(options,userOptions,jqXHR){if(!options.crossDomain||!options.async||!getOrPostRegEx.test(options.type)||!httpRegEx.test(options.url)||!sameSchemeRegEx.test(options.url)){return}var xdr=null;return{send:function(headers,complete){var postData="";var userType=(userOptions.dataType||"").toLowerCase();xdr=new XDomainRequest;if(/^\d+$/.test(userOptions.timeout)){xdr.timeout=userOptions.timeout}xdr.ontimeout=function(){complete(500,"timeout")};xdr.onload=function(){var allResponseHeaders="Content-Length: "+xdr.responseText.length+"\r\nContent-Type: "+xdr.contentType;var status={code:200,message:"success"};var responses={text:xdr.responseText};try{if(userType==="html"||/text\/html/i.test(xdr.contentType)){responses.html=xdr.responseText}else if(userType==="json"||userType!=="text"&&/\/json/i.test(xdr.contentType)){try{responses.json=$.parseJSON(xdr.responseText)}catch(e){status.code=500;status.message="parseerror"}}else if(userType==="xml"||userType!=="text"&&/\/xml/i.test(xdr.contentType)){var doc=new ActiveXObject("Microsoft.XMLDOM");doc.async=false;try{doc.loadXML(xdr.responseText)}catch(e){doc=undefined}if(!doc||!doc.documentElement||doc.getElementsByTagName("parsererror").length){status.code=500;status.message="parseerror";throw"Invalid XML: "+xdr.responseText}responses.xml=doc}}catch(parseMessage){throw parseMessage}finally{complete(status.code,status.message,responses,allResponseHeaders)}};xdr.onprogress=function(){};xdr.onerror=function(){complete(500,"error",{text:xdr.responseText})};if(userOptions.data){postData=$.type(userOptions.data)==="string"?userOptions.data:$.param(userOptions.data)}xdr.open(options.type,options.url);xdr.send(postData)},abort:function(){if(xdr){xdr.abort()}}}})}(window.jQuery); 861 }); 862 863 var webflowForms = __commonjs(function (module) { 864 /** 865 * Webflow: Forms 866 */ 867 868 var Webflow = require$$0; 869 870 Webflow.define('forms', module.exports = function($, _) { 871 var api = {}; 872 873 // Cross-Domain AJAX for IE8 874 875 876 var $doc = $(document); 877 var $forms; 878 var loc = window.location; 879 var retro = window.XDomainRequest && !window.atob; 880 var namespace = '.w-form'; 881 var siteId; 882 var emailField = /e(-)?mail/i; 883 var emailValue = /^\S+@\S+$/; 884 var alert = window.alert; 885 var inApp = Webflow.env(); 886 var listening; 887 888 // MailChimp domains: list-manage.com + mirrors 889 var chimpRegex = /list-manage[1-9]?.com/i; 890 891 var disconnected = _.debounce(function() { 892 alert('Oops! This page has improperly configured forms. Please contact your website administrator to fix this issue.'); 893 }, 100); 894 895 api.ready = api.design = api.preview = function() { 896 // Init forms 897 init(); 898
899 // Wire document events on published site only once 900 if (!inApp && !listening) { 901 addListeners(); 902 } 903 }; 904 905 function init() { 906 siteId = $('html').attr('data-wf-site'); 907 908 $forms = $(namespace + ' form'); 909 if (!$forms.length) return; 910 $forms.each(build); 911 } 912 913 function build(i, el) { 914 // Store form state using namespace 915 var $el = $(el); 916 var data = $.data(el, namespace); 917 if (!data) data = $.data(el, namespace, { form: $el }); // data.form 918 919 reset(data); 920 var wrap = $el.closest('div.w-form'); 921 data.done = wrap.find('> .w-form-done'); 922 data.fail = wrap.find('> .w-form-fail'); 923 924 var action = data.action = $el.attr('action'); 925 data.handler = null; 926 data.redirect = $el.attr('data-redirect'); 927 928 // MailChimp form 929 if (chimpRegex.test(action)) { data.handler = submitMailChimp; return; } 930 931 // Custom form action 932 if (action) return; 933 934 // Webflow form 935 if (siteId) { data.handler = submitWebflow; return; } 936 937 // Alert for disconnected Webflow forms 938 disconnected(); 939 } 940 941 function addListeners() { 942 listening = true; 943 944 // Handle form submission for Webflow forms 945 $doc.on('submit', namespace + ' form', function(evt) { 946 var data = $.data(this, namespace); 947 if (data.handler) { 948 data.evt = evt; 949 data.handler(data); 950 } 951 }); 952 } 953 954 // Reset data common to all submit handlers 955 function reset(data) { 956 var btn = data.btn = data.form.find(':input[type="submit"]'); 957 data.wait = data.btn.attr('data-wait') || null; 958 data.success = false; 959 btn.prop('disabled', false); 960 data.label && btn.val(data.label); 961 } 962 963 // Disable submit button 964 function disableBtn(data) { 965 var btn = data.btn; 966 var wait = data.wait; 967 btn.prop('disabled', true); 968 // Show wait text and store previous label 969 if (wait) { 970 data.label = btn.val(); 971 btn.val(wait); 972 } 973 } 974 975 // Find form fields, validate, and set value pairs 976 function findFields(form, result) { 977 var status = null; 978 result = result || {}; 979 980 // The ":input" selector is a jQuery shortcut to select all inputs, selects, textareas 981 form.find(':input:not([type="submit"])').each(function(i, el) { 982 var field = $(el); 983 var type = field.attr('type'); 984 var name = field.attr('data-name') || field.attr('name') || ('Field ' + (i + 1)); 985 var value = field.val(); 986 987 if (type === 'checkbox') { 988 value = field.is(':checked'); 989 } if (type === 'radio') { 990 // Radio group value already processed 991 if (result[name] === null || typeof result[name] === 'string') { 992 return; 993 } 994 995 value = form.find('input[name="' + field.attr('name') + '"]:checked').val() || null; 996 } 997 998 if (typeof value === 'string') value = $.trim(value); 999 result[name] = value; 1000 status = status || getStatus(field, type, name, value); 1001 }); 1002 1003 return status; 1004 } 1005 1006 function getStatus(field, type, name, value) { 1007 var status = null; 1008 1009 if (type === 'password') { 1010 status = 'Passwords cannot be submitted.'; 1011 } else if (field.attr('required')) { 1012 if (!value) { 1013 status = 'Please fill out the required field: ' + name; 1014 } else if (emailField.test(name) || emailField.test(field.attr('type'))) { 1015 if (!emailValue.test(value)) status = 'Please enter a valid email address for: ' + name; 1016 } 1017 } 1018 1019 return status; 1020 } 1021 1022 // Submit form to Webflow 1023 function submitWebflow(data) { 1024 reset(data); 1025 1026 var form = data.form; 1027 var payload = { 1028 name: form.attr('data-name') || form.attr('name') || 'Untitled Form', 1029 source: loc.href, 1030 test: Webflow.env(), 1031 fields: {}, 1032 dolphin: /pass[\s-_]?(word|code)|secret|login|credentials/i.test(form.html()) 1033 }; 1034 1035 preventDefault(data); 1036 1037 // Find & populate all fields 1038 var status = findFields(form, payload.fields); 1039 if (status) return alert(status); 1040 1041 // Disable submit button 1042 disableBtn(data); 1043 1044 // Read site ID 1045 // NOTE: If this site is exported, the HTML tag must retain the data-wf-site attribute for forms to work 1046 if (!siteId) { afterSubmit(data); return; } 1047 var url = "https://webflow.com" + '/api/v1/form/' + siteId; 1048 1049 // Work around same-protocol IE XDR limitation - without this IE9 and below forms won't submit 1050 if (retro && url.indexOf("https://webflow.com") >= 0) { 1051 url = url.replace("https://webflow.com", "http://formdata.webflow.com"); 1052 } 1053 1054 $.ajax({
1055 url: url, 1056 type: 'POST', 1057 data: payload, 1058 dataType: 'json', 1059 crossDomain: true 1060 }).done(function() { 1061 data.success = true; 1062 afterSubmit(data); 1063 }).fail(function() { 1064 afterSubmit(data); 1065 }); 1066 } 1067 1068 // Submit form to MailChimp 1069 function submitMailChimp(data) { 1070 reset(data); 1071 1072 var form = data.form; 1073 var payload = {}; 1074 1075 // Skip Ajax submission if http/s mismatch, fallback to POST instead 1076 if (/^https/.test(loc.href) && !/^https/.test(data.action)) { 1077 form.attr('method', 'post'); 1078 return; 1079 } 1080 1081 preventDefault(data); 1082 1083 // Find & populate all fields 1084 var status = findFields(form, payload); 1085 if (status) return alert(status); 1086 1087 // Disable submit button 1088 disableBtn(data); 1089 1090 // Use special format for MailChimp params 1091 var fullName; 1092 _.each(payload, function(value, key) { 1093 if (emailField.test(key)) payload.EMAIL = value; 1094 if (/^((full[ _-]?)?name)$/i.test(key)) fullName = value; 1095 if (/^(first[ _-]?name)$/i.test(key)) payload.FNAME = value; 1096 if (/^(last[ _-]?name)$/i.test(key)) payload.LNAME = value; 1097 }); 1098 1099 if (fullName && !payload.FNAME) { 1100 fullName = fullName.split(' '); 1101 payload.FNAME = fullName[0]; 1102 payload.LNAME = payload.LNAME || fullName[1]; 1103 } 1104 1105 // Use the (undocumented) MailChimp jsonp api 1106 var url = data.action.replace('/post?', '/post-json?') + '&c=?'; 1107 // Add special param to prevent bot signups 1108 var userId = url.indexOf('u=') + 2; 1109 userId = url.substring(userId, url.indexOf('&', userId)); 1110 var listId = url.indexOf('id=') + 3; 1111 listId = url.substring(listId, url.indexOf('&', listId)); 1112 payload['b_' + userId + '_' + listId] = ''; 1113 1114 $.ajax({
1115 url: url, 1116 data: payload, 1117 dataType: 'jsonp' 1118 }).done(function(resp) { 1119 data.success = (resp.result === 'success' || /already/.test(resp.msg)); 1120 if (!data.success) console.info('MailChimp error: ' + resp.msg); 1121 afterSubmit(data); 1122 }).fail(function() { 1123 afterSubmit(data); 1124 }); 1125 } 1126 1127 // Common callback which runs after all Ajax submissions 1128 function afterSubmit(data) { 1129 var form = data.form; 1130 var redirect = data.redirect; 1131 var success = data.success; 1132 1133 // Redirect to a success url if defined 1134 if (success && redirect) { 1135 Webflow.location(redirect); 1136 return; 1137 } 1138 1139 // Show or hide status divs 1140 data.done.toggle(success); 1141 data.fail.toggle(!success); 1142 1143 // Hide form on success 1144 form.toggle(!success); 1145 1146 // Reset data and enable submit button 1147 reset(data); 1148 } 1149 1150 function preventDefault(data) { 1151 data.evt && data.evt.preventDefault(); 1152 data.evt = null; 1153 } 1154 1155 // Export module 1156 return api; 1157 }); 1158 }); 1159 1160 var webflowIxEvents = __commonjs(function (module) { 1161 'use strict'; 1162 1163 /** 1164 * Webflow: IX Event triggers for other modules 1165 */ 1166 1167 var $ = window.jQuery; 1168 var api = {}; 1169 var eventQueue = []; 1170 var namespace = '.w-ix'; 1171 1172 var eventTriggers = { 1173 reset: function(i, el) { 1174 el.__wf_intro = null; 1175 }, 1176 intro: function(i, el) { 1177 if (el.__wf_intro) return; 1178 el.__wf_intro = true; 1179 $(el).triggerHandler(api.types.INTRO); 1180 }, 1181 outro: function(i, el) { 1182 if (!el.__wf_intro) return; 1183 el.__wf_intro = null; 1184 $(el).triggerHandler(api.types.OUTRO); 1185 } 1186 }; 1187 1188 api.triggers = {}; 1189 1190 api.types = { 1191 INTRO: 'w-ix-intro' + namespace, 1192 OUTRO: 'w-ix-outro' + namespace 1193 }; 1194 1195 // Trigger any events in queue + restore trigger methods 1196 api.init = function() { 1197 var count = eventQueue.length; 1198 for (var i = 0; i < count; i++) { 1199 var memo = eventQueue[i]; 1200 memo[0](0, memo[1]); 1201 } 1202 eventQueue = []; 1203 $.extend(api.triggers, eventTriggers); 1204 }; 1205 1206 // Replace all triggers with async wrapper to queue events until init 1207 api.async = function() { 1208 for (var key in eventTriggers) { 1209 var func = eventTriggers[key]; 1210 if (!eventTriggers.hasOwnProperty(key)) continue; 1211 1212 // Replace trigger method with async wrapper 1213 api.triggers[key] = function(i, el) { 1214 eventQueue.push([func, el]); 1215 }; 1216 } 1217 }; 1218 1219 // Default triggers to async queue 1220 api.async(); 1221 1222 module.exports = api; 1223 }); 1224 1225 var require$$0$2 = (webflowIxEvents && typeof webflowIxEvents === 'object' && 'default' in webflowIxEvents ? webflowIxEvents['default'] : webflowIxEvents); 1226 1227 var webflowIx = __commonjs(function (module) { 1228 /** 1229 * Webflow: Interactions 1230 */ 1231 1232 var Webflow = require$$0; 1233 var IXEvents = require$$0$2; 1234 1235 Webflow.define('ix', module.exports = function($, _) { 1236 var api = {}; 1237 var designer; 1238 var $win = $(window); 1239 var namespace = '.w-ix'; 1240 var tram = $.tram; 1241 var env = Webflow.env; 1242 var inApp = env(); 1243 var emptyFix = env.chrome && env.chrome < 35; 1244 var transNone = 'none 0s ease 0s'; 1245 var $subs = $(); 1246 var config = {}; 1247 var anchors = []; 1248 var loads = []; 1249 var readys = []; 1250 var destroyed; 1251 var readyDelay = 1; 1252 1253 // Component types and proxy selectors 1254 var components = { 1255 tabs: '.w-tab-link, .w-tab-pane', 1256 dropdown: '.w-dropdown', 1257 slider: '.w-slide-webflow-webflow', 1258 navbar: '.w-nav-webflow-webflow' 1259 }; 1260 1261 // ----------------------------------- 1262 // Module methods 1263 1264 api.init = function(list) { 1265 setTimeout(function() { configure(list); }, 1); 1266 }; 1267 1268 api.preview = function() { 1269 designer = false; 1270 readyDelay = 100; 1271 setTimeout(function() { configure(window.__wf_ix); }, 1); 1272 }; 1273 1274 api.design = function() { 1275 designer = true; 1276 api.destroy(); 1277 }; 1278 1279 api.destroy = function() { 1280 destroyed = true; 1281 $subs.each(teardown); 1282 Webflow.scroll.off(scroll); 1283 IXEvents.async(); 1284 anchors = []; 1285 loads = []; 1286 readys = []; 1287 }; 1288 1289 api.ready = function() { 1290 // Redirect IX init while in design/preview modes 1291 if (inApp) return env('design') ? api.design() : api.preview(); 1292 1293 // Ready should only be used after destroy, as a way to re-init 1294 if (config && destroyed) { 1295 destroyed = false; 1296 init(); 1297 } 1298 }; 1299 1300 api.run = run; 1301 api.style = inApp ? styleApp : stylePub; 1302 1303 // ----------------------------------- 1304 // Private methods 1305 1306 function configure(list) { 1307 if (!list) return; 1308 1309 // Map all interactions by slug 1310 config = {}; 1311 _.each(list, function(item) { 1312 config[item.slug] = item.value; 1313 }); 1314 1315 // Init ix after config 1316 init(); 1317 } 1318
1319 function init() { 1320 // Build each element's interaction keying from data attribute 1321 var els = $('[data-ix]'); 1322 if (!els.length) return; 1323 els.each(teardown); 1324 els.each(build); 1325 1326 // Listen for scroll events if any anchors exist 1327 if (anchors.length) { 1328 Webflow.scroll.on(scroll); 1329 setTimeout(scroll, 1); 1330 } 1331 1332 // Handle loads or readys if they exist 1333 if (loads.length) Webflow.load(runLoads); 1334 if (readys.length) setTimeout(runReadys, readyDelay); 1335 1336 // Trigger queued events, must happen after init 1337 IXEvents.init(); 1338 1339 // Trigger a redraw to ensure all IX intros play 1340 Webflow.redraw.up(); 1341 } 1342 1343 function build(i, el) { 1344 var $el = $(el); 1345 var id = $el.attr('data-ix'); 1346 var ix = config[id]; 1347 if (!ix) return; 1348 var triggers = ix.triggers; 1349 if (!triggers) return; 1350 1351 // Set styles immediately to provide tram with starting transform values 1352 api.style($el, ix.style); 1353 1354 _.each(triggers, function(trigger) { 1355 var state = {}; 1356 var type = trigger.type; 1357 var stepsB = trigger.stepsB && trigger.stepsB.length; 1358 1359 function runA() { run(trigger, $el, { group: 'A' }); } 1360 function runB() { run(trigger, $el, { group: 'B' }); } 1361 1362 if (type === 'load') { 1363 (trigger.preload && !inApp) ? loads.push(runA) : readys.push(runA); 1364 return; 1365 } 1366 1367 if (type === 'click') { 1368 $el.on('click' + namespace, function(evt) { 1369 // Avoid late clicks on touch devices 1370 if (!Webflow.validClick(evt.currentTarget)) return; 1371 1372 // Prevent default on empty hash urls 1373 if ($el.attr('href') === '#') evt.preventDefault(); 1374 1375 run(trigger, $el, { group: state.clicked ? 'B' : 'A' }); 1376 if (stepsB) state.clicked = !state.clicked; 1377 }); 1378 $subs = $subs.add($el); 1379 return; 1380 } 1381 1382 if (type === 'hover') { 1383 $el.on('mouseenter' + namespace, runA); 1384 $el.on('mouseleave' + namespace, runB); 1385 $subs = $subs.add($el); 1386 return; 1387 } 1388 1389 if (type === 'scroll') { 1390 anchors.push({ 1391 el: $el, trigger: trigger, state: { active: false }, 1392 offsetTop: convert(trigger.offsetTop), 1393 offsetBot: convert(trigger.offsetBot) 1394 }); 1395 return; 1396 } 1397 1398 // Check for a proxy component selector 1399 // type == [tabs, dropdown, slider, navbar] 1400 var proxy = components[type]; 1401 if (proxy) { 1402 var $proxy = $el.closest(proxy); 1403 $proxy.on(IXEvents.types.INTRO, runA).on(IXEvents.types.OUTRO, runB); 1404 $subs = $subs.add($proxy); 1405 return; 1406 } 1407 }); 1408 } 1409 1410 function convert(offset) { 1411 if (!offset) return 0; 1412 offset = String(offset); 1413 var result = parseInt(offset, 10); 1414 if (result !== result) return 0; 1415 if (offset.indexOf('%') > 0) { 1416 result /= 100; 1417 if (result >= 1) result = 0.999; 1418 } 1419 return result; 1420 } 1421 1422 function teardown(i, el) { 1423 $(el).off(namespace); 1424 } 1425 1426 function scroll() { 1427 var viewTop = $win.scrollTop(); 1428 var viewHeight = $win.height(); 1429 1430 // Check each anchor for a valid scroll trigger 1431 var count = anchors.length; 1432 for (var i = 0; i < count; i++) { 1433 var anchor = anchors[i]; 1434 var $el = anchor.el; 1435 var trigger = anchor.trigger; 1436 var stepsB = trigger.stepsB && trigger.stepsB.length; 1437 var state = anchor.state; 1438 var top = $el.offset().top; 1439 var height = $el.outerHeight(); 1440 var offsetTop = anchor.offsetTop; 1441 var offsetBot = anchor.offsetBot; 1442 if (offsetTop < 1 && offsetTop > 0) offsetTop *= viewHeight; 1443 if (offsetBot < 1 && offsetBot > 0) offsetBot *= viewHeight; 1444 var active = (top + height - offsetTop >= viewTop && top + offsetBot <= viewTop + viewHeight); 1445 if (active === state.active) continue; 1446 if (active === false && !stepsB) continue; 1447 state.active = active; 1448 run(trigger, $el, { group: active ? 'A' : 'B' });
1449 } 1450 } 1451 1452 function runLoads() { 1453 var count = loads.length; 1454 for (var i = 0; i < count; i++) { 1455 loads[i](); 1456 } 1457 } 1458 1459 function runReadys() { 1460 var count = readys.length; 1461 for (var i = 0; i < count; i++) { 1462 readys[i](); 1463 } 1464 } 1465 1466 function run(trigger, $el, opts, replay) { 1467 opts = opts || {}; 1468 var done = opts.done; 1469 var preserve3d = trigger.preserve3d; 1470 1471 // Do not run in designer unless forced 1472 if (designer && !opts.force) return; 1473 1474 // Operate on a set of grouped steps 1475 var group = opts.group || 'A'; 1476 var loop = trigger['loop' + group]; 1477 var steps = trigger['steps' + group]; 1478 if (!steps || !steps.length) return; 1479 if (steps.length < 2) loop = false; 1480 1481 // One-time init before any loops 1482 if (!replay) { 1483 1484 // Find selector within element descendants, siblings, or query whole document 1485 var selector = trigger.selector; 1486 if (selector) { 1487 if (trigger.descend) { 1488 $el = $el.find(selector); 1489 } else if (trigger.siblings) { 1490 $el = $el.siblings(selector); 1491 } else { 1492 $el = $(selector); 1493 } 1494 if (inApp) $el.attr('data-ix-affect', 1); 1495 } 1496 1497 // Apply empty fix for certain Chrome versions 1498 if (emptyFix) $el.addClass('w-ix-emptyfix'); 1499 1500 // Set preserve3d for triggers with 3d transforms 1501 if (preserve3d) $el.css('transform-style', 'preserve-3d'); 1502 } 1503 1504 var _tram = tram($el); 1505 1506 // Add steps 1507 var meta = {omit3d: !preserve3d}; 1508 for (var i = 0; i < steps.length; i++) { 1509 addStep(_tram, steps[i], meta); 1510 } 1511 1512 function fin() { 1513 // Run trigger again if looped 1514 if (loop) return run(trigger, $el, opts, true); 1515 1516 // Reset any 'auto' values 1517 if (meta.width === 'auto') _tram.set({ width: 'auto' }); 1518 if (meta.height === 'auto') _tram.set({ height: 'auto' }); 1519 1520 // Run callback 1521 done && done(); 1522 } 1523 1524 // Add final step to queue if tram has started 1525 meta.start ? _tram.then(fin) : fin(); 1526 } 1527 1528 function addStep(_tram, step, meta) { 1529 var addMethod = 'add'; 1530 var startMethod = 'start'; 1531 1532 // Once the transition has started, we will always use then() to add to the queue. 1533 if (meta.start) addMethod = startMethod = 'then'; 1534 1535 // Parse transitions string on the current step 1536 var transitions = step.transition; 1537 if (transitions) { 1538 transitions = transitions.split(','); 1539 for (var i = 0; i < transitions.length; i++) { 1540 var transition = transitions[i]; 1541 _tram[addMethod](transition); 1542 } 1543 } 1544 1545 // Build a clean object to pass to the tram method 1546 var clean = tramify(step, meta) || {}; 1547 1548 // Store last width and height values 1549 if (clean.width != null) meta.width = clean.width; 1550 if (clean.height != null) meta.height = clean.height; 1551 1552 // When transitions are not present, set values immediately and continue queue. 1553 if (transitions == null) { 1554 1555 // If we have started, wrap set() in then() and reset queue 1556 if (meta.start) { 1557 _tram.then(function() { 1558 var queue = this.queue; 1559 this.set(clean); 1560 if (clean.display) { 1561 _tram.redraw(); 1562 Webflow.redraw.up(); 1563 } 1564 this.queue = queue; 1565 this.next(); 1566 }); 1567 } else { 1568 _tram.set(clean); 1569 1570 // Always redraw after setting display 1571 if (clean.display) { 1572 _tram.redraw(); 1573 Webflow.redraw.up(); 1574 } 1575 } 1576 1577 // Use the wait() method to kick off queue in absence of transitions. 1578 var wait = clean.wait; 1579 if (wait != null) { 1580 _tram.wait(wait); 1581 meta.start = true; 1582 } 1583 1584 // Otherwise, when transitions are present 1585 } else { 1586 1587 // If display is present, handle it separately 1588 if (clean.display) { 1589 var display = clean.display; 1590 delete clean.display; 1591 1592 // If we've already started, we need to wrap it in a then() 1593 if (meta.start) { 1594 _tram.then(function() { 1595 var queue = this.queue; 1596 this.set({ display: display }).redraw(); 1597 Webflow.redraw.up(); 1598 this.queue = queue; 1599 this.next(); 1600 }); 1601 } else { 1602 _tram.set({ display: display }).redraw(); 1603 Webflow.redraw.up(); 1604 } 1605 } 1606 1607 // Otherwise, start a transition using the current start method. 1608 _tram[startMethod](clean); 1609 meta.start = true; 1610 } 1611 } 1612 1613 // (In app) Set styles immediately and manage upstream transition
1614 function styleApp(el, data) { 1615 var _tram = tram(el); 1616 1617 // Exit early when data is empty to avoid clearing upstream 1618 if ($.isEmptyObject(data)) return; 1619 1620 // Get computed transition value 1621 el.css('transition', ''); 1622 var computed = el.css('transition'); 1623 1624 // If computed is set to none, clear upstream 1625 if (computed === transNone) computed = _tram.upstream = null; 1626 1627 // Set upstream transition to none temporarily 1628 _tram.upstream = transNone; 1629 1630 // Set values immediately 1631 _tram.set(tramify(data)); 1632 1633 // Only restore upstream in preview mode 1634 _tram.upstream = computed; 1635 } 1636 1637 // (Published) Set styles immediately on specified jquery element 1638 function stylePub(el, data) { 1639 tram(el).set(tramify(data)); 1640 } 1641 1642 // Build a clean object for tram 1643 function tramify(obj, meta) { 1644 var omit3d = meta && meta.omit3d; 1645 var result = {}; 1646 var found = false; 1647 for (var key in obj) { 1648 if (key === 'transition') continue; 1649 if (key === 'keysort') continue; 1650 if (omit3d) { 1651 if (key === 'z' || key === 'rotateX' || key === 'rotateY' || key === 'scaleZ') { 1652 continue; 1653 } 1654 } 1655 result[key] = obj[key]; 1656 found = true; 1657 } 1658 // If empty, return null for tram.set/stop compliance 1659 return found ? result : null; 1660 } 1661 1662 // Export module 1663 return api; 1664 }); 1665 }); 1666 1667 var webflowLinks = __commonjs(function (module) { 1668 /** 1669 * Webflow: Auto-select links to current page or section 1670 */ 1671 1672 var Webflow = require$$0; 1673 1674 Webflow.define('links', module.exports = function($, _) { 1675 var api = {}; 1676 var $win = $(window); 1677 var designer; 1678 var inApp = Webflow.env(); 1679 var location = window.location; 1680 var tempLink = document.createElement('a'); 1681 var linkCurrent = 'w--current'; 1682 var validHash = /^#[a-zA-Z][\w:.-]*$/; 1683 var indexPage = /index\.(html|php)$/; 1684 var dirList = /\/$/; 1685 var anchors; 1686 var slug; 1687 1688 // ----------------------------------- 1689 // Module methods 1690 1691 api.ready = api.design = api.preview = init; 1692 1693 // ----------------------------------- 1694 // Private methods 1695 1696 function init() { 1697 designer = inApp && Webflow.env('design'); 1698 slug = Webflow.env('slug') || location.pathname || ''; 1699 1700 // Reset scroll listener, init anchors 1701 Webflow.scroll.off(scroll); 1702 anchors = []; 1703 1704 // Test all links for a selectable href 1705 var links = document.links; 1706 for (var i = 0; i < links.length; ++i) { 1707 select(links[i]); 1708 } 1709 1710 // Listen for scroll if any anchors exist 1711 if (anchors.length) { 1712 Webflow.scroll.on(scroll); 1713 scroll(); 1714 } 1715 } 1716 1717 function select(link) { 1718 var href = (designer && link.getAttribute('href-disabled')) || link.getAttribute('href'); 1719 tempLink.href = href; 1720 1721 // Ignore any hrefs with a colon to safely avoid all uri schemes 1722 if (href.indexOf(':') >= 0) return; 1723 1724 var $link = $(link); 1725 1726 // Check for valid hash links w/ sections and use scroll anchor 1727 if (href.indexOf('#') === 0 && validHash.test(href)) { 1728 var $section = $(href); 1729 $section.length && anchors.push({ link: $link, sec: $section, active: false }); 1730 return; 1731 } 1732 1733 // Ignore empty # links 1734 if (href === '#') return; 1735 1736 // Determine whether the link should be selected 1737 var match = (tempLink.href === location.href) || (href === slug) || (indexPage.test(href) && dirList.test(slug)); 1738 setClass($link, linkCurrent, match); 1739 } 1740 1741 function scroll() { 1742 var viewTop = $win.scrollTop(); 1743 var viewHeight = $win.height(); 1744 1745 // Check each anchor for a section in view 1746 _.each(anchors, function(anchor) { 1747 var $link = anchor.link; 1748 var $section = anchor.sec; 1749 var top = $section.offset().top; 1750 var height = $section.outerHeight(); 1751 var offset = viewHeight * 0.5; 1752 var active = ($section.is(':visible') && 1753 top + height - offset >= viewTop && 1754 top + offset <= viewTop + viewHeight); 1755 if (anchor.active === active) return; 1756 anchor.active = active; 1757 setClass($link, linkCurrent, active); 1758 if (designer) $link[0].__wf_current = active; 1759 }); 1760 } 1761 1762 function setClass($elem, className, add) { 1763 var exists = $elem.hasClass(className); 1764 if (add && exists) return; 1765 if (!add && !exists) return; 1766 add ? $elem.addClass(className) : $elem.removeClass(className); 1767 } 1768 1769 // Export module 1770 return api; 1771 }); 1772 }); 1773 1774 var webflowNavbar = __commonjs(function (module) { 1775 /** 1776 * Webflow: Navbar component 1777 */ 1778 1779 var Webflow = require$$0; 1780 var IXEvents = require$$0$2; 1781 1782 Webflow.define('navbar', module.exports = function($, _) { 1783 var api = {}; 1784 var tram = $.tram; 1785 var $win = $(window); 1786 var $doc = $(document); 1787 var $body;
1788 var $navbars; 1789 var designer; 1790 var inApp = Webflow.env(); 1791 var overlay = '<div class="w-nav-overlay-webflow" data-wf-ignore />'; 1792 var namespace = '.w-nav-webflow'; 1793 var buttonOpen = 'w--open'; 1794 var menuOpen = 'w--nav-menu-open'; 1795 var linkOpen = 'w--nav-link-open'; 1796 var ix = IXEvents.triggers; 1797 var menuSibling = $(); 1798 1799 // ----------------------------------- 1800 // Module methods 1801 1802 api.ready = api.design = api.preview = init; 1803 1804 api.destroy = function() { 1805 menuSibling = $(); 1806 removeListeners(); 1807 if ($navbars && $navbars.length) { 1808 $navbars.each(teardown); 1809 } 1810 }; 1811 1812 // ----------------------------------- 1813 // Private methods 1814 1815 function init() { 1816 designer = inApp && Webflow.env('design'); 1817 $body = $(document.body); 1818 1819 // Find all instances on the page 1820 $navbars = $doc.find(namespace); 1821 if (!$navbars.length) return; 1822 $navbars.each(build); 1823 1824 // Wire events 1825 removeListeners(); 1826 addListeners(); 1827 } 1828 1829 function removeListeners() { 1830 Webflow.resize.off(resizeAll); 1831 } 1832 1833 function addListeners() { 1834 Webflow.resize.on(resizeAll); 1835 } 1836 1837 function resizeAll() { 1838 $navbars.each(resize); 1839 } 1840 1841 function build(i, el) { 1842 var $el = $(el); 1843 1844 // Store state in data 1845 var data = $.data(el, namespace); 1846 if (!data) data = $.data(el, namespace, { open: false, el: $el, config: {} }); 1847 data.menu = $el.find('.w-nav-menu-webflow'); 1848 data.links = data.menu.find('.w-nav-link-webflow'); 1849 data.dropdowns = data.menu.find('.w-dropdown'); 1850 data.button = $el.find('.w-nav-button'); 1851 data.container = $el.find('.w-container'); 1852 data.outside = outside(data); 1853 1854 // Remove old events 1855 data.el.off(namespace); 1856 data.button.off(namespace); 1857 data.menu.off(namespace); 1858 1859 // Set config from data attributes 1860 configure(data); 1861 1862 // Add events based on mode 1863 if (designer) { 1864 removeOverlay(data); 1865 data.el.on('setting' + namespace, handler(data)); 1866 } else { 1867 addOverlay(data); 1868 data.button.on('tap' + namespace, toggle(data)); 1869 data.menu.on('click' + namespace, 'a', navigate(data)); 1870 } 1871 1872 // Trigger initial resize 1873 resize(i, el); 1874 } 1875 1876 function teardown(i, el) { 1877 var data = $.data(el, namespace); 1878 if (data) { 1879 removeOverlay(data); 1880 $.removeData(el, namespace); 1881 } 1882 } 1883 1884 function removeOverlay(data) { 1885 if (!data.overlay) return; 1886 close(data, true); 1887 data.overlay.remove(); 1888 data.overlay = null; 1889 } 1890 1891 function addOverlay(data) { 1892 if (data.overlay) return; 1893 data.overlay = $(overlay).appendTo(data.el); 1894 data.parent = data.menu.parent(); 1895 close(data, true); 1896 } 1897 1898 function configure(data) { 1899 var config = {}; 1900 var old = data.config || {}; 1901 1902 // Set config options from data attributes 1903 var animation = config.animation = data.el.attr('data-animation') || 'default'; 1904 config.animOver = /^over/.test(animation); 1905 config.animDirect = /left$/.test(animation) ? -1 : 1; 1906 1907 // Re-open menu if the animation type changed 1908 if (old.animation !== animation) { 1909 data.open && _.defer(reopen, data); 1910 } 1911 1912 config.easing = data.el.attr('data-easing') || 'ease'; 1913 config.easing2 = data.el.attr('data-easing2') || 'ease'; 1914 1915 var duration = data.el.attr('data-duration'); 1916 config.duration = duration != null ? Number(duration) : 400; 1917 1918 config.docHeight = data.el.attr('data-doc-height'); 1919 1920 // Store config in data 1921 data.config = config; 1922 } 1923 1924 function handler(data) { 1925 return function(evt, options) { 1926 options = options || {}; 1927 var winWidth = $win.width(); 1928 configure(data); 1929 options.open === true && open(data, true); 1930 options.open === false && close(data, true); 1931 // Reopen if media query changed after setting 1932 data.open && _.defer(function() { 1933 if (winWidth !== $win.width()) reopen(data); 1934 }); 1935 }; 1936 } 1937 1938 function reopen(data) { 1939 if (!data.open) return; 1940 close(data, true); 1941 open(data, true); 1942 } 1943 1944 function toggle(data) { 1945 // Debounce toggle to wait for accurate open state 1946 return _.debounce(function() { 1947 data.open ? close(data) : open(data); 1948 }); 1949 } 1950 1951 function navigate(data) { 1952 return function(evt) { 1953 var link = $(this); 1954 var href = link.attr('href'); 1955 1956 // Avoid late clicks on touch devices 1957 if (!Webflow.validClick(evt.currentTarget)) { 1958 evt.preventDefault(); 1959 return; 1960 } 1961 1962 // Close when navigating to an in-page anchor 1963 if (href && href.indexOf('#') === 0 && data.open) { 1964 close(data); 1965 } 1966 }; 1967 } 1968 1969 function outside(data) { 1970 // Unbind previous tap handler if it exists 1971 if (data.outside) $doc.off('tap' + namespace, data.outside); 1972 1973 // Close menu when tapped outside, debounced to wait for state 1974 return _.debounce(function(evt) { 1975 if (!data.open) return; 1976 var menu = $(evt.target).closest('.w-nav-menu-webflow'); 1977 if (!data.menu.is(menu)) { 1978 close(data); 1979 } 1980 }); 1981 } 1982 1983 function resize(i, el) { 1984 var data = $.data(el, namespace);
1985 // Check for collapsed state based on button display 1986 var collapsed = data.collapsed = data.button.css('display') !== 'none'; 1987 // Close menu if button is no longer visible (and not in designer) 1988 if (data.open && !collapsed && !designer) close(data, true); 1989 // Set max-width of links + dropdowns to match container 1990 if (data.container.length) { 1991 var updateEachMax = updateMax(data); 1992 data.links.each(updateEachMax); 1993 data.dropdowns.each(updateEachMax); 1994 } 1995 // If currently open, update height to match body 1996 if (data.open) { 1997 setOverlayHeight(data); 1998 } 1999 } 2000 2001 var maxWidth = 'max-width'; 2002 function updateMax(data) { 2003 // Set max-width of each element to match container 2004 var containMax = data.container.css(maxWidth); 2005 if (containMax === 'none') containMax = ''; 2006 return function(i, link) { 2007 link = $(link); 2008 link.css(maxWidth, ''); 2009 // Don't set the max-width if an upstream value exists 2010 if (link.css(maxWidth) === 'none') link.css(maxWidth, containMax); 2011 }; 2012 } 2013 2014 function open(data, immediate) { 2015 if (data.open) return; 2016 data.open = true; 2017 data.menu.addClass(menuOpen); 2018 data.links.addClass(linkOpen); 2019 data.button.addClass(buttonOpen); 2020 var config = data.config; 2021 var animation = config.animation; 2022 if (animation === 'none' || !tram.support.transform) immediate = true; 2023 var bodyHeight = setOverlayHeight(data); 2024 var menuHeight = data.menu.outerHeight(true); 2025 var menuWidth = data.menu.outerWidth(true); 2026 var navHeight = data.el.height(); 2027 var navbarEl = data.el[0]; 2028 resize(0, navbarEl); 2029 ix.intro(0, navbarEl); 2030 Webflow.redraw.up(); 2031 2032 // Listen for tap outside events 2033 if (!designer) $doc.on('tap' + namespace, data.outside); 2034 2035 // No transition for immediate 2036 if (immediate) return; 2037 2038 var transConfig = 'transform ' + config.duration + 'ms ' + config.easing; 2039 2040 // Add menu to overlay 2041 if (data.overlay) { 2042 menuSibling = data.menu.prev(); 2043 data.overlay.show().append(data.menu); 2044 } 2045 2046 // Over left/right 2047 if (config.animOver) { 2048 tram(data.menu) 2049 .add(transConfig) 2050 .set({ x: config.animDirect * menuWidth, height: bodyHeight }).start({ x: 0 }); 2051 data.overlay && data.overlay.width(menuWidth); 2052 return; 2053 } 2054 2055 // Drop Down 2056 var offsetY = navHeight + menuHeight; 2057 tram(data.menu) 2058 .add(transConfig) 2059 .set({ y: -offsetY }).start({ y: 0 }); 2060 } 2061 2062 function setOverlayHeight(data) { 2063 var config = data.config; 2064 var bodyHeight = config.docHeight ? $doc.height() : $body.height(); 2065 if (config.animOver) { 2066 data.menu.height(bodyHeight); 2067 } else if (data.el.css('position') !== 'fixed') { 2068 bodyHeight -= data.el.height(); 2069 } 2070 data.overlay && data.overlay.height(bodyHeight); 2071 return bodyHeight; 2072 } 2073 2074 function close(data, immediate) { 2075 if (!data.open) return; 2076 data.open = false; 2077 data.button.removeClass(buttonOpen); 2078 var config = data.config; 2079 if (config.animation === 'none' || !tram.support.transform || config.duration <= 0) immediate = true; 2080 ix.outro(0, data.el[0]); 2081 2082 // Stop listening for tap outside events 2083 $doc.off('tap' + namespace, data.outside); 2084 2085 if (immediate) { 2086 tram(data.menu).stop(); 2087 complete(); 2088 return; 2089 } 2090 2091 var transConfig = 'transform ' + config.duration + 'ms ' + config.easing2; 2092 var menuHeight = data.menu.outerHeight(true); 2093 var menuWidth = data.menu.outerWidth(true); 2094 var navHeight = data.el.height(); 2095 2096 // Over left/right 2097 if (config.animOver) { 2098 tram(data.menu) 2099 .add(transConfig) 2100 .start({ x: menuWidth * config.animDirect }).then(complete); 2101 return; 2102 } 2103 2104 // Drop Down 2105 var offsetY = navHeight + menuHeight; 2106 tram(data.menu) 2107 .add(transConfig) 2108 .start({ y: -offsetY }).then(complete); 2109 2110 function complete() { 2111 data.menu.height(''); 2112 tram(data.menu).set({ x: 0, y: 0 }); 2113 data.menu.removeClass(menuOpen); 2114 data.links.removeClass(linkOpen); 2115 if (data.overlay && data.overlay.children().length) { 2116 // Move menu back to parent at the original location 2117 menuSibling.length ? data.menu.insertAfter(menuSibling) : data.menu.prependTo(data.parent); 2118 data.overlay.attr('style', '').hide(); 2119 } 2120 2121 // Trigger event so other components can hook in (dropdown) 2122 data.el.triggerHandler('w-close'); 2123 } 2124 } 2125 2126 // Export module 2127 return api; 2128 }); 2129 }); 2130 2131 var webflowScroll = __commonjs(function (module) { 2132 /** 2133 * Webflow: Smooth scroll 2134 */ 2135 2136 var Webflow = require$$0; 2137 2138 Webflow.define('scroll', module.exports = function($) { 2139 var $doc = $(document); 2140 var win = window; 2141 var loc = win.location; 2142 var history = inIframe() ? null : win.history;
2143 var validHash = /^[a-zA-Z0-9][\w:.-]*$/; 2144 2145 function inIframe() { 2146 try { 2147 return Boolean(win.frameElement); 2148 } catch (e) { 2149 return true; 2150 } 2151 } 2152 2153 function ready() { 2154 // If hash is already present on page load, scroll to it right away 2155 if (loc.hash) { 2156 findEl(loc.hash.substring(1)); 2157 } 2158 2159 // The current page url without the hash part. 2160 var locHref = loc.href.split('#')[0]; 2161 2162 // When clicking on a link, check if it links to another part of the page 2163 $doc.on('click', 'a', function(e) { 2164 if (Webflow.env('design')) { 2165 return; 2166 } 2167 2168 // Ignore links being used by jQuery mobile 2169 if (window.$.mobile && $(e.currentTarget).hasClass('ui-link')) return; 2170 2171 // Ignore empty # links 2172 if (this.getAttribute('href') === '#') { 2173 e.preventDefault(); 2174 return; 2175 } 2176 2177 // The href property always contains the full url so we can compare 2178 // with the documentâs location to only target links on this page. 2179 var parts = this.href.split('#'); 2180 var hash = parts[0] === locHref ? parts[1] : null; 2181 if (hash) { 2182 findEl(hash, e); 2183 } 2184 }); 2185 } 2186 2187 function findEl(hash, e) { 2188 if (!validHash.test(hash)) return; 2189 2190 var el = $('#' + hash); 2191 if (!el.length) { 2192 return; 2193 } 2194 2195 if (e) { 2196 e.preventDefault(); 2197 e.stopPropagation(); 2198 } 2199 2200 // Push new history state 2201 if ( 2202 loc.hash !== hash && 2203 history && history.pushState && 2204 // Navigation breaks Chrome when the protocol is `file:`. 2205 !(Webflow.env.chrome && loc.protocol === 'file:') 2206 ) { 2207 var oldHash = history.state && history.state.hash; 2208 if (oldHash !== hash) { 2209 history.pushState({ hash: hash }, '', '#' + hash); 2210 } 2211 } 2212 2213 // If a fixed header exists, offset for the height 2214 var rootTag = Webflow.env('editor') ? '.w-editor-body' : 'body'; 2215 var header = $('header, ' + rootTag + ' > .header, ' + rootTag + ' > .w-nav:not([data-no-scroll])'); 2216 var offset = header.css('position') === 'fixed' ? header.outerHeight() : 0; 2217 2218 win.setTimeout(function() { 2219 scroll(el, offset); 2220 }, e ? 0 : 300); 2221 } 2222 2223 function scroll(el, offset){ 2224 var start = $(win).scrollTop(); 2225 var end = el.offset().top - offset; 2226 2227 // If specified, scroll so that the element ends up in the middle of the viewport 2228 if (el.data('scroll') === 'mid') { 2229 var available = $(win).height() - offset; 2230 var elHeight = el.outerHeight(); 2231 if (elHeight < available) { 2232 end -= Math.round((available - elHeight) / 2); 2233 } 2234 } 2235 2236 var mult = 1; 2237 2238 // Check for custom time multiplier on the body and the element 2239 $('body').add(el).each(function() { 2240 var time = parseFloat($(this).attr('data-scroll-time'), 10); 2241 if (!isNaN(time) && (time === 0 || time > 0)) { 2242 mult = time; 2243 } 2244 }); 2245 2246 // Shim for IE8 and below 2247 if (!Date.now) { 2248 Date.now = function() { return new Date().getTime(); }; 2249 } 2250 2251 var clock = Date.now(); 2252 var animate = win.requestAnimationFrame || win.mozRequestAnimationFrame || win.webkitRequestAnimationFrame || function(fn) { win.setTimeout(fn, 15); }; 2253 var duration = (472.143 * Math.log(Math.abs(start - end) +125) - 2000) * mult; 2254 2255 var step = function() { 2256 var elapsed = Date.now() - clock; 2257 win.scroll(0, getY(start, end, elapsed, duration)); 2258 2259 if (elapsed <= duration) { 2260 animate(step); 2261 } 2262 }; 2263 2264 step(); 2265 } 2266 2267 function getY(start, end, elapsed, duration) { 2268 if (elapsed > duration) { 2269 return end; 2270 } 2271 2272 return start + (end - start) * ease(elapsed / duration); 2273 } 2274 2275 function ease(t) { 2276 return t<0.5 ? 4 * t * t * t : (t-1) * (2 * t-2) * (2 * t-2)+1; 2277 } 2278 2279 // Export module 2280 return { ready: ready }; 2281 }); 2282 }); 2283 2284 var webflowSlider = __commonjs(function (module) { 2285 /** 2286 * Webflow: Slider component 2287 */ 2288 2289 var Webflow = require$$0; 2290 var IXEvents = require$$0$2; 2291 2292 Webflow.define('slider', module.exports = function($, _) { 2293 var api = {}; 2294 var tram = $.tram; 2295 var $doc = $(document); 2296 var $sliders; 2297 var designer; 2298 var inApp = Webflow.env(); 2299 var namespace = '.w-slider-webflow'; 2300 var dot = '<div class="w-slider-dot-weblow" data-wf-ignore />'; 2301 var ix = IXEvents.triggers; 2302 var fallback; 2303 var inRedraw; 2304 2305 // ----------------------------------- 2306 // Module methods 2307 2308 api.ready = function() { 2309 designer = Webflow.env('design'); 2310 init(); 2311 }; 2312 2313 api.design = function() { 2314 designer = true; 2315 init(); 2316 }; 2317 2318 api.preview = function() { 2319 designer = false; 2320 init(); 2321 }; 2322 2323 api.redraw = function() { 2324 inRedraw = true; 2325 init(); 2326 }; 2327 2328 api.destroy = removeListeners; 2329 2330 // ----------------------------------- 2331 // Private methods 2332
2333 function init() { 2334 // Find all sliders on the page 2335 $sliders = $doc.find(namespace); 2336 if (!$sliders.length) return; 2337 $sliders.filter(':visible').each(build); 2338 inRedraw = null; 2339 if (fallback) return; 2340 2341 removeListeners(); 2342 addListeners(); 2343 } 2344 2345 function removeListeners() { 2346 Webflow.resize.off(renderAll); 2347 Webflow.redraw.off(api.redraw); 2348 } 2349 2350 function addListeners() { 2351 Webflow.resize.on(renderAll); 2352 Webflow.redraw.on(api.redraw); 2353 } 2354 2355 function renderAll() { 2356 $sliders.filter(':visible').each(render); 2357 } 2358 2359 function build(i, el) { 2360 var $el = $(el); 2361 2362 // Store slider state in data 2363 var data = $.data(el, namespace); 2364 if (!data) { 2365 data = $.data(el, namespace, { 2366 index: 0, 2367 depth: 1, 2368 el: $el, 2369 config: {} 2370 }); 2371 } 2372 data.mask = $el.children('.w-slider-mask-webflow'); 2373 data.left = $el.children('.w-slider-arrow-left-webflow'); 2374 data.right = $el.children('.w-slider-arrow-right'); 2375 data.nav = $el.children('.w-slider-nav'); 2376 data.slides = data.mask.children('.w-slide-webflow'); 2377 data.slides.each(ix.reset); 2378 if (inRedraw) data.maskWidth = 0; 2379 2380 // Disable in old browsers 2381 if (!tram.support.transform) { 2382 data.left.hide(); 2383 data.right.hide(); 2384 data.nav.hide(); 2385 fallback = true; 2386 return; 2387 } 2388 2389 // Remove old events 2390 data.el.off(namespace); 2391 data.left.off(namespace); 2392 data.right.off(namespace); 2393 data.nav.off(namespace); 2394 2395 // Set config from data attributes 2396 configure(data); 2397 2398 // Add events based on mode 2399 if (designer) { 2400 data.el.on('setting' + namespace, handler(data)); 2401 stopTimer(data); 2402 data.hasTimer = false; 2403 } else { 2404 data.el.on('swipe' + namespace, handler(data)); 2405 data.left.on('tap' + namespace, previousFunction(data)); 2406 data.right.on('tap' + namespace, next(data)); 2407 2408 // Start timer if autoplay is true, only once 2409 if (data.config.autoplay && !data.hasTimer) { 2410 data.hasTimer = true; 2411 data.timerCount = 1; 2412 startTimer(data); 2413 } 2414 } 2415 2416 // Listen to nav events 2417 data.nav.on('tap' + namespace, '> div', handler(data)); 2418 2419 // Remove gaps from formatted html (for inline-blocks) 2420 if (!inApp) { 2421 data.mask.contents().filter(function() { 2422 return this.nodeType === 3; 2423 }).remove(); 2424 } 2425 2426 // Run first render 2427 render(i, el); 2428 } 2429 2430 function configure(data) { 2431 var config = {}; 2432 2433 config.crossOver = 0; 2434 2435 // Set config options from data attributes 2436 config.animation = data.el.attr('data-animation') || 'slide'; 2437 if (config.animation === 'outin') { 2438 config.animation = 'cross'; 2439 config.crossOver = 0.5; 2440 } 2441 config.easing = data.el.attr('data-easing') || 'ease'; 2442 2443 var duration = data.el.attr('data-duration'); 2444 config.duration = duration != null ? parseInt(duration, 10) : 500; 2445 2446 if (isAttrTrue(data.el.attr('data-infinite'))) { 2447 config.infinite = true; 2448 } 2449 2450 if (isAttrTrue(data.el.attr('data-disable-swipe'))) { 2451 config.disableSwipe = true; 2452 } 2453 2454 if (isAttrTrue(data.el.attr('data-hide-arrows'))) { 2455 config.hideArrows = true; 2456 } else if (data.config.hideArrows) { 2457 data.left.show(); 2458 data.right.show(); 2459 } 2460 2461 if (isAttrTrue(data.el.attr('data-autoplay'))) { 2462 config.autoplay = true; 2463 config.delay = parseInt(data.el.attr('data-delay'), 10) || 2000; 2464 config.timerMax = parseInt(data.el.attr('data-autoplay-limit'), 10); 2465 // Disable timer on first touch or mouse down 2466 var touchEvents = 'mousedown' + namespace + ' touchstart' + namespace; 2467 if (!designer) { 2468 data.el.off(touchEvents).one(touchEvents, function() { 2469 stopTimer(data); 2470 }); 2471 } 2472 } 2473 2474 // Use edge buffer to help calculate page count 2475 var arrowWidth = data.right.width(); 2476 config.edge = arrowWidth ? arrowWidth + 40 : 100; 2477 2478 // Store config in data 2479 data.config = config; 2480 } 2481 2482 function isAttrTrue(value) { 2483 return value === '1' || value === 'true'; 2484 } 2485 2486 function previousFunction(data) { 2487 return function() { 2488 change(data, { index: data.index - 1, vector: -1 }); 2489 }; 2490 } 2491 2492 function next(data) { 2493 return function() { 2494 change(data, { index: data.index + 1, vector: 1 }); 2495 }; 2496 } 2497 2498 function select(data, value) { 2499 // Select page based on slide element index 2500 var found = null; 2501 if (value === data.slides.length) { 2502 init(); layout(data); // Rebuild and find new slides 2503 } 2504 _.each(data.anchors, function(anchor, index) { 2505 $(anchor.els).each(function(i, el) { 2506 if ($(el).index() === value) found = index; 2507 }); 2508 }); 2509 if (found != null) change(data, { index: found, immediate: true });
2510 } 2511 2512 function startTimer(data) { 2513 stopTimer(data); 2514 var config = data.config; 2515 var timerMax = config.timerMax; 2516 if (timerMax && data.timerCount++ > timerMax) return; 2517 data.timerId = window.setTimeout(function() { 2518 if (data.timerId == null || designer) return; 2519 next(data)(); 2520 startTimer(data); 2521 }, config.delay); 2522 } 2523 2524 function stopTimer(data) { 2525 window.clearTimeout(data.timerId); 2526 data.timerId = null; 2527 } 2528 2529 function handler(data) { 2530 return function(evt, options) { 2531 options = options || {}; 2532 var config = data.config; 2533 2534 // Designer settings 2535 if (designer && evt.type === 'setting') { 2536 if (options.select === 'prev') return previousFunction(data)(); 2537 if (options.select === 'next') return next(data)(); 2538 configure(data); 2539 layout(data); 2540 if (options.select == null) return; 2541 select(data, options.select); 2542 return; 2543 } 2544 2545 // Swipe event 2546 if (evt.type === 'swipe') { 2547 if (config.disableSwipe) return; 2548 if (Webflow.env('editor')) return; 2549 if (options.direction === 'left') return next(data)(); 2550 if (options.direction === 'right') return previousFunction(data)(); 2551 return; 2552 } 2553 2554 // Page buttons 2555 if (data.nav.has(evt.target).length) { 2556 change(data, { index: $(evt.target).index() }); 2557 } 2558 }; 2559 } 2560 2561 function change(data, options) { 2562 options = options || {}; 2563 var config = data.config; 2564 var anchors = data.anchors; 2565 2566 // Set new index 2567 data.previous = data.index; 2568 var index = options.index; 2569 var shift = {}; 2570 if (index < 0) { 2571 index = anchors.length - 1; 2572 if (config.infinite) { 2573 // Shift first slide to the end 2574 shift.x = -data.endX; 2575 shift.from = 0; 2576 shift.to = anchors[0].width; 2577 } 2578 } else if (index >= anchors.length) { 2579 index = 0; 2580 if (config.infinite) { 2581 // Shift last slide to the start 2582 shift.x = anchors[anchors.length - 1].width; 2583 shift.from = -anchors[anchors.length - 1].x; 2584 shift.to = shift.from - shift.x; 2585 } 2586 } 2587 data.index = index; 2588 2589 // Select page nav 2590 var active = data.nav.children().eq(data.index).addClass('w-active'); 2591 data.nav.children().not(active).removeClass('w-active'); 2592 2593 // Hide arrows 2594 if (config.hideArrows) { 2595 data.index === anchors.length - 1 ? data.right.hide() : data.right.show(); 2596 data.index === 0 ? data.left.hide() : data.left.show(); 2597 } 2598 2599 // Get page offset from anchors 2600 var lastOffsetX = data.offsetX || 0; 2601 var offsetX = data.offsetX = -anchors[data.index].x; 2602 var resetConfig = { x: offsetX, opacity: 1, visibility: '' }; 2603 2604 // Transition slides 2605 var targets = $(anchors[data.index].els); 2606 var prevTargs = $(anchors[data.previous] && anchors[data.previous].els); 2607 var others = data.slides.not(targets); 2608 var animation = config.animation; 2609 var easing = config.easing; 2610 var duration = Math.round(config.duration); 2611 var vector = options.vector || (data.index > data.previous ? 1 : -1); 2612 var fadeRule = 'opacity ' + duration + 'ms ' + easing; 2613 var slideRule = 'transform ' + duration + 'ms ' + easing; 2614 2615 // Trigger IX events 2616 if (!designer) { 2617 targets.each(ix.intro); 2618 others.each(ix.outro); 2619 } 2620 2621 // Set immediately after layout changes (but not during redraw) 2622 if (options.immediate && !inRedraw) { 2623 tram(targets).set(resetConfig); 2624 resetOthers(); 2625 return; 2626 } 2627 2628 // Exit early if index is unchanged 2629 if (data.index === data.previous) return; 2630 2631 // Cross Fade / Out-In 2632 if (animation === 'cross') { 2633 var reduced = Math.round(duration - duration * config.crossOver); 2634 var wait = Math.round(duration - reduced);
2635 fadeRule = 'opacity ' + reduced + 'ms ' + easing; 2636 tram(prevTargs) 2637 .set({ visibility: '' }) 2638 .add(fadeRule) 2639 .start({ opacity: 0 }); 2640 tram(targets) 2641 .set({ visibility: '', x: offsetX, opacity: 0, zIndex: data.depth++ }) 2642 .add(fadeRule) 2643 .wait(wait) 2644 .then({ opacity: 1 }) 2645 .then(resetOthers); 2646 return; 2647 } 2648 2649 // Fade Over 2650 if (animation === 'fade') { 2651 tram(prevTargs) 2652 .set({ visibility: '' }) 2653 .stop(); 2654 tram(targets) 2655 .set({ visibility: '', x: offsetX, opacity: 0, zIndex: data.depth++ }) 2656 .add(fadeRule) 2657 .start({ opacity: 1 }) 2658 .then(resetOthers); 2659 return; 2660 } 2661 2662 // Slide Over 2663 if (animation === 'over') { 2664 resetConfig = { x: data.endX }; 2665 tram(prevTargs) 2666 .set({ visibility: '' }) 2667 .stop(); 2668 tram(targets) 2669 .set({ visibility: '', zIndex: data.depth++, x: offsetX + anchors[data.index].width * vector }) 2670 .add(slideRule) 2671 .start({ x: offsetX }) 2672 .then(resetOthers); 2673 return; 2674 } 2675 2676 // Slide - infinite scroll 2677 if (config.infinite && shift.x) { 2678 tram(data.slides.not(prevTargs)) 2679 .set({ visibility: '', x: shift.x }) 2680 .add(slideRule) 2681 .start({ x: offsetX }); 2682 tram(prevTargs) 2683 .set({ visibility: '', x: shift.from }) 2684 .add(slideRule) 2685 .start({ x: shift.to }); 2686 data.shifted = prevTargs; 2687 2688 } else { 2689 if (config.infinite && data.shifted) { 2690 tram(data.shifted).set({ visibility: '', x: lastOffsetX }); 2691 data.shifted = null; 2692 } 2693 2694 // Slide - basic scroll 2695 tram(data.slides) 2696 .set({ visibility: '' }) 2697 .add(slideRule) 2698 .start({ x: offsetX }); 2699 } 2700 2701 // Helper to move others out of view 2702 function resetOthers() { 2703 targets = $(anchors[data.index].els); 2704 others = data.slides.not(targets); 2705 if (animation !== 'slide') resetConfig.visibility = 'hidden'; 2706 tram(others).set(resetConfig); 2707 } 2708 } 2709 2710 function render(i, el) { 2711 var data = $.data(el, namespace); 2712 if (maskChanged(data)) return layout(data); 2713 if (designer && slidesChanged(data)) layout(data); 2714 } 2715 2716 function layout(data) { 2717 // Determine page count from width of slides 2718 var pages = 1; 2719 var offset = 0; 2720 var anchor = 0; 2721 var width = 0; 2722 var maskWidth = data.maskWidth; 2723 var threshold = maskWidth - data.config.edge; 2724 if (threshold < 0) threshold = 0; 2725 data.anchors = [{ els: [], x: 0, width: 0 }]; 2726 data.slides.each(function(i, el) { 2727 if (anchor - offset > threshold) { 2728 pages++; 2729 offset += maskWidth; 2730 // Store page anchor for transition 2731 data.anchors[pages - 1] = { els: [], x: anchor, width: 0 }; 2732 } 2733 // Set next anchor using current width + margin 2734 width = $(el).outerWidth(true); 2735 anchor += width; 2736 data.anchors[pages - 1].width += width; 2737 data.anchors[pages - 1].els.push(el); 2738 }); 2739 data.endX = anchor; 2740 2741 // Build dots if nav exists and needs updating 2742 if (designer) data.pages = null; 2743 if (data.nav.length && data.pages !== pages){ 2744 data.pages = pages; 2745 buildNav(data); 2746 } 2747 2748 // Make sure index is still within range and call change handler 2749 var index = data.index; 2750 if (index >= pages) index = pages - 1; 2751 change(data, { immediate: true, index: index }); 2752 } 2753 2754 function buildNav(data) { 2755 var dots = []; 2756 var $dot; 2757 var spacing = data.el.attr('data-nav-spacing'); 2758 if (spacing) spacing = parseFloat(spacing) + 'px'; 2759 for (var i = 0; i < data.pages; i++) { 2760 $dot = $(dot); 2761 if (data.nav.hasClass('w-num')) $dot.text(i + 1); 2762 if (spacing != null) { 2763 $dot.css({ 2764 'margin-left': spacing, 2765 'margin-right': spacing 2766 }); 2767 } 2768 dots.push($dot); 2769 } 2770 data.nav.empty().append(dots); 2771 } 2772 2773 function maskChanged(data) { 2774 var maskWidth = data.mask.width(); 2775 if (data.maskWidth !== maskWidth) { 2776 data.maskWidth = maskWidth; 2777 return true; 2778 } 2779 return false; 2780 } 2781 2782 function slidesChanged(data) { 2783 var slidesWidth = 0; 2784 data.slides.each(function(i, el) { 2785 slidesWidth += $(el).outerWidth(true); 2786 }); 2787 if (data.slidesWidth !== slidesWidth) { 2788 data.slidesWidth = slidesWidth; 2789 return true; 2790 } 2791 return false; 2792 } 2793 2794 // Export module 2795 return api; 2796 }); 2797 }); 2798 2799 var webflowTouch = __commonjs(function (module) { 2800 /** 2801 * Webflow: Touch events 2802 */ 2803 2804 var Webflow = require$$0; 2805 2806 Webflow.define('touch', module.exports = function($) { 2807 var api = {}; 2808 var fallback = !document.addEventListener; 2809 var getSelection = window.getSelection; 2810 2811 // Fallback to click events in old IE 2812 if (fallback) { 2813 $.event.special.tap = { bindType: 'click', delegateType: 'click' }; 2814 } 2815 2816 api.init = function(el) { 2817 if (fallback) return null; 2818 el = typeof el === 'string' ? $(el).get(0) : el; 2819 return el ? new Touch(el) : null; 2820 }; 2821 2822 function Touch(el) { 2823 var active = false; 2824 var dirty = false; 2825 var useTouch = false; 2826 var thresholdX = Math.min(Math.round(window.innerWidth * 0.04), 40); 2827 var startX; 2828 var startY; 2829 var lastX; 2830 2831 el.addEventListener('touchstart', start, false); 2832 el.addEventListener('touchmove', move, false); 2833 el.addEventListener('touchend', end, false); 2834 el.addEventListener('touchcancel', cancel, false); 2835 el.addEventListener('mousedown', start, false); 2836 el.addEventListener('mousemove', move, false); 2837 el.addEventListener('mouseup', end, false);
2838 el.addEventListener('mouseout', cancel, false); 2839 2840 function start(evt) { 2841 // We donât handle multi-touch events yet. 2842 var touches = evt.touches; 2843 if (touches && touches.length > 1) { 2844 return; 2845 } 2846 2847 active = true; 2848 dirty = false; 2849 2850 if (touches) { 2851 useTouch = true; 2852 startX = touches[0].clientX; 2853 startY = touches[0].clientY; 2854 } else { 2855 startX = evt.clientX; 2856 startY = evt.clientY; 2857 } 2858 2859 lastX = startX; 2860 } 2861 2862 function move(evt) { 2863 if (!active) return; 2864 2865 if (useTouch && evt.type === 'mousemove') { 2866 evt.preventDefault(); 2867 evt.stopPropagation(); 2868 return; 2869 } 2870 2871 var touches = evt.touches; 2872 var x = touches ? touches[0].clientX : evt.clientX; 2873 var y = touches ? touches[0].clientY : evt.clientY; 2874 2875 var velocityX = x - lastX; 2876 lastX = x; 2877 2878 // Allow swipes while pointer is down, but prevent them during text selection 2879 if (Math.abs(velocityX) > thresholdX && getSelection && String(getSelection()) === '') { 2880 triggerEvent('swipe', evt, { direction: velocityX > 0 ? 'right' : 'left' }); 2881 cancel(); 2882 } 2883 2884 // If pointer moves more than 10px flag to cancel tap 2885 if (Math.abs(x - startX) > 10 || Math.abs(y - startY) > 10) { 2886 dirty = true; 2887 } 2888 } 2889 2890 function end(evt) { 2891 if (!active) return; 2892 active = false; 2893 2894 if (useTouch && evt.type === 'mouseup') { 2895 evt.preventDefault(); 2896 evt.stopPropagation(); 2897 useTouch = false; 2898 return; 2899 } 2900 2901 if (!dirty) triggerEvent('tap', evt); 2902 } 2903 2904 function cancel() { 2905 active = false; 2906 } 2907 2908 function destroy() { 2909 el.removeEventListener('touchstart', start, false); 2910 el.removeEventListener('touchmove', move, false); 2911 el.removeEventListener('touchend', end, false); 2912 el.removeEventListener('touchcancel', cancel, false); 2913 el.removeEventListener('mousedown', start, false); 2914 el.removeEventListener('mousemove', move, false); 2915 el.removeEventListener('mouseup', end, false); 2916 el.removeEventListener('mouseout', cancel, false); 2917 el = null; 2918 } 2919 2920 // Public instance methods 2921 this.destroy = destroy; 2922 } 2923 2924 // Wrap native event to supoprt preventdefault + stopPropagation 2925 function triggerEvent(type, evt, data) { 2926 var newEvent = $.Event(type, { originalEvent: evt }); 2927 $(evt.target).trigger(newEvent, data); 2928 } 2929 2930 // Listen for touch events on all nodes by default. 2931 api.instance = api.init(document); 2932 2933 // Export module 2934 return api; 2935 }); 2936 }); 2937 2938}());
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.