2 * Foundation Responsive Library
3 * http://foundation.zurb.com
5 * Free to use under the MIT license.
6 * http://www.opensource.org/licenses/mit-license.php
9 (function ($, window
, document
, undefined) {
12 var header_helpers = function (class_array
) {
13 var i
= class_array
.length
;
17 if (head
.has('.' + class_array
[i
]).length
=== 0) {
18 head
.append('<meta class="' + class_array
[i
] + '" />');
24 'foundation-mq-small',
25 'foundation-mq-small-only',
26 'foundation-mq-medium',
27 'foundation-mq-medium-only',
28 'foundation-mq-large',
29 'foundation-mq-large-only',
30 'foundation-mq-xlarge',
31 'foundation-mq-xlarge-only',
32 'foundation-mq-xxlarge',
33 'foundation-data-attribute-namespace']);
35 // Enable FastClick if present
38 if (typeof FastClick
!== 'undefined') {
39 // Don't attach to body if undefined
40 if (typeof document
.body
!== 'undefined') {
41 FastClick
.attach(document
.body
);
46 // private Fast Selector wrapper,
47 // returns jQuery object. Only use where
48 // getElementById is not available.
49 var S = function (selector
, context
) {
50 if (typeof selector
=== 'string') {
55 if (!cont
) return context
;
59 return $(cont
.querySelectorAll(selector
));
62 return $(document
.querySelectorAll(selector
));
65 return $(selector
, context
);
68 // Namespace functions.
70 var attr_name = function (init
) {
72 if (!init
) arr
.push('data');
73 if (this.namespace.length
> 0) arr
.push(this.namespace);
79 var add_namespace = function (str
) {
80 var parts
= str
.split('-'),
88 if (this.namespace.length
> 0) {
89 arr
.push(this.namespace, parts
[i
]);
96 return arr
.reverse().join('-');
99 // Event binding and data-options updating.
101 var bindings = function (method
, options
) {
103 should_bind_events
= !S(this).data(this.attr_name(true));
105 if (S(this.scope
).is('[' + this.attr_name() + ']')) {
106 S(this.scope
).data(this.attr_name(true) + '-init', $.extend({}, this.settings
, (options
|| method
), this.data_options(S(this.scope
))));
108 if (should_bind_events
) {
109 this.events(this.scope
);
113 S('[' + this.attr_name() + ']', this.scope
).each(function () {
114 var should_bind_events
= !S(this).data(self
.attr_name(true) + '-init');
115 S(this).data(self
.attr_name(true) + '-init', $.extend({}, self
.settings
, (options
|| method
), self
.data_options(S(this))));
117 if (should_bind_events
) {
122 // # Patch to fix #5043 to move this *after* the if/else clause in order for Backbone and similar frameworks to have improved control over event binding and data-options updating.
123 if (typeof method
=== 'string') {
124 return this[method
].call(this, options
);
129 var single_image_loaded = function (image
, callback
) {
134 function bindLoad() {
135 this.one('load', loaded
);
137 if (/MSIE (\d+\.\d+);/.test(navigator
.userAgent
)) {
138 var src
= this.attr('src'),
139 param
= src
.match(/\?/) ? '&' : '?';
141 param
+= 'random=' + (new Date()).getTime();
142 this.attr('src', src
+ param
);
146 if (!image
.attr('src')) {
151 if (image
[0].complete
|| image
[0].readyState
=== 4) {
154 bindLoad
.call(image
);
159 https://github.com/paulirish/matchMedia.js
162 window
.matchMedia
= window
.matchMedia
|| (function (doc
) {
167 docElem
= doc
.documentElement
,
168 refNode
= docElem
.firstElementChild
|| docElem
.firstChild
,
169 // fakeBody required for <FF4 when executed in <head>
170 fakeBody
= doc
.createElement('body'),
171 div
= doc
.createElement('div');
173 div
.id
= 'mq-test-1';
174 div
.style
.cssText
= 'position:absolute;top:-100em';
175 fakeBody
.style
.background
= 'none';
176 fakeBody
.appendChild(div
);
178 return function (q
) {
180 div
.innerHTML
= '­<style media="' + q
+ '"> #mq-test-1 { width: 42px; }</style>';
182 docElem
.insertBefore(fakeBody
, refNode
);
183 bool
= div
.offsetWidth
=== 42;
184 docElem
.removeChild(fakeBody
);
196 * jquery.requestAnimationFrame
197 * https://github.com/gnarf37/jquery-requestAnimationFrame
198 * Requires jQuery 1.8+
200 * Copyright (c) 2012 Corey Frang
201 * Licensed under the MIT license.
206 // requestAnimationFrame polyfill adapted from Erik Möller
207 // fixes from Paul Irish and Tino Zijdel
208 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
209 // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
213 vendors
= ['webkit', 'moz'],
214 requestAnimationFrame
= window
.requestAnimationFrame
,
215 cancelAnimationFrame
= window
.cancelAnimationFrame
,
216 jqueryFxAvailable
= 'undefined' !== typeof jQuery
.fx
;
218 for (; lastTime
< vendors
.length
&& !requestAnimationFrame
; lastTime
++) {
219 requestAnimationFrame
= window
[vendors
[lastTime
] + 'RequestAnimationFrame'];
220 cancelAnimationFrame
= cancelAnimationFrame
||
221 window
[vendors
[lastTime
] + 'CancelAnimationFrame'] ||
222 window
[vendors
[lastTime
] + 'CancelRequestAnimationFrame'];
227 requestAnimationFrame(raf
);
229 if (jqueryFxAvailable
) {
235 if (requestAnimationFrame
) {
237 window
.requestAnimationFrame
= requestAnimationFrame
;
238 window
.cancelAnimationFrame
= cancelAnimationFrame
;
240 if (jqueryFxAvailable
) {
241 jQuery
.fx
.timer = function (timer
) {
242 if (timer() && jQuery
.timers
.push(timer
) && !animating
) {
248 jQuery
.fx
.stop = function () {
254 window
.requestAnimationFrame = function (callback
) {
255 var currTime
= new Date().getTime(),
256 timeToCall
= Math
.max(0, 16 - (currTime
- lastTime
)),
257 id
= window
.setTimeout(function () {
258 callback(currTime
+ timeToCall
);
260 lastTime
= currTime
+ timeToCall
;
264 window
.cancelAnimationFrame = function (id
) {
273 function removeQuotes(string
) {
274 if (typeof string
=== 'string' || string
instanceof String
) {
275 string
= string
.replace(/^['\\/"]+|(;\s?})+|['\\/"]+$/g, '');
281 window
.Foundation
= {
287 'small': S('.foundation-mq-small').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''),
288 'small-only': S('.foundation-mq-small-only').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''),
289 'medium': S('.foundation-mq-medium').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''),
290 'medium-only': S('.foundation-mq-medium-only').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''),
291 'large': S('.foundation-mq-large').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''),
292 'large-only': S('.foundation-mq-large-only').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''),
293 'xlarge': S('.foundation-mq-xlarge').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''),
294 'xlarge-only': S('.foundation-mq-xlarge-only').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, ''),
295 'xxlarge': S('.foundation-mq-xxlarge').css('font-family').replace(/^[\/\\'"]+|(;\s?})+|[\/\\'"]+$/g, '')
298 stylesheet
: $('<style></style>').appendTo('head')[0].sheet
,
304 init: function (scope
, libraries
, method
, options
, response
) {
305 var args
= [scope
, method
, options
, response
],
309 this.rtl
= /rtl/i.test(S('html').attr('dir'));
311 // set foundation global scope
312 this.scope
= scope
|| this.scope
;
314 this.set_namespace();
316 if (libraries
&& typeof libraries
=== 'string' && !/reflow/i.test(libraries
)) {
317 if (this.libs
.hasOwnProperty(libraries
)) {
318 responses
.push(this.init_lib(libraries
, args
));
321 for (var lib
in this.libs
) {
322 responses
.push(this.init_lib(lib
, libraries
));
326 S(window
).load(function () {
328 .trigger('resize.fndtn.clearing')
329 .trigger('resize.fndtn.dropdown')
330 .trigger('resize.fndtn.equalizer')
331 .trigger('resize.fndtn.interchange')
332 .trigger('resize.fndtn.joyride')
333 .trigger('resize.fndtn.magellan')
334 .trigger('resize.fndtn.topbar')
335 .trigger('resize.fndtn.slider');
341 init_lib: function (lib
, args
) {
342 if (this.libs
.hasOwnProperty(lib
)) {
343 this.patch(this.libs
[lib
]);
345 if (args
&& args
.hasOwnProperty(lib
)) {
346 if (typeof this.libs
[lib
].settings
!== 'undefined') {
347 $.extend(true, this.libs
[lib
].settings
, args
[lib
]);
349 else if (typeof this.libs
[lib
].defaults
!== 'undefined') {
350 $.extend(true, this.libs
[lib
].defaults
, args
[lib
]);
352 return this.libs
[lib
].init
.apply(this.libs
[lib
], [this.scope
, args
[lib
]]);
355 args
= args
instanceof Array
? args
: new Array(args
);
356 return this.libs
[lib
].init
.apply(this.libs
[lib
], args
);
363 patch: function (lib
) {
364 lib
.scope
= this.scope
;
365 lib
.namespace = this.global
.namespace;
367 lib
['data_options'] = this.utils
.data_options
;
368 lib
['attr_name'] = attr_name
;
369 lib
['add_namespace'] = add_namespace
;
370 lib
['bindings'] = bindings
;
371 lib
['S'] = this.utils
.S
;
374 inherit: function (scope
, methods
) {
375 var methods_arr
= methods
.split(' '),
376 i
= methods_arr
.length
;
379 if (this.utils
.hasOwnProperty(methods_arr
[i
])) {
380 scope
[methods_arr
[i
]] = this.utils
[methods_arr
[i
]];
385 set_namespace: function () {
388 // Don't bother reading the namespace out of the meta tag
389 // if the namespace has been set globally in javascript
392 // Foundation.global.namespace = 'my-namespace';
393 // or make it an empty string:
394 // Foundation.global.namespace = '';
398 // If the namespace has not been set (is undefined), try to read it out of the meta element.
399 // Otherwise use the globally defined namespace, even if it's empty ('')
400 var namespace = ( this.global
.namespace === undefined ) ? $('.foundation-data-attribute-namespace').css('font-family') : this.global
.namespace;
402 // Finally, if the namsepace is either undefined or false, set it to an empty string.
403 // Otherwise use the namespace value.
404 this.global
.namespace = ( namespace === undefined || /false/i.test(namespace) ) ? '' : namespace;
409 // methods that can be inherited in libraries
413 // Fast Selector wrapper returns jQuery object. Only use where getElementById
417 // Selector (String): CSS selector describing the element(s) to be
418 // returned as a jQuery object.
420 // Scope (String): CSS selector describing the area to be searched. Default
424 // Element (jQuery Object): jQuery object containing elements matching the
425 // selector within the scope.
429 // Executes a function a max of once every n milliseconds
432 // Func (Function): Function to be throttled.
434 // Delay (Integer): Function execution threshold in milliseconds.
437 // Lazy_function (Function): Function with throttling applied.
438 throttle: function (func
, delay
) {
442 var context
= this, args
= arguments
;
445 timer
= setTimeout(function () {
446 func
.apply(context
, args
);
454 // Executes a function when it stops being invoked for n seconds
455 // Modified version of _.debounce() http://underscorejs.org
458 // Func (Function): Function to be debounced.
460 // Delay (Integer): Function execution threshold in milliseconds.
462 // Immediate (Bool): Whether the function should be called at the beginning
463 // of the delay instead of the end. Default is false.
466 // Lazy_function (Function): Function with debouncing applied.
467 debounce: function (func
, delay
, immediate
) {
470 var context
= this, args
= arguments
;
471 var later = function () {
473 if (!immediate
) result
= func
.apply(context
, args
);
475 var callNow
= immediate
&& !timeout
;
476 clearTimeout(timeout
);
477 timeout
= setTimeout(later
, delay
);
478 if (callNow
) result
= func
.apply(context
, args
);
484 // Parses data-options attribute
487 // El (jQuery Object): Element to be parsed.
490 // Options (Javascript Object): Contents of the element's data-options
492 data_options: function (el
, data_attr_name
) {
493 data_attr_name
= data_attr_name
|| 'options';
494 var opts
= {}, ii
, p
, opts_arr
,
495 data_options = function (el
) {
496 var namespace = Foundation
.global
.namespace;
498 if (namespace.length
> 0) {
499 return el
.data(namespace + '-' + data_attr_name
);
502 return el
.data(data_attr_name
);
505 var cached_options
= data_options(el
);
507 if (typeof cached_options
=== 'object') {
508 return cached_options
;
511 opts_arr
= (cached_options
|| ':').split(';');
512 ii
= opts_arr
.length
;
514 function isNumber(o
) {
515 return !isNaN(o
- 0) && o
!== null && o
!== '' && o
!== false && o
!== true;
519 if (typeof str
=== 'string') return $.trim(str
);
524 p
= opts_arr
[ii
].split(':');
525 p
= [p
[0], p
.slice(1).join(':')];
527 if (/true/i.test(p
[1])) p
[1] = true;
528 if (/false/i.test(p
[1])) p
[1] = false;
529 if (isNumber(p
[1])) {
530 if (p
[1].indexOf('.') === -1) {
531 p
[1] = parseInt(p
[1], 10);
533 p
[1] = parseFloat(p
[1]);
537 if (p
.length
=== 2 && p
[0].length
> 0) {
538 opts
[trim(p
[0])] = trim(p
[1]);
546 // Adds JS-recognizable media queries
549 // Media (String): Key string for the media query to be stored as in
550 // Foundation.media_queries
552 // Class (String): Class name for the generated <meta> tag
553 register_media: function (media
, media_class
) {
554 if (Foundation
.media_queries
[media
] === undefined) {
555 $('head').append('<meta class="' + media_class
+ '"/>');
556 Foundation
.media_queries
[media
] = removeQuotes($('.' + media_class
).css('font-family'));
561 // Add custom CSS within a JS-defined media query
564 // Rule (String): CSS rule to be appended to the document.
566 // Media (String): Optional media query string for the CSS rule to be
568 add_custom_rule: function (rule
, media
) {
569 if (media
=== undefined && Foundation
.stylesheet
) {
570 Foundation
.stylesheet
.insertRule(rule
, Foundation
.stylesheet
.cssRules
.length
);
572 var query
= Foundation
.media_queries
[media
];
574 if (query
!== undefined) {
575 Foundation
.stylesheet
.insertRule('@media ' +
576 Foundation
.media_queries
[media
] + '{ ' + rule
+ ' }');
582 // Performs a callback function when an image is fully loaded
585 // Image (jQuery Object): Image(s) to check if loaded.
587 // Callback (Function): Function to execute when image is fully loaded.
588 image_loaded: function (images
, callback
) {
590 unloaded
= images
.length
;
592 if (unloaded
=== 0) {
596 images
.each(function () {
597 single_image_loaded(self
.S(this), function () {
599 if (unloaded
=== 0) {
607 // Returns a random, alphanumeric string
610 // Length (Integer): Length of string to be generated. Defaults to random
614 // Rand (String): Pseudo-random, alphanumeric string.
615 random_str: function () {
616 if (!this.fidx
) this.fidx
= 0;
617 this.prefix
= this.prefix
|| [(this.name
|| 'F'), (+new Date
).toString(36)].join('-');
619 return this.prefix
+ (this.fidx
++).toString(36);
623 // Helper for window.matchMedia
626 // mq (String): Media query
629 // (Boolean): Whether the media query passes or not
630 match: function (mq
) {
631 return window
.matchMedia(mq
).matches
;
635 // Helpers for checking Foundation default media queries with JS
638 // (Boolean): Whether the media query passes or not
640 is_small_up: function () {
641 return this.match(Foundation
.media_queries
.small
);
644 is_medium_up: function () {
645 return this.match(Foundation
.media_queries
.medium
);
648 is_large_up: function () {
649 return this.match(Foundation
.media_queries
.large
);
652 is_xlarge_up: function () {
653 return this.match(Foundation
.media_queries
.xlarge
);
656 is_xxlarge_up: function () {
657 return this.match(Foundation
.media_queries
.xxlarge
);
660 is_small_only: function () {
661 return !this.is_medium_up() && !this.is_large_up() && !this.is_xlarge_up() && !this.is_xxlarge_up();
664 is_medium_only: function () {
665 return this.is_medium_up() && !this.is_large_up() && !this.is_xlarge_up() && !this.is_xxlarge_up();
668 is_large_only: function () {
669 return this.is_medium_up() && this.is_large_up() && !this.is_xlarge_up() && !this.is_xxlarge_up();
672 is_xlarge_only: function () {
673 return this.is_medium_up() && this.is_large_up() && this.is_xlarge_up() && !this.is_xxlarge_up();
676 is_xxlarge_only: function () {
677 return this.is_medium_up() && this.is_large_up() && this.is_xlarge_up() && this.is_xxlarge_up();
682 $.fn
.foundation = function () {
683 var args
= Array
.prototype.slice
.call(arguments
, 0);
685 return this.each(function () {
686 Foundation
.init
.apply(Foundation
, [this].concat(args
));
691 }(jQuery
, window
, window
.document
));
693 (function ($, window
, document
, undefined) {
696 Foundation
.libs
.slider
= {
707 display_selector
: '',
709 trigger_input_change
: false,
710 on_change: function () {
716 init: function (scope
, method
, options
) {
717 Foundation
.inherit(this, 'throttle');
718 this.bindings(method
, options
);
722 events: function () {
727 .on('mousedown.fndtn.slider touchstart.fndtn.slider pointerdown.fndtn.slider',
728 '[' + self
.attr_name() + ']:not(.disabled, [disabled]) .range-slider-handle', function (e
) {
729 if (!self
.cache
.active
) {
731 self
.set_active_slider($(e
.target
));
734 .on('mousemove.fndtn.slider touchmove.fndtn.slider pointermove.fndtn.slider', function (e
) {
735 if (!!self
.cache
.active
) {
737 if ($.data(self
.cache
.active
[0], 'settings').vertical
) {
738 var scroll_offset
= 0;
740 scroll_offset
= window
.scrollY
;
742 self
.calculate_position(self
.cache
.active
, self
.get_cursor_position(e
, 'y') + scroll_offset
);
744 self
.calculate_position(self
.cache
.active
, self
.get_cursor_position(e
, 'x'));
748 .on('mouseup.fndtn.slider touchend.fndtn.slider pointerup.fndtn.slider', function (e
) {
749 self
.remove_active_slider();
751 .on('change.fndtn.slider', function (e
) {
752 self
.settings
.on_change();
756 .on('resize.fndtn.slider', self
.throttle(function (e
) {
761 get_cursor_position: function (e
, xy
) {
762 var pageXY
= 'page' + xy
.toUpperCase(),
763 clientXY
= 'client' + xy
.toUpperCase(),
766 if (typeof e
[pageXY
] !== 'undefined') {
767 position
= e
[pageXY
];
769 else if (typeof e
.originalEvent
[clientXY
] !== 'undefined') {
770 position
= e
.originalEvent
[clientXY
];
772 else if (e
.originalEvent
.touches
&& e
.originalEvent
.touches
[0] && typeof e
.originalEvent
.touches
[0][clientXY
] !== 'undefined') {
773 position
= e
.originalEvent
.touches
[0][clientXY
];
775 else if (e
.currentPoint
&& typeof e
.currentPoint
[xy
] !== 'undefined') {
776 position
= e
.currentPoint
[xy
];
781 set_active_slider: function ($handle
) {
782 this.cache
.active
= $handle
;
785 remove_active_slider: function () {
786 this.cache
.active
= null;
789 calculate_position: function ($handle
, cursor_x
) {
791 settings
= $.data($handle
[0], 'settings'),
792 handle_l
= $.data($handle
[0], 'handle_l'),
793 handle_o
= $.data($handle
[0], 'handle_o'),
794 bar_l
= $.data($handle
[0], 'bar_l'),
795 bar_o
= $.data($handle
[0], 'bar_o');
797 requestAnimationFrame(function () {
800 if (Foundation
.rtl
&& !settings
.vertical
) {
801 pct
= self
.limit_to(((bar_o
+ bar_l
- cursor_x
) / bar_l
), 0, 1);
803 pct
= self
.limit_to(((cursor_x
- bar_o
) / bar_l
), 0, 1);
806 pct
= settings
.vertical
? 1 - pct
: pct
;
808 var norm
= self
.normalized_value(pct
, settings
.start
, settings
.end
, settings
.step
, settings
.precision
);
810 self
.set_ui($handle
, norm
);
814 set_ui: function ($handle
, value
) {
815 var settings
= $.data($handle
[0], 'settings'),
816 handle_l
= $.data($handle
[0], 'handle_l'),
817 bar_l
= $.data($handle
[0], 'bar_l'),
818 norm_pct
= this.normalized_percentage(value
, settings
.start
, settings
.end
),
819 handle_offset
= norm_pct
* (bar_l
- handle_l
) - 1,
820 progress_bar_length
= norm_pct
* 100,
821 $handle_parent
= $handle
.parent(),
822 $hidden_inputs
= $handle
.parent().children('input[type=hidden]');
824 if (Foundation
.rtl
&& !settings
.vertical
) {
825 handle_offset
= -handle_offset
;
828 handle_offset
= settings
.vertical
? -handle_offset
+ bar_l
- handle_l
+ 1 : handle_offset
;
829 this.set_translate($handle
, handle_offset
, settings
.vertical
);
831 if (settings
.vertical
) {
832 $handle
.siblings('.range-slider-active-segment').css('height', progress_bar_length
+ '%');
834 $handle
.siblings('.range-slider-active-segment').css('width', progress_bar_length
+ '%');
837 $handle_parent
.attr(this.attr_name(), value
).trigger('change').trigger('change.fndtn.slider');
839 $hidden_inputs
.val(value
);
840 if (settings
.trigger_input_change
) {
841 $hidden_inputs
.trigger('change');
844 if (!$handle
[0].hasAttribute('aria-valuemin')) {
846 'aria-valuemin': settings
.start
,
847 'aria-valuemax': settings
.end
850 $handle
.attr('aria-valuenow', value
);
852 if (settings
.display_selector
!= '') {
853 $(settings
.display_selector
).each(function () {
854 if (this.hasOwnProperty('value')) {
864 normalized_percentage: function (val
, start
, end
) {
865 return Math
.min(1, (val
- start
) / (end
- start
));
868 normalized_value: function (val
, start
, end
, step
, precision
) {
869 var range
= end
- start
,
871 mod
= (point
- (point
% step
)) / step
,
873 round
= ( rem
>= step
* 0.5 ? step
: 0);
874 return ((mod
* step
+ round
) + start
).toFixed(precision
);
877 set_translate: function (ele
, offset
, vertical
) {
880 .css('-webkit-transform', 'translateY(' + offset
+ 'px)')
881 .css('-moz-transform', 'translateY(' + offset
+ 'px)')
882 .css('-ms-transform', 'translateY(' + offset
+ 'px)')
883 .css('-o-transform', 'translateY(' + offset
+ 'px)')
884 .css('transform', 'translateY(' + offset
+ 'px)');
887 .css('-webkit-transform', 'translateX(' + offset
+ 'px)')
888 .css('-moz-transform', 'translateX(' + offset
+ 'px)')
889 .css('-ms-transform', 'translateX(' + offset
+ 'px)')
890 .css('-o-transform', 'translateX(' + offset
+ 'px)')
891 .css('transform', 'translateX(' + offset
+ 'px)');
895 limit_to: function (val
, min
, max
) {
896 return Math
.min(Math
.max(val
, min
), max
);
900 initialize_settings: function (handle
) {
901 var settings
= $.extend({}, this.settings
, this.data_options($(handle
).parent())),
902 decimal_places_match_result
;
904 if (settings
.precision
=== null) {
905 decimal_places_match_result
= ('' + settings
.step
).match(/\.([\d]*)/);
906 settings
.precision
= decimal_places_match_result
&& decimal_places_match_result
[1] ? decimal_places_match_result
[1].length
: 0;
909 if (settings
.vertical
) {
910 $.data(handle
, 'bar_o', $(handle
).parent().offset().top
);
911 $.data(handle
, 'bar_l', $(handle
).parent().outerHeight());
912 $.data(handle
, 'handle_o', $(handle
).offset().top
);
913 $.data(handle
, 'handle_l', $(handle
).outerHeight());
915 $.data(handle
, 'bar_o', $(handle
).parent().offset().left
);
916 $.data(handle
, 'bar_l', $(handle
).parent().outerWidth());
917 $.data(handle
, 'handle_o', $(handle
).offset().left
);
918 $.data(handle
, 'handle_l', $(handle
).outerWidth());
921 $.data(handle
, 'bar', $(handle
).parent());
922 $.data(handle
, 'settings', settings
);
925 set_initial_position: function ($ele
) {
926 var settings
= $.data($ele
.children('.range-slider-handle')[0], 'settings'),
927 initial
= ((typeof settings
.initial
== 'number' && !isNaN(settings
.initial
)) ? settings
.initial
: Math
.floor((settings
.end
- settings
.start
) * 0.5 / settings
.step
) * settings
.step
+ settings
.start
),
928 $handle
= $ele
.children('.range-slider-handle');
929 this.set_ui($handle
, initial
);
932 set_value: function (value
) {
934 $('[' + self
.attr_name() + ']', this.scope
).each(function () {
935 $(this).attr(self
.attr_name(), value
);
937 if (!!$(this.scope
).attr(self
.attr_name())) {
938 $(this.scope
).attr(self
.attr_name(), value
);
943 reflow: function () {
945 self
.S('[' + this.attr_name() + ']').each(function () {
946 var handle
= $(this).children('.range-slider-handle')[0],
947 val
= $(this).attr(self
.attr_name());
948 self
.initialize_settings(handle
);
951 self
.set_ui($(handle
), parseFloat(val
));
953 self
.set_initial_position($(this));
959 }(jQuery
, window
, window
.document
));
961 (function ($, window
, document
, undefined) {
964 var Modernizr
= Modernizr
|| false;
966 Foundation
.libs
.joyride
= {
972 expose
: false, // turn on or off the expose feature
973 modal
: true, // Whether to cover page with modal during the tour
974 keyboard
: true, // enable left, right and esc keystrokes
975 tip_location
: 'bottom', // 'top' or 'bottom' in relation to parent
976 nub_position
: 'auto', // override on a per tooltip bases
977 scroll_speed
: 1500, // Page scrolling speed in milliseconds, 0 = no scroll animation
978 scroll_animation
: 'linear', // supports 'swing' and 'linear', extend with jQuery UI.
979 timer
: 0, // 0 = no timer , all other numbers = timer in milliseconds
980 start_timer_on_click
: true, // true or false - true requires clicking the first button start the timer
981 start_offset
: 0, // the index of the tooltip you want to start on (index of the li)
982 next_button
: true, // true or false to control whether a next button is used
983 prev_button
: true, // true or false to control whether a prev button is used
984 tip_animation
: 'fade', // 'pop' or 'fade' in each tip
985 pause_after
: [], // array of indexes where to pause the tour after
986 exposed
: [], // array of expose elements
987 tip_animation_fade_speed
: 300, // when tipAnimation = 'fade' this is speed in milliseconds for the transition
988 cookie_monster
: false, // true or false to control whether cookies are used
989 cookie_name
: 'joyride', // Name the cookie you'll use
990 cookie_domain
: false, // Will this cookie be attached to a domain, ie. '.notableapp.com'
991 cookie_expires
: 365, // set when you would like the cookie to expire.
992 tip_container
: 'body', // Where will the tip be attached
993 abort_on_close
: true, // When true, the close event will not fire any callback
994 tip_location_patterns
: {
996 bottom
: [], // bottom should not need to be repositioned
997 left
: ['right', 'top', 'bottom'],
998 right
: ['left', 'top', 'bottom']
1000 post_ride_callback: function () {
1001 }, // A method to call once the tour closes (canceled or complete)
1002 post_step_callback: function () {
1003 }, // A method to call after each step
1004 pre_step_callback: function () {
1005 }, // A method to call before each step
1006 pre_ride_callback: function () {
1007 }, // A method to call before the tour starts (passed index, tip, and cloned exposed element)
1008 post_expose_callback: function () {
1009 }, // A method to call after an element has been exposed
1010 template
: { // HTML segments for tip layout
1011 link
: '<a href="#close" class="joyride-close-tip">×</a>',
1012 timer
: '<div class="joyride-timer-indicator-wrap"><span class="joyride-timer-indicator"></span></div>',
1013 tip
: '<div class="joyride-tip-guide"><span class="joyride-nub"></span></div>',
1014 wrapper
: '<div class="joyride-content-wrapper"></div>',
1015 button
: '<a href="#" class="small button joyride-next-tip"></a>',
1016 prev_button
: '<a href="#" class="small button joyride-prev-tip"></a>',
1017 modal
: '<div class="joyride-modal-bg"></div>',
1018 expose
: '<div class="joyride-expose-wrapper"></div>',
1019 expose_cover
: '<div class="joyride-expose-cover"></div>'
1021 expose_add_class
: '' // One or more space-separated class names to be added to exposed element
1024 init: function (scope
, method
, options
) {
1025 Foundation
.inherit(this, 'throttle random_str');
1027 this.settings
= this.settings
|| $.extend({}, this.defaults
, (options
|| method
));
1029 this.bindings(method
, options
)
1032 go_next: function () {
1033 if (this.settings
.$li
.next().length
< 1) {
1035 } else if (this.settings
.timer
> 0) {
1036 clearTimeout(this.settings
.automate
);
1046 go_prev: function () {
1047 if (this.settings
.$li
.prev().length
< 1) {
1048 // Do nothing if there are no prev element
1049 } else if (this.settings
.timer
> 0) {
1050 clearTimeout(this.settings
.automate
);
1052 this.show(null, true);
1056 this.show(null, true);
1060 events: function () {
1065 .on('click.fndtn.joyride', '.joyride-next-tip, .joyride-modal-bg', function (e
) {
1069 .on('click.fndtn.joyride', '.joyride-prev-tip', function (e
) {
1074 .on('click.fndtn.joyride', '.joyride-close-tip', function (e
) {
1076 this.end(this.settings
.abort_on_close
);
1079 .on('keyup.fndtn.joyride', function (e
) {
1080 // Don't do anything if keystrokes are disabled
1081 // or if the joyride is not being shown
1082 if (!this.settings
.keyboard
|| !this.settings
.riding
) return;
1085 case 39: // right arrow
1089 case 37: // left arrow
1095 this.end(this.settings
.abort_on_close
);
1101 .on('resize.fndtn.joyride', self
.throttle(function () {
1102 if ($('[' + self
.attr_name() + ']').length
> 0 && self
.settings
.$next_tip
&& self
.settings
.riding
) {
1103 if (self
.settings
.exposed
.length
> 0) {
1104 var $els
= $(self
.settings
.exposed
);
1106 $els
.each(function () {
1107 var $this = $(this);
1108 self
.un_expose($this);
1113 if (self
.is_phone()) {
1116 self
.pos_default(false);
1122 start: function () {
1124 $this = $('[' + this.attr_name() + ']', this.scope
),
1125 integer_settings
= ['timer', 'scrollSpeed', 'startOffset', 'tipAnimationFadeSpeed', 'cookieExpires'],
1126 int_settings_count
= integer_settings
.length
;
1128 if (!$this.length
> 0) return;
1130 if (!this.settings
.init
) this.events();
1132 this.settings
= $this.data(this.attr_name(true) + '-init');
1134 // non configureable settings
1135 this.settings
.$content_el
= $this;
1136 this.settings
.$body
= $(this.settings
.tip_container
);
1137 this.settings
.body_offset
= $(this.settings
.tip_container
).position();
1138 this.settings
.$tip_content
= this.settings
.$content_el
.find('> li');
1139 this.settings
.paused
= false;
1140 this.settings
.attempts
= 0;
1141 this.settings
.riding
= true;
1143 // can we create cookies?
1144 if (typeof $.cookie
!== 'function') {
1145 this.settings
.cookie_monster
= false;
1148 // generate the tips and insert into dom.
1149 if (!this.settings
.cookie_monster
|| this.settings
.cookie_monster
&& !$.cookie(this.settings
.cookie_name
)) {
1150 this.settings
.$tip_content
.each(function (index
) {
1151 var $this = $(this);
1152 this.settings
= $.extend({}, self
.defaults
, self
.data_options($this));
1154 // Make sure that settings parsed from data_options are integers where necessary
1155 var i
= int_settings_count
;
1157 self
.settings
[integer_settings
[i
]] = parseInt(self
.settings
[integer_settings
[i
]], 10);
1159 self
.create({$li
: $this, index
: index
});
1163 if (!this.settings
.start_timer_on_click
&& this.settings
.timer
> 0) {
1173 resume: function () {
1178 tip_template: function (opts
) {
1179 var $blank
, content
;
1181 opts
.tip_class
= opts
.tip_class
|| '';
1183 $blank
= $(this.settings
.template
.tip
).addClass(opts
.tip_class
);
1184 content
= $.trim($(opts
.li
).html()) +
1185 this.prev_button_text(opts
.prev_button_text
, opts
.index
) +
1186 this.button_text(opts
.button_text
) +
1187 this.settings
.template
.link
+
1188 this.timer_instance(opts
.index
);
1190 $blank
.append($(this.settings
.template
.wrapper
));
1191 $blank
.first().attr(this.add_namespace('data-index'), opts
.index
);
1192 $('.joyride-content-wrapper', $blank
).append(content
);
1197 timer_instance: function (index
) {
1200 if ((index
=== 0 && this.settings
.start_timer_on_click
&& this.settings
.timer
> 0) || this.settings
.timer
=== 0) {
1203 txt
= $(this.settings
.template
.timer
)[0].outerHTML
;
1208 button_text: function (txt
) {
1209 if (this.settings
.tip_settings
.next_button
) {
1210 txt
= $.trim(txt
) || 'Next';
1211 txt
= $(this.settings
.template
.button
).append(txt
)[0].outerHTML
;
1218 prev_button_text: function (txt
, idx
) {
1219 if (this.settings
.tip_settings
.prev_button
) {
1220 txt
= $.trim(txt
) || 'Previous';
1222 // Add the disabled class to the button if it's the first element
1224 txt
= $(this.settings
.template
.prev_button
).append(txt
).addClass('disabled')[0].outerHTML
;
1226 txt
= $(this.settings
.template
.prev_button
).append(txt
)[0].outerHTML
;
1233 create: function (opts
) {
1234 this.settings
.tip_settings
= $.extend({}, this.settings
, this.data_options(opts
.$li
));
1235 var buttonText
= opts
.$li
.attr(this.add_namespace('data-button'))
1236 || opts
.$li
.attr(this.add_namespace('data-text')),
1237 prevButtonText
= opts
.$li
.attr(this.add_namespace('data-button-prev'))
1238 || opts
.$li
.attr(this.add_namespace('data-prev-text')),
1239 tipClass
= opts
.$li
.attr('class'),
1240 $tip_content
= $(this.tip_template({
1241 tip_class
: tipClass
,
1243 button_text
: buttonText
,
1244 prev_button_text
: prevButtonText
,
1248 $(this.settings
.tip_container
).append($tip_content
);
1251 show: function (init
, is_prev
) {
1255 if (this.settings
.$li
=== undefined
1256 || ($.inArray(this.settings
.$li
.index(), this.settings
.pause_after
) === -1)) {
1258 // don't go to the next li if the tour was paused
1259 if (this.settings
.paused
) {
1260 this.settings
.paused
= false;
1262 this.set_li(init
, is_prev
);
1265 this.settings
.attempts
= 0;
1267 if (this.settings
.$li
.length
&& this.settings
.$target
.length
> 0) {
1268 if (init
) { //run when we first start
1269 this.settings
.pre_ride_callback(this.settings
.$li
.index(), this.settings
.$next_tip
);
1270 if (this.settings
.modal
) {
1275 this.settings
.pre_step_callback(this.settings
.$li
.index(), this.settings
.$next_tip
);
1277 if (this.settings
.modal
&& this.settings
.expose
) {
1281 this.settings
.tip_settings
= $.extend({}, this.settings
, this.data_options(this.settings
.$li
));
1283 this.settings
.timer
= parseInt(this.settings
.timer
, 10);
1285 this.settings
.tip_settings
.tip_location_pattern
= this.settings
.tip_location_patterns
[this.settings
.tip_settings
.tip_location
];
1287 // scroll and hide bg if not modal
1288 if (!/body/i.test(this.settings
.$target
.selector
)) {
1289 var joyridemodalbg
= $('.joyride-modal-bg');
1290 if (/pop/i.test(this.settings
.tipAnimation
)) {
1291 joyridemodalbg
.hide();
1293 joyridemodalbg
.fadeOut(this.settings
.tipAnimationFadeSpeed
);
1298 if (this.is_phone()) {
1299 this.pos_phone(true);
1301 this.pos_default(true);
1304 $timer
= this.settings
.$next_tip
.find('.joyride-timer-indicator');
1306 if (/pop/i.test(this.settings
.tip_animation
)) {
1310 if (this.settings
.timer
> 0) {
1312 this.settings
.$next_tip
.show();
1314 setTimeout(function () {
1316 width
: $timer
.parent().width()
1317 }, this.settings
.timer
, 'linear');
1318 }.bind(this), this.settings
.tip_animation_fade_speed
);
1321 this.settings
.$next_tip
.show();
1326 } else if (/fade/i.test(this.settings
.tip_animation
)) {
1330 if (this.settings
.timer
> 0) {
1332 this.settings
.$next_tip
1333 .fadeIn(this.settings
.tip_animation_fade_speed
)
1336 setTimeout(function () {
1338 width
: $timer
.parent().width()
1339 }, this.settings
.timer
, 'linear');
1340 }.bind(this), this.settings
.tip_animation_fade_speed
);
1343 this.settings
.$next_tip
.fadeIn(this.settings
.tip_animation_fade_speed
);
1347 this.settings
.$current_tip
= this.settings
.$next_tip
;
1349 // skip non-existant targets
1350 } else if (this.settings
.$li
&& this.settings
.$target
.length
< 1) {
1352 this.show(init
, is_prev
);
1361 this.settings
.paused
= true;
1367 is_phone: function () {
1368 return matchMedia(Foundation
.media_queries
.small
).matches
&& !matchMedia(Foundation
.media_queries
.medium
).matches
;
1372 if (this.settings
.modal
&& this.settings
.expose
) {
1376 if (!this.settings
.modal
) {
1377 $('.joyride-modal-bg').hide();
1380 // Prevent scroll bouncing...wait to remove from layout
1381 this.settings
.$current_tip
.css('visibility', 'hidden');
1382 setTimeout($.proxy(function () {
1384 this.css('visibility', 'visible');
1385 }, this.settings
.$current_tip
), 0);
1386 this.settings
.post_step_callback(this.settings
.$li
.index(),
1387 this.settings
.$current_tip
);
1390 set_li: function (init
, is_prev
) {
1392 this.settings
.$li
= this.settings
.$tip_content
.eq(this.settings
.start_offset
);
1393 this.set_next_tip();
1394 this.settings
.$current_tip
= this.settings
.$next_tip
;
1397 this.settings
.$li
= this.settings
.$li
.prev();
1399 this.settings
.$li
= this.settings
.$li
.next();
1400 this.set_next_tip();
1406 set_next_tip: function () {
1407 this.settings
.$next_tip
= $('.joyride-tip-guide').eq(this.settings
.$li
.index());
1408 this.settings
.$next_tip
.data('closed', '');
1411 set_target: function () {
1412 var cl
= this.settings
.$li
.attr(this.add_namespace('data-class')),
1413 id
= this.settings
.$li
.attr(this.add_namespace('data-id')),
1414 $sel = function () {
1416 return $(document
.getElementById(id
));
1418 return $('.' + cl
).first();
1424 this.settings
.$target
= $sel();
1427 scroll_to: function () {
1428 var window_half
, tipOffset
;
1430 window_half
= $(window
).height() / 2;
1431 tipOffset
= Math
.ceil(this.settings
.$target
.offset().top
- window_half
+ this.settings
.$next_tip
.outerHeight());
1433 if (tipOffset
!= 0) {
1434 $('html, body').stop().animate({
1435 scrollTop
: tipOffset
1436 }, this.settings
.scroll_speed
, 'swing');
1440 paused: function () {
1441 return ($.inArray((this.settings
.$li
.index() + 1), this.settings
.pause_after
) === -1);
1444 restart: function () {
1446 this.settings
.$li
= undefined;
1450 pos_default: function (init
) {
1451 var $nub
= this.settings
.$next_tip
.find('.joyride-nub'),
1452 nub_width
= Math
.ceil($nub
.outerWidth() / 2),
1453 nub_height
= Math
.ceil($nub
.outerHeight() / 2),
1454 toggle
= init
|| false;
1456 // tip must not be "display: none" to calculate position
1458 this.settings
.$next_tip
.css('visibility', 'hidden');
1459 this.settings
.$next_tip
.show();
1462 if (!/body/i.test(this.settings
.$target
.selector
)) {
1463 var topAdjustment
= this.settings
.tip_settings
.tipAdjustmentY
? parseInt(this.settings
.tip_settings
.tipAdjustmentY
) : 0,
1464 leftAdjustment
= this.settings
.tip_settings
.tipAdjustmentX
? parseInt(this.settings
.tip_settings
.tipAdjustmentX
) : 0;
1466 if (this.bottom()) {
1468 this.settings
.$next_tip
.css({
1469 top
: (this.settings
.$target
.offset().top
+ nub_height
+ this.settings
.$target
.outerHeight() + topAdjustment
),
1470 left
: this.settings
.$target
.offset().left
+ this.settings
.$target
.outerWidth() - this.settings
.$next_tip
.outerWidth() + leftAdjustment
1473 this.settings
.$next_tip
.css({
1474 top
: (this.settings
.$target
.offset().top
+ nub_height
+ this.settings
.$target
.outerHeight() + topAdjustment
),
1475 left
: this.settings
.$target
.offset().left
+ leftAdjustment
1479 this.nub_position($nub
, this.settings
.tip_settings
.nub_position
, 'top');
1481 } else if (this.top()) {
1483 this.settings
.$next_tip
.css({
1484 top
: (this.settings
.$target
.offset().top
- this.settings
.$next_tip
.outerHeight() - nub_height
+ topAdjustment
),
1485 left
: this.settings
.$target
.offset().left
+ this.settings
.$target
.outerWidth() - this.settings
.$next_tip
.outerWidth()
1488 this.settings
.$next_tip
.css({
1489 top
: (this.settings
.$target
.offset().top
- this.settings
.$next_tip
.outerHeight() - nub_height
+ topAdjustment
),
1490 left
: this.settings
.$target
.offset().left
+ leftAdjustment
1494 this.nub_position($nub
, this.settings
.tip_settings
.nub_position
, 'bottom');
1496 } else if (this.right()) {
1498 this.settings
.$next_tip
.css({
1499 top
: this.settings
.$target
.offset().top
+ topAdjustment
,
1500 left
: (this.settings
.$target
.outerWidth() + this.settings
.$target
.offset().left
+ nub_width
+ leftAdjustment
)
1503 this.nub_position($nub
, this.settings
.tip_settings
.nub_position
, 'left');
1505 } else if (this.left()) {
1507 this.settings
.$next_tip
.css({
1508 top
: this.settings
.$target
.offset().top
+ topAdjustment
,
1509 left
: (this.settings
.$target
.offset().left
- this.settings
.$next_tip
.outerWidth() - nub_width
+ leftAdjustment
)
1512 this.nub_position($nub
, this.settings
.tip_settings
.nub_position
, 'right');
1516 if (!this.visible(this.corners(this.settings
.$next_tip
)) && this.settings
.attempts
< this.settings
.tip_settings
.tip_location_pattern
.length
) {
1518 $nub
.removeClass('bottom')
1520 .removeClass('right')
1521 .removeClass('left');
1523 this.settings
.tip_settings
.tip_location
= this.settings
.tip_settings
.tip_location_pattern
[this.settings
.attempts
];
1525 this.settings
.attempts
++;
1531 } else if (this.settings
.$li
.length
) {
1533 this.pos_modal($nub
);
1538 this.settings
.$next_tip
.hide();
1539 this.settings
.$next_tip
.css('visibility', 'visible');
1544 pos_phone: function (init
) {
1545 var tip_height
= this.settings
.$next_tip
.outerHeight(),
1546 tip_offset
= this.settings
.$next_tip
.offset(),
1547 target_height
= this.settings
.$target
.outerHeight(),
1548 $nub
= $('.joyride-nub', this.settings
.$next_tip
),
1549 nub_height
= Math
.ceil($nub
.outerHeight() / 2),
1550 toggle
= init
|| false;
1552 $nub
.removeClass('bottom')
1554 .removeClass('right')
1555 .removeClass('left');
1558 this.settings
.$next_tip
.css('visibility', 'hidden');
1559 this.settings
.$next_tip
.show();
1562 if (!/body/i.test(this.settings
.$target
.selector
)) {
1566 this.settings
.$next_tip
.offset({top
: this.settings
.$target
.offset().top
- tip_height
- nub_height
});
1567 $nub
.addClass('bottom');
1571 this.settings
.$next_tip
.offset({top
: this.settings
.$target
.offset().top
+ target_height
+ nub_height
});
1572 $nub
.addClass('top');
1576 } else if (this.settings
.$li
.length
) {
1577 this.pos_modal($nub
);
1581 this.settings
.$next_tip
.hide();
1582 this.settings
.$next_tip
.css('visibility', 'visible');
1586 pos_modal: function ($nub
) {
1593 show_modal: function () {
1594 if (!this.settings
.$next_tip
.data('closed')) {
1595 var joyridemodalbg
= $('.joyride-modal-bg');
1596 if (joyridemodalbg
.length
< 1) {
1597 var joyridemodalbg
= $(this.settings
.template
.modal
);
1598 joyridemodalbg
.appendTo('body');
1601 if (/pop/i.test(this.settings
.tip_animation
)) {
1602 joyridemodalbg
.show();
1604 joyridemodalbg
.fadeIn(this.settings
.tip_animation_fade_speed
);
1609 expose: function () {
1615 randId
= 'expose-' + this.random_str(6);
1617 if (arguments
.length
> 0 && arguments
[0] instanceof $) {
1619 } else if (this.settings
.$target
&& !/body/i.test(this.settings
.$target
.selector
)) {
1620 el
= this.settings
.$target
;
1625 if (el
.length
< 1) {
1626 if (window
.console
) {
1627 console
.error('element not valid', el
);
1632 expose
= $(this.settings
.template
.expose
);
1633 this.settings
.$body
.append(expose
);
1635 top
: el
.offset().top
,
1636 left
: el
.offset().left
,
1637 width
: el
.outerWidth(true),
1638 height
: el
.outerHeight(true)
1641 exposeCover
= $(this.settings
.template
.expose_cover
);
1644 zIndex
: el
.css('z-index'),
1645 position
: el
.css('position')
1648 origClasses
= el
.attr('class') == null ? '' : el
.attr('class');
1650 el
.css('z-index', parseInt(expose
.css('z-index')) + 1);
1652 if (origCSS
.position
== 'static') {
1653 el
.css('position', 'relative');
1656 el
.data('expose-css', origCSS
);
1657 el
.data('orig-class', origClasses
);
1658 el
.attr('class', origClasses
+ ' ' + this.settings
.expose_add_class
);
1661 top
: el
.offset().top
,
1662 left
: el
.offset().left
,
1663 width
: el
.outerWidth(true),
1664 height
: el
.outerHeight(true)
1667 if (this.settings
.modal
) this.show_modal();
1669 this.settings
.$body
.append(exposeCover
);
1670 expose
.addClass(randId
);
1671 exposeCover
.addClass(randId
);
1672 el
.data('expose', randId
);
1673 this.settings
.post_expose_callback(this.settings
.$li
.index(), this.settings
.$next_tip
, el
);
1674 this.add_exposed(el
);
1677 un_expose: function () {
1685 if (arguments
.length
> 0 && arguments
[0] instanceof $) {
1687 } else if (this.settings
.$target
&& !/body/i.test(this.settings
.$target
.selector
)) {
1688 el
= this.settings
.$target
;
1693 if (el
.length
< 1) {
1694 if (window
.console
) {
1695 console
.error('element not valid', el
);
1700 exposeId
= el
.data('expose');
1701 expose
= $('.' + exposeId
);
1703 if (arguments
.length
> 1) {
1704 clearAll
= arguments
[1];
1707 if (clearAll
=== true) {
1708 $('.joyride-expose-wrapper,.joyride-expose-cover').remove();
1713 origCSS
= el
.data('expose-css');
1715 if (origCSS
.zIndex
== 'auto') {
1716 el
.css('z-index', '');
1718 el
.css('z-index', origCSS
.zIndex
);
1721 if (origCSS
.position
!= el
.css('position')) {
1722 if (origCSS
.position
== 'static') {// this is default, no need to set it.
1723 el
.css('position', '');
1725 el
.css('position', origCSS
.position
);
1729 origClasses
= el
.data('orig-class');
1730 el
.attr('class', origClasses
);
1731 el
.removeData('orig-classes');
1733 el
.removeData('expose');
1734 el
.removeData('expose-z-index');
1735 this.remove_exposed(el
);
1738 add_exposed: function (el
) {
1739 this.settings
.exposed
= this.settings
.exposed
|| [];
1740 if (el
instanceof $ || typeof el
=== 'object') {
1741 this.settings
.exposed
.push(el
[0]);
1742 } else if (typeof el
== 'string') {
1743 this.settings
.exposed
.push(el
);
1747 remove_exposed: function (el
) {
1749 if (el
instanceof $) {
1751 } else if (typeof el
== 'string') {
1755 this.settings
.exposed
= this.settings
.exposed
|| [];
1756 i
= this.settings
.exposed
.length
;
1759 if (this.settings
.exposed
[i
] == search
) {
1760 this.settings
.exposed
.splice(i
, 1);
1766 center: function () {
1769 this.settings
.$next_tip
.css({
1770 top
: ((($w
.height() - this.settings
.$next_tip
.outerHeight()) / 2) + $w
.scrollTop()),
1771 left
: ((($w
.width() - this.settings
.$next_tip
.outerWidth()) / 2) + $w
.scrollLeft())
1777 bottom: function () {
1778 return /bottom/i.test(this.settings
.tip_settings
.tip_location
);
1782 return /top/i.test(this.settings
.tip_settings
.tip_location
);
1785 right: function () {
1786 return /right/i.test(this.settings
.tip_settings
.tip_location
);
1790 return /left/i.test(this.settings
.tip_settings
.tip_location
);
1793 corners: function (el
) {
1795 window_half
= w
.height() / 2,
1796 //using this to calculate since scroll may not have finished yet.
1797 tipOffset
= Math
.ceil(this.settings
.$target
.offset().top
- window_half
+ this.settings
.$next_tip
.outerHeight()),
1798 right
= w
.width() + w
.scrollLeft(),
1799 offsetBottom
= w
.height() + tipOffset
,
1800 bottom
= w
.height() + w
.scrollTop(),
1801 top
= w
.scrollTop();
1803 if (tipOffset
< top
) {
1804 if (tipOffset
< 0) {
1811 if (offsetBottom
> bottom
) {
1812 bottom
= offsetBottom
;
1816 el
.offset().top
< top
,
1817 right
< el
.offset().left
+ el
.outerWidth(),
1818 bottom
< el
.offset().top
+ el
.outerHeight(),
1819 w
.scrollLeft() > el
.offset().left
1823 visible: function (hidden_corners
) {
1824 var i
= hidden_corners
.length
;
1827 if (hidden_corners
[i
]) return false;
1833 nub_position: function (nub
, pos
, def
) {
1834 if (pos
=== 'auto') {
1841 startTimer: function () {
1842 if (this.settings
.$li
.length
) {
1843 this.settings
.automate
= setTimeout(function () {
1847 }.bind(this), this.settings
.timer
);
1849 clearTimeout(this.settings
.automate
);
1853 end: function (abort
) {
1854 if (this.settings
.cookie_monster
) {
1855 $.cookie(this.settings
.cookie_name
, 'ridden', {
1856 expires
: this.settings
.cookie_expires
,
1857 domain
: this.settings
.cookie_domain
1861 if (this.settings
.timer
> 0) {
1862 clearTimeout(this.settings
.automate
);
1865 if (this.settings
.modal
&& this.settings
.expose
) {
1869 // Unplug keystrokes listener
1870 $(this.scope
).off('keyup.joyride')
1872 this.settings
.$next_tip
.data('closed', true);
1873 this.settings
.riding
= false;
1875 $('.joyride-modal-bg').hide();
1876 this.settings
.$current_tip
.hide();
1878 if (typeof abort
=== 'undefined' || abort
=== false) {
1879 this.settings
.post_step_callback(this.settings
.$li
.index(), this.settings
.$current_tip
);
1880 this.settings
.post_ride_callback(this.settings
.$li
.index(), this.settings
.$current_tip
);
1883 $('.joyride-tip-guide').remove();
1887 $(this.scope
).off('.joyride');
1888 $(window
).off('.joyride');
1889 $('.joyride-close-tip, .joyride-next-tip, .joyride-modal-bg').off('.joyride');
1890 $('.joyride-tip-guide, .joyride-modal-bg').remove();
1891 clearTimeout(this.settings
.automate
);
1895 reflow: function () {
1898 }(jQuery
, window
, window
.document
));
1900 (function ($, window
, document
, undefined) {
1903 Foundation
.libs
.equalizer
= {
1910 before_height_change
: $.noop
,
1911 after_height_change
: $.noop
,
1912 equalize_on_stack
: false
1915 init: function (scope
, method
, options
) {
1916 Foundation
.inherit(this, 'image_loaded');
1917 this.bindings(method
, options
);
1921 events: function () {
1922 this.S(window
).off('.equalizer').on('resize.fndtn.equalizer', function (e
) {
1927 equalize: function (equalizer
) {
1928 var isStacked
= false,
1929 vals
= equalizer
.find('[' + this.attr_name() + '-watch]:visible'),
1930 settings
= equalizer
.data(this.attr_name(true) + '-init');
1932 if (vals
.length
=== 0) return;
1933 var firstTopOffset
= vals
.first().offset().top
;
1934 settings
.before_height_change();
1935 equalizer
.trigger('before-height-change').trigger('before-height-change.fndth.equalizer');
1936 vals
.height('inherit');
1937 vals
.each(function () {
1939 if (el
.offset().top
!== firstTopOffset
) {
1944 if (settings
.equalize_on_stack
=== false) {
1945 if (isStacked
) return;
1949 var heights
= vals
.map(function () {
1950 return $(this).outerHeight(false)
1953 if (settings
.use_tallest
) {
1954 var max
= Math
.max
.apply(null, heights
);
1955 vals
.css('height', max
);
1957 var min
= Math
.min
.apply(null, heights
);
1958 vals
.css('height', min
);
1960 settings
.after_height_change();
1961 equalizer
.trigger('after-height-change').trigger('after-height-change.fndtn.equalizer');
1964 reflow: function () {
1967 this.S('[' + this.attr_name() + ']', this.scope
).each(function () {
1968 var $eq_target
= $(this);
1969 self
.image_loaded(self
.S('img', this), function () {
1970 self
.equalize($eq_target
)
1975 })(jQuery
, window
, window
.document
);
1977 (function ($, window
, document
, undefined) {
1980 Foundation
.libs
.dropdown
= {
1986 active_class
: 'open',
1987 disabled_class
: 'disabled',
1992 opened: function () {
1994 closed: function () {
1998 init: function (scope
, method
, options
) {
1999 Foundation
.inherit(this, 'throttle');
2001 $.extend(true, this.settings
, method
, options
);
2002 this.bindings(method
, options
);
2005 events: function (scope
) {
2011 .on('click.fndtn.dropdown', '[' + this.attr_name() + ']', function (e
) {
2012 var settings
= S(this).data(self
.attr_name(true) + '-init') || self
.settings
;
2013 if (!settings
.is_hover
|| Modernizr
.touch
) {
2015 if (S(this).parent('[data-reveal-id]')) {
2016 e
.stopPropagation();
2018 self
.toggle($(this));
2021 .on('mouseenter.fndtn.dropdown', '[' + this.attr_name() + '], [' + this.attr_name() + '-content]', function (e
) {
2022 var $this = S(this),
2026 clearTimeout(self
.timeout
);
2028 if ($this.data(self
.data_attr())) {
2029 dropdown
= S('#' + $this.data(self
.data_attr()));
2033 target
= S('[' + self
.attr_name() + '="' + dropdown
.attr('id') + '"]');
2036 var settings
= target
.data(self
.attr_name(true) + '-init') || self
.settings
;
2038 if (S(e
.currentTarget
).data(self
.data_attr()) && settings
.is_hover
) {
2039 self
.closeall
.call(self
);
2042 if (settings
.is_hover
) self
.open
.apply(self
, [dropdown
, target
]);
2044 .on('mouseleave.fndtn.dropdown', '[' + this.attr_name() + '], [' + this.attr_name() + '-content]', function (e
) {
2045 var $this = S(this);
2048 if ($this.data(self
.data_attr())) {
2049 settings
= $this.data(self
.data_attr(true) + '-init') || self
.settings
;
2052 var target
= S('[' + self
.attr_name() + '="' + S(this).attr('id') + '"]'),
2053 settings
= target
.data(self
.attr_name(true) + '-init') || self
.settings
;
2056 self
.timeout
= setTimeout(function () {
2057 if ($this.data(self
.data_attr())) {
2058 if (settings
.is_hover
) self
.close
.call(self
, S('#' + $this.data(self
.data_attr())));
2060 if (settings
.is_hover
) self
.close
.call(self
, $this);
2062 }.bind(this), settings
.hover_timeout
);
2064 .on('click.fndtn.dropdown', function (e
) {
2065 var parent
= S(e
.target
).closest('[' + self
.attr_name() + '-content]');
2066 var links
= parent
.find('a');
2068 if (links
.length
> 0 && parent
.attr('aria-autoclose') !== "false") {
2069 self
.close
.call(self
, S('[' + self
.attr_name() + '-content]'));
2072 if (S(e
.target
).closest('[' + self
.attr_name() + ']').length
> 0) {
2076 if (!(S(e
.target
).data('revealId')) &&
2077 (parent
.length
> 0 && (S(e
.target
).is('[' + self
.attr_name() + '-content]') ||
2078 $.contains(parent
.first()[0], e
.target
)))) {
2079 e
.stopPropagation();
2083 self
.close
.call(self
, S('[' + self
.attr_name() + '-content]'));
2085 .on('opened.fndtn.dropdown', '[' + self
.attr_name() + '-content]', function () {
2086 self
.settings
.opened
.call(this);
2088 .on('closed.fndtn.dropdown', '[' + self
.attr_name() + '-content]', function () {
2089 self
.settings
.closed
.call(this);
2094 .on('resize.fndtn.dropdown', self
.throttle(function () {
2095 self
.resize
.call(self
);
2101 close: function (dropdown
) {
2103 dropdown
.each(function () {
2104 var original_target
= $('[' + self
.attr_name() + '=' + dropdown
[0].id
+ ']') || $('aria-controls=' + dropdown
[0].id
+ ']');
2105 original_target
.attr('aria-expanded', 'false');
2106 if (self
.S(this).hasClass(self
.settings
.active_class
)) {
2108 .css(Foundation
.rtl
? 'right' : 'left', '-99999px')
2109 .attr('aria-hidden', 'true')
2110 .removeClass(self
.settings
.active_class
)
2111 .prev('[' + self
.attr_name() + ']')
2112 .removeClass(self
.settings
.active_class
)
2113 .removeData('target');
2115 self
.S(this).trigger('closed').trigger('closed.fndtn.dropdown', [dropdown
]);
2118 dropdown
.removeClass('f-open-' + this.attr_name(true));
2121 closeall: function () {
2123 $.each(self
.S('.f-open-' + this.attr_name(true)), function () {
2124 self
.close
.call(self
, self
.S(this));
2128 open: function (dropdown
, target
) {
2131 .addClass(this.settings
.active_class
), target
);
2132 dropdown
.prev('[' + this.attr_name() + ']').addClass(this.settings
.active_class
);
2133 dropdown
.data('target', target
.get(0)).trigger('opened').trigger('opened.fndtn.dropdown', [dropdown
, target
]);
2134 dropdown
.attr('aria-hidden', 'false');
2135 target
.attr('aria-expanded', 'true');
2137 dropdown
.addClass('f-open-' + this.attr_name(true));
2140 data_attr: function () {
2141 if (this.namespace.length
> 0) {
2142 return this.namespace + '-' + this.name
;
2148 toggle: function (target
) {
2149 if (target
.hasClass(this.settings
.disabled_class
)) {
2152 var dropdown
= this.S('#' + target
.data(this.data_attr()));
2153 if (dropdown
.length
=== 0) {
2154 // No dropdown found, not continuing
2158 this.close
.call(this, this.S('[' + this.attr_name() + '-content]').not(dropdown
));
2160 if (dropdown
.hasClass(this.settings
.active_class
)) {
2161 this.close
.call(this, dropdown
);
2162 if (dropdown
.data('target') !== target
.get(0))
2163 this.open
.call(this, dropdown
, target
);
2165 this.open
.call(this, dropdown
, target
);
2169 resize: function () {
2170 var dropdown
= this.S('[' + this.attr_name() + '-content].open'),
2171 target
= this.S('[' + this.attr_name() + '="' + dropdown
.attr('id') + '"]');
2173 if (dropdown
.length
&& target
.length
) {
2174 this.css(dropdown
, target
);
2178 css: function (dropdown
, target
) {
2179 var left_offset
= Math
.max((target
.width() - dropdown
.width()) / 2, 8),
2180 settings
= target
.data(this.attr_name(true) + '-init') || this.settings
;
2185 var p
= this.dirs
.bottom
.call(dropdown
, target
, settings
);
2187 dropdown
.attr('style', '').removeClass('drop-left drop-right drop-top').css({
2188 position
: 'absolute',
2190 'max-width': 'none',
2194 dropdown
.css(Foundation
.rtl
? 'right' : 'left', left_offset
);
2197 this.style(dropdown
, target
, settings
);
2203 style: function (dropdown
, target
, settings
) {
2204 var css
= $.extend({position
: 'absolute'},
2205 this.dirs
[settings
.align
].call(dropdown
, target
, settings
));
2207 dropdown
.attr('style', '').css(css
);
2210 // return CSS property object
2211 // `this` is the dropdown
2213 // Calculate target offset
2214 _base: function (t
) {
2215 var o_p
= this.offsetParent(),
2222 //set some flags on the p object to pass along
2223 p
.missRight
= false;
2226 p
.leftRightFlag
= false;
2228 //lets see if the panel will be off the screen
2229 //get the actual width of the page and store it
2230 var actualBodyWidth
;
2231 if (document
.getElementsByClassName('row')[0]) {
2232 actualBodyWidth
= document
.getElementsByClassName('row')[0].clientWidth
;
2234 actualBodyWidth
= window
.outerWidth
;
2237 var actualMarginWidth
= (window
.outerWidth
- actualBodyWidth
) / 2;
2238 var actualBoundary
= actualBodyWidth
;
2240 if (!this.hasClass('mega')) {
2242 if (t
.offset().top
<= this.outerHeight()) {
2244 actualBoundary
= window
.outerWidth
- actualMarginWidth
;
2245 p
.leftRightFlag
= true;
2249 if (t
.offset().left
+ this.outerWidth() > t
.offset().left
+ actualMarginWidth
&& t
.offset().left
- actualMarginWidth
> this.outerWidth()) {
2255 if (t
.offset().left
- this.outerWidth() <= 0) {
2257 p
.missRight
= false;
2264 top: function (t
, s
) {
2265 var self
= Foundation
.libs
.dropdown
,
2266 p
= self
.dirs
._base
.call(this, t
);
2268 this.addClass('drop-top');
2270 if (p
.missTop
== true) {
2271 p
.top
= p
.top
+ t
.outerHeight() + this.outerHeight();
2272 this.removeClass('drop-top');
2275 if (p
.missRight
== true) {
2276 p
.left
= p
.left
- this.outerWidth() + t
.outerWidth();
2279 if (t
.outerWidth() < this.outerWidth() || self
.small() || this.hasClass(s
.mega_menu
)) {
2280 self
.adjust_pip(this, t
, s
, p
);
2283 if (Foundation
.rtl
) {
2285 left
: p
.left
- this.outerWidth() + t
.outerWidth(),
2286 top
: p
.top
- this.outerHeight()
2290 return {left
: p
.left
, top
: p
.top
- this.outerHeight()};
2293 bottom: function (t
, s
) {
2294 var self
= Foundation
.libs
.dropdown
,
2295 p
= self
.dirs
._base
.call(this, t
);
2297 if (p
.missRight
== true) {
2298 p
.left
= p
.left
- this.outerWidth() + t
.outerWidth();
2301 if (t
.outerWidth() < this.outerWidth() || self
.small() || this.hasClass(s
.mega_menu
)) {
2302 self
.adjust_pip(this, t
, s
, p
);
2306 return {left
: p
.left
- this.outerWidth() + t
.outerWidth(), top
: p
.top
+ t
.outerHeight()};
2309 return {left
: p
.left
, top
: p
.top
+ t
.outerHeight()};
2312 left: function (t
, s
) {
2313 var p
= Foundation
.libs
.dropdown
.dirs
._base
.call(this, t
);
2315 this.addClass('drop-left');
2317 if (p
.missLeft
== true) {
2318 p
.left
= p
.left
+ this.outerWidth();
2319 p
.top
= p
.top
+ t
.outerHeight();
2320 this.removeClass('drop-left');
2323 return {left
: p
.left
- this.outerWidth(), top
: p
.top
};
2326 right: function (t
, s
) {
2327 var p
= Foundation
.libs
.dropdown
.dirs
._base
.call(this, t
);
2329 this.addClass('drop-right');
2331 if (p
.missRight
== true) {
2332 p
.left
= p
.left
- this.outerWidth();
2333 p
.top
= p
.top
+ t
.outerHeight();
2334 this.removeClass('drop-right');
2336 p
.triggeredRight
= true;
2339 var self
= Foundation
.libs
.dropdown
;
2341 if (t
.outerWidth() < this.outerWidth() || self
.small() || this.hasClass(s
.mega_menu
)) {
2342 self
.adjust_pip(this, t
, s
, p
);
2345 return {left
: p
.left
+ t
.outerWidth(), top
: p
.top
};
2349 // Insert rule to style psuedo elements
2350 adjust_pip: function (dropdown
, target
, settings
, position
) {
2351 var sheet
= Foundation
.stylesheet
,
2352 pip_offset_base
= 8;
2354 if (dropdown
.hasClass(settings
.mega_class
)) {
2355 pip_offset_base
= position
.left
+ (target
.outerWidth() / 2) - 8;
2357 else if (this.small()) {
2358 pip_offset_base
+= position
.left
- 8;
2361 this.rule_idx
= sheet
.cssRules
.length
;
2364 var sel_before
= '.f-dropdown.open:before',
2365 sel_after
= '.f-dropdown.open:after',
2366 css_before
= 'left: ' + pip_offset_base
+ 'px;',
2367 css_after
= 'left: ' + (pip_offset_base
- 1) + 'px;';
2369 if (position
.missRight
== true) {
2370 pip_offset_base
= dropdown
.outerWidth() - 23;
2371 sel_before
= '.f-dropdown.open:before',
2372 sel_after
= '.f-dropdown.open:after',
2373 css_before
= 'left: ' + pip_offset_base
+ 'px;',
2374 css_after
= 'left: ' + (pip_offset_base
- 1) + 'px;';
2377 //just a case where right is fired, but its not missing right
2378 if (position
.triggeredRight
== true) {
2379 sel_before
= '.f-dropdown.open:before',
2380 sel_after
= '.f-dropdown.open:after',
2381 css_before
= 'left:-12px;',
2382 css_after
= 'left:-14px;';
2385 if (sheet
.insertRule
) {
2386 sheet
.insertRule([sel_before
, '{', css_before
, '}'].join(' '), this.rule_idx
);
2387 sheet
.insertRule([sel_after
, '{', css_after
, '}'].join(' '), this.rule_idx
+ 1);
2389 sheet
.addRule(sel_before
, css_before
, this.rule_idx
);
2390 sheet
.addRule(sel_after
, css_after
, this.rule_idx
+ 1);
2394 // Remove old dropdown rule index
2395 clear_idx: function () {
2396 var sheet
= Foundation
.stylesheet
;
2398 if (typeof this.rule_idx
!== 'undefined') {
2399 sheet
.deleteRule(this.rule_idx
);
2400 sheet
.deleteRule(this.rule_idx
);
2401 delete this.rule_idx
;
2405 small: function () {
2406 return matchMedia(Foundation
.media_queries
.small
).matches
&& !matchMedia(Foundation
.media_queries
.medium
).matches
;
2410 this.S(this.scope
).off('.fndtn.dropdown');
2411 this.S('html, body').off('.fndtn.dropdown');
2412 this.S(window
).off('.fndtn.dropdown');
2413 this.S('[data-dropdown-content]').off('.fndtn.dropdown');
2416 reflow: function () {
2419 }(jQuery
, window
, window
.document
));
2421 (function ($, window
, document
, undefined) {
2424 Foundation
.libs
.clearing
= {
2431 viewing
: '<a href="#" class="clearing-close">×</a>' +
2432 '<div class="visible-img" style="display: none"><div class="clearing-touch-label"></div><img src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" alt="" />' +
2433 '<p class="clearing-caption"></p><a href="#" class="clearing-main-prev"><span></span></a>' +
2434 '<a href="#" class="clearing-main-next"><span></span></a></div>'
2437 // comma delimited list of selectors that, on click, will close clearing,
2438 // add 'div.clearing-blackout, div.visible-img' to close on background click
2439 close_selectors
: '.clearing-close, div.clearing-blackout',
2441 // Default to the entire li element.
2444 // Image will be skipped in carousel.
2449 // event initializers and locks
2454 init: function (scope
, method
, options
) {
2456 Foundation
.inherit(this, 'throttle image_loaded');
2458 this.bindings(method
, options
);
2460 if (self
.S(this.scope
).is('[' + this.attr_name() + ']')) {
2461 this.assemble(self
.S('li', this.scope
));
2463 self
.S('[' + this.attr_name() + ']', this.scope
).each(function () {
2464 self
.assemble(self
.S('li', this));
2469 events: function (scope
) {
2472 $scroll_container
= $('.scroll-container');
2474 if ($scroll_container
.length
> 0) {
2475 this.scope
= $scroll_container
;
2480 .on('click.fndtn.clearing', 'ul[' + this.attr_name() + '] li ' + this.settings
.open_selectors
,
2481 function (e
, current
, target
) {
2482 var current
= current
|| S(this),
2483 target
= target
|| current
,
2484 next
= current
.next('li'),
2485 settings
= current
.closest('[' + self
.attr_name() + ']').data(self
.attr_name(true) + '-init'),
2486 image
= S(e
.target
);
2492 settings
= current
.closest('[' + self
.attr_name() + ']').data(self
.attr_name(true) + '-init');
2495 // if clearing is open and the current image is
2496 // clicked, go to the next image in sequence
2497 if (target
.hasClass('visible') &&
2498 current
[0] === target
[0] &&
2499 next
.length
> 0 && self
.is_open(current
)) {
2501 image
= S('img', target
);
2504 // set current and target to the clicked li if not otherwise defined.
2505 self
.open(image
, current
, target
);
2506 self
.update_paddles(target
);
2509 .on('click.fndtn.clearing', '.clearing-main-next',
2513 .on('click.fndtn.clearing', '.clearing-main-prev',
2517 .on('click.fndtn.clearing', this.settings
.close_selectors
,
2519 Foundation
.libs
.clearing
.close(e
, this)
2522 $(document
).on('keydown.fndtn.clearing',
2527 S(window
).off('.clearing').on('resize.fndtn.clearing',
2532 this.swipe_events(scope
);
2535 swipe_events: function (scope
) {
2540 .on('touchstart.fndtn.clearing', '.visible-img', function (e
) {
2542 e
= e
.originalEvent
;
2545 start_page_x
: e
.touches
[0].pageX
,
2546 start_page_y
: e
.touches
[0].pageY
,
2547 start_time
: (new Date()).getTime(),
2549 is_scrolling
: undefined
2552 S(this).data('swipe-transition', data
);
2553 e
.stopPropagation();
2555 .on('touchmove.fndtn.clearing', '.visible-img', function (e
) {
2557 e
= e
.originalEvent
;
2559 // Ignore pinch/zoom events
2560 if (e
.touches
.length
> 1 || e
.scale
&& e
.scale
!== 1) return;
2562 var data
= S(this).data('swipe-transition');
2564 if (typeof data
=== 'undefined') {
2568 data
.delta_x
= e
.touches
[0].pageX
- data
.start_page_x
;
2570 if (Foundation
.rtl
) {
2571 data
.delta_x
= -data
.delta_x
;
2574 if (typeof data
.is_scrolling
=== 'undefined') {
2575 data
.is_scrolling
= !!( data
.is_scrolling
|| Math
.abs(data
.delta_x
) < Math
.abs(e
.touches
[0].pageY
- data
.start_page_y
) );
2578 if (!data
.is_scrolling
&& !data
.active
) {
2580 var direction
= (data
.delta_x
< 0) ? 'next' : 'prev';
2582 self
.nav(e
, direction
);
2585 .on('touchend.fndtn.clearing', '.visible-img', function (e
) {
2586 S(this).data('swipe-transition', {});
2587 e
.stopPropagation();
2591 assemble: function ($li
) {
2592 var $el
= $li
.parent();
2594 if ($el
.parent().hasClass('carousel')) {
2598 $el
.after('<div id="foundationClearingHolder"></div>');
2600 var grid
= $el
.detach(),
2601 grid_outerHTML
= '';
2603 if (grid
[0] == null) {
2606 grid_outerHTML
= grid
[0].outerHTML
;
2609 var holder
= this.S('#foundationClearingHolder'),
2610 settings
= $el
.data(this.attr_name(true) + '-init'),
2612 grid
: '<div class="carousel">' + grid_outerHTML
+ '</div>',
2613 viewing
: settings
.templates
.viewing
2615 wrapper
= '<div class="clearing-assembled"><div>' + data
.viewing
+
2616 data
.grid
+ '</div></div>',
2617 touch_label
= this.settings
.touch_label
;
2619 if (Modernizr
.touch
) {
2620 wrapper
= $(wrapper
).find('.clearing-touch-label').html(touch_label
).end();
2623 holder
.after(wrapper
).remove();
2626 open: function ($image
, current
, target
) {
2628 body
= $(document
.body
),
2629 root
= target
.closest('.clearing-assembled'),
2630 container
= self
.S('div', root
).first(),
2631 visible_image
= self
.S('.visible-img', container
),
2632 image
= self
.S('img', visible_image
).not($image
),
2633 label
= self
.S('.clearing-touch-label', container
),
2636 // Event to disable scrolling on touch devices when Clearing is activated
2637 $('body').on('touchmove', function (e
) {
2641 image
.error(function () {
2645 function startLoad() {
2646 setTimeout(function () {
2647 this.image_loaded(image
, function () {
2648 if (image
.outerWidth() === 1 && !error
) {
2649 startLoad
.call(this);
2651 cb
.call(this, image
);
2657 function cb(image
) {
2658 var $image
= $(image
);
2659 $image
.css('visibility', 'visible');
2660 // toggle the gallery
2661 body
.css('overflow', 'hidden');
2662 root
.addClass('clearing-blackout');
2663 container
.addClass('clearing-container');
2664 visible_image
.show();
2665 this.fix_height(target
)
2666 .caption(self
.S('.clearing-caption', visible_image
), self
.S('img', target
))
2667 .center_and_label(image
, label
)
2668 .shift(current
, target
, function () {
2669 target
.closest('li').siblings().removeClass('visible');
2670 target
.closest('li').addClass('visible');
2672 visible_image
.trigger('opened.fndtn.clearing')
2675 if (!this.locked()) {
2676 visible_image
.trigger('open.fndtn.clearing');
2677 // set the image to the selected thumbnail
2679 .attr('src', this.load($image
))
2680 .css('visibility', 'hidden');
2682 startLoad
.call(this);
2686 close: function (e
, el
) {
2689 var root
= (function (target
) {
2690 if (/blackout/.test(target
.selector
)) {
2693 return target
.closest('.clearing-blackout');
2696 body
= $(document
.body
), container
, visible_image
;
2698 if (el
=== e
.target
&& root
) {
2699 body
.css('overflow', '');
2700 container
= $('div', root
).first();
2701 visible_image
= $('.visible-img', container
);
2702 visible_image
.trigger('close.fndtn.clearing');
2703 this.settings
.prev_index
= 0;
2704 $('ul[' + this.attr_name() + ']', root
)
2705 .attr('style', '').closest('.clearing-blackout')
2706 .removeClass('clearing-blackout');
2707 container
.removeClass('clearing-container');
2708 visible_image
.hide();
2709 visible_image
.trigger('closed.fndtn.clearing');
2712 // Event to re-enable scrolling on touch devices
2713 $('body').off('touchmove');
2718 is_open: function (current
) {
2719 return current
.parent().prop('style').length
> 0;
2722 keydown: function (e
) {
2723 var clearing
= $('.clearing-blackout ul[' + this.attr_name() + ']'),
2724 NEXT_KEY
= this.rtl
? 37 : 39,
2725 PREV_KEY
= this.rtl
? 39 : 37,
2728 if (e
.which
=== NEXT_KEY
) this.go(clearing
, 'next');
2729 if (e
.which
=== PREV_KEY
) this.go(clearing
, 'prev');
2730 if (e
.which
=== ESC_KEY
) this.S('a.clearing-close').trigger('click').trigger('click.fndtn.clearing');
2733 nav: function (e
, direction
) {
2734 var clearing
= $('ul[' + this.attr_name() + ']', '.clearing-blackout');
2737 this.go(clearing
, direction
);
2740 resize: function () {
2741 var image
= $('img', '.clearing-blackout .visible-img'),
2742 label
= $('.clearing-touch-label', '.clearing-blackout');
2745 this.center_and_label(image
, label
);
2746 image
.trigger('resized.fndtn.clearing')
2750 // visual adjustments
2751 fix_height: function (target
) {
2752 var lis
= target
.parent().children(),
2755 lis
.each(function () {
2756 var li
= self
.S(this),
2757 image
= li
.find('img');
2759 if (li
.height() > image
.outerHeight()) {
2760 li
.addClass('fix-height');
2764 .width(lis
.length
* 100 + '%');
2769 update_paddles: function (target
) {
2770 target
= target
.closest('li');
2771 var visible_image
= target
2772 .closest('.carousel')
2773 .siblings('.visible-img');
2775 if (target
.next().length
> 0) {
2776 this.S('.clearing-main-next', visible_image
).removeClass('disabled');
2778 this.S('.clearing-main-next', visible_image
).addClass('disabled');
2781 if (target
.prev().length
> 0) {
2782 this.S('.clearing-main-prev', visible_image
).removeClass('disabled');
2784 this.S('.clearing-main-prev', visible_image
).addClass('disabled');
2788 center_and_label: function (target
, label
) {
2791 marginLeft
: -(target
.outerWidth() / 2),
2792 marginTop
: -(target
.outerHeight() / 2)
2795 if (label
.length
> 0) {
2797 marginLeft
: -(label
.outerWidth() / 2),
2798 marginTop
: -(target
.outerHeight() / 2) - label
.outerHeight() - 10
2803 marginRight
: -(target
.outerWidth() / 2),
2804 marginTop
: -(target
.outerHeight() / 2),
2809 if (label
.length
> 0) {
2811 marginRight
: -(label
.outerWidth() / 2),
2812 marginTop
: -(target
.outerHeight() / 2) - label
.outerHeight() - 10,
2821 // image loading and preloading
2823 load: function ($image
) {
2826 if ($image
[0].nodeName
=== 'A') {
2827 href
= $image
.attr('href');
2829 href
= $image
.closest('a').attr('href');
2832 this.preload($image
);
2834 if (href
) return href
;
2835 return $image
.attr('src');
2838 preload: function ($image
) {
2840 .img($image
.closest('li').next())
2841 .img($image
.closest('li').prev());
2844 img: function (img
) {
2846 var new_img
= new Image(),
2847 new_a
= this.S('a', img
);
2850 new_img
.src
= new_a
.attr('href');
2852 new_img
.src
= this.S('img', img
).attr('src');
2860 caption: function (container
, $image
) {
2861 var caption
= $image
.attr('data-caption');
2875 // directional methods
2877 go: function ($ul
, direction
) {
2878 var current
= this.S('.visible', $ul
),
2879 target
= current
[direction
]();
2881 // Check for skip selector.
2882 if (this.settings
.skip_selector
&& target
.find(this.settings
.skip_selector
).length
!= 0) {
2883 target
= target
[direction
]();
2886 if (target
.length
) {
2887 this.S('img', target
)
2888 .trigger('click', [current
, target
]).trigger('click.fndtn.clearing', [current
, target
])
2889 .trigger('change.fndtn.clearing');
2893 shift: function (current
, target
, callback
) {
2894 var clearing
= target
.parent(),
2895 old_index
= this.settings
.prev_index
|| target
.index(),
2896 direction
= this.direction(clearing
, current
, target
),
2897 dir
= this.rtl
? 'right' : 'left',
2898 left
= parseInt(clearing
.css('left'), 10),
2899 width
= target
.outerWidth(),
2904 // we use jQuery animate instead of CSS transitions because we
2905 // need a callback to unlock the next animation
2906 // needs support for RTL **
2907 if (target
.index() !== old_index
&& !/skip/.test(direction
)) {
2908 if (/left/.test(direction
)) {
2910 dir_obj
[dir
] = left
+ width
;
2911 clearing
.animate(dir_obj
, 300, this.unlock());
2912 } else if (/right/.test(direction
)) {
2914 dir_obj
[dir
] = left
- width
;
2915 clearing
.animate(dir_obj
, 300, this.unlock());
2917 } else if (/skip/.test(direction
)) {
2918 // the target image is not adjacent to the current image, so
2919 // do we scroll right or not
2920 skip_shift
= target
.index() - this.settings
.up_count
;
2923 if (skip_shift
> 0) {
2924 dir_obj
[dir
] = -(skip_shift
* width
);
2925 clearing
.animate(dir_obj
, 300, this.unlock());
2928 clearing
.animate(dir_obj
, 300, this.unlock());
2935 direction: function ($el
, current
, target
) {
2936 var lis
= this.S('li', $el
),
2937 li_width
= lis
.outerWidth() + (lis
.outerWidth() / 4),
2938 up_count
= Math
.floor(this.S('.clearing-container').outerWidth() / li_width
) - 1,
2939 target_index
= lis
.index(target
),
2942 this.settings
.up_count
= up_count
;
2944 if (this.adjacent(this.settings
.prev_index
, target_index
)) {
2945 if ((target_index
> up_count
) && target_index
> this.settings
.prev_index
) {
2947 } else if ((target_index
> up_count
- 1) && target_index
<= this.settings
.prev_index
) {
2956 this.settings
.prev_index
= target_index
;
2961 adjacent: function (current_index
, target_index
) {
2962 for (var i
= target_index
+ 1; i
>= target_index
- 1; i
--) {
2963 if (i
=== current_index
) return true;
2971 this.settings
.locked
= true;
2974 unlock: function () {
2975 this.settings
.locked
= false;
2978 locked: function () {
2979 return this.settings
.locked
;
2983 this.S(this.scope
).off('.fndtn.clearing');
2984 this.S(window
).off('.fndtn.clearing');
2987 reflow: function () {
2992 }(jQuery
, window
, window
.document
));
2994 (function ($, window
, document
, undefined) {
2997 var noop = function () {
3000 var Orbit = function (el
, settings
) {
3001 // Don't reinitialize plugin
3002 if (el
.hasClass(settings
.slides_container_class
)) {
3008 slides_container
= el
,
3016 adjust_height_after
= false;
3019 self
.slides = function () {
3020 return slides_container
.children(settings
.slide_selector
);
3023 self
.slides().first().addClass(settings
.active_slide_class
);
3025 self
.update_slide_number = function (index
) {
3026 if (settings
.slide_number
) {
3027 number_container
.find('span:first').text(parseInt(index
) + 1);
3028 number_container
.find('span:last').text(self
.slides().length
);
3030 if (settings
.bullets
) {
3031 bullets_container
.children().removeClass(settings
.bullets_active_class
);
3032 $(bullets_container
.children().get(index
)).addClass(settings
.bullets_active_class
);
3036 self
.update_active_link = function (index
) {
3037 var link
= $('[data-orbit-link="' + self
.slides().eq(index
).attr('data-orbit-slide') + '"]');
3038 link
.siblings().removeClass(settings
.bullets_active_class
);
3039 link
.addClass(settings
.bullets_active_class
);
3042 self
.build_markup = function () {
3043 slides_container
.wrap('<div class="' + settings
.container_class
+ '"></div>');
3044 container
= slides_container
.parent();
3045 slides_container
.addClass(settings
.slides_container_class
);
3047 if (settings
.stack_on_small
) {
3048 container
.addClass(settings
.stack_on_small_class
);
3051 if (settings
.navigation_arrows
) {
3052 container
.append($('<a href="#"><span></span></a>').addClass(settings
.prev_class
));
3053 container
.append($('<a href="#"><span></span></a>').addClass(settings
.next_class
));
3056 if (settings
.timer
) {
3057 timer_container
= $('<div>').addClass(settings
.timer_container_class
);
3058 timer_container
.append('<span>');
3059 timer_container
.append($('<div>').addClass(settings
.timer_progress_class
));
3060 timer_container
.addClass(settings
.timer_paused_class
);
3061 container
.append(timer_container
);
3064 if (settings
.slide_number
) {
3065 number_container
= $('<div>').addClass(settings
.slide_number_class
);
3066 number_container
.append('<span></span> ' + settings
.slide_number_text
+ ' <span></span>');
3067 container
.append(number_container
);
3070 if (settings
.bullets
) {
3071 bullets_container
= $('<ol>').addClass(settings
.bullets_container_class
);
3072 container
.append(bullets_container
);
3073 bullets_container
.wrap('<div class="orbit-bullets-container"></div>');
3074 self
.slides().each(function (idx
, el
) {
3075 var bullet
= $('<li>').attr('data-orbit-slide', idx
).on('click', self
.link_bullet
);
3077 bullets_container
.append(bullet
);
3083 self
._goto = function (next_idx
, start_timer
) {
3084 // if (locked) {return false;}
3085 if (next_idx
=== idx
) {
3088 if (typeof timer
=== 'object') {
3091 var slides
= self
.slides();
3095 if (next_idx
< idx
) {
3098 if (next_idx
>= slides
.length
) {
3099 if (!settings
.circular
) return false;
3101 } else if (next_idx
< 0) {
3102 if (!settings
.circular
) return false;
3103 next_idx
= slides
.length
- 1;
3106 var current
= $(slides
.get(idx
));
3107 var next
= $(slides
.get(next_idx
));
3109 current
.css('zIndex', 2);
3110 current
.removeClass(settings
.active_slide_class
);
3111 next
.css('zIndex', 4).addClass(settings
.active_slide_class
);
3113 slides_container
.trigger('before-slide-change.fndtn.orbit');
3114 settings
.before_slide_change();
3115 self
.update_active_link(next_idx
);
3117 var callback = function () {
3118 var unlock = function () {
3121 if (start_timer
=== true) {
3122 timer
= self
.create_timer();
3125 self
.update_slide_number(idx
);
3126 slides_container
.trigger('after-slide-change.fndtn.orbit', [{
3128 total_slides
: slides
.length
3130 settings
.after_slide_change(idx
, slides
.length
);
3132 if (slides_container
.height() != next
.height() && settings
.variable_height
) {
3133 slides_container
.animate({'height': next
.height()}, 250, 'linear', unlock
);
3139 if (slides
.length
=== 1) {
3144 var start_animation = function () {
3145 if (dir
=== 'next') {
3146 animate
.next(current
, next
, callback
);
3148 if (dir
=== 'prev') {
3149 animate
.prev(current
, next
, callback
);
3153 if (next
.height() > slides_container
.height() && settings
.variable_height
) {
3154 slides_container
.animate({'height': next
.height()}, 250, 'linear', start_animation
);
3160 self
.next = function (e
) {
3161 e
.stopImmediatePropagation();
3163 self
._goto(idx
+ 1);
3166 self
.prev = function (e
) {
3167 e
.stopImmediatePropagation();
3169 self
._goto(idx
- 1);
3172 self
.link_custom = function (e
) {
3174 var link
= $(this).attr('data-orbit-link');
3175 if ((typeof link
=== 'string') && (link
= $.trim(link
)) != '') {
3176 var slide
= container
.find('[data-orbit-slide=' + link
+ ']');
3177 if (slide
.index() != -1) {
3178 self
._goto(slide
.index());
3183 self
.link_bullet = function (e
) {
3184 var index
= $(this).attr('data-orbit-slide');
3185 if ((typeof index
=== 'string') && (index
= $.trim(index
)) != '') {
3186 if (isNaN(parseInt(index
))) {
3187 var slide
= container
.find('[data-orbit-slide=' + index
+ ']');
3188 if (slide
.index() != -1) {
3189 self
._goto(slide
.index() + 1);
3193 self
._goto(parseInt(index
));
3199 self
.timer_callback = function () {
3200 self
._goto(idx
+ 1, true);
3203 self
.compute_dimensions = function () {
3204 var current
= $(self
.slides().get(idx
));
3205 var h
= current
.height();
3206 if (!settings
.variable_height
) {
3207 self
.slides().each(function () {
3208 if ($(this).height() > h
) {
3209 h
= $(this).height();
3213 slides_container
.height(h
);
3216 self
.create_timer = function () {
3218 container
.find('.' + settings
.timer_container_class
),
3225 self
.stop_timer = function () {
3226 if (typeof timer
=== 'object') timer
.stop();
3229 self
.toggle_timer = function () {
3230 var t
= container
.find('.' + settings
.timer_container_class
);
3231 if (t
.hasClass(settings
.timer_paused_class
)) {
3232 if (typeof timer
=== 'undefined') {
3233 timer
= self
.create_timer();
3238 if (typeof timer
=== 'object') {
3244 self
.init = function () {
3245 self
.build_markup();
3246 if (settings
.timer
) {
3247 timer
= self
.create_timer();
3248 Foundation
.utils
.image_loaded(this.slides().children('img'), timer
.start
);
3250 animate
= new FadeAnimation(settings
, slides_container
);
3251 if (settings
.animation
=== 'slide')
3252 animate
= new SlideAnimation(settings
, slides_container
);
3254 container
.on('click', '.' + settings
.next_class
, self
.next
);
3255 container
.on('click', '.' + settings
.prev_class
, self
.prev
);
3257 if (settings
.next_on_click
) {
3258 container
.on('click', '.' + settings
.slides_container_class
+ ' [data-orbit-slide]', self
.link_bullet
);
3261 container
.on('click', self
.toggle_timer
);
3262 if (settings
.swipe
) {
3263 container
.on('touchstart.fndtn.orbit', function (e
) {
3265 e
= e
.originalEvent
;
3268 start_page_x
: e
.touches
[0].pageX
,
3269 start_page_y
: e
.touches
[0].pageY
,
3270 start_time
: (new Date()).getTime(),
3272 is_scrolling
: undefined
3274 container
.data('swipe-transition', data
);
3275 e
.stopPropagation();
3277 .on('touchmove.fndtn.orbit', function (e
) {
3279 e
= e
.originalEvent
;
3281 // Ignore pinch/zoom events
3282 if (e
.touches
.length
> 1 || e
.scale
&& e
.scale
!== 1) return;
3284 var data
= container
.data('swipe-transition');
3285 if (typeof data
=== 'undefined') {
3289 data
.delta_x
= e
.touches
[0].pageX
- data
.start_page_x
;
3291 if (typeof data
.is_scrolling
=== 'undefined') {
3292 data
.is_scrolling
= !!( data
.is_scrolling
|| Math
.abs(data
.delta_x
) < Math
.abs(e
.touches
[0].pageY
- data
.start_page_y
) );
3295 if (!data
.is_scrolling
&& !data
.active
) {
3297 var direction
= (data
.delta_x
< 0) ? (idx
+ 1) : (idx
- 1);
3299 self
._goto(direction
);
3302 .on('touchend.fndtn.orbit', function (e
) {
3303 container
.data('swipe-transition', {});
3304 e
.stopPropagation();
3307 container
.on('mouseenter.fndtn.orbit', function (e
) {
3308 if (settings
.timer
&& settings
.pause_on_hover
) {
3312 .on('mouseleave.fndtn.orbit', function (e
) {
3313 if (settings
.timer
&& settings
.resume_on_mouseout
) {
3318 $(document
).on('click', '[data-orbit-link]', self
.link_custom
);
3319 $(window
).on('load resize', self
.compute_dimensions
);
3320 Foundation
.utils
.image_loaded(this.slides().children('img'), self
.compute_dimensions
);
3321 Foundation
.utils
.image_loaded(this.slides().children('img'), function () {
3322 container
.prev('.' + settings
.preloader_class
).css('display', 'none');
3323 self
.update_slide_number(0);
3324 self
.update_active_link(0);
3325 slides_container
.trigger('ready.fndtn.orbit');
3332 var Timer = function (el
, settings
, callback
) {
3334 duration
= settings
.timer_speed
,
3335 progress
= el
.find('.' + settings
.timer_progress_class
),
3340 this.update_progress = function (w
) {
3341 var new_progress
= progress
.clone();
3342 new_progress
.attr('style', '');
3343 new_progress
.css('width', w
+ '%');
3344 progress
.replaceWith(new_progress
);
3345 progress
= new_progress
;
3348 this.restart = function () {
3349 clearTimeout(timeout
);
3350 el
.addClass(settings
.timer_paused_class
);
3352 self
.update_progress(0);
3355 this.start = function () {
3356 if (!el
.hasClass(settings
.timer_paused_class
)) {
3359 left
= (left
=== -1) ? duration
: left
;
3360 el
.removeClass(settings
.timer_paused_class
);
3361 start
= new Date().getTime();
3362 progress
.animate({'width': '100%'}, left
, 'linear');
3363 timeout
= setTimeout(function () {
3367 el
.trigger('timer-started.fndtn.orbit')
3370 this.stop = function () {
3371 if (el
.hasClass(settings
.timer_paused_class
)) {
3374 clearTimeout(timeout
);
3375 el
.addClass(settings
.timer_paused_class
);
3376 var end
= new Date().getTime();
3377 left
= left
- (end
- start
);
3378 var w
= 100 - ((left
/ duration
) * 100);
3379 self
.update_progress(w
);
3380 el
.trigger('timer-stopped.fndtn.orbit');
3384 var SlideAnimation = function (settings
, container
) {
3385 var duration
= settings
.animation_speed
;
3386 var is_rtl
= ($('html[dir=rtl]').length
=== 1);
3387 var margin
= is_rtl
? 'marginRight' : 'marginLeft';
3388 var animMargin
= {};
3389 animMargin
[margin
] = '0%';
3391 this.next = function (current
, next
, callback
) {
3392 current
.animate({marginLeft
: '-100%'}, duration
);
3393 next
.animate(animMargin
, duration
, function () {
3394 current
.css(margin
, '100%');
3399 this.prev = function (current
, prev
, callback
) {
3400 current
.animate({marginLeft
: '100%'}, duration
);
3401 prev
.css(margin
, '-100%');
3402 prev
.animate(animMargin
, duration
, function () {
3403 current
.css(margin
, '100%');
3409 var FadeAnimation = function (settings
, container
) {
3410 var duration
= settings
.animation_speed
;
3411 var is_rtl
= ($('html[dir=rtl]').length
=== 1);
3412 var margin
= is_rtl
? 'marginRight' : 'marginLeft';
3414 this.next = function (current
, next
, callback
) {
3415 next
.css({'margin': '0%', 'opacity': '0.01'});
3416 next
.animate({'opacity': '1'}, duration
, 'linear', function () {
3417 current
.css('margin', '100%');
3422 this.prev = function (current
, prev
, callback
) {
3423 prev
.css({'margin': '0%', 'opacity': '0.01'});
3424 prev
.animate({'opacity': '1'}, duration
, 'linear', function () {
3425 current
.css('margin', '100%');
3432 Foundation
.libs
= Foundation
.libs
|| {};
3434 Foundation
.libs
.orbit
= {
3442 pause_on_hover
: true,
3443 resume_on_mouseout
: false,
3444 next_on_click
: true,
3445 animation_speed
: 500,
3446 stack_on_small
: false,
3447 navigation_arrows
: true,
3449 slide_number_text
: 'of',
3450 container_class
: 'orbit-container',
3451 stack_on_small_class
: 'orbit-stack-on-small',
3452 next_class
: 'orbit-next',
3453 prev_class
: 'orbit-prev',
3454 timer_container_class
: 'orbit-timer',
3455 timer_paused_class
: 'paused',
3456 timer_progress_class
: 'orbit-progress',
3457 slides_container_class
: 'orbit-slides-container',
3458 preloader_class
: 'preloader',
3459 slide_selector
: '*',
3460 bullets_container_class
: 'orbit-bullets',
3461 bullets_active_class
: 'active',
3462 slide_number_class
: 'orbit-slide-number',
3463 caption_class
: 'orbit-caption',
3464 active_slide_class
: 'active',
3465 orbit_transition_class
: 'orbit-transitioning',
3469 variable_height
: false,
3471 before_slide_change
: noop
,
3472 after_slide_change
: noop
3475 init: function (scope
, method
, options
) {
3477 this.bindings(method
, options
);
3480 events: function (instance
) {
3481 var orbit_instance
= new Orbit(this.S(instance
), this.S(instance
).data('orbit-init'));
3482 this.S(instance
).data(this.name
+ '-instance', orbit_instance
);
3485 reflow: function () {
3488 if (self
.S(self
.scope
).is('[data-orbit]')) {
3489 var $el
= self
.S(self
.scope
);
3490 var instance
= $el
.data(self
.name
+ '-instance');
3491 instance
.compute_dimensions();
3493 self
.S('[data-orbit]', self
.scope
).each(function (idx
, el
) {
3494 var $el
= self
.S(el
);
3495 var opts
= self
.data_options($el
);
3496 var instance
= $el
.data(self
.name
+ '-instance');
3497 instance
.compute_dimensions();
3504 }(jQuery
, window
, window
.document
));
3506 (function ($, window
, document
, undefined) {
3509 Foundation
.libs
.offcanvas
= {
3515 open_method
: 'move',
3516 close_on_click
: false
3519 init: function (scope
, method
, options
) {
3520 this.bindings(method
, options
);
3523 events: function () {
3530 if (this.settings
.open_method
=== 'move') {
3531 move_class
= 'move-';
3532 right_postfix
= 'right';
3533 left_postfix
= 'left';
3534 } else if (this.settings
.open_method
=== 'overlap_single') {
3535 move_class
= 'offcanvas-overlap-';
3536 right_postfix
= 'right';
3537 left_postfix
= 'left';
3538 } else if (this.settings
.open_method
=== 'overlap') {
3539 move_class
= 'offcanvas-overlap';
3542 S(this.scope
).off('.offcanvas')
3543 .on('click.fndtn.offcanvas', '.left-off-canvas-toggle', function (e
) {
3544 self
.click_toggle_class(e
, move_class
+ right_postfix
);
3545 if (self
.settings
.open_method
!== 'overlap') {
3546 S('.left-submenu').removeClass(move_class
+ right_postfix
);
3548 $('.left-off-canvas-toggle').attr('aria-expanded', 'true');
3550 .on('click.fndtn.offcanvas', '.left-off-canvas-menu a', function (e
) {
3551 var settings
= self
.get_settings(e
);
3552 var parent
= S(this).parent();
3554 if (settings
.close_on_click
&& !parent
.hasClass('has-submenu') && !parent
.hasClass('back')) {
3555 self
.hide
.call(self
, move_class
+ right_postfix
, self
.get_wrapper(e
));
3556 parent
.parent().removeClass(move_class
+ right_postfix
);
3557 } else if (S(this).parent().hasClass('has-submenu')) {
3559 S(this).siblings('.left-submenu').toggleClass(move_class
+ right_postfix
);
3560 } else if (parent
.hasClass('back')) {
3562 parent
.parent().removeClass(move_class
+ right_postfix
);
3564 $('.left-off-canvas-toggle').attr('aria-expanded', 'true');
3566 .on('click.fndtn.offcanvas', '.right-off-canvas-toggle', function (e
) {
3567 self
.click_toggle_class(e
, move_class
+ left_postfix
);
3568 if (self
.settings
.open_method
!== 'overlap') {
3569 S('.right-submenu').removeClass(move_class
+ left_postfix
);
3571 $('.right-off-canvas-toggle').attr('aria-expanded', 'true');
3573 .on('click.fndtn.offcanvas', '.right-off-canvas-menu a', function (e
) {
3574 var settings
= self
.get_settings(e
);
3575 var parent
= S(this).parent();
3577 if (settings
.close_on_click
&& !parent
.hasClass('has-submenu') && !parent
.hasClass('back')) {
3578 self
.hide
.call(self
, move_class
+ left_postfix
, self
.get_wrapper(e
));
3579 parent
.parent().removeClass(move_class
+ left_postfix
);
3580 } else if (S(this).parent().hasClass('has-submenu')) {
3582 S(this).siblings('.right-submenu').toggleClass(move_class
+ left_postfix
);
3583 } else if (parent
.hasClass('back')) {
3585 parent
.parent().removeClass(move_class
+ left_postfix
);
3587 $('.right-off-canvas-toggle').attr('aria-expanded', 'true');
3589 .on('click.fndtn.offcanvas', '.exit-off-canvas', function (e
) {
3590 self
.click_remove_class(e
, move_class
+ left_postfix
);
3591 S('.right-submenu').removeClass(move_class
+ left_postfix
);
3592 if (right_postfix
) {
3593 self
.click_remove_class(e
, move_class
+ right_postfix
);
3594 S('.left-submenu').removeClass(move_class
+ left_postfix
);
3596 $('.right-off-canvas-toggle').attr('aria-expanded', 'true');
3598 .on('click.fndtn.offcanvas', '.exit-off-canvas', function (e
) {
3599 self
.click_remove_class(e
, move_class
+ left_postfix
);
3600 $('.left-off-canvas-toggle').attr('aria-expanded', 'false');
3601 if (right_postfix
) {
3602 self
.click_remove_class(e
, move_class
+ right_postfix
);
3603 $('.right-off-canvas-toggle').attr('aria-expanded', 'false');
3608 toggle: function (class_name
, $off_canvas
) {
3609 $off_canvas
= $off_canvas
|| this.get_wrapper();
3610 if ($off_canvas
.is('.' + class_name
)) {
3611 this.hide(class_name
, $off_canvas
);
3613 this.show(class_name
, $off_canvas
);
3617 show: function (class_name
, $off_canvas
) {
3618 $off_canvas
= $off_canvas
|| this.get_wrapper();
3619 $off_canvas
.trigger('open').trigger('open.fndtn.offcanvas');
3620 $off_canvas
.addClass(class_name
);
3623 hide: function (class_name
, $off_canvas
) {
3624 $off_canvas
= $off_canvas
|| this.get_wrapper();
3625 $off_canvas
.trigger('close').trigger('close.fndtn.offcanvas');
3626 $off_canvas
.removeClass(class_name
);
3629 click_toggle_class: function (e
, class_name
) {
3631 var $off_canvas
= this.get_wrapper(e
);
3632 this.toggle(class_name
, $off_canvas
);
3635 click_remove_class: function (e
, class_name
) {
3637 var $off_canvas
= this.get_wrapper(e
);
3638 this.hide(class_name
, $off_canvas
);
3641 get_settings: function (e
) {
3642 var offcanvas
= this.S(e
.target
).closest('[' + this.attr_name() + ']');
3643 return offcanvas
.data(this.attr_name(true) + '-init') || this.settings
;
3646 get_wrapper: function (e
) {
3647 var $off_canvas
= this.S(e
? e
.target
: this.scope
).closest('.off-canvas-wrap');
3649 if ($off_canvas
.length
=== 0) {
3650 $off_canvas
= this.S('.off-canvas-wrap');
3655 reflow: function () {
3658 }(jQuery
, window
, window
.document
));
3660 (function ($, window
, document
, undefined) {
3663 Foundation
.libs
.alert
= {
3669 callback: function () {
3673 init: function (scope
, method
, options
) {
3674 this.bindings(method
, options
);
3677 events: function () {
3681 $(this.scope
).off('.alert').on('click.fndtn.alert', '[' + this.attr_name() + '] .close', function (e
) {
3682 var alertBox
= S(this).closest('[' + self
.attr_name() + ']'),
3683 settings
= alertBox
.data(self
.attr_name(true) + '-init') || self
.settings
;
3686 if (Modernizr
.csstransitions
) {
3687 alertBox
.addClass('alert-close');
3688 alertBox
.on('transitionend webkitTransitionEnd oTransitionEnd', function (e
) {
3689 S(this).trigger('close').trigger('close.fndtn.alert').remove();
3690 settings
.callback();
3693 alertBox
.fadeOut(300, function () {
3694 S(this).trigger('close').trigger('close.fndtn.alert').remove();
3695 settings
.callback();
3701 reflow: function () {
3704 }(jQuery
, window
, window
.document
));
3706 (function ($, window
, document
, undefined) {
3709 Foundation
.libs
.reveal
= {
3717 animation
: 'fadeAndPop',
3718 animation_speed
: 250,
3719 close_on_background_click
: true,
3721 dismiss_modal_class
: 'close-reveal-modal',
3722 bg_class
: 'reveal-modal-bg',
3723 bg_root_element
: 'body',
3724 root_element
: 'body',
3727 opened: function () {
3729 close: function () {
3731 closed: function () {
3733 bg
: $('.reveal-modal-bg'),
3737 'visibility': 'visible',
3742 'visibility': 'hidden',
3748 init: function (scope
, method
, options
) {
3749 $.extend(true, this.settings
, method
, options
);
3750 this.bindings(method
, options
);
3753 events: function (scope
) {
3759 .on('click.fndtn.reveal', '[' + this.add_namespace('data-reveal-id') + ']:not([disabled])', function (e
) {
3763 var element
= S(this),
3764 ajax
= element
.data(self
.data_attr('reveal-ajax'));
3768 if (typeof ajax
=== 'undefined') {
3769 self
.open
.call(self
, element
);
3771 var url
= ajax
=== true ? element
.attr('href') : ajax
;
3773 self
.open
.call(self
, element
, {url
: url
});
3779 .on('click.fndtn.reveal', this.close_targets(), function (e
) {
3784 var settings
= S('[' + self
.attr_name() + '].open').data(self
.attr_name(true) + '-init') || self
.settings
,
3785 bg_clicked
= S(e
.target
)[0] === S('.' + settings
.bg_class
)[0];
3788 if (settings
.close_on_background_click
) {
3789 e
.stopPropagation();
3796 self
.close
.call(self
, bg_clicked
? S('[' + self
.attr_name() + '].open') : S(this).closest('[' + self
.attr_name() + ']'));
3800 if (S('[' + self
.attr_name() + ']', this.scope
).length
> 0) {
3803 .on('open.fndtn.reveal', this.settings
.open
)
3804 .on('opened.fndtn.reveal', this.settings
.opened
)
3805 .on('opened.fndtn.reveal', this.open_video
)
3806 .on('close.fndtn.reveal', this.settings
.close
)
3807 .on('closed.fndtn.reveal', this.settings
.closed
)
3808 .on('closed.fndtn.reveal', this.close_video
);
3812 .on('open.fndtn.reveal', '[' + self
.attr_name() + ']', this.settings
.open
)
3813 .on('opened.fndtn.reveal', '[' + self
.attr_name() + ']', this.settings
.opened
)
3814 .on('opened.fndtn.reveal', '[' + self
.attr_name() + ']', this.open_video
)
3815 .on('close.fndtn.reveal', '[' + self
.attr_name() + ']', this.settings
.close
)
3816 .on('closed.fndtn.reveal', '[' + self
.attr_name() + ']', this.settings
.closed
)
3817 .on('closed.fndtn.reveal', '[' + self
.attr_name() + ']', this.close_video
);
3823 // PATCH #3: turning on key up capture only when a reveal window is open
3824 key_up_on: function (scope
) {
3827 // PATCH #1: fixing multiple keyup event trigger from single key press
3828 self
.S('body').off('keyup.fndtn.reveal').on('keyup.fndtn.reveal', function (event
) {
3829 var open_modal
= self
.S('[' + self
.attr_name() + '].open'),
3830 settings
= open_modal
.data(self
.attr_name(true) + '-init') || self
.settings
;
3831 // PATCH #2: making sure that the close event can be called only while unlocked,
3832 // so that multiple keyup.fndtn.reveal events don't prevent clean closing of the reveal window.
3833 if (settings
&& event
.which
=== 27 && settings
.close_on_esc
&& !self
.locked
) { // 27 is the keycode for the Escape key
3834 self
.close
.call(self
, open_modal
);
3841 // PATCH #3: turning on key up capture only when a reveal window is open
3842 key_up_off: function (scope
) {
3843 this.S('body').off('keyup.fndtn.reveal');
3848 open: function (target
, ajax_settings
) {
3853 if (typeof target
.selector
!== 'undefined') {
3854 // Find the named node; only use the first one found, since the rest of the code assumes there's only one node
3855 modal
= self
.S('#' + target
.data(self
.data_attr('reveal-id'))).first();
3857 modal
= self
.S(this.scope
);
3859 ajax_settings
= target
;
3862 modal
= self
.S(this.scope
);
3865 var settings
= modal
.data(self
.attr_name(true) + '-init');
3866 settings
= settings
|| this.settings
;
3869 if (modal
.hasClass('open') && target
.attr('data-reveal-id') == modal
.attr('id')) {
3870 return self
.close(modal
);
3873 if (!modal
.hasClass('open')) {
3874 var open_modal
= self
.S('[' + self
.attr_name() + '].open');
3876 if (typeof modal
.data('css-top') === 'undefined') {
3877 modal
.data('css-top', parseInt(modal
.css('top'), 10))
3878 .data('offset', this.cache_offset(modal
));
3881 this.key_up_on(modal
); // PATCH #3: turning on key up capture only when a reveal window is open
3882 modal
.trigger('open').trigger('open.fndtn.reveal');
3884 if (open_modal
.length
< 1) {
3885 this.toggle_bg(modal
, true);
3888 if (typeof ajax_settings
=== 'string') {
3894 if (typeof ajax_settings
=== 'undefined' || !ajax_settings
.url
) {
3895 if (open_modal
.length
> 0) {
3896 this.hide(open_modal
, settings
.css
.close
);
3899 this.show(modal
, settings
.css
.open
);
3901 var old_success
= typeof ajax_settings
.success
!== 'undefined' ? ajax_settings
.success
: null;
3903 $.extend(ajax_settings
, {
3904 success: function (data
, textStatus
, jqXHR
) {
3905 if ($.isFunction(old_success
)) {
3906 var result
= old_success(data
, textStatus
, jqXHR
);
3907 if (typeof result
== 'string') data
= result
;
3911 self
.S(modal
).foundation('section', 'reflow');
3912 self
.S(modal
).children().foundation();
3914 if (open_modal
.length
> 0) {
3915 self
.hide(open_modal
, settings
.css
.close
);
3917 self
.show(modal
, settings
.css
.open
);
3921 $.ajax(ajax_settings
);
3924 self
.S(window
).trigger('resize');
3927 close: function (modal
) {
3928 var modal
= modal
&& modal
.length
? modal
: this.S(this.scope
),
3929 open_modals
= this.S('[' + this.attr_name() + '].open'),
3930 settings
= modal
.data(this.attr_name(true) + '-init') || this.settings
;
3932 if (open_modals
.length
> 0) {
3934 this.key_up_off(modal
); // PATCH #3: turning on key up capture only when a reveal window is open
3935 modal
.trigger('close').trigger('close.fndtn.reveal');
3936 this.toggle_bg(modal
, false);
3937 this.hide(open_modals
, settings
.css
.close
, settings
);
3941 close_targets: function () {
3942 var base
= '.' + this.settings
.dismiss_modal_class
;
3944 if (this.settings
.close_on_background_click
) {
3945 return base
+ ', .' + this.settings
.bg_class
;
3951 toggle_bg: function (el
, modal
, state
) {
3952 var settings
= el
.data(this.attr_name(true) + '-init') || this.settings
,
3953 bg_root_element
= settings
.bg_root_element
; // Adding option to specify the background root element fixes scrolling issue
3955 if (this.S('.' + this.settings
.bg_class
).length
=== 0) {
3956 this.settings
.bg
= $('<div />', {'class': this.settings
.bg_class
})
3957 .appendTo(bg_root_element
).hide();
3960 var visible
= this.settings
.bg
.filter(':visible').length
> 0;
3961 if (state
!= visible
) {
3962 if (state
== undefined ? visible
: !state
) {
3963 this.hide(this.settings
.bg
);
3965 this.show(this.settings
.bg
);
3970 show: function (el
, css
) {
3973 var settings
= el
.data(this.attr_name(true) + '-init') || this.settings
,
3974 root_element
= settings
.root_element
;
3976 if (el
.parent(root_element
).length
=== 0) {
3977 var placeholder
= el
.wrap('<div style="display: none;" />').parent();
3979 el
.on('closed.fndtn.reveal.wrapped', function () {
3980 el
.detach().appendTo(placeholder
);
3981 el
.unwrap().unbind('closed.fndtn.reveal.wrapped');
3984 el
.detach().appendTo(root_element
);
3987 var animData
= getAnimationData(settings
.animation
);
3988 if (!animData
.animate
) {
3989 this.locked
= false;
3992 css
.top
= $(root_element
).scrollTop() - el
.data('offset') + 'px'; //adding root_element instead of window for scrolling offset if modal trigger is below the fold
3994 top
: $(root_element
).scrollTop() + el
.data('css-top') + 'px', //adding root_element instead of window for scrolling offset if modal trigger is below the fold
3998 return setTimeout(function () {
4001 .animate(end_css
, settings
.animation_speed
, 'linear', function () {
4002 this.locked
= false;
4003 el
.trigger('opened').trigger('opened.fndtn.reveal');
4006 }.bind(this), settings
.animation_speed
/ 2);
4009 if (animData
.fade
) {
4010 css
.top
= $(root_element
).scrollTop() + el
.data('css-top') + 'px'; //adding root_element instead of window for scrolling offset if modal trigger is below the fold
4011 var end_css
= {opacity
: 1};
4013 return setTimeout(function () {
4016 .animate(end_css
, settings
.animation_speed
, 'linear', function () {
4017 this.locked
= false;
4018 el
.trigger('opened').trigger('opened.fndtn.reveal');
4021 }.bind(this), settings
.animation_speed
/ 2);
4024 return el
.css(css
).show().css({opacity
: 1}).addClass('open').trigger('opened').trigger('opened.fndtn.reveal');
4027 var settings
= this.settings
;
4029 // should we animate the background?
4030 if (getAnimationData(settings
.animation
).fade
) {
4031 return el
.fadeIn(settings
.animation_speed
/ 2);
4034 this.locked
= false;
4039 hide: function (el
, css
) {
4042 var settings
= el
.data(this.attr_name(true) + '-init') || this.settings
,
4043 root_element
= settings
.root_element
;
4045 var animData
= getAnimationData(settings
.animation
);
4046 if (!animData
.animate
) {
4047 this.locked
= false;
4051 top
: -$(root_element
).scrollTop() - el
.data('offset') + 'px', //adding root_element instead of window for scrolling offset if modal trigger is below the fold
4055 return setTimeout(function () {
4057 .animate(end_css
, settings
.animation_speed
, 'linear', function () {
4058 this.locked
= false;
4059 el
.css(css
).trigger('closed').trigger('closed.fndtn.reveal');
4061 .removeClass('open');
4062 }.bind(this), settings
.animation_speed
/ 2);
4065 if (animData
.fade
) {
4066 var end_css
= {opacity
: 0};
4068 return setTimeout(function () {
4070 .animate(end_css
, settings
.animation_speed
, 'linear', function () {
4071 this.locked
= false;
4072 el
.css(css
).trigger('closed').trigger('closed.fndtn.reveal');
4074 .removeClass('open');
4075 }.bind(this), settings
.animation_speed
/ 2);
4078 return el
.hide().css(css
).removeClass('open').trigger('closed').trigger('closed.fndtn.reveal');
4081 var settings
= this.settings
;
4083 // should we animate the background?
4084 if (getAnimationData(settings
.animation
).fade
) {
4085 return el
.fadeOut(settings
.animation_speed
/ 2);
4091 close_video: function (e
) {
4092 var video
= $('.flex-video', e
.target
),
4093 iframe
= $('iframe', video
);
4095 if (iframe
.length
> 0) {
4096 iframe
.attr('data-src', iframe
[0].src
);
4097 iframe
.attr('src', iframe
.attr('src'));
4102 open_video: function (e
) {
4103 var video
= $('.flex-video', e
.target
),
4104 iframe
= video
.find('iframe');
4106 if (iframe
.length
> 0) {
4107 var data_src
= iframe
.attr('data-src');
4108 if (typeof data_src
=== 'string') {
4109 iframe
[0].src
= iframe
.attr('data-src');
4111 var src
= iframe
[0].src
;
4112 iframe
[0].src
= undefined;
4113 iframe
[0].src
= src
;
4119 data_attr: function (str
) {
4120 if (this.namespace.length
> 0) {
4121 return this.namespace + '-' + str
;
4127 cache_offset: function (modal
) {
4128 var offset
= modal
.show().height() + parseInt(modal
.css('top'), 10);
4136 $(this.scope
).off('.fndtn.reveal');
4139 reflow: function () {
4144 * getAnimationData('popAndFade') // {animate: true, pop: true, fade: true}
4145 * getAnimationData('fade') // {animate: true, pop: false, fade: true}
4146 * getAnimationData('pop') // {animate: true, pop: true, fade: false}
4147 * getAnimationData('foo') // {animate: false, pop: false, fade: false}
4148 * getAnimationData(null) // {animate: false, pop: false, fade: false}
4150 function getAnimationData(str
) {
4151 var fade
= /fade/i.test(str
);
4152 var pop
= /pop/i.test(str
);
4154 animate
: fade
|| pop
,
4159 }(jQuery
, window
, window
.document
));
4161 (function ($, window
, document
, undefined) {
4164 Foundation
.libs
.interchange
= {
4165 name
: 'interchange',
4171 images_loaded
: false,
4172 nodes_loaded
: false,
4175 load_attr
: 'interchange',
4178 'default': 'only screen',
4179 'small': Foundation
.media_queries
['small'],
4180 'small-only': Foundation
.media_queries
['small-only'],
4181 'medium': Foundation
.media_queries
['medium'],
4182 'medium-only': Foundation
.media_queries
['medium-only'],
4183 'large': Foundation
.media_queries
['large'],
4184 'large-only': Foundation
.media_queries
['large-only'],
4185 'xlarge': Foundation
.media_queries
['xlarge'],
4186 'xlarge-only': Foundation
.media_queries
['xlarge-only'],
4187 'xxlarge': Foundation
.media_queries
['xxlarge'],
4188 'landscape': 'only screen and (orientation: landscape)',
4189 'portrait': 'only screen and (orientation: portrait)',
4190 'retina': 'only screen and (-webkit-min-device-pixel-ratio: 2),' +
4191 'only screen and (min--moz-device-pixel-ratio: 2),' +
4192 'only screen and (-o-min-device-pixel-ratio: 2/1),' +
4193 'only screen and (min-device-pixel-ratio: 2),' +
4194 'only screen and (min-resolution: 192dpi),' +
4195 'only screen and (min-resolution: 2dppx)'
4199 replace: function (el
, path
, trigger
) {
4200 // The trigger argument, if called within the directive, fires
4201 // an event named after the directive on the element, passing
4202 // any parameters along to the event that you pass to trigger.
4204 // ex. trigger(), trigger([a, b, c]), or trigger(a, b, c)
4206 // This allows you to bind a callback like so:
4207 // $('#interchangeContainer').on('replace', function (e, a, b, c) {
4208 // console.log($(this).html(), a, b, c);
4211 if (/IMG/.test(el
[0].nodeName
)) {
4212 var orig_path
= el
[0].src
;
4214 if (new RegExp(path
, 'i').test(orig_path
)) return;
4218 return trigger(el
[0].src
);
4220 var last_path
= el
.data(this.data_attr
+ '-last-path'),
4223 if (last_path
== path
) return;
4225 if (/\.(gif|jpg|jpeg|tiff|png)([?#].*)?/i.test(path
)) {
4226 $(el
).css('background-image', 'url(' + path
+ ')');
4227 el
.data('interchange-last-path', path
);
4228 return trigger(path
);
4231 return $.get(path
, function (response
) {
4233 el
.data(self
.data_attr
+ '-last-path', path
);
4241 init: function (scope
, method
, options
) {
4242 Foundation
.inherit(this, 'throttle random_str');
4244 this.data_attr
= this.set_data_attr();
4245 $.extend(true, this.settings
, method
, options
);
4246 this.bindings(method
, options
);
4247 this.load('images');
4251 get_media_hash: function () {
4253 for (var queryName
in this.settings
.named_queries
) {
4254 mediaHash
+= matchMedia(this.settings
.named_queries
[queryName
]).matches
.toString();
4259 events: function () {
4260 var self
= this, prevMediaHash
;
4263 .off('.interchange')
4264 .on('resize.fndtn.interchange', self
.throttle(function () {
4265 var currMediaHash
= self
.get_media_hash();
4266 if (currMediaHash
!== prevMediaHash
) {
4269 prevMediaHash
= currMediaHash
;
4275 resize: function () {
4276 var cache
= this.cache
;
4278 if (!this.images_loaded
|| !this.nodes_loaded
) {
4279 setTimeout($.proxy(this.resize
, this), 50);
4283 for (var uuid
in cache
) {
4284 if (cache
.hasOwnProperty(uuid
)) {
4285 var passed
= this.results(uuid
, cache
[uuid
]);
4288 this.settings
.directives
[passed
4289 .scenario
[1]].call(this, passed
.el
, passed
.scenario
[0], function () {
4290 if (arguments
[0] instanceof Array
) {
4291 var args
= arguments
[0];
4293 var args
= Array
.prototype.slice
.call(arguments
, 0);
4296 passed
.el
.trigger(passed
.scenario
[1], args
);
4304 results: function (uuid
, scenarios
) {
4305 var count
= scenarios
.length
;
4308 var el
= this.S('[' + this.add_namespace('data-uuid') + '="' + uuid
+ '"]');
4311 var mq
, rule
= scenarios
[count
][2];
4312 if (this.settings
.named_queries
.hasOwnProperty(rule
)) {
4313 mq
= matchMedia(this.settings
.named_queries
[rule
]);
4315 mq
= matchMedia(rule
);
4318 return {el
: el
, scenario
: scenarios
[count
]};
4326 load: function (type
, force_update
) {
4327 if (typeof this['cached_' + type
] === 'undefined' || force_update
) {
4328 this['update_' + type
]();
4331 return this['cached_' + type
];
4334 update_images: function () {
4335 var images
= this.S('img[' + this.data_attr
+ ']'),
4336 count
= images
.length
,
4339 data_attr
= this.data_attr
;
4342 this.cached_images
= [];
4343 this.images_loaded
= (count
=== 0);
4348 var str
= images
[i
].getAttribute(data_attr
) || '';
4350 if (str
.length
> 0) {
4351 this.cached_images
.push(images
[i
]);
4355 if (loaded_count
=== count
) {
4356 this.images_loaded
= true;
4357 this.enhance('images');
4364 update_nodes: function () {
4365 var nodes
= this.S('[' + this.data_attr
+ ']').not('img'),
4366 count
= nodes
.length
,
4369 data_attr
= this.data_attr
;
4371 this.cached_nodes
= [];
4372 this.nodes_loaded
= (count
=== 0);
4377 var str
= nodes
[i
].getAttribute(data_attr
) || '';
4379 if (str
.length
> 0) {
4380 this.cached_nodes
.push(nodes
[i
]);
4383 if (loaded_count
=== count
) {
4384 this.nodes_loaded
= true;
4385 this.enhance('nodes');
4392 enhance: function (type
) {
4393 var i
= this['cached_' + type
].length
;
4396 this.object($(this['cached_' + type
][i
]));
4399 return $(window
).trigger('resize').trigger('resize.fndtn.interchange');
4402 convert_directive: function (directive
) {
4404 var trimmed
= this.trim(directive
);
4406 if (trimmed
.length
> 0) {
4413 parse_scenario: function (scenario
) {
4414 // This logic had to be made more complex since some users were using commas in the url path
4415 // So we cannot simply just split on a comma
4416 var directive_match
= scenario
[0].match(/(.+),\s*(\w+)\s*$/),
4417 media_query
= scenario
[1];
4419 if (directive_match
) {
4420 var path
= directive_match
[1],
4421 directive
= directive_match
[2];
4424 var cached_split
= scenario
[0].split(/,\s*$/),
4425 path
= cached_split
[0],
4429 return [this.trim(path
), this.convert_directive(directive
), this.trim(media_query
)];
4432 object: function (el
) {
4433 var raw_arr
= this.parse_data_attr(el
),
4439 var split
= raw_arr
[i
].split(/\((.*?)(\))$/);
4441 if (split
.length
> 1) {
4442 var params
= this.parse_scenario(split
);
4443 scenarios
.push(params
);
4448 return this.store(el
, scenarios
);
4451 store: function (el
, scenarios
) {
4452 var uuid
= this.random_str(),
4453 current_uuid
= el
.data(this.add_namespace('uuid', true));
4455 if (this.cache
[current_uuid
]) return this.cache
[current_uuid
];
4457 el
.attr(this.add_namespace('data-uuid'), uuid
);
4459 return this.cache
[uuid
] = scenarios
;
4462 trim: function (str
) {
4464 if (typeof str
=== 'string') {
4471 set_data_attr: function (init
) {
4473 if (this.namespace.length
> 0) {
4474 return this.namespace + '-' + this.settings
.load_attr
;
4477 return this.settings
.load_attr
;
4480 if (this.namespace.length
> 0) {
4481 return 'data-' + this.namespace + '-' + this.settings
.load_attr
;
4484 return 'data-' + this.settings
.load_attr
;
4487 parse_data_attr: function (el
) {
4488 var raw
= el
.attr(this.attr_name()).split(/\[(.*?)\]/),
4493 if (raw
[i
].replace(/[\W\d]+/, '').length
> 4) {
4494 output
.push(raw
[i
]);
4501 reflow: function () {
4502 this.load('images', true);
4503 this.load('nodes', true);
4508 }(jQuery
, window
, window
.document
));
4510 (function ($, window
, document
, undefined) {
4513 Foundation
.libs
['magellan-expedition'] = {
4514 name
: 'magellan-expedition',
4519 active_class
: 'active',
4520 threshold
: 0, // pixels from the top of the expedition for it to become fixes
4521 destination_threshold
: 20, // pixels from the top of destination for it to be considered active
4522 throttle_delay
: 30, // calculation throttling to increase framerate
4523 fixed_top
: 0, // top distance in pixels assigend to the fixed element on scroll
4524 offset_by_height
: true, // whether to offset the destination by the expedition height. Usually you want this to be true, unless your expedition is on the side.
4525 duration
: 700, // animation duration time
4526 easing
: 'swing' // animation easing
4529 init: function (scope
, method
, options
) {
4530 Foundation
.inherit(this, 'throttle');
4531 this.bindings(method
, options
);
4534 events: function () {
4537 settings
= self
.settings
;
4539 // initialize expedition offset
4540 self
.set_expedition_position();
4544 .on('click.fndtn.magellan', '[' + self
.add_namespace('data-magellan-arrival') + '] a[href^="#"]', function (e
) {
4546 var expedition
= $(this).closest('[' + self
.attr_name() + ']'),
4547 settings
= expedition
.data('magellan-expedition-init'),
4548 hash
= this.hash
.split('#').join(''),
4549 target
= $('a[name="' + hash
+ '"]');
4551 if (target
.length
=== 0) {
4552 target
= $('#' + hash
);
4557 // Account for expedition height if fixed position
4558 var scroll_top
= target
.offset().top
- settings
.destination_threshold
+ 1;
4559 if (settings
.offset_by_height
) {
4560 scroll_top
= scroll_top
- expedition
.outerHeight();
4563 $('html, body').stop().animate({
4564 'scrollTop': scroll_top
4565 }, settings
.duration
, settings
.easing
, function () {
4566 if (history
.pushState
) {
4567 history
.pushState(null, null, '#' + hash
);
4570 location
.hash
= '#' + hash
;
4574 .on('scroll.fndtn.magellan', self
.throttle(this.check_for_arrivals
.bind(this), settings
.throttle_delay
));
4577 .on('resize.fndtn.magellan', self
.throttle(this.set_expedition_position
.bind(this), settings
.throttle_delay
));
4580 check_for_arrivals: function () {
4582 self
.update_arrivals();
4583 self
.update_expedition_positions();
4586 set_expedition_position: function () {
4588 $('[' + this.attr_name() + '=fixed]', self
.scope
).each(function (idx
, el
) {
4589 var expedition
= $(this),
4590 settings
= expedition
.data('magellan-expedition-init'),
4591 styles
= expedition
.attr('styles'), // save styles
4592 top_offset
, fixed_top
;
4594 expedition
.attr('style', '');
4595 top_offset
= expedition
.offset().top
+ settings
.threshold
;
4597 //set fixed-top by attribute
4598 fixed_top
= parseInt(expedition
.data('magellan-fixed-top'));
4599 if (!isNaN(fixed_top
))
4600 self
.settings
.fixed_top
= fixed_top
;
4602 expedition
.data(self
.data_attr('magellan-top-offset'), top_offset
);
4603 expedition
.attr('style', styles
);
4607 update_expedition_positions: function () {
4609 window_top_offset
= $(window
).scrollTop();
4611 $('[' + this.attr_name() + '=fixed]', self
.scope
).each(function () {
4612 var expedition
= $(this),
4613 settings
= expedition
.data('magellan-expedition-init'),
4614 styles
= expedition
.attr('style'), // save styles
4615 top_offset
= expedition
.data('magellan-top-offset');
4617 //scroll to the top distance
4618 if (window_top_offset
+ self
.settings
.fixed_top
>= top_offset
) {
4619 // Placeholder allows height calculations to be consistent even when
4620 // appearing to switch between fixed/non-fixed placement
4621 var placeholder
= expedition
.prev('[' + self
.add_namespace('data-magellan-expedition-clone') + ']');
4622 if (placeholder
.length
=== 0) {
4623 placeholder
= expedition
.clone();
4624 placeholder
.removeAttr(self
.attr_name());
4625 placeholder
.attr(self
.add_namespace('data-magellan-expedition-clone'), '');
4626 expedition
.before(placeholder
);
4628 expedition
.css({position
: 'fixed', top
: settings
.fixed_top
}).addClass('fixed');
4630 expedition
.prev('[' + self
.add_namespace('data-magellan-expedition-clone') + ']').remove();
4631 expedition
.attr('style', styles
).css('position', '').css('top', '').removeClass('fixed');
4636 update_arrivals: function () {
4638 window_top_offset
= $(window
).scrollTop();
4640 $('[' + this.attr_name() + ']', self
.scope
).each(function () {
4641 var expedition
= $(this),
4642 settings
= expedition
.data(self
.attr_name(true) + '-init'),
4643 offsets
= self
.offsets(expedition
, window_top_offset
),
4644 arrivals
= expedition
.find('[' + self
.add_namespace('data-magellan-arrival') + ']'),
4645 active_item
= false;
4646 offsets
.each(function (idx
, item
) {
4647 if (item
.viewport_offset
>= item
.top_offset
) {
4648 var arrivals
= expedition
.find('[' + self
.add_namespace('data-magellan-arrival') + ']');
4649 arrivals
.not(item
.arrival
).removeClass(settings
.active_class
);
4650 item
.arrival
.addClass(settings
.active_class
);
4656 if (!active_item
) arrivals
.removeClass(settings
.active_class
);
4660 offsets: function (expedition
, window_offset
) {
4662 settings
= expedition
.data(self
.attr_name(true) + '-init'),
4663 viewport_offset
= window_offset
;
4665 return expedition
.find('[' + self
.add_namespace('data-magellan-arrival') + ']').map(function (idx
, el
) {
4666 var name
= $(this).data(self
.data_attr('magellan-arrival')),
4667 dest
= $('[' + self
.add_namespace('data-magellan-destination') + '=' + name
+ ']');
4668 if (dest
.length
> 0) {
4669 var top_offset
= dest
.offset().top
- settings
.destination_threshold
;
4670 if (settings
.offset_by_height
) {
4671 top_offset
= top_offset
- expedition
.outerHeight();
4673 top_offset
= Math
.floor(top_offset
);
4677 top_offset
: top_offset
,
4678 viewport_offset
: viewport_offset
4681 }).sort(function (a
, b
) {
4682 if (a
.top_offset
< b
.top_offset
) return -1;
4683 if (a
.top_offset
> b
.top_offset
) return 1;
4688 data_attr: function (str
) {
4689 if (this.namespace.length
> 0) {
4690 return this.namespace + '-' + str
;
4697 this.S(this.scope
).off('.magellan');
4698 this.S(window
).off('.magellan');
4701 reflow: function () {
4703 // remove placeholder expeditions used for height calculation purposes
4704 $('[' + self
.add_namespace('data-magellan-expedition-clone') + ']', self
.scope
).remove();
4707 }(jQuery
, window
, window
.document
));
4709 (function ($, window
, document
, undefined) {
4712 Foundation
.libs
.accordion
= {
4718 content_class
: 'content',
4719 active_class
: 'active',
4720 multi_expand
: false,
4722 callback: function () {
4726 init: function (scope
, method
, options
) {
4727 this.bindings(method
, options
);
4730 events: function () {
4734 .off('.fndtn.accordion')
4735 .on('click.fndtn.accordion', '[' + this.attr_name() + '] > .accordion-navigation > a', function (e
) {
4736 var accordion
= S(this).closest('[' + self
.attr_name() + ']'),
4737 groupSelector
= self
.attr_name() + '=' + accordion
.attr(self
.attr_name()),
4738 settings
= accordion
.data(self
.attr_name(true) + '-init') || self
.settings
,
4739 target
= S('#' + this.href
.split('#')[1]),
4740 aunts
= $('> .accordion-navigation', accordion
),
4741 siblings
= aunts
.children('.' + settings
.content_class
),
4742 active_content
= siblings
.filter('.' + settings
.active_class
);
4746 if (accordion
.attr(self
.attr_name())) {
4747 siblings
= siblings
.add('[' + groupSelector
+ '] dd > ' + '.' + settings
.content_class
);
4748 aunts
= aunts
.add('[' + groupSelector
+ '] .accordion-navigation');
4751 if (settings
.toggleable
&& target
.is(active_content
)) {
4752 target
.parent('.accordion-navigation').toggleClass(settings
.active_class
, false);
4753 target
.toggleClass(settings
.active_class
, false);
4754 settings
.callback(target
);
4755 target
.triggerHandler('toggled', [accordion
]);
4756 accordion
.triggerHandler('toggled', [target
]);
4760 if (!settings
.multi_expand
) {
4761 siblings
.removeClass(settings
.active_class
);
4762 aunts
.removeClass(settings
.active_class
);
4765 target
.addClass(settings
.active_class
).parent().addClass(settings
.active_class
);
4766 settings
.callback(target
);
4767 target
.triggerHandler('toggled', [accordion
]);
4768 accordion
.triggerHandler('toggled', [target
]);
4775 reflow: function () {
4778 }(jQuery
, window
, window
.document
));
4780 (function ($, window
, document
, undefined) {
4783 Foundation
.libs
.topbar
= {
4790 sticky_class
: 'sticky',
4791 custom_back_text
: true,
4793 mobile_show_parent_link
: true,
4795 scrolltop
: true, // jump to top when sticky nav menu toggle is clicked
4799 init: function (section
, method
, options
) {
4800 Foundation
.inherit(this, 'add_custom_rule register_media throttle');
4803 self
.register_media('topbar', 'foundation-mq-topbar');
4805 this.bindings(method
, options
);
4807 self
.S('[' + this.attr_name() + ']', this.scope
).each(function () {
4808 var topbar
= $(this),
4809 settings
= topbar
.data(self
.attr_name(true) + '-init'),
4810 section
= self
.S('section, .top-bar-section', this);
4811 topbar
.data('index', 0);
4812 var topbarContainer
= topbar
.parent();
4813 if (topbarContainer
.hasClass('fixed') || self
.is_sticky(topbar
, topbarContainer
, settings
)) {
4814 self
.settings
.sticky_class
= settings
.sticky_class
;
4815 self
.settings
.sticky_topbar
= topbar
;
4816 topbar
.data('height', topbarContainer
.outerHeight());
4817 topbar
.data('stickyoffset', topbarContainer
.offset().top
);
4819 topbar
.data('height', topbar
.outerHeight());
4822 if (!settings
.assembled
) {
4823 self
.assemble(topbar
);
4826 if (settings
.is_hover
) {
4827 self
.S('.has-dropdown', topbar
).addClass('not-click');
4829 self
.S('.has-dropdown', topbar
).removeClass('not-click');
4832 // Pad body when sticky (scrolled) or fixed.
4833 self
.add_custom_rule('.f-topbar-fixed { padding-top: ' + topbar
.data('height') + 'px }');
4835 if (topbarContainer
.hasClass('fixed')) {
4836 self
.S('body').addClass('f-topbar-fixed');
4842 is_sticky: function (topbar
, topbarContainer
, settings
) {
4843 var sticky
= topbarContainer
.hasClass(settings
.sticky_class
);
4845 if (sticky
&& settings
.sticky_on
=== 'all') {
4847 } else if (sticky
&& this.small() && settings
.sticky_on
=== 'small') {
4848 return (matchMedia(Foundation
.media_queries
.small
).matches
&& !matchMedia(Foundation
.media_queries
.medium
).matches
&& !matchMedia(Foundation
.media_queries
.large
).matches
);
4850 } else if (sticky
&& this.medium() && settings
.sticky_on
=== 'medium') {
4851 return (matchMedia(Foundation
.media_queries
.small
).matches
&& matchMedia(Foundation
.media_queries
.medium
).matches
&& !matchMedia(Foundation
.media_queries
.large
).matches
);
4853 } else if (sticky
&& this.large() && settings
.sticky_on
=== 'large') {
4854 return (matchMedia(Foundation
.media_queries
.small
).matches
&& matchMedia(Foundation
.media_queries
.medium
).matches
&&
4855 matchMedia(Foundation
.media_queries
.large
).matches
);
4862 toggle: function (toggleEl
) {
4867 topbar
= self
.S(toggleEl
).closest('[' + this.attr_name() + ']');
4869 topbar
= self
.S('[' + this.attr_name() + ']');
4872 var settings
= topbar
.data(this.attr_name(true) + '-init');
4874 var section
= self
.S('section, .top-bar-section', topbar
);
4876 if (self
.breakpoint()) {
4878 section
.css({left
: '0%'});
4879 $('>.name', section
).css({left
: '100%'});
4881 section
.css({right
: '0%'});
4882 $('>.name', section
).css({right
: '100%'});
4885 self
.S('li.moved', section
).removeClass('moved');
4886 topbar
.data('index', 0);
4889 .toggleClass('expanded')
4893 if (settings
.scrolltop
) {
4894 if (!topbar
.hasClass('expanded')) {
4895 if (topbar
.hasClass('fixed')) {
4896 topbar
.parent().addClass('fixed');
4897 topbar
.removeClass('fixed');
4898 self
.S('body').addClass('f-topbar-fixed');
4900 } else if (topbar
.parent().hasClass('fixed')) {
4901 if (settings
.scrolltop
) {
4902 topbar
.parent().removeClass('fixed');
4903 topbar
.addClass('fixed');
4904 self
.S('body').removeClass('f-topbar-fixed');
4906 window
.scrollTo(0, 0);
4908 topbar
.parent().removeClass('expanded');
4912 if (self
.is_sticky(topbar
, topbar
.parent(), settings
)) {
4913 topbar
.parent().addClass('fixed');
4916 if (topbar
.parent().hasClass('fixed')) {
4917 if (!topbar
.hasClass('expanded')) {
4918 topbar
.removeClass('fixed');
4919 topbar
.parent().removeClass('expanded');
4920 self
.update_sticky_positioning();
4922 topbar
.addClass('fixed');
4923 topbar
.parent().addClass('expanded');
4924 self
.S('body').addClass('f-topbar-fixed');
4932 events: function (bar
) {
4938 .on('click.fndtn.topbar', '[' + this.attr_name() + '] .toggle-topbar', function (e
) {
4942 .on('click.fndtn.topbar', '.top-bar .top-bar-section li a[href^="#"],[' + this.attr_name() + '] .top-bar-section li a[href^="#"]', function (e
) {
4943 var li
= $(this).closest('li');
4944 if (self
.breakpoint() && !li
.hasClass('back') && !li
.hasClass('has-dropdown')) {
4948 .on('click.fndtn.topbar', '[' + this.attr_name() + '] li.has-dropdown', function (e
) {
4950 target
= S(e
.target
),
4951 topbar
= li
.closest('[' + self
.attr_name() + ']'),
4952 settings
= topbar
.data(self
.attr_name(true) + '-init');
4954 if (target
.data('revealId')) {
4959 if (self
.breakpoint()) return;
4960 if (settings
.is_hover
&& !Modernizr
.touch
) return;
4962 e
.stopImmediatePropagation();
4964 if (li
.hasClass('hover')) {
4966 .removeClass('hover')
4968 .removeClass('hover');
4970 li
.parents('li.hover')
4971 .removeClass('hover');
4973 li
.addClass('hover');
4975 $(li
).siblings().removeClass('hover');
4977 if (target
[0].nodeName
=== 'A' && target
.parent().hasClass('has-dropdown')) {
4982 .on('click.fndtn.topbar', '[' + this.attr_name() + '] .has-dropdown>a', function (e
) {
4983 if (self
.breakpoint()) {
4987 var $this = S(this),
4988 topbar
= $this.closest('[' + self
.attr_name() + ']'),
4989 section
= topbar
.find('section, .top-bar-section'),
4990 dropdownHeight
= $this.next('.dropdown').outerHeight(),
4991 $selectedLi
= $this.closest('li');
4993 topbar
.data('index', topbar
.data('index') + 1);
4994 $selectedLi
.addClass('moved');
4997 section
.css({left
: -(100 * topbar
.data('index')) + '%'});
4998 section
.find('>.name').css({left
: 100 * topbar
.data('index') + '%'});
5000 section
.css({right
: -(100 * topbar
.data('index')) + '%'});
5001 section
.find('>.name').css({right
: 100 * topbar
.data('index') + '%'});
5004 topbar
.css('height', $this.siblings('ul').outerHeight(true) + topbar
.data('height'));
5008 S(window
).off('.topbar').on('resize.fndtn.topbar', self
.throttle(function () {
5009 self
.resize
.call(self
);
5010 }, 50)).trigger('resize').trigger('resize.fndtn.topbar').load(function () {
5011 // Ensure that the offset is calculated after all of the pages resources have loaded
5012 S(this).trigger('resize.fndtn.topbar');
5015 S('body').off('.topbar').on('click.fndtn.topbar', function (e
) {
5016 var parent
= S(e
.target
).closest('li').closest('li.hover');
5018 if (parent
.length
> 0) {
5022 S('[' + self
.attr_name() + '] li.hover').removeClass('hover');
5025 // Go up a level on Click
5026 S(this.scope
).on('click.fndtn.topbar', '[' + this.attr_name() + '] .has-dropdown .back', function (e
) {
5029 var $this = S(this),
5030 topbar
= $this.closest('[' + self
.attr_name() + ']'),
5031 section
= topbar
.find('section, .top-bar-section'),
5032 settings
= topbar
.data(self
.attr_name(true) + '-init'),
5033 $movedLi
= $this.closest('li.moved'),
5034 $previousLevelUl
= $movedLi
.parent();
5036 topbar
.data('index', topbar
.data('index') - 1);
5039 section
.css({left
: -(100 * topbar
.data('index')) + '%'});
5040 section
.find('>.name').css({left
: 100 * topbar
.data('index') + '%'});
5042 section
.css({right
: -(100 * topbar
.data('index')) + '%'});
5043 section
.find('>.name').css({right
: 100 * topbar
.data('index') + '%'});
5046 if (topbar
.data('index') === 0) {
5047 topbar
.css('height', '');
5049 topbar
.css('height', $previousLevelUl
.outerHeight(true) + topbar
.data('height'));
5052 setTimeout(function () {
5053 $movedLi
.removeClass('moved');
5057 // Show dropdown menus when their items are focused
5058 S(this.scope
).find('.dropdown a')
5059 .focus(function () {
5060 $(this).parents('.has-dropdown').addClass('hover');
5063 $(this).parents('.has-dropdown').removeClass('hover');
5067 resize: function () {
5069 self
.S('[' + this.attr_name() + ']').each(function () {
5070 var topbar
= self
.S(this),
5071 settings
= topbar
.data(self
.attr_name(true) + '-init');
5073 var stickyContainer
= topbar
.parent('.' + self
.settings
.sticky_class
);
5076 if (!self
.breakpoint()) {
5077 var doToggle
= topbar
.hasClass('expanded');
5080 .removeClass('expanded')
5082 .removeClass('hover');
5085 self
.toggle(topbar
);
5089 if (self
.is_sticky(topbar
, stickyContainer
, settings
)) {
5090 if (stickyContainer
.hasClass('fixed')) {
5091 // Remove the fixed to allow for correct calculation of the offset.
5092 stickyContainer
.removeClass('fixed');
5094 stickyOffset
= stickyContainer
.offset().top
;
5095 if (self
.S(document
.body
).hasClass('f-topbar-fixed')) {
5096 stickyOffset
-= topbar
.data('height');
5099 topbar
.data('stickyoffset', stickyOffset
);
5100 stickyContainer
.addClass('fixed');
5102 stickyOffset
= stickyContainer
.offset().top
;
5103 topbar
.data('stickyoffset', stickyOffset
);
5110 breakpoint: function () {
5111 return !matchMedia(Foundation
.media_queries
['topbar']).matches
;
5114 small: function () {
5115 return matchMedia(Foundation
.media_queries
['small']).matches
;
5118 medium: function () {
5119 return matchMedia(Foundation
.media_queries
['medium']).matches
;
5122 large: function () {
5123 return matchMedia(Foundation
.media_queries
['large']).matches
;
5126 assemble: function (topbar
) {
5128 settings
= topbar
.data(this.attr_name(true) + '-init'),
5129 section
= self
.S('section, .top-bar-section', topbar
);
5131 // Pull element out of the DOM for manipulation
5134 self
.S('.has-dropdown>a', section
).each(function () {
5135 var $link
= self
.S(this),
5136 $dropdown
= $link
.siblings('.dropdown'),
5137 url
= $link
.attr('href'),
5141 if (!$dropdown
.find('.title.back').length
) {
5143 if (settings
.mobile_show_parent_link
== true && url
) {
5144 $titleLi
= $('<li class="title back js-generated"><h5><a href="javascript:void(0)"></a></h5></li><li class="parent-link show-for-small-only"><a class="parent-link js-generated" href="' + url
+ '">' + $link
.html() + '</a></li>');
5146 $titleLi
= $('<li class="title back js-generated"><h5><a href="javascript:void(0)"></a></h5>');
5149 // Copy link to subnav
5150 if (settings
.custom_back_text
== true) {
5151 $('h5>a', $titleLi
).html(settings
.back_text
);
5153 $('h5>a', $titleLi
).html('« ' + $link
.html());
5155 $dropdown
.prepend($titleLi
);
5159 // Put element back in the DOM
5160 section
.appendTo(topbar
);
5165 this.assembled(topbar
);
5168 assembled: function (topbar
) {
5169 topbar
.data(this.attr_name(true), $.extend({}, topbar
.data(this.attr_name(true)), {assembled
: true}));
5172 height: function (ul
) {
5176 $('> li', ul
).each(function () {
5177 total
+= self
.S(this).outerHeight(true);
5183 sticky: function () {
5186 this.S(window
).on('scroll', function () {
5187 self
.update_sticky_positioning();
5191 update_sticky_positioning: function () {
5192 var klass
= '.' + this.settings
.sticky_class
,
5193 $window
= this.S(window
),
5196 if (self
.settings
.sticky_topbar
&& self
.is_sticky(this.settings
.sticky_topbar
, this.settings
.sticky_topbar
.parent(), this.settings
)) {
5197 var distance
= this.settings
.sticky_topbar
.data('stickyoffset');
5198 if (!self
.S(klass
).hasClass('expanded')) {
5199 if ($window
.scrollTop() > (distance
)) {
5200 if (!self
.S(klass
).hasClass('fixed')) {
5201 self
.S(klass
).addClass('fixed');
5202 self
.S('body').addClass('f-topbar-fixed');
5204 } else if ($window
.scrollTop() <= distance
) {
5205 if (self
.S(klass
).hasClass('fixed')) {
5206 self
.S(klass
).removeClass('fixed');
5207 self
.S('body').removeClass('f-topbar-fixed');
5215 this.S(this.scope
).off('.fndtn.topbar');
5216 this.S(window
).off('.fndtn.topbar');
5219 reflow: function () {
5222 }(jQuery
, window
, window
.document
));
5224 (function ($, window
, document
, undefined) {
5227 Foundation
.libs
.tab
= {
5233 active_class
: 'active',
5234 callback: function () {
5236 deep_linking
: false,
5237 scroll_to_content
: true,
5241 default_tab_hashes
: [],
5243 init: function (scope
, method
, options
) {
5247 this.bindings(method
, options
);
5248 this.handle_location_hash_change();
5250 // Store the default active tabs which will be referenced when the
5251 // location hash is absent, as in the case of navigating the tabs and
5252 // returning to the first viewing via the browser Back button.
5253 S('[' + this.attr_name() + '] > .active > a', this.scope
).each(function () {
5254 self
.default_tab_hashes
.push(this.hash
);
5258 events: function () {
5262 var usual_tab_behavior = function (e
) {
5263 var settings
= S(this).closest('[' + self
.attr_name() + ']').data(self
.attr_name(true) + '-init');
5264 if (!settings
.is_hover
|| Modernizr
.touch
) {
5266 e
.stopPropagation();
5267 self
.toggle_active_tab(S(this).parent());
5273 // Click event: tab title
5274 .on('focus.fndtn.tab', '[' + this.attr_name() + '] > * > a', usual_tab_behavior
)
5275 .on('click.fndtn.tab', '[' + this.attr_name() + '] > * > a', usual_tab_behavior
)
5276 // Hover event: tab title
5277 .on('mouseenter.fndtn.tab', '[' + this.attr_name() + '] > * > a', function (e
) {
5278 var settings
= S(this).closest('[' + self
.attr_name() + ']').data(self
.attr_name(true) + '-init');
5279 if (settings
.is_hover
) self
.toggle_active_tab(S(this).parent());
5282 // Location hash change event
5283 S(window
).on('hashchange.fndtn.tab', function (e
) {
5285 self
.handle_location_hash_change();
5289 handle_location_hash_change: function () {
5294 S('[' + this.attr_name() + ']', this.scope
).each(function () {
5295 var settings
= S(this).data(self
.attr_name(true) + '-init');
5296 if (settings
.deep_linking
) {
5297 // Match the location hash to a label
5299 if (settings
.scroll_to_content
) {
5300 hash
= self
.scope
.location
.hash
;
5302 // prefix the hash to prevent anchor scrolling
5303 hash
= self
.scope
.location
.hash
.replace('fndtn-', '');
5306 // Check whether the location hash references a tab content div or
5307 // another element on the page (inside or outside the tab content div)
5308 var hash_element
= S(hash
);
5309 if (hash_element
.hasClass('content') && hash_element
.parent().hasClass('tabs-content')) {
5311 self
.toggle_active_tab($('[' + self
.attr_name() + '] > * > a[href=' + hash
+ ']').parent());
5313 // Not the tab content div. If inside the tab content, find the
5314 // containing tab and toggle it as active.
5315 var hash_tab_container_id
= hash_element
.closest('.content').attr('id');
5316 if (hash_tab_container_id
!= undefined) {
5317 self
.toggle_active_tab($('[' + self
.attr_name() + '] > * > a[href=#' + hash_tab_container_id
+ ']').parent(), hash
);
5321 // Reference the default tab hashes which were initialized in the init function
5322 for (var ind
= 0; ind
< self
.default_tab_hashes
.length
; ind
++) {
5323 self
.toggle_active_tab($('[' + self
.attr_name() + '] > * > a[href=' + self
.default_tab_hashes
[ind
] + ']').parent());
5330 toggle_active_tab: function (tab
, location_hash
) {
5332 tabs
= tab
.closest('[' + this.attr_name() + ']'),
5333 tab_link
= tab
.find('a'),
5334 anchor
= tab
.children('a').first(),
5335 target_hash
= '#' + anchor
.attr('href').split('#')[1],
5336 target
= S(target_hash
),
5337 siblings
= tab
.siblings(),
5338 settings
= tabs
.data(this.attr_name(true) + '-init'),
5339 interpret_keyup_action = function (e
) {
5340 // Light modification of Heydon Pickering's Practical ARIA Examples: http://heydonworks.com/practical_aria_examples/js/a11y.js
5342 // define current, previous and next (possible) tabs
5344 var $original
= $(this);
5345 var $prev
= $(this).parents('li').prev().children('[role="tab"]');
5346 var $next
= $(this).parents('li').next().children('[role="tab"]');
5349 // find the direction (prev or next)
5351 switch (e
.keyCode
) {
5363 if ($target
.length
) {
5366 'aria-selected': null
5370 'aria-selected': true
5376 $('[role="tabpanel"]')
5377 .attr('aria-hidden', 'true');
5379 // Show panel which corresponds to target
5381 $('#' + $(document
.activeElement
).attr('href').substring(1))
5382 .attr('aria-hidden', null);
5386 // allow usage of data-tab-content attribute instead of href
5387 if (S(this).data(this.data_attr('tab-content'))) {
5388 target_hash
= '#' + S(this).data(this.data_attr('tab-content')).split('#')[1];
5389 target
= S(target_hash
);
5392 if (settings
.deep_linking
) {
5394 if (settings
.scroll_to_content
) {
5395 // retain current hash to scroll to content
5396 window
.location
.hash
= location_hash
|| target_hash
;
5397 if (location_hash
== undefined || location_hash
== target_hash
) {
5398 tab
.parent()[0].scrollIntoView();
5400 S(target_hash
)[0].scrollIntoView();
5403 // prefix the hashes so that the browser doesn't scroll down
5404 if (location_hash
!= undefined) {
5405 window
.location
.hash
= 'fndtn-' + location_hash
.replace('#', '');
5407 window
.location
.hash
= 'fndtn-' + target_hash
.replace('#', '');
5412 // WARNING: The activation and deactivation of the tab content must
5413 // occur after the deep linking in order to properly refresh the browser
5414 // window (notably in Chrome).
5415 // Clean up multiple attr instances to done once
5416 tab
.addClass(settings
.active_class
).triggerHandler('opened');
5417 tab_link
.attr({'aria-selected': 'true', tabindex
: 0});
5418 siblings
.removeClass(settings
.active_class
)
5419 siblings
.find('a').attr({'aria-selected': 'false', tabindex
: -1});
5420 target
.siblings().removeClass(settings
.active_class
).attr({'aria-hidden': 'true', tabindex
: -1});
5421 target
.addClass(settings
.active_class
).attr('aria-hidden', 'false').removeAttr('tabindex');
5422 settings
.callback(tab
);
5423 target
.triggerHandler('toggled', [tab
]);
5424 tabs
.triggerHandler('toggled', [target
]);
5426 tab_link
.off('keydown').on('keydown', interpret_keyup_action
);
5429 data_attr: function (str
) {
5430 if (this.namespace.length
> 0) {
5431 return this.namespace + '-' + str
;
5440 reflow: function () {
5443 }(jQuery
, window
, window
.document
));
5445 (function ($, window
, document
, undefined) {
5448 Foundation
.libs
.abide
= {
5454 live_validate
: true,
5455 validate_on_blur
: true,
5456 focus_on_invalid
: true,
5457 error_labels
: true, // labels with a for="inputId" will recieve an `error` class
5458 error_class
: 'error',
5461 alpha
: /^[a-zA-Z]+$/,
5462 alpha_numeric
: /^[a-zA-Z0-9]+$/,
5463 integer
: /^[-+]?\d+$/,
5464 number
: /^[-+]?\d*(?:[\.\,]\d+)?$/,
5466 // amex, visa, diners
5467 card
: /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/,
5468 cvv
: /^([0-9]){3,4}$/,
5470 // http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address
5471 email
: /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/,
5473 url
: /^(https?|ftp|file|ssh):\/\/(((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-zA-Z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-zA-Z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/,
5475 domain
: /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,8}$/,
5477 datetime
: /^([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])T([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])(Z|([\-\+]([0-1][0-9])\:00))$/,
5479 date
: /(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))$/,
5481 time
: /^(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2}$/,
5482 dateISO
: /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/,
5484 month_day_year
: /^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.]\d{4}$/,
5486 day_month_year
: /^(0[1-9]|[12][0-9]|3[01])[- \/.](0[1-9]|1[012])[- \/.]\d{4}$/,
5489 color
: /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/
5492 equalTo: function (el
, required
, parent
) {
5493 var from = document
.getElementById(el
.getAttribute(this.add_namespace('data-equalto'))).value
,
5495 valid
= (from === to
);
5504 init: function (scope
, method
, options
) {
5505 this.bindings(method
, options
);
5508 events: function (scope
) {
5510 form
= self
.S(scope
).attr('novalidate', 'novalidate'),
5511 settings
= form
.data(this.attr_name(true) + '-init') || {};
5513 this.invalid_attr
= this.add_namespace('data-invalid');
5517 .on('submit.fndtn.abide validate.fndtn.abide', function (e
) {
5518 var is_ajax
= /ajax/i.test(self
.S(this).attr(self
.attr_name()));
5519 return self
.validate(self
.S(this).find('input, textarea, select').get(), e
, is_ajax
);
5521 .on('reset', function () {
5522 return self
.reset($(this));
5524 .find('input, textarea, select')
5526 .on('blur.fndtn.abide change.fndtn.abide', function (e
) {
5527 if (settings
.validate_on_blur
=== true) {
5528 self
.validate([this], e
);
5531 .on('keydown.fndtn.abide', function (e
) {
5532 if (settings
.live_validate
=== true && e
.which
!= 9) {
5533 clearTimeout(self
.timer
);
5534 self
.timer
= setTimeout(function () {
5535 self
.validate([this], e
);
5536 }.bind(this), settings
.timeout
);
5541 reset: function (form
) {
5542 form
.removeAttr(this.invalid_attr
);
5543 $(this.invalid_attr
, form
).removeAttr(this.invalid_attr
);
5544 $('.' + this.settings
.error_class
, form
).not('small').removeClass(this.settings
.error_class
);
5547 validate: function (els
, e
, is_ajax
) {
5548 var validations
= this.parse_patterns(els
),
5549 validation_count
= validations
.length
,
5550 form
= this.S(els
[0]).closest('form'),
5551 submit_event
= /submit/.test(e
.type
);
5553 // Has to count up to make sure the focus gets applied to the top error
5554 for (var i
= 0; i
< validation_count
; i
++) {
5555 if (!validations
[i
] && (submit_event
|| is_ajax
)) {
5556 if (this.settings
.focus_on_invalid
) els
[i
].focus();
5557 form
.trigger('invalid').trigger('invalid.fndtn.abide');
5558 this.S(els
[i
]).closest('form').attr(this.invalid_attr
, '');
5563 if (submit_event
|| is_ajax
) {
5564 form
.trigger('valid').trigger('valid.fndtn.abide');
5567 form
.removeAttr(this.invalid_attr
);
5569 if (is_ajax
) return false;
5574 parse_patterns: function (els
) {
5579 el_patterns
.push(this.pattern(els
[i
]));
5582 return this.check_validation_and_apply_styles(el_patterns
);
5585 pattern: function (el
) {
5586 var type
= el
.getAttribute('type'),
5587 required
= typeof el
.getAttribute('required') === 'string';
5589 var pattern
= el
.getAttribute('pattern') || '';
5591 if (this.settings
.patterns
.hasOwnProperty(pattern
) && pattern
.length
> 0) {
5592 return [el
, this.settings
.patterns
[pattern
], required
];
5593 } else if (pattern
.length
> 0) {
5594 return [el
, new RegExp(pattern
), required
];
5597 if (this.settings
.patterns
.hasOwnProperty(type
)) {
5598 return [el
, this.settings
.patterns
[type
], required
];
5603 return [el
, pattern
, required
];
5606 // TODO: Break this up into smaller methods, getting hard to read.
5607 check_validation_and_apply_styles: function (el_patterns
) {
5608 var i
= el_patterns
.length
,
5610 form
= this.S(el_patterns
[0][0]).closest('[data-' + this.attr_name(true) + ']'),
5611 settings
= form
.data(this.attr_name(true) + '-init') || {};
5613 var el
= el_patterns
[i
][0],
5614 required
= el_patterns
[i
][2],
5615 value
= el
.value
.trim(),
5616 direct_parent
= this.S(el
).parent(),
5617 validator
= el
.getAttribute(this.add_namespace('data-abide-validator')),
5618 is_radio
= el
.type
=== "radio",
5619 is_checkbox
= el
.type
=== "checkbox",
5620 label
= this.S('label[for="' + el
.getAttribute('id') + '"]'),
5621 valid_length
= (required
) ? (el
.value
.length
> 0) : true,
5622 el_validations
= [];
5626 // support old way to do equalTo validations
5627 if (el
.getAttribute(this.add_namespace('data-equalto'))) {
5628 validator
= "equalTo"
5631 if (!direct_parent
.is('label')) {
5632 parent
= direct_parent
;
5634 parent
= direct_parent
.parent();
5638 valid
= this.settings
.validators
[validator
].apply(this, [el
, required
, parent
]);
5639 el_validations
.push(valid
);
5642 if (is_radio
&& required
) {
5643 el_validations
.push(this.valid_radio(el
, required
));
5644 } else if (is_checkbox
&& required
) {
5645 el_validations
.push(this.valid_checkbox(el
, required
));
5648 if (el_patterns
[i
][1].test(value
) && valid_length
||
5649 !required
&& el
.value
.length
< 1 || $(el
).attr('disabled')) {
5650 el_validations
.push(true);
5652 el_validations
.push(false);
5655 el_validations
= [el_validations
.every(function (valid
) {
5659 if (el_validations
[0]) {
5660 this.S(el
).removeAttr(this.invalid_attr
);
5661 el
.setAttribute('aria-invalid', 'false');
5662 el
.removeAttribute('aria-describedby');
5663 parent
.removeClass(this.settings
.error_class
);
5664 if (label
.length
> 0 && this.settings
.error_labels
) {
5665 label
.removeClass(this.settings
.error_class
).removeAttr('role');
5667 $(el
).triggerHandler('valid');
5669 this.S(el
).attr(this.invalid_attr
, '');
5670 el
.setAttribute('aria-invalid', 'true');
5672 // Try to find the error associated with the input
5673 var errorElem
= parent
.find('small.' + this.settings
.error_class
, 'span.' + this.settings
.error_class
);
5674 var errorID
= errorElem
.length
> 0 ? errorElem
[0].id
: "";
5675 if (errorID
.length
> 0) el
.setAttribute('aria-describedby', errorID
);
5677 // el.setAttribute('aria-describedby', $(el).find('.error')[0].id);
5678 parent
.addClass(this.settings
.error_class
);
5679 if (label
.length
> 0 && this.settings
.error_labels
) {
5680 label
.addClass(this.settings
.error_class
).attr('role', 'alert');
5682 $(el
).triggerHandler('invalid');
5685 validations
.push(el_validations
[0]);
5687 validations
= [validations
.every(function (valid
) {
5693 valid_checkbox: function (el
, required
) {
5694 var el
= this.S(el
),
5695 valid
= (el
.is(':checked') || !required
);
5698 el
.removeAttr(this.invalid_attr
).parent().removeClass(this.settings
.error_class
);
5700 el
.attr(this.invalid_attr
, '').parent().addClass(this.settings
.error_class
);
5706 valid_radio: function (el
, required
) {
5707 var name
= el
.getAttribute('name'),
5708 group
= this.S(el
).closest('[data-' + this.attr_name(true) + ']').find("[name='" + name
+ "']"),
5709 count
= group
.length
,
5712 // Has to count up to make sure the focus gets applied to the top error
5713 for (var i
= 0; i
< count
; i
++) {
5714 if (group
[i
].checked
) valid
= true;
5717 // Has to count up to make sure the focus gets applied to the top error
5718 for (var i
= 0; i
< count
; i
++) {
5720 this.S(group
[i
]).removeAttr(this.invalid_attr
).parent().removeClass(this.settings
.error_class
);
5722 this.S(group
[i
]).attr(this.invalid_attr
, '').parent().addClass(this.settings
.error_class
);
5729 valid_equal: function (el
, required
, parent
) {
5730 var from = document
.getElementById(el
.getAttribute(this.add_namespace('data-equalto'))).value
,
5732 valid
= (from === to
);
5735 this.S(el
).removeAttr(this.invalid_attr
);
5736 parent
.removeClass(this.settings
.error_class
);
5737 if (label
.length
> 0 && settings
.error_labels
) label
.removeClass(this.settings
.error_class
);
5739 this.S(el
).attr(this.invalid_attr
, '');
5740 parent
.addClass(this.settings
.error_class
);
5741 if (label
.length
> 0 && settings
.error_labels
) label
.addClass(this.settings
.error_class
);
5747 valid_oneof: function (el
, required
, parent
, doNotValidateOthers
) {
5748 var el
= this.S(el
),
5749 others
= this.S('[' + this.add_namespace('data-oneof') + ']'),
5750 valid
= others
.filter(':checked').length
> 0;
5753 el
.removeAttr(this.invalid_attr
).parent().removeClass(this.settings
.error_class
);
5755 el
.attr(this.invalid_attr
, '').parent().addClass(this.settings
.error_class
);
5758 if (!doNotValidateOthers
) {
5760 others
.each(function () {
5761 _this
.valid_oneof
.call(_this
, this, null, null, true);
5768 }(jQuery
, window
, window
.document
));
5770 (function ($, window
, document
, undefined) {
5773 Foundation
.libs
.tooltip
= {
5779 additional_inheritable_classes
: [],
5780 tooltip_class
: '.tooltip',
5782 touch_close_text
: 'Tap To Close',
5783 disable_for_touch
: false,
5786 tip_template: function (selector
, content
) {
5787 return '<span data-selector="' + selector
+ '" id="' + selector
+ '" class="'
5788 + Foundation
.libs
.tooltip
.settings
.tooltip_class
.substring(1)
5789 + '" role="tooltip">' + content
+ '<span class="nub"></span></span>';
5795 init: function (scope
, method
, options
) {
5796 Foundation
.inherit(this, 'random_str');
5797 this.bindings(method
, options
);
5800 should_show: function (target
, tip
) {
5801 var settings
= $.extend({}, this.settings
, this.data_options(target
));
5803 if (settings
.show_on
=== 'all') {
5805 } else if (this.small() && settings
.show_on
=== 'small') {
5807 } else if (this.medium() && settings
.show_on
=== 'medium') {
5809 } else if (this.large() && settings
.show_on
=== 'large') {
5815 medium: function () {
5816 return matchMedia(Foundation
.media_queries
['medium']).matches
;
5819 large: function () {
5820 return matchMedia(Foundation
.media_queries
['large']).matches
;
5823 events: function (instance
) {
5827 self
.create(this.S(instance
));
5831 .on('mouseenter.fndtn.tooltip mouseleave.fndtn.tooltip touchstart.fndtn.tooltip MSPointerDown.fndtn.tooltip',
5832 '[' + this.attr_name() + ']', function (e
) {
5833 var $this = S(this),
5834 settings
= $.extend({}, self
.settings
, self
.data_options($this)),
5837 if (Modernizr
.touch
&& /touchstart|MSPointerDown/i.test(e
.type
) && S(e
.target
).is('a')) {
5841 if (/mouse/i.test(e
.type
) && self
.ie_touch(e
)) return false;
5843 if ($this.hasClass('open')) {
5844 if (Modernizr
.touch
&& /touchstart|MSPointerDown/i.test(e
.type
)) e
.preventDefault();
5847 if (settings
.disable_for_touch
&& Modernizr
.touch
&& /touchstart|MSPointerDown/i.test(e
.type
)) {
5849 } else if (!settings
.disable_for_touch
&& Modernizr
.touch
&& /touchstart|MSPointerDown/i.test(e
.type
)) {
5851 S(settings
.tooltip_class
+ '.open').hide();
5855 if (/enter|over/i.test(e
.type
)) {
5856 this.timer
= setTimeout(function () {
5857 var tip
= self
.showTip($this);
5858 }.bind(this), self
.settings
.hover_delay
);
5859 } else if (e
.type
=== 'mouseout' || e
.type
=== 'mouseleave') {
5860 clearTimeout(this.timer
);
5863 self
.showTip($this);
5867 .on('mouseleave.fndtn.tooltip touchstart.fndtn.tooltip MSPointerDown.fndtn.tooltip', '[' + this.attr_name() + '].open', function (e
) {
5868 if (/mouse/i.test(e
.type
) && self
.ie_touch(e
)) return false;
5870 if ($(this).data('tooltip-open-event-type') == 'touch' && e
.type
== 'mouseleave') {
5873 else if ($(this).data('tooltip-open-event-type') == 'mouse' && /MSPointerDown|touchstart/i.test(e
.type
)) {
5874 self
.convert_to_touch($(this));
5879 .on('DOMNodeRemoved DOMAttrModified', '[' + this.attr_name() + ']:not(a)', function (e
) {
5884 ie_touch: function (e
) {
5885 // How do I distinguish between IE11 and Windows Phone 8?????
5889 showTip: function ($target
) {
5890 var $tip
= this.getTip($target
);
5891 if (this.should_show($target
, $tip
)) {
5892 return this.show($target
);
5897 getTip: function ($target
) {
5898 var selector
= this.selector($target
),
5899 settings
= $.extend({}, this.settings
, this.data_options($target
)),
5903 tip
= this.S('span[data-selector="' + selector
+ '"]' + settings
.tooltip_class
);
5906 return (typeof tip
=== 'object') ? tip
: false;
5909 selector: function ($target
) {
5910 var id
= $target
.attr('id'),
5911 dataSelector
= $target
.attr(this.attr_name()) || $target
.attr('data-selector');
5913 if ((id
&& id
.length
< 1 || !id
) && typeof dataSelector
!= 'string') {
5914 dataSelector
= this.random_str(6);
5916 .attr('data-selector', dataSelector
)
5917 .attr('aria-describedby', dataSelector
);
5920 return (id
&& id
.length
> 0) ? id
: dataSelector
;
5923 create: function ($target
) {
5925 settings
= $.extend({}, this.settings
, this.data_options($target
)),
5926 tip_template
= this.settings
.tip_template
;
5928 if (typeof settings
.tip_template
=== 'string' && window
.hasOwnProperty(settings
.tip_template
)) {
5929 tip_template
= window
[settings
.tip_template
];
5932 var $tip
= $(tip_template(this.selector($target
), $('<div></div>').html($target
.attr('title')).html())),
5933 classes
= this.inheritable_classes($target
);
5935 $tip
.addClass(classes
).appendTo(settings
.append_to
);
5937 if (Modernizr
.touch
) {
5938 $tip
.append('<span class="tap-to-close">' + settings
.touch_close_text
+ '</span>');
5939 $tip
.on('touchstart.fndtn.tooltip MSPointerDown.fndtn.tooltip', function (e
) {
5944 $target
.removeAttr('title').attr('title', '');
5947 reposition: function (target
, tip
, classes
) {
5948 var width
, nub
, nubHeight
, nubWidth
, column
, objPos
;
5950 tip
.css('visibility', 'hidden').show();
5952 width
= target
.data('width');
5953 nub
= tip
.children('.nub');
5954 nubHeight
= nub
.outerHeight();
5955 nubWidth
= nub
.outerHeight();
5958 tip
.css({'width': '100%'});
5960 tip
.css({'width': (width
) ? width
: 'auto'});
5963 objPos = function (obj
, top
, right
, bottom
, left
, width
) {
5965 'top': (top
) ? top
: 'auto',
5966 'bottom': (bottom
) ? bottom
: 'auto',
5967 'left': (left
) ? left
: 'auto',
5968 'right': (right
) ? right
: 'auto'
5972 objPos(tip
, (target
.offset().top
+ target
.outerHeight() + 10), 'auto', 'auto', target
.offset().left
);
5975 objPos(tip
, (target
.offset().top
+ target
.outerHeight() + 10), 'auto', 'auto', 12.5, $(this.scope
).width());
5976 tip
.addClass('tip-override');
5977 objPos(nub
, -nubHeight
, 'auto', 'auto', target
.offset().left
);
5979 var left
= target
.offset().left
;
5980 if (Foundation
.rtl
) {
5981 nub
.addClass('rtl');
5982 left
= target
.offset().left
+ target
.outerWidth() - tip
.outerWidth();
5984 objPos(tip
, (target
.offset().top
+ target
.outerHeight() + 10), 'auto', 'auto', left
);
5985 tip
.removeClass('tip-override');
5986 if (classes
&& classes
.indexOf('tip-top') > -1) {
5987 if (Foundation
.rtl
) nub
.addClass('rtl');
5988 objPos(tip
, (target
.offset().top
- tip
.outerHeight()), 'auto', 'auto', left
)
5989 .removeClass('tip-override');
5990 } else if (classes
&& classes
.indexOf('tip-left') > -1) {
5991 objPos(tip
, (target
.offset().top
+ (target
.outerHeight() / 2) - (tip
.outerHeight() / 2)), 'auto', 'auto', (target
.offset().left
- tip
.outerWidth() - nubHeight
))
5992 .removeClass('tip-override');
5993 nub
.removeClass('rtl');
5994 } else if (classes
&& classes
.indexOf('tip-right') > -1) {
5995 objPos(tip
, (target
.offset().top
+ (target
.outerHeight() / 2) - (tip
.outerHeight() / 2)), 'auto', 'auto', (target
.offset().left
+ target
.outerWidth() + nubHeight
))
5996 .removeClass('tip-override');
5997 nub
.removeClass('rtl');
6001 tip
.css('visibility', 'visible').hide();
6004 small: function () {
6005 return matchMedia(Foundation
.media_queries
.small
).matches
&& !matchMedia(Foundation
.media_queries
.medium
).matches
;
6008 inheritable_classes: function ($target
) {
6009 var settings
= $.extend({}, this.settings
, this.data_options($target
)),
6010 inheritables
= ['tip-top', 'tip-left', 'tip-bottom', 'tip-right', 'radius', 'round'].concat(settings
.additional_inheritable_classes
),
6011 classes
= $target
.attr('class'),
6012 filtered
= classes
? $.map(classes
.split(' '), function (el
, i
) {
6013 if ($.inArray(el
, inheritables
) !== -1) {
6018 return $.trim(filtered
);
6021 convert_to_touch: function ($target
) {
6023 $tip
= self
.getTip($target
),
6024 settings
= $.extend({}, self
.settings
, self
.data_options($target
));
6026 if ($tip
.find('.tap-to-close').length
=== 0) {
6027 $tip
.append('<span class="tap-to-close">' + settings
.touch_close_text
+ '</span>');
6028 $tip
.on('click.fndtn.tooltip.tapclose touchstart.fndtn.tooltip.tapclose MSPointerDown.fndtn.tooltip.tapclose', function (e
) {
6033 $target
.data('tooltip-open-event-type', 'touch');
6036 show: function ($target
) {
6037 var $tip
= this.getTip($target
);
6039 if ($target
.data('tooltip-open-event-type') == 'touch') {
6040 this.convert_to_touch($target
);
6043 this.reposition($target
, $tip
, $target
.attr('class'));
6044 $target
.addClass('open');
6048 hide: function ($target
) {
6049 var $tip
= this.getTip($target
);
6051 $tip
.fadeOut(150, function () {
6052 $tip
.find('.tap-to-close').remove();
6053 $tip
.off('click.fndtn.tooltip.tapclose MSPointerDown.fndtn.tapclose');
6054 $target
.removeClass('open');
6060 this.S(this.scope
).off('.fndtn.tooltip');
6061 this.S(this.settings
.tooltip_class
).each(function (i
) {
6062 $('[' + self
.attr_name() + ']').eq(i
).attr('title', $(this).text());
6066 reflow: function () {
6069 }(jQuery
, window
, window
.document
));