2 * Materialize v0.97.1 (http://materializecss.com)
3 * Copyright 2014-2015 Materialize
4 * MIT License (https://raw.githubusercontent.com/Dogfalo/materialize/master/LICENSE)
7 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
9 * Uses the built in easing capabilities added In jQuery 1.1
10 * to offer multiple easing options
12 * TERMS OF USE - jQuery Easing
14 * Open source under the BSD License.
16 * Copyright © 2008 George McGinley Smith
17 * All rights reserved.
19 * Redistribution and use in source and binary forms, with or without modification,
20 * are permitted provided that the following conditions are met:
22 * Redistributions of source code must retain the above copyright notice, this list of
23 * conditions and the following disclaimer.
24 * Redistributions in binary form must reproduce the above copyright notice, this list
25 * of conditions and the following disclaimer in the documentation and/or other materials
26 * provided with the distribution.
28 * Neither the name of the author nor the names of contributors may be used to endorse
29 * or promote products derived from this software without specific prior written permission.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
32 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
33 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
35 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
36 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
37 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
43 // t: current time, b: begInnIng value, c: change In value, d: duration
44 jQuery
.easing
['jswing'] = jQuery
.easing
['swing'];
46 jQuery
.extend( jQuery
.easing
,
49 swing: function (x
, t
, b
, c
, d
) {
50 //alert(jQuery.easing.default);
51 return jQuery
.easing
[jQuery
.easing
.def
](x
, t
, b
, c
, d
);
53 easeInQuad: function (x
, t
, b
, c
, d
) {
54 return c
*(t
/=d
)*t
+ b
;
56 easeOutQuad: function (x
, t
, b
, c
, d
) {
57 return -c
*(t
/=d
)*(t
-2) + b
;
59 easeInOutQuad: function (x
, t
, b
, c
, d
) {
60 if ((t
/=d/2) < 1) return c
/2*t
*t
+ b
;
61 return -c
/2 * ((--t
)*(t
-2) - 1) + b
;
63 easeInCubic: function (x
, t
, b
, c
, d
) {
64 return c
*(t
/=d
)*t
*t
+ b
;
66 easeOutCubic: function (x
, t
, b
, c
, d
) {
67 return c
*((t
=t
/d
-1)*t
*t
+ 1) + b
;
69 easeInOutCubic: function (x
, t
, b
, c
, d
) {
70 if ((t
/=d/2) < 1) return c
/2*t
*t
*t
+ b
;
71 return c
/2*((t
-=2)*t
*t
+ 2) + b
;
73 easeInQuart: function (x
, t
, b
, c
, d
) {
74 return c
*(t
/=d
)*t
*t
*t
+ b
;
76 easeOutQuart: function (x
, t
, b
, c
, d
) {
77 return -c
* ((t
=t
/d
-1)*t
*t
*t
- 1) + b
;
79 easeInOutQuart: function (x
, t
, b
, c
, d
) {
80 if ((t
/=d/2) < 1) return c
/2*t
*t
*t
*t
+ b
;
81 return -c
/2 * ((t
-=2)*t
*t
*t
- 2) + b
;
83 easeInQuint: function (x
, t
, b
, c
, d
) {
84 return c
*(t
/=d
)*t
*t
*t
*t
+ b
;
86 easeOutQuint: function (x
, t
, b
, c
, d
) {
87 return c
*((t
=t
/d
-1)*t
*t
*t
*t
+ 1) + b
;
89 easeInOutQuint: function (x
, t
, b
, c
, d
) {
90 if ((t
/=d/2) < 1) return c
/2*t
*t
*t
*t
*t
+ b
;
91 return c
/2*((t
-=2)*t
*t
*t
*t
+ 2) + b
;
93 easeInSine: function (x
, t
, b
, c
, d
) {
94 return -c
* Math
.cos(t
/d
* (Math
.PI
/2)) + c
+ b
;
96 easeOutSine: function (x
, t
, b
, c
, d
) {
97 return c
* Math
.sin(t
/d
* (Math
.PI
/2)) + b
;
99 easeInOutSine: function (x
, t
, b
, c
, d
) {
100 return -c
/2 * (Math
.cos(Math
.PI
*t
/d
) - 1) + b
;
102 easeInExpo: function (x
, t
, b
, c
, d
) {
103 return (t
==0) ? b : c
* Math
.pow(2, 10 * (t
/d
- 1)) + b
;
105 easeOutExpo: function (x
, t
, b
, c
, d
) {
106 return (t
==d
) ? b
+c : c
* (-Math
.pow(2, -10 * t
/d
) + 1) + b
;
108 easeInOutExpo: function (x
, t
, b
, c
, d
) {
110 if (t
==d
) return b
+c
;
111 if ((t
/=d/2) < 1) return c
/2 * Math
.pow(2, 10 * (t
- 1)) + b
;
112 return c
/2 * (-Math
.pow(2, -10 * --t
) + 2) + b
;
114 easeInCirc: function (x
, t
, b
, c
, d
) {
115 return -c
* (Math
.sqrt(1 - (t
/=d
)*t
) - 1) + b
;
117 easeOutCirc: function (x
, t
, b
, c
, d
) {
118 return c
* Math
.sqrt(1 - (t
=t
/d
-1)*t
) + b
;
120 easeInOutCirc: function (x
, t
, b
, c
, d
) {
121 if ((t
/=d/2) < 1) return -c
/2 * (Math
.sqrt(1 - t
*t
) - 1) + b
;
122 return c
/2 * (Math
.sqrt(1 - (t
-=2)*t
) + 1) + b
;
124 easeInElastic: function (x
, t
, b
, c
, d
) {
125 var s
=1.70158;var p
=0;var a
=c
;
126 if (t
==0) return b
; if ((t
/=d
)==1) return b
+c
; if (!p
) p
=d
*.3;
127 if (a
< Math
.abs(c
)) { a
=c
; var s
=p
/4; }
128 else var s
= p
/(2*Math
.PI
) * Math
.asin (c
/a
);
129 return -(a
*Math
.pow(2,10*(t
-=1)) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)) + b
;
131 easeOutElastic: function (x
, t
, b
, c
, d
) {
132 var s
=1.70158;var p
=0;var a
=c
;
133 if (t
==0) return b
; if ((t
/=d
)==1) return b
+c
; if (!p
) p
=d
*.3;
134 if (a
< Math
.abs(c
)) { a
=c
; var s
=p
/4; }
135 else var s
= p
/(2*Math
.PI
) * Math
.asin (c
/a
);
136 return a
*Math
.pow(2,-10*t
) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
) + c
+ b
;
138 easeInOutElastic: function (x
, t
, b
, c
, d
) {
139 var s
=1.70158;var p
=0;var a
=c
;
140 if (t
==0) return b
; if ((t
/=d/2)==2) return b
+c
; if (!p
) p
=d
*(.3*1.5);
141 if (a
< Math
.abs(c
)) { a
=c
; var s
=p
/4; }
142 else var s
= p
/(2*Math
.PI
) * Math
.asin (c
/a
);
143 if (t
< 1) return -.5*(a
*Math
.pow(2,10*(t
-=1)) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)) + b
;
144 return a
*Math
.pow(2,-10*(t
-=1)) * Math
.sin( (t
*d
-s
)*(2*Math
.PI
)/p
)*.5 + c
+ b
;
146 easeInBack: function (x
, t
, b
, c
, d
, s
) {
147 if (s
== undefined) s
= 1.70158;
148 return c
*(t
/=d
)*t
*((s
+1)*t
- s
) + b
;
150 easeOutBack: function (x
, t
, b
, c
, d
, s
) {
151 if (s
== undefined) s
= 1.70158;
152 return c
*((t
=t
/d
-1)*t
*((s
+1)*t
+ s
) + 1) + b
;
154 easeInOutBack: function (x
, t
, b
, c
, d
, s
) {
155 if (s
== undefined) s
= 1.70158;
156 if ((t
/=d/2) < 1) return c
/2*(t
*t
*(((s
*=(1.525))+1)*t
- s
)) + b
;
157 return c
/2*((t
-=2)*t
*(((s
*=(1.525))+1)*t
+ s
) + 2) + b
;
159 easeInBounce: function (x
, t
, b
, c
, d
) {
160 return c
- jQuery
.easing
.easeOutBounce (x
, d
-t
, 0, c
, d
) + b
;
162 easeOutBounce: function (x
, t
, b
, c
, d
) {
163 if ((t
/=d
) < (1/2.75)) {
164 return c
*(7.5625*t
*t
) + b
;
165 } else if (t
< (2/2.75)) {
166 return c
*(7.5625*(t
-=(1.5/2.75))*t
+ .75) + b
;
167 } else if (t
< (2.5/2.75)) {
168 return c
*(7.5625*(t
-=(2.25/2.75))*t
+ .9375) + b
;
170 return c
*(7.5625*(t
-=(2.625/2.75))*t
+ .984375) + b
;
173 easeInOutBounce: function (x
, t
, b
, c
, d
) {
174 if (t
< d
/2) return jQuery
.easing
.easeInBounce (x
, t
*2, 0, c
, d
) * .5 + b
;
175 return jQuery
.easing
.easeOutBounce (x
, t
*2-d
, 0, c
, d
) * .5 + c
*.5 + b
;
181 * TERMS OF USE - EASING EQUATIONS
183 * Open source under the BSD License.
185 * Copyright © 2001 Robert Penner
186 * All rights reserved.
188 * Redistribution and use in source and binary forms, with or without modification,
189 * are permitted provided that the following conditions are met:
191 * Redistributions of source code must retain the above copyright notice, this list of
192 * conditions and the following disclaimer.
193 * Redistributions in binary form must reproduce the above copyright notice, this list
194 * of conditions and the following disclaimer in the documentation and/or other materials
195 * provided with the distribution.
197 * Neither the name of the author nor the names of contributors may be used to endorse
198 * or promote products derived from this software without specific prior written permission.
200 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
201 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
202 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
203 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
204 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
205 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
206 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
207 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
208 * OF THE POSSIBILITY OF SUCH DAMAGE.
211 jQuery
.extend( jQuery
.easing
,
213 easeInOutMaterial: function (x
, t
, b
, c
, d
) {
214 if ((t
/=d/2) < 1) return c
/2*t
*t
+ b
;
215 return c
/4*((t
-=2)*t
*t
+ 2) + b
;
219 ;/*! VelocityJS.org (1.2.2). (C) 2014 Julian Shapiro. MIT @license: en.wikipedia.org/wiki/MIT_License */
220 /*! VelocityJS.org jQuery Shim (1.0.1). (C) 2014 The jQuery Foundation. MIT @license: en.wikipedia.org/wiki/MIT_License. */
221 !function(e
){function t(e
){var t
=e
.length
,r
=$.type(e
);return"function"===r
||$.isWindow(e
)?!1:1===e
.nodeType
&&t
?!0:"array"===r
||0===t
||"number"==typeof t
&&t
>0&&t
-1 in e
}if(!e
.jQuery
){var $=function(e
,t
){return new $.fn
.init(e
,t
)};$.isWindow=function(e
){return null!=e
&&e
==e
.window
},$.type=function(e
){return null==e
?e
+"":"object"==typeof e
||"function"==typeof e
?a
[o
.call(e
)]||"object":typeof e
},$.isArray
=Array
.isArray
||function(e
){return"array"===$.type(e
)},$.isPlainObject=function(e
){var t
;if(!e
||"object"!==$.type(e
)||e
.nodeType
||$.isWindow(e
))return!1;try{if(e
.constructor&&!n
.call(e
,"constructor")&&!n
.call(e
.constructor.prototype,"isPrototypeOf"))return!1}catch(r
){return!1}for(t
in e
);return void 0===t
||n
.call(e
,t
)},$.each=function(e
,r
,a
){var n
,o
=0,i
=e
.length
,s
=t(e
);if(a
){if(s
)for(;i
>o
&&(n
=r
.apply(e
[o
],a
),n
!==!1);o
++);else for(o
in e
)if(n
=r
.apply(e
[o
],a
),n
===!1)break}else if(s
)for(;i
>o
&&(n
=r
.call(e
[o
],o
,e
[o
]),n
!==!1);o
++);else for(o
in e
)if(n
=r
.call(e
[o
],o
,e
[o
]),n
===!1)break;return e
},$.data=function(e
,t
,a
){if(void 0===a
){var n
=e
[$.expando
],o
=n
&&r
[n
];if(void 0===t
)return o
;if(o
&&t
in o
)return o
[t
]}else if(void 0!==t
){var n
=e
[$.expando
]||(e
[$.expando
]=++$.uuid
);return r
[n
]=r
[n
]||{},r
[n
][t
]=a
,a
}},$.removeData=function(e
,t
){var a
=e
[$.expando
],n
=a
&&r
[a
];n
&&$.each(t
,function(e
,t
){delete n
[t
]})},$.extend=function(){var e
,t
,r
,a
,n
,o
,i
=arguments
[0]||{},s
=1,l
=arguments
.length
,u
=!1;for("boolean"==typeof i
&&(u
=i
,i
=arguments
[s
]||{},s
++),"object"!=typeof i
&&"function"!==$.type(i
)&&(i
={}),s
===l
&&(i
=this,s
--);l
>s
;s
++)if(null!=(n
=arguments
[s
]))for(a
in n
)e
=i
[a
],r
=n
[a
],i
!==r
&&(u
&&r
&&($.isPlainObject(r
)||(t
=$.isArray(r
)))?(t
?(t
=!1,o
=e
&&$.isArray(e
)?e:[]):o
=e
&&$.isPlainObject(e
)?e:{},i
[a
]=$.extend(u
,o
,r
)):void 0!==r
&&(i
[a
]=r
));return i
},$.queue=function(e
,r
,a
){function n(e
,r
){var a
=r
||[];return null!=e
&&(t(Object(e
))?!function(e
,t
){for(var r
=+t
.length
,a
=0,n
=e
.length
;r
>a
;)e
[n
++]=t
[a
++];if(r
!==r
)for(;void 0!==t
[a
];)e
[n
++]=t
[a
++];return e
.length
=n
,e
}(a
,"string"==typeof e
?[e
]:e
):[].push
.call(a
,e
)),a
}if(e
){r
=(r
||"fx")+"queue";var o
=$.data(e
,r
);return a
?(!o
||$.isArray(a
)?o
=$.data(e
,r
,n(a
)):o
.push(a
),o
):o
||[]}},$.dequeue=function(e
,t
){$.each(e
.nodeType
?[e
]:e
,function(e
,r
){t
=t
||"fx";var a
=$.queue(r
,t
),n
=a
.shift();"inprogress"===n
&&(n
=a
.shift()),n
&&("fx"===t
&&a
.unshift("inprogress"),n
.call(r
,function(){$.dequeue(r
,t
)}))})},$.fn
=$.prototype={init:function(e
){if(e
.nodeType
)return this[0]=e
,this;throw new Error("Not a DOM node.")},offset:function(){var t
=this[0].getBoundingClientRect
?this[0].getBoundingClientRect():{top:0,left:0};return{top:t
.top
+(e
.pageYOffset
||document
.scrollTop
||0)-(document
.clientTop
||0),left:t
.left
+(e
.pageXOffset
||document
.scrollLeft
||0)-(document
.clientLeft
||0)}},position:function(){function e(){for(var e
=this.offsetParent
||document
;e
&&"html"===!e
.nodeType
.toLowerCase
&&"static"===e
.style
.position
;)e
=e
.offsetParent
;return e
||document
}var t
=this[0],e
=e
.apply(t
),r
=this.offset(),a
=/^(?:body|html)$/i.test(e
.nodeName
)?{top:0,left:0}:$(e
).offset();return r
.top
-=parseFloat(t
.style
.marginTop
)||0,r
.left
-=parseFloat(t
.style
.marginLeft
)||0,e
.style
&&(a
.top
+=parseFloat(e
.style
.borderTopWidth
)||0,a
.left
+=parseFloat(e
.style
.borderLeftWidth
)||0),{top:r
.top
-a
.top
,left:r
.left
-a
.left
}}};var r
={};$.expando
="velocity"+(new Date
).getTime(),$.uuid
=0;for(var a
={},n
=a
.hasOwnProperty
,o
=a
.toString
,i
="Boolean Number String Function Array Date RegExp Object Error".split(" "),s
=0;s
<i
.length
;s
++)a
["[object "+i
[s
]+"]"]=i
[s
].toLowerCase();$.fn
.init
.prototype=$.fn
,e
.Velocity
={Utilities:$}}}(window
),function(e
){"object"==typeof module
&&"object"==typeof module
.exports
?module
.exports
=e():"function"==typeof define
&&define
.amd
?define(e
):e()}(function(){return function(e
,t
,r
,a
){function n(e
){for(var t
=-1,r
=e
?e
.length:0,a
=[];++t
<r
;){var n
=e
[t
];n
&&a
.push(n
)}return a
}function o(e
){return g
.isWrapped(e
)?e
=[].slice
.call(e
):g
.isNode(e
)&&(e
=[e
]),e
}function i(e
){var t
=$.data(e
,"velocity");return null===t
?a:t
}function s(e
){return function(t
){return Math
.round(t
*e
)*(1/e
)}}function l(e
,r
,a
,n
){function o(e
,t
){return 1-3*t
+3*e
}function i(e
,t
){return 3*t
-6*e
}function s(e
){return 3*e
}function l(e
,t
,r
){return((o(t
,r
)*e
+i(t
,r
))*e
+s(t
))*e
}function u(e
,t
,r
){return 3*o(t
,r
)*e
*e
+2*i(t
,r
)*e
+s(t
)}function c(t
,r
){for(var n
=0;m
>n
;++n
){var o
=u(r
,e
,a
);if(0===o
)return r
;var i
=l(r
,e
,a
)-t
;r
-=i
/o
}return r
}function p(){for(var t
=0;b
>t
;++t
)w
[t
]=l(t
*x
,e
,a
)}function f(t
,r
,n
){var o
,i
,s
=0;do i
=r
+(n
-r
)/2,o
=l(i
,e
,a
)-t
,o
>0?n
=i:r
=i
;while(Math
.abs(o
)>h
&&++s
<v
);return i
}function d(t
){for(var r
=0,n
=1,o
=b
-1;n
!=o
&&w
[n
]<=t
;++n
)r
+=x
;--n
;var i
=(t
-w
[n
])/(w
[n
+1]-w
[n
]),s
=r
+i
*x
,l
=u(s
,e
,a
);return l
>=y
?c(t
,s
):0==l
?s:f(t
,r
,r
+x
)}function g(){V
=!0,(e
!=r
||a
!=n
)&&p()}var m
=4,y
=.001,h
=1e-7,v
=10,b
=11,x
=1/(b
-1),S
="Float32Array"in t
;if(4!==arguments
.length
)return!1;for(var P
=0;4>P
;++P
)if("number"!=typeof arguments
[P
]||isNaN(arguments
[P
])||!isFinite(arguments
[P
]))return!1;e
=Math
.min(e
,1),a
=Math
.min(a
,1),e
=Math
.max(e
,0),a
=Math
.max(a
,0);var w
=S
?new Float32Array(b
):new Array(b
),V
=!1,C=function(t
){return V
||g(),e
===r
&&a
===n
?t:0===t
?0:1===t
?1:l(d(t
),r
,n
)};C
.getControlPoints=function(){return[{x:e
,y:r
},{x:a
,y:n
}]};var T
="generateBezier("+[e
,r
,a
,n
]+")";return C
.toString=function(){return T
},C
}function u(e
,t
){var r
=e
;return g
.isString(e
)?v
.Easings
[e
]||(r
=!1):r
=g
.isArray(e
)&&1===e
.length
?s
.apply(null,e
):g
.isArray(e
)&&2===e
.length
?b
.apply(null,e
.concat([t
])):g
.isArray(e
)&&4===e
.length
?l
.apply(null,e
):!1,r
===!1&&(r
=v
.Easings
[v
.defaults
.easing
]?v
.defaults
.easing:h
),r
}function c(e
){if(e
){var t
=(new Date
).getTime(),r
=v
.State
.calls
.length
;r
>1e4
&&(v
.State
.calls
=n(v
.State
.calls
));for(var o
=0;r
>o
;o
++)if(v
.State
.calls
[o
]){var s
=v
.State
.calls
[o
],l
=s
[0],u
=s
[2],f
=s
[3],d
=!!f
,m
=null;f
||(f
=v
.State
.calls
[o
][3]=t
-16);for(var y
=Math
.min((t
-f
)/u
.duration
,1),h
=0,b
=l
.length
;b
>h
;h
++){var S
=l
[h
],w
=S
.element
;if(i(w
)){var V
=!1;if(u
.display
!==a
&&null!==u
.display
&&"none"!==u
.display
){if("flex"===u
.display
){var C
=["-webkit-box","-moz-box","-ms-flexbox","-webkit-flex"];$.each(C
,function(e
,t
){x
.setPropertyValue(w
,"display",t
)})}x
.setPropertyValue(w
,"display",u
.display
)}u
.visibility
!==a
&&"hidden"!==u
.visibility
&&x
.setPropertyValue(w
,"visibility",u
.visibility
);for(var T
in S
)if("element"!==T
){var k
=S
[T
],A
,F
=g
.isString(k
.easing
)?v
.Easings
[k
.easing
]:k
.easing
;if(1===y
)A
=k
.endValue
;else{var E
=k
.endValue
-k
.startValue
;if(A
=k
.startValue
+E
*F(y
,u
,E
),!d
&&A
===k
.currentValue
)continue}if(k
.currentValue
=A
,"tween"===T
)m
=A
;else{if(x
.Hooks
.registered
[T
]){var j
=x
.Hooks
.getRoot(T
),H
=i(w
).rootPropertyValueCache
[j
];H
&&(k
.rootPropertyValue
=H
)}var N
=x
.setPropertyValue(w
,T
,k
.currentValue
+(0===parseFloat(A
)?"":k
.unitType
),k
.rootPropertyValue
,k
.scrollData
);x
.Hooks
.registered
[T
]&&(i(w
).rootPropertyValueCache
[j
]=x
.Normalizations
.registered
[j
]?x
.Normalizations
.registered
[j
]("extract",null,N
[1]):N
[1]),"transform"===N
[0]&&(V
=!0)}}u
.mobileHA
&&i(w
).transformCache
.translate3d
===a
&&(i(w
).transformCache
.translate3d
="(0px, 0px, 0px)",V
=!0),V
&&x
.flushTransformCache(w
)}}u
.display
!==a
&&"none"!==u
.display
&&(v
.State
.calls
[o
][2].display
=!1),u
.visibility
!==a
&&"hidden"!==u
.visibility
&&(v
.State
.calls
[o
][2].visibility
=!1),u
.progress
&&u
.progress
.call(s
[1],s
[1],y
,Math
.max(0,f
+u
.duration
-t
),f
,m
),1===y
&&p(o
)}}v
.State
.isTicking
&&P(c
)}function p(e
,t
){if(!v
.State
.calls
[e
])return!1;for(var r
=v
.State
.calls
[e
][0],n
=v
.State
.calls
[e
][1],o
=v
.State
.calls
[e
][2],s
=v
.State
.calls
[e
][4],l
=!1,u
=0,c
=r
.length
;c
>u
;u
++){var p
=r
[u
].element
;if(t
||o
.loop
||("none"===o
.display
&&x
.setPropertyValue(p
,"display",o
.display
),"hidden"===o
.visibility
&&x
.setPropertyValue(p
,"visibility",o
.visibility
)),o
.loop
!==!0&&($.queue(p
)[1]===a
||!/\.velocityQueueEntryFlag/i.test($.queue(p
)[1]))&&i(p
)){i(p
).isAnimating
=!1,i(p
).rootPropertyValueCache
={};var f
=!1;$.each(x
.Lists
.transforms3D
,function(e
,t
){var r
=/^scale/.test(t
)?1:0,n
=i(p
).transformCache
[t
];i(p
).transformCache
[t
]!==a
&&new RegExp("^\\("+r
+"[^.]").test(n
)&&(f
=!0,delete i(p
).transformCache
[t
])}),o
.mobileHA
&&(f
=!0,delete i(p
).transformCache
.translate3d
),f
&&x
.flushTransformCache(p
),x
.Values
.removeClass(p
,"velocity-animating")}if(!t
&&o
.complete
&&!o
.loop
&&u
===c
-1)try{o
.complete
.call(n
,n
)}catch(d
){setTimeout(function(){throw d
},1)}s
&&o
.loop
!==!0&&s(n
),i(p
)&&o
.loop
===!0&&!t
&&($.each(i(p
).tweensContainer
,function(e
,t
){/^rotate/.test(e
)&&360===parseFloat(t
.endValue
)&&(t
.endValue
=0,t
.startValue
=360),/^backgroundPosition/.test(e
)&&100===parseFloat(t
.endValue
)&&"%"===t
.unitType
&&(t
.endValue
=0,t
.startValue
=100)}),v(p
,"reverse",{loop:!0,delay:o
.delay
})),o
.queue
!==!1&&$.dequeue(p
,o
.queue
)}v
.State
.calls
[e
]=!1;for(var g
=0,m
=v
.State
.calls
.length
;m
>g
;g
++)if(v
.State
.calls
[g
]!==!1){l
=!0;break}l
===!1&&(v
.State
.isTicking
=!1,delete v
.State
.calls
,v
.State
.calls
=[])}var f=function(){if(r
.documentMode
)return r
.documentMode
;for(var e
=7;e
>4;e
--){var t
=r
.createElement("div");if(t
.innerHTML
="<!--[if IE "+e
+"]><span></span><![endif]-->",t
.getElementsByTagName("span").length
)return t
=null,e
}return a
}(),d=function(){var e
=0;return t
.webkitRequestAnimationFrame
||t
.mozRequestAnimationFrame
||function(t
){var r
=(new Date
).getTime(),a
;return a
=Math
.max(0,16-(r
-e
)),e
=r
+a
,setTimeout(function(){t(r
+a
)},a
)}}(),g
={isString:function(e
){return"string"==typeof e
},isArray:Array
.isArray
||function(e
){return"[object Array]"===Object
.prototype.toString
.call(e
)},isFunction:function(e
){return"[object Function]"===Object
.prototype.toString
.call(e
)},isNode:function(e
){return e
&&e
.nodeType
},isNodeList:function(e
){return"object"==typeof e
&&/^\[object (HTMLCollection
|NodeList
|Object
)\]$/.test(Object
.prototype.toString
.call(e
))&&e
.length
!==a
&&(0===e
.length
||"object"==typeof e
[0]&&e
[0].nodeType
>0)},isWrapped:function(e
){return e
&&(e
.jquery
||t
.Zepto
&&t
.Zepto
.zepto
.isZ(e
))},isSVG:function(e
){return t
.SVGElement
&&e
instanceof t
.SVGElement
},isEmptyObject:function(e
){for(var t
in e
)return!1;return!0}},$,m
=!1;if(e
.fn
&&e
.fn
.jquery
?($=e
,m
=!0):$=t
.Velocity
.Utilities
,8>=f
&&!m
)throw new Error("Velocity: IE8 and below require jQuery to be loaded before Velocity.");if(7>=f
)return void(jQuery
.fn
.velocity
=jQuery
.fn
.animate
);var y
=400,h
="swing",v
={State:{isMobile:/Android
|webOS
|iPhone
|iPad
|iPod
|BlackBerry
|IEMobile
|Opera Mini
/i.test(navigator.userAgent),isAndroid:/Android
/i.test(navigator.userAgent),isGingerbread:/Android
2\.3\.[3-7]/i.test(navigator.userAgent),isChrome:t.chrome,isFirefox:/Firefox
/i
.test(navigator
.userAgent
),prefixElement:r
.createElement("div"),prefixMatches:{},scrollAnchor:null,scrollPropertyLeft:null,scrollPropertyTop:null,isTicking:!1,calls:[]},CSS:{},Utilities:$,Redirects:{},Easings:{},Promise:t
.Promise
,defaults:{queue:"",duration:y
,easing:h
,begin:a
,complete:a
,progress:a
,display:a
,visibility:a
,loop:!1,delay:!1,mobileHA:!0,_cacheValues:!0},init:function(e
){$.data(e
,"velocity",{isSVG:g
.isSVG(e
),isAnimating:!1,computedStyle:null,tweensContainer:null,rootPropertyValueCache:{},transformCache:{}})},hook:null,mock:!1,version:{major:1,minor:2,patch:2},debug:!1};t
.pageYOffset
!==a
?(v
.State
.scrollAnchor
=t
,v
.State
.scrollPropertyLeft
="pageXOffset",v
.State
.scrollPropertyTop
="pageYOffset"):(v
.State
.scrollAnchor
=r
.documentElement
||r
.body
.parentNode
||r
.body
,v
.State
.scrollPropertyLeft
="scrollLeft",v
.State
.scrollPropertyTop
="scrollTop");var b=function(){function e(e
){return-e
.tension
*e
.x
-e
.friction
*e
.v
}function t(t
,r
,a
){var n
={x:t
.x
+a
.dx
*r
,v:t
.v
+a
.dv
*r
,tension:t
.tension
,friction:t
.friction
};return{dx:n
.v
,dv:e(n
)}}function r(r
,a
){var n
={dx:r
.v
,dv:e(r
)},o
=t(r
,.5*a
,n
),i
=t(r
,.5*a
,o
),s
=t(r
,a
,i
),l
=1/6*(n.dx+2*(o.dx+i.dx)+s.dx),u=1/6*(n
.dv
+2*(o
.dv
+i
.dv
)+s
.dv
);return r
.x
=r
.x
+l
*a
,r
.v
=r
.v
+u
*a
,r
}return function a(e
,t
,n
){var o
={x:-1,v:0,tension:null,friction:null},i
=[0],s
=0,l
=1e-4,u
=.016,c
,p
,f
;for(e
=parseFloat(e
)||500,t
=parseFloat(t
)||20,n
=n
||null,o
.tension
=e
,o
.friction
=t
,c
=null!==n
,c
?(s
=a(e
,t
),p
=s
/n
*u
):p
=u
;;)if(f
=r(f
||o
,p
),i
.push(1+f
.x
),s
+=16,!(Math
.abs(f
.x
)>l
&&Math
.abs(f
.v
)>l
))break;return c
?function(e
){return i
[e
*(i
.length
-1)|0]}:s
}}();v
.Easings
={linear:function(e
){return e
},swing:function(e
){return.5-Math
.cos(e
*Math
.PI
)/2},spring:function(e
){return 1-Math
.cos(4.5*e
*Math
.PI
)*Math
.exp(6*-e
)}},$.each([["ease",[.25,.1,.25,1]],["ease-in",[.42,0,1,1]],["ease-out",[0,0,.58,1]],["ease-in-out",[.42,0,.58,1]],["easeInSine",[.47,0,.745,.715]],["easeOutSine",[.39,.575,.565,1]],["easeInOutSine",[.445,.05,.55,.95]],["easeInQuad",[.55,.085,.68,.53]],["easeOutQuad",[.25,.46,.45,.94]],["easeInOutQuad",[.455,.03,.515,.955]],["easeInCubic",[.55,.055,.675,.19]],["easeOutCubic",[.215,.61,.355,1]],["easeInOutCubic",[.645,.045,.355,1]],["easeInQuart",[.895,.03,.685,.22]],["easeOutQuart",[.165,.84,.44,1]],["easeInOutQuart",[.77,0,.175,1]],["easeInQuint",[.755,.05,.855,.06]],["easeOutQuint",[.23,1,.32,1]],["easeInOutQuint",[.86,0,.07,1]],["easeInExpo",[.95,.05,.795,.035]],["easeOutExpo",[.19,1,.22,1]],["easeInOutExpo",[1,0,0,1]],["easeInCirc",[.6,.04,.98,.335]],["easeOutCirc",[.075,.82,.165,1]],["easeInOutCirc",[.785,.135,.15,.86]]],function(e
,t
){v
.Easings
[t
[0]]=l
.apply(null,t
[1])});var x
=v
.CSS
={RegEx:{isHex:/^#([A-f\d]{3}){1,2}$/i,valueUnwrap:/^[A-z]+\((.*)\)$/i,wrappedValueAlreadyExtracted:/[0-9.]+ [0-9.]+ [0-9.]+( [0-9.]+)?/,valueSplit:/([A
-z
]+\(.+\))|(([A
-z0
-9#-.]+?)(?=\s
|$))/gi
},Lists:{colors:["fill","stroke","stopColor","color","backgroundColor","borderColor","borderTopColor","borderRightColor","borderBottomColor","borderLeftColor","outlineColor"],transformsBase:["translateX","translateY","scale","scaleX","scaleY","skewX","skewY","rotateZ"],transforms3D:["transformPerspective","translateZ","scaleZ","rotateX","rotateY"]},Hooks:{templates:{textShadow:["Color X Y Blur","black 0px 0px 0px"],boxShadow:["Color X Y Blur Spread","black 0px 0px 0px 0px"],clip:["Top Right Bottom Left","0px 0px 0px 0px"],backgroundPosition:["X Y","0% 0%"],transformOrigin:["X Y Z","50% 50% 0px"],perspectiveOrigin:["X Y","50% 50%"]},registered:{},register:function(){for(var e
=0;e
<x
.Lists
.colors
.length
;e
++){var t
="color"===x
.Lists
.colors
[e
]?"0 0 0 1":"255 255 255 1";x
.Hooks
.templates
[x
.Lists
.colors
[e
]]=["Red Green Blue Alpha",t
]}var r
,a
,n
;if(f
)for(r
in x
.Hooks
.templates
){a
=x
.Hooks
.templates
[r
],n
=a
[0].split(" ");var o
=a
[1].match(x
.RegEx
.valueSplit
);"Color"===n
[0]&&(n
.push(n
.shift()),o
.push(o
.shift()),x
.Hooks
.templates
[r
]=[n
.join(" "),o
.join(" ")])}for(r
in x
.Hooks
.templates
){a
=x
.Hooks
.templates
[r
],n
=a
[0].split(" ");for(var e
in n
){var i
=r
+n
[e
],s
=e
;x
.Hooks
.registered
[i
]=[r
,s
]}}},getRoot:function(e
){var t
=x
.Hooks
.registered
[e
];return t
?t
[0]:e
},cleanRootPropertyValue:function(e
,t
){return x
.RegEx
.valueUnwrap
.test(t
)&&(t
=t
.match(x
.RegEx
.valueUnwrap
)[1]),x
.Values
.isCSSNullValue(t
)&&(t
=x
.Hooks
.templates
[e
][1]),t
},extractValue:function(e
,t
){var r
=x
.Hooks
.registered
[e
];if(r
){var a
=r
[0],n
=r
[1];return t
=x
.Hooks
.cleanRootPropertyValue(a
,t
),t
.toString().match(x
.RegEx
.valueSplit
)[n
]}return t
},injectValue:function(e
,t
,r
){var a
=x
.Hooks
.registered
[e
];if(a
){var n
=a
[0],o
=a
[1],i
,s
;return r
=x
.Hooks
.cleanRootPropertyValue(n
,r
),i
=r
.toString().match(x
.RegEx
.valueSplit
),i
[o
]=t
,s
=i
.join(" ")}return r
}},Normalizations:{registered:{clip:function(e
,t
,r
){switch(e
){case"name":return"clip";case"extract":var a
;return x
.RegEx
.wrappedValueAlreadyExtracted
.test(r
)?a
=r:(a
=r
.toString().match(x
.RegEx
.valueUnwrap
),a
=a
?a
[1].replace(/,(\s+)?/g," "):r
),a
;case"inject":return"rect("+r
+")"}},blur:function(e
,t
,r
){switch(e
){case"name":return v
.State
.isFirefox
?"filter":"-webkit-filter";case"extract":var a
=parseFloat(r
);if(!a
&&0!==a
){var n
=r
.toString().match(/blur\(([0-9]+[A-z]+)\)/i);a
=n
?n
[1]:0}return a
;case"inject":return parseFloat(r
)?"blur("+r
+")":"none"}},opacity:function(e
,t
,r
){if(8>=f
)switch(e
){case"name":return"filter";case"extract":var a
=r
.toString().match(/alpha\(opacity=(.*)\)/i);return r
=a
?a
[1]/100:1;case"inject":return t
.style
.zoom
=1,parseFloat(r
)>=1?"":"alpha(opacity="+parseInt(100*parseFloat(r
),10)+")"}else switch(e
){case"name":return"opacity";case"extract":return r
;case"inject":return r
}}},register:function(){9>=f
||v
.State
.isGingerbread
||(x
.Lists
.transformsBase
=x
.Lists
.transformsBase
.concat(x
.Lists
.transforms3D
));for(var e
=0;e
<x
.Lists
.transformsBase
.length
;e
++)!function(){var t
=x
.Lists
.transformsBase
[e
];x
.Normalizations
.registered
[t
]=function(e
,r
,n
){switch(e
){case"name":return"transform";case"extract":return i(r
)===a
||i(r
).transformCache
[t
]===a
?/^scale/i.test(t
)?1:0:i(r
).transformCache
[t
].replace(/[()]/g,"");case"inject":var o
=!1;switch(t
.substr(0,t
.length
-1)){case"translate":o
=!/(%|px|em|rem|vw|vh|\d)$/i.test(n
);break;case"scal":case"scale":v
.State
.isAndroid
&&i(r
).transformCache
[t
]===a
&&1>n
&&(n
=1),o
=!/(\d)$/i.test(n
);break;case"skew":o
=!/(deg|\d)$/i.test(n
);break;case"rotate":o
=!/(deg|\d)$/i.test(n
)}return o
||(i(r
).transformCache
[t
]="("+n
+")"),i(r
).transformCache
[t
]}}}();for(var e
=0;e
<x
.Lists
.colors
.length
;e
++)!function(){var t
=x
.Lists
.colors
[e
];x
.Normalizations
.registered
[t
]=function(e
,r
,n
){switch(e
){case"name":return t
;case"extract":var o
;if(x
.RegEx
.wrappedValueAlreadyExtracted
.test(n
))o
=n
;else{var i
,s
={black:"rgb(0, 0, 0)",blue:"rgb(0, 0, 255)",gray:"rgb(128, 128, 128)",green:"rgb(0, 128, 0)",red:"rgb(255, 0, 0)",white:"rgb(255, 255, 255)"};/^[A-z]+$/i.test(n
)?i
=s
[n
]!==a
?s
[n
]:s
.black:x
.RegEx
.isHex
.test(n
)?i
="rgb("+x
.Values
.hexToRgb(n
).join(" ")+")":/^rgba?\(/i.test(n
)||(i
=s
.black
),o
=(i
||n
).toString().match(x
.RegEx
.valueUnwrap
)[1].replace(/,(\s+)?/g," ")}return 8>=f
||3!==o
.split(" ").length
||(o
+=" 1"),o
;case"inject":return 8>=f
?4===n
.split(" ").length
&&(n
=n
.split(/\s+/).slice(0,3).join(" ")):3===n
.split(" ").length
&&(n
+=" 1"),(8>=f
?"rgb":"rgba")+"("+n
.replace(/\s+/g,",").replace(/\.(\d)+(?=,)/g,"")+")"}}}()}},Names:{camelCase:function(e
){return e
.replace(/-(\w)/g,function(e
,t
){return t
.toUpperCase()})},SVGAttribute:function(e
){var t
="width|height|x|y|cx|cy|r|rx|ry|x1|x2|y1|y2";return(f
||v
.State
.isAndroid
&&!v
.State
.isChrome
)&&(t
+="|transform"),new RegExp("^("+t
+")$","i").test(e
)},prefixCheck:function(e
){if(v
.State
.prefixMatches
[e
])return[v
.State
.prefixMatches
[e
],!0];for(var t
=["","Webkit","Moz","ms","O"],r
=0,a
=t
.length
;a
>r
;r
++){var n
;if(n
=0===r
?e:t
[r
]+e
.replace(/^\w/,function(e
){return e
.toUpperCase()}),g
.isString(v
.State
.prefixElement
.style
[n
]))return v
.State
.prefixMatches
[e
]=n
,[n
,!0]}return[e
,!1]}},Values:{hexToRgb:function(e
){var t
=/^#?([a-f\d])([a-f\d])([a-f\d])$/i,r
=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i,a
;return e
=e
.replace(t
,function(e
,t
,r
,a
){return t
+t
+r
+r
+a
+a
}),a
=r
.exec(e
),a
?[parseInt(a
[1],16),parseInt(a
[2],16),parseInt(a
[3],16)]:[0,0,0]},isCSSNullValue:function(e
){return 0==e
||/^(none
|auto
|transparent
|(rgba
\(0, ?0, ?0, ?0\)))$/i.test(e)},getUnitType:function(e){return/^(rotate
|skew
)/i.test(e)?"deg":/(^(scale
|scaleX
|scaleY
|scaleZ
|alpha
|flexGrow
|flexHeight
|zIndex
|fontWeight
)$)|((opacity
|red
|green
|blue
|alpha
)$)/i
.test(e
)?"":"px"},getDisplayType:function(e
){var t
=e
&&e
.tagName
.toString().toLowerCase();return/^(b|big|i|small|tt|abbr|acronym|cite|code|dfn|em|kbd|strong|samp|var|a|bdo|br|img|map|object|q|script|span|sub|sup|button|input|label|select|textarea)$/i.test(t
)?"inline":/^(li)$/i.test(t
)?"list-item":/^(tr)$/i.test(t
)?"table-row":/^(table)$/i.test(t
)?"table":/^(tbody)$/i.test(t
)?"table-row-group":"block"},addClass:function(e
,t
){e
.classList
?e
.classList
.add(t
):e
.className
+=(e
.className
.length
?" ":"")+t
},removeClass:function(e
,t
){e
.classList
?e
.classList
.remove(t
):e
.className
=e
.className
.toString().replace(new RegExp("(^|\\s)"+t
.split(" ").join("|")+"(\\s|$)","gi")," ")}},getPropertyValue:function(e
,r
,n
,o
){function s(e
,r
){function n(){u
&&x
.setPropertyValue(e
,"display","none")}var l
=0;if(8>=f
)l
=$.css(e
,r
);else{var u
=!1;if(/^(width|height)$/.test(r
)&&0===x
.getPropertyValue(e
,"display")&&(u
=!0,x
.setPropertyValue(e
,"display",x
.Values
.getDisplayType(e
))),!o
){if("height"===r
&&"border-box"!==x
.getPropertyValue(e
,"boxSizing").toString().toLowerCase()){var c
=e
.offsetHeight
-(parseFloat(x
.getPropertyValue(e
,"borderTopWidth"))||0)-(parseFloat(x
.getPropertyValue(e
,"borderBottomWidth"))||0)-(parseFloat(x
.getPropertyValue(e
,"paddingTop"))||0)-(parseFloat(x
.getPropertyValue(e
,"paddingBottom"))||0);return n(),c
}if("width"===r
&&"border-box"!==x
.getPropertyValue(e
,"boxSizing").toString().toLowerCase()){var p
=e
.offsetWidth
-(parseFloat(x
.getPropertyValue(e
,"borderLeftWidth"))||0)-(parseFloat(x
.getPropertyValue(e
,"borderRightWidth"))||0)-(parseFloat(x
.getPropertyValue(e
,"paddingLeft"))||0)-(parseFloat(x
.getPropertyValue(e
,"paddingRight"))||0);return n(),p
}}var d
;d
=i(e
)===a
?t
.getComputedStyle(e
,null):i(e
).computedStyle
?i(e
).computedStyle:i(e
).computedStyle
=t
.getComputedStyle(e
,null),"borderColor"===r
&&(r
="borderTopColor"),l
=9===f
&&"filter"===r
?d
.getPropertyValue(r
):d
[r
],(""===l
||null===l
)&&(l
=e
.style
[r
]),n()}if("auto"===l
&&/^(top|right|bottom|left)$/i.test(r
)){var g
=s(e
,"position");("fixed"===g
||"absolute"===g
&&/top|left/i.test(r
))&&(l
=$(e
).position()[r
]+"px")}return l
}var l
;if(x
.Hooks
.registered
[r
]){var u
=r
,c
=x
.Hooks
.getRoot(u
);n
===a
&&(n
=x
.getPropertyValue(e
,x
.Names
.prefixCheck(c
)[0])),x
.Normalizations
.registered
[c
]&&(n
=x
.Normalizations
.registered
[c
]("extract",e
,n
)),l
=x
.Hooks
.extractValue(u
,n
)}else if(x
.Normalizations
.registered
[r
]){var p
,d
;p
=x
.Normalizations
.registered
[r
]("name",e
),"transform"!==p
&&(d
=s(e
,x
.Names
.prefixCheck(p
)[0]),x
.Values
.isCSSNullValue(d
)&&x
.Hooks
.templates
[r
]&&(d
=x
.Hooks
.templates
[r
][1])),l
=x
.Normalizations
.registered
[r
]("extract",e
,d
)}if(!/^[\d-]/.test(l
))if(i(e
)&&i(e
).isSVG
&&x
.Names
.SVGAttribute(r
))if(/^(height|width)$/i.test(r
))try{l
=e
.getBBox()[r
]}catch(g
){l
=0}else l
=e
.getAttribute(r
);else l
=s(e
,x
.Names
.prefixCheck(r
)[0]);return x
.Values
.isCSSNullValue(l
)&&(l
=0),v
.debug
>=2&&console
.log("Get "+r
+": "+l
),l
},setPropertyValue:function(e
,r
,a
,n
,o
){var s
=r
;if("scroll"===r
)o
.container
?o
.container
["scroll"+o
.direction
]=a:"Left"===o
.direction
?t
.scrollTo(a
,o
.alternateValue
):t
.scrollTo(o
.alternateValue
,a
);else if(x
.Normalizations
.registered
[r
]&&"transform"===x
.Normalizations
.registered
[r
]("name",e
))x
.Normalizations
.registered
[r
]("inject",e
,a
),s
="transform",a
=i(e
).transformCache
[r
];else{if(x
.Hooks
.registered
[r
]){var l
=r
,u
=x
.Hooks
.getRoot(r
);n
=n
||x
.getPropertyValue(e
,u
),a
=x
.Hooks
.injectValue(l
,a
,n
),r
=u
}if(x
.Normalizations
.registered
[r
]&&(a
=x
.Normalizations
.registered
[r
]("inject",e
,a
),r
=x
.Normalizations
.registered
[r
]("name",e
)),s
=x
.Names
.prefixCheck(r
)[0],8>=f
)try{e
.style
[s
]=a
}catch(c
){v
.debug
&&console
.log("Browser does not support ["+a
+"] for ["+s
+"]")}else i(e
)&&i(e
).isSVG
&&x
.Names
.SVGAttribute(r
)?e
.setAttribute(r
,a
):e
.style
[s
]=a
;v
.debug
>=2&&console
.log("Set "+r
+" ("+s
+"): "+a
)}return[s
,a
]},flushTransformCache:function(e
){function t(t
){return parseFloat(x
.getPropertyValue(e
,t
))}var r
="";if((f
||v
.State
.isAndroid
&&!v
.State
.isChrome
)&&i(e
).isSVG
){var a
={translate:[t("translateX"),t("translateY")],skewX:[t("skewX")],skewY:[t("skewY")],scale:1!==t("scale")?[t("scale"),t("scale")]:[t("scaleX"),t("scaleY")],rotate:[t("rotateZ"),0,0]};$.each(i(e
).transformCache
,function(e
){/^translate/i.test(e
)?e
="translate":/^scale/i.test(e
)?e
="scale":/^rotate/i.test(e
)&&(e
="rotate"),a
[e
]&&(r
+=e
+"("+a
[e
].join(" ")+") ",delete a
[e
])})}else{var n
,o
;$.each(i(e
).transformCache
,function(t
){return n
=i(e
).transformCache
[t
],"transformPerspective"===t
?(o
=n
,!0):(9===f
&&"rotateZ"===t
&&(t
="rotate"),void(r
+=t
+n
+" "))}),o
&&(r
="perspective"+o
+" "+r
)}x
.setPropertyValue(e
,"transform",r
)}};x
.Hooks
.register(),x
.Normalizations
.register(),v
.hook=function(e
,t
,r
){var n
=a
;return e
=o(e
),$.each(e
,function(e
,o
){if(i(o
)===a
&&v
.init(o
),r
===a
)n
===a
&&(n
=v
.CSS
.getPropertyValue(o
,t
));else{var s
=v
.CSS
.setPropertyValue(o
,t
,r
);"transform"===s
[0]&&v
.CSS
.flushTransformCache(o
),n
=s
}}),n
};var S=function(){function e(){return l
?T
.promise
||null:f
}function n(){function e(e
){function p(e
,t
){var r
=a
,i
=a
,s
=a
;return g
.isArray(e
)?(r
=e
[0],!g
.isArray(e
[1])&&/^[\d-]/.test(e
[1])||g
.isFunction(e
[1])||x
.RegEx
.isHex
.test(e
[1])?s
=e
[1]:(g
.isString(e
[1])&&!x
.RegEx
.isHex
.test(e
[1])||g
.isArray(e
[1]))&&(i
=t
?e
[1]:u(e
[1],o
.duration
),e
[2]!==a
&&(s
=e
[2]))):r
=e
,t
||(i
=i
||o
.easing
),g
.isFunction(r
)&&(r
=r
.call(n
,w
,P
)),g
.isFunction(s
)&&(s
=s
.call(n
,w
,P
)),[r
||0,i
,s
]}function f(e
,t
){var r
,a
;return a
=(t
||"0").toString().toLowerCase().replace(/[%A-z]+$/,function(e
){return r
=e
,""}),r
||(r
=x
.Values
.getUnitType(e
)),[a
,r
]}function d(){var e
={myParent:n
.parentNode
||r
.body
,position:x
.getPropertyValue(n
,"position"),fontSize:x
.getPropertyValue(n
,"fontSize")},a
=e
.position
===N
.lastPosition
&&e
.myParent
===N
.lastParent
,o
=e
.fontSize
===N
.lastFontSize
;N
.lastParent
=e
.myParent
,N
.lastPosition
=e
.position
,N
.lastFontSize
=e
.fontSize
;var s
=100,l
={};if(o
&&a
)l
.emToPx
=N
.lastEmToPx
,l
.percentToPxWidth
=N
.lastPercentToPxWidth
,l
.percentToPxHeight
=N
.lastPercentToPxHeight
;else{var u
=i(n
).isSVG
?r
.createElementNS("http://www.w3.org/2000/svg","rect"):r
.createElement("div");v
.init(u
),e
.myParent
.appendChild(u
),$.each(["overflow","overflowX","overflowY"],function(e
,t
){v
.CSS
.setPropertyValue(u
,t
,"hidden")}),v
.CSS
.setPropertyValue(u
,"position",e
.position
),v
.CSS
.setPropertyValue(u
,"fontSize",e
.fontSize
),v
.CSS
.setPropertyValue(u
,"boxSizing","content-box"),$.each(["minWidth","maxWidth","width","minHeight","maxHeight","height"],function(e
,t
){v
.CSS
.setPropertyValue(u
,t
,s
+"%")}),v
.CSS
.setPropertyValue(u
,"paddingLeft",s
+"em"),l
.percentToPxWidth
=N
.lastPercentToPxWidth
=(parseFloat(x
.getPropertyValue(u
,"width",null,!0))||1)/s
,l
.percentToPxHeight
=N
.lastPercentToPxHeight
=(parseFloat(x
.getPropertyValue(u
,"height",null,!0))||1)/s,l.emToPx=N.lastEmToPx=(parseFloat(x.getPropertyValue(u,"paddingLeft"))||1)/s,e
.myParent
.removeChild(u
)}return null===N
.remToPx
&&(N
.remToPx
=parseFloat(x
.getPropertyValue(r
.body
,"fontSize"))||16),null===N
.vwToPx
&&(N
.vwToPx
=parseFloat(t
.innerWidth
)/100,N.vhToPx=parseFloat(t.innerHeight)/100),l
.remToPx
=N
.remToPx
,l
.vwToPx
=N
.vwToPx
,l
.vhToPx
=N
.vhToPx
,v
.debug
>=1&&console
.log("Unit ratios: "+JSON
.stringify(l
),n
),l
}if(o
.begin
&&0===w
)try{o
.begin
.call(m
,m
)}catch(y
){setTimeout(function(){throw y
},1)}if("scroll"===k
){var S
=/^x$/i.test(o
.axis
)?"Left":"Top",V
=parseFloat(o
.offset
)||0,C
,A
,F
;o
.container
?g
.isWrapped(o
.container
)||g
.isNode(o
.container
)?(o
.container
=o
.container
[0]||o
.container
,C
=o
.container
["scroll"+S
],F
=C
+$(n
).position()[S
.toLowerCase()]+V
):o
.container
=null:(C
=v
.State
.scrollAnchor
[v
.State
["scrollProperty"+S
]],A
=v
.State
.scrollAnchor
[v
.State
["scrollProperty"+("Left"===S
?"Top":"Left")]],F
=$(n
).offset()[S
.toLowerCase()]+V
),s
={scroll:{rootPropertyValue:!1,startValue:C
,currentValue:C
,endValue:F
,unitType:"",easing:o
.easing
,scrollData:{container:o
.container
,direction:S
,alternateValue:A
}},element:n
},v
.debug
&&console
.log("tweensContainer (scroll): ",s
.scroll
,n
)}else if("reverse"===k
){if(!i(n
).tweensContainer
)return void $.dequeue(n
,o
.queue
);"none"===i(n
).opts
.display
&&(i(n
).opts
.display
="auto"),"hidden"===i(n
).opts
.visibility
&&(i(n
).opts
.visibility
="visible"),i(n
).opts
.loop
=!1,i(n
).opts
.begin
=null,i(n
).opts
.complete
=null,b
.easing
||delete o
.easing
,b
.duration
||delete o
.duration
,o
=$.extend({},i(n
).opts
,o
);var E
=$.extend(!0,{},i(n
).tweensContainer
);for(var j
in E
)if("element"!==j
){var H
=E
[j
].startValue
;E
[j
].startValue
=E
[j
].currentValue
=E
[j
].endValue
,E
[j
].endValue
=H
,g
.isEmptyObject(b
)||(E
[j
].easing
=o
.easing
),v
.debug
&&console
.log("reverse tweensContainer ("+j
+"): "+JSON
.stringify(E
[j
]),n
)}s
=E
}else if("start"===k
){var E
;i(n
).tweensContainer
&&i(n
).isAnimating
===!0&&(E
=i(n
).tweensContainer
),$.each(h
,function(e
,t
){if(RegExp("^"+x
.Lists
.colors
.join("$|^")+"$").test(e
)){var r
=p(t
,!0),n
=r
[0],o
=r
[1],i
=r
[2];if(x
.RegEx
.isHex
.test(n
)){for(var s
=["Red","Green","Blue"],l
=x
.Values
.hexToRgb(n
),u
=i
?x
.Values
.hexToRgb(i
):a
,c
=0;c
<s
.length
;c
++){var f
=[l
[c
]];o
&&f
.push(o
),u
!==a
&&f
.push(u
[c
]),h
[e
+s
[c
]]=f
}delete h
[e
]}}});for(var R
in h
){var O
=p(h
[R
]),z
=O
[0],q
=O
[1],M
=O
[2];R
=x
.Names
.camelCase(R
);var I
=x
.Hooks
.getRoot(R
),B
=!1;if(i(n
).isSVG
||"tween"===I
||x
.Names
.prefixCheck(I
)[1]!==!1||x
.Normalizations
.registered
[I
]!==a
){(o
.display
!==a
&&null!==o
.display
&&"none"!==o
.display
||o
.visibility
!==a
&&"hidden"!==o
.visibility
)&&/opacity|filter/.test(R
)&&!M
&&0!==z
&&(M
=0),o
._cacheValues
&&E
&&E
[R
]?(M
===a
&&(M
=E
[R
].endValue
+E
[R
].unitType
),B
=i(n
).rootPropertyValueCache
[I
]):x
.Hooks
.registered
[R
]?M
===a
?(B
=x
.getPropertyValue(n
,I
),M
=x
.getPropertyValue(n
,R
,B
)):B
=x
.Hooks
.templates
[I
][1]:M
===a
&&(M
=x
.getPropertyValue(n
,R
));var W
,G
,D
,X
=!1;if(W
=f(R
,M
),M
=W
[0],D
=W
[1],W
=f(R
,z
),z
=W
[0].replace(/^([+-\/*])=/,function(e
,t
){return X
=t
,""}),G
=W
[1],M
=parseFloat(M
)||0,z
=parseFloat(z
)||0,"%"===G
&&(/^(fontSize|lineHeight)$/.test(R
)?(z
/=100,G="em"):/^scale
/.test(R)?(z/=100,G
=""):/(Red|Green|Blue)$/i.test(R
)&&(z
=z
/100*255,G="")),/[\/*]/.test(X))G=D;else if(D!==G&&0!==M)if(0===z)G=D;else{l=l||d();var Y=/margin|padding|left|right|width|text|word|letter/i.test(R)||/X$/.test(R)||"x"===R?"x":"y";switch(D){case"%":M*="x"===Y?l.percentToPxWidth:l.percentToPxHeight;break;case"px":break;default:M*=l[D+"ToPx"]}switch(G){case"%":M*=1/("x"===Y?l.percentToPxWidth:l.percentToPxHeight);break;case"px":break;default:M*=1/l[G+"ToPx"]}}switch(X){case"+":z=M+z;break;case"-":z=M-z;break;case"*":z=M*z;break;case"/":z=M/z}s[R]={rootPropertyValue:B,startValue:M,currentValue:M,endValue:z,unitType:G,easing:q},v.debug&&console.log("tweensContainer ("+R+"): "+JSON.stringify(s[R]),n)}else v.debug&&console.log("Skipping ["+I+"] due to a lack of browser support.")}s.element=n}s.element&&(x.Values.addClass(n,"velocity-animating"),L.push(s),""===o.queue&&(i(n).tweensContainer=s,i(n).opts=o),i(n).isAnimating=!0,w===P-1?(v.State.calls.push([L,m,o,null,T.resolver]),v.State.isTicking===!1&&(v.State.isTicking=!0,c())):w++)}var n=this,o=$.extend({},v.defaults,b),s={},l;switch(i(n)===a&&v.init(n),parseFloat(o.delay)&&o.queue!==!1&&$.queue(n,o.queue,function(e){v.velocityQueueEntryFlag=!0,i(n).delayTimer={setTimeout:setTimeout(e,parseFloat(o.delay)),next:e}}),o.duration.toString().toLowerCase()){case"fast":o.duration=200;break;case"normal":o.duration=y;break;case"slow":o.duration=600;break;default:o.duration=parseFloat(o.duration)||1}v.mock!==!1&&(v.mock===!0?o.duration=o.delay=1:(o.duration*=parseFloat(v.mock)||1,o.delay*=parseFloat(v.mock)||1)),o.easing=u(o.easing,o.duration),o.begin&&!g.isFunction(o.begin)&&(o.begin=null),o.progress&&!g.isFunction(o.progress)&&(o.progress=null),o.complete&&!g.isFunction(o.complete)&&(o.complete=null),o.display!==a&&null!==o.display&&(o.display=o.display.toString().toLowerCase(),"auto"===o.display&&(o.display=v.CSS.Values.getDisplayType(n))),o.visibility!==a&&null!==o.visibility&&(o.visibility=o.visibility.toString().toLowerCase()),o.mobileHA=o.mobileHA&&v.State.isMobile&&!v.State.isGingerbread,o.queue===!1?o.delay?setTimeout(e,o.delay):e():$.queue(n,o.queue,function(t,r){return r===!0?(T.promise&&T.resolver(m),!0):(v.velocityQueueEntryFlag=!0,void e(t))}),""!==o.queue&&"fx"!==o.queue||"inprogress"===$.queue(n)[0]||$.dequeue(n)}var s=arguments[0]&&(arguments[0].p||$.isPlainObject(arguments[0].properties)&&!arguments[0].properties.names||g.isString(arguments[0].properties)),l,f,d,m,h,b;if(g.isWrapped(this)?(l=!1,d=0,m=this,f=this):(l=!0,d=1,m=s?arguments[0].elements||arguments[0].e:arguments[0]),m=o(m)){s?(h=arguments[0].properties||arguments[0].p,b=arguments[0].options||arguments[0].o):(h=arguments[d],b=arguments[d+1]);var P=m.length,w=0;if(!/^(stop|finish)$/i.test(h)&&!$.isPlainObject(b)){var V=d+1;b={};for(var C=V;C<arguments.length;C++)g.isArray(arguments[C])||!/^(fast|normal|slow)$/i.test(arguments[C])&&!/^\d/.test(arguments[C])?g.isString(arguments[C])||g.isArray(arguments[C])?b.easing=arguments[C]:g.isFunction(arguments[C])&&(b.complete=arguments[C]):b.duration=arguments[C]}var T={promise:null,resolver:null,rejecter:null};l&&v.Promise&&(T.promise=new v.Promise(function(e,t){T.resolver=e,T.rejecter=t}));var k;switch(h){case"scroll":k="scroll";break;case"reverse":k="reverse";break;case"finish":case"stop":$.each(m,function(e,t){i(t)&&i(t).delayTimer&&(clearTimeout(i(t).delayTimer.setTimeout),i(t).delayTimer.next&&i(t).delayTimer.next(),delete i(t).delayTimer)});var A=[];return $.each(v.State.calls,function(e,t){t&&$.each(t[1],function(r,n){var o=b===a?"":b;return o===!0||t[2].queue===o||b===a&&t[2].queue===!1?void $.each(m,function(r,a){a===n&&((b===!0||g.isString(b))&&($.each($.queue(a,g.isString(b)?b:""),function(e,t){g.isFunction(t)&&t(null,!0)}),$.queue(a,g.isString(b)?b:"",[])),"stop"===h?(i(a)&&i(a).tweensContainer&&o!==!1&&$.each(i(a).tweensContainer,function(e,t){t.endValue=t.currentValue
222 }),A.push(e)):"finish"===h&&(t[2].duration=1))}):!0})}),"stop"===h&&($.each(A,function(e,t){p(t,!0)}),T.promise&&T.resolver(m)),e();default:if(!$.isPlainObject(h)||g.isEmptyObject(h)){if(g.isString(h)&&v.Redirects[h]){var F=$.extend({},b),E=F.duration,j=F.delay||0;return F.backwards===!0&&(m=$.extend(!0,[],m).reverse()),$.each(m,function(e,t){parseFloat(F.stagger)?F.delay=j+parseFloat(F.stagger)*e:g.isFunction(F.stagger)&&(F.delay=j+F.stagger.call(t,e,P)),F.drag&&(F.duration=parseFloat(E)||(/^(callout|transition)/.test(h)?1e3:y),F.duration=Math.max(F.duration*(F.backwards?1-e/P:(e+1)/P),.75*F.duration,200)),v.Redirects[h].call(t,t,F||{},e,P,m,T.promise?T:a)}),e()}var H="Velocity: First argument ("+h+") was not a property map, a known action, or a registered redirect. Aborting.";return T.promise?T.rejecter(new Error(H)):console.log(H),e()}k="start"}var N={lastParent:null,lastPosition:null,lastFontSize:null,lastPercentToPxWidth:null,lastPercentToPxHeight:null,lastEmToPx:null,remToPx:null,vwToPx:null,vhToPx:null},L=[];$.each(m,function(e,t){g.isNode(t)&&n.call(t)});var F=$.extend({},v.defaults,b),R;if(F.loop=parseInt(F.loop),R=2*F.loop-1,F.loop)for(var O=0;R>O;O++){var z={delay:F.delay,progress:F.progress};O===R-1&&(z.display=F.display,z.visibility=F.visibility,z.complete=F.complete),S(m,"reverse",z)}return e()}};v=$.extend(S,v),v.animate=S;var P=t.requestAnimationFrame||d;return v.State.isMobile||r.hidden===a||r.addEventListener("visibilitychange",function(){r.hidden?(P=function(e){return setTimeout(function(){e(!0)},16)},c()):P=t.requestAnimationFrame||d}),e.Velocity=v,e!==t&&(e.fn.velocity=S,e.fn.velocity.defaults=v.defaults),$.each(["Down","Up"],function(e,t){v.Redirects["slide"+t]=function(e,r,n,o,i,s){var l=$.extend({},r),u=l.begin,c=l.complete,p={height:"",marginTop:"",marginBottom:"",paddingTop:"",paddingBottom:""},f={};l.display===a&&(l.display="Down"===t?"inline"===v.CSS.Values.getDisplayType(e)?"inline-block":"block":"none"),l.begin=function(){u&&u.call(i,i);for(var r in p){f[r]=e.style[r];var a=v.CSS.getPropertyValue(e,r);p[r]="Down"===t?[a,0]:[0,a]}f.overflow=e.style.overflow,e.style.overflow="hidden"},l.complete=function(){for(var t in f)e.style[t]=f[t];c&&c.call(i,i),s&&s.resolver(i)},v(e,p,l)}}),$.each(["In","Out"],function(e,t){v.Redirects["fade"+t]=function(e,r,n,o,i,s){var l=$.extend({},r),u={opacity:"In"===t?1:0},c=l.complete;l.complete=n!==o-1?l.begin=null:function(){c&&c.call(i,i),s&&s.resolver(i)},l.display===a&&(l.display="In"===t?"auto":"none"),v(this,u,l)}}),v}(window.jQuery||window.Zepto||window,window,document)});;!function(a,b,c,d){"use strict";function k(a,b,c){return setTimeout(q(a,c),b)}function l(a,b,c){return Array.isArray(a)?(m(a,c[b],c),!0):!1}function m(a,b,c){var e;if(a)if(a.forEach)a.forEach(b,c);else if(a.length!==d)for(e=0;e<a.length;)b.call(c,a[e],e,a),e++;else for(e in a)a.hasOwnProperty(e)&&b.call(c,a[e],e,a)}function n(a,b,c){for(var e=Object.keys(b),f=0;f<e.length;)(!c||c&&a[e[f]]===d)&&(a[e[f]]=b[e[f]]),f++;return a}function o(a,b){return n(a,b,!0)}function p(a,b,c){var e,d=b.prototype;e=a.prototype=Object.create(d),e.constructor=a,e._super=d,c&&n(e,c)}function q(a,b){return function(){return a.apply(b,arguments)}}function r(a,b){return typeof a==g?a.apply(b?b[0]||d:d,b):a}function s(a,b){return a===d?b:a}function t(a,b,c){m(x(b),function(b){a.addEventListener(b,c,!1)})}function u(a,b,c){m(x(b),function(b){a.removeEventListener(b,c,!1)})}function v(a,b){for(;a;){if(a==b)return!0;a=a.parentNode}return!1}function w(a,b){return a.indexOf(b)>-1}function x(a){return a.trim().split(/\s+/g)}function y(a,b,c){if(a.indexOf&&!c)return a.indexOf(b);for(var d=0;d<a.length;){if(c&&a[d][c]==b||!c&&a[d]===b)return d;d++}return-1}function z(a){return Array.prototype.slice.call(a,0)}function A(a,b,c){for(var d=[],e=[],f=0;f<a.length;){var g=b?a[f][b]:a[f];y(e,g)<0&&d.push(a[f]),e[f]=g,f++}return c&&(d=b?d.sort(function(a,c){return a[b]>c[b]}):d.sort()),d}function B(a,b){for(var c,f,g=b[0].toUpperCase()+b.slice(1),h=0;h<e.length;){if(c=e[h],f=c?c+g:b,f in a)return f;h++}return d}function D(){return C++}function E(a){var b=a.ownerDocument;return b.defaultView||b.parentWindow}function ab(a,b){var c=this;this.manager=a,this.callback=b,this.element=a.element,this.target=a.options.inputTarget,this.domHandler=function(b){r(a.options.enable,[a])&&c.handler(b)},this.init()}function bb(a){var b,c=a.options.inputClass;return b=c?c:H?wb:I?Eb:G?Gb:rb,new b(a,cb)}function cb(a,b,c){var d=c.pointers.length,e=c.changedPointers.length,f=b&O&&0===d-e,g=b&(Q|R)&&0===d-e;c.isFirst=!!f,c.isFinal=!!g,f&&(a.session={}),c.eventType=b,db(a,c),a.emit("hammer.input",c),a.recognize(c),a.session.prevInput=c}function db(a,b){var c=a.session,d=b.pointers,e=d.length;c.firstInput||(c.firstInput=gb(b)),e>1&&!c.firstMultiple?c.firstMultiple=gb(b):1===e&&(c.firstMultiple=!1);var f=c.firstInput,g=c.firstMultiple,h=g?g.center:f.center,i=b.center=hb(d);b.timeStamp=j(),b.deltaTime=b.timeStamp-f.timeStamp,b.angle=lb(h,i),b.distance=kb(h,i),eb(c,b),b.offsetDirection=jb(b.deltaX,b.deltaY),b.scale=g?nb(g.pointers,d):1,b.rotation=g?mb(g.pointers,d):0,fb(c,b);var k=a.element;v(b.srcEvent.target,k)&&(k=b.srcEvent.target),b.target=k}function eb(a,b){var c=b.center,d=a.offsetDelta||{},e=a.prevDelta||{},f=a.prevInput||{};(b.eventType===O||f.eventType===Q)&&(e=a.prevDelta={x:f.deltaX||0,y:f.deltaY||0},d=a.offsetDelta={x:c.x,y:c.y}),b.deltaX=e.x+(c.x-d.x),b.deltaY=e.y+(c.y-d.y)}function fb(a,b){var f,g,h,j,c=a.lastInterval||b,e=b.timeStamp-c.timeStamp;if(b.eventType!=R&&(e>N||c.velocity===d)){var k=c.deltaX-b.deltaX,l=c.deltaY-b.deltaY,m=ib(e,k,l);g=m.x,h=m.y,f=i(m.x)>i(m.y)?m.x:m.y,j=jb(k,l),a.lastInterval=b}else f=c.velocity,g=c.velocityX,h=c.velocityY,j=c.direction;b.velocity=f,b.velocityX=g,b.velocityY=h,b.direction=j}function gb(a){for(var b=[],c=0;c<a.pointers.length;)b[c]={clientX:h(a.pointers[c].clientX),clientY:h(a.pointers[c].clientY)},c++;return{timeStamp:j(),pointers:b,center:hb(b),deltaX:a.deltaX,deltaY:a.deltaY}}function hb(a){var b=a.length;if(1===b)return{x:h(a[0].clientX),y:h(a[0].clientY)};for(var c=0,d=0,e=0;b>e;)c+=a[e].clientX,d+=a[e].clientY,e++;return{x:h(c/b),y:h(d/b)}}function ib(a,b,c){return{x:b/a||0,y:c/a||0}}function jb(a,b){return a===b?S:i(a)>=i(b)?a>0?T:U:b>0?V:W}function kb(a,b,c){c||(c=$);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return Math.sqrt(d*d+e*e)}function lb(a,b,c){c||(c=$);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return 180*Math.atan2(e,d)/Math.PI}function mb(a,b){return lb(b[1],b[0],_)-lb(a[1],a[0],_)}function nb(a,b){return kb(b[0],b[1],_)/kb(a[0],a[1],_)}function rb(){this.evEl=pb,this.evWin=qb,this.allow=!0,this.pressed=!1,ab.apply(this,arguments)}function wb(){this.evEl=ub,this.evWin=vb,ab.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function Ab(){this.evTarget=yb,this.evWin=zb,this.started=!1,ab.apply(this,arguments)}function Bb(a,b){var c=z(a.touches),d=z(a.changedTouches);return b&(Q|R)&&(c=A(c.concat(d),"identifier",!0)),[c,d]}function Eb(){this.evTarget=Db,this.targetIds={},ab.apply(this,arguments)}function Fb(a,b){var c=z(a.touches),d=this.targetIds;if(b&(O|P)&&1===c.length)return d[c[0].identifier]=!0,[c,c];var e,f,g=z(a.changedTouches),h=[],i=this.target;if(f=c.filter(function(a){return v(a.target,i)}),b===O)for(e=0;e<f.length;)d[f[e].identifier]=!0,e++;for(e=0;e<g.length;)d[g[e].identifier]&&h.push(g[e]),b&(Q|R)&&delete d[g[e].identifier],e++;return h.length?[A(f.concat(h),"identifier",!0),h]:void 0}function Gb(){ab.apply(this,arguments);var a=q(this.handler,this);this.touch=new Eb(this.manager,a),this.mouse=new rb(this.manager,a)}function Pb(a,b){this.manager=a,this.set(b)}function Qb(a){if(w(a,Mb))return Mb;var b=w(a,Nb),c=w(a,Ob);return b&&c?Nb+" "+Ob:b||c?b?Nb:Ob:w(a,Lb)?Lb:Kb}function Yb(a){this.id=D(),this.manager=null,this.options=o(a||{},this.defaults),this.options.enable=s(this.options.enable,!0),this.state=Rb,this.simultaneous={},this.requireFail=[]}function Zb(a){return a&Wb?"cancel":a&Ub?"end":a&Tb?"move":a&Sb?"start":""}function $b(a){return a==W?"down":a==V?"up":a==T?"left":a==U?"right":""}function _b(a,b){var c=b.manager;return c?c.get(a):a}function ac(){Yb.apply(this,arguments)}function bc(){ac.apply(this,arguments),this.pX=null,this.pY=null}function cc(){ac.apply(this,arguments)}function dc(){Yb.apply(this,arguments),this._timer=null,this._input=null}function ec(){ac.apply(this,arguments)}function fc(){ac.apply(this,arguments)}function gc(){Yb.apply(this,arguments),this.pTime=!1,this.pCenter=!1,this._timer=null,this._input=null,this.count=0}function hc(a,b){return b=b||{},b.recognizers=s(b.recognizers,hc.defaults.preset),new kc(a,b)}function kc(a,b){b=b||{},this.options=o(b,hc.defaults),this.options.inputTarget=this.options.inputTarget||a,this.handlers={},this.session={},this.recognizers=[],this.element=a,this.input=bb(this),this.touchAction=new Pb(this,this.options.touchAction),lc(this,!0),m(b.recognizers,function(a){var b=this.add(new a[0](a[1]));a[2]&&b.recognizeWith(a[2]),a[3]&&b.requireFailure(a[3])},this)}function lc(a,b){var c=a.element;m(a.options.cssProps,function(a,d){c.style[B(c.style,d)]=b?a:""})}function mc(a,c){var d=b.createEvent("Event");d.initEvent(a,!0,!0),d.gesture=c,c.target.dispatchEvent(d)}var e=["","webkit","moz","MS","ms","o"],f=b.createElement("div"),g="function",h=Math.round,i=Math.abs,j=Date.now,C=1,F=/mobile|tablet|ip(ad|hone|od)|android/i,G="ontouchstart"in a,H=B(a,"PointerEvent")!==d,I=G&&F.test(navigator.userAgent),J="touch",K="pen",L="mouse",M="kinect",N=25,O=1,P=2,Q=4,R=8,S=1,T=2,U=4,V=8,W=16,X=T|U,Y=V|W,Z=X|Y,$=["x","y"],_=["clientX","clientY"];ab.prototype={handler:function(){},init:function(){this.evEl&&t(this.element,this.evEl,this.domHandler),this.evTarget&&t(this.target,this.evTarget,this.domHandler),this.evWin&&t(E(this.element),this.evWin,this.domHandler)},destroy:function(){this.evEl&&u(this.element,this.evEl,this.domHandler),this.evTarget&&u(this.target,this.evTarget,this.domHandler),this.evWin&&u(E(this.element),this.evWin,this.domHandler)}};var ob={mousedown:O,mousemove:P,mouseup:Q},pb="mousedown",qb="mousemove mouseup";p(rb,ab,{handler:function(a){var b=ob[a.type];b&O&&0===a.button&&(this.pressed=!0),b&P&&1!==a.which&&(b=Q),this.pressed&&this.allow&&(b&Q&&(this.pressed=!1),this.callback(this.manager,b,{pointers:[a],changedPointers:[a],pointerType:L,srcEvent:a}))}});var sb={pointerdown:O,pointermove:P,pointerup:Q,pointercancel:R,pointerout:R},tb={2:J,3:K,4:L,5:M},ub="pointerdown",vb="pointermove pointerup pointercancel";a.MSPointerEvent&&(ub="MSPointerDown",vb="MSPointerMove MSPointerUp MSPointerCancel"),p(wb,ab,{handler:function(a){var b=this.store,c=!1,d=a.type.toLowerCase().replace("ms",""),e=sb[d],f=tb[a.pointerType]||a.pointerType,g=f==J,h=y(b,a.pointerId,"pointerId");e&O&&(0===a.button||g)?0>h&&(b.push(a),h=b.length-1):e&(Q|R)&&(c=!0),0>h||(b[h]=a,this.callback(this.manager,e,{pointers:b,changedPointers:[a],pointerType:f,srcEvent:a}),c&&b.splice(h,1))}});var xb={touchstart:O,touchmove:P,touchend:Q,touchcancel:R},yb="touchstart",zb="touchstart touchmove touchend touchcancel";p(Ab,ab,{handler:function(a){var b=xb[a.type];if(b===O&&(this.started=!0),this.started){var c=Bb.call(this,a,b);b&(Q|R)&&0===c[0].length-c[1].length&&(this.started=!1),this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:J,srcEvent:a})}}});var Cb={touchstart:O,touchmove:P,touchend:Q,touchcancel:R},Db="touchstart touchmove touchend touchcancel";p(Eb,ab,{handler:function(a){var b=Cb[a.type],c=Fb.call(this,a,b);c&&this.callback(this.manager,b,{pointers:c[0],changedPointers:c[1],pointerType:J,srcEvent:a})}}),p(Gb,ab,{handler:function(a,b,c){var d=c.pointerType==J,e=c.pointerType==L;if(d)this.mouse.allow=!1;else if(e&&!this.mouse.allow)return;b&(Q|R)&&(this.mouse.allow=!0),this.callback(a,b,c)},destroy:function(){this.touch.destroy(),this.mouse.destroy()}});var Hb=B(f.style,"touchAction"),Ib=Hb!==d,Jb="compute",Kb="auto",Lb="manipulation",Mb="none",Nb="pan-x",Ob="pan-y";Pb.prototype={set:function(a){a==Jb&&(a=this.compute()),Ib&&(this.manager.element.style[Hb]=a),this.actions=a.toLowerCase().trim()},update:function(){this.set(this.manager.options.touchAction)},compute:function(){var a=[];return m(this.manager.recognizers,function(b){r(b.options.enable,[b])&&(a=a.concat(b.getTouchAction()))}),Qb(a.join(" "))},preventDefaults:function(a){if(!Ib){var b=a.srcEvent,c=a.offsetDirection;if(this.manager.session.prevented)return b.preventDefault(),void 0;var d=this.actions,e=w(d,Mb),f=w(d,Ob),g=w(d,Nb);return e||f&&c&X||g&&c&Y?this.preventSrc(b):void 0}},preventSrc:function(a){this.manager.session.prevented=!0,a.preventDefault()}};var Rb=1,Sb=2,Tb=4,Ub=8,Vb=Ub,Wb=16,Xb=32;Yb.prototype={defaults:{},set:function(a){return n(this.options,a),this.manager&&this.manager.touchAction.update(),this},recognizeWith:function(a){if(l(a,"recognizeWith",this))return this;var b=this.simultaneous;return a=_b(a,this),b[a.id]||(b[a.id]=a,a.recognizeWith(this)),this},dropRecognizeWith:function(a){return l(a,"dropRecognizeWith",this)?this:(a=_b(a,this),delete this.simultaneous[a.id],this)},requireFailure:function(a){if(l(a,"requireFailure",this))return this;var b=this.requireFail;return a=_b(a,this),-1===y(b,a)&&(b.push(a),a.requireFailure(this)),this},dropRequireFailure:function(a){if(l(a,"dropRequireFailure",this))return this;a=_b(a,this);var b=y(this.requireFail,a);return b>-1&&this.requireFail.splice(b,1),this},hasRequireFailures:function(){return this.requireFail.length>0},canRecognizeWith:function(a){return!!this.simultaneous[a.id]},emit:function(a){function d(d){b.manager.emit(b.options.event+(d?Zb(c):""),a)}var b=this,c=this.state;Ub>c&&d(!0),d(),c>=Ub&&d(!0)},tryEmit:function(a){return this.canEmit()?this.emit(a):(this.state=Xb,void 0)},canEmit:function(){for(var a=0;a<this.requireFail.length;){if(!(this.requireFail[a].state&(Xb|Rb)))return!1;a++}return!0},recognize:function(a){var b=n({},a);return r(this.options.enable,[this,b])?(this.state&(Vb|Wb|Xb)&&(this.state=Rb),this.state=this.process(b),this.state&(Sb|Tb|Ub|Wb)&&this.tryEmit(b),void 0):(this.reset(),this.state=Xb,void 0)},process:function(){},getTouchAction:function(){},reset:function(){}},p(ac,Yb,{defaults:{pointers:1},attrTest:function(a){var b=this.options.pointers;return 0===b||a.pointers.length===b},process:function(a){var b=this.state,c=a.eventType,d=b&(Sb|Tb),e=this.attrTest(a);return d&&(c&R||!e)?b|Wb:d||e?c&Q?b|Ub:b&Sb?b|Tb:Sb:Xb}}),p(bc,ac,{defaults:{event:"pan",threshold:10,pointers:1,direction:Z},getTouchAction:function(){var a=this.options.direction,b=[];return a&X&&b.push(Ob),a&Y&&b.push(Nb),b},directionTest:function(a){var b=this.options,c=!0,d=a.distance,e=a.direction,f=a.deltaX,g=a.deltaY;return e&b.direction||(b.direction&X?(e=0===f?S:0>f?T:U,c=f!=this.pX,d=Math.abs(a.deltaX)):(e=0===g?S:0>g?V:W,c=g!=this.pY,d=Math.abs(a.deltaY))),a.direction=e,c&&d>b.threshold&&e&b.direction},attrTest:function(a){return ac.prototype.attrTest.call(this,a)&&(this.state&Sb||!(this.state&Sb)&&this.directionTest(a))},emit:function(a){this.pX=a.deltaX,this.pY=a.deltaY;var b=$b(a.direction);b&&this.manager.emit(this.options.event+b,a),this._super.emit.call(this,a)}}),p(cc,ac,{defaults:{event:"pinch",threshold:0,pointers:2},getTouchAction:function(){return[Mb]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.scale-1)>this.options.threshold||this.state&Sb)},emit:function(a){if(this._super.emit.call(this,a),1!==a.scale){var b=a.scale<1?"in":"out";this.manager.emit(this.options.event+b,a)}}}),p(dc,Yb,{defaults:{event:"press",pointers:1,time:500,threshold:5},getTouchAction:function(){return[Kb]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distance<b.threshold,e=a.deltaTime>b.time;if(this._input=a,!d||!c||a.eventType&(Q|R)&&!e)this.reset();else if(a.eventType&O)this.reset(),this._timer=k(function(){this.state=Vb,this.tryEmit()},b.time,this);else if(a.eventType&Q)return Vb;return Xb},reset:function(){clearTimeout(this._timer)},emit:function(a){this.state===Vb&&(a&&a.eventType&Q?this.manager.emit(this.options.event+"up",a):(this._input.timeStamp=j(),this.manager.emit(this.options.event,this._input)))}}),p(ec,ac,{defaults:{event:"rotate",threshold:0,pointers:2},getTouchAction:function(){return[Mb]},attrTest:function(a){return this._super.attrTest.call(this,a)&&(Math.abs(a.rotation)>this.options.threshold||this.state&Sb)}}),p(fc,ac,{defaults:{event:"swipe",threshold:10,velocity:.65,direction:X|Y,pointers:1},getTouchAction:function(){return bc.prototype.getTouchAction.call(this)},attrTest:function(a){var c,b=this.options.direction;return b&(X|Y)?c=a.velocity:b&X?c=a.velocityX:b&Y&&(c=a.velocityY),this._super.attrTest.call(this,a)&&b&a.direction&&a.distance>this.options.threshold&&i(c)>this.options.velocity&&a.eventType&Q},emit:function(a){var b=$b(a.direction);b&&this.manager.emit(this.options.event+b,a),this.manager.emit(this.options.event,a)}}),p(gc,Yb,{defaults:{event:"tap",pointers:1,taps:1,interval:300,time:250,threshold:2,posThreshold:10},getTouchAction:function(){return[Lb]},process:function(a){var b=this.options,c=a.pointers.length===b.pointers,d=a.distance<b.threshold,e=a.deltaTime<b.time;if(this.reset(),a.eventType&O&&0===this.count)return this.failTimeout();if(d&&e&&c){if(a.eventType!=Q)return this.failTimeout();var f=this.pTime?a.timeStamp-this.pTime<b.interval:!0,g=!this.pCenter||kb(this.pCenter,a.center)<b.posThreshold;this.pTime=a.timeStamp,this.pCenter=a.center,g&&f?this.count+=1:this.count=1,this._input=a;var h=this.count%b.taps;if(0===h)return this.hasRequireFailures()?(this._timer=k(function(){this.state=Vb,this.tryEmit()},b.interval,this),Sb):Vb}return Xb},failTimeout:function(){return this._timer=k(function(){this.state=Xb},this.options.interval,this),Xb},reset:function(){clearTimeout(this._timer)},emit:function(){this.state==Vb&&(this._input.tapCount=this.count,this.manager.emit(this.options.event,this._input))}}),hc.VERSION="2.0.4",hc.defaults={domEvents:!1,touchAction:Jb,enable:!0,inputTarget:null,inputClass:null,preset:[[ec,{enable:!1}],[cc,{enable:!1},["rotate"]],[fc,{direction:X}],[bc,{direction:X},["swipe"]],[gc],[gc,{event:"doubletap",taps:2},["tap"]],[dc]],cssProps:{userSelect:"default",touchSelect:"none",touchCallout:"none",contentZooming:"none",userDrag:"none",tapHighlightColor:"rgba(0,0,0,0)"}};var ic=1,jc=2;kc.prototype={set:function(a){return n(this.options,a),a.touchAction&&this.touchAction.update(),a.inputTarget&&(this.input.destroy(),this.input.target=a.inputTarget,this.input.init()),this},stop:function(a){this.session.stopped=a?jc:ic},recognize:function(a){var b=this.session;if(!b.stopped){this.touchAction.preventDefaults(a);var c,d=this.recognizers,e=b.curRecognizer;(!e||e&&e.state&Vb)&&(e=b.curRecognizer=null);for(var f=0;f<d.length;)c=d[f],b.stopped===jc||e&&c!=e&&!c.canRecognizeWith(e)?c.reset():c.recognize(a),!e&&c.state&(Sb|Tb|Ub)&&(e=b.curRecognizer=c),f++}},get:function(a){if(a instanceof Yb)return a;for(var b=this.recognizers,c=0;c<b.length;c++)if(b[c].options.event==a)return b[c];return null},add:function(a){if(l(a,"add",this))return this;var b=this.get(a.options.event);return b&&this.remove(b),this.recognizers.push(a),a.manager=this,this.touchAction.update(),a},remove:function(a){if(l(a,"remove",this))return this;var b=this.recognizers;return a=this.get(a),b.splice(y(b,a),1),this.touchAction.update(),this},on:function(a,b){var c=this.handlers;return m(x(a),function(a){c[a]=c[a]||[],c[a].push(b)}),this},off:function(a,b){var c=this.handlers;return m(x(a),function(a){b?c[a].splice(y(c[a],b),1):delete c[a]}),this},emit:function(a,b){this.options.domEvents&&mc(a,b);var c=this.handlers[a]&&this.handlers[a].slice();if(c&&c.length){b.type=a,b.preventDefault=function(){b.srcEvent.preventDefault()};for(var d=0;d<c.length;)c[d](b),d++}},destroy:function(){this.element&&lc(this,!1),this.handlers={},this.session={},this.input.destroy(),this.element=null}},n(hc,{INPUT_START:O,INPUT_MOVE:P,INPUT_END:Q,INPUT_CANCEL:R,STATE_POSSIBLE:Rb,STATE_BEGAN:Sb,STATE_CHANGED:Tb,STATE_ENDED:Ub,STATE_RECOGNIZED:Vb,STATE_CANCELLED:Wb,STATE_FAILED:Xb,DIRECTION_NONE:S,DIRECTION_LEFT:T,DIRECTION_RIGHT:U,DIRECTION_UP:V,DIRECTION_DOWN:W,DIRECTION_HORIZONTAL:X,DIRECTION_VERTICAL:Y,DIRECTION_ALL:Z,Manager:kc,Input:ab,TouchAction:Pb,TouchInput:Eb,MouseInput:rb,PointerEventInput:wb,TouchMouseInput:Gb,SingleTouchInput:Ab,Recognizer:Yb,AttrRecognizer:ac,Tap:gc,Pan:bc,Swipe:fc,Pinch:cc,Rotate:ec,Press:dc,on:t,off:u,each:m,merge:o,extend:n,inherit:p,bindFn:q,prefixed:B}),typeof define==g&&define.amd?define(function(){return hc}):"undefined"!=typeof module&&module.exports?module.exports=hc:a[c]=hc}(window,document,"Hammer");;(function(factory) {
223 if (typeof define === 'function' && define.amd) {
224 define(['jquery', 'hammerjs'], factory);
225 } else if (typeof exports === 'object') {
226 factory(require('jquery'), require('hammerjs'));
228 factory(jQuery, Hammer);
230 }(function($, Hammer) {
231 function hammerify(el, options) {
233 if(!$el.data("hammer")) {
234 $el.data("hammer", new Hammer($el[0], options));
238 $.fn.hammer = function(options) {
239 return this.each(function() {
240 hammerify(this, options);
244 // extend the emit method to also trigger jQuery events
245 Hammer.Manager.prototype.emit = (function(originalEmit) {
246 return function(type, data) {
247 originalEmit.call(this, type, data);
248 $(this.element).trigger({
253 })(Hammer.Manager.prototype.emit);
255 ;window.Materialize = {};
258 Materialize.guid = (function() {
260 return Math.floor((1 + Math.random()) * 0x10000)
265 return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
266 s4() + '-' + s4() + s4() + s4();
270 Materialize.elementOrParentIsFixed = function(element) {
271 var $element = $(element);
272 var $checkElements = $element.add($element.parents());
274 $checkElements.each(function(){
275 if ($(this).css("position") === "fixed") {
283 // Velocity has conflicts when loaded with jQuery, this will check for it
292 $.fn.collapsible = function(options) {
297 options = $.extend(defaults, options);
300 return this.each(function() {
304 var $panel_headers = $(this).find('> li > .collapsible-header');
306 var collapsible_type = $this.data("collapsible");
308 // Turn off any existing event handlers
309 $this.off('click.collapse', '.collapsible-header');
310 $panel_headers.off('click.collapse');
318 function accordionOpen(object
) {
319 $panel_headers
= $this.find('> li > .collapsible-header');
320 if (object
.hasClass('active')) {
321 object
.parent().addClass('active');
324 object
.parent().removeClass('active');
326 if (object
.parent().hasClass('active')){
327 object
.siblings('.collapsible-body').stop(true,false).slideDown({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
330 object
.siblings('.collapsible-body').stop(true,false).slideUp({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
333 $panel_headers
.not(object
).removeClass('active').parent().removeClass('active');
334 $panel_headers
.not(object
).parent().children('.collapsible-body').stop(true,false).slideUp(
337 easing: "easeOutQuart",
341 $(this).css('height', '');
347 function expandableOpen(object
) {
348 if (object
.hasClass('active')) {
349 object
.parent().addClass('active');
352 object
.parent().removeClass('active');
354 if (object
.parent().hasClass('active')){
355 object
.siblings('.collapsible-body').stop(true,false).slideDown({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
358 object
.siblings('.collapsible-body').stop(true,false).slideUp({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
363 * Check if object is children of panel header
364 * @param {Object} object Jquery object
365 * @return {Boolean} true if it is children
367 function isChildrenOfPanelHeader(object
) {
369 var panelHeader
= getPanelHeader(object
);
371 return panelHeader
.length
> 0;
375 * Get panel header from a children element
376 * @param {Object} object Jquery object
377 * @return {Object} panel header object
379 function getPanelHeader(object
) {
381 return object
.closest('li > .collapsible-header');
384 /***** End Helper Functions *****/
388 if (options
.accordion
|| collapsible_type
=== "accordion" || collapsible_type
=== undefined) { // Handle Accordion
389 // Add click handler to only direct collapsible header children
390 $panel_headers
= $this.find('> li > .collapsible-header');
391 $panel_headers
.on('click.collapse', function (e
) {
392 var element
= $(e
.target
);
394 if (isChildrenOfPanelHeader(element
)) {
395 element
= getPanelHeader(element
);
398 element
.toggleClass('active');
399 accordionOpen(element
);
402 accordionOpen($panel_headers
.filter('.active').first());
404 else { // Handle Expandables
405 $panel_headers
.each(function () {
406 // Add click handler to only direct collapsible header children
407 $(this).on('click.collapse', function (e
) {
408 var element
= $(e
.target
);
409 if (isChildrenOfPanelHeader(element
)) {
410 element
= getPanelHeader(element
);
412 element
.toggleClass('active');
413 expandableOpen(element
);
415 // Open any bodies that have the active class
416 if ($(this).hasClass('active')) {
417 expandableOpen($(this));
426 $(document
).ready(function(){
427 $('.collapsible').collapsible();
429 }( jQuery
));;(function ($) {
431 // Add posibility to scroll to selected option
432 // usefull for select for example
433 $.fn
.scrollTo = function(elem
) {
434 $(this).scrollTop($(this).scrollTop() - $(this).offset().top
+ $(elem
).offset().top
);
438 $.fn
.dropdown = function (option
) {
442 constrain_width: true, // Constrains width of dropdown to the activator
444 gutter: 0, // Spacing from edge
449 this.each(function(){
450 var origin
= $(this);
451 var options
= $.extend({}, defaults
, option
);
454 var activates
= $("#"+ origin
.attr('data-activates'));
456 function updateOptions() {
457 if (origin
.data('induration') !== undefined)
458 options
.inDuration
= origin
.data('inDuration');
459 if (origin
.data('outduration') !== undefined)
460 options
.outDuration
= origin
.data('outDuration');
461 if (origin
.data('constrainwidth') !== undefined)
462 options
.constrain_width
= origin
.data('constrainwidth');
463 if (origin
.data('hover') !== undefined)
464 options
.hover
= origin
.data('hover');
465 if (origin
.data('gutter') !== undefined)
466 options
.gutter
= origin
.data('gutter');
467 if (origin
.data('beloworigin') !== undefined)
468 options
.belowOrigin
= origin
.data('beloworigin');
469 if (origin
.data('alignment') !== undefined)
470 options
.alignment
= origin
.data('alignment');
475 // Attach dropdown to its activator
476 origin
.after(activates
);
479 Helper function to position and resize dropdown.
480 Used in hover and click handler.
482 function placeDropdown() {
483 // Check html data attributes
486 // Set Dropdown state
487 activates
.addClass('active');
490 if (options
.constrain_width
=== true) {
491 activates
.css('width', origin
.outerWidth());
494 activates
.css('white-space', 'nowrap');
497 if (options
.belowOrigin
=== true) {
498 offset
= origin
.height();
501 // Offscreen detection
502 var offsetLeft
= origin
.offset().left
;
503 var activatesLeft
, width_difference
, gutter_spacing
;
504 if (offsetLeft
+ activates
.innerWidth() > $(window
).width()) {
505 options
.alignment
= 'right';
507 else if (offsetLeft
- activates
.innerWidth() + origin
.innerWidth() < 0) {
508 options
.alignment
= 'left';
511 // Handle edge alignment
512 if (options
.alignment
=== 'left') {
513 width_difference
= 0;
514 gutter_spacing
= options
.gutter
;
515 activatesLeft
= origin
.position().left
+ width_difference
+ gutter_spacing
;
518 activates
.css({ left: activatesLeft
});
520 else if (options
.alignment
=== 'right') {
521 var offsetRight
= $(window
).width() - offsetLeft
- origin
.innerWidth();
522 width_difference
= 0;
523 gutter_spacing
= options
.gutter
;
524 activatesLeft
= ( $(window
).width() - origin
.position().left
- origin
.innerWidth() ) + gutter_spacing
;
527 activates
.css({ right: activatesLeft
});
531 position: 'absolute',
532 top: origin
.position().top
+ offset
,
538 activates
.stop(true, true).css('opacity', 0)
541 duration: options
.inDuration
,
542 easing: 'easeOutCubic',
543 complete: function() {
544 $(this).css('height', '');
547 .animate( {opacity: 1}, {queue: false, duration: options
.inDuration
, easing: 'easeOutSine'});
550 function hideDropdown() {
551 activates
.fadeOut(options
.outDuration
);
552 activates
.removeClass('active');
558 origin
.unbind('click.' + origin
.attr('id'));
559 // Hover handler to show dropdown
560 origin
.on('mouseenter', function(e
){ // Mouse over
561 if (open
=== false) {
566 origin
.on('mouseleave', function(e
){
567 // If hover on origin then to something other than dropdown content, then close
568 var toEl
= e
.toElement
|| e
.relatedTarget
; // added browser compatibility for target element
569 if(!$(toEl
).closest('.dropdown-content').is(activates
)) {
570 activates
.stop(true, true);
576 activates
.on('mouseleave', function(e
){ // Mouse out
577 var toEl
= e
.toElement
|| e
.relatedTarget
;
578 if(!$(toEl
).closest('.dropdown-button').is(origin
)) {
579 activates
.stop(true, true);
588 // Click handler to show dropdown
589 origin
.unbind('click.' + origin
.attr('id'));
590 origin
.bind('click.'+origin
.attr('id'), function(e
){
592 if ( origin
[0] == e
.currentTarget
&& ($(e
.target
).closest('.dropdown-content').length
=== 0) ) {
593 e
.preventDefault(); // Prevents button click from moving window
597 // If origin is clicked and menu is open, close menu
599 if (origin
.hasClass('active')) {
601 $(document
).unbind('click.' + activates
.attr('id'));
604 // If menu open, add click close handler to document
605 if (activates
.hasClass('active')) {
606 $(document
).bind('click.'+ activates
.attr('id'), function (e
) {
607 if (!activates
.is(e
.target
) && !origin
.is(e
.target
) && (!origin
.find(e
.target
).length
> 0) ) {
609 $(document
).unbind('click.' + activates
.attr('id'));
617 // Listen to open and close event - useful for select component
618 origin
.on('open', placeDropdown
);
619 origin
.on('close', hideDropdown
);
623 }; // End dropdown plugin
625 $(document
).ready(function(){
626 $('.dropdown-button').dropdown();
632 _generateID = function() {
634 return 'materialize-lean-overlay-' + _lastID
;
638 openModal: function(options
) {
640 $('body').css('overflow', 'hidden');
651 overlayID
= _generateID(),
653 $overlay
= $('<div class="lean-overlay"></div>'),
656 // Store a reference of the overlay
657 $overlay
.attr('id', overlayID
).css('z-index', 1000 + lStack
* 2);
658 $modal
.data('overlay-id', overlayID
).css('z-index', 1000 + lStack
* 2 + 1);
660 $("body").append($overlay
);
663 options
= $.extend(defaults
, options
);
665 if (options
.dismissible
) {
666 $overlay
.click(function() {
667 $modal
.closeModal(options
);
670 $(document
).on('keyup.leanModal' + overlayID
, function(e
) {
671 if (e
.keyCode
=== 27) { // ESC key
672 $modal
.closeModal(options
);
677 $modal
.find(".modal-close").on('click.close', function(e
) {
678 $modal
.closeModal(options
);
681 $overlay
.css({ display : "block", opacity : 0 });
688 $overlay
.velocity({opacity: options
.opacity
}, {duration: options
.in_duration
, queue: false, ease: "easeOutCubic"});
689 $modal
.data('associated-overlay', $overlay
[0]);
691 // Define Bottom Sheet animation
692 if ($modal
.hasClass('bottom-sheet')) {
693 $modal
.velocity({bottom: "0", opacity: 1}, {
694 duration: options
.in_duration
,
696 ease: "easeOutCubic",
697 // Handle modal ready callback
698 complete: function() {
699 if (typeof(options
.ready
) === "function") {
706 $.Velocity
.hook($modal
, "scaleX", 0.7);
707 $modal
.css({ top: options
.starting_top
});
708 $modal
.velocity({top: "10%", opacity: 1, scaleX: '1'}, {
709 duration: options
.in_duration
,
711 ease: "easeOutCubic",
712 // Handle modal ready callback
713 complete: function() {
714 if (typeof(options
.ready
) === "function") {
726 closeModal: function(options
) {
732 overlayID
= $modal
.data('overlay-id'),
733 $overlay
= $('#' + overlayID
);
735 options
= $.extend(defaults
, options
);
738 $('body').css('overflow', '');
740 $modal
.find('.modal-close').off('click.close');
741 $(document
).off('keyup.leanModal' + overlayID
);
743 $overlay
.velocity( { opacity: 0}, {duration: options
.out_duration
, queue: false, ease: "easeOutQuart"});
746 // Define Bottom Sheet animation
747 if ($modal
.hasClass('bottom-sheet')) {
748 $modal
.velocity({bottom: "-100%", opacity: 0}, {
749 duration: options
.out_duration
,
751 ease: "easeOutCubic",
752 // Handle modal ready callback
753 complete: function() {
754 $overlay
.css({display:"none"});
756 // Call complete callback
757 if (typeof(options
.complete
) === "function") {
767 { top: options
.starting_top
, opacity: 0, scaleX: 0.7}, {
768 duration: options
.out_duration
,
772 $(this).css('display', 'none');
773 // Call complete callback
774 if (typeof(options
.complete
) === "function") {
787 leanModal: function(option
) {
788 return this.each(function() {
794 options
= $.extend(defaults
, option
);
797 $(this).click(function(e
) {
798 options
.starting_top
= ($(this).offset().top
- $(window
).scrollTop()) /1.15;
799 var modal_id
= $(this).attr("href") || '#' + $(this).data('target');
800 $(modal_id
).openModal(options
);
802 }); // done set on click
809 $.fn
.materialbox = function () {
811 return this.each(function() {
813 if ($(this).hasClass('initialized')) {
817 $(this).addClass('initialized');
819 var overlayActive
= false;
820 var doneAnimating
= true;
821 var inDuration
= 275;
822 var outDuration
= 200;
823 var origin
= $(this);
824 var placeholder
= $('<div></div>').addClass('material-placeholder');
825 var originalWidth
= 0;
826 var originalHeight
= 0;
827 origin
.wrap(placeholder
);
830 origin
.on('click', function(){
831 var placeholder
= origin
.parent('.material-placeholder');
832 var windowWidth
= window
.innerWidth
;
833 var windowHeight
= window
.innerHeight
;
834 var originalWidth
= origin
.width();
835 var originalHeight
= origin
.height();
838 // If already modal, return to original
839 if (doneAnimating
=== false) {
843 else if (overlayActive
&& doneAnimating
===true) {
850 doneAnimating
= false;
851 origin
.addClass('active');
852 overlayActive
= true;
854 // Set positioning for placeholder
857 width: placeholder
[0].getBoundingClientRect().width
,
858 height: placeholder
[0].getBoundingClientRect().height
,
859 position: 'relative',
867 origin
.css({position: 'absolute', 'z-index': 1000})
868 .data('width', originalWidth
)
869 .data('height', originalHeight
);
872 var overlay
= $('<div id="materialbox-overlay"></div>')
877 if (doneAnimating
=== true)
881 $('body').append(overlay
);
882 overlay
.velocity({opacity: 1}, {duration: inDuration
, queue: false, easing: 'easeOutQuad'}
886 // Add and animate caption if it exists
887 if (origin
.data('caption') !== "") {
888 var $photo_caption
= $('<div class="materialbox-caption"></div>');
889 $photo_caption
.text(origin
.data('caption'));
890 $('body').append($photo_caption
);
891 $photo_caption
.css({ "display": "inline" });
892 $photo_caption
.velocity({opacity: 1}, {duration: inDuration
, queue: false, easing: 'easeOutQuad'});
899 var widthPercent
= originalWidth
/ windowWidth
;
900 var heightPercent
= originalHeight
/ windowHeight
;
904 if (widthPercent
> heightPercent
) {
905 ratio
= originalHeight
/ originalWidth
;
906 newWidth
= windowWidth
* 0.9;
907 newHeight
= windowWidth
* 0.9 * ratio
;
910 ratio
= originalWidth
/ originalHeight
;
911 newWidth
= (windowHeight
* 0.9) * ratio
;
912 newHeight
= windowHeight
* 0.9;
915 // Animate image + set z-index
916 if(origin
.hasClass('responsive-img')) {
917 origin
.velocity({'max-width': newWidth
, 'width': originalWidth
}, {duration: 0, queue: false,
918 complete: function(){
919 origin
.css({left: 0, top: 0})
924 left: $(document
).scrollLeft() + windowWidth
/2 - origin
.parent('.material-placeholder').offset().left
- newWidth
/2,
925 top: $(document
).scrollTop() + windowHeight
/2 - origin
.parent('.material-placeholder').offset().top
- newHeight
/ 2
928 duration: inDuration
,
930 easing: 'easeOutQuad',
931 complete: function(){doneAnimating
= true;}
938 origin
.css('left', 0)
944 left: $(document
).scrollLeft() + windowWidth
/2 - origin
.parent('.material-placeholder').offset().left
- newWidth
/2,
945 top: $(document
).scrollTop() + windowHeight
/2 - origin
.parent('.material-placeholder').offset().top
- newHeight
/ 2
948 duration: inDuration
,
950 easing: 'easeOutQuad',
951 complete: function(){doneAnimating
= true;}
956 }); // End origin on click
960 $(window
).scroll(function() {
961 if (overlayActive
) {
967 $(document
).keyup(function(e
) {
969 if (e
.keyCode
=== 27 && doneAnimating
=== true) { // ESC key
977 // This function returns the modaled image to the original spot
978 function returnToOriginal() {
980 doneAnimating
= false;
982 var placeholder
= origin
.parent('.material-placeholder');
983 var windowWidth
= window
.innerWidth
;
984 var windowHeight
= window
.innerHeight
;
985 var originalWidth
= origin
.data('width');
986 var originalHeight
= origin
.data('height');
988 origin
.velocity("stop", true);
989 $('#materialbox-overlay').velocity("stop", true);
990 $('.materialbox-caption').velocity("stop", true);
993 $('#materialbox-overlay').velocity({opacity: 0}, {
994 duration: outDuration
, // Delay prevents animation overlapping
995 queue: false, easing: 'easeOutQuad',
996 complete: function(){
998 overlayActive
= false;
1006 width: originalWidth
,
1007 height: originalHeight
,
1012 duration: outDuration
,
1013 queue: false, easing: 'easeOutQuad'
1017 // Remove Caption + reset css settings on image
1018 $('.materialbox-caption').velocity({opacity: 0}, {
1019 duration: outDuration
, // Delay prevents animation overlapping
1020 queue: false, easing: 'easeOutQuad',
1021 complete: function(){
1041 origin
.removeClass('active');
1042 doneAnimating
= true;
1051 $(document
).ready(function(){
1052 $('.materialboxed').materialbox();
1058 $.fn
.parallax = function () {
1059 var window_width
= $(window
).width();
1061 return this.each(function(i
) {
1062 var $this = $(this);
1063 $this.addClass('parallax');
1065 function updateParallax(initial
) {
1066 var container_height
;
1067 if (window_width
< 601) {
1068 container_height
= ($this.height() > 0) ? $this.height() : $this.children("img").height();
1071 container_height
= ($this.height() > 0) ? $this.height() : 500;
1073 var $img
= $this.children("img").first();
1074 var img_height
= $img
.height();
1075 var parallax_dist
= img_height
- container_height
;
1076 var bottom
= $this.offset().top
+ container_height
;
1077 var top
= $this.offset().top
;
1078 var scrollTop
= $(window
).scrollTop();
1079 var windowHeight
= window
.innerHeight
;
1080 var windowBottom
= scrollTop
+ windowHeight
;
1081 var percentScrolled
= (windowBottom
- top
) / (container_height
+ windowHeight
);
1082 var parallax
= Math
.round((parallax_dist
* percentScrolled
));
1085 $img
.css('display', 'block');
1087 if ((bottom
> scrollTop
) && (top
< (scrollTop
+ windowHeight
))) {
1088 $img
.css('transform', "translate3D(-50%," + parallax
+ "px, 0)");
1093 // Wait for image load
1094 $this.children("img").one("load", function() {
1095 updateParallax(true);
1096 }).each(function() {
1097 if(this.complete
) $(this).load();
1100 $(window
).scroll(function() {
1101 window_width
= $(window
).width();
1102 updateParallax(false);
1105 $(window
).resize(function() {
1106 window_width
= $(window
).width();
1107 updateParallax(false);
1113 }( jQuery
));;(function ($) {
1117 return this.each(function() {
1119 // For each set of tabs, we want to keep track of
1120 // which tab is active and its associated content
1121 var $this = $(this),
1122 window_width
= $(window
).width();
1124 $this.width('100%');
1125 var $active
, $content
, $links
= $this.find('li.tab a'),
1126 $tabs_width
= $this.width(),
1127 $tab_width
= $this.find('li').first().outerWidth(),
1130 // If the location.hash matches one of the links, use that as the active tab.
1131 $active
= $($links
.filter('[href="'+location
.hash
+'"]'));
1133 // If no match is found, use the first link or any with class 'active' as the initial active tab.
1134 if ($active
.length
=== 0) {
1135 $active
= $(this).find('li.tab a.active').first();
1137 if ($active
.length
=== 0) {
1138 $active
= $(this).find('li.tab a').first();
1141 $active
.addClass('active');
1142 $index
= $links
.index($active
);
1147 $content
= $($active
[0].hash
);
1149 // append indicator then set indicator width to tab width
1150 $this.append('<div class="indicator"></div>');
1151 var $indicator
= $this.find('.indicator');
1152 if ($this.is(":visible")) {
1153 $indicator
.css({"right": $tabs_width
- (($index
+ 1) * $tab_width
)});
1154 $indicator
.css({"left": $index
* $tab_width
});
1156 $(window
).resize(function () {
1157 $tabs_width
= $this.width();
1158 $tab_width
= $this.find('li').first().outerWidth();
1162 if ($tab_width
!== 0 && $tabs_width
!== 0) {
1163 $indicator
.css({"right": $tabs_width
- (($index
+ 1) * $tab_width
)});
1164 $indicator
.css({"left": $index
* $tab_width
});
1168 // Hide the remaining content
1169 $links
.not($active
).each(function () {
1170 $(this.hash
).hide();
1174 // Bind the click event handler
1175 $this.on('click', 'a', function(e
){
1176 if ($(this).parent().hasClass('disabled')) {
1181 $tabs_width
= $this.width();
1182 $tab_width
= $this.find('li').first().outerWidth();
1184 // Make the old tab inactive.
1185 $active
.removeClass('active');
1188 // Update the variables with the new link and content
1190 $content
= $(this.hash
);
1191 $links
= $this.find('li.tab a');
1193 // Make the tab active.
1194 $active
.addClass('active');
1195 var $prev_index
= $index
;
1196 $index
= $links
.index($(this));
1200 // Change url to current tab
1201 // window.location.hash = $active.attr('href');
1206 if (($index
- $prev_index
) >= 0) {
1207 $indicator
.velocity({"right": $tabs_width
- (($index
+ 1) * $tab_width
)}, { duration: 300, queue: false, easing: 'easeOutQuad'});
1208 $indicator
.velocity({"left": $index
* $tab_width
}, {duration: 300, queue: false, easing: 'easeOutQuad', delay: 90});
1212 $indicator
.velocity({"left": $index
* $tab_width
}, { duration: 300, queue: false, easing: 'easeOutQuad'});
1213 $indicator
.velocity({"right": $tabs_width
- (($index
+ 1) * $tab_width
)}, {duration: 300, queue: false, easing: 'easeOutQuad', delay: 90});
1216 // Prevent the anchor's default click action
1222 select_tab : function( id
) {
1223 this.find('a[href="#' + id
+ '"]').trigger('click');
1227 $.fn
.tabs = function(methodOrOptions
) {
1228 if ( methods
[methodOrOptions
] ) {
1229 return methods
[ methodOrOptions
].apply( this, Array
.prototype.slice
.call( arguments
, 1 ));
1230 } else if ( typeof methodOrOptions
=== 'object' || ! methodOrOptions
) {
1231 // Default to "init"
1232 return methods
.init
.apply( this, arguments
);
1234 $.error( 'Method ' + methodOrOptions
+ ' does not exist on jQuery.tooltip' );
1238 $(document
).ready(function(){
1239 $('ul.tabs').tabs();
1243 $.fn
.tooltip = function (options
) {
1247 counterInterval
= null,
1255 // Remove tooltip from the activator
1256 if (options
=== "remove") {
1257 this.each(function(){
1258 $('#' + $(this).attr('data-tooltip-id')).remove();
1263 options
= $.extend(defaults
, options
);
1266 return this.each(function(){
1267 var tooltipId
= Materialize
.guid();
1268 var origin
= $(this);
1269 origin
.attr('data-tooltip-id', tooltipId
);
1272 var tooltip_text
= $('<span></span>').text(origin
.attr('data-tooltip'));
1275 var newTooltip
= $('<div></div>');
1276 newTooltip
.addClass('material-tooltip').append(tooltip_text
)
1277 .appendTo($('body'))
1278 .attr('id', tooltipId
);
1280 var backdrop
= $('<div></div>').addClass('backdrop');
1281 backdrop
.appendTo(newTooltip
);
1282 backdrop
.css({ top: 0, left:0 });
1285 //Destroy previously binded events
1286 origin
.off('mouseenter.tooltip mouseleave.tooltip');
1289 'mouseenter.tooltip': function(e
) {
1290 var tooltip_delay
= origin
.data("delay");
1291 tooltip_delay
= (tooltip_delay
=== undefined || tooltip_delay
=== '') ? options
.delay : tooltip_delay
;
1293 counterInterval
= setInterval(function(){
1295 if (counter
>= tooltip_delay
&& started
=== false) {
1297 newTooltip
.css({ display: 'block', left: '0px', top: '0px' });
1300 newTooltip
.children('span').text(origin
.attr('data-tooltip'));
1302 // Tooltip positioning
1303 var originWidth
= origin
.outerWidth();
1304 var originHeight
= origin
.outerHeight();
1305 var tooltipPosition
= origin
.attr('data-position');
1306 var tooltipHeight
= newTooltip
.outerHeight();
1307 var tooltipWidth
= newTooltip
.outerWidth();
1308 var tooltipVerticalMovement
= '0px';
1309 var tooltipHorizontalMovement
= '0px';
1310 var scale_factor
= 8;
1312 if (tooltipPosition
=== "top") {
1315 top: origin
.offset().top
- tooltipHeight
- margin
,
1316 left: origin
.offset().left
+ originWidth
/2 - tooltipWidth
/2
1318 tooltipVerticalMovement
= '-10px';
1320 borderRadius: '14px 14px 0 0',
1321 transformOrigin: '50% 90%',
1322 marginTop: tooltipHeight
,
1323 marginLeft: (tooltipWidth
/2) - (backdrop
.width()/2)
1328 else if (tooltipPosition
=== "left") {
1330 top: origin
.offset().top
+ originHeight
/2 - tooltipHeight
/2,
1331 left: origin
.offset().left
- tooltipWidth
- margin
1333 tooltipHorizontalMovement
= '-10px';
1337 borderRadius: '14px 0 0 14px',
1338 transformOrigin: '95% 50%',
1339 marginTop: tooltipHeight
/2,
1340 marginLeft: tooltipWidth
1344 else if (tooltipPosition
=== "right") {
1346 top: origin
.offset().top
+ originHeight
/2 - tooltipHeight
/2,
1347 left: origin
.offset().left
+ originWidth
+ margin
1349 tooltipHorizontalMovement
= '+10px';
1353 borderRadius: '0 14px 14px 0',
1354 transformOrigin: '5% 50%',
1355 marginTop: tooltipHeight
/2,
1362 top: origin
.offset().top
+ origin
.outerHeight() + margin
,
1363 left: origin
.offset().left
+ originWidth
/2 - tooltipWidth
/2
1365 tooltipVerticalMovement
= '+10px';
1367 marginLeft: (tooltipWidth
/2) - (backdrop
.width()/2)
1371 // Calculate Scale to fill
1372 scale_factor
= tooltipWidth
/ 8;
1373 if (scale_factor
< 8) {
1376 if (tooltipPosition
=== "right" || tooltipPosition
=== "left") {
1377 scale_factor
= tooltipWidth
/ 10;
1378 if (scale_factor
< 6)
1382 newTooltip
.velocity({ marginTop: tooltipVerticalMovement
, marginLeft: tooltipHorizontalMovement
}, { duration: 350, queue: false })
1383 .velocity({opacity: 1}, {duration: 300, delay: 50, queue: false});
1384 backdrop
.css({ display: 'block' })
1385 .velocity({opacity:1},{duration: 55, delay: 0, queue: false})
1386 .velocity({scale: scale_factor
}, {duration: 300, delay: 0, queue: false, easing: 'easeInOutQuad'});
1389 }, 10); // End Interval
1393 'mouseleave.tooltip': function(){
1395 clearInterval(counterInterval
);
1399 newTooltip
.velocity({
1400 opacity: 0, marginTop: 0, marginLeft: 0}, { duration: 225, queue: false, delay: 225 }
1402 backdrop
.velocity({opacity: 0, scale: 1}, {
1404 delay: 275, queue: false,
1405 complete: function(){
1406 backdrop
.css('display', 'none');
1407 newTooltip
.css('display', 'none');
1415 $(document
).ready(function(){
1416 $('.tooltipped').tooltip();
1421 * http://fian.my.id/Waves
1423 * Copyright 2014 Alfiana E. Sibuea and other contributors
1424 * Released under the MIT license
1425 * https://github.com/fians/Waves/blob/master/LICENSE
1428 ;(function(window
) {
1431 var Waves
= Waves
|| {};
1432 var $$ = document
.querySelectorAll
.bind(document
);
1434 // Find exact position of element
1435 function isWindow(obj
) {
1436 return obj
!== null && obj
=== obj
.window
;
1439 function getWindow(elem
) {
1440 return isWindow(elem
) ? elem : elem
.nodeType
=== 9 && elem
.defaultView
;
1443 function offset(elem
) {
1445 box
= {top: 0, left: 0},
1446 doc
= elem
&& elem
.ownerDocument
;
1448 docElem
= doc
.documentElement
;
1450 if (typeof elem
.getBoundingClientRect
!== typeof undefined) {
1451 box
= elem
.getBoundingClientRect();
1453 win
= getWindow(doc
);
1455 top: box
.top
+ win
.pageYOffset
- docElem
.clientTop
,
1456 left: box
.left
+ win
.pageXOffset
- docElem
.clientLeft
1460 function convertStyle(obj
) {
1463 for (var a
in obj
) {
1464 if (obj
.hasOwnProperty(a
)) {
1465 style
+= (a
+ ':' + obj
[a
] + ';');
1477 show: function(e
, element
) {
1479 // Disable right click
1480 if (e
.button
=== 2) {
1484 var el
= element
|| this;
1487 var ripple
= document
.createElement('div');
1488 ripple
.className
= 'waves-ripple';
1489 el
.appendChild(ripple
);
1491 // Get click coordinate and element witdh
1492 var pos
= offset(el
);
1493 var relativeY
= (e
.pageY
- pos
.top
);
1494 var relativeX
= (e
.pageX
- pos
.left
);
1495 var scale
= 'scale('+((el
.clientWidth
/ 100) * 10)+')';
1497 // Support for touch devices
1498 if ('touches' in e
) {
1499 relativeY
= (e
.touches
[0].pageY
- pos
.top
);
1500 relativeX
= (e
.touches
[0].pageX
- pos
.left
);
1503 // Attach data to element
1504 ripple
.setAttribute('data-hold', Date
.now());
1505 ripple
.setAttribute('data-scale', scale
);
1506 ripple
.setAttribute('data-x', relativeX
);
1507 ripple
.setAttribute('data-y', relativeY
);
1509 // Set ripple position
1511 'top': relativeY
+'px',
1512 'left': relativeX
+'px'
1515 ripple
.className
= ripple
.className
+ ' waves-notransition';
1516 ripple
.setAttribute('style', convertStyle(rippleStyle
));
1517 ripple
.className
= ripple
.className
.replace('waves-notransition', '');
1520 rippleStyle
['-webkit-transform'] = scale
;
1521 rippleStyle
['-moz-transform'] = scale
;
1522 rippleStyle
['-ms-transform'] = scale
;
1523 rippleStyle
['-o-transform'] = scale
;
1524 rippleStyle
.transform
= scale
;
1525 rippleStyle
.opacity
= '1';
1527 rippleStyle
['-webkit-transition-duration'] = Effect
.duration
+ 'ms';
1528 rippleStyle
['-moz-transition-duration'] = Effect
.duration
+ 'ms';
1529 rippleStyle
['-o-transition-duration'] = Effect
.duration
+ 'ms';
1530 rippleStyle
['transition-duration'] = Effect
.duration
+ 'ms';
1532 rippleStyle
['-webkit-transition-timing-function'] = 'cubic-bezier(0.250, 0.460, 0.450, 0.940)';
1533 rippleStyle
['-moz-transition-timing-function'] = 'cubic-bezier(0.250, 0.460, 0.450, 0.940)';
1534 rippleStyle
['-o-transition-timing-function'] = 'cubic-bezier(0.250, 0.460, 0.450, 0.940)';
1535 rippleStyle
['transition-timing-function'] = 'cubic-bezier(0.250, 0.460, 0.450, 0.940)';
1537 ripple
.setAttribute('style', convertStyle(rippleStyle
));
1541 TouchHandler
.touchup(e
);
1544 var width
= el
.clientWidth
* 1.4;
1548 var ripples
= el
.getElementsByClassName('waves-ripple');
1549 if (ripples
.length
> 0) {
1550 ripple
= ripples
[ripples
.length
- 1];
1555 var relativeX
= ripple
.getAttribute('data-x');
1556 var relativeY
= ripple
.getAttribute('data-y');
1557 var scale
= ripple
.getAttribute('data-scale');
1559 // Get delay beetween mousedown and mouse leave
1560 var diff
= Date
.now() - Number(ripple
.getAttribute('data-hold'));
1561 var delay
= 350 - diff
;
1567 // Fade out ripple after delay
1568 setTimeout(function() {
1570 'top': relativeY
+'px',
1571 'left': relativeX
+'px',
1575 '-webkit-transition-duration': Effect
.duration
+ 'ms',
1576 '-moz-transition-duration': Effect
.duration
+ 'ms',
1577 '-o-transition-duration': Effect
.duration
+ 'ms',
1578 'transition-duration': Effect
.duration
+ 'ms',
1579 '-webkit-transform': scale
,
1580 '-moz-transform': scale
,
1581 '-ms-transform': scale
,
1582 '-o-transform': scale
,
1586 ripple
.setAttribute('style', convertStyle(style
));
1588 setTimeout(function() {
1590 el
.removeChild(ripple
);
1594 }, Effect
.duration
);
1598 // Little hack to make <input> can perform waves effect
1599 wrapInput: function(elements
) {
1600 for (var a
= 0; a
< elements
.length
; a
++) {
1601 var el
= elements
[a
];
1603 if (el
.tagName
.toLowerCase() === 'input') {
1604 var parent
= el
.parentNode
;
1606 // If input already have parent just pass through
1607 if (parent
.tagName
.toLowerCase() === 'i' && parent
.className
.indexOf('waves-effect') !== -1) {
1611 // Put element class and style to the specified parent
1612 var wrapper
= document
.createElement('i');
1613 wrapper
.className
= el
.className
+ ' waves-input-wrapper';
1615 var elementStyle
= el
.getAttribute('style');
1617 if (!elementStyle
) {
1621 wrapper
.setAttribute('style', elementStyle
);
1623 el
.className
= 'waves-button-input';
1624 el
.removeAttribute('style');
1626 // Put element as child
1627 parent
.replaceChild(wrapper
, el
);
1628 wrapper
.appendChild(el
);
1636 * Disable mousedown event for 500ms during and after touch
1638 var TouchHandler
= {
1639 /* uses an integer rather than bool so there's no issues with
1640 * needing to clear timeouts if another touch event occurred
1641 * within the 500ms. Cannot mouseup between touchstart and
1642 * touchend, nor in the 500ms after touchend. */
1644 allowEvent: function(e
) {
1647 if (e
.type
=== 'touchstart') {
1648 TouchHandler
.touches
+= 1; //push
1649 } else if (e
.type
=== 'touchend' || e
.type
=== 'touchcancel') {
1650 setTimeout(function() {
1651 if (TouchHandler
.touches
> 0) {
1652 TouchHandler
.touches
-= 1; //pop after 500ms
1655 } else if (e
.type
=== 'mousedown' && TouchHandler
.touches
> 0) {
1661 touchup: function(e
) {
1662 TouchHandler
.allowEvent(e
);
1668 * Delegated click handler for .waves-effect element.
1669 * returns null when .waves-effect element not in "click tree"
1671 function getWavesEffectElement(e
) {
1672 if (TouchHandler
.allowEvent(e
) === false) {
1677 var target
= e
.target
|| e
.srcElement
;
1679 while (target
.parentElement
!== null) {
1680 if (!(target
instanceof SVGElement
) && target
.className
.indexOf('waves-effect') !== -1) {
1683 } else if (target
.classList
.contains('waves-effect')) {
1687 target
= target
.parentElement
;
1694 * Bubble the click and show effect if .waves-effect elem was found
1696 function showEffect(e
) {
1697 var element
= getWavesEffectElement(e
);
1699 if (element
!== null) {
1700 Effect
.show(e
, element
);
1702 if ('ontouchstart' in window
) {
1703 element
.addEventListener('touchend', Effect
.hide
, false);
1704 element
.addEventListener('touchcancel', Effect
.hide
, false);
1707 element
.addEventListener('mouseup', Effect
.hide
, false);
1708 element
.addEventListener('mouseleave', Effect
.hide
, false);
1712 Waves
.displayEffect = function(options
) {
1713 options
= options
|| {};
1715 if ('duration' in options
) {
1716 Effect
.duration
= options
.duration
;
1719 //Wrap input inside <i> tag
1720 Effect
.wrapInput($$('.waves-effect'));
1722 if ('ontouchstart' in window
) {
1723 document
.body
.addEventListener('touchstart', showEffect
, false);
1726 document
.body
.addEventListener('mousedown', showEffect
, false);
1730 * Attach Waves to an input element (or any element which doesn't
1731 * bubble mouseup/mousedown events).
1732 * Intended to be used with dynamically loaded forms/inputs, or
1733 * where the user doesn't want a delegated click handler.
1735 Waves
.attach = function(element
) {
1736 //FUTURE: automatically add waves classes and allow users
1737 // to specify them with an options param? Eg. light/classic/button
1738 if (element
.tagName
.toLowerCase() === 'input') {
1739 Effect
.wrapInput([element
]);
1740 element
= element
.parentElement
;
1743 if ('ontouchstart' in window
) {
1744 element
.addEventListener('touchstart', showEffect
, false);
1747 element
.addEventListener('mousedown', showEffect
, false);
1750 window
.Waves
= Waves
;
1752 document
.addEventListener('DOMContentLoaded', function() {
1753 Waves
.displayEffect();
1757 ;Materialize
.toast = function (message
, displayLength
, className
, completeCallback
) {
1758 className
= className
|| "";
1760 var container
= document
.getElementById('toast-container');
1762 // Create toast container if it does not exist
1763 if (container
=== null) {
1764 // create notification container
1765 container
= document
.createElement('div');
1766 container
.id
= 'toast-container';
1767 document
.body
.appendChild(container
);
1770 // Select and append toast
1771 var newToast
= createToast(message
);
1773 // only append toast if message is not undefined
1775 container
.appendChild(newToast
);
1778 newToast
.style
.top
= '35px';
1779 newToast
.style
.opacity
= 0;
1782 Vel(newToast
, { "top" : "0px", opacity: 1 }, {duration: 300,
1783 easing: 'easeOutCubic',
1786 // Allows timer to be pause while being panned
1787 var timeLeft
= displayLength
;
1788 var counterInterval
= setInterval (function(){
1791 if (newToast
.parentNode
=== null)
1792 window
.clearInterval(counterInterval
);
1794 // If toast is not being dragged, decrease its time remaining
1795 if (!newToast
.classList
.contains('panning')) {
1799 if (timeLeft
<= 0) {
1800 // Animate toast out
1801 Vel(newToast
, {"opacity": 0, marginTop: '-40px'}, { duration: 375,
1802 easing: 'easeOutExpo',
1804 complete: function(){
1805 // Call the optional callback
1806 if(typeof(completeCallback
) === "function")
1808 // Remove toast after it times out
1809 this[0].parentNode
.removeChild(this[0]);
1812 window
.clearInterval(counterInterval
);
1818 function createToast(html
) {
1821 var toast
= document
.createElement('div');
1822 toast
.classList
.add('toast');
1824 var classes
= className
.split(' ');
1826 for (var i
= 0, count
= classes
.length
; i
< count
; i
++) {
1827 toast
.classList
.add(classes
[i
]);
1830 // If type of parameter is HTML Element
1831 if ( typeof HTMLElement
=== "object" ? html
instanceof HTMLElement : html
&& typeof html
=== "object" && html
!== null && html
.nodeType
=== 1 && typeof html
.nodeName
==="string"
1833 toast
.appendChild(html
);
1835 else if (html
instanceof jQuery
) {
1836 // Check if it is jQuery object
1837 toast
.appendChild(html
[0]);
1841 toast
.innerHTML
= html
;
1844 var hammerHandler
= new Hammer(toast
, {prevent_default: false});
1845 hammerHandler
.on('pan', function(e
) {
1846 var deltaX
= e
.deltaX
;
1847 var activationDistance
= 80;
1849 // Change toast state
1850 if (!toast
.classList
.contains('panning')){
1851 toast
.classList
.add('panning');
1854 var opacityPercent
= 1-Math
.abs(deltaX
/ activationDistance
);
1855 if (opacityPercent
< 0)
1858 Vel(toast
, {left: deltaX
, opacity: opacityPercent
}, {duration: 50, queue: false, easing: 'easeOutQuad'});
1862 hammerHandler
.on('panend', function(e
) {
1863 var deltaX
= e
.deltaX
;
1864 var activationDistance
= 80;
1866 // If toast dragged past activation point
1867 if (Math
.abs(deltaX
) > activationDistance
) {
1868 Vel(toast
, {marginTop: '-40px'}, { duration: 375,
1869 easing: 'easeOutExpo',
1871 complete: function(){
1872 if(typeof(completeCallback
) === "function") {
1875 toast
.parentNode
.removeChild(toast
);
1880 toast
.classList
.remove('panning');
1881 // Put toast back into original position
1882 Vel(toast
, { left: 0, opacity: 1 }, { duration: 300,
1883 easing: 'easeOutExpo',
1896 init : function(options
) {
1902 options
= $.extend(defaults
, options
);
1904 $(this).each(function(){
1905 var $this = $(this);
1906 var menu_id
= $("#"+ $this.attr('data-activates'));
1909 if (options
.menuWidth
!= 240) {
1910 menu_id
.css('width', options
.menuWidth
);
1914 var dragTarget
= $('<div class="drag-target"></div>');
1915 $('body').append(dragTarget
);
1917 if (options
.edge
== 'left') {
1918 menu_id
.css('left', -1 * (options
.menuWidth
+ 10));
1919 dragTarget
.css({'left': 0}); // Add Touch Area
1922 menu_id
.addClass('right-aligned') // Change text-alignment to right
1923 .css('right', -1 * (options
.menuWidth
+ 10))
1925 dragTarget
.css({'right': 0}); // Add Touch Area
1928 // If fixed sidenav, bring menu out
1929 if (menu_id
.hasClass('fixed')) {
1930 if (window
.innerWidth
> 992) {
1931 menu_id
.css('left', 0);
1935 // Window resize to reset on large screens fixed
1936 if (menu_id
.hasClass('fixed')) {
1937 $(window
).resize( function() {
1938 if (window
.innerWidth
> 992) {
1939 // Close menu if window is resized bigger than 992 and user has fixed sidenav
1940 if ($('#sidenav-overlay').css('opacity') !== 0 && menuOut
) {
1944 menu_id
.removeAttr('style');
1945 menu_id
.css('width', options
.menuWidth
);
1948 else if (menuOut
=== false){
1949 if (options
.edge
=== 'left')
1950 menu_id
.css('left', -1 * (options
.menuWidth
+ 10));
1952 menu_id
.css('right', -1 * (options
.menuWidth
+ 10));
1958 // if closeOnClick, then add close event for all a tags in side sideNav
1959 if (options
.closeOnClick
=== true) {
1960 menu_id
.on("click.itemclick", "a:not(.collapsible-header)", function(){
1965 function removeMenu(restoreNav
) {
1969 // Reenable scrolling
1970 $('body').css('overflow', '');
1972 $('#sidenav-overlay').velocity({opacity: 0}, {duration: 200, queue: false, easing: 'easeOutQuad',
1973 complete: function() {
1976 if (options
.edge
=== 'left') {
1977 // Reset phantom div
1978 dragTarget
.css({width: '', right: '', left: '0'});
1980 {left: -1 * (options
.menuWidth
+ 10)},
1983 easing: 'easeOutCubic',
1984 complete: function() {
1985 if (restoreNav
=== true) {
1986 // Restore Fixed sidenav
1987 menu_id
.removeAttr('style');
1988 menu_id
.css('width', options
.menuWidth
);
1995 // Reset phantom div
1996 dragTarget
.css({width: '', right: '0', left: ''});
1998 {right: -1 * (options
.menuWidth
+ 10)},
2001 easing: 'easeOutCubic',
2002 complete: function() {
2003 if (restoreNav
=== true) {
2004 // Restore Fixed sidenav
2005 menu_id
.removeAttr('style');
2006 menu_id
.css('width', options
.menuWidth
);
2016 var panning
= false;
2017 var menuOut
= false;
2019 dragTarget
.on('click', function(){
2024 prevent_default: false
2025 }).bind('pan', function(e
) {
2027 if (e
.gesture
.pointerType
== "touch") {
2029 var direction
= e
.gesture
.direction
;
2030 var x
= e
.gesture
.center
.x
;
2031 var y
= e
.gesture
.center
.y
;
2032 var velocityX
= e
.gesture
.velocityX
;
2034 // Disable Scrolling
2035 $('body').css('overflow', 'hidden');
2037 // If overlay does not exist, create one and if it is clicked, close menu
2038 if ($('#sidenav-overlay').length
=== 0) {
2039 var overlay
= $('<div id="sidenav-overlay"></div>');
2040 overlay
.css('opacity', 0).click( function(){
2043 $('body').append(overlay
);
2046 // Keep within boundaries
2047 if (options
.edge
=== 'left') {
2048 if (x
> options
.menuWidth
) { x
= options
.menuWidth
; }
2049 else if (x
< 0) { x
= 0; }
2052 if (options
.edge
=== 'left') {
2054 if (x
< (options
.menuWidth
/ 2)) { menuOut
= false; }
2056 else if (x
>= (options
.menuWidth
/ 2)) { menuOut
= true; }
2058 menu_id
.css('left', (x
- options
.menuWidth
));
2062 if (x
< (window
.innerWidth
- options
.menuWidth
/ 2)) {
2066 else if (x
>= (window
.innerWidth
- options
.menuWidth
/ 2)) {
2069 var rightPos
= -1 *(x
- options
.menuWidth
/ 2);
2074 menu_id
.css('right', rightPos
);
2080 // Percentage overlay
2082 if (options
.edge
=== 'left') {
2083 overlayPerc
= x
/ options
.menuWidth
;
2084 $('#sidenav-overlay').velocity({opacity: overlayPerc
}, {duration: 50, queue: false, easing: 'easeOutQuad'});
2087 overlayPerc
= Math
.abs((x
- window
.innerWidth
) / options
.menuWidth
);
2088 $('#sidenav-overlay').velocity({opacity: overlayPerc
}, {duration: 50, queue: false, easing: 'easeOutQuad'});
2092 }).bind('panend', function(e
) {
2094 if (e
.gesture
.pointerType
== "touch") {
2095 var velocityX
= e
.gesture
.velocityX
;
2097 if (options
.edge
=== 'left') {
2098 // If velocityX <= 0.3 then the user is flinging the menu closed so ignore menuOut
2099 if ((menuOut
&& velocityX
<= 0.3) || velocityX
< -0.5) {
2100 menu_id
.velocity({left: 0}, {duration: 300, queue: false, easing: 'easeOutQuad'});
2101 $('#sidenav-overlay').velocity({opacity: 1 }, {duration: 50, queue: false, easing: 'easeOutQuad'});
2102 dragTarget
.css({width: '50%', right: 0, left: ''});
2104 else if (!menuOut
|| velocityX
> 0.3) {
2106 $('body').css('overflow', '');
2107 // Slide menu closed
2108 menu_id
.velocity({left: -1 * (options
.menuWidth
+ 10)}, {duration: 200, queue: false, easing: 'easeOutQuad'});
2109 $('#sidenav-overlay').velocity({opacity: 0 }, {duration: 200, queue: false, easing: 'easeOutQuad',
2110 complete: function () {
2113 dragTarget
.css({width: '10px', right: '', left: 0});
2117 if ((menuOut
&& velocityX
>= -0.3) || velocityX
> 0.5) {
2118 menu_id
.velocity({right: 0}, {duration: 300, queue: false, easing: 'easeOutQuad'});
2119 $('#sidenav-overlay').velocity({opacity: 1 }, {duration: 50, queue: false, easing: 'easeOutQuad'});
2120 dragTarget
.css({width: '50%', right: '', left: 0});
2122 else if (!menuOut
|| velocityX
< -0.3) {
2124 $('body').css('overflow', '');
2125 // Slide menu closed
2126 menu_id
.velocity({right: -1 * (options
.menuWidth
+ 10)}, {duration: 200, queue: false, easing: 'easeOutQuad'});
2127 $('#sidenav-overlay').velocity({opacity: 0 }, {duration: 200, queue: false, easing: 'easeOutQuad',
2128 complete: function () {
2131 dragTarget
.css({width: '10px', right: 0, left: ''});
2138 $this.click(function() {
2139 if (menuOut
=== true) {
2146 // Disable Scrolling
2147 $('body').css('overflow', 'hidden');
2148 // Push current drag target on top of DOM tree
2149 $('body').append(dragTarget
);
2151 if (options
.edge
=== 'left') {
2152 dragTarget
.css({width: '50%', right: 0, left: ''});
2153 menu_id
.velocity({left: 0}, {duration: 300, queue: false, easing: 'easeOutQuad'});
2156 dragTarget
.css({width: '50%', right: '', left: 0});
2157 menu_id
.velocity({right: 0}, {duration: 300, queue: false, easing: 'easeOutQuad'});
2158 menu_id
.css('left','');
2161 var overlay
= $('<div id="sidenav-overlay"></div>');
2162 overlay
.css('opacity', 0)
2167 overlay
.velocity({opacity: 0}, {duration: 300, queue: false, easing: 'easeOutQuad',
2168 complete: function() {
2173 $('body').append(overlay
);
2174 overlay
.velocity({opacity: 1}, {duration: 300, queue: false, easing: 'easeOutQuad',
2175 complete: function () {
2189 this.trigger('click');
2192 $('#sidenav-overlay').trigger('click');
2197 $.fn
.sideNav = function(methodOrOptions
) {
2198 if ( methods
[methodOrOptions
] ) {
2199 return methods
[ methodOrOptions
].apply( this, Array
.prototype.slice
.call( arguments
, 1 ));
2200 } else if ( typeof methodOrOptions
=== 'object' || ! methodOrOptions
) {
2201 // Default to "init"
2202 return methods
.init
.apply( this, arguments
);
2204 $.error( 'Method ' + methodOrOptions
+ ' does not exist on jQuery.sideNav' );
2209 * Extend jquery with a scrollspy plugin.
2210 * This watches the window scroll and fires events when elements are scrolled into viewport.
2212 * throttle() and getTime() taken from Underscore.js
2213 * https://github.com/jashkenas/underscore
2215 * @author Copyright 2013 John Smart
2216 * @license https://raw.github.com/thesmart/jquery-scrollspy/master/LICENSE
2217 * @see https://github.com/thesmart
2222 var jWindow
= $(window
);
2224 var elementsInView
= [];
2225 var isSpying
= false;
2236 * Find elements that are within the boundary
2237 * @param {number} top
2238 * @param {number} right
2239 * @param {number} bottom
2240 * @param {number} left
2241 * @return {jQuery} A collection of elements
2243 function findElements(top
, right
, bottom
, left
) {
2245 $.each(elements
, function(i
, element
) {
2246 if (element
.height() > 0) {
2247 var elTop
= element
.offset().top
,
2248 elLeft
= element
.offset().left
,
2249 elRight
= elLeft
+ element
.width(),
2250 elBottom
= elTop
+ element
.height();
2252 var isIntersect
= !(elLeft
> right
||
2268 * Called when the user scrolls the window
2270 function onScroll() {
2274 // viewport rectangle
2275 var top
= jWindow
.scrollTop(),
2276 left
= jWindow
.scrollLeft(),
2277 right
= left
+ jWindow
.width(),
2278 bottom
= top
+ jWindow
.height();
2280 // determine which elements are in view
2281 // + 60 accounts for fixed nav
2282 var intersections
= findElements(top
+offset
.top
+ 200, right
+offset
.right
, bottom
+offset
.bottom
, left
+offset
.left
);
2283 $.each(intersections
, function(i
, element
) {
2285 var lastTick
= element
.data('scrollSpy:ticks');
2286 if (typeof lastTick
!= 'number') {
2287 // entered into view
2288 element
.triggerHandler('scrollSpy:enter');
2292 element
.data('scrollSpy:ticks', ticks
);
2295 // determine which elements are no longer in view
2296 $.each(elementsInView
, function(i
, element
) {
2297 var lastTick
= element
.data('scrollSpy:ticks');
2298 if (typeof lastTick
== 'number' && lastTick
!== ticks
) {
2300 element
.triggerHandler('scrollSpy:exit');
2301 element
.data('scrollSpy:ticks', null);
2305 // remember elements in view for next tick
2306 elementsInView
= intersections
;
2310 * Called when window is resized
2312 function onWinSize() {
2313 jWindow
.trigger('scrollSpy:winSize');
2318 * @license https://raw.github.com/jashkenas/underscore/master/LICENSE
2322 var getTime
= (Date
.now
|| function () {
2323 return new Date().getTime();
2327 * Returns a function, that, when invoked, will only be triggered at most once
2328 * during a given window of time. Normally, the throttled function will run
2329 * as much as it can, without ever going more than once per `wait` duration;
2330 * but if you'd like to disable the execution on the leading edge, pass
2331 * `{leading: false}`. To disable execution on the trailing edge, ditto.
2332 * @license https://raw.github.com/jashkenas/underscore/master/LICENSE
2333 * @param {function} func
2334 * @param {number} wait
2335 * @param {Object=} options
2336 * @returns {Function}
2338 function throttle(func
, wait
, options
) {
2339 var context
, args
, result
;
2342 options
|| (options
= {});
2343 var later = function () {
2344 previous
= options
.leading
=== false ? 0 : getTime();
2346 result
= func
.apply(context
, args
);
2347 context
= args
= null;
2349 return function () {
2350 var now
= getTime();
2351 if (!previous
&& options
.leading
=== false) previous
= now
;
2352 var remaining
= wait
- (now
- previous
);
2355 if (remaining
<= 0) {
2356 clearTimeout(timeout
);
2359 result
= func
.apply(context
, args
);
2360 context
= args
= null;
2361 } else if (!timeout
&& options
.trailing
!== false) {
2362 timeout
= setTimeout(later
, remaining
);
2369 * Enables ScrollSpy using a selector
2370 * @param {jQuery|string} selector The elements collection, or a selector
2371 * @param {Object=} options Optional.
2372 throttle : number -> scrollspy throttling. Default: 100 ms
2373 offsetTop : number -> offset from top. Default: 0
2374 offsetRight : number -> offset from right. Default: 0
2375 offsetBottom : number -> offset from bottom. Default: 0
2376 offsetLeft : number -> offset from left. Default: 0
2379 $.scrollSpy = function(selector
, options
) {
2381 selector
= $(selector
);
2382 selector
.each(function(i
, element
) {
2383 elements
.push($(element
));
2384 $(element
).data("scrollSpy:id", i
);
2385 // Smooth scroll to section
2386 $('a[href=#' + $(element
).attr('id') + ']').click(function(e
) {
2388 var offset
= $(this.hash
).offset().top
+ 1;
2390 // offset - 200 allows elements near bottom of page to scroll
2392 $('html, body').animate({ scrollTop: offset
- 200 }, {duration: 400, queue: false, easing: 'easeOutCubic'});
2396 options
= options
|| {
2400 offset
.top
= options
.offsetTop
|| 0;
2401 offset
.right
= options
.offsetRight
|| 0;
2402 offset
.bottom
= options
.offsetBottom
|| 0;
2403 offset
.left
= options
.offsetLeft
|| 0;
2405 var throttledScroll
= throttle(onScroll
, options
.throttle
|| 100);
2406 var readyScroll = function(){
2407 $(document
).ready(throttledScroll
);
2411 jWindow
.on('scroll', readyScroll
);
2412 jWindow
.on('resize', readyScroll
);
2416 // perform a scan once, after current execution context, and after dom is ready
2417 setTimeout(readyScroll
, 0);
2420 selector
.on('scrollSpy:enter', function() {
2421 visible
= $.grep(visible
, function(value
) {
2422 return value
.height() != 0;
2425 var $this = $(this);
2428 $('a[href=#' + visible
[0].attr('id') + ']').removeClass('active');
2429 if ($this.data('scrollSpy:id') < visible
[0].data('scrollSpy:id')) {
2430 visible
.unshift($(this));
2433 visible
.push($(this));
2437 visible
.push($(this));
2441 $('a[href=#' + visible
[0].attr('id') + ']').addClass('active');
2443 selector
.on('scrollSpy:exit', function() {
2444 visible
= $.grep(visible
, function(value
) {
2445 return value
.height() != 0;
2449 $('a[href=#' + visible
[0].attr('id') + ']').removeClass('active');
2450 var $this = $(this);
2451 visible
= $.grep(visible
, function(value
) {
2452 return value
.attr('id') != $this.attr('id');
2454 if (visible
[0]) { // Check if empty
2455 $('a[href=#' + visible
[0].attr('id') + ']').addClass('active');
2464 * Listen for window resize events
2465 * @param {Object=} options Optional. Set { throttle: number } to change throttling. Default: 100 ms
2466 * @returns {jQuery} $(window)
2468 $.winSizeSpy = function(options
) {
2469 $.winSizeSpy = function() { return jWindow
; }; // lock from multiple calls
2470 options
= options
|| {
2473 return jWindow
.on('resize', throttle(onWinSize
, options
.throttle
|| 100));
2477 * Enables ScrollSpy on a collection of elements
2478 * e.g. $('.scrollSpy').scrollSpy()
2479 * @param {Object=} options Optional.
2480 throttle : number -> scrollspy throttling. Default: 100 ms
2481 offsetTop : number -> offset from top. Default: 0
2482 offsetRight : number -> offset from right. Default: 0
2483 offsetBottom : number -> offset from bottom. Default: 0
2484 offsetLeft : number -> offset from left. Default: 0
2487 $.fn
.scrollSpy = function(options
) {
2488 return $.scrollSpy($(this), options
);
2491 })(jQuery
);;(function ($) {
2492 $(document
).ready(function() {
2494 // Function to update labels of text fields
2495 Materialize
.updateTextFields = function() {
2496 var input_selector
= 'input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=number], input[type=search], textarea';
2497 $(input_selector
).each(function(index
, element
) {
2498 if ($(element
).val().length
> 0 || $(this).attr('placeholder') !== undefined || $(element
)[0].validity
.badInput
=== true) {
2499 $(this).siblings('label').addClass('active');
2502 $(this).siblings('label, i').removeClass('active');
2507 // Text based inputs
2508 var input_selector
= 'input[type=text], input[type=password], input[type=email], input[type=url], input[type=tel], input[type=number], input[type=search], textarea';
2510 // Handle HTML5 autofocus
2511 $('input[autofocus]').siblings('label, i').addClass('active');
2513 // Add active if form auto complete
2514 $(document
).on('change', input_selector
, function () {
2515 if($(this).val().length
!== 0 || $(this).attr('placeholder') !== undefined) {
2516 $(this).siblings('label').addClass('active');
2518 validate_field($(this));
2521 // Add active if input element has been pre-populated on document ready
2522 $(document
).ready(function() {
2523 Materialize
.updateTextFields();
2526 // HTML DOM FORM RESET handling
2527 $(document
).on('reset', function(e
) {
2528 var formReset
= $(e
.target
);
2529 if (formReset
.is('form')) {
2530 formReset
.find(input_selector
).removeClass('valid').removeClass('invalid');
2531 formReset
.find(input_selector
).each(function () {
2532 if ($(this).attr('value') === '') {
2533 $(this).siblings('label, i').removeClass('active');
2538 formReset
.find('select.initialized').each(function () {
2539 var reset_text
= formReset
.find('option[selected]').text();
2540 formReset
.siblings('input.select-dropdown').val(reset_text
);
2545 // Add active when element has focus
2546 $(document
).on('focus', input_selector
, function () {
2547 $(this).siblings('label, i').addClass('active');
2550 $(document
).on('blur', input_selector
, function () {
2551 var $inputElement
= $(this);
2552 if ($inputElement
.val().length
=== 0 && $inputElement
[0].validity
.badInput
!== true && $inputElement
.attr('placeholder') === undefined) {
2553 $inputElement
.siblings('label, i').removeClass('active');
2556 if ($inputElement
.val().length
=== 0 && $inputElement
[0].validity
.badInput
!== true && $inputElement
.attr('placeholder') !== undefined) {
2557 $inputElement
.siblings('i').removeClass('active');
2559 validate_field($inputElement
);
2562 window
.validate_field = function(object
) {
2563 var hasLength
= object
.attr('length') !== undefined;
2564 var lenAttr
= parseInt(object
.attr('length'));
2565 var len
= object
.val().length
;
2567 if (object
.val().length
=== 0 && object
[0].validity
.badInput
=== false) {
2568 if (object
.hasClass('validate')) {
2569 object
.removeClass('valid');
2570 object
.removeClass('invalid');
2574 if (object
.hasClass('validate')) {
2575 // Check for character counter attributes
2576 if ((object
.is(':valid') && hasLength
&& (len
<= lenAttr
)) || (object
.is(':valid') && !hasLength
)) {
2577 object
.removeClass('invalid');
2578 object
.addClass('valid');
2581 object
.removeClass('valid');
2582 object
.addClass('invalid');
2589 // Textarea Auto Resize
2590 var hiddenDiv
= $('.hiddendiv').first();
2591 if (!hiddenDiv
.length
) {
2592 hiddenDiv
= $('<div class="hiddendiv common"></div>');
2593 $('body').append(hiddenDiv
);
2595 var text_area_selector
= '.materialize-textarea';
2597 function textareaAutoResize($textarea
) {
2598 // Set font properties of hiddenDiv
2600 var fontFamily
= $textarea
.css('font-family');
2601 var fontSize
= $textarea
.css('font-size');
2603 if (fontSize
) { hiddenDiv
.css('font-size', fontSize
); }
2604 if (fontFamily
) { hiddenDiv
.css('font-family', fontFamily
); }
2606 if ($textarea
.attr('wrap') === "off") {
2607 hiddenDiv
.css('overflow-wrap', "normal")
2608 .css('white-space', "pre");
2614 hiddenDiv
.text($textarea
.val() + '\n');
2615 var content
= hiddenDiv
.html().replace(/\n/g, '<br>');
2616 hiddenDiv
.html(content
);
2619 // When textarea is hidden, width goes crazy.
2620 // Approximate with half of window size
2622 if ($textarea
.is(':visible')) {
2623 hiddenDiv
.css('width', $textarea
.width());
2626 hiddenDiv
.css('width', $(window
).width()/2);
2629 $textarea
.css('height', hiddenDiv
.height());
2632 $(text_area_selector
).each(function () {
2633 var $textarea
= $(this);
2634 if ($textarea
.val().length
) {
2635 textareaAutoResize($textarea
);
2639 $('body').on('keyup keydown autoresize', text_area_selector
, function () {
2640 textareaAutoResize($(this));
2646 $(document
).on('change', '.file-field input[type="file"]', function () {
2647 var file_field
= $(this).closest('.file-field');
2648 var path_input
= file_field
.find('input.file-path');
2649 var files
= $(this)[0].files
;
2650 var file_names
= [];
2651 for (var i
= 0; i
< files
.length
; i
++) {
2652 file_names
.push(files
[i
].name
);
2654 path_input
.val(file_names
.join(", "));
2655 path_input
.trigger('change');
2663 var range_type
= 'input[type=range]';
2664 var range_mousedown
= false;
2667 $(range_type
).each(function () {
2668 var thumb
= $('<span class="thumb"><span class="value"></span></span>');
2669 $(this).after(thumb
);
2672 var range_wrapper
= '.range-field';
2673 $(document
).on('change', range_type
, function(e
) {
2674 var thumb
= $(this).siblings('.thumb');
2675 thumb
.find('.value').html($(this).val());
2678 $(document
).on('input mousedown touchstart', range_type
, function(e
) {
2679 var thumb
= $(this).siblings('.thumb');
2681 // If thumb indicator does not exist yet, create it
2682 if (thumb
.length
<= 0) {
2683 thumb
= $('<span class="thumb"><span class="value"></span></span>');
2684 $(this).append(thumb
);
2687 // Set indicator value
2688 thumb
.find('.value').html($(this).val());
2690 range_mousedown
= true;
2691 $(this).addClass('active');
2693 if (!thumb
.hasClass('active')) {
2694 thumb
.velocity({ height: "30px", width: "30px", top: "-20px", marginLeft: "-15px"}, { duration: 300, easing: 'easeOutExpo' });
2697 if(e
.pageX
=== undefined || e
.pageX
=== null){//mobile
2698 left
= e
.originalEvent
.touches
[0].pageX
- $(this).offset().left
;
2701 left
= e
.pageX
- $(this).offset().left
;
2703 var width
= $(this).outerWidth();
2708 else if (left
> width
) {
2711 thumb
.addClass('active').css('left', left
);
2712 thumb
.find('.value').html($(this).val());
2717 $(document
).on('mouseup touchend', range_wrapper
, function() {
2718 range_mousedown
= false;
2719 $(this).removeClass('active');
2722 $(document
).on('mousemove touchmove', range_wrapper
, function(e
) {
2723 var thumb
= $(this).children('.thumb');
2725 if (range_mousedown
) {
2726 if (!thumb
.hasClass('active')) {
2727 thumb
.velocity({ height: '30px', width: '30px', top: '-20px', marginLeft: '-15px'}, { duration: 300, easing: 'easeOutExpo' });
2729 if (e
.pageX
=== undefined || e
.pageX
=== null) { //mobile
2730 left
= e
.originalEvent
.touches
[0].pageX
- $(this).offset().left
;
2733 left
= e
.pageX
- $(this).offset().left
;
2735 var width
= $(this).outerWidth();
2740 else if (left
> width
) {
2743 thumb
.addClass('active').css('left', left
);
2744 thumb
.find('.value').html(thumb
.siblings(range_type
).val());
2748 $(document
).on('mouseout touchleave', range_wrapper
, function() {
2749 if (!range_mousedown
) {
2751 var thumb
= $(this).children('.thumb');
2753 if (thumb
.hasClass('active')) {
2754 thumb
.velocity({ height: '0', width: '0', top: '10px', marginLeft: '-6px'}, { duration: 100 });
2756 thumb
.removeClass('active');
2760 }); // End of $(document).ready
2766 $.fn
.material_select = function (callback
) {
2767 $(this).each(function(){
2770 if ( $select
.hasClass('browser-default')) {
2771 return; // Continue to next (return false breaks out of entire loop)
2774 // Tear down structure if Select needs to be rebuilt
2775 var lastID
= $select
.data('select-id');
2777 $select
.parent().find('span.caret').remove();
2778 $select
.parent().find('input').remove();
2781 $('ul#select-options-'+lastID
).remove();
2784 // If destroying the select, remove the selelct-id and reset it to it's uninitialized state.
2785 if(callback
=== 'destroy') {
2786 $select
.data('select-id', null).removeClass('initialized');
2790 var uniqueID
= Materialize
.guid();
2791 $select
.data('select-id', uniqueID
);
2792 var wrapper
= $('<div class="select-wrapper"></div>');
2793 wrapper
.addClass($select
.attr('class'));
2794 var options
= $('<ul id="select-options-' + uniqueID
+'" class="dropdown-content select-dropdown"></ul>');
2795 var selectOptions
= $select
.children('option');
2798 if ($select
.find('option:selected') !== undefined) {
2799 label
= $select
.find('option:selected');
2802 label
= options
.first();
2806 // Create Dropdown structure
2807 selectOptions
.each(function () {
2808 // Add disabled attr if disabled
2809 options
.append($('<li class="' + (($(this).is(':disabled')) ? 'disabled' : '') + '"><span>' + $(this).html() + '</span></li>'));
2813 options
.find('li').each(function (i
) {
2814 var $curr_select
= $select
;
2815 $(this).click(function () {
2816 // Check if option element is disabled
2817 if (!$(this).hasClass('disabled')) {
2818 $curr_select
.find('option').eq(i
).prop('selected', true);
2819 // Trigger onchange() event
2820 $curr_select
.trigger('change');
2821 $curr_select
.siblings('input.select-dropdown').val($(this).text());
2822 if (typeof callback
!== 'undefined') callback();
2829 $select
.wrap(wrapper
);
2830 // Add Select Display Element
2831 var dropdownIcon
= $('<span class="caret">▼</span>');
2832 if ( $select
.is(':disabled') )
2833 dropdownIcon
.addClass('disabled');
2835 // escape double quotes
2836 var sanitizedLabelHtml
= label
.html().replace(/"/g, '"');
2838 var $newSelect = $('<input type="text
" class="select
-dropdown
" readonly="true" ' + (($select.is(':disabled')) ? 'disabled' : '') + ' data-activates="select
-options
-' + uniqueID +'" value="'+ sanitizedLabelHtml +'"/>');
2839 $select.before($newSelect);
2840 $newSelect.before(dropdownIcon);
2842 $('body').append(options);
2843 // Check if section element is disabled
2844 if (!$select.is(':disabled')) {
2845 $newSelect.dropdown({"hover
": false});
2849 if ($select.attr('tabindex')) {
2850 $($newSelect[0]).attr('tabindex', $select.attr('tabindex'));
2853 $select.addClass('initialized');
2855 $newSelect.on('focus', function(){
2856 $(this).trigger('open');
2857 label = $(this).val();
2858 selectedOption = options.find('li').filter(function() {
2859 return $(this).text().toLowerCase() === label.toLowerCase();
2861 activateOption(options, selectedOption);
2864 $newSelect.on('blur', function(){
2865 $(this).trigger('close');
2868 // Make option as selected and scroll to selected position
2869 activateOption = function(collection, newOption) {
2870 collection.find('li.active').removeClass('active');
2871 $(newOption).addClass('active');
2872 collection.scrollTo(newOption);
2875 // Allow user to search by typing
2876 // this array is cleared after 1 second
2879 onKeyDown = function(event){
2880 // TAB - switch to another input
2881 if(event.which == 9){
2882 $newSelect.trigger('close');
2886 // ARROW DOWN WHEN SELECT IS CLOSED - open select options
2887 if(event.which == 40 && !options.is(":visible
")){
2888 $newSelect.trigger('open');
2892 // ENTER WHEN SELECT IS CLOSED - submit form
2893 if(event.which == 13 && !options.is(":visible
")){
2897 event.preventDefault();
2899 // CASE WHEN USER TYPE LETTERS
2900 letter = String.fromCharCode(event.which).toLowerCase();
2901 var nonLetters = [9,13,27,38,40];
2902 if (letter && (nonLetters.indexOf(event.which) === -1)){
2903 filterQuery.push(letter);
2905 string = filterQuery.join("");
2907 newOption = options.find('li').filter(function() {
2908 return $(this).text().toLowerCase().indexOf(string) === 0;
2912 activateOption(options, newOption);
2916 // ENTER - select option and close when select options are opened
2917 if(event.which == 13){
2918 activeOption = options.find('li.active:not(.disabled)')[0];
2920 $(activeOption).trigger('click');
2921 $newSelect.trigger('close');
2925 // ARROW DOWN - move to next not disabled option
2926 if(event.which == 40){
2927 newOption = options.find('li.active').next('li:not(.disabled)')[0];
2929 activateOption(options, newOption);
2933 // ESC - close options
2934 if(event.which == 27){
2935 $newSelect.trigger('close');
2938 // ARROW UP - move to previous not disabled option
2939 if(event.which == 38){
2940 newOption = options.find('li.active').prev('li:not(.disabled)')[0];
2942 activateOption(options, newOption);
2946 // Automaticaly clean filter query so user can search again by starting letters
2947 setTimeout(function(){ filterQuery = []; }, 1000);
2950 $newSelect.on('keydown', onKeyDown);
2959 init : function(options) {
2966 options = $.extend(defaults, options);
2968 return this.each(function() {
2970 // For each slider, we want to keep track of
2971 // which slide is active and its associated content
2972 var $this = $(this);
2973 var $slider = $this.find('ul.slides').first();
2974 var $slides = $slider.find('li');
2975 var $active_index = $slider.find('.active').index();
2977 if ($active_index != -1) { $active = $slides.eq($active_index); }
2979 // Transitions the caption depending on alignment
2980 function captionTransition(caption, duration) {
2981 if (caption.hasClass("center
-align
")) {
2982 caption.velocity({opacity: 0, translateY: -100}, {duration: duration, queue: false});
2984 else if (caption.hasClass("right
-align
")) {
2985 caption.velocity({opacity: 0, translateX: 100}, {duration: duration, queue: false});
2987 else if (caption.hasClass("left
-align
")) {
2988 caption.velocity({opacity: 0, translateX: -100}, {duration: duration, queue: false});
2992 // This function will transition the slide to any index of the next slide
2993 function moveToSlide(index) {
2994 if (index >= $slides.length) index = 0;
2995 else if (index < 0) index = $slides.length -1;
2997 $active_index = $slider.find('.active').index();
2999 // Only do if index changes
3000 if ($active_index != index) {
3001 $active = $slides.eq($active_index);
3002 $caption = $active.find('.caption');
3004 $active.removeClass('active');
3005 $active.velocity({opacity: 0}, {duration: options.transition, queue: false, easing: 'easeOutQuad',
3006 complete: function() {
3007 $slides.not('.active').velocity({opacity: 0, translateX: 0, translateY: 0}, {duration: 0, queue: false});
3009 captionTransition($caption, options.transition);
3012 // Update indicators
3013 if (options.indicators) {
3014 $indicators.eq($active_index).removeClass('active');
3017 $slides.eq(index).velocity({opacity: 1}, {duration: options.transition, queue: false, easing: 'easeOutQuad'});
3018 $slides.eq(index).find('.caption').velocity({opacity: 1, translateX: 0, translateY: 0}, {duration: options.transition, delay: options.transition, queue: false, easing: 'easeOutQuad'});
3019 $slides.eq(index).addClass('active');
3022 // Update indicators
3023 if (options.indicators) {
3024 $indicators.eq(index).addClass('active');
3029 // Set height of slider
3030 // If fullscreen, do nothing
3031 if (!$this.hasClass('fullscreen')) {
3032 if (options.indicators) {
3033 // Add height if indicators are present
3034 $this.height(options.height + 40);
3037 $this.height(options.height);
3039 $slider.height(options.height);
3043 // Set initial positions of captions
3044 $slides.find('.caption').each(function () {
3045 captionTransition($(this), 0);
3048 // Move img src into background-image
3049 $slides.find('img').each(function () {
3050 $(this).css('background-image', 'url(' + $(this).attr('src') + ')' );
3051 $(this).attr('src', 'data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==');
3054 // dynamically add indicators
3055 if (options.indicators) {
3056 var $indicators = $('<ul class="indicators
"></ul>');
3057 $slides.each(function( index ) {
3058 var $indicator = $('<li class="indicator
-item
"></li>');
3060 // Handle clicks on indicators
3061 $indicator.click(function () {
3062 var $parent = $slider.parent();
3063 var curr_index = $parent.find($(this)).index();
3064 moveToSlide(curr_index);
3067 clearInterval($interval);
3068 $interval = setInterval(
3070 $active_index = $slider.find('.active').index();
3071 if ($slides.length == $active_index + 1) $active_index = 0; // loop to start
3072 else $active_index += 1;
3074 moveToSlide($active_index);
3076 }, options.transition + options.interval
3079 $indicators.append($indicator);
3081 $this.append($indicators);
3082 $indicators = $this.find('ul.indicators').find('li.indicator-item');
3089 $slides.first().addClass('active').velocity({opacity: 1}, {duration: options.transition, queue: false, easing: 'easeOutQuad'});
3092 $active = $slides.eq($active_index);
3094 // Update indicators
3095 if (options.indicators) {
3096 $indicators.eq($active_index).addClass('active');
3100 // Adjust height to current slide
3101 $active.find('img').each(function() {
3102 $active.find('.caption').velocity({opacity: 1, translateX: 0, translateY: 0}, {duration: options.transition, queue: false, easing: 'easeOutQuad'});
3106 $interval = setInterval(
3108 $active_index = $slider.find('.active').index();
3109 moveToSlide($active_index + 1);
3111 }, options.transition + options.interval
3115 // HammerJS, Swipe navigation
3118 var panning = false;
3119 var swipeLeft = false;
3120 var swipeRight = false;
3123 prevent_default: false
3124 }).bind('pan', function(e) {
3125 if (e.gesture.pointerType === "touch
") {
3128 clearInterval($interval);
3130 var direction = e.gesture.direction;
3131 var x = e.gesture.deltaX;
3132 var velocityX = e.gesture.velocityX;
3134 $curr_slide = $slider.find('.active');
3135 $curr_slide.velocity({ translateX: x
3136 }, {duration: 50, queue: false, easing: 'easeOutQuad'});
3139 if (direction === 4 && (x > ($this.innerWidth() / 2) || velocityX < -0.65)) {
3143 else if (direction === 2 && (x < (-1 * $this.innerWidth() / 2) || velocityX > 0.65)) {
3147 // Make Slide Behind active slide visible
3150 next_slide = $curr_slide.next();
3151 if (next_slide.length === 0) {
3152 next_slide = $slides.first();
3154 next_slide.velocity({ opacity: 1
3155 }, {duration: 300, queue: false, easing: 'easeOutQuad'});
3158 next_slide = $curr_slide.prev();
3159 if (next_slide.length === 0) {
3160 next_slide = $slides.last();
3162 next_slide.velocity({ opacity: 1
3163 }, {duration: 300, queue: false, easing: 'easeOutQuad'});
3169 }).bind('panend', function(e) {
3170 if (e.gesture.pointerType === "touch
") {
3172 $curr_slide = $slider.find('.active');
3174 curr_index = $slider.find('.active').index();
3176 if (!swipeRight && !swipeLeft) {
3177 // Return to original spot
3178 $curr_slide.velocity({ translateX: 0
3179 }, {duration: 300, queue: false, easing: 'easeOutQuad'});
3181 else if (swipeLeft) {
3182 moveToSlide(curr_index + 1);
3183 $curr_slide.velocity({translateX: -1 * $this.innerWidth() }, {duration: 300, queue: false, easing: 'easeOutQuad',
3184 complete: function() {
3185 $curr_slide.velocity({opacity: 0, translateX: 0}, {duration: 0, queue: false});
3188 else if (swipeRight) {
3189 moveToSlide(curr_index - 1);
3190 $curr_slide.velocity({translateX: $this.innerWidth() }, {duration: 300, queue: false, easing: 'easeOutQuad',
3191 complete: function() {
3192 $curr_slide.velocity({opacity: 0, translateX: 0}, {duration: 0, queue: false});
3199 clearInterval($interval);
3200 $interval = setInterval(
3202 $active_index = $slider.find('.active').index();
3203 if ($slides.length == $active_index + 1) $active_index = 0; // loop to start
3204 else $active_index += 1;
3206 moveToSlide($active_index);
3208 }, options.transition + options.interval
3213 $this.on('sliderPause', function() {
3214 clearInterval($interval);
3217 $this.on('sliderStart', function() {
3218 clearInterval($interval);
3219 $interval = setInterval(
3221 $active_index = $slider.find('.active').index();
3222 if ($slides.length == $active_index + 1) $active_index = 0; // loop to start
3223 else $active_index += 1;
3225 moveToSlide($active_index);
3227 }, options.transition + options.interval
3236 pause : function() {
3237 $(this).trigger('sliderPause');
3239 start : function() {
3240 $(this).trigger('sliderStart');
3245 $.fn.slider = function(methodOrOptions) {
3246 if ( methods[methodOrOptions] ) {
3247 return methods[ methodOrOptions ].apply( this, Array.prototype.slice.call( arguments, 1 ));
3248 } else if ( typeof methodOrOptions === 'object' || ! methodOrOptions ) {
3249 // Default to "init
"
3250 return methods.init.apply( this, arguments );
3252 $.error( 'Method ' + methodOrOptions + ' does not exist on jQuery.tooltip' );
3255 }( jQuery ));;(function ($) {
3256 $(document).ready(function() {
3258 $(document).on('click.card', '.card', function (e) {
3259 if ($(this).find('> .card-reveal').length) {
3260 if ($(e.target).is($('.card-reveal .card-title')) || $(e.target).is($('.card-reveal .card-title i'))) {
3261 // Make Reveal animate down and display none
3262 $(this).find('.card-reveal').velocity(
3266 easing: 'easeInOutQuad',
3267 complete: function() { $(this).css({ display: 'none'}); }
3271 else if ($(e.target).is($('.card .activator')) ||
3272 $(e.target).is($('.card .activator i')) ) {
3273 $(this).find('.card-reveal').css({ display: 'block'}).velocity("stop
", false).velocity({translateY: '-100%'}, {duration: 300, queue: false, easing: 'easeInOutQuad'});
3281 }( jQuery ));;(function ($) {
3282 $(document).ready(function() {
3284 $(document).on('click.chip', '.chip .material-icons', function (e) {
3285 $(this).parent().remove();
3289 }( jQuery ));;(function ($) {
3290 $(document).ready(function() {
3292 $.fn.pushpin = function (options) {
3299 options = $.extend(defaults, options);
3302 return this.each(function() {
3303 var $uniqueId = Materialize.guid(),
3305 $original_offset = $(this).offset().top;
3307 function removePinClasses(object) {
3308 object.removeClass('pin-top');
3309 object.removeClass('pinned');
3310 object.removeClass('pin-bottom');
3313 function updateElements(objects, scrolled) {
3314 objects.each(function () {
3315 // Add position fixed (because its between top and bottom)
3316 if (options.top <= scrolled && options.bottom >= scrolled && !$(this).hasClass('pinned')) {
3317 removePinClasses($(this));
3318 $(this).css('top', options.offset);
3319 $(this).addClass('pinned');
3322 // Add pin-top (when scrolled position is above top)
3323 if (scrolled < options.top && !$(this).hasClass('pin-top')) {
3324 removePinClasses($(this));
3325 $(this).css('top', 0);
3326 $(this).addClass('pin-top');
3329 // Add pin-bottom (when scrolled position is below bottom)
3330 if (scrolled > options.bottom && !$(this).hasClass('pin-bottom')) {
3331 removePinClasses($(this));
3332 $(this).addClass('pin-bottom');
3333 $(this).css('top', options.bottom - $original_offset);
3338 updateElements($this, $(window).scrollTop());
3339 $(window).on('scroll.' + $uniqueId, function () {
3340 var $scrolled = $(window).scrollTop() + options.offset;
3341 updateElements($this, $scrolled);
3350 }( jQuery ));;(function ($) {
3351 $(document).ready(function() {
3354 $.fn.reverse = [].reverse;
3356 $(document).on('mouseenter.fixedActionBtn', '.fixed-action-btn', function(e) {
3357 var $this = $(this);
3362 $(document).on('mouseleave.fixedActionBtn', '.fixed-action-btn', function(e) {
3363 var $this = $(this);
3364 closeFABMenu($this);
3370 openFAB: function() {
3371 var $this = $(this);
3374 closeFAB: function() {
3375 closeFABMenu($this);
3380 var openFABMenu = function (btn) {
3382 if ($this.hasClass('active') === false) {
3383 $this.addClass('active');
3384 $this.find('ul .btn-floating').velocity(
3385 { scaleY: ".4", scaleX: ".4", translateY: "40px
"},
3389 $this.find('ul .btn-floating').reverse().each(function () {
3391 { opacity: "1", scaleX: "1", scaleY: "1", translateY: "0"},
3392 { duration: 80, delay: time });
3398 var closeFABMenu = function (btn) {
3400 $this.removeClass('active');
3402 $this.find('ul .btn-floating').velocity("stop
", true);
3403 $this.find('ul .btn-floating').velocity(
3404 { opacity: "0", scaleX: ".4", scaleY: ".4", translateY: "40px
"},
3412 // Image transition function
3413 Materialize.fadeInImage = function(selector){
3414 var element = $(selector);
3415 element.css({opacity: 0});
3416 $(element).velocity({opacity: 1}, {
3419 easing: 'easeOutSine'
3421 $(element).velocity({opacity: 1}, {
3425 step: function(now, fx) {
3427 var grayscale_setting = now/100;
3428 var brightness_setting = 150 - (100 - now)/1.75;
3430 if (brightness_setting < 100) {
3431 brightness_setting = 100;
3435 "-webkit
-filter
": "grayscale("+grayscale_setting+")" + "brightness("+brightness_setting+"%)",
3436 "filter
": "grayscale("+grayscale_setting+")" + "brightness("+brightness_setting+"%)"
3443 // Horizontal staggered list
3444 Materialize.showStaggeredList = function(selector) {
3446 $(selector).find('li').velocity(
3447 { translateX: "-100px
"},
3450 $(selector).find('li').each(function() {
3452 { opacity: "1", translateX: "0"},
3453 { duration: 800, delay: time, easing: [60, 10] });
3459 $(document).ready(function() {
3460 // Hardcoded .staggered-list scrollFire
3461 // var staggeredListOptions = [];
3462 // $('ul.staggered-list').each(function (i) {
3464 // var label = 'scrollFire-' + i;
3465 // $(this).addClass(label);
3466 // staggeredListOptions.push(
3467 // {selector: 'ul.staggered-list.' + label,
3469 // callback: 'showStaggeredList("ul
.staggered
-list
.' + label + '")'});
3471 // scrollFire(staggeredListOptions);
3473 // HammerJS, Swipe navigation
3476 var swipeLeft = false;
3477 var swipeRight = false;
3480 // Dismissible Collections
3481 $('.dismissable').each(function() {
3483 prevent_default: false
3484 }).bind('pan', function(e) {
3485 if (e.gesture.pointerType === "touch
") {
3486 var $this = $(this);
3487 var direction = e.gesture.direction;
3488 var x = e.gesture.deltaX;
3489 var velocityX = e.gesture.velocityX;
3491 $this.velocity({ translateX: x
3492 }, {duration: 50, queue: false, easing: 'easeOutQuad'});
3495 if (direction === 4 && (x > ($this.innerWidth() / 2) || velocityX < -0.75)) {
3500 if (direction === 2 && (x < (-1 * $this.innerWidth() / 2) || velocityX > 0.75)) {
3504 }).bind('panend', function(e) {
3505 // Reset if collection is moved back into original position
3506 if (Math.abs(e.gesture.deltaX) < ($(this).innerWidth() / 2)) {
3511 if (e.gesture.pointerType === "touch
") {
3512 var $this = $(this);
3513 if (swipeLeft || swipeRight) {
3515 if (swipeLeft) { fullWidth = $this.innerWidth(); }
3516 else { fullWidth = -1 * $this.innerWidth(); }
3518 $this.velocity({ translateX: fullWidth,
3519 }, {duration: 100, queue: false, easing: 'easeOutQuad', complete:
3521 $this.css('border', 'none');
3522 $this.velocity({ height: 0, padding: 0,
3523 }, {duration: 200, queue: false, easing: 'easeOutQuad', complete:
3524 function() { $this.remove(); }
3530 $this.velocity({ translateX: 0,
3531 }, {duration: 100, queue: false, easing: 'easeOutQuad'});
3542 // // Vertical Staggered list
3543 // $('ul.staggered-list.vertical li').velocity(
3544 // { translateY: "100px
"},
3545 // { duration: 0 });
3547 // $('ul.staggered-list.vertical li').each(function() {
3548 // $(this).velocity(
3549 // { opacity: "1", translateY: "0"},
3550 // { duration: 800, delay: time, easing: [60, 25] });
3554 // // Fade in and Scale
3555 // $('.fade-in.scale').velocity(
3556 // { scaleX: .4, scaleY: .4, translateX: -600},
3558 // $('.fade-in').each(function() {
3559 // $(this).velocity(
3560 // { opacity: "1", scaleX: 1, scaleY: 1, translateX: 0},
3561 // { duration: 800, easing: [60, 10] });
3567 // Input: Array of JSON objects {selector, offset, callback}
3569 Materialize.scrollFire = function(options) {
3571 var didScroll = false;
3573 window.addEventListener("scroll
", function() {
3577 // Rate limit to 100ms
3578 setInterval(function() {
3582 var windowScroll = window.pageYOffset + window.innerHeight;
3584 for (var i = 0 ; i < options.length; i++) {
3585 // Get options from each line
3586 var value = options[i];
3587 var selector = value.selector,
3588 offset = value.offset,
3589 callback = value.callback;
3591 var currentElement = document.querySelector(selector);
3592 if ( currentElement !== null) {
3593 var elementOffset = currentElement.getBoundingClientRect().top + window.pageYOffset;
3595 if (windowScroll > (elementOffset + offset)) {
3596 if (value.done !== true) {
3597 var callbackFunc = new Function(callback);
3609 * pickadate.js v3.5.0, 2014/04/13
3610 * By Amsul, http://amsul.ca
3611 * Hosted on http://amsul.github.io/pickadate.js
3612 * Licensed under MIT
3615 (function ( factory ) {
3618 if ( typeof define == 'function' && define.amd )
3619 define( 'picker', ['jquery'], factory )
3621 // Node.js/browserify.
3622 else if ( typeof exports == 'object' )
3623 module.exports = factory( require('jquery') )
3626 else this.Picker = factory( jQuery )
3630 var $window = $( window )
3631 var $document = $( document )
3632 var $html = $( document.documentElement )
3636 * The picker constructor that creates a blank picker.
3638 function PickerConstructor( ELEMENT, NAME, COMPONENT, OPTIONS ) {
3640 // If there’s no element, return the picker constructor.
3641 if ( !ELEMENT ) return PickerConstructor
3645 IS_DEFAULT_THEME = false,
3648 // The state of the picker.
3650 id: ELEMENT.id || 'P' + Math.abs( ~~(Math.random() * new Date()) )
3654 // Merge the defaults and options passed.
3655 SETTINGS = COMPONENT ? $.extend( true, {}, COMPONENT.defaults, OPTIONS ) : OPTIONS || {},
3658 // Merge the default classes with the settings classes.
3659 CLASSES = $.extend( {}, PickerConstructor.klasses(), SETTINGS.klass ),
3662 // The element node wrapper into a jQuery object.
3663 $ELEMENT = $( ELEMENT ),
3666 // Pseudo picker constructor.
3667 PickerInstance = function() {
3672 // The picker prototype.
3673 P = PickerInstance.prototype = {
3675 constructor: PickerInstance,
3681 * Initialize everything
3685 // If it’s already started, do nothing.
3686 if ( STATE && STATE.start ) return P
3689 // Update the picker states.
3693 STATE.type = ELEMENT.type
3696 // Confirm focus state, convert into text input to remove UA stylings,
3697 // and set as readonly to prevent keyboard popup.
3698 ELEMENT.autofocus = ELEMENT == getActiveElement()
3699 ELEMENT.readOnly = !SETTINGS.editable
3700 ELEMENT.id = ELEMENT.id || STATE.id
3701 if ( ELEMENT.type != 'text' ) {
3702 ELEMENT.type = 'text'
3706 // Create a new picker component with the settings.
3707 P.component = new COMPONENT(P, SETTINGS)
3710 // Create the picker root with a holder and then prepare it.
3711 P.$root = $( PickerConstructor._.node('div', createWrappedComponent(), CLASSES.picker, 'id="' + ELEMENT.id + '_root
" tabindex="0"') )
3712 prepareElementRoot()
3715 // If there’s a format for the hidden input element, create the element.
3716 if ( SETTINGS.formatSubmit ) {
3717 prepareElementHidden()
3721 // Prepare the input element.
3725 // Insert the root as specified in the settings.
3726 if ( SETTINGS.container ) $( SETTINGS.container ).append( P.$root )
3727 else $ELEMENT.after( P.$root )
3730 // Bind the default component and settings events.
3732 start: P.component.onStart,
3733 render: P.component.onRender,
3734 stop: P.component.onStop,
3735 open: P.component.onOpen,
3736 close: P.component.onClose,
3737 set: P.component.onSet
3739 start: SETTINGS.onStart,
3740 render: SETTINGS.onRender,
3741 stop: SETTINGS.onStop,
3742 open: SETTINGS.onOpen,
3743 close: SETTINGS.onClose,
3748 // Once we’re all set, check the theme in use.
3749 IS_DEFAULT_THEME = isUsingDefaultTheme( P.$root.children()[ 0 ] )
3752 // If the element has autofocus, open the picker.
3753 if ( ELEMENT.autofocus ) {
3758 // Trigger queued the “start” and “render” events.
3759 return P.trigger( 'start' ).trigger( 'render' )
3764 * Render a new picker
3766 render: function( entireComponent ) {
3768 // Insert a new component holder in the root or box.
3769 if ( entireComponent ) P.$root.html( createWrappedComponent() )
3770 else P.$root.find( '.' + CLASSES.box ).html( P.component.nodes( STATE.open ) )
3772 // Trigger the queued “render” events.
3773 return P.trigger( 'render' )
3778 * Destroy everything
3782 // If it’s already stopped, do nothing.
3783 if ( !STATE.start ) return P
3785 // Then close the picker.
3788 // Remove the hidden field.
3790 P._hidden.parentNode.removeChild( P._hidden )
3796 // Remove the input class, remove the stored data, and unbind
3797 // the events (after a tick for IE - see `P.close`).
3798 $ELEMENT.removeClass( CLASSES.input ).removeData( NAME )
3799 setTimeout( function() {
3800 $ELEMENT.off( '.' + STATE.id )
3803 // Restore the element state
3804 ELEMENT.type = STATE.type
3805 ELEMENT.readOnly = false
3807 // Trigger the queued “stop” events.
3810 // Reset the picker states.
3819 * Open up the picker
3821 open: function( dontGiveFocus ) {
3823 // If it’s already open, do nothing.
3824 if ( STATE.open ) return P
3826 // Add the “active” class.
3827 $ELEMENT.addClass( CLASSES.active )
3828 aria( ELEMENT, 'expanded', true )
3830 // * A Firefox bug, when `html` has `overflow:hidden`, results in
3831 // killing transitions :(. So add the “opened” state on the next tick.
3832 // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=625289
3833 setTimeout( function() {
3835 // Add the “opened” class to the picker root.
3836 P.$root.addClass( CLASSES.opened )
3837 aria( P.$root[0], 'hidden', false )
3841 // If we have to give focus, bind the element and doc events.
3842 if ( dontGiveFocus !== false ) {
3847 // Prevent the page from scrolling.
3848 if ( IS_DEFAULT_THEME ) {
3850 css( 'overflow', 'hidden' ).
3851 css( 'padding-right', '+=' + getScrollbarWidth() )
3854 // Pass focus to the root element’s jQuery object.
3855 // * Workaround for iOS8 to bring the picker’s root into view.
3858 // Bind the document events.
3859 $document.on( 'click.' + STATE.id + ' focusin.' + STATE.id, function( event ) {
3861 var target = event.target
3863 // If the target of the event is not the element, close the picker picker.
3864 // * Don’t worry about clicks or focusins on the root because those don’t bubble up.
3865 // Also, for Firefox, a click on an `option` element bubbles up directly
3866 // to the doc. So make sure the target wasn't the doc.
3867 // * In Firefox stopPropagation() doesn’t prevent right-click events from bubbling,
3868 // which causes the picker to unexpectedly close when right-clicking it. So make
3869 // sure the event wasn’t a right-click.
3870 if ( target != ELEMENT && target != document && event.which != 3 ) {
3872 // If the target was the holder that covers the screen,
3873 // keep the element focused to maintain tabindex.
3874 P.close( target === P.$root.children()[0] )
3877 }).on( 'keydown.' + STATE.id, function( event ) {
3881 keycode = event.keyCode,
3883 // Translate that to a selection change.
3884 keycodeToMove = P.component.key[ keycode ],
3887 target = event.target
3890 // On escape, close the picker and give focus.
3891 if ( keycode == 27 ) {
3896 // Check if there is a key movement or “enter” keypress on the element.
3897 else if ( target == P.$root[0] && ( keycodeToMove || keycode == 13 ) ) {
3899 // Prevent the default action to stop page movement.
3900 event.preventDefault()
3902 // Trigger the key movement action.
3903 if ( keycodeToMove ) {
3904 PickerConstructor._.trigger( P.component.key.go, P, [ PickerConstructor._.trigger( keycodeToMove ) ] )
3907 // On “enter”, if the highlighted item isn’t disabled, set the value and close.
3908 else if ( !P.$root.find( '.' + CLASSES.highlighted ).hasClass( CLASSES.disabled ) ) {
3909 P.set( 'select', P.component.item.highlight ).close()
3914 // If the target is within the root and “enter” is pressed,
3915 // prevent the default action and trigger a click on the target instead.
3916 else if ( $.contains( P.$root[0], target ) && keycode == 13 ) {
3917 event.preventDefault()
3923 // Trigger the queued “open” events.
3924 return P.trigger( 'open' )
3931 close: function( giveFocus ) {
3933 // If we need to give focus, do it before changing states.
3935 // ....ah yes! It would’ve been incomplete without a crazy workaround for IE :|
3936 // The focus is triggered *after* the close has completed - causing it
3937 // to open again. So unbind and rebind the event at the next tick.
3938 P.$root.off( 'focus.toOpen' )[0].focus()
3939 setTimeout( function() {
3940 P.$root.on( 'focus.toOpen', handleFocusToOpenEvent )
3944 // Remove the “active” class.
3945 $ELEMENT.removeClass( CLASSES.active )
3946 aria( ELEMENT, 'expanded', false )
3948 // * A Firefox bug, when `html` has `overflow:hidden`, results in
3949 // killing transitions :(. So remove the “opened” state on the next tick.
3950 // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=625289
3951 setTimeout( function() {
3953 // Remove the “opened” and “focused” class from the picker root.
3954 P.$root.removeClass( CLASSES.opened + ' ' + CLASSES.focused )
3955 aria( P.$root[0], 'hidden', true )
3959 // If it’s already closed, do nothing more.
3960 if ( !STATE.open ) return P
3962 // Set it as closed.
3965 // Allow the page to scroll.
3966 if ( IS_DEFAULT_THEME ) {
3968 css( 'overflow', '' ).
3969 css( 'padding-right', '-=' + getScrollbarWidth() )
3972 // Unbind the document events.
3973 $document.off( '.' + STATE.id )
3975 // Trigger the queued “close” events.
3976 return P.trigger( 'close' )
3983 clear: function( options ) {
3984 return P.set( 'clear', null, options )
3991 set: function( thing, value, options ) {
3993 var thingItem, thingValue,
3994 thingIsObject = $.isPlainObject( thing ),
3995 thingObject = thingIsObject ? thing : {}
3997 // Make sure we have usable options.
3998 options = thingIsObject && $.isPlainObject( value ) ? value : options || {}
4002 // If the thing isn’t an object, make it one.
4003 if ( !thingIsObject ) {
4004 thingObject[ thing ] = value
4007 // Go through the things of items to set.
4008 for ( thingItem in thingObject ) {
4010 // Grab the value of the thing.
4011 thingValue = thingObject[ thingItem ]
4013 // First, if the item exists and there’s a value, set it.
4014 if ( thingItem in P.component.item ) {
4015 if ( thingValue === undefined ) thingValue = null
4016 P.component.set( thingItem, thingValue, options )
4019 // Then, check to update the element value and broadcast a change.
4020 if ( thingItem == 'select' || thingItem == 'clear' ) {
4022 val( thingItem == 'clear' ? '' : P.get( thingItem, SETTINGS.format ) ).
4027 // Render a new picker.
4031 // When the method isn’t muted, trigger queued “set” events and pass the `thingObject`.
4032 return options.muted ? P : P.trigger( 'set', thingObject )
4039 get: function( thing, format ) {
4041 // Make sure there’s something to get.
4042 thing = thing || 'value'
4044 // If a picker state exists, return that.
4045 if ( STATE[ thing ] != null ) {
4046 return STATE[ thing ]
4049 // Return the submission value, if that.
4050 if ( thing == 'valueSubmit' ) {
4052 return P._hidden.value
4057 // Return the value, if that.
4058 if ( thing == 'value' ) {
4059 return ELEMENT.value
4062 // Check if a component item exists, return that.
4063 if ( thing in P.component.item ) {
4064 if ( typeof format == 'string' ) {
4065 var thingValue = P.component.get( thing )
4067 PickerConstructor._.trigger(
4068 P.component.formats.toString,
4070 [ format, thingValue ]
4073 return P.component.get( thing )
4080 * Bind events on the things.
4082 on: function( thing, method, internal ) {
4084 var thingName, thingMethod,
4085 thingIsObject = $.isPlainObject( thing ),
4086 thingObject = thingIsObject ? thing : {}
4090 // If the thing isn’t an object, make it one.
4091 if ( !thingIsObject ) {
4092 thingObject[ thing ] = method
4095 // Go through the things to bind to.
4096 for ( thingName in thingObject ) {
4098 // Grab the method of the thing.
4099 thingMethod = thingObject[ thingName ]
4101 // If it was an internal binding, prefix it.
4103 thingName = '_' + thingName
4106 // Make sure the thing methods collection exists.
4107 STATE.methods[ thingName ] = STATE.methods[ thingName ] || []
4109 // Add the method to the relative method collection.
4110 STATE.methods[ thingName ].push( thingMethod )
4120 * Unbind events on the things.
4125 for ( i = 0, namesCount = names.length; i < namesCount; i += 1 ) {
4126 thingName = names[i]
4127 if ( thingName in STATE.methods ) {
4128 delete STATE.methods[thingName]
4136 * Fire off method events.
4138 trigger: function( name, data ) {
4139 var _trigger = function( name ) {
4140 var methodList = STATE.methods[ name ]
4142 methodList.map( function( method ) {
4143 PickerConstructor._.trigger( method, P, [ data ] )
4147 _trigger( '_' + name )
4151 } //PickerInstance.prototype
4155 * Wrap the picker holder components together.
4157 function createWrappedComponent() {
4159 // Create a picker wrapper holder
4160 return PickerConstructor._.node( 'div',
4162 // Create a picker wrapper node
4163 PickerConstructor._.node( 'div',
4165 // Create a picker frame
4166 PickerConstructor._.node( 'div',
4168 // Create a picker box node
4169 PickerConstructor._.node( 'div',
4171 // Create the components nodes.
4172 P.component.nodes( STATE.open ),
4174 // The picker box class
4178 // Picker wrap class
4182 // Picker frame class
4186 // Picker holder class
4189 } //createWrappedComponent
4194 * Prepare the input element with all bindings.
4196 function prepareElement() {
4200 // Store the picker data by component name.
4203 // Add the “input” class name.
4204 addClass(CLASSES.input).
4206 // Remove the tabindex.
4207 attr('tabindex', -1).
4209 // If there’s a `data-value`, update the value of the element.
4210 val( $ELEMENT.data('value') ?
4211 P.get('select', SETTINGS.format) :
4216 // Only bind keydown events if the element isn’t editable.
4217 if ( !SETTINGS.editable ) {
4221 // On focus/click, focus onto the root to open it up.
4222 on( 'focus.' + STATE.id + ' click.' + STATE.id, function( event ) {
4223 event.preventDefault()
4227 // Handle keyboard event based on the picker being opened or not.
4228 on( 'keydown.' + STATE.id, handleKeydownEvent )
4232 // Update the aria attributes.
4237 owns: ELEMENT.id + '_root'
4243 * Prepare the root picker element with all bindings.
4245 function prepareElementRoot() {
4252 keydown: handleKeydownEvent,
4254 // When something within the root is focused, stop from bubbling
4255 // to the doc and remove the “focused” state from the root.
4256 focusin: function( event ) {
4257 P.$root.removeClass( CLASSES.focused )
4258 event.stopPropagation()
4261 // When something within the root holder is clicked, stop it
4262 // from bubbling to the doc.
4263 'mousedown click': function( event ) {
4265 var target = event.target
4267 // Make sure the target isn’t the root holder so it can bubble up.
4268 if ( target != P.$root.children()[ 0 ] ) {
4270 event.stopPropagation()
4272 // * For mousedown events, cancel the default action in order to
4273 // prevent cases where focus is shifted onto external elements
4274 // when using things like jQuery mobile or MagnificPopup (ref: #249 & #120).
4275 // Also, for Firefox, don’t prevent action on the `option` element.
4276 if ( event.type == 'mousedown' && !$( target ).is( 'input, select, textarea, button, option' )) {
4278 event.preventDefault()
4280 // Re-focus onto the root so that users can click away
4281 // from elements focused within the picker.
4288 // Add/remove the “target” class on focus and blur.
4291 $ELEMENT.addClass( CLASSES.target )
4294 $ELEMENT.removeClass( CLASSES.target )
4298 // Open the picker and adjust the root “focused” state
4299 on( 'focus.toOpen', handleFocusToOpenEvent ).
4301 // If there’s a click on an actionable element, carry out the actions.
4302 on( 'click', '[data-pick], [data-nav], [data-clear], [data-close]', function() {
4304 var $target = $( this ),
4305 targetData = $target.data(),
4306 targetDisabled = $target.hasClass( CLASSES.navDisabled ) || $target.hasClass( CLASSES.disabled ),
4308 // * For IE, non-focusable elements can be active elements as well
4309 // (http://stackoverflow.com/a/2684561).
4310 activeElement = getActiveElement()
4311 activeElement = activeElement && ( activeElement.type || activeElement.href )
4313 // If it’s disabled or nothing inside is actively focused, re-focus the element.
4314 if ( targetDisabled || activeElement && !$.contains( P.$root[0], activeElement ) ) {
4318 // If something is superficially changed, update the `highlight` based on the `nav`.
4319 if ( !targetDisabled && targetData.nav ) {
4320 P.set( 'highlight', P.component.item.highlight, { nav: targetData.nav } )
4323 // If something is picked, set `select` then close with focus.
4324 else if ( !targetDisabled && 'pick' in targetData ) {
4325 P.set( 'select', targetData.pick )
4328 // If a “clear” button is pressed, empty the values and close with focus.
4329 else if ( targetData.clear ) {
4330 P.clear().close( true )
4333 else if ( targetData.close ) {
4339 aria( P.$root[0], 'hidden', true )
4344 * Prepare the hidden input element along with all bindings.
4346 function prepareElementHidden() {
4350 if ( SETTINGS.hiddenName === true ) {
4356 typeof SETTINGS.hiddenPrefix == 'string' ? SETTINGS.hiddenPrefix : '',
4357 typeof SETTINGS.hiddenSuffix == 'string' ? SETTINGS.hiddenSuffix : '_submit'
4359 name = name[0] + ELEMENT.name + name[1]
4366 // Create the name using the original input’s with a prefix and suffix.
4367 'name="' + name + '"' +
4369 // If the element has a value, set the hidden value as well.
4371 $ELEMENT.data('value') || ELEMENT.value ?
4372 ' value="' + P.get('select
', SETTINGS.formatSubmit) + '"' :
4380 // If the value changes, update the hidden input with the correct format.
4381 on('change.' + STATE.id, function() {
4382 P._hidden.value = ELEMENT.value ?
4383 P.get('select', SETTINGS.formatSubmit) :
4388 // Insert the hidden input as specified in the settings.
4389 if ( SETTINGS.container ) $( SETTINGS.container ).append( P._hidden )
4390 else $ELEMENT.after( P._hidden )
4395 function handleKeydownEvent( event ) {
4397 var keycode = event.keyCode,
4399 // Check if one of the delete keys was pressed.
4400 isKeycodeDelete = /^(8|46)$/.test(keycode)
4402 // For some reason IE clears the input value on “escape”.
4403 if ( keycode == 27 ) {
4408 // Check if `space` or `delete` was pressed or the picker is closed with a key movement.
4409 if ( keycode == 32 || isKeycodeDelete || !STATE.open && P.component.key[keycode] ) {
4411 // Prevent it from moving the page and bubbling to doc.
4412 event.preventDefault()
4413 event.stopPropagation()
4415 // If `delete` was pressed, clear the values and close the picker.
4416 // Otherwise open the picker.
4417 if ( isKeycodeDelete ) { P.clear().close() }
4424 function handleFocusToOpenEvent( event ) {
4426 // Stop the event from propagating to the doc.
4427 event.stopPropagation()
4429 // If it’s a focus event, add the “focused” class to the root.
4430 if ( event.type == 'focus' ) {
4431 P.$root.addClass( CLASSES.focused )
4434 // And then finally open the picker.
4439 // Return a new picker instance.
4440 return new PickerInstance()
4441 } //PickerConstructor
4446 * The default classes and prefix to use for the HTML classes.
4448 PickerConstructor.klasses = function( prefix ) {
4449 prefix = prefix || 'picker'
4453 opened: prefix + '--opened',
4454 focused: prefix + '--focused',
4456 input: prefix + '__input',
4457 active: prefix + '__input--active',
4458 target: prefix + '__input--target',
4460 holder: prefix + '__holder',
4462 frame: prefix + '__frame',
4463 wrap: prefix + '__wrap',
4465 box: prefix + '__box'
4467 } //PickerConstructor.klasses
4472 * Check if the default theme is being used.
4474 function isUsingDefaultTheme( element ) {
4480 if ( element.currentStyle ) {
4481 theme = element.currentStyle[prop]
4484 // For normal browsers.
4485 else if ( window.getComputedStyle ) {
4486 theme = getComputedStyle( element )[prop]
4489 return theme == 'fixed'
4495 * Get the width of the browser’s scrollbar.
4496 * Taken from: https://github.com/VodkaBears/Remodal/blob/master/src/jquery.remodal.js
4498 function getScrollbarWidth() {
4500 if ( $html.height() <= $window.height() ) {
4504 var $outer = $( '<div style="visibility:hidden
;width:100px
" />' ).
4507 // Get the width without scrollbars.
4508 var widthWithoutScroll = $outer[0].offsetWidth
4510 // Force adding scrollbars.
4511 $outer.css( 'overflow', 'scroll' )
4513 // Add the inner div.
4514 var $inner = $( '<div style="width:100%" />' ).appendTo( $outer )
4516 // Get the width with scrollbars.
4517 var widthWithScroll = $inner[0].offsetWidth
4522 // Return the difference between the widths.
4523 return widthWithoutScroll - widthWithScroll
4529 * PickerConstructor helper methods.
4531 PickerConstructor._ = {
4534 * Create a group of nodes. Expects:
4545 group: function( groupObject ) {
4548 // Scope for the looped object
4551 // Create the nodes list
4554 // The counter starts from the `min`
4555 counter = PickerConstructor._.trigger( groupObject.min, groupObject )
4558 // Loop from the `min` to `max`, incrementing by `i`
4559 for ( ; counter <= PickerConstructor._.trigger( groupObject.max, groupObject, [ counter ] ); counter += groupObject.i ) {
4561 // Trigger the `item` function within scope of the object
4562 loopObjectScope = PickerConstructor._.trigger( groupObject.item, groupObject, [ counter ] )
4564 // Splice the subgroup and create nodes out of the sub nodes
4565 nodesList += PickerConstructor._.node(
4567 loopObjectScope[ 0 ], // the node
4568 loopObjectScope[ 1 ], // the classes
4569 loopObjectScope[ 2 ] // the attributes
4573 // Return the list of nodes
4579 * Create a dom node string
4581 node: function( wrapper, item, klass, attribute ) {
4583 // If the item is false-y, just return an empty string
4584 if ( !item ) return ''
4586 // If the item is an array, do a join
4587 item = $.isArray( item ) ? item.join( '' ) : item
4589 // Check for the class
4590 klass = klass ? ' class="' + klass + '"' : ''
4592 // Check for any attributes
4593 attribute = attribute ? ' ' + attribute : ''
4595 // Return the wrapped item
4596 return '<' + wrapper + klass + attribute + '>' + item + '</' + wrapper + '>'
4601 * Lead numbers below 10 with a zero.
4603 lead: function( number ) {
4604 return ( number < 10 ? '0': '' ) + number
4609 * Trigger a function otherwise return the value.
4611 trigger: function( callback, scope, args ) {
4612 return typeof callback == 'function' ? callback.apply( scope, args || [] ) : callback
4617 * If the second character is a digit, length is 2 otherwise 1.
4619 digits: function( string ) {
4620 return ( /\d/ ).test( string[ 1 ] ) ? 2 : 1
4625 * Tell if something is a date object.
4627 isDate: function( value ) {
4628 return {}.toString.call( value ).indexOf( 'Date' ) > -1 && this.isInteger( value.getDate() )
4633 * Tell if something is an integer.
4635 isInteger: function( value ) {
4636 return {}.toString.call( value ).indexOf( 'Number' ) > -1 && value % 1 === 0
4641 * Create ARIA attribute strings.
4644 } //PickerConstructor._
4649 * Extend the picker with a component and defaults.
4651 PickerConstructor.extend = function( name, Component ) {
4654 $.fn[ name ] = function( options, action ) {
4656 // Grab the component data.
4657 var componentData = this.data( name )
4659 // If the picker is requested, return the data object.
4660 if ( options == 'picker' ) {
4661 return componentData
4664 // If the component data exists and `options` is a string, carry out the action.
4665 if ( componentData && typeof options == 'string' ) {
4666 return PickerConstructor._.trigger( componentData[ options ], componentData, [ action ] )
4669 // Otherwise go through each matched element and if the component
4670 // doesn’t exist, create a new picker using `this` element
4671 // and merging the defaults and options with a deep copy.
4672 return this.each( function() {
4673 var $this = $( this )
4674 if ( !$this.data( name ) ) {
4675 new PickerConstructor( this, name, Component, options )
4680 // Set the defaults.
4681 $.fn[ name ].defaults = Component.defaults
4682 } //PickerConstructor.extend
4686 function aria(element, attribute, value) {
4687 if ( $.isPlainObject(attribute) ) {
4688 for ( var key in attribute ) {
4689 ariaSet(element, key, attribute[key])
4693 ariaSet(element, attribute, value)
4696 function ariaSet(element, attribute, value) {
4697 element.setAttribute(
4698 (attribute == 'role' ? '' : 'aria-') + attribute,
4702 function ariaAttr(attribute, data) {
4703 if ( !$.isPlainObject(attribute) ) {
4704 attribute = { attribute: data }
4707 for ( var key in attribute ) {
4708 var attr = (key == 'role' ? '' : 'aria-') + key,
4709 attrVal = attribute[key]
4710 data += attrVal == null ? '' : attr + '="' + attribute[key] + '"'
4715 // IE8 bug throws an error for activeElements within iframes.
4716 function getActiveElement() {
4718 return document.activeElement
4724 // Expose the picker constructor.
4725 return PickerConstructor
4732 * Date picker for pickadate.js v3.5.0
4733 * http://amsul.github.io/pickadate.js/date.htm
4736 (function ( factory ) {
4739 if ( typeof define == 'function' && define.amd )
4740 define( ['picker', 'jquery'], factory )
4742 // Node.js/browserify.
4743 else if ( typeof exports == 'object' )
4744 module.exports = factory( require('./picker.js'), require('jquery') )
4747 else factory( Picker, jQuery )
4749 }(function( Picker, $ ) {
4753 * Globals and constants
4755 var DAYS_IN_WEEK = 7,
4756 WEEKS_IN_CALENDAR = 6,
4762 * The date picker constructor
4764 function DatePicker( picker, settings ) {
4766 var calendar = this,
4767 element = picker.$node[ 0 ],
4768 elementValue = element.value,
4769 elementDataValue = picker.$node.data( 'value' ),
4770 valueString = elementDataValue || elementValue,
4771 formatString = elementDataValue ? settings.formatSubmit : settings.format,
4772 isRTL = function() {
4774 return element.currentStyle ?
4777 element.currentStyle.direction == 'rtl' :
4779 // For normal browsers.
4780 getComputedStyle( picker.$root[0] ).direction == 'rtl'
4783 calendar.settings = settings
4784 calendar.$node = picker.$node
4786 // The queue of methods that will be used to build item objects.
4788 min: 'measure create',
4789 max: 'measure create',
4791 select: 'parse create validate',
4792 highlight: 'parse navigate create validate',
4793 view: 'parse create validate viewset',
4794 disable: 'deactivate',
4798 // The component's item object.
4801 calendar.item.clear = null
4802 calendar.item.disable = ( settings.disable || [] ).slice( 0 )
4803 calendar.item.enable = -(function( collectionDisabled ) {
4804 return collectionDisabled[ 0 ] === true ? collectionDisabled.shift() : -1
4805 })( calendar.item.disable )
4808 set( 'min', settings.min ).
4809 set( 'max', settings.max ).
4812 // When there’s a value, set the `select`, which in turn
4813 // also sets the `highlight` and `view`.
4814 if ( valueString ) {
4815 calendar.set( 'select', valueString, { format: formatString })
4818 // If there’s no value, default to highlighting “today”.
4821 set( 'select', null ).
4822 set( 'highlight', calendar.item.now )
4826 // The keycode to movement mapping.
4830 39: function() { return isRTL() ? -1 : 1 }, // Right
4831 37: function() { return isRTL() ? 1 : -1 }, // Left
4832 go: function( timeChange ) {
4833 var highlightedObject = calendar.item.highlight,
4834 targetDate = new Date( highlightedObject.year, highlightedObject.month, highlightedObject.date + timeChange )
4838 { interval: timeChange }
4845 // Bind some picker events.
4847 on( 'render', function() {
4848 picker.$root.find( '.' + settings.klass.selectMonth ).on( 'change', function() {
4849 var value = this.value
4851 picker.set( 'highlight', [ picker.get( 'view' ).year, value, picker.get( 'highlight' ).date ] )
4852 picker.$root.find( '.' + settings.klass.selectMonth ).trigger( 'focus' )
4855 picker.$root.find( '.' + settings.klass.selectYear ).on( 'change', function() {
4856 var value = this.value
4858 picker.set( 'highlight', [ value, picker.get( 'view' ).month, picker.get( 'highlight' ).date ] )
4859 picker.$root.find( '.' + settings.klass.selectYear ).trigger( 'focus' )
4863 on( 'open', function() {
4864 var includeToday = ''
4865 if ( calendar.disabled( calendar.get('now') ) ) {
4866 includeToday = ':not(.' + settings.klass.buttonToday + ')'
4868 picker.$root.find( 'button' + includeToday + ', select' ).attr( 'disabled', false )
4870 on( 'close', function() {
4871 picker.$root.find( 'button, select' ).attr( 'disabled', true )
4878 * Set a datepicker item object.
4880 DatePicker.prototype.set = function( type, value, options ) {
4882 var calendar = this,
4883 calendarItem = calendar.item
4885 // If the value is `null` just set it immediately.
4886 if ( value === null ) {
4887 if ( type == 'clear' ) type = 'select'
4888 calendarItem[ type ] = value
4892 // Otherwise go through the queue of methods, and invoke the functions.
4893 // Update this as the time unit, and set the final value as this item.
4894 // * In the case of `enable`, keep the queue but set `disable` instead.
4895 // And in the case of `flip`, keep the queue but set `enable` instead.
4896 calendarItem[ ( type == 'enable' ? 'disable' : type == 'flip' ? 'enable' : type ) ] = calendar.queue[ type ].split( ' ' ).map( function( method ) {
4897 value = calendar[ method ]( type, value, options )
4901 // Check if we need to cascade through more updates.
4902 if ( type == 'select' ) {
4903 calendar.set( 'highlight', calendarItem.select, options )
4905 else if ( type == 'highlight' ) {
4906 calendar.set( 'view', calendarItem.highlight, options )
4908 else if ( type.match( /^(flip|min|max|disable|enable)$/ ) ) {
4909 if ( calendarItem.select && calendar.disabled( calendarItem.select ) ) {
4910 calendar.set( 'select', calendarItem.select, options )
4912 if ( calendarItem.highlight && calendar.disabled( calendarItem.highlight ) ) {
4913 calendar.set( 'highlight', calendarItem.highlight, options )
4918 } //DatePicker.prototype.set
4922 * Get a datepicker item object.
4924 DatePicker.prototype.get = function( type ) {
4925 return this.item[ type ]
4926 } //DatePicker.prototype.get
4930 * Create a picker date object.
4932 DatePicker.prototype.create = function( type, value, options ) {
4934 var isInfiniteValue,
4937 // If there’s no value, use the type as the value.
4938 value = value === undefined ? type : value
4941 // If it’s infinity, update the value.
4942 if ( value == -Infinity || value == Infinity ) {
4943 isInfiniteValue = value
4946 // If it’s an object, use the native date object.
4947 else if ( $.isPlainObject( value ) && _.isInteger( value.pick ) ) {
4951 // If it’s an array, convert it into a date and make sure
4952 // that it’s a valid date – otherwise default to today.
4953 else if ( $.isArray( value ) ) {
4954 value = new Date( value[ 0 ], value[ 1 ], value[ 2 ] )
4955 value = _.isDate( value ) ? value : calendar.create().obj
4958 // If it’s a number or date object, make a normalized date.
4959 else if ( _.isInteger( value ) || _.isDate( value ) ) {
4960 value = calendar.normalize( new Date( value ), options )
4963 // If it’s a literal true or any other case, set it to now.
4964 else /*if ( value === true )*/ {
4965 value = calendar.now( type, value, options )
4968 // Return the compiled object.
4970 year: isInfiniteValue || value.getFullYear(),
4971 month: isInfiniteValue || value.getMonth(),
4972 date: isInfiniteValue || value.getDate(),
4973 day: isInfiniteValue || value.getDay(),
4974 obj: isInfiniteValue || value,
4975 pick: isInfiniteValue || value.getTime()
4977 } //DatePicker.prototype.create
4981 * Create a range limit object using an array, date object,
4982 * literal “true”, or integer relative to another time.
4984 DatePicker.prototype.createRange = function( from, to ) {
4986 var calendar = this,
4987 createDate = function( date ) {
4988 if ( date === true || $.isArray( date ) || _.isDate( date ) ) {
4989 return calendar.create( date )
4994 // Create objects if possible.
4995 if ( !_.isInteger( from ) ) {
4996 from = createDate( from )
4998 if ( !_.isInteger( to ) ) {
4999 to = createDate( to )
5002 // Create relative dates.
5003 if ( _.isInteger( from ) && $.isPlainObject( to ) ) {
5004 from = [ to.year, to.month, to.date + from ];
5006 else if ( _.isInteger( to ) && $.isPlainObject( from ) ) {
5007 to = [ from.year, from.month, from.date + to ];
5011 from: createDate( from ),
5012 to: createDate( to )
5014 } //DatePicker.prototype.createRange
5018 * Check if a date unit falls within a date range object.
5020 DatePicker.prototype.withinRange = function( range, dateUnit ) {
5021 range = this.createRange(range.from, range.to)
5022 return dateUnit.pick >= range.from.pick && dateUnit.pick <= range.to.pick
5027 * Check if two date range objects overlap.
5029 DatePicker.prototype.overlapRanges = function( one, two ) {
5033 // Convert the ranges into comparable dates.
5034 one = calendar.createRange( one.from, one.to )
5035 two = calendar.createRange( two.from, two.to )
5037 return calendar.withinRange( one, two.from ) || calendar.withinRange( one, two.to ) ||
5038 calendar.withinRange( two, one.from ) || calendar.withinRange( two, one.to )
5043 * Get the date today.
5045 DatePicker.prototype.now = function( type, value, options ) {
5047 if ( options && options.rel ) {
5048 value.setDate( value.getDate() + options.rel )
5050 return this.normalize( value, options )
5055 * Navigate to next/prev month.
5057 DatePicker.prototype.navigate = function( type, value, options ) {
5059 var targetDateObject,
5063 isTargetArray = $.isArray( value ),
5064 isTargetObject = $.isPlainObject( value ),
5065 viewsetObject = this.item.view/*,
5069 if ( isTargetArray || isTargetObject ) {
5071 if ( isTargetObject ) {
5072 targetYear = value.year
5073 targetMonth = value.month
5074 targetDate = value.date
5077 targetYear = +value[0]
5078 targetMonth = +value[1]
5079 targetDate = +value[2]
5082 // If we’re navigating months but the view is in a different
5083 // month, navigate to the view’s year and month.
5084 if ( options && options.nav && viewsetObject && viewsetObject.month !== targetMonth ) {
5085 targetYear = viewsetObject.year
5086 targetMonth = viewsetObject.month
5089 // Figure out the expected target year and month.
5090 targetDateObject = new Date( targetYear, targetMonth + ( options && options.nav ? options.nav : 0 ), 1 )
5091 targetYear = targetDateObject.getFullYear()
5092 targetMonth = targetDateObject.getMonth()
5094 // If the month we’re going to doesn’t have enough days,
5095 // keep decreasing the date until we reach the month’s last date.
5096 while ( /*safety &&*/ new Date( targetYear, targetMonth, targetDate ).getMonth() !== targetMonth ) {
5100 throw 'Fell into an infinite loop while navigating to ' + new Date( targetYear, targetMonth, targetDate ) + '.'
5104 value = [ targetYear, targetMonth, targetDate ]
5108 } //DatePicker.prototype.navigate
5112 * Normalize a date by setting the hours to midnight.
5114 DatePicker.prototype.normalize = function( value/*, options*/ ) {
5115 value.setHours( 0, 0, 0, 0 )
5121 * Measure the range of dates.
5123 DatePicker.prototype.measure = function( type, value/*, options*/ ) {
5127 // If it’s anything false-y, remove the limits.
5129 value = type == 'min' ? -Infinity : Infinity
5132 // If it’s a string, parse it.
5133 else if ( typeof value == 'string' ) {
5134 value = calendar.parse( type, value )
5137 // If it's an integer, get a date relative to today.
5138 else if ( _.isInteger( value ) ) {
5139 value = calendar.now( type, value, { rel: value } )
5143 } ///DatePicker.prototype.measure
5147 * Create a viewset object based on navigation.
5149 DatePicker.prototype.viewset = function( type, dateObject/*, options*/ ) {
5150 return this.create([ dateObject.year, dateObject.month, 1 ])
5155 * Validate a date as enabled and shift if needed.
5157 DatePicker.prototype.validate = function( type, dateObject, options ) {
5159 var calendar = this,
5161 // Keep a reference to the original date.
5162 originalDateObject = dateObject,
5164 // Make sure we have an interval.
5165 interval = options && options.interval ? options.interval : 1,
5167 // Check if the calendar enabled dates are inverted.
5168 isFlippedBase = calendar.item.enable === -1,
5170 // Check if we have any enabled dates after/before now.
5171 hasEnabledBeforeTarget, hasEnabledAfterTarget,
5173 // The min & max limits.
5174 minLimitObject = calendar.item.min,
5175 maxLimitObject = calendar.item.max,
5177 // Check if we’ve reached the limit during shifting.
5178 reachedMin, reachedMax,
5180 // Check if the calendar is inverted and at least one weekday is enabled.
5181 hasEnabledWeekdays = isFlippedBase && calendar.item.disable.filter( function( value ) {
5183 // If there’s a date, check where it is relative to the target.
5184 if ( $.isArray( value ) ) {
5185 var dateTime = calendar.create( value ).pick
5186 if ( dateTime < dateObject.pick ) hasEnabledBeforeTarget = true
5187 else if ( dateTime > dateObject.pick ) hasEnabledAfterTarget = true
5190 // Return only integers for enabled weekdays.
5191 return _.isInteger( value )
5198 // Cases to validate for:
5199 // [1] Not inverted and date disabled.
5200 // [2] Inverted and some dates enabled.
5201 // [3] Not inverted and out of range.
5203 // Cases to **not** validate for:
5204 // • Navigating months.
5205 // • Not inverted and date enabled.
5206 // • Inverted and all dates disabled.
5207 // • ..and anything else.
5208 if ( !options || !options.nav ) if (
5209 /* 1 */ ( !isFlippedBase && calendar.disabled( dateObject ) ) ||
5210 /* 2 */ ( isFlippedBase && calendar.disabled( dateObject ) && ( hasEnabledWeekdays || hasEnabledBeforeTarget || hasEnabledAfterTarget ) ) ||
5211 /* 3 */ ( !isFlippedBase && (dateObject.pick <= minLimitObject.pick || dateObject.pick >= maxLimitObject.pick) )
5215 // When inverted, flip the direction if there aren’t any enabled weekdays
5216 // and there are no enabled dates in the direction of the interval.
5217 if ( isFlippedBase && !hasEnabledWeekdays && ( ( !hasEnabledAfterTarget && interval > 0 ) || ( !hasEnabledBeforeTarget && interval < 0 ) ) ) {
5222 // Keep looping until we reach an enabled date.
5223 while ( /*safety &&*/ calendar.disabled( dateObject ) ) {
5227 throw 'Fell into an infinite loop while validating ' + dateObject.obj + '.'
5231 // If we’ve looped into the next/prev month with a large interval, return to the original date and flatten the interval.
5232 if ( Math.abs( interval ) > 1 && ( dateObject.month < originalDateObject.month || dateObject.month > originalDateObject.month ) ) {
5233 dateObject = originalDateObject
5234 interval = interval > 0 ? 1 : -1
5238 // If we’ve reached the min/max limit, reverse the direction, flatten the interval and set it to the limit.
5239 if ( dateObject.pick <= minLimitObject.pick ) {
5242 dateObject = calendar.create([
5243 minLimitObject.year,
5244 minLimitObject.month,
5245 minLimitObject.date + (dateObject.pick === minLimitObject.pick ? 0 : -1)
5248 else if ( dateObject.pick >= maxLimitObject.pick ) {
5251 dateObject = calendar.create([
5252 maxLimitObject.year,
5253 maxLimitObject.month,
5254 maxLimitObject.date + (dateObject.pick === maxLimitObject.pick ? 0 : 1)
5259 // If we’ve reached both limits, just break out of the loop.
5260 if ( reachedMin && reachedMax ) {
5265 // Finally, create the shifted date using the interval and keep looping.
5266 dateObject = calendar.create([ dateObject.year, dateObject.month, dateObject.date + interval ])
5272 // Return the date object settled on.
5274 } //DatePicker.prototype.validate
5278 * Check if a date is disabled.
5280 DatePicker.prototype.disabled = function( dateToVerify ) {
5285 // Filter through the disabled dates to check if this is one.
5286 isDisabledMatch = calendar.item.disable.filter( function( dateToDisable ) {
5288 // If the date is a number, match the weekday with 0index and `firstDay` check.
5289 if ( _.isInteger( dateToDisable ) ) {
5290 return dateToVerify.day === ( calendar.settings.firstDay ? dateToDisable : dateToDisable - 1 ) % 7
5293 // If it’s an array or a native JS date, create and match the exact date.
5294 if ( $.isArray( dateToDisable ) || _.isDate( dateToDisable ) ) {
5295 return dateToVerify.pick === calendar.create( dateToDisable ).pick
5298 // If it’s an object, match a date within the “from” and “to” range.
5299 if ( $.isPlainObject( dateToDisable ) ) {
5300 return calendar.withinRange( dateToDisable, dateToVerify )
5304 // If this date matches a disabled date, confirm it’s not inverted.
5305 isDisabledMatch = isDisabledMatch.length && !isDisabledMatch.filter(function( dateToDisable ) {
5306 return $.isArray( dateToDisable ) && dateToDisable[3] == 'inverted' ||
5307 $.isPlainObject( dateToDisable ) && dateToDisable.inverted
5310 // Check the calendar “enabled” flag and respectively flip the
5311 // disabled state. Then also check if it’s beyond the min/max limits.
5312 return calendar.item.enable === -1 ? !isDisabledMatch : isDisabledMatch ||
5313 dateToVerify.pick < calendar.item.min.pick ||
5314 dateToVerify.pick > calendar.item.max.pick
5316 } //DatePicker.prototype.disabled
5320 * Parse a string into a usable type.
5322 DatePicker.prototype.parse = function( type, value, options ) {
5324 var calendar = this,
5327 // If it’s already parsed, we’re good.
5328 if ( !value || typeof value != 'string' ) {
5332 // We need a `.format` to parse the value with.
5333 if ( !( options && options.format ) ) {
5334 options = options || {}
5335 options.format = calendar.settings.format
5338 // Convert the format into an array and then map through it.
5339 calendar.formats.toArray( options.format ).map( function( label ) {
5342 // Grab the formatting label.
5343 formattingLabel = calendar.formats[ label ],
5345 // The format length is from the formatting label function or the
5346 // label length without the escaping exclamation (!) mark.
5347 formatLength = formattingLabel ? _.trigger( formattingLabel, calendar, [ value, parsingObject ] ) : label.replace( /^!/, '' ).length
5349 // If there's a format label, split the value up to the format length.
5350 // Then add it to the parsing object with appropriate label.
5351 if ( formattingLabel ) {
5352 parsingObject[ label ] = value.substr( 0, formatLength )
5355 // Update the value as the substring from format length to end.
5356 value = value.substr( formatLength )
5359 // Compensate for month 0index.
5361 parsingObject.yyyy || parsingObject.yy,
5362 +( parsingObject.mm || parsingObject.m ) - 1,
5363 parsingObject.dd || parsingObject.d
5365 } //DatePicker.prototype.parse
5369 * Various formats to display the object in.
5371 DatePicker.prototype.formats = (function() {
5373 // Return the length of the first word in a collection.
5374 function getWordLengthFromCollection( string, collection, dateObject ) {
5376 // Grab the first word from the string.
5377 var word = string.match( /\w+/ )[ 0 ]
5379 // If there's no month index, add it to the date object
5380 if ( !dateObject.mm && !dateObject.m ) {
5381 dateObject.m = collection.indexOf( word ) + 1
5384 // Return the length of the word.
5388 // Get the length of the first word in a string.
5389 function getFirstWordLength( string ) {
5390 return string.match( /\w+/ )[ 0 ].length
5395 d: function( string, dateObject ) {
5397 // If there's string, then get the digits length.
5398 // Otherwise return the selected date.
5399 return string ? _.digits( string ) : dateObject.date
5401 dd: function( string, dateObject ) {
5403 // If there's a string, then the length is always 2.
5404 // Otherwise return the selected date with a leading zero.
5405 return string ? 2 : _.lead( dateObject.date )
5407 ddd: function( string, dateObject ) {
5409 // If there's a string, then get the length of the first word.
5410 // Otherwise return the short selected weekday.
5411 return string ? getFirstWordLength( string ) : this.settings.weekdaysShort[ dateObject.day ]
5413 dddd: function( string, dateObject ) {
5415 // If there's a string, then get the length of the first word.
5416 // Otherwise return the full selected weekday.
5417 return string ? getFirstWordLength( string ) : this.settings.weekdaysFull[ dateObject.day ]
5419 m: function( string, dateObject ) {
5421 // If there's a string, then get the length of the digits
5422 // Otherwise return the selected month with 0index compensation.
5423 return string ? _.digits( string ) : dateObject.month + 1
5425 mm: function( string, dateObject ) {
5427 // If there's a string, then the length is always 2.
5428 // Otherwise return the selected month with 0index and leading zero.
5429 return string ? 2 : _.lead( dateObject.month + 1 )
5431 mmm: function( string, dateObject ) {
5433 var collection = this.settings.monthsShort
5435 // If there's a string, get length of the relevant month from the short
5436 // months collection. Otherwise return the selected month from that collection.
5437 return string ? getWordLengthFromCollection( string, collection, dateObject ) : collection[ dateObject.month ]
5439 mmmm: function( string, dateObject ) {
5441 var collection = this.settings.monthsFull
5443 // If there's a string, get length of the relevant month from the full
5444 // months collection. Otherwise return the selected month from that collection.
5445 return string ? getWordLengthFromCollection( string, collection, dateObject ) : collection[ dateObject.month ]
5447 yy: function( string, dateObject ) {
5449 // If there's a string, then the length is always 2.
5450 // Otherwise return the selected year by slicing out the first 2 digits.
5451 return string ? 2 : ( '' + dateObject.year ).slice( 2 )
5453 yyyy: function( string, dateObject ) {
5455 // If there's a string, then the length is always 4.
5456 // Otherwise return the selected year.
5457 return string ? 4 : dateObject.year
5460 // Create an array by splitting the formatting string passed.
5461 toArray: function( formatString ) { return formatString.split( /(d{1,4}|m{1,4}|y{4}|yy|!.)/g ) },
5463 // Format an object into a string using the formatting options.
5464 toString: function ( formatString, itemObject ) {
5466 return calendar.formats.toArray( formatString ).map( function( label ) {
5467 return _.trigger( calendar.formats[ label ], calendar, [ 0, itemObject ] ) || label.replace( /^!/, '' )
5471 })() //DatePicker.prototype.formats
5477 * Check if two date units are the exact.
5479 DatePicker.prototype.isDateExact = function( one, two ) {
5483 // When we’re working with weekdays, do a direct comparison.
5485 ( _.isInteger( one ) && _.isInteger( two ) ) ||
5486 ( typeof one == 'boolean' && typeof two == 'boolean' )
5491 // When we’re working with date representations, compare the “pick” value.
5493 ( _.isDate( one ) || $.isArray( one ) ) &&
5494 ( _.isDate( two ) || $.isArray( two ) )
5496 return calendar.create( one ).pick === calendar.create( two ).pick
5499 // When we’re working with range objects, compare the “from” and “to”.
5500 if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
5501 return calendar.isDateExact( one.from, two.from ) && calendar.isDateExact( one.to, two.to )
5509 * Check if two date units overlap.
5511 DatePicker.prototype.isDateOverlap = function( one, two ) {
5513 var calendar = this,
5514 firstDay = calendar.settings.firstDay ? 1 : 0
5516 // When we’re working with a weekday index, compare the days.
5517 if ( _.isInteger( one ) && ( _.isDate( two ) || $.isArray( two ) ) ) {
5518 one = one % 7 + firstDay
5519 return one === calendar.create( two ).day + 1
5521 if ( _.isInteger( two ) && ( _.isDate( one ) || $.isArray( one ) ) ) {
5522 two = two % 7 + firstDay
5523 return two === calendar.create( one ).day + 1
5526 // When we’re working with range objects, check if the ranges overlap.
5527 if ( $.isPlainObject( one ) && $.isPlainObject( two ) ) {
5528 return calendar.overlapRanges( one, two )
5536 * Flip the “enabled” state.
5538 DatePicker.prototype.flipEnable = function(val) {
5539 var itemObject = this.item
5540 itemObject.enable = val || (itemObject.enable == -1 ? 1 : -1)
5545 * Mark a collection of dates as “disabled”.
5547 DatePicker.prototype.deactivate = function( type, datesToDisable ) {
5549 var calendar = this,
5550 disabledItems = calendar.item.disable.slice(0)
5553 // If we’re flipping, that’s all we need to do.
5554 if ( datesToDisable == 'flip' ) {
5555 calendar.flipEnable()
5558 else if ( datesToDisable === false ) {
5559 calendar.flipEnable(1)
5563 else if ( datesToDisable === true ) {
5564 calendar.flipEnable(-1)
5568 // Otherwise go through the dates to disable.
5571 datesToDisable.map(function( unitToDisable ) {
5575 // When we have disabled items, check for matches.
5576 // If something is matched, immediately break out.
5577 for ( var index = 0; index < disabledItems.length; index += 1 ) {
5578 if ( calendar.isDateExact( unitToDisable, disabledItems[index] ) ) {
5584 // If nothing was found, add the validated unit to the collection.
5585 if ( !matchFound ) {
5587 _.isInteger( unitToDisable ) ||
5588 _.isDate( unitToDisable ) ||
5589 $.isArray( unitToDisable ) ||
5590 ( $.isPlainObject( unitToDisable ) && unitToDisable.from && unitToDisable.to )
5592 disabledItems.push( unitToDisable )
5598 // Return the updated collection.
5599 return disabledItems
5600 } //DatePicker.prototype.deactivate
5604 * Mark a collection of dates as “enabled”.
5606 DatePicker.prototype.activate = function( type, datesToEnable ) {
5608 var calendar = this,
5609 disabledItems = calendar.item.disable,
5610 disabledItemsCount = disabledItems.length
5612 // If we’re flipping, that’s all we need to do.
5613 if ( datesToEnable == 'flip' ) {
5614 calendar.flipEnable()
5617 else if ( datesToEnable === true ) {
5618 calendar.flipEnable(1)
5622 else if ( datesToEnable === false ) {
5623 calendar.flipEnable(-1)
5627 // Otherwise go through the disabled dates.
5630 datesToEnable.map(function( unitToEnable ) {
5637 // Go through the disabled items and try to find a match.
5638 for ( index = 0; index < disabledItemsCount; index += 1 ) {
5640 disabledUnit = disabledItems[index]
5642 // When an exact match is found, remove it from the collection.
5643 if ( calendar.isDateExact( disabledUnit, unitToEnable ) ) {
5644 matchFound = disabledItems[index] = null
5649 // When an overlapped match is found, add the “inverted” state to it.
5650 else if ( calendar.isDateOverlap( disabledUnit, unitToEnable ) ) {
5651 if ( $.isPlainObject( unitToEnable ) ) {
5652 unitToEnable.inverted = true
5653 matchFound = unitToEnable
5655 else if ( $.isArray( unitToEnable ) ) {
5656 matchFound = unitToEnable
5657 if ( !matchFound[3] ) matchFound.push( 'inverted' )
5659 else if ( _.isDate( unitToEnable ) ) {
5660 matchFound = [ unitToEnable.getFullYear(), unitToEnable.getMonth(), unitToEnable.getDate(), 'inverted' ]
5666 // If a match was found, remove a previous duplicate entry.
5667 if ( matchFound ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
5668 if ( calendar.isDateExact( disabledItems[index], unitToEnable ) ) {
5669 disabledItems[index] = null
5674 // In the event that we’re dealing with an exact range of dates,
5675 // make sure there are no “inverted” dates because of it.
5676 if ( isExactRange ) for ( index = 0; index < disabledItemsCount; index += 1 ) {
5677 if ( calendar.isDateOverlap( disabledItems[index], unitToEnable ) ) {
5678 disabledItems[index] = null
5683 // If something is still matched, add it into the collection.
5685 disabledItems.push( matchFound )
5690 // Return the updated collection.
5691 return disabledItems.filter(function( val ) { return val != null })
5692 } //DatePicker.prototype.activate
5696 * Create a string for the nodes in the picker.
5698 DatePicker.prototype.nodes = function( isOpen ) {
5702 settings = calendar.settings,
5703 calendarItem = calendar.item,
5704 nowObject = calendarItem.now,
5705 selectedObject = calendarItem.select,
5706 highlightedObject = calendarItem.highlight,
5707 viewsetObject = calendarItem.view,
5708 disabledCollection = calendarItem.disable,
5709 minLimitObject = calendarItem.min,
5710 maxLimitObject = calendarItem.max,
5713 // Create the calendar table head using a copy of weekday labels collection.
5714 // * We do a copy so we don't mutate the original array.
5715 tableHead = (function( collection, fullCollection ) {
5717 // If the first day should be Monday, move Sunday to the end.
5718 if ( settings.firstDay ) {
5719 collection.push( collection.shift() )
5720 fullCollection.push( fullCollection.shift() )
5723 // Create and return the table head group.
5730 max: DAYS_IN_WEEK - 1,
5733 item: function( counter ) {
5735 collection[ counter ],
5736 settings.klass.weekdays,
5737 'scope=col title="' + fullCollection[ counter ] + '"'
5744 // Materialize modified
5745 })( ( settings.showWeekdaysFull ? settings.weekdaysFull : settings.weekdaysLetter ).slice( 0 ), settings.weekdaysFull.slice( 0 ) ), //tableHead
5748 // Create the nav for next/prev month.
5749 createMonthNav = function( next ) {
5751 // Otherwise, return the created month tag.
5755 settings.klass[ 'nav' + ( next ? 'Next' : 'Prev' ) ] + (
5757 // If the focused month is outside the range, disabled the button.
5758 ( next && viewsetObject.year >= maxLimitObject.year && viewsetObject.month >= maxLimitObject.month ) ||
5759 ( !next && viewsetObject.year <= minLimitObject.year && viewsetObject.month <= minLimitObject.month ) ?
5760 ' ' + settings.klass.navDisabled : ''
5762 'data-nav=' + ( next || -1 ) + ' ' +
5765 controls: calendar.$node[0].id + '_table'
5767 'title="' + (next ? settings.labelMonthNext : settings.labelMonthPrev ) + '"'
5772 // Create the month label.
5773 //Materialize modified
5774 createMonthLabel = function(override) {
5776 var monthsCollection = settings.showMonthsShort ? settings.monthsShort : settings.monthsFull
5778 // Materialize modified
5779 if (override == "short_months
") {
5780 monthsCollection = settings.monthsShort;
5783 // If there are months to select, add a dropdown menu.
5784 if ( settings.selectMonths && override == undefined) {
5786 return _.node( 'select',
5792 item: function( loopedMonth ) {
5796 // The looped month and no classes.
5797 monthsCollection[ loopedMonth ], 0,
5799 // Set the value and selected index.
5800 'value=' + loopedMonth +
5801 ( viewsetObject.month == loopedMonth ? ' selected' : '' ) +
5804 ( viewsetObject.year == minLimitObject.year && loopedMonth < minLimitObject.month ) ||
5805 ( viewsetObject.year == maxLimitObject.year && loopedMonth > maxLimitObject.month )
5812 settings.klass.selectMonth + ' browser-default',
5813 ( isOpen ? '' : 'disabled' ) + ' ' +
5814 _.ariaAttr({ controls: calendar.$node[0].id + '_table' }) + ' ' +
5815 'title="' + settings.labelMonthSelect + '"'
5819 // Materialize modified
5820 if (override == "short_months
")
5821 if (selectedObject != null)
5822 return _.node( 'div', monthsCollection[ selectedObject.month ] );
5823 else return _.node( 'div', monthsCollection[ viewsetObject.month ] );
5825 // If there's a need for a month selector
5826 return _.node( 'div', monthsCollection[ viewsetObject.month ], settings.klass.month )
5827 }, //createMonthLabel
5830 // Create the year label.
5831 // Materialize modified
5832 createYearLabel = function(override) {
5834 var focusedYear = viewsetObject.year,
5836 // If years selector is set to a literal "true", set it to 5. Otherwise
5837 // divide in half to get half before and half after focused year.
5838 numberYears = settings.selectYears === true ? 5 : ~~( settings.selectYears / 2 )
5840 // If there are years to select, add a dropdown menu.
5841 if ( numberYears ) {
5844 minYear = minLimitObject.year,
5845 maxYear = maxLimitObject.year,
5846 lowestYear = focusedYear - numberYears,
5847 highestYear = focusedYear + numberYears
5849 // If the min year is greater than the lowest year, increase the highest year
5850 // by the difference and set the lowest year to the min year.
5851 if ( minYear > lowestYear ) {
5852 highestYear += minYear - lowestYear
5853 lowestYear = minYear
5856 // If the max year is less than the highest year, decrease the lowest year
5857 // by the lower of the two: available and needed years. Then set the
5858 // highest year to the max year.
5859 if ( maxYear < highestYear ) {
5861 var availableYears = lowestYear - minYear,
5862 neededYears = highestYear - maxYear
5864 lowestYear -= availableYears > neededYears ? neededYears : availableYears
5865 highestYear = maxYear
5868 if ( settings.selectYears && override == undefined ) {
5869 return _.node( 'select',
5875 item: function( loopedYear ) {
5878 // The looped year and no classes.
5881 // Set the value and selected index.
5882 'value=' + loopedYear + ( focusedYear == loopedYear ? ' selected' : '' )
5886 settings.klass.selectYear + ' browser-default',
5887 ( isOpen ? '' : 'disabled' ) + ' ' + _.ariaAttr({ controls: calendar.$node[0].id + '_table' }) + ' ' +
5888 'title="' + settings.labelYearSelect + '"'
5893 // Materialize modified
5894 if (override == "raw
")
5895 return _.node( 'div', focusedYear )
5897 // Otherwise just return the year focused
5898 return _.node( 'div', focusedYear, settings.klass.year )
5902 // Materialize modified
5903 createDayLabel = function() {
5904 if (selectedObject != null)
5905 return _.node( 'div', selectedObject.date)
5906 else return _.node( 'div', nowObject.date)
5908 createWeekdayLabel = function() {
5911 if (selectedObject != null)
5912 display_day = selectedObject.day;
5914 display_day = nowObject.day;
5915 var weekday = settings.weekdaysFull[ display_day ]
5920 // Create and return the entire calendar.
5922 // Date presentation View
5926 createWeekdayLabel(),
5927 "picker__weekday
-display
"
5930 // Div for short Month
5932 createMonthLabel("short_months
"),
5933 settings.klass.month_display
5939 settings.klass.day_display
5944 createYearLabel("raw
") ,
5945 settings.klass.year_display
5947 settings.klass.date_display
5949 // Calendar container
5952 ( settings.selectYears ? createMonthLabel() + createYearLabel() : createMonthLabel() + createYearLabel() ) +
5953 createMonthNav() + createMonthNav( 1 ),
5954 settings.klass.header
5962 max: WEEKS_IN_CALENDAR - 1,
5965 item: function( rowCounter ) {
5967 // If Monday is the first day and the month starts on Sunday, shift the date back a week.
5968 var shiftDateBy = settings.firstDay && calendar.create([ viewsetObject.year, viewsetObject.month, 1 ]).day === 0 ? -7 : 0
5972 min: DAYS_IN_WEEK * rowCounter - viewsetObject.day + shiftDateBy + 1, // Add 1 for weekday 0index
5974 return this.min + DAYS_IN_WEEK - 1
5978 item: function( targetDate ) {
5980 // Convert the time date from a relative date to a target date.
5981 targetDate = calendar.create([ viewsetObject.year, viewsetObject.month, targetDate + ( settings.firstDay ? 1 : 0 ) ])
5983 var isSelected = selectedObject && selectedObject.pick == targetDate.pick,
5984 isHighlighted = highlightedObject && highlightedObject.pick == targetDate.pick,
5985 isDisabled = disabledCollection && calendar.disabled( targetDate ) || targetDate.pick < minLimitObject.pick || targetDate.pick > maxLimitObject.pick,
5986 formattedDate = _.trigger( calendar.formats.toString, calendar, [ settings.format, targetDate ] )
5992 (function( klasses ) {
5994 // Add the `infocus` or `outfocus` classes based on month in view.
5995 klasses.push( viewsetObject.month == targetDate.month ? settings.klass.infocus : settings.klass.outfocus )
5997 // Add the `today` class if needed.
5998 if ( nowObject.pick == targetDate.pick ) {
5999 klasses.push( settings.klass.now )
6002 // Add the `selected` class if something's selected and the time matches.
6004 klasses.push( settings.klass.selected )
6007 // Add the `highlighted` class if something's highlighted and the time matches.
6008 if ( isHighlighted ) {
6009 klasses.push( settings.klass.highlighted )
6012 // Add the `disabled` class if something's disabled and the object matches.
6014 klasses.push( settings.klass.disabled )
6017 return klasses.join( ' ' )
6018 })([ settings.klass.day ]),
6019 'data-pick=' + targetDate.pick + ' ' + _.ariaAttr({
6021 label: formattedDate,
6022 selected: isSelected && calendar.$node.val() === formattedDate ? true : null,
6023 activedescendant: isHighlighted ? true : null,
6024 disabled: isDisabled ? true : null
6028 _.ariaAttr({ role: 'presentation' })
6036 settings.klass.table,
6037 'id="' + calendar.$node[0].id + '_table
' + '" ' + _.ariaAttr({
6039 controls: calendar.$node[0].id,
6043 , settings.klass.calendar_container) // end calendar
6047 // * For Firefox forms to submit, make sure to set the buttons’ `type` attributes as “button”.
6050 _.node( 'button', settings.today, "btn
-flat picker__today
",
6051 'type=button data-pick=' + nowObject.pick +
6052 ( isOpen && !calendar.disabled(nowObject) ? '' : ' disabled' ) + ' ' +
6053 _.ariaAttr({ controls: calendar.$node[0].id }) ) +
6054 _.node( 'button', settings.clear, "btn
-flat picker__clear
",
6055 'type=button data-clear=1' +
6056 ( isOpen ? '' : ' disabled' ) + ' ' +
6057 _.ariaAttr({ controls: calendar.$node[0].id }) ) +
6058 _.node('button', settings.close, "btn
-flat picker__close
",
6059 'type=button data-close=true ' +
6060 ( isOpen ? '' : ' disabled' ) + ' ' +
6061 _.ariaAttr({ controls: calendar.$node[0].id }) ),
6062 settings.klass.footer
6064 } //DatePicker.prototype.nodes
6070 * The date picker defaults.
6072 DatePicker.defaults = (function( prefix ) {
6076 // The title label to use for the month nav buttons
6077 labelMonthNext: 'Next month',
6078 labelMonthPrev: 'Previous month',
6080 // The title label to use for the dropdown selectors
6081 labelMonthSelect: 'Select a month',
6082 labelYearSelect: 'Select a year',
6084 // Months and weekdays
6085 monthsFull: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ],
6086 monthsShort: [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ],
6087 weekdaysFull: [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' ],
6088 weekdaysShort: [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ],
6090 // Materialize modified
6091 weekdaysLetter: [ 'S', 'M', 'T', 'W', 'T', 'F', 'S' ],
6098 // The format to show on the `input` element
6099 format: 'd mmmm, yyyy',
6104 table: prefix + 'table',
6106 header: prefix + 'header',
6109 // Materialize Added klasses
6110 date_display: prefix + 'date-display',
6111 day_display: prefix + 'day-display',
6112 month_display: prefix + 'month-display',
6113 year_display: prefix + 'year-display',
6114 calendar_container: prefix + 'calendar-container',
6119 navPrev: prefix + 'nav--prev',
6120 navNext: prefix + 'nav--next',
6121 navDisabled: prefix + 'nav--disabled',
6123 month: prefix + 'month',
6124 year: prefix + 'year',
6126 selectMonth: prefix + 'select--month',
6127 selectYear: prefix + 'select--year',
6129 weekdays: prefix + 'weekday',
6131 day: prefix + 'day',
6132 disabled: prefix + 'day--disabled',
6133 selected: prefix + 'day--selected',
6134 highlighted: prefix + 'day--highlighted',
6135 now: prefix + 'day--today',
6136 infocus: prefix + 'day--infocus',
6137 outfocus: prefix + 'day--outfocus',
6139 footer: prefix + 'footer',
6141 buttonClear: prefix + 'button--clear',
6142 buttonToday: prefix + 'button--today',
6143 buttonClose: prefix + 'button--close'
6146 })( Picker.klasses().picker + '__' )
6153 * Extend the picker to add the date picker.
6155 Picker.extend( 'pickadate', DatePicker )
6163 $.fn.characterCounter = function(){
6164 return this.each(function(){
6166 var itHasLengthAttribute = $(this).attr('length') !== undefined;
6168 if(itHasLengthAttribute){
6169 $(this).on('input', updateCounter);
6170 $(this).on('focus', updateCounter);
6171 $(this).on('blur', removeCounterElement);
6173 addCounterElement($(this));
6179 function updateCounter(){
6180 var maxLength = +$(this).attr('length'),
6181 actualLength = +$(this).val().length,
6182 isValidLength = actualLength <= maxLength;
6184 $(this).parent().find('span[class="character
-counter
"]')
6185 .html( actualLength + '/' + maxLength);
6187 addInputStyle(isValidLength, $(this));
6190 function addCounterElement($input){
6191 var $counterElement = $('<span/>')
6192 .addClass('character-counter')
6193 .css('float','right')
6194 .css('font-size','12px')
6197 $input.parent().append($counterElement);
6200 function removeCounterElement(){
6201 $(this).parent().find('span[class="character
-counter
"]').html('');
6204 function addInputStyle(isValidLength, $input){
6205 var inputHasInvalidClass = $input.hasClass('invalid');
6206 if (isValidLength && inputHasInvalidClass) {
6207 $input.removeClass('invalid');
6209 else if(!isValidLength && !inputHasInvalidClass){
6210 $input.removeClass('valid');
6211 $input.addClass('invalid');
6215 $(document).ready(function(){
6216 $('input, textarea').characterCounter();