aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/Wallabag/CoreBundle/Resources/public/themes/material/js/materialize.js
diff options
context:
space:
mode:
authorThomas Citharel <tcit@tcit.fr>2016-03-08 17:02:34 +0100
committerThomas Citharel <tcit@tcit.fr>2016-06-09 17:12:51 +0200
commit5ecdfcd041767c9e3244a92bb0a6cc3c3f80fea3 (patch)
tree03ee1eab0d89d1857daca9e273fd8c9ca47e33c2 /src/Wallabag/CoreBundle/Resources/public/themes/material/js/materialize.js
parent9f95b14dec88cf083cefa38d5fbd84189e07acac (diff)
downloadwallabag-5ecdfcd041767c9e3244a92bb0a6cc3c3f80fea3.tar.gz
wallabag-5ecdfcd041767c9e3244a92bb0a6cc3c3f80fea3.tar.zst
wallabag-5ecdfcd041767c9e3244a92bb0a6cc3c3f80fea3.zip
manage assets through npm
first draft remote assetic totally work nearly there use at least nodejs > 0.12 use proper version of grunt bump nodejs version for travis update npm workaround for materialize install node 5.0 add grunt-cli baggy theme & cache node modules cache bower & npm make travis build assets on php7 only exclude installing node & npm if not needed & use bash clean & try to make icomoon work on baggy ready config for travis rebase make travis work more travis work impove travis & update deps add missing pixrem deps add module through oddly lost ui updates install latest nodejs add install_dev.sh, link local binaries for npm/bower/grunt ui improvements (mostly baggy) fix travis build no need to install on travis Add unread filter to entries pages Add the ability to filter for unread pages in the filters menu. Add unread filter test to EntryControllerTest Add a new test to the EntryControllerTest collection which checks that only entries which have not been archived (and are treated as "unread") are retrieved. Improve English translation Update FAQ -Fix grammar -Add notes about MTA, firewall, and SELinux Update installation instructions -Fix grammar -Add SELinux section add screenshots of android docu in English Fix the deletion of Tags/Entries relation when delete an entry Fix #2121 Move fixtures to the right place Display a message when saving an entry failed When saving an entry fail because of database error we previously just returned `false`. Now we got an error in the log and the displayed notice to the user is updated too. Change ManyToMany between entry & tag Following https://gist.github.com/Ocramius/3121916 Be sure to remove the related entity when removing an entity. Let say you have Entry -> EntryTag -> Tag. If you remove the entry: - before that commit, the EntryTag will stay (at least using SQLite). - with that commit, the related entity is removed Prepare wallabag 2.0.5 enforce older materialize version
Diffstat (limited to 'src/Wallabag/CoreBundle/Resources/public/themes/material/js/materialize.js')
-rw-r--r--src/Wallabag/CoreBundle/Resources/public/themes/material/js/materialize.js6219
1 files changed, 0 insertions, 6219 deletions
diff --git a/src/Wallabag/CoreBundle/Resources/public/themes/material/js/materialize.js b/src/Wallabag/CoreBundle/Resources/public/themes/material/js/materialize.js
deleted file mode 100644
index b7242f6b..00000000
--- a/src/Wallabag/CoreBundle/Resources/public/themes/material/js/materialize.js
+++ /dev/null
@@ -1,6219 +0,0 @@
1/*!
2 * Materialize v0.97.1 (http://materializecss.com)
3 * Copyright 2014-2015 Materialize
4 * MIT License (https://raw.githubusercontent.com/Dogfalo/materialize/master/LICENSE)
5 */
6/*
7 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
8 *
9 * Uses the built in easing capabilities added In jQuery 1.1
10 * to offer multiple easing options
11 *
12 * TERMS OF USE - jQuery Easing
13 *
14 * Open source under the BSD License.
15 *
16 * Copyright © 2008 George McGinley Smith
17 * All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without modification,
20 * are permitted provided that the following conditions are met:
21 *
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.
27 *
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.
30 *
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.
40 *
41*/
42
43// t: current time, b: begInnIng value, c: change In value, d: duration
44jQuery.easing['jswing'] = jQuery.easing['swing'];
45
46jQuery.extend( jQuery.easing,
47{
48 def: 'easeOutQuad',
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);
52 },
53 easeInQuad: function (x, t, b, c, d) {
54 return c*(t/=d)*t + b;
55 },
56 easeOutQuad: function (x, t, b, c, d) {
57 return -c *(t/=d)*(t-2) + b;
58 },
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;
62 },
63 easeInCubic: function (x, t, b, c, d) {
64 return c*(t/=d)*t*t + b;
65 },
66 easeOutCubic: function (x, t, b, c, d) {
67 return c*((t=t/d-1)*t*t + 1) + b;
68 },
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;
72 },
73 easeInQuart: function (x, t, b, c, d) {
74 return c*(t/=d)*t*t*t + b;
75 },
76 easeOutQuart: function (x, t, b, c, d) {
77 return -c * ((t=t/d-1)*t*t*t - 1) + b;
78 },
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;
82 },
83 easeInQuint: function (x, t, b, c, d) {
84 return c*(t/=d)*t*t*t*t + b;
85 },
86 easeOutQuint: function (x, t, b, c, d) {
87 return c*((t=t/d-1)*t*t*t*t + 1) + b;
88 },
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;
92 },
93 easeInSine: function (x, t, b, c, d) {
94 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
95 },
96 easeOutSine: function (x, t, b, c, d) {
97 return c * Math.sin(t/d * (Math.PI/2)) + b;
98 },
99 easeInOutSine: function (x, t, b, c, d) {
100 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
101 },
102 easeInExpo: function (x, t, b, c, d) {
103 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
104 },
105 easeOutExpo: function (x, t, b, c, d) {
106 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
107 },
108 easeInOutExpo: function (x, t, b, c, d) {
109 if (t==0) return b;
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;
113 },
114 easeInCirc: function (x, t, b, c, d) {
115 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
116 },
117 easeOutCirc: function (x, t, b, c, d) {
118 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
119 },
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;
123 },
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;
130 },
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;
137 },
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;
145 },
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;
149 },
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;
153 },
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;
158 },
159 easeInBounce: function (x, t, b, c, d) {
160 return c - jQuery.easing.easeOutBounce (x, d-t, 0, c, d) + b;
161 },
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;
169 } else {
170 return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
171 }
172 },
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;
176 }
177});
178
179/*
180 *
181 * TERMS OF USE - EASING EQUATIONS
182 *
183 * Open source under the BSD License.
184 *
185 * Copyright © 2001 Robert Penner
186 * All rights reserved.
187 *
188 * Redistribution and use in source and binary forms, with or without modification,
189 * are permitted provided that the following conditions are met:
190 *
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.
196 *
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.
199 *
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.
209 *
210 */; // Custom Easing
211 jQuery.extend( jQuery.easing,
212 {
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;
216 }
217 });
218
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'));
227 } else {
228 factory(jQuery, Hammer);
229 }
230}(function($, Hammer) {
231 function hammerify(el, options) {
232 var $el = $(el);
233 if(!$el.data("hammer")) {
234 $el.data("hammer", new Hammer($el[0], options));
235 }
236 }
237
238 $.fn.hammer = function(options) {
239 return this.each(function() {
240 hammerify(this, options);
241 });
242 };
243
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({
249 type: type,
250 gesture: data
251 });
252 };
253 })(Hammer.Manager.prototype.emit);
254}));
255;window.Materialize = {};
256
257// Unique ID
258Materialize.guid = (function() {
259 function s4() {
260 return Math.floor((1 + Math.random()) * 0x10000)
261 .toString(16)
262 .substring(1);
263 }
264 return function() {
265 return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
266 s4() + '-' + s4() + s4() + s4();
267 };
268})();
269
270Materialize.elementOrParentIsFixed = function(element) {
271 var $element = $(element);
272 var $checkElements = $element.add($element.parents());
273 var isFixed = false;
274 $checkElements.each(function(){
275 if ($(this).css("position") === "fixed") {
276 isFixed = true;
277 return false;
278 }
279 });
280 return isFixed;
281};
282
283// Velocity has conflicts when loaded with jQuery, this will check for it
284var Vel;
285if ($) {
286 Vel = $.Velocity;
287}
288else {
289 Vel = Velocity;
290}
291;(function ($) {
292 $.fn.collapsible = function(options) {
293 var defaults = {
294 accordion: undefined
295 };
296
297 options = $.extend(defaults, options);
298
299
300 return this.each(function() {
301
302 var $this = $(this);
303
304 var $panel_headers = $(this).find('> li > .collapsible-header');
305
306 var collapsible_type = $this.data("collapsible");
307
308 // Turn off any existing event handlers
309 $this.off('click.collapse', '.collapsible-header');
310 $panel_headers.off('click.collapse');
311
312
313 /****************
314 Helper Functions
315 ****************/
316
317 // Accordion Open
318 function accordionOpen(object) {
319 $panel_headers = $this.find('> li > .collapsible-header');
320 if (object.hasClass('active')) {
321 object.parent().addClass('active');
322 }
323 else {
324 object.parent().removeClass('active');
325 }
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', '');}});
328 }
329 else{
330 object.siblings('.collapsible-body').stop(true,false).slideUp({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
331 }
332
333 $panel_headers.not(object).removeClass('active').parent().removeClass('active');
334 $panel_headers.not(object).parent().children('.collapsible-body').stop(true,false).slideUp(
335 {
336 duration: 350,
337 easing: "easeOutQuart",
338 queue: false,
339 complete:
340 function() {
341 $(this).css('height', '');
342 }
343 });
344 }
345
346 // Expandable Open
347 function expandableOpen(object) {
348 if (object.hasClass('active')) {
349 object.parent().addClass('active');
350 }
351 else {
352 object.parent().removeClass('active');
353 }
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', '');}});
356 }
357 else{
358 object.siblings('.collapsible-body').stop(true,false).slideUp({ duration: 350, easing: "easeOutQuart", queue: false, complete: function() {$(this).css('height', '');}});
359 }
360 }
361
362 /**
363 * Check if object is children of panel header
364 * @param {Object} object Jquery object
365 * @return {Boolean} true if it is children
366 */
367 function isChildrenOfPanelHeader(object) {
368
369 var panelHeader = getPanelHeader(object);
370
371 return panelHeader.length > 0;
372 }
373
374 /**
375 * Get panel header from a children element
376 * @param {Object} object Jquery object
377 * @return {Object} panel header object
378 */
379 function getPanelHeader(object) {
380
381 return object.closest('li > .collapsible-header');
382 }
383
384 /***** End Helper Functions *****/
385
386
387
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);
393
394 if (isChildrenOfPanelHeader(element)) {
395 element = getPanelHeader(element);
396 }
397
398 element.toggleClass('active');
399 accordionOpen(element);
400 });
401 // Open first active
402 accordionOpen($panel_headers.filter('.active').first());
403 }
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);
411 }
412 element.toggleClass('active');
413 expandableOpen(element);
414 });
415 // Open any bodies that have the active class
416 if ($(this).hasClass('active')) {
417 expandableOpen($(this));
418 }
419
420 });
421 }
422
423 });
424 };
425
426 $(document).ready(function(){
427 $('.collapsible').collapsible();
428 });
429}( jQuery ));;(function ($) {
430
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);
435 return this;
436 };
437
438 $.fn.dropdown = function (option) {
439 var defaults = {
440 inDuration: 300,
441 outDuration: 225,
442 constrain_width: true, // Constrains width of dropdown to the activator
443 hover: false,
444 gutter: 0, // Spacing from edge
445 belowOrigin: false,
446 alignment: 'left'
447 };
448
449 this.each(function(){
450 var origin = $(this);
451 var options = $.extend({}, defaults, option);
452
453 // Dropdown menu
454 var activates = $("#"+ origin.attr('data-activates'));
455
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');
471 }
472
473 updateOptions();
474
475 // Attach dropdown to its activator
476 origin.after(activates);
477
478 /*
479 Helper function to position and resize dropdown.
480 Used in hover and click handler.
481 */
482 function placeDropdown() {
483 // Check html data attributes
484 updateOptions();
485
486 // Set Dropdown state
487 activates.addClass('active');
488
489 // Constrain width
490 if (options.constrain_width === true) {
491 activates.css('width', origin.outerWidth());
492 }
493 else {
494 activates.css('white-space', 'nowrap');
495 }
496 var offset = 0;
497 if (options.belowOrigin === true) {
498 offset = origin.height();
499 }
500
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';
506 }
507 else if (offsetLeft - activates.innerWidth() + origin.innerWidth() < 0) {
508 options.alignment = 'left';
509 }
510
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;
516
517 // Position dropdown
518 activates.css({ left: activatesLeft });
519 }
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;
525
526 // Position dropdown
527 activates.css({ right: activatesLeft });
528 }
529 // Position dropdown
530 activates.css({
531 position: 'absolute',
532 top: origin.position().top + offset,
533 });
534
535
536
537 // Show dropdown
538 activates.stop(true, true).css('opacity', 0)
539 .slideDown({
540 queue: false,
541 duration: options.inDuration,
542 easing: 'easeOutCubic',
543 complete: function() {
544 $(this).css('height', '');
545 }
546 })
547 .animate( {opacity: 1}, {queue: false, duration: options.inDuration, easing: 'easeOutSine'});
548 }
549
550 function hideDropdown() {
551 activates.fadeOut(options.outDuration);
552 activates.removeClass('active');
553 }
554
555 // Hover
556 if (options.hover) {
557 var open = false;
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) {
562 placeDropdown();
563 open = true;
564 }
565 });
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);
571 hideDropdown();
572 open = false;
573 }
574 });
575
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);
580 hideDropdown();
581 open = false;
582 }
583 });
584
585 // Click
586 } else {
587
588 // Click handler to show dropdown
589 origin.unbind('click.' + origin.attr('id'));
590 origin.bind('click.'+origin.attr('id'), function(e){
591
592 if ( origin[0] == e.currentTarget && ($(e.target).closest('.dropdown-content').length === 0) ) {
593 e.preventDefault(); // Prevents button click from moving window
594 placeDropdown();
595
596 }
597 // If origin is clicked and menu is open, close menu
598 else {
599 if (origin.hasClass('active')) {
600 hideDropdown();
601 $(document).unbind('click.' + activates.attr('id'));
602 }
603 }
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) ) {
608 hideDropdown();
609 $(document).unbind('click.' + activates.attr('id'));
610 }
611 });
612 }
613 });
614
615 } // End else
616
617 // Listen to open and close event - useful for select component
618 origin.on('open', placeDropdown);
619 origin.on('close', hideDropdown);
620
621
622 });
623 }; // End dropdown plugin
624
625 $(document).ready(function(){
626 $('.dropdown-button').dropdown();
627 });
628}( jQuery ));
629;(function($) {
630 var _stack = 0,
631 _lastID = 0,
632 _generateID = function() {
633 _lastID++;
634 return 'materialize-lean-overlay-' + _lastID;
635 };
636
637 $.fn.extend({
638 openModal: function(options) {
639
640 $('body').css('overflow', 'hidden');
641
642 var defaults = {
643 opacity: 0.5,
644 in_duration: 350,
645 out_duration: 250,
646 ready: undefined,
647 complete: undefined,
648 dismissible: true,
649 starting_top: '4%'
650 },
651 overlayID = _generateID(),
652 $modal = $(this),
653 $overlay = $('<div class="lean-overlay"></div>'),
654 lStack = (++_stack);
655
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);
659
660 $("body").append($overlay);
661
662 // Override defaults
663 options = $.extend(defaults, options);
664
665 if (options.dismissible) {
666 $overlay.click(function() {
667 $modal.closeModal(options);
668 });
669 // Return on ESC
670 $(document).on('keyup.leanModal' + overlayID, function(e) {
671 if (e.keyCode === 27) { // ESC key
672 $modal.closeModal(options);
673 }
674 });
675 }
676
677 $modal.find(".modal-close").on('click.close', function(e) {
678 $modal.closeModal(options);
679 });
680
681 $overlay.css({ display : "block", opacity : 0 });
682
683 $modal.css({
684 display : "block",
685 opacity: 0
686 });
687
688 $overlay.velocity({opacity: options.opacity}, {duration: options.in_duration, queue: false, ease: "easeOutCubic"});
689 $modal.data('associated-overlay', $overlay[0]);
690
691 // Define Bottom Sheet animation
692 if ($modal.hasClass('bottom-sheet')) {
693 $modal.velocity({bottom: "0", opacity: 1}, {
694 duration: options.in_duration,
695 queue: false,
696 ease: "easeOutCubic",
697 // Handle modal ready callback
698 complete: function() {
699 if (typeof(options.ready) === "function") {
700 options.ready();
701 }
702 }
703 });
704 }
705 else {
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,
710 queue: false,
711 ease: "easeOutCubic",
712 // Handle modal ready callback
713 complete: function() {
714 if (typeof(options.ready) === "function") {
715 options.ready();
716 }
717 }
718 });
719 }
720
721
722 }
723 });
724
725 $.fn.extend({
726 closeModal: function(options) {
727 var defaults = {
728 out_duration: 250,
729 complete: undefined
730 },
731 $modal = $(this),
732 overlayID = $modal.data('overlay-id'),
733 $overlay = $('#' + overlayID);
734
735 options = $.extend(defaults, options);
736
737 // Disable scrolling
738 $('body').css('overflow', '');
739
740 $modal.find('.modal-close').off('click.close');
741 $(document).off('keyup.leanModal' + overlayID);
742
743 $overlay.velocity( { opacity: 0}, {duration: options.out_duration, queue: false, ease: "easeOutQuart"});
744
745
746 // Define Bottom Sheet animation
747 if ($modal.hasClass('bottom-sheet')) {
748 $modal.velocity({bottom: "-100%", opacity: 0}, {
749 duration: options.out_duration,
750 queue: false,
751 ease: "easeOutCubic",
752 // Handle modal ready callback
753 complete: function() {
754 $overlay.css({display:"none"});
755
756 // Call complete callback
757 if (typeof(options.complete) === "function") {
758 options.complete();
759 }
760 $overlay.remove();
761 _stack--;
762 }
763 });
764 }
765 else {
766 $modal.velocity(
767 { top: options.starting_top, opacity: 0, scaleX: 0.7}, {
768 duration: options.out_duration,
769 complete:
770 function() {
771
772 $(this).css('display', 'none');
773 // Call complete callback
774 if (typeof(options.complete) === "function") {
775 options.complete();
776 }
777 $overlay.remove();
778 _stack--;
779 }
780 }
781 );
782 }
783 }
784 });
785
786 $.fn.extend({
787 leanModal: function(option) {
788 return this.each(function() {
789
790 var defaults = {
791 starting_top: '4%'
792 },
793 // Override defaults
794 options = $.extend(defaults, option);
795
796 // Close Handlers
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);
801 e.preventDefault();
802 }); // done set on click
803 }); // done return
804 }
805 });
806})(jQuery);
807;(function ($) {
808
809 $.fn.materialbox = function () {
810
811 return this.each(function() {
812
813 if ($(this).hasClass('initialized')) {
814 return;
815 }
816
817 $(this).addClass('initialized');
818
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);
828
829
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();
836
837
838 // If already modal, return to original
839 if (doneAnimating === false) {
840 returnToOriginal();
841 return false;
842 }
843 else if (overlayActive && doneAnimating===true) {
844 returnToOriginal();
845 return false;
846 }
847
848
849 // Set states
850 doneAnimating = false;
851 origin.addClass('active');
852 overlayActive = true;
853
854 // Set positioning for placeholder
855
856 placeholder.css({
857 width: placeholder[0].getBoundingClientRect().width,
858 height: placeholder[0].getBoundingClientRect().height,
859 position: 'relative',
860 top: 0,
861 left: 0
862 });
863
864
865
866 // Set css on origin
867 origin.css({position: 'absolute', 'z-index': 1000})
868 .data('width', originalWidth)
869 .data('height', originalHeight);
870
871 // Add overlay
872 var overlay = $('<div id="materialbox-overlay"></div>')
873 .css({
874 opacity: 0
875 })
876 .click(function(){
877 if (doneAnimating === true)
878 returnToOriginal();
879 });
880 // Animate Overlay
881 $('body').append(overlay);
882 overlay.velocity({opacity: 1}, {duration: inDuration, queue: false, easing: 'easeOutQuad'}
883 );
884
885
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'});
893 }
894
895
896
897 // Resize Image
898 var ratio = 0;
899 var widthPercent = originalWidth / windowWidth;
900 var heightPercent = originalHeight / windowHeight;
901 var newWidth = 0;
902 var newHeight = 0;
903
904 if (widthPercent > heightPercent) {
905 ratio = originalHeight / originalWidth;
906 newWidth = windowWidth * 0.9;
907 newHeight = windowWidth * 0.9 * ratio;
908 }
909 else {
910 ratio = originalWidth / originalHeight;
911 newWidth = (windowHeight * 0.9) * ratio;
912 newHeight = windowHeight * 0.9;
913 }
914
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})
920 .velocity(
921 {
922 height: newHeight,
923 width: newWidth,
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
926 },
927 {
928 duration: inDuration,
929 queue: false,
930 easing: 'easeOutQuad',
931 complete: function(){doneAnimating = true;}
932 }
933 );
934 } // End Complete
935 }); // End Velocity
936 }
937 else {
938 origin.css('left', 0)
939 .css('top', 0)
940 .velocity(
941 {
942 height: newHeight,
943 width: newWidth,
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
946 },
947 {
948 duration: inDuration,
949 queue: false,
950 easing: 'easeOutQuad',
951 complete: function(){doneAnimating = true;}
952 }
953 ); // End Velocity
954 }
955
956 }); // End origin on click
957
958
959 // Return on scroll
960 $(window).scroll(function() {
961 if (overlayActive ) {
962 returnToOriginal();
963 }
964 });
965
966 // Return on ESC
967 $(document).keyup(function(e) {
968
969 if (e.keyCode === 27 && doneAnimating === true) { // ESC key
970 if (overlayActive) {
971 returnToOriginal();
972 }
973 }
974 });
975
976
977 // This function returns the modaled image to the original spot
978 function returnToOriginal() {
979
980 doneAnimating = false;
981
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');
987
988 origin.velocity("stop", true);
989 $('#materialbox-overlay').velocity("stop", true);
990 $('.materialbox-caption').velocity("stop", true);
991
992
993 $('#materialbox-overlay').velocity({opacity: 0}, {
994 duration: outDuration, // Delay prevents animation overlapping
995 queue: false, easing: 'easeOutQuad',
996 complete: function(){
997 // Remove Overlay
998 overlayActive = false;
999 $(this).remove();
1000 }
1001 });
1002
1003 // Resize Image
1004 origin.velocity(
1005 {
1006 width: originalWidth,
1007 height: originalHeight,
1008 left: 0,
1009 top: 0
1010 },
1011 {
1012 duration: outDuration,
1013 queue: false, easing: 'easeOutQuad'
1014 }
1015 );
1016
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(){
1022 placeholder.css({
1023 height: '',
1024 width: '',
1025 position: '',
1026 top: '',
1027 left: ''
1028 });
1029
1030 origin.css({
1031 height: '',
1032 top: '',
1033 left: '',
1034 width: '',
1035 'max-width': '',
1036 position: '',
1037 'z-index': ''
1038 });
1039
1040 // Remove class
1041 origin.removeClass('active');
1042 doneAnimating = true;
1043 $(this).remove();
1044 }
1045 });
1046
1047 }
1048 });
1049};
1050
1051$(document).ready(function(){
1052 $('.materialboxed').materialbox();
1053});
1054
1055}( jQuery ));
1056;(function ($) {
1057
1058 $.fn.parallax = function () {
1059 var window_width = $(window).width();
1060 // Parallax Scripts
1061 return this.each(function(i) {
1062 var $this = $(this);
1063 $this.addClass('parallax');
1064
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();
1069 }
1070 else {
1071 container_height = ($this.height() > 0) ? $this.height() : 500;
1072 }
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));
1083
1084 if (initial) {
1085 $img.css('display', 'block');
1086 }
1087 if ((bottom > scrollTop) && (top < (scrollTop + windowHeight))) {
1088 $img.css('transform', "translate3D(-50%," + parallax + "px, 0)");
1089 }
1090
1091 }
1092
1093 // Wait for image load
1094 $this.children("img").one("load", function() {
1095 updateParallax(true);
1096 }).each(function() {
1097 if(this.complete) $(this).load();
1098 });
1099
1100 $(window).scroll(function() {
1101 window_width = $(window).width();
1102 updateParallax(false);
1103 });
1104
1105 $(window).resize(function() {
1106 window_width = $(window).width();
1107 updateParallax(false);
1108 });
1109
1110 });
1111
1112 };
1113}( jQuery ));;(function ($) {
1114
1115 var methods = {
1116 init : function() {
1117 return this.each(function() {
1118
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();
1123
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(),
1128 $index = 0;
1129
1130 // If the location.hash matches one of the links, use that as the active tab.
1131 $active = $($links.filter('[href="'+location.hash+'"]'));
1132
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();
1136 }
1137 if ($active.length === 0) {
1138 $active = $(this).find('li.tab a').first();
1139 }
1140
1141 $active.addClass('active');
1142 $index = $links.index($active);
1143 if ($index < 0) {
1144 $index = 0;
1145 }
1146
1147 $content = $($active[0].hash);
1148
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});
1155 }
1156 $(window).resize(function () {
1157 $tabs_width = $this.width();
1158 $tab_width = $this.find('li').first().outerWidth();
1159 if ($index < 0) {
1160 $index = 0;
1161 }
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});
1165 }
1166 });
1167
1168 // Hide the remaining content
1169 $links.not($active).each(function () {
1170 $(this.hash).hide();
1171 });
1172
1173
1174 // Bind the click event handler
1175 $this.on('click', 'a', function(e){
1176 if ($(this).parent().hasClass('disabled')) {
1177 e.preventDefault();
1178 return;
1179 }
1180
1181 $tabs_width = $this.width();
1182 $tab_width = $this.find('li').first().outerWidth();
1183
1184 // Make the old tab inactive.
1185 $active.removeClass('active');
1186 $content.hide();
1187
1188 // Update the variables with the new link and content
1189 $active = $(this);
1190 $content = $(this.hash);
1191 $links = $this.find('li.tab a');
1192
1193 // Make the tab active.
1194 $active.addClass('active');
1195 var $prev_index = $index;
1196 $index = $links.index($(this));
1197 if ($index < 0) {
1198 $index = 0;
1199 }
1200 // Change url to current tab
1201 // window.location.hash = $active.attr('href');
1202
1203 $content.show();
1204
1205 // Update indicator
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});
1209
1210 }
1211 else {
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});
1214 }
1215
1216 // Prevent the anchor's default click action
1217 e.preventDefault();
1218 });
1219 });
1220
1221 },
1222 select_tab : function( id ) {
1223 this.find('a[href="#' + id + '"]').trigger('click');
1224 }
1225 };
1226
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 );
1233 } else {
1234 $.error( 'Method ' + methodOrOptions + ' does not exist on jQuery.tooltip' );
1235 }
1236 };
1237
1238 $(document).ready(function(){
1239 $('ul.tabs').tabs();
1240 });
1241}( jQuery ));
1242;(function ($) {
1243 $.fn.tooltip = function (options) {
1244 var timeout = null,
1245 counter = null,
1246 started = false,
1247 counterInterval = null,
1248 margin = 5;
1249
1250 // Defaults
1251 var defaults = {
1252 delay: 350
1253 };
1254
1255 // Remove tooltip from the activator
1256 if (options === "remove") {
1257 this.each(function(){
1258 $('#' + $(this).attr('data-tooltip-id')).remove();
1259 });
1260 return false;
1261 }
1262
1263 options = $.extend(defaults, options);
1264
1265
1266 return this.each(function(){
1267 var tooltipId = Materialize.guid();
1268 var origin = $(this);
1269 origin.attr('data-tooltip-id', tooltipId);
1270
1271 // Create Text span
1272 var tooltip_text = $('<span></span>').text(origin.attr('data-tooltip'));
1273
1274 // Create tooltip
1275 var newTooltip = $('<div></div>');
1276 newTooltip.addClass('material-tooltip').append(tooltip_text)
1277 .appendTo($('body'))
1278 .attr('id', tooltipId);
1279
1280 var backdrop = $('<div></div>').addClass('backdrop');
1281 backdrop.appendTo(newTooltip);
1282 backdrop.css({ top: 0, left:0 });
1283
1284
1285 //Destroy previously binded events
1286 origin.off('mouseenter.tooltip mouseleave.tooltip');
1287 // Mouse In
1288 origin.on({
1289 'mouseenter.tooltip': function(e) {
1290 var tooltip_delay = origin.data("delay");
1291 tooltip_delay = (tooltip_delay === undefined || tooltip_delay === '') ? options.delay : tooltip_delay;
1292 counter = 0;
1293 counterInterval = setInterval(function(){
1294 counter += 10;
1295 if (counter >= tooltip_delay && started === false) {
1296 started = true;
1297 newTooltip.css({ display: 'block', left: '0px', top: '0px' });
1298
1299 // Set Tooltip text
1300 newTooltip.children('span').text(origin.attr('data-tooltip'));
1301
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;
1311
1312 if (tooltipPosition === "top") {
1313 // Top Position
1314 newTooltip.css({
1315 top: origin.offset().top - tooltipHeight - margin,
1316 left: origin.offset().left + originWidth/2 - tooltipWidth/2
1317 });
1318 tooltipVerticalMovement = '-10px';
1319 backdrop.css({
1320 borderRadius: '14px 14px 0 0',
1321 transformOrigin: '50% 90%',
1322 marginTop: tooltipHeight,
1323 marginLeft: (tooltipWidth/2) - (backdrop.width()/2)
1324
1325 });
1326 }
1327 // Left Position
1328 else if (tooltipPosition === "left") {
1329 newTooltip.css({
1330 top: origin.offset().top + originHeight/2 - tooltipHeight/2,
1331 left: origin.offset().left - tooltipWidth - margin
1332 });
1333 tooltipHorizontalMovement = '-10px';
1334 backdrop.css({
1335 width: '14px',
1336 height: '14px',
1337 borderRadius: '14px 0 0 14px',
1338 transformOrigin: '95% 50%',
1339 marginTop: tooltipHeight/2,
1340 marginLeft: tooltipWidth
1341 });
1342 }
1343 // Right Position
1344 else if (tooltipPosition === "right") {
1345 newTooltip.css({
1346 top: origin.offset().top + originHeight/2 - tooltipHeight/2,
1347 left: origin.offset().left + originWidth + margin
1348 });
1349 tooltipHorizontalMovement = '+10px';
1350 backdrop.css({
1351 width: '14px',
1352 height: '14px',
1353 borderRadius: '0 14px 14px 0',
1354 transformOrigin: '5% 50%',
1355 marginTop: tooltipHeight/2,
1356 marginLeft: '0px'
1357 });
1358 }
1359 else {
1360 // Bottom Position
1361 newTooltip.css({
1362 top: origin.offset().top + origin.outerHeight() + margin,
1363 left: origin.offset().left + originWidth/2 - tooltipWidth/2
1364 });
1365 tooltipVerticalMovement = '+10px';
1366 backdrop.css({
1367 marginLeft: (tooltipWidth/2) - (backdrop.width()/2)
1368 });
1369 }
1370
1371 // Calculate Scale to fill
1372 scale_factor = tooltipWidth / 8;
1373 if (scale_factor < 8) {
1374 scale_factor = 8;
1375 }
1376 if (tooltipPosition === "right" || tooltipPosition === "left") {
1377 scale_factor = tooltipWidth / 10;
1378 if (scale_factor < 6)
1379 scale_factor = 6;
1380 }
1381
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'});
1387
1388 }
1389 }, 10); // End Interval
1390
1391 // Mouse Out
1392 },
1393 'mouseleave.tooltip': function(){
1394 // Reset State
1395 clearInterval(counterInterval);
1396 counter = 0;
1397
1398 // Animate back
1399 newTooltip.velocity({
1400 opacity: 0, marginTop: 0, marginLeft: 0}, { duration: 225, queue: false, delay: 225 }
1401 );
1402 backdrop.velocity({opacity: 0, scale: 1}, {
1403 duration:225,
1404 delay: 275, queue: false,
1405 complete: function(){
1406 backdrop.css('display', 'none');
1407 newTooltip.css('display', 'none');
1408 started = false;}
1409 });
1410 }
1411 });
1412 });
1413 };
1414
1415 $(document).ready(function(){
1416 $('.tooltipped').tooltip();
1417 });
1418}( jQuery ));
1419;/*!
1420 * Waves v0.6.4
1421 * http://fian.my.id/Waves
1422 *
1423 * Copyright 2014 Alfiana E. Sibuea and other contributors
1424 * Released under the MIT license
1425 * https://github.com/fians/Waves/blob/master/LICENSE
1426 */
1427
1428;(function(window) {
1429 'use strict';
1430
1431 var Waves = Waves || {};
1432 var $$ = document.querySelectorAll.bind(document);
1433
1434 // Find exact position of element
1435 function isWindow(obj) {
1436 return obj !== null && obj === obj.window;
1437 }
1438
1439 function getWindow(elem) {
1440 return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;
1441 }
1442
1443 function offset(elem) {
1444 var docElem, win,
1445 box = {top: 0, left: 0},
1446 doc = elem && elem.ownerDocument;
1447
1448 docElem = doc.documentElement;
1449
1450 if (typeof elem.getBoundingClientRect !== typeof undefined) {
1451 box = elem.getBoundingClientRect();
1452 }
1453 win = getWindow(doc);
1454 return {
1455 top: box.top + win.pageYOffset - docElem.clientTop,
1456 left: box.left + win.pageXOffset - docElem.clientLeft
1457 };
1458 }
1459
1460 function convertStyle(obj) {
1461 var style = '';
1462
1463 for (var a in obj) {
1464 if (obj.hasOwnProperty(a)) {
1465 style += (a + ':' + obj[a] + ';');
1466 }
1467 }
1468
1469 return style;
1470 }
1471
1472 var Effect = {
1473
1474 // Effect delay
1475 duration: 750,
1476
1477 show: function(e, element) {
1478
1479 // Disable right click
1480 if (e.button === 2) {
1481 return false;
1482 }
1483
1484 var el = element || this;
1485
1486 // Create ripple
1487 var ripple = document.createElement('div');
1488 ripple.className = 'waves-ripple';
1489 el.appendChild(ripple);
1490
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)+')';
1496
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);
1501 }
1502
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);
1508
1509 // Set ripple position
1510 var rippleStyle = {
1511 'top': relativeY+'px',
1512 'left': relativeX+'px'
1513 };
1514
1515 ripple.className = ripple.className + ' waves-notransition';
1516 ripple.setAttribute('style', convertStyle(rippleStyle));
1517 ripple.className = ripple.className.replace('waves-notransition', '');
1518
1519 // Scale the ripple
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';
1526
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';
1531
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)';
1536
1537 ripple.setAttribute('style', convertStyle(rippleStyle));
1538 },
1539
1540 hide: function(e) {
1541 TouchHandler.touchup(e);
1542
1543 var el = this;
1544 var width = el.clientWidth * 1.4;
1545
1546 // Get first ripple
1547 var ripple = null;
1548 var ripples = el.getElementsByClassName('waves-ripple');
1549 if (ripples.length > 0) {
1550 ripple = ripples[ripples.length - 1];
1551 } else {
1552 return false;
1553 }
1554
1555 var relativeX = ripple.getAttribute('data-x');
1556 var relativeY = ripple.getAttribute('data-y');
1557 var scale = ripple.getAttribute('data-scale');
1558
1559 // Get delay beetween mousedown and mouse leave
1560 var diff = Date.now() - Number(ripple.getAttribute('data-hold'));
1561 var delay = 350 - diff;
1562
1563 if (delay < 0) {
1564 delay = 0;
1565 }
1566
1567 // Fade out ripple after delay
1568 setTimeout(function() {
1569 var style = {
1570 'top': relativeY+'px',
1571 'left': relativeX+'px',
1572 'opacity': '0',
1573
1574 // Duration
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,
1583 'transform': scale,
1584 };
1585
1586 ripple.setAttribute('style', convertStyle(style));
1587
1588 setTimeout(function() {
1589 try {
1590 el.removeChild(ripple);
1591 } catch(e) {
1592 return false;
1593 }
1594 }, Effect.duration);
1595 }, delay);
1596 },
1597
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];
1602
1603 if (el.tagName.toLowerCase() === 'input') {
1604 var parent = el.parentNode;
1605
1606 // If input already have parent just pass through
1607 if (parent.tagName.toLowerCase() === 'i' && parent.className.indexOf('waves-effect') !== -1) {
1608 continue;
1609 }
1610
1611 // Put element class and style to the specified parent
1612 var wrapper = document.createElement('i');
1613 wrapper.className = el.className + ' waves-input-wrapper';
1614
1615 var elementStyle = el.getAttribute('style');
1616
1617 if (!elementStyle) {
1618 elementStyle = '';
1619 }
1620
1621 wrapper.setAttribute('style', elementStyle);
1622
1623 el.className = 'waves-button-input';
1624 el.removeAttribute('style');
1625
1626 // Put element as child
1627 parent.replaceChild(wrapper, el);
1628 wrapper.appendChild(el);
1629 }
1630 }
1631 }
1632 };
1633
1634
1635 /**
1636 * Disable mousedown event for 500ms during and after touch
1637 */
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. */
1643 touches: 0,
1644 allowEvent: function(e) {
1645 var allow = true;
1646
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
1653 }
1654 }, 500);
1655 } else if (e.type === 'mousedown' && TouchHandler.touches > 0) {
1656 allow = false;
1657 }
1658
1659 return allow;
1660 },
1661 touchup: function(e) {
1662 TouchHandler.allowEvent(e);
1663 }
1664 };
1665
1666
1667 /**
1668 * Delegated click handler for .waves-effect element.
1669 * returns null when .waves-effect element not in "click tree"
1670 */
1671 function getWavesEffectElement(e) {
1672 if (TouchHandler.allowEvent(e) === false) {
1673 return null;
1674 }
1675
1676 var element = null;
1677 var target = e.target || e.srcElement;
1678
1679 while (target.parentElement !== null) {
1680 if (!(target instanceof SVGElement) && target.className.indexOf('waves-effect') !== -1) {
1681 element = target;
1682 break;
1683 } else if (target.classList.contains('waves-effect')) {
1684 element = target;
1685 break;
1686 }
1687 target = target.parentElement;
1688 }
1689
1690 return element;
1691 }
1692
1693 /**
1694 * Bubble the click and show effect if .waves-effect elem was found
1695 */
1696 function showEffect(e) {
1697 var element = getWavesEffectElement(e);
1698
1699 if (element !== null) {
1700 Effect.show(e, element);
1701
1702 if ('ontouchstart' in window) {
1703 element.addEventListener('touchend', Effect.hide, false);
1704 element.addEventListener('touchcancel', Effect.hide, false);
1705 }
1706
1707 element.addEventListener('mouseup', Effect.hide, false);
1708 element.addEventListener('mouseleave', Effect.hide, false);
1709 }
1710 }
1711
1712 Waves.displayEffect = function(options) {
1713 options = options || {};
1714
1715 if ('duration' in options) {
1716 Effect.duration = options.duration;
1717 }
1718
1719 //Wrap input inside <i> tag
1720 Effect.wrapInput($$('.waves-effect'));
1721
1722 if ('ontouchstart' in window) {
1723 document.body.addEventListener('touchstart', showEffect, false);
1724 }
1725
1726 document.body.addEventListener('mousedown', showEffect, false);
1727 };
1728
1729 /**
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.
1734 */
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;
1741 }
1742
1743 if ('ontouchstart' in window) {
1744 element.addEventListener('touchstart', showEffect, false);
1745 }
1746
1747 element.addEventListener('mousedown', showEffect, false);
1748 };
1749
1750 window.Waves = Waves;
1751
1752 document.addEventListener('DOMContentLoaded', function() {
1753 Waves.displayEffect();
1754 }, false);
1755
1756})(window);
1757;Materialize.toast = function (message, displayLength, className, completeCallback) {
1758 className = className || "";
1759
1760 var container = document.getElementById('toast-container');
1761
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);
1768 }
1769
1770 // Select and append toast
1771 var newToast = createToast(message);
1772
1773 // only append toast if message is not undefined
1774 if(message){
1775 container.appendChild(newToast);
1776 }
1777
1778 newToast.style.top = '35px';
1779 newToast.style.opacity = 0;
1780
1781 // Animate toast in
1782 Vel(newToast, { "top" : "0px", opacity: 1 }, {duration: 300,
1783 easing: 'easeOutCubic',
1784 queue: false});
1785
1786 // Allows timer to be pause while being panned
1787 var timeLeft = displayLength;
1788 var counterInterval = setInterval (function(){
1789
1790
1791 if (newToast.parentNode === null)
1792 window.clearInterval(counterInterval);
1793
1794 // If toast is not being dragged, decrease its time remaining
1795 if (!newToast.classList.contains('panning')) {
1796 timeLeft -= 20;
1797 }
1798
1799 if (timeLeft <= 0) {
1800 // Animate toast out
1801 Vel(newToast, {"opacity": 0, marginTop: '-40px'}, { duration: 375,
1802 easing: 'easeOutExpo',
1803 queue: false,
1804 complete: function(){
1805 // Call the optional callback
1806 if(typeof(completeCallback) === "function")
1807 completeCallback();
1808 // Remove toast after it times out
1809 this[0].parentNode.removeChild(this[0]);
1810 }
1811 });
1812 window.clearInterval(counterInterval);
1813 }
1814 }, 20);
1815
1816
1817
1818 function createToast(html) {
1819
1820 // Create toast
1821 var toast = document.createElement('div');
1822 toast.classList.add('toast');
1823 if (className) {
1824 var classes = className.split(' ');
1825
1826 for (var i = 0, count = classes.length; i < count; i++) {
1827 toast.classList.add(classes[i]);
1828 }
1829 }
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"
1832) {
1833 toast.appendChild(html);
1834 }
1835 else if (html instanceof jQuery) {
1836 // Check if it is jQuery object
1837 toast.appendChild(html[0]);
1838 }
1839 else {
1840 // Insert as text;
1841 toast.innerHTML = html;
1842 }
1843 // Bind hammer
1844 var hammerHandler = new Hammer(toast, {prevent_default: false});
1845 hammerHandler.on('pan', function(e) {
1846 var deltaX = e.deltaX;
1847 var activationDistance = 80;
1848
1849 // Change toast state
1850 if (!toast.classList.contains('panning')){
1851 toast.classList.add('panning');
1852 }
1853
1854 var opacityPercent = 1-Math.abs(deltaX / activationDistance);
1855 if (opacityPercent < 0)
1856 opacityPercent = 0;
1857
1858 Vel(toast, {left: deltaX, opacity: opacityPercent }, {duration: 50, queue: false, easing: 'easeOutQuad'});
1859
1860 });
1861
1862 hammerHandler.on('panend', function(e) {
1863 var deltaX = e.deltaX;
1864 var activationDistance = 80;
1865
1866 // If toast dragged past activation point
1867 if (Math.abs(deltaX) > activationDistance) {
1868 Vel(toast, {marginTop: '-40px'}, { duration: 375,
1869 easing: 'easeOutExpo',
1870 queue: false,
1871 complete: function(){
1872 if(typeof(completeCallback) === "function") {
1873 completeCallback();
1874 }
1875 toast.parentNode.removeChild(toast);
1876 }
1877 });
1878
1879 } else {
1880 toast.classList.remove('panning');
1881 // Put toast back into original position
1882 Vel(toast, { left: 0, opacity: 1 }, { duration: 300,
1883 easing: 'easeOutExpo',
1884 queue: false
1885 });
1886
1887 }
1888 });
1889
1890 return toast;
1891 }
1892};
1893;(function ($) {
1894
1895 var methods = {
1896 init : function(options) {
1897 var defaults = {
1898 menuWidth: 240,
1899 edge: 'left',
1900 closeOnClick: false
1901 };
1902 options = $.extend(defaults, options);
1903
1904 $(this).each(function(){
1905 var $this = $(this);
1906 var menu_id = $("#"+ $this.attr('data-activates'));
1907
1908 // Set to width
1909 if (options.menuWidth != 240) {
1910 menu_id.css('width', options.menuWidth);
1911 }
1912
1913 // Add Touch Area
1914 var dragTarget = $('<div class="drag-target"></div>');
1915 $('body').append(dragTarget);
1916
1917 if (options.edge == 'left') {
1918 menu_id.css('left', -1 * (options.menuWidth + 10));
1919 dragTarget.css({'left': 0}); // Add Touch Area
1920 }
1921 else {
1922 menu_id.addClass('right-aligned') // Change text-alignment to right
1923 .css('right', -1 * (options.menuWidth + 10))
1924 .css('left', '');
1925 dragTarget.css({'right': 0}); // Add Touch Area
1926 }
1927
1928 // If fixed sidenav, bring menu out
1929 if (menu_id.hasClass('fixed')) {
1930 if (window.innerWidth > 992) {
1931 menu_id.css('left', 0);
1932 }
1933 }
1934
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) {
1941 removeMenu(true);
1942 }
1943 else {
1944 menu_id.removeAttr('style');
1945 menu_id.css('width', options.menuWidth);
1946 }
1947 }
1948 else if (menuOut === false){
1949 if (options.edge === 'left')
1950 menu_id.css('left', -1 * (options.menuWidth + 10));
1951 else
1952 menu_id.css('right', -1 * (options.menuWidth + 10));
1953 }
1954
1955 });
1956 }
1957
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(){
1961 removeMenu();
1962 });
1963 }
1964
1965 function removeMenu(restoreNav) {
1966 panning = false;
1967 menuOut = false;
1968
1969 // Reenable scrolling
1970 $('body').css('overflow', '');
1971
1972 $('#sidenav-overlay').velocity({opacity: 0}, {duration: 200, queue: false, easing: 'easeOutQuad',
1973 complete: function() {
1974 $(this).remove();
1975 } });
1976 if (options.edge === 'left') {
1977 // Reset phantom div
1978 dragTarget.css({width: '', right: '', left: '0'});
1979 menu_id.velocity(
1980 {left: -1 * (options.menuWidth + 10)},
1981 { duration: 200,
1982 queue: false,
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);
1989 }
1990 }
1991
1992 });
1993 }
1994 else {
1995 // Reset phantom div
1996 dragTarget.css({width: '', right: '0', left: ''});
1997 menu_id.velocity(
1998 {right: -1 * (options.menuWidth + 10)},
1999 { duration: 200,
2000 queue: false,
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);
2007 }
2008 }
2009 });
2010 }
2011 }
2012
2013
2014
2015 // Touch Event
2016 var panning = false;
2017 var menuOut = false;
2018
2019 dragTarget.on('click', function(){
2020 removeMenu();
2021 });
2022
2023 dragTarget.hammer({
2024 prevent_default: false
2025 }).bind('pan', function(e) {
2026
2027 if (e.gesture.pointerType == "touch") {
2028
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;
2033
2034 // Disable Scrolling
2035 $('body').css('overflow', 'hidden');
2036
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(){
2041 removeMenu();
2042 });
2043 $('body').append(overlay);
2044 }
2045
2046 // Keep within boundaries
2047 if (options.edge === 'left') {
2048 if (x > options.menuWidth) { x = options.menuWidth; }
2049 else if (x < 0) { x = 0; }
2050 }
2051
2052 if (options.edge === 'left') {
2053 // Left Direction
2054 if (x < (options.menuWidth / 2)) { menuOut = false; }
2055 // Right Direction
2056 else if (x >= (options.menuWidth / 2)) { menuOut = true; }
2057
2058 menu_id.css('left', (x - options.menuWidth));
2059 }
2060 else {
2061 // Left Direction
2062 if (x < (window.innerWidth - options.menuWidth / 2)) {
2063 menuOut = true;
2064 }
2065 // Right Direction
2066 else if (x >= (window.innerWidth - options.menuWidth / 2)) {
2067 menuOut = false;
2068 }
2069 var rightPos = -1 *(x - options.menuWidth / 2);
2070 if (rightPos > 0) {
2071 rightPos = 0;
2072 }
2073
2074 menu_id.css('right', rightPos);
2075 }
2076
2077
2078
2079
2080 // Percentage overlay
2081 var overlayPerc;
2082 if (options.edge === 'left') {
2083 overlayPerc = x / options.menuWidth;
2084 $('#sidenav-overlay').velocity({opacity: overlayPerc }, {duration: 50, queue: false, easing: 'easeOutQuad'});
2085 }
2086 else {
2087 overlayPerc = Math.abs((x - window.innerWidth) / options.menuWidth);
2088 $('#sidenav-overlay').velocity({opacity: overlayPerc }, {duration: 50, queue: false, easing: 'easeOutQuad'});
2089 }
2090 }
2091
2092 }).bind('panend', function(e) {
2093
2094 if (e.gesture.pointerType == "touch") {
2095 var velocityX = e.gesture.velocityX;
2096 panning = false;
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: ''});
2103 }
2104 else if (!menuOut || velocityX > 0.3) {
2105 // Enable Scrolling
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 () {
2111 $(this).remove();
2112 }});
2113 dragTarget.css({width: '10px', right: '', left: 0});
2114 }
2115 }
2116 else {
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});
2121 }
2122 else if (!menuOut || velocityX < -0.3) {
2123 // Enable Scrolling
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 () {
2129 $(this).remove();
2130 }});
2131 dragTarget.css({width: '10px', right: 0, left: ''});
2132 }
2133 }
2134
2135 }
2136 });
2137
2138 $this.click(function() {
2139 if (menuOut === true) {
2140 menuOut = false;
2141 panning = false;
2142 removeMenu();
2143 }
2144 else {
2145
2146 // Disable Scrolling
2147 $('body').css('overflow', 'hidden');
2148 // Push current drag target on top of DOM tree
2149 $('body').append(dragTarget);
2150
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'});
2154 }
2155 else {
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','');
2159 }
2160
2161 var overlay = $('<div id="sidenav-overlay"></div>');
2162 overlay.css('opacity', 0)
2163 .click(function(){
2164 menuOut = false;
2165 panning = false;
2166 removeMenu();
2167 overlay.velocity({opacity: 0}, {duration: 300, queue: false, easing: 'easeOutQuad',
2168 complete: function() {
2169 $(this).remove();
2170 } });
2171
2172 });
2173 $('body').append(overlay);
2174 overlay.velocity({opacity: 1}, {duration: 300, queue: false, easing: 'easeOutQuad',
2175 complete: function () {
2176 menuOut = true;
2177 panning = false;
2178 }
2179 });
2180 }
2181
2182 return false;
2183 });
2184 });
2185
2186
2187 },
2188 show : function() {
2189 this.trigger('click');
2190 },
2191 hide : function() {
2192 $('#sidenav-overlay').trigger('click');
2193 }
2194 };
2195
2196
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 );
2203 } else {
2204 $.error( 'Method ' + methodOrOptions + ' does not exist on jQuery.sideNav' );
2205 }
2206 }; // Plugin end
2207}( jQuery ));
2208;/**
2209 * Extend jquery with a scrollspy plugin.
2210 * This watches the window scroll and fires events when elements are scrolled into viewport.
2211 *
2212 * throttle() and getTime() taken from Underscore.js
2213 * https://github.com/jashkenas/underscore
2214 *
2215 * @author Copyright 2013 John Smart
2216 * @license https://raw.github.com/thesmart/jquery-scrollspy/master/LICENSE
2217 * @see https://github.com/thesmart
2218 * @version 0.1.2
2219 */
2220(function($) {
2221
2222 var jWindow = $(window);
2223 var elements = [];
2224 var elementsInView = [];
2225 var isSpying = false;
2226 var ticks = 0;
2227 var unique_id = 1;
2228 var offset = {
2229 top : 0,
2230 right : 0,
2231 bottom : 0,
2232 left : 0,
2233 }
2234
2235 /**
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
2242 */
2243 function findElements(top, right, bottom, left) {
2244 var hits = $();
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();
2251
2252 var isIntersect = !(elLeft > right ||
2253 elRight < left ||
2254 elTop > bottom ||
2255 elBottom < top);
2256
2257 if (isIntersect) {
2258 hits.push(element);
2259 }
2260 }
2261 });
2262
2263 return hits;
2264 }
2265
2266
2267 /**
2268 * Called when the user scrolls the window
2269 */
2270 function onScroll() {
2271 // unique tick id
2272 ++ticks;
2273
2274 // viewport rectangle
2275 var top = jWindow.scrollTop(),
2276 left = jWindow.scrollLeft(),
2277 right = left + jWindow.width(),
2278 bottom = top + jWindow.height();
2279
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) {
2284
2285 var lastTick = element.data('scrollSpy:ticks');
2286 if (typeof lastTick != 'number') {
2287 // entered into view
2288 element.triggerHandler('scrollSpy:enter');
2289 }
2290
2291 // update tick id
2292 element.data('scrollSpy:ticks', ticks);
2293 });
2294
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) {
2299 // exited from view
2300 element.triggerHandler('scrollSpy:exit');
2301 element.data('scrollSpy:ticks', null);
2302 }
2303 });
2304
2305 // remember elements in view for next tick
2306 elementsInView = intersections;
2307 }
2308
2309 /**
2310 * Called when window is resized
2311 */
2312 function onWinSize() {
2313 jWindow.trigger('scrollSpy:winSize');
2314 }
2315
2316 /**
2317 * Get time in ms
2318 * @license https://raw.github.com/jashkenas/underscore/master/LICENSE
2319 * @type {function}
2320 * @return {number}
2321 */
2322 var getTime = (Date.now || function () {
2323 return new Date().getTime();
2324 });
2325
2326 /**
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}
2337 */
2338 function throttle(func, wait, options) {
2339 var context, args, result;
2340 var timeout = null;
2341 var previous = 0;
2342 options || (options = {});
2343 var later = function () {
2344 previous = options.leading === false ? 0 : getTime();
2345 timeout = null;
2346 result = func.apply(context, args);
2347 context = args = null;
2348 };
2349 return function () {
2350 var now = getTime();
2351 if (!previous && options.leading === false) previous = now;
2352 var remaining = wait - (now - previous);
2353 context = this;
2354 args = arguments;
2355 if (remaining <= 0) {
2356 clearTimeout(timeout);
2357 timeout = null;
2358 previous = now;
2359 result = func.apply(context, args);
2360 context = args = null;
2361 } else if (!timeout && options.trailing !== false) {
2362 timeout = setTimeout(later, remaining);
2363 }
2364 return result;
2365 };
2366 };
2367
2368 /**
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
2377 * @returns {jQuery}
2378 */
2379 $.scrollSpy = function(selector, options) {
2380 var visible = [];
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) {
2387 e.preventDefault();
2388 var offset = $(this.hash).offset().top + 1;
2389
2390// offset - 200 allows elements near bottom of page to scroll
2391
2392 $('html, body').animate({ scrollTop: offset - 200 }, {duration: 400, queue: false, easing: 'easeOutCubic'});
2393
2394 });
2395 });
2396 options = options || {
2397 throttle: 100
2398 };
2399
2400 offset.top = options.offsetTop || 0;
2401 offset.right = options.offsetRight || 0;
2402 offset.bottom = options.offsetBottom || 0;
2403 offset.left = options.offsetLeft || 0;
2404
2405 var throttledScroll = throttle(onScroll, options.throttle || 100);
2406 var readyScroll = function(){
2407 $(document).ready(throttledScroll);
2408 };
2409
2410 if (!isSpying) {
2411 jWindow.on('scroll', readyScroll);
2412 jWindow.on('resize', readyScroll);
2413 isSpying = true;
2414 }
2415
2416 // perform a scan once, after current execution context, and after dom is ready
2417 setTimeout(readyScroll, 0);
2418
2419
2420 selector.on('scrollSpy:enter', function() {
2421 visible = $.grep(visible, function(value) {
2422 return value.height() != 0;
2423 });
2424
2425 var $this = $(this);
2426
2427 if (visible[0]) {
2428 $('a[href=#' + visible[0].attr('id') + ']').removeClass('active');
2429 if ($this.data('scrollSpy:id') < visible[0].data('scrollSpy:id')) {
2430 visible.unshift($(this));
2431 }
2432 else {
2433 visible.push($(this));
2434 }
2435 }
2436 else {
2437 visible.push($(this));
2438 }
2439
2440
2441 $('a[href=#' + visible[0].attr('id') + ']').addClass('active');
2442 });
2443 selector.on('scrollSpy:exit', function() {
2444 visible = $.grep(visible, function(value) {
2445 return value.height() != 0;
2446 });
2447
2448 if (visible[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');
2453 });
2454 if (visible[0]) { // Check if empty
2455 $('a[href=#' + visible[0].attr('id') + ']').addClass('active');
2456 }
2457 }
2458 });
2459
2460 return selector;
2461 };
2462
2463 /**
2464 * Listen for window resize events
2465 * @param {Object=} options Optional. Set { throttle: number } to change throttling. Default: 100 ms
2466 * @returns {jQuery} $(window)
2467 */
2468 $.winSizeSpy = function(options) {
2469 $.winSizeSpy = function() { return jWindow; }; // lock from multiple calls
2470 options = options || {
2471 throttle: 100
2472 };
2473 return jWindow.on('resize', throttle(onWinSize, options.throttle || 100));
2474 };
2475
2476 /**
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
2485 * @returns {jQuery}
2486 */
2487 $.fn.scrollSpy = function(options) {
2488 return $.scrollSpy($(this), options);
2489 };
2490
2491})(jQuery);;(function ($) {
2492 $(document).ready(function() {
2493
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');
2500 }
2501 else {
2502 $(this).siblings('label, i').removeClass('active');
2503 }
2504 });
2505 };
2506
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';
2509
2510 // Handle HTML5 autofocus
2511 $('input[autofocus]').siblings('label, i').addClass('active');
2512
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');
2517 }
2518 validate_field($(this));
2519 });
2520
2521 // Add active if input element has been pre-populated on document ready
2522 $(document).ready(function() {
2523 Materialize.updateTextFields();
2524 });
2525
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');
2534 }
2535 });
2536
2537 // Reset select
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);
2541 });
2542 }
2543 });
2544
2545 // Add active when element has focus
2546 $(document).on('focus', input_selector, function () {
2547 $(this).siblings('label, i').addClass('active');
2548 });
2549
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');
2554 }
2555
2556 if ($inputElement.val().length === 0 && $inputElement[0].validity.badInput !== true && $inputElement.attr('placeholder') !== undefined) {
2557 $inputElement.siblings('i').removeClass('active');
2558 }
2559 validate_field($inputElement);
2560 });
2561
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;
2566
2567 if (object.val().length === 0 && object[0].validity.badInput === false) {
2568 if (object.hasClass('validate')) {
2569 object.removeClass('valid');
2570 object.removeClass('invalid');
2571 }
2572 }
2573 else {
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');
2579 }
2580 else {
2581 object.removeClass('valid');
2582 object.addClass('invalid');
2583 }
2584 }
2585 }
2586 };
2587
2588
2589 // Textarea Auto Resize
2590 var hiddenDiv = $('.hiddendiv').first();
2591 if (!hiddenDiv.length) {
2592 hiddenDiv = $('<div class="hiddendiv common"></div>');
2593 $('body').append(hiddenDiv);
2594 }
2595 var text_area_selector = '.materialize-textarea';
2596
2597 function textareaAutoResize($textarea) {
2598 // Set font properties of hiddenDiv
2599
2600 var fontFamily = $textarea.css('font-family');
2601 var fontSize = $textarea.css('font-size');
2602
2603 if (fontSize) { hiddenDiv.css('font-size', fontSize); }
2604 if (fontFamily) { hiddenDiv.css('font-family', fontFamily); }
2605
2606 if ($textarea.attr('wrap') === "off") {
2607 hiddenDiv.css('overflow-wrap', "normal")
2608 .css('white-space', "pre");
2609 }
2610
2611
2612
2613
2614 hiddenDiv.text($textarea.val() + '\n');
2615 var content = hiddenDiv.html().replace(/\n/g, '<br>');
2616 hiddenDiv.html(content);
2617
2618
2619 // When textarea is hidden, width goes crazy.
2620 // Approximate with half of window size
2621
2622 if ($textarea.is(':visible')) {
2623 hiddenDiv.css('width', $textarea.width());
2624 }
2625 else {
2626 hiddenDiv.css('width', $(window).width()/2);
2627 }
2628
2629 $textarea.css('height', hiddenDiv.height());
2630 }
2631
2632 $(text_area_selector).each(function () {
2633 var $textarea = $(this);
2634 if ($textarea.val().length) {
2635 textareaAutoResize($textarea);
2636 }
2637 });
2638
2639 $('body').on('keyup keydown autoresize', text_area_selector, function () {
2640 textareaAutoResize($(this));
2641 });
2642
2643
2644 // File Input Path
2645
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);
2653 }
2654 path_input.val(file_names.join(", "));
2655 path_input.trigger('change');
2656 });
2657
2658
2659 /****************
2660 * Range Input *
2661 ****************/
2662
2663 var range_type = 'input[type=range]';
2664 var range_mousedown = false;
2665 var left;
2666
2667 $(range_type).each(function () {
2668 var thumb = $('<span class="thumb"><span class="value"></span></span>');
2669 $(this).after(thumb);
2670 });
2671
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());
2676 });
2677
2678 $(document).on('input mousedown touchstart', range_type, function(e) {
2679 var thumb = $(this).siblings('.thumb');
2680
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);
2685 }
2686
2687 // Set indicator value
2688 thumb.find('.value').html($(this).val());
2689
2690 range_mousedown = true;
2691 $(this).addClass('active');
2692
2693 if (!thumb.hasClass('active')) {
2694 thumb.velocity({ height: "30px", width: "30px", top: "-20px", marginLeft: "-15px"}, { duration: 300, easing: 'easeOutExpo' });
2695 }
2696
2697 if(e.pageX === undefined || e.pageX === null){//mobile
2698 left = e.originalEvent.touches[0].pageX - $(this).offset().left;
2699 }
2700 else{ // desktop
2701 left = e.pageX - $(this).offset().left;
2702 }
2703 var width = $(this).outerWidth();
2704
2705 if (left < 0) {
2706 left = 0;
2707 }
2708 else if (left > width) {
2709 left = width;
2710 }
2711 thumb.addClass('active').css('left', left);
2712 thumb.find('.value').html($(this).val());
2713
2714
2715 });
2716
2717 $(document).on('mouseup touchend', range_wrapper, function() {
2718 range_mousedown = false;
2719 $(this).removeClass('active');
2720 });
2721
2722 $(document).on('mousemove touchmove', range_wrapper, function(e) {
2723 var thumb = $(this).children('.thumb');
2724 var left;
2725 if (range_mousedown) {
2726 if (!thumb.hasClass('active')) {
2727 thumb.velocity({ height: '30px', width: '30px', top: '-20px', marginLeft: '-15px'}, { duration: 300, easing: 'easeOutExpo' });
2728 }
2729 if (e.pageX === undefined || e.pageX === null) { //mobile
2730 left = e.originalEvent.touches[0].pageX - $(this).offset().left;
2731 }
2732 else{ // desktop
2733 left = e.pageX - $(this).offset().left;
2734 }
2735 var width = $(this).outerWidth();
2736
2737 if (left < 0) {
2738 left = 0;
2739 }
2740 else if (left > width) {
2741 left = width;
2742 }
2743 thumb.addClass('active').css('left', left);
2744 thumb.find('.value').html(thumb.siblings(range_type).val());
2745 }
2746 });
2747
2748 $(document).on('mouseout touchleave', range_wrapper, function() {
2749 if (!range_mousedown) {
2750
2751 var thumb = $(this).children('.thumb');
2752
2753 if (thumb.hasClass('active')) {
2754 thumb.velocity({ height: '0', width: '0', top: '10px', marginLeft: '-6px'}, { duration: 100 });
2755 }
2756 thumb.removeClass('active');
2757 }
2758 });
2759
2760 }); // End of $(document).ready
2761
2762
2763
2764
2765 // Select Plugin
2766 $.fn.material_select = function (callback) {
2767 $(this).each(function(){
2768 $select = $(this);
2769
2770 if ( $select.hasClass('browser-default')) {
2771 return; // Continue to next (return false breaks out of entire loop)
2772 }
2773
2774 // Tear down structure if Select needs to be rebuilt
2775 var lastID = $select.data('select-id');
2776 if (lastID) {
2777 $select.parent().find('span.caret').remove();
2778 $select.parent().find('input').remove();
2779
2780 $select.unwrap();
2781 $('ul#select-options-'+lastID).remove();
2782 }
2783
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');
2787 return;
2788 }
2789
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');
2796
2797 var label;
2798 if ($select.find('option:selected') !== undefined) {
2799 label = $select.find('option:selected');
2800 }
2801 else {
2802 label = options.first();
2803 }
2804
2805
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>'));
2810 });
2811
2812
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();
2823 }
2824 });
2825
2826 });
2827
2828 // Wrap Elements
2829 $select.wrap(wrapper);
2830 // Add Select Display Element
2831 var dropdownIcon = $('<span class="caret">&#9660;</span>');
2832 if ( $select.is(':disabled') )
2833 dropdownIcon.addClass('disabled');
2834
2835 // escape double quotes
2836 var sanitizedLabelHtml = label.html().replace(/"/g, '&quot;');
2837
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);
2841
2842 $('body').append(options);
2843 // Check if section element is disabled
2844 if (!$select.is(':disabled')) {
2845 $newSelect.dropdown({"hover": false});
2846 }
2847
2848 // Copy tabindex
2849 if ($select.attr('tabindex')) {
2850 $($newSelect[0]).attr('tabindex', $select.attr('tabindex'));
2851 }
2852
2853 $select.addClass('initialized');
2854
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();
2860 })[0];
2861 activateOption(options, selectedOption);
2862 });
2863
2864 $newSelect.on('blur', function(){
2865 $(this).trigger('close');
2866 });
2867
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);
2873 };
2874
2875 // Allow user to search by typing
2876 // this array is cleared after 1 second
2877 filterQuery = [];
2878
2879 onKeyDown = function(event){
2880 // TAB - switch to another input
2881 if(event.which == 9){
2882 $newSelect.trigger('close');
2883 return;
2884 }
2885
2886 // ARROW DOWN WHEN SELECT IS CLOSED - open select options
2887 if(event.which == 40 && !options.is(":visible")){
2888 $newSelect.trigger('open');
2889 return;
2890 }
2891
2892 // ENTER WHEN SELECT IS CLOSED - submit form
2893 if(event.which == 13 && !options.is(":visible")){
2894 return;
2895 }
2896
2897 event.preventDefault();
2898
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);
2904
2905 string = filterQuery.join("");
2906
2907 newOption = options.find('li').filter(function() {
2908 return $(this).text().toLowerCase().indexOf(string) === 0;
2909 })[0];
2910
2911 if(newOption){
2912 activateOption(options, newOption);
2913 }
2914 }
2915
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];
2919 if(activeOption){
2920 $(activeOption).trigger('click');
2921 $newSelect.trigger('close');
2922 }
2923 }
2924
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];
2928 if(newOption){
2929 activateOption(options, newOption);
2930 }
2931 }
2932
2933 // ESC - close options
2934 if(event.which == 27){
2935 $newSelect.trigger('close');
2936 }
2937
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];
2941 if(newOption){
2942 activateOption(options, newOption);
2943 }
2944 }
2945
2946 // Automaticaly clean filter query so user can search again by starting letters
2947 setTimeout(function(){ filterQuery = []; }, 1000);
2948 };
2949
2950 $newSelect.on('keydown', onKeyDown);
2951 });
2952 };
2953
2954}( jQuery ));
2955;(function ($) {
2956
2957 var methods = {
2958
2959 init : function(options) {
2960 var defaults = {
2961 indicators: true,
2962 height: 400,
2963 transition: 500,
2964 interval: 6000
2965 };
2966 options = $.extend(defaults, options);
2967
2968 return this.each(function() {
2969
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();
2976 var $active;
2977 if ($active_index != -1) { $active = $slides.eq($active_index); }
2978
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});
2983 }
2984 else if (caption.hasClass("right-align")) {
2985 caption.velocity({opacity: 0, translateX: 100}, {duration: duration, queue: false});
2986 }
2987 else if (caption.hasClass("left-align")) {
2988 caption.velocity({opacity: 0, translateX: -100}, {duration: duration, queue: false});
2989 }
2990 }
2991
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;
2996
2997 $active_index = $slider.find('.active').index();
2998
2999 // Only do if index changes
3000 if ($active_index != index) {
3001 $active = $slides.eq($active_index);
3002 $caption = $active.find('.caption');
3003
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});
3008 } });
3009 captionTransition($caption, options.transition);
3010
3011
3012 // Update indicators
3013 if (options.indicators) {
3014 $indicators.eq($active_index).removeClass('active');
3015 }
3016
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');
3020
3021
3022 // Update indicators
3023 if (options.indicators) {
3024 $indicators.eq(index).addClass('active');
3025 }
3026 }
3027 }
3028
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);
3035 }
3036 else {
3037 $this.height(options.height);
3038 }
3039 $slider.height(options.height);
3040 }
3041
3042
3043 // Set initial positions of captions
3044 $slides.find('.caption').each(function () {
3045 captionTransition($(this), 0);
3046 });
3047
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==');
3052 });
3053
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>');
3059
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);
3065
3066 // reset interval
3067 clearInterval($interval);
3068 $interval = setInterval(
3069 function(){
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;
3073
3074 moveToSlide($active_index);
3075
3076 }, options.transition + options.interval
3077 );
3078 });
3079 $indicators.append($indicator);
3080 });
3081 $this.append($indicators);
3082 $indicators = $this.find('ul.indicators').find('li.indicator-item');
3083 }
3084
3085 if ($active) {
3086 $active.show();
3087 }
3088 else {
3089 $slides.first().addClass('active').velocity({opacity: 1}, {duration: options.transition, queue: false, easing: 'easeOutQuad'});
3090
3091 $active_index = 0;
3092 $active = $slides.eq($active_index);
3093
3094 // Update indicators
3095 if (options.indicators) {
3096 $indicators.eq($active_index).addClass('active');
3097 }
3098 }
3099
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'});
3103 });
3104
3105 // auto scroll
3106 $interval = setInterval(
3107 function(){
3108 $active_index = $slider.find('.active').index();
3109 moveToSlide($active_index + 1);
3110
3111 }, options.transition + options.interval
3112 );
3113
3114
3115 // HammerJS, Swipe navigation
3116
3117 // Touch Event
3118 var panning = false;
3119 var swipeLeft = false;
3120 var swipeRight = false;
3121
3122 $this.hammer({
3123 prevent_default: false
3124 }).bind('pan', function(e) {
3125 if (e.gesture.pointerType === "touch") {
3126
3127 // reset interval
3128 clearInterval($interval);
3129
3130 var direction = e.gesture.direction;
3131 var x = e.gesture.deltaX;
3132 var velocityX = e.gesture.velocityX;
3133
3134 $curr_slide = $slider.find('.active');
3135 $curr_slide.velocity({ translateX: x
3136 }, {duration: 50, queue: false, easing: 'easeOutQuad'});
3137
3138 // Swipe Left
3139 if (direction === 4 && (x > ($this.innerWidth() / 2) || velocityX < -0.65)) {
3140 swipeRight = true;
3141 }
3142 // Swipe Right
3143 else if (direction === 2 && (x < (-1 * $this.innerWidth() / 2) || velocityX > 0.65)) {
3144 swipeLeft = true;
3145 }
3146
3147 // Make Slide Behind active slide visible
3148 var next_slide;
3149 if (swipeLeft) {
3150 next_slide = $curr_slide.next();
3151 if (next_slide.length === 0) {
3152 next_slide = $slides.first();
3153 }
3154 next_slide.velocity({ opacity: 1
3155 }, {duration: 300, queue: false, easing: 'easeOutQuad'});
3156 }
3157 if (swipeRight) {
3158 next_slide = $curr_slide.prev();
3159 if (next_slide.length === 0) {
3160 next_slide = $slides.last();
3161 }
3162 next_slide.velocity({ opacity: 1
3163 }, {duration: 300, queue: false, easing: 'easeOutQuad'});
3164 }
3165
3166
3167 }
3168
3169 }).bind('panend', function(e) {
3170 if (e.gesture.pointerType === "touch") {
3171
3172 $curr_slide = $slider.find('.active');
3173 panning = false;
3174 curr_index = $slider.find('.active').index();
3175
3176 if (!swipeRight && !swipeLeft) {
3177 // Return to original spot
3178 $curr_slide.velocity({ translateX: 0
3179 }, {duration: 300, queue: false, easing: 'easeOutQuad'});
3180 }
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});
3186 } });
3187 }
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});
3193 } });
3194 }
3195 swipeLeft = false;
3196 swipeRight = false;
3197
3198 // Restart interval
3199 clearInterval($interval);
3200 $interval = setInterval(
3201 function(){
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;
3205
3206 moveToSlide($active_index);
3207
3208 }, options.transition + options.interval
3209 );
3210 }
3211 });
3212
3213 $this.on('sliderPause', function() {
3214 clearInterval($interval);
3215 });
3216
3217 $this.on('sliderStart', function() {
3218 clearInterval($interval);
3219 $interval = setInterval(
3220 function(){
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;
3224
3225 moveToSlide($active_index);
3226
3227 }, options.transition + options.interval
3228 );
3229 });
3230
3231 });
3232
3233
3234
3235 },
3236 pause : function() {
3237 $(this).trigger('sliderPause');
3238 },
3239 start : function() {
3240 $(this).trigger('sliderStart');
3241 }
3242 };
3243
3244
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 );
3251 } else {
3252 $.error( 'Method ' + methodOrOptions + ' does not exist on jQuery.tooltip' );
3253 }
3254 }; // Plugin end
3255}( jQuery ));;(function ($) {
3256 $(document).ready(function() {
3257
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(
3263 {translateY: 0}, {
3264 duration: 225,
3265 queue: false,
3266 easing: 'easeInOutQuad',
3267 complete: function() { $(this).css({ display: 'none'}); }
3268 }
3269 );
3270 }
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'});
3274 }
3275 }
3276
3277
3278 });
3279
3280 });
3281}( jQuery ));;(function ($) {
3282 $(document).ready(function() {
3283
3284 $(document).on('click.chip', '.chip .material-icons', function (e) {
3285 $(this).parent().remove();
3286 });
3287
3288 });
3289}( jQuery ));;(function ($) {
3290 $(document).ready(function() {
3291
3292 $.fn.pushpin = function (options) {
3293
3294 var defaults = {
3295 top: 0,
3296 bottom: Infinity,
3297 offset: 0
3298 }
3299 options = $.extend(defaults, options);
3300
3301 $index = 0;
3302 return this.each(function() {
3303 var $uniqueId = Materialize.guid(),
3304 $this = $(this),
3305 $original_offset = $(this).offset().top;
3306
3307 function removePinClasses(object) {
3308 object.removeClass('pin-top');
3309 object.removeClass('pinned');
3310 object.removeClass('pin-bottom');
3311 }
3312
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');
3320 }
3321
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');
3327 }
3328
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);
3334 }
3335 });
3336 }
3337
3338 updateElements($this, $(window).scrollTop());
3339 $(window).on('scroll.' + $uniqueId, function () {
3340 var $scrolled = $(window).scrollTop() + options.offset;
3341 updateElements($this, $scrolled);
3342 });
3343
3344 });
3345
3346 };
3347
3348
3349 });
3350}( jQuery ));;(function ($) {
3351 $(document).ready(function() {
3352
3353 // jQuery reverse
3354 $.fn.reverse = [].reverse;
3355
3356 $(document).on('mouseenter.fixedActionBtn', '.fixed-action-btn', function(e) {
3357 var $this = $(this);
3358 openFABMenu($this);
3359
3360 });
3361
3362 $(document).on('mouseleave.fixedActionBtn', '.fixed-action-btn', function(e) {
3363 var $this = $(this);
3364 closeFABMenu($this);
3365 });
3366
3367 });
3368
3369 $.fn.extend({
3370 openFAB: function() {
3371 var $this = $(this);
3372 openFABMenu($this);
3373 },
3374 closeFAB: function() {
3375 closeFABMenu($this);
3376 }
3377 });
3378
3379
3380 var openFABMenu = function (btn) {
3381 $this = 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"},
3386 { duration: 0 });
3387
3388 var time = 0;
3389 $this.find('ul .btn-floating').reverse().each(function () {
3390 $(this).velocity(
3391 { opacity: "1", scaleX: "1", scaleY: "1", translateY: "0"},
3392 { duration: 80, delay: time });
3393 time += 40;
3394 });
3395 }
3396 };
3397
3398 var closeFABMenu = function (btn) {
3399 $this = btn;
3400 $this.removeClass('active');
3401 var time = 0;
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"},
3405 { duration: 80 }
3406 );
3407 };
3408
3409
3410}( jQuery ));
3411;(function ($) {
3412 // Image transition function
3413 Materialize.fadeInImage = function(selector){
3414 var element = $(selector);
3415 element.css({opacity: 0});
3416 $(element).velocity({opacity: 1}, {
3417 duration: 650,
3418 queue: false,
3419 easing: 'easeOutSine'
3420 });
3421 $(element).velocity({opacity: 1}, {
3422 duration: 1300,
3423 queue: false,
3424 easing: 'swing',
3425 step: function(now, fx) {
3426 fx.start = 100;
3427 var grayscale_setting = now/100;
3428 var brightness_setting = 150 - (100 - now)/1.75;
3429
3430 if (brightness_setting < 100) {
3431 brightness_setting = 100;
3432 }
3433 if (now >= 0) {
3434 $(this).css({
3435 "-webkit-filter": "grayscale("+grayscale_setting+")" + "brightness("+brightness_setting+"%)",
3436 "filter": "grayscale("+grayscale_setting+")" + "brightness("+brightness_setting+"%)"
3437 });
3438 }
3439 }
3440 });
3441 };
3442
3443 // Horizontal staggered list
3444 Materialize.showStaggeredList = function(selector) {
3445 var time = 0;
3446 $(selector).find('li').velocity(
3447 { translateX: "-100px"},
3448 { duration: 0 });
3449
3450 $(selector).find('li').each(function() {
3451 $(this).velocity(
3452 { opacity: "1", translateX: "0"},
3453 { duration: 800, delay: time, easing: [60, 10] });
3454 time += 120;
3455 });
3456 };
3457
3458
3459 $(document).ready(function() {
3460 // Hardcoded .staggered-list scrollFire
3461 // var staggeredListOptions = [];
3462 // $('ul.staggered-list').each(function (i) {
3463
3464 // var label = 'scrollFire-' + i;
3465 // $(this).addClass(label);
3466 // staggeredListOptions.push(
3467 // {selector: 'ul.staggered-list.' + label,
3468 // offset: 200,
3469 // callback: 'showStaggeredList("ul.staggered-list.' + label + '")'});
3470 // });
3471 // scrollFire(staggeredListOptions);
3472
3473 // HammerJS, Swipe navigation
3474
3475 // Touch Event
3476 var swipeLeft = false;
3477 var swipeRight = false;
3478
3479
3480 // Dismissible Collections
3481 $('.dismissable').each(function() {
3482 $(this).hammer({
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;
3490
3491 $this.velocity({ translateX: x
3492 }, {duration: 50, queue: false, easing: 'easeOutQuad'});
3493
3494 // Swipe Left
3495 if (direction === 4 && (x > ($this.innerWidth() / 2) || velocityX < -0.75)) {
3496 swipeLeft = true;
3497 }
3498
3499 // Swipe Right
3500 if (direction === 2 && (x < (-1 * $this.innerWidth() / 2) || velocityX > 0.75)) {
3501 swipeRight = true;
3502 }
3503 }
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)) {
3507 swipeRight = false;
3508 swipeLeft = false;
3509 }
3510
3511 if (e.gesture.pointerType === "touch") {
3512 var $this = $(this);
3513 if (swipeLeft || swipeRight) {
3514 var fullWidth;
3515 if (swipeLeft) { fullWidth = $this.innerWidth(); }
3516 else { fullWidth = -1 * $this.innerWidth(); }
3517
3518 $this.velocity({ translateX: fullWidth,
3519 }, {duration: 100, queue: false, easing: 'easeOutQuad', complete:
3520 function() {
3521 $this.css('border', 'none');
3522 $this.velocity({ height: 0, padding: 0,
3523 }, {duration: 200, queue: false, easing: 'easeOutQuad', complete:
3524 function() { $this.remove(); }
3525 });
3526 }
3527 });
3528 }
3529 else {
3530 $this.velocity({ translateX: 0,
3531 }, {duration: 100, queue: false, easing: 'easeOutQuad'});
3532 }
3533 swipeLeft = false;
3534 swipeRight = false;
3535 }
3536 });
3537
3538 });
3539
3540
3541 // time = 0
3542 // // Vertical Staggered list
3543 // $('ul.staggered-list.vertical li').velocity(
3544 // { translateY: "100px"},
3545 // { duration: 0 });
3546
3547 // $('ul.staggered-list.vertical li').each(function() {
3548 // $(this).velocity(
3549 // { opacity: "1", translateY: "0"},
3550 // { duration: 800, delay: time, easing: [60, 25] });
3551 // time += 120;
3552 // });
3553
3554 // // Fade in and Scale
3555 // $('.fade-in.scale').velocity(
3556 // { scaleX: .4, scaleY: .4, translateX: -600},
3557 // { duration: 0});
3558 // $('.fade-in').each(function() {
3559 // $(this).velocity(
3560 // { opacity: "1", scaleX: 1, scaleY: 1, translateX: 0},
3561 // { duration: 800, easing: [60, 10] });
3562 // });
3563 });
3564}( jQuery ));
3565;(function($) {
3566
3567 // Input: Array of JSON objects {selector, offset, callback}
3568
3569 Materialize.scrollFire = function(options) {
3570
3571 var didScroll = false;
3572
3573 window.addEventListener("scroll", function() {
3574 didScroll = true;
3575 });
3576
3577 // Rate limit to 100ms
3578 setInterval(function() {
3579 if(didScroll) {
3580 didScroll = false;
3581
3582 var windowScroll = window.pageYOffset + window.innerHeight;
3583
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;
3590
3591 var currentElement = document.querySelector(selector);
3592 if ( currentElement !== null) {
3593 var elementOffset = currentElement.getBoundingClientRect().top + window.pageYOffset;
3594
3595 if (windowScroll > (elementOffset + offset)) {
3596 if (value.done !== true) {
3597 var callbackFunc = new Function(callback);
3598 callbackFunc();
3599 value.done = true;
3600 }
3601 }
3602 }
3603 }
3604 }
3605 }, 100);
3606 };
3607
3608})(jQuery);;/*!
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
3613 */
3614
3615(function ( factory ) {
3616
3617 // AMD.
3618 if ( typeof define == 'function' && define.amd )
3619 define( 'picker', ['jquery'], factory )
3620
3621 // Node.js/browserify.
3622 else if ( typeof exports == 'object' )
3623 module.exports = factory( require('jquery') )
3624
3625 // Browser globals.
3626 else this.Picker = factory( jQuery )
3627
3628}(function( $ ) {
3629
3630var $window = $( window )
3631var $document = $( document )
3632var $html = $( document.documentElement )
3633
3634
3635/**
3636 * The picker constructor that creates a blank picker.
3637 */
3638function PickerConstructor( ELEMENT, NAME, COMPONENT, OPTIONS ) {
3639
3640 // If there’s no element, return the picker constructor.
3641 if ( !ELEMENT ) return PickerConstructor
3642
3643
3644 var
3645 IS_DEFAULT_THEME = false,
3646
3647
3648 // The state of the picker.
3649 STATE = {
3650 id: ELEMENT.id || 'P' + Math.abs( ~~(Math.random() * new Date()) )
3651 },
3652
3653
3654 // Merge the defaults and options passed.
3655 SETTINGS = COMPONENT ? $.extend( true, {}, COMPONENT.defaults, OPTIONS ) : OPTIONS || {},
3656
3657
3658 // Merge the default classes with the settings classes.
3659 CLASSES = $.extend( {}, PickerConstructor.klasses(), SETTINGS.klass ),
3660
3661
3662 // The element node wrapper into a jQuery object.
3663 $ELEMENT = $( ELEMENT ),
3664
3665
3666 // Pseudo picker constructor.
3667 PickerInstance = function() {
3668 return this.start()
3669 },
3670
3671
3672 // The picker prototype.
3673 P = PickerInstance.prototype = {
3674
3675 constructor: PickerInstance,
3676
3677 $node: $ELEMENT,
3678
3679
3680 /**
3681 * Initialize everything
3682 */
3683 start: function() {
3684
3685 // If it’s already started, do nothing.
3686 if ( STATE && STATE.start ) return P
3687
3688
3689 // Update the picker states.
3690 STATE.methods = {}
3691 STATE.start = true
3692 STATE.open = false
3693 STATE.type = ELEMENT.type
3694
3695
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'
3703 }
3704
3705
3706 // Create a new picker component with the settings.
3707 P.component = new COMPONENT(P, SETTINGS)
3708
3709
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()
3713
3714
3715 // If there’s a format for the hidden input element, create the element.
3716 if ( SETTINGS.formatSubmit ) {
3717 prepareElementHidden()
3718 }
3719
3720
3721 // Prepare the input element.
3722 prepareElement()
3723
3724
3725 // Insert the root as specified in the settings.
3726 if ( SETTINGS.container ) $( SETTINGS.container ).append( P.$root )
3727 else $ELEMENT.after( P.$root )
3728
3729
3730 // Bind the default component and settings events.
3731 P.on({
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
3738 }).on({
3739 start: SETTINGS.onStart,
3740 render: SETTINGS.onRender,
3741 stop: SETTINGS.onStop,
3742 open: SETTINGS.onOpen,
3743 close: SETTINGS.onClose,
3744 set: SETTINGS.onSet
3745 })
3746
3747
3748 // Once we’re all set, check the theme in use.
3749 IS_DEFAULT_THEME = isUsingDefaultTheme( P.$root.children()[ 0 ] )
3750
3751
3752 // If the element has autofocus, open the picker.
3753 if ( ELEMENT.autofocus ) {
3754 P.open()
3755 }
3756
3757
3758 // Trigger queued the “start” and “render” events.
3759 return P.trigger( 'start' ).trigger( 'render' )
3760 }, //start
3761
3762
3763 /**
3764 * Render a new picker
3765 */
3766 render: function( entireComponent ) {
3767
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 ) )
3771
3772 // Trigger the queued “render” events.
3773 return P.trigger( 'render' )
3774 }, //render
3775
3776
3777 /**
3778 * Destroy everything
3779 */
3780 stop: function() {
3781
3782 // If it’s already stopped, do nothing.
3783 if ( !STATE.start ) return P
3784
3785 // Then close the picker.
3786 P.close()
3787
3788 // Remove the hidden field.
3789 if ( P._hidden ) {
3790 P._hidden.parentNode.removeChild( P._hidden )
3791 }
3792
3793 // Remove the root.
3794 P.$root.remove()
3795
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 )
3801 }, 0)
3802
3803 // Restore the element state
3804 ELEMENT.type = STATE.type
3805 ELEMENT.readOnly = false
3806
3807 // Trigger the queued “stop” events.
3808 P.trigger( 'stop' )
3809
3810 // Reset the picker states.
3811 STATE.methods = {}
3812 STATE.start = false
3813
3814 return P
3815 }, //stop
3816
3817
3818 /**
3819 * Open up the picker
3820 */
3821 open: function( dontGiveFocus ) {
3822
3823 // If it’s already open, do nothing.
3824 if ( STATE.open ) return P
3825
3826 // Add the “active” class.
3827 $ELEMENT.addClass( CLASSES.active )
3828 aria( ELEMENT, 'expanded', true )
3829
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() {
3834
3835 // Add the “opened” class to the picker root.
3836 P.$root.addClass( CLASSES.opened )
3837 aria( P.$root[0], 'hidden', false )
3838
3839 }, 0 )
3840
3841 // If we have to give focus, bind the element and doc events.
3842 if ( dontGiveFocus !== false ) {
3843
3844 // Set it as open.
3845 STATE.open = true
3846
3847 // Prevent the page from scrolling.
3848 if ( IS_DEFAULT_THEME ) {
3849 $html.
3850 css( 'overflow', 'hidden' ).
3851 css( 'padding-right', '+=' + getScrollbarWidth() )
3852 }
3853
3854 // Pass focus to the root element’s jQuery object.
3855 // * Workaround for iOS8 to bring the picker’s root into view.
3856 P.$root[0].focus()
3857
3858 // Bind the document events.
3859 $document.on( 'click.' + STATE.id + ' focusin.' + STATE.id, function( event ) {
3860
3861 var target = event.target
3862
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 ) {
3871
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] )
3875 }
3876
3877 }).on( 'keydown.' + STATE.id, function( event ) {
3878
3879 var
3880 // Get the keycode.
3881 keycode = event.keyCode,
3882
3883 // Translate that to a selection change.
3884 keycodeToMove = P.component.key[ keycode ],
3885
3886 // Grab the target.
3887 target = event.target
3888
3889
3890 // On escape, close the picker and give focus.
3891 if ( keycode == 27 ) {
3892 P.close( true )
3893 }
3894
3895
3896 // Check if there is a key movement or “enter” keypress on the element.
3897 else if ( target == P.$root[0] && ( keycodeToMove || keycode == 13 ) ) {
3898
3899 // Prevent the default action to stop page movement.
3900 event.preventDefault()
3901
3902 // Trigger the key movement action.
3903 if ( keycodeToMove ) {
3904 PickerConstructor._.trigger( P.component.key.go, P, [ PickerConstructor._.trigger( keycodeToMove ) ] )
3905 }
3906
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()
3910 }
3911 }
3912
3913
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()
3918 target.click()
3919 }
3920 })
3921 }
3922
3923 // Trigger the queued “open” events.
3924 return P.trigger( 'open' )
3925 }, //open
3926
3927
3928 /**
3929 * Close the picker
3930 */
3931 close: function( giveFocus ) {
3932
3933 // If we need to give focus, do it before changing states.
3934 if ( giveFocus ) {
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 )
3941 }, 0 )
3942 }
3943
3944 // Remove the “active” class.
3945 $ELEMENT.removeClass( CLASSES.active )
3946 aria( ELEMENT, 'expanded', false )
3947
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() {
3952
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 )
3956
3957 }, 0 )
3958
3959 // If it’s already closed, do nothing more.
3960 if ( !STATE.open ) return P
3961
3962 // Set it as closed.
3963 STATE.open = false
3964
3965 // Allow the page to scroll.
3966 if ( IS_DEFAULT_THEME ) {
3967 $html.
3968 css( 'overflow', '' ).
3969 css( 'padding-right', '-=' + getScrollbarWidth() )
3970 }
3971
3972 // Unbind the document events.
3973 $document.off( '.' + STATE.id )
3974
3975 // Trigger the queued “close” events.
3976 return P.trigger( 'close' )
3977 }, //close
3978
3979
3980 /**
3981 * Clear the values
3982 */
3983 clear: function( options ) {
3984 return P.set( 'clear', null, options )
3985 }, //clear
3986
3987
3988 /**
3989 * Set something
3990 */
3991 set: function( thing, value, options ) {
3992
3993 var thingItem, thingValue,
3994 thingIsObject = $.isPlainObject( thing ),
3995 thingObject = thingIsObject ? thing : {}
3996
3997 // Make sure we have usable options.
3998 options = thingIsObject && $.isPlainObject( value ) ? value : options || {}
3999
4000 if ( thing ) {
4001
4002 // If the thing isn’t an object, make it one.
4003 if ( !thingIsObject ) {
4004 thingObject[ thing ] = value
4005 }
4006
4007 // Go through the things of items to set.
4008 for ( thingItem in thingObject ) {
4009
4010 // Grab the value of the thing.
4011 thingValue = thingObject[ thingItem ]
4012
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 )
4017 }
4018
4019 // Then, check to update the element value and broadcast a change.
4020 if ( thingItem == 'select' || thingItem == 'clear' ) {
4021 $ELEMENT.
4022 val( thingItem == 'clear' ? '' : P.get( thingItem, SETTINGS.format ) ).
4023 trigger( 'change' )
4024 }
4025 }
4026
4027 // Render a new picker.
4028 P.render()
4029 }
4030
4031 // When the method isn’t muted, trigger queued “set” events and pass the `thingObject`.
4032 return options.muted ? P : P.trigger( 'set', thingObject )
4033 }, //set
4034
4035
4036 /**
4037 * Get something
4038 */
4039 get: function( thing, format ) {
4040
4041 // Make sure there’s something to get.
4042 thing = thing || 'value'
4043
4044 // If a picker state exists, return that.
4045 if ( STATE[ thing ] != null ) {
4046 return STATE[ thing ]
4047 }
4048
4049 // Return the submission value, if that.
4050 if ( thing == 'valueSubmit' ) {
4051 if ( P._hidden ) {
4052 return P._hidden.value
4053 }
4054 thing = 'value'
4055 }
4056
4057 // Return the value, if that.
4058 if ( thing == 'value' ) {
4059 return ELEMENT.value
4060 }
4061
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 )
4066 return thingValue ?
4067 PickerConstructor._.trigger(
4068 P.component.formats.toString,
4069 P.component,
4070 [ format, thingValue ]
4071 ) : ''
4072 }
4073 return P.component.get( thing )
4074 }
4075 }, //get
4076
4077
4078
4079 /**
4080 * Bind events on the things.
4081 */
4082 on: function( thing, method, internal ) {
4083
4084 var thingName, thingMethod,
4085 thingIsObject = $.isPlainObject( thing ),
4086 thingObject = thingIsObject ? thing : {}
4087
4088 if ( thing ) {
4089
4090 // If the thing isn’t an object, make it one.
4091 if ( !thingIsObject ) {
4092 thingObject[ thing ] = method
4093 }
4094
4095 // Go through the things to bind to.
4096 for ( thingName in thingObject ) {
4097
4098 // Grab the method of the thing.
4099 thingMethod = thingObject[ thingName ]
4100
4101 // If it was an internal binding, prefix it.
4102 if ( internal ) {
4103 thingName = '_' + thingName
4104 }
4105
4106 // Make sure the thing methods collection exists.
4107 STATE.methods[ thingName ] = STATE.methods[ thingName ] || []
4108
4109 // Add the method to the relative method collection.
4110 STATE.methods[ thingName ].push( thingMethod )
4111 }
4112 }
4113
4114 return P
4115 }, //on
4116
4117
4118
4119 /**
4120 * Unbind events on the things.
4121 */
4122 off: function() {
4123 var i, thingName,
4124 names = arguments;
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]
4129 }
4130 }
4131 return P
4132 },
4133
4134
4135 /**
4136 * Fire off method events.
4137 */
4138 trigger: function( name, data ) {
4139 var _trigger = function( name ) {
4140 var methodList = STATE.methods[ name ]
4141 if ( methodList ) {
4142 methodList.map( function( method ) {
4143 PickerConstructor._.trigger( method, P, [ data ] )
4144 })
4145 }
4146 }
4147 _trigger( '_' + name )
4148 _trigger( name )
4149 return P
4150 } //trigger
4151 } //PickerInstance.prototype
4152
4153
4154 /**
4155 * Wrap the picker holder components together.
4156 */
4157 function createWrappedComponent() {
4158
4159 // Create a picker wrapper holder
4160 return PickerConstructor._.node( 'div',
4161
4162 // Create a picker wrapper node
4163 PickerConstructor._.node( 'div',
4164
4165 // Create a picker frame
4166 PickerConstructor._.node( 'div',
4167
4168 // Create a picker box node
4169 PickerConstructor._.node( 'div',
4170
4171 // Create the components nodes.
4172 P.component.nodes( STATE.open ),
4173
4174 // The picker box class
4175 CLASSES.box
4176 ),
4177
4178 // Picker wrap class
4179 CLASSES.wrap
4180 ),
4181
4182 // Picker frame class
4183 CLASSES.frame
4184 ),
4185
4186 // Picker holder class
4187 CLASSES.holder
4188 ) //endreturn
4189 } //createWrappedComponent
4190
4191
4192
4193 /**
4194 * Prepare the input element with all bindings.
4195 */
4196 function prepareElement() {
4197
4198 $ELEMENT.
4199
4200 // Store the picker data by component name.
4201 data(NAME, P).
4202
4203 // Add the “input” class name.
4204 addClass(CLASSES.input).
4205
4206 // Remove the tabindex.
4207 attr('tabindex', -1).
4208
4209 // If there’s a `data-value`, update the value of the element.
4210 val( $ELEMENT.data('value') ?
4211 P.get('select', SETTINGS.format) :
4212 ELEMENT.value
4213 )
4214
4215
4216 // Only bind keydown events if the element isn’t editable.
4217 if ( !SETTINGS.editable ) {
4218
4219 $ELEMENT.
4220
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()
4224 P.$root[0].focus()
4225 }).
4226
4227 // Handle keyboard event based on the picker being opened or not.
4228 on( 'keydown.' + STATE.id, handleKeydownEvent )
4229 }
4230
4231
4232 // Update the aria attributes.
4233 aria(ELEMENT, {
4234 haspopup: true,
4235 expanded: false,
4236 readonly: false,
4237 owns: ELEMENT.id + '_root'
4238 })
4239 }
4240
4241
4242 /**
4243 * Prepare the root picker element with all bindings.
4244 */
4245 function prepareElementRoot() {
4246
4247 P.$root.
4248
4249 on({
4250
4251 // For iOS8.
4252 keydown: handleKeydownEvent,
4253
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()
4259 },
4260
4261 // When something within the root holder is clicked, stop it
4262 // from bubbling to the doc.
4263 'mousedown click': function( event ) {
4264
4265 var target = event.target
4266
4267 // Make sure the target isn’t the root holder so it can bubble up.
4268 if ( target != P.$root.children()[ 0 ] ) {
4269
4270 event.stopPropagation()
4271
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' )) {
4277
4278 event.preventDefault()
4279
4280 // Re-focus onto the root so that users can click away
4281 // from elements focused within the picker.
4282 P.$root[0].focus()
4283 }
4284 }
4285 }
4286 }).
4287
4288 // Add/remove the “target” class on focus and blur.
4289 on({
4290 focus: function() {
4291 $ELEMENT.addClass( CLASSES.target )
4292 },
4293 blur: function() {
4294 $ELEMENT.removeClass( CLASSES.target )
4295 }
4296 }).
4297
4298 // Open the picker and adjust the root “focused” state
4299 on( 'focus.toOpen', handleFocusToOpenEvent ).
4300
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() {
4303
4304 var $target = $( this ),
4305 targetData = $target.data(),
4306 targetDisabled = $target.hasClass( CLASSES.navDisabled ) || $target.hasClass( CLASSES.disabled ),
4307
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 )
4312
4313 // If it’s disabled or nothing inside is actively focused, re-focus the element.
4314 if ( targetDisabled || activeElement && !$.contains( P.$root[0], activeElement ) ) {
4315 P.$root[0].focus()
4316 }
4317
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 } )
4321 }
4322
4323 // If something is picked, set `select` then close with focus.
4324 else if ( !targetDisabled && 'pick' in targetData ) {
4325 P.set( 'select', targetData.pick )
4326 }
4327
4328 // If a “clear” button is pressed, empty the values and close with focus.
4329 else if ( targetData.clear ) {
4330 P.clear().close( true )
4331 }
4332
4333 else if ( targetData.close ) {
4334 P.close( true )
4335 }
4336
4337 }) //P.$root
4338
4339 aria( P.$root[0], 'hidden', true )
4340 }
4341
4342
4343 /**
4344 * Prepare the hidden input element along with all bindings.
4345 */
4346 function prepareElementHidden() {
4347
4348 var name
4349
4350 if ( SETTINGS.hiddenName === true ) {
4351 name = ELEMENT.name
4352 ELEMENT.name = ''
4353 }
4354 else {
4355 name = [
4356 typeof SETTINGS.hiddenPrefix == 'string' ? SETTINGS.hiddenPrefix : '',
4357 typeof SETTINGS.hiddenSuffix == 'string' ? SETTINGS.hiddenSuffix : '_submit'
4358 ]
4359 name = name[0] + ELEMENT.name + name[1]
4360 }
4361
4362 P._hidden = $(
4363 '<input ' +
4364 'type=hidden ' +
4365
4366 // Create the name using the original input’s with a prefix and suffix.
4367 'name="' + name + '"' +
4368
4369 // If the element has a value, set the hidden value as well.
4370 (
4371 $ELEMENT.data('value') || ELEMENT.value ?
4372 ' value="' + P.get('select', SETTINGS.formatSubmit) + '"' :
4373 ''
4374 ) +
4375 '>'
4376 )[0]
4377
4378 $ELEMENT.
4379
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) :
4384 ''
4385 })
4386
4387
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 )
4391 }
4392
4393
4394 // For iOS8.
4395 function handleKeydownEvent( event ) {
4396
4397 var keycode = event.keyCode,
4398
4399 // Check if one of the delete keys was pressed.
4400 isKeycodeDelete = /^(8|46)$/.test(keycode)
4401
4402 // For some reason IE clears the input value on “escape”.
4403 if ( keycode == 27 ) {
4404 P.close()
4405 return false
4406 }
4407
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] ) {
4410
4411 // Prevent it from moving the page and bubbling to doc.
4412 event.preventDefault()
4413 event.stopPropagation()
4414
4415 // If `delete` was pressed, clear the values and close the picker.
4416 // Otherwise open the picker.
4417 if ( isKeycodeDelete ) { P.clear().close() }
4418 else { P.open() }
4419 }
4420 }
4421
4422
4423 // Separated for IE
4424 function handleFocusToOpenEvent( event ) {
4425
4426 // Stop the event from propagating to the doc.
4427 event.stopPropagation()
4428
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 )
4432 }
4433
4434 // And then finally open the picker.
4435 P.open()
4436 }
4437
4438
4439 // Return a new picker instance.
4440 return new PickerInstance()
4441} //PickerConstructor
4442
4443
4444
4445/**
4446 * The default classes and prefix to use for the HTML classes.
4447 */
4448PickerConstructor.klasses = function( prefix ) {
4449 prefix = prefix || 'picker'
4450 return {
4451
4452 picker: prefix,
4453 opened: prefix + '--opened',
4454 focused: prefix + '--focused',
4455
4456 input: prefix + '__input',
4457 active: prefix + '__input--active',
4458 target: prefix + '__input--target',
4459
4460 holder: prefix + '__holder',
4461
4462 frame: prefix + '__frame',
4463 wrap: prefix + '__wrap',
4464
4465 box: prefix + '__box'
4466 }
4467} //PickerConstructor.klasses
4468
4469
4470
4471/**
4472 * Check if the default theme is being used.
4473 */
4474function isUsingDefaultTheme( element ) {
4475
4476 var theme,
4477 prop = 'position'
4478
4479 // For IE.
4480 if ( element.currentStyle ) {
4481 theme = element.currentStyle[prop]
4482 }
4483
4484 // For normal browsers.
4485 else if ( window.getComputedStyle ) {
4486 theme = getComputedStyle( element )[prop]
4487 }
4488
4489 return theme == 'fixed'
4490}
4491
4492
4493
4494/**
4495 * Get the width of the browser’s scrollbar.
4496 * Taken from: https://github.com/VodkaBears/Remodal/blob/master/src/jquery.remodal.js
4497 */
4498function getScrollbarWidth() {
4499
4500 if ( $html.height() <= $window.height() ) {
4501 return 0
4502 }
4503
4504 var $outer = $( '<div style="visibility:hidden;width:100px" />' ).
4505 appendTo( 'body' )
4506
4507 // Get the width without scrollbars.
4508 var widthWithoutScroll = $outer[0].offsetWidth
4509
4510 // Force adding scrollbars.
4511 $outer.css( 'overflow', 'scroll' )
4512
4513 // Add the inner div.
4514 var $inner = $( '<div style="width:100%" />' ).appendTo( $outer )
4515
4516 // Get the width with scrollbars.
4517 var widthWithScroll = $inner[0].offsetWidth
4518
4519 // Remove the divs.
4520 $outer.remove()
4521
4522 // Return the difference between the widths.
4523 return widthWithoutScroll - widthWithScroll
4524}
4525
4526
4527
4528/**
4529 * PickerConstructor helper methods.
4530 */
4531PickerConstructor._ = {
4532
4533 /**
4534 * Create a group of nodes. Expects:
4535 * `
4536 {
4537 min: {Integer},
4538 max: {Integer},
4539 i: {Integer},
4540 node: {String},
4541 item: {Function}
4542 }
4543 * `
4544 */
4545 group: function( groupObject ) {
4546
4547 var
4548 // Scope for the looped object
4549 loopObjectScope,
4550
4551 // Create the nodes list
4552 nodesList = '',
4553
4554 // The counter starts from the `min`
4555 counter = PickerConstructor._.trigger( groupObject.min, groupObject )
4556
4557
4558 // Loop from the `min` to `max`, incrementing by `i`
4559 for ( ; counter <= PickerConstructor._.trigger( groupObject.max, groupObject, [ counter ] ); counter += groupObject.i ) {
4560
4561 // Trigger the `item` function within scope of the object
4562 loopObjectScope = PickerConstructor._.trigger( groupObject.item, groupObject, [ counter ] )
4563
4564 // Splice the subgroup and create nodes out of the sub nodes
4565 nodesList += PickerConstructor._.node(
4566 groupObject.node,
4567 loopObjectScope[ 0 ], // the node
4568 loopObjectScope[ 1 ], // the classes
4569 loopObjectScope[ 2 ] // the attributes
4570 )
4571 }
4572
4573 // Return the list of nodes
4574 return nodesList
4575 }, //group
4576
4577
4578 /**
4579 * Create a dom node string
4580 */
4581 node: function( wrapper, item, klass, attribute ) {
4582
4583 // If the item is false-y, just return an empty string
4584 if ( !item ) return ''
4585
4586 // If the item is an array, do a join
4587 item = $.isArray( item ) ? item.join( '' ) : item
4588
4589 // Check for the class
4590 klass = klass ? ' class="' + klass + '"' : ''
4591
4592 // Check for any attributes
4593 attribute = attribute ? ' ' + attribute : ''
4594
4595 // Return the wrapped item
4596 return '<' + wrapper + klass + attribute + '>' + item + '</' + wrapper + '>'
4597 }, //node
4598
4599
4600 /**
4601 * Lead numbers below 10 with a zero.
4602 */
4603 lead: function( number ) {
4604 return ( number < 10 ? '0': '' ) + number
4605 },
4606
4607
4608 /**
4609 * Trigger a function otherwise return the value.
4610 */
4611 trigger: function( callback, scope, args ) {
4612 return typeof callback == 'function' ? callback.apply( scope, args || [] ) : callback
4613 },
4614
4615
4616 /**
4617 * If the second character is a digit, length is 2 otherwise 1.
4618 */
4619 digits: function( string ) {
4620 return ( /\d/ ).test( string[ 1 ] ) ? 2 : 1
4621 },
4622
4623
4624 /**
4625 * Tell if something is a date object.
4626 */
4627 isDate: function( value ) {
4628 return {}.toString.call( value ).indexOf( 'Date' ) > -1 && this.isInteger( value.getDate() )
4629 },
4630
4631
4632 /**
4633 * Tell if something is an integer.
4634 */
4635 isInteger: function( value ) {
4636 return {}.toString.call( value ).indexOf( 'Number' ) > -1 && value % 1 === 0
4637 },
4638
4639
4640 /**
4641 * Create ARIA attribute strings.
4642 */
4643 ariaAttr: ariaAttr
4644} //PickerConstructor._
4645
4646
4647
4648/**
4649 * Extend the picker with a component and defaults.
4650 */
4651PickerConstructor.extend = function( name, Component ) {
4652
4653 // Extend jQuery.
4654 $.fn[ name ] = function( options, action ) {
4655
4656 // Grab the component data.
4657 var componentData = this.data( name )
4658
4659 // If the picker is requested, return the data object.
4660 if ( options == 'picker' ) {
4661 return componentData
4662 }
4663
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 ] )
4667 }
4668
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 )
4676 }
4677 })
4678 }
4679
4680 // Set the defaults.
4681 $.fn[ name ].defaults = Component.defaults
4682} //PickerConstructor.extend
4683
4684
4685
4686function aria(element, attribute, value) {
4687 if ( $.isPlainObject(attribute) ) {
4688 for ( var key in attribute ) {
4689 ariaSet(element, key, attribute[key])
4690 }
4691 }
4692 else {
4693 ariaSet(element, attribute, value)
4694 }
4695}
4696function ariaSet(element, attribute, value) {
4697 element.setAttribute(
4698 (attribute == 'role' ? '' : 'aria-') + attribute,
4699 value
4700 )
4701}
4702function ariaAttr(attribute, data) {
4703 if ( !$.isPlainObject(attribute) ) {
4704 attribute = { attribute: data }
4705 }
4706 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] + '"'
4711 }
4712 return data
4713}
4714
4715// IE8 bug throws an error for activeElements within iframes.
4716function getActiveElement() {
4717 try {
4718 return document.activeElement
4719 } catch ( err ) { }
4720}
4721
4722
4723
4724// Expose the picker constructor.
4725return PickerConstructor
4726
4727
4728}));
4729
4730
4731;/*!
4732 * Date picker for pickadate.js v3.5.0
4733 * http://amsul.github.io/pickadate.js/date.htm
4734 */
4735
4736(function ( factory ) {
4737
4738 // AMD.
4739 if ( typeof define == 'function' && define.amd )
4740 define( ['picker', 'jquery'], factory )
4741
4742 // Node.js/browserify.
4743 else if ( typeof exports == 'object' )
4744 module.exports = factory( require('./picker.js'), require('jquery') )
4745
4746 // Browser globals.
4747 else factory( Picker, jQuery )
4748
4749}(function( Picker, $ ) {
4750
4751
4752/**
4753 * Globals and constants
4754 */
4755var DAYS_IN_WEEK = 7,
4756 WEEKS_IN_CALENDAR = 6,
4757 _ = Picker._
4758
4759
4760
4761/**
4762 * The date picker constructor
4763 */
4764function DatePicker( picker, settings ) {
4765
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() {
4773
4774 return element.currentStyle ?
4775
4776 // For IE.
4777 element.currentStyle.direction == 'rtl' :
4778
4779 // For normal browsers.
4780 getComputedStyle( picker.$root[0] ).direction == 'rtl'
4781 }
4782
4783 calendar.settings = settings
4784 calendar.$node = picker.$node
4785
4786 // The queue of methods that will be used to build item objects.
4787 calendar.queue = {
4788 min: 'measure create',
4789 max: 'measure create',
4790 now: 'now create',
4791 select: 'parse create validate',
4792 highlight: 'parse navigate create validate',
4793 view: 'parse create validate viewset',
4794 disable: 'deactivate',
4795 enable: 'activate'
4796 }
4797
4798 // The component's item object.
4799 calendar.item = {}
4800
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 )
4806
4807 calendar.
4808 set( 'min', settings.min ).
4809 set( 'max', settings.max ).
4810 set( 'now' )
4811
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 })
4816 }
4817
4818 // If there’s no value, default to highlighting “today”.
4819 else {
4820 calendar.
4821 set( 'select', null ).
4822 set( 'highlight', calendar.item.now )
4823 }
4824
4825
4826 // The keycode to movement mapping.
4827 calendar.key = {
4828 40: 7, // Down
4829 38: -7, // Up
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 )
4835 calendar.set(
4836 'highlight',
4837 targetDate,
4838 { interval: timeChange }
4839 )
4840 this.render()
4841 }
4842 }
4843
4844
4845 // Bind some picker events.
4846 picker.
4847 on( 'render', function() {
4848 picker.$root.find( '.' + settings.klass.selectMonth ).on( 'change', function() {
4849 var value = this.value
4850 if ( value ) {
4851 picker.set( 'highlight', [ picker.get( 'view' ).year, value, picker.get( 'highlight' ).date ] )
4852 picker.$root.find( '.' + settings.klass.selectMonth ).trigger( 'focus' )
4853 }
4854 })
4855 picker.$root.find( '.' + settings.klass.selectYear ).on( 'change', function() {
4856 var value = this.value
4857 if ( value ) {
4858 picker.set( 'highlight', [ value, picker.get( 'view' ).month, picker.get( 'highlight' ).date ] )
4859 picker.$root.find( '.' + settings.klass.selectYear ).trigger( 'focus' )
4860 }
4861 })
4862 }, 1 ).
4863 on( 'open', function() {
4864 var includeToday = ''
4865 if ( calendar.disabled( calendar.get('now') ) ) {
4866 includeToday = ':not(.' + settings.klass.buttonToday + ')'
4867 }
4868 picker.$root.find( 'button' + includeToday + ', select' ).attr( 'disabled', false )
4869 }, 1 ).
4870 on( 'close', function() {
4871 picker.$root.find( 'button, select' ).attr( 'disabled', true )
4872 }, 1 )
4873
4874} //DatePicker
4875
4876
4877/**
4878 * Set a datepicker item object.
4879 */
4880DatePicker.prototype.set = function( type, value, options ) {
4881
4882 var calendar = this,
4883 calendarItem = calendar.item
4884
4885 // If the value is `null` just set it immediately.
4886 if ( value === null ) {
4887 if ( type == 'clear' ) type = 'select'
4888 calendarItem[ type ] = value
4889 return calendar
4890 }
4891
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 )
4898 return value
4899 }).pop()
4900
4901 // Check if we need to cascade through more updates.
4902 if ( type == 'select' ) {
4903 calendar.set( 'highlight', calendarItem.select, options )
4904 }
4905 else if ( type == 'highlight' ) {
4906 calendar.set( 'view', calendarItem.highlight, options )
4907 }
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 )
4911 }
4912 if ( calendarItem.highlight && calendar.disabled( calendarItem.highlight ) ) {
4913 calendar.set( 'highlight', calendarItem.highlight, options )
4914 }
4915 }
4916
4917 return calendar
4918} //DatePicker.prototype.set
4919
4920
4921/**
4922 * Get a datepicker item object.
4923 */
4924DatePicker.prototype.get = function( type ) {
4925 return this.item[ type ]
4926} //DatePicker.prototype.get
4927
4928
4929/**
4930 * Create a picker date object.
4931 */
4932DatePicker.prototype.create = function( type, value, options ) {
4933
4934 var isInfiniteValue,
4935 calendar = this
4936
4937 // If there’s no value, use the type as the value.
4938 value = value === undefined ? type : value
4939
4940
4941 // If it’s infinity, update the value.
4942 if ( value == -Infinity || value == Infinity ) {
4943 isInfiniteValue = value
4944 }
4945
4946 // If it’s an object, use the native date object.
4947 else if ( $.isPlainObject( value ) && _.isInteger( value.pick ) ) {
4948 value = value.obj
4949 }
4950
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
4956 }
4957
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 )
4961 }
4962
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 )
4966 }
4967
4968 // Return the compiled object.
4969 return {
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()
4976 }
4977} //DatePicker.prototype.create
4978
4979
4980/**
4981 * Create a range limit object using an array, date object,
4982 * literal “true”, or integer relative to another time.
4983 */
4984DatePicker.prototype.createRange = function( from, to ) {
4985
4986 var calendar = this,
4987 createDate = function( date ) {
4988 if ( date === true || $.isArray( date ) || _.isDate( date ) ) {
4989 return calendar.create( date )
4990 }
4991 return date
4992 }
4993
4994 // Create objects if possible.
4995 if ( !_.isInteger( from ) ) {
4996 from = createDate( from )
4997 }
4998 if ( !_.isInteger( to ) ) {
4999 to = createDate( to )
5000 }
5001
5002 // Create relative dates.
5003 if ( _.isInteger( from ) && $.isPlainObject( to ) ) {
5004 from = [ to.year, to.month, to.date + from ];
5005 }
5006 else if ( _.isInteger( to ) && $.isPlainObject( from ) ) {
5007 to = [ from.year, from.month, from.date + to ];
5008 }
5009
5010 return {
5011 from: createDate( from ),
5012 to: createDate( to )
5013 }
5014} //DatePicker.prototype.createRange
5015
5016
5017/**
5018 * Check if a date unit falls within a date range object.
5019 */
5020DatePicker.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
5023}
5024
5025
5026/**
5027 * Check if two date range objects overlap.
5028 */
5029DatePicker.prototype.overlapRanges = function( one, two ) {
5030
5031 var calendar = this
5032
5033 // Convert the ranges into comparable dates.
5034 one = calendar.createRange( one.from, one.to )
5035 two = calendar.createRange( two.from, two.to )
5036
5037 return calendar.withinRange( one, two.from ) || calendar.withinRange( one, two.to ) ||
5038 calendar.withinRange( two, one.from ) || calendar.withinRange( two, one.to )
5039}
5040
5041
5042/**
5043 * Get the date today.
5044 */
5045DatePicker.prototype.now = function( type, value, options ) {
5046 value = new Date()
5047 if ( options && options.rel ) {
5048 value.setDate( value.getDate() + options.rel )
5049 }
5050 return this.normalize( value, options )
5051}
5052
5053
5054/**
5055 * Navigate to next/prev month.
5056 */
5057DatePicker.prototype.navigate = function( type, value, options ) {
5058
5059 var targetDateObject,
5060 targetYear,
5061 targetMonth,
5062 targetDate,
5063 isTargetArray = $.isArray( value ),
5064 isTargetObject = $.isPlainObject( value ),
5065 viewsetObject = this.item.view/*,
5066 safety = 100*/
5067
5068
5069 if ( isTargetArray || isTargetObject ) {
5070
5071 if ( isTargetObject ) {
5072 targetYear = value.year
5073 targetMonth = value.month
5074 targetDate = value.date
5075 }
5076 else {
5077 targetYear = +value[0]
5078 targetMonth = +value[1]
5079 targetDate = +value[2]
5080 }
5081
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
5087 }
5088
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()
5093
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 ) {
5097 targetDate -= 1
5098 /*safety -= 1
5099 if ( !safety ) {
5100 throw 'Fell into an infinite loop while navigating to ' + new Date( targetYear, targetMonth, targetDate ) + '.'
5101 }*/
5102 }
5103
5104 value = [ targetYear, targetMonth, targetDate ]
5105 }
5106
5107 return value
5108} //DatePicker.prototype.navigate
5109
5110
5111/**
5112 * Normalize a date by setting the hours to midnight.
5113 */
5114DatePicker.prototype.normalize = function( value/*, options*/ ) {
5115 value.setHours( 0, 0, 0, 0 )
5116 return value
5117}
5118
5119
5120/**
5121 * Measure the range of dates.
5122 */
5123DatePicker.prototype.measure = function( type, value/*, options*/ ) {
5124
5125 var calendar = this
5126
5127 // If it’s anything false-y, remove the limits.
5128 if ( !value ) {
5129 value = type == 'min' ? -Infinity : Infinity
5130 }
5131
5132 // If it’s a string, parse it.
5133 else if ( typeof value == 'string' ) {
5134 value = calendar.parse( type, value )
5135 }
5136
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 } )
5140 }
5141
5142 return value
5143} ///DatePicker.prototype.measure
5144
5145
5146/**
5147 * Create a viewset object based on navigation.
5148 */
5149DatePicker.prototype.viewset = function( type, dateObject/*, options*/ ) {
5150 return this.create([ dateObject.year, dateObject.month, 1 ])
5151}
5152
5153
5154/**
5155 * Validate a date as enabled and shift if needed.
5156 */
5157DatePicker.prototype.validate = function( type, dateObject, options ) {
5158
5159 var calendar = this,
5160
5161 // Keep a reference to the original date.
5162 originalDateObject = dateObject,
5163
5164 // Make sure we have an interval.
5165 interval = options && options.interval ? options.interval : 1,
5166
5167 // Check if the calendar enabled dates are inverted.
5168 isFlippedBase = calendar.item.enable === -1,
5169
5170 // Check if we have any enabled dates after/before now.
5171 hasEnabledBeforeTarget, hasEnabledAfterTarget,
5172
5173 // The min & max limits.
5174 minLimitObject = calendar.item.min,
5175 maxLimitObject = calendar.item.max,
5176
5177 // Check if we’ve reached the limit during shifting.
5178 reachedMin, reachedMax,
5179
5180 // Check if the calendar is inverted and at least one weekday is enabled.
5181 hasEnabledWeekdays = isFlippedBase && calendar.item.disable.filter( function( value ) {
5182
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
5188 }
5189
5190 // Return only integers for enabled weekdays.
5191 return _.isInteger( value )
5192 }).length/*,
5193
5194 safety = 100*/
5195
5196
5197
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.
5202 //
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) )
5212 ) {
5213
5214
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 ) ) ) {
5218 interval *= -1
5219 }
5220
5221
5222 // Keep looping until we reach an enabled date.
5223 while ( /*safety &&*/ calendar.disabled( dateObject ) ) {
5224
5225 /*safety -= 1
5226 if ( !safety ) {
5227 throw 'Fell into an infinite loop while validating ' + dateObject.obj + '.'
5228 }*/
5229
5230
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
5235 }
5236
5237
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 ) {
5240 reachedMin = true
5241 interval = 1
5242 dateObject = calendar.create([
5243 minLimitObject.year,
5244 minLimitObject.month,
5245 minLimitObject.date + (dateObject.pick === minLimitObject.pick ? 0 : -1)
5246 ])
5247 }
5248 else if ( dateObject.pick >= maxLimitObject.pick ) {
5249 reachedMax = true
5250 interval = -1
5251 dateObject = calendar.create([
5252 maxLimitObject.year,
5253 maxLimitObject.month,
5254 maxLimitObject.date + (dateObject.pick === maxLimitObject.pick ? 0 : 1)
5255 ])
5256 }
5257
5258
5259 // If we’ve reached both limits, just break out of the loop.
5260 if ( reachedMin && reachedMax ) {
5261 break
5262 }
5263
5264
5265 // Finally, create the shifted date using the interval and keep looping.
5266 dateObject = calendar.create([ dateObject.year, dateObject.month, dateObject.date + interval ])
5267 }
5268
5269 } //endif
5270
5271
5272 // Return the date object settled on.
5273 return dateObject
5274} //DatePicker.prototype.validate
5275
5276
5277/**
5278 * Check if a date is disabled.
5279 */
5280DatePicker.prototype.disabled = function( dateToVerify ) {
5281
5282 var
5283 calendar = this,
5284
5285 // Filter through the disabled dates to check if this is one.
5286 isDisabledMatch = calendar.item.disable.filter( function( dateToDisable ) {
5287
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
5291 }
5292
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
5296 }
5297
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 )
5301 }
5302 })
5303
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
5308 }).length
5309
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
5315
5316} //DatePicker.prototype.disabled
5317
5318
5319/**
5320 * Parse a string into a usable type.
5321 */
5322DatePicker.prototype.parse = function( type, value, options ) {
5323
5324 var calendar = this,
5325 parsingObject = {}
5326
5327 // If it’s already parsed, we’re good.
5328 if ( !value || typeof value != 'string' ) {
5329 return value
5330 }
5331
5332 // We need a `.format` to parse the value with.
5333 if ( !( options && options.format ) ) {
5334 options = options || {}
5335 options.format = calendar.settings.format
5336 }
5337
5338 // Convert the format into an array and then map through it.
5339 calendar.formats.toArray( options.format ).map( function( label ) {
5340
5341 var
5342 // Grab the formatting label.
5343 formattingLabel = calendar.formats[ label ],
5344
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
5348
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 )
5353 }
5354
5355 // Update the value as the substring from format length to end.
5356 value = value.substr( formatLength )
5357 })
5358
5359 // Compensate for month 0index.
5360 return [
5361 parsingObject.yyyy || parsingObject.yy,
5362 +( parsingObject.mm || parsingObject.m ) - 1,
5363 parsingObject.dd || parsingObject.d
5364 ]
5365} //DatePicker.prototype.parse
5366
5367
5368/**
5369 * Various formats to display the object in.
5370 */
5371DatePicker.prototype.formats = (function() {
5372
5373 // Return the length of the first word in a collection.
5374 function getWordLengthFromCollection( string, collection, dateObject ) {
5375
5376 // Grab the first word from the string.
5377 var word = string.match( /\w+/ )[ 0 ]
5378
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
5382 }
5383
5384 // Return the length of the word.
5385 return word.length
5386 }
5387
5388 // Get the length of the first word in a string.
5389 function getFirstWordLength( string ) {
5390 return string.match( /\w+/ )[ 0 ].length
5391 }
5392
5393 return {
5394
5395 d: function( string, dateObject ) {
5396
5397 // If there's string, then get the digits length.
5398 // Otherwise return the selected date.
5399 return string ? _.digits( string ) : dateObject.date
5400 },
5401 dd: function( string, dateObject ) {
5402
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 )
5406 },
5407 ddd: function( string, dateObject ) {
5408
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 ]
5412 },
5413 dddd: function( string, dateObject ) {
5414
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 ]
5418 },
5419 m: function( string, dateObject ) {
5420
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
5424 },
5425 mm: function( string, dateObject ) {
5426
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 )
5430 },
5431 mmm: function( string, dateObject ) {
5432
5433 var collection = this.settings.monthsShort
5434
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 ]
5438 },
5439 mmmm: function( string, dateObject ) {
5440
5441 var collection = this.settings.monthsFull
5442
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 ]
5446 },
5447 yy: function( string, dateObject ) {
5448
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 )
5452 },
5453 yyyy: function( string, dateObject ) {
5454
5455 // If there's a string, then the length is always 4.
5456 // Otherwise return the selected year.
5457 return string ? 4 : dateObject.year
5458 },
5459
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 ) },
5462
5463 // Format an object into a string using the formatting options.
5464 toString: function ( formatString, itemObject ) {
5465 var calendar = this
5466 return calendar.formats.toArray( formatString ).map( function( label ) {
5467 return _.trigger( calendar.formats[ label ], calendar, [ 0, itemObject ] ) || label.replace( /^!/, '' )
5468 }).join( '' )
5469 }
5470 }
5471})() //DatePicker.prototype.formats
5472
5473
5474
5475
5476/**
5477 * Check if two date units are the exact.
5478 */
5479DatePicker.prototype.isDateExact = function( one, two ) {
5480
5481 var calendar = this
5482
5483 // When we’re working with weekdays, do a direct comparison.
5484 if (
5485 ( _.isInteger( one ) && _.isInteger( two ) ) ||
5486 ( typeof one == 'boolean' && typeof two == 'boolean' )
5487 ) {
5488 return one === two
5489 }
5490
5491 // When we’re working with date representations, compare the “pick” value.
5492 if (
5493 ( _.isDate( one ) || $.isArray( one ) ) &&
5494 ( _.isDate( two ) || $.isArray( two ) )
5495 ) {
5496 return calendar.create( one ).pick === calendar.create( two ).pick
5497 }
5498
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 )
5502 }
5503
5504 return false
5505}
5506
5507
5508/**
5509 * Check if two date units overlap.
5510 */
5511DatePicker.prototype.isDateOverlap = function( one, two ) {
5512
5513 var calendar = this,
5514 firstDay = calendar.settings.firstDay ? 1 : 0
5515
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
5520 }
5521 if ( _.isInteger( two ) && ( _.isDate( one ) || $.isArray( one ) ) ) {
5522 two = two % 7 + firstDay
5523 return two === calendar.create( one ).day + 1
5524 }
5525
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 )
5529 }
5530
5531 return false
5532}
5533
5534
5535/**
5536 * Flip the “enabled” state.
5537 */
5538DatePicker.prototype.flipEnable = function(val) {
5539 var itemObject = this.item
5540 itemObject.enable = val || (itemObject.enable == -1 ? 1 : -1)
5541}
5542
5543
5544/**
5545 * Mark a collection of dates as “disabled”.
5546 */
5547DatePicker.prototype.deactivate = function( type, datesToDisable ) {
5548
5549 var calendar = this,
5550 disabledItems = calendar.item.disable.slice(0)
5551
5552
5553 // If we’re flipping, that’s all we need to do.
5554 if ( datesToDisable == 'flip' ) {
5555 calendar.flipEnable()
5556 }
5557
5558 else if ( datesToDisable === false ) {
5559 calendar.flipEnable(1)
5560 disabledItems = []
5561 }
5562
5563 else if ( datesToDisable === true ) {
5564 calendar.flipEnable(-1)
5565 disabledItems = []
5566 }
5567
5568 // Otherwise go through the dates to disable.
5569 else {
5570
5571 datesToDisable.map(function( unitToDisable ) {
5572
5573 var matchFound
5574
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] ) ) {
5579 matchFound = true
5580 break
5581 }
5582 }
5583
5584 // If nothing was found, add the validated unit to the collection.
5585 if ( !matchFound ) {
5586 if (
5587 _.isInteger( unitToDisable ) ||
5588 _.isDate( unitToDisable ) ||
5589 $.isArray( unitToDisable ) ||
5590 ( $.isPlainObject( unitToDisable ) && unitToDisable.from && unitToDisable.to )
5591 ) {
5592 disabledItems.push( unitToDisable )
5593 }
5594 }
5595 })
5596 }
5597
5598 // Return the updated collection.
5599 return disabledItems
5600} //DatePicker.prototype.deactivate
5601
5602
5603/**
5604 * Mark a collection of dates as “enabled”.
5605 */
5606DatePicker.prototype.activate = function( type, datesToEnable ) {
5607
5608 var calendar = this,
5609 disabledItems = calendar.item.disable,
5610 disabledItemsCount = disabledItems.length
5611
5612 // If we’re flipping, that’s all we need to do.
5613 if ( datesToEnable == 'flip' ) {
5614 calendar.flipEnable()
5615 }
5616
5617 else if ( datesToEnable === true ) {
5618 calendar.flipEnable(1)
5619 disabledItems = []
5620 }
5621
5622 else if ( datesToEnable === false ) {
5623 calendar.flipEnable(-1)
5624 disabledItems = []
5625 }
5626
5627 // Otherwise go through the disabled dates.
5628 else {
5629
5630 datesToEnable.map(function( unitToEnable ) {
5631
5632 var matchFound,
5633 disabledUnit,
5634 index,
5635 isExactRange
5636
5637 // Go through the disabled items and try to find a match.
5638 for ( index = 0; index < disabledItemsCount; index += 1 ) {
5639
5640 disabledUnit = disabledItems[index]
5641
5642 // When an exact match is found, remove it from the collection.
5643 if ( calendar.isDateExact( disabledUnit, unitToEnable ) ) {
5644 matchFound = disabledItems[index] = null
5645 isExactRange = true
5646 break
5647 }
5648
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
5654 }
5655 else if ( $.isArray( unitToEnable ) ) {
5656 matchFound = unitToEnable
5657 if ( !matchFound[3] ) matchFound.push( 'inverted' )
5658 }
5659 else if ( _.isDate( unitToEnable ) ) {
5660 matchFound = [ unitToEnable.getFullYear(), unitToEnable.getMonth(), unitToEnable.getDate(), 'inverted' ]
5661 }
5662 break
5663 }
5664 }
5665
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
5670 break
5671 }
5672 }
5673
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
5679 break
5680 }
5681 }
5682
5683 // If something is still matched, add it into the collection.
5684 if ( matchFound ) {
5685 disabledItems.push( matchFound )
5686 }
5687 })
5688 }
5689
5690 // Return the updated collection.
5691 return disabledItems.filter(function( val ) { return val != null })
5692} //DatePicker.prototype.activate
5693
5694
5695/**
5696 * Create a string for the nodes in the picker.
5697 */
5698DatePicker.prototype.nodes = function( isOpen ) {
5699
5700 var
5701 calendar = this,
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,
5711
5712
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 ) {
5716
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() )
5721 }
5722
5723 // Create and return the table head group.
5724 return _.node(
5725 'thead',
5726 _.node(
5727 'tr',
5728 _.group({
5729 min: 0,
5730 max: DAYS_IN_WEEK - 1,
5731 i: 1,
5732 node: 'th',
5733 item: function( counter ) {
5734 return [
5735 collection[ counter ],
5736 settings.klass.weekdays,
5737 'scope=col title="' + fullCollection[ counter ] + '"'
5738 ]
5739 }
5740 })
5741 )
5742 ) //endreturn
5743
5744 // Materialize modified
5745 })( ( settings.showWeekdaysFull ? settings.weekdaysFull : settings.weekdaysLetter ).slice( 0 ), settings.weekdaysFull.slice( 0 ) ), //tableHead
5746
5747
5748 // Create the nav for next/prev month.
5749 createMonthNav = function( next ) {
5750
5751 // Otherwise, return the created month tag.
5752 return _.node(
5753 'div',
5754 ' ',
5755 settings.klass[ 'nav' + ( next ? 'Next' : 'Prev' ) ] + (
5756
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 : ''
5761 ),
5762 'data-nav=' + ( next || -1 ) + ' ' +
5763 _.ariaAttr({
5764 role: 'button',
5765 controls: calendar.$node[0].id + '_table'
5766 }) + ' ' +
5767 'title="' + (next ? settings.labelMonthNext : settings.labelMonthPrev ) + '"'
5768 ) //endreturn
5769 }, //createMonthNav
5770
5771
5772 // Create the month label.
5773 //Materialize modified
5774 createMonthLabel = function(override) {
5775
5776 var monthsCollection = settings.showMonthsShort ? settings.monthsShort : settings.monthsFull
5777
5778 // Materialize modified
5779 if (override == "short_months") {
5780 monthsCollection = settings.monthsShort;
5781 }
5782
5783 // If there are months to select, add a dropdown menu.
5784 if ( settings.selectMonths && override == undefined) {
5785
5786 return _.node( 'select',
5787 _.group({
5788 min: 0,
5789 max: 11,
5790 i: 1,
5791 node: 'option',
5792 item: function( loopedMonth ) {
5793
5794 return [
5795
5796 // The looped month and no classes.
5797 monthsCollection[ loopedMonth ], 0,
5798
5799 // Set the value and selected index.
5800 'value=' + loopedMonth +
5801 ( viewsetObject.month == loopedMonth ? ' selected' : '' ) +
5802 (
5803 (
5804 ( viewsetObject.year == minLimitObject.year && loopedMonth < minLimitObject.month ) ||
5805 ( viewsetObject.year == maxLimitObject.year && loopedMonth > maxLimitObject.month )
5806 ) ?
5807 ' disabled' : ''
5808 )
5809 ]
5810 }
5811 }),
5812 settings.klass.selectMonth + ' browser-default',
5813 ( isOpen ? '' : 'disabled' ) + ' ' +
5814 _.ariaAttr({ controls: calendar.$node[0].id + '_table' }) + ' ' +
5815 'title="' + settings.labelMonthSelect + '"'
5816 )
5817 }
5818
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 ] );
5824
5825 // If there's a need for a month selector
5826 return _.node( 'div', monthsCollection[ viewsetObject.month ], settings.klass.month )
5827 }, //createMonthLabel
5828
5829
5830 // Create the year label.
5831 // Materialize modified
5832 createYearLabel = function(override) {
5833
5834 var focusedYear = viewsetObject.year,
5835
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 )
5839
5840 // If there are years to select, add a dropdown menu.
5841 if ( numberYears ) {
5842
5843 var
5844 minYear = minLimitObject.year,
5845 maxYear = maxLimitObject.year,
5846 lowestYear = focusedYear - numberYears,
5847 highestYear = focusedYear + numberYears
5848
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
5854 }
5855
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 ) {
5860
5861 var availableYears = lowestYear - minYear,
5862 neededYears = highestYear - maxYear
5863
5864 lowestYear -= availableYears > neededYears ? neededYears : availableYears
5865 highestYear = maxYear
5866 }
5867
5868 if ( settings.selectYears && override == undefined ) {
5869 return _.node( 'select',
5870 _.group({
5871 min: lowestYear,
5872 max: highestYear,
5873 i: 1,
5874 node: 'option',
5875 item: function( loopedYear ) {
5876 return [
5877
5878 // The looped year and no classes.
5879 loopedYear, 0,
5880
5881 // Set the value and selected index.
5882 'value=' + loopedYear + ( focusedYear == loopedYear ? ' selected' : '' )
5883 ]
5884 }
5885 }),
5886 settings.klass.selectYear + ' browser-default',
5887 ( isOpen ? '' : 'disabled' ) + ' ' + _.ariaAttr({ controls: calendar.$node[0].id + '_table' }) + ' ' +
5888 'title="' + settings.labelYearSelect + '"'
5889 )
5890 }
5891 }
5892
5893 // Materialize modified
5894 if (override == "raw")
5895 return _.node( 'div', focusedYear )
5896
5897 // Otherwise just return the year focused
5898 return _.node( 'div', focusedYear, settings.klass.year )
5899 } //createYearLabel
5900
5901
5902 // Materialize modified
5903 createDayLabel = function() {
5904 if (selectedObject != null)
5905 return _.node( 'div', selectedObject.date)
5906 else return _.node( 'div', nowObject.date)
5907 }
5908 createWeekdayLabel = function() {
5909 var display_day;
5910
5911 if (selectedObject != null)
5912 display_day = selectedObject.day;
5913 else
5914 display_day = nowObject.day;
5915 var weekday = settings.weekdaysFull[ display_day ]
5916 return weekday
5917 }
5918
5919
5920 // Create and return the entire calendar.
5921return _.node(
5922 // Date presentation View
5923 'div',
5924 _.node(
5925 'div',
5926 createWeekdayLabel(),
5927 "picker__weekday-display"
5928 )+
5929 _.node(
5930 // Div for short Month
5931 'div',
5932 createMonthLabel("short_months"),
5933 settings.klass.month_display
5934 )+
5935 _.node(
5936 // Div for Day
5937 'div',
5938 createDayLabel() ,
5939 settings.klass.day_display
5940 )+
5941 _.node(
5942 // Div for Year
5943 'div',
5944 createYearLabel("raw") ,
5945 settings.klass.year_display
5946 ),
5947 settings.klass.date_display
5948 )+
5949 // Calendar container
5950 _.node('div',
5951 _.node('div',
5952 ( settings.selectYears ? createMonthLabel() + createYearLabel() : createMonthLabel() + createYearLabel() ) +
5953 createMonthNav() + createMonthNav( 1 ),
5954 settings.klass.header
5955 ) + _.node(
5956 'table',
5957 tableHead +
5958 _.node(
5959 'tbody',
5960 _.group({
5961 min: 0,
5962 max: WEEKS_IN_CALENDAR - 1,
5963 i: 1,
5964 node: 'tr',
5965 item: function( rowCounter ) {
5966
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
5969
5970 return [
5971 _.group({
5972 min: DAYS_IN_WEEK * rowCounter - viewsetObject.day + shiftDateBy + 1, // Add 1 for weekday 0index
5973 max: function() {
5974 return this.min + DAYS_IN_WEEK - 1
5975 },
5976 i: 1,
5977 node: 'td',
5978 item: function( targetDate ) {
5979
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 ) ])
5982
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 ] )
5987
5988 return [
5989 _.node(
5990 'div',
5991 targetDate.date,
5992 (function( klasses ) {
5993
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 )
5996
5997 // Add the `today` class if needed.
5998 if ( nowObject.pick == targetDate.pick ) {
5999 klasses.push( settings.klass.now )
6000 }
6001
6002 // Add the `selected` class if something's selected and the time matches.
6003 if ( isSelected ) {
6004 klasses.push( settings.klass.selected )
6005 }
6006
6007 // Add the `highlighted` class if something's highlighted and the time matches.
6008 if ( isHighlighted ) {
6009 klasses.push( settings.klass.highlighted )
6010 }
6011
6012 // Add the `disabled` class if something's disabled and the object matches.
6013 if ( isDisabled ) {
6014 klasses.push( settings.klass.disabled )
6015 }
6016
6017 return klasses.join( ' ' )
6018 })([ settings.klass.day ]),
6019 'data-pick=' + targetDate.pick + ' ' + _.ariaAttr({
6020 role: 'gridcell',
6021 label: formattedDate,
6022 selected: isSelected && calendar.$node.val() === formattedDate ? true : null,
6023 activedescendant: isHighlighted ? true : null,
6024 disabled: isDisabled ? true : null
6025 })
6026 ),
6027 '',
6028 _.ariaAttr({ role: 'presentation' })
6029 ] //endreturn
6030 }
6031 })
6032 ] //endreturn
6033 }
6034 })
6035 ),
6036 settings.klass.table,
6037 'id="' + calendar.$node[0].id + '_table' + '" ' + _.ariaAttr({
6038 role: 'grid',
6039 controls: calendar.$node[0].id,
6040 readonly: true
6041 })
6042 )
6043 , settings.klass.calendar_container) // end calendar
6044
6045 +
6046
6047 // * For Firefox forms to submit, make sure to set the buttons’ `type` attributes as “button”.
6048 _.node(
6049 'div',
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
6063 ) //endreturn
6064} //DatePicker.prototype.nodes
6065
6066
6067
6068
6069/**
6070 * The date picker defaults.
6071 */
6072DatePicker.defaults = (function( prefix ) {
6073
6074 return {
6075
6076 // The title label to use for the month nav buttons
6077 labelMonthNext: 'Next month',
6078 labelMonthPrev: 'Previous month',
6079
6080 // The title label to use for the dropdown selectors
6081 labelMonthSelect: 'Select a month',
6082 labelYearSelect: 'Select a year',
6083
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' ],
6089
6090 // Materialize modified
6091 weekdaysLetter: [ 'S', 'M', 'T', 'W', 'T', 'F', 'S' ],
6092
6093 // Today and clear
6094 today: 'Today',
6095 clear: 'Clear',
6096 close: 'Close',
6097
6098 // The format to show on the `input` element
6099 format: 'd mmmm, yyyy',
6100
6101 // Classes
6102 klass: {
6103
6104 table: prefix + 'table',
6105
6106 header: prefix + 'header',
6107
6108
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',
6115 // end
6116
6117
6118
6119 navPrev: prefix + 'nav--prev',
6120 navNext: prefix + 'nav--next',
6121 navDisabled: prefix + 'nav--disabled',
6122
6123 month: prefix + 'month',
6124 year: prefix + 'year',
6125
6126 selectMonth: prefix + 'select--month',
6127 selectYear: prefix + 'select--year',
6128
6129 weekdays: prefix + 'weekday',
6130
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',
6138
6139 footer: prefix + 'footer',
6140
6141 buttonClear: prefix + 'button--clear',
6142 buttonToday: prefix + 'button--today',
6143 buttonClose: prefix + 'button--close'
6144 }
6145 }
6146})( Picker.klasses().picker + '__' )
6147
6148
6149
6150
6151
6152/**
6153 * Extend the picker to add the date picker.
6154 */
6155Picker.extend( 'pickadate', DatePicker )
6156
6157
6158}));
6159
6160
6161;(function ($) {
6162
6163 $.fn.characterCounter = function(){
6164 return this.each(function(){
6165
6166 var itHasLengthAttribute = $(this).attr('length') !== undefined;
6167
6168 if(itHasLengthAttribute){
6169 $(this).on('input', updateCounter);
6170 $(this).on('focus', updateCounter);
6171 $(this).on('blur', removeCounterElement);
6172
6173 addCounterElement($(this));
6174 }
6175
6176 });
6177 };
6178
6179 function updateCounter(){
6180 var maxLength = +$(this).attr('length'),
6181 actualLength = +$(this).val().length,
6182 isValidLength = actualLength <= maxLength;
6183
6184 $(this).parent().find('span[class="character-counter"]')
6185 .html( actualLength + '/' + maxLength);
6186
6187 addInputStyle(isValidLength, $(this));
6188 }
6189
6190 function addCounterElement($input){
6191 var $counterElement = $('<span/>')
6192 .addClass('character-counter')
6193 .css('float','right')
6194 .css('font-size','12px')
6195 .css('height', 1);
6196
6197 $input.parent().append($counterElement);
6198 }
6199
6200 function removeCounterElement(){
6201 $(this).parent().find('span[class="character-counter"]').html('');
6202 }
6203
6204 function addInputStyle(isValidLength, $input){
6205 var inputHasInvalidClass = $input.hasClass('invalid');
6206 if (isValidLength && inputHasInvalidClass) {
6207 $input.removeClass('invalid');
6208 }
6209 else if(!isValidLength && !inputHasInvalidClass){
6210 $input.removeClass('valid');
6211 $input.addClass('invalid');
6212 }
6213 }
6214
6215 $(document).ready(function(){
6216 $('input, textarea').characterCounter();
6217 });
6218
6219}( jQuery ));