2013-05-28 01:10:05 +00:00
|
|
|
;(function ($, window, document, undefined) {
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
Foundation.libs = Foundation.libs || {};
|
|
|
|
|
|
|
|
Foundation.libs.orbit = {
|
|
|
|
name: 'orbit',
|
|
|
|
|
2013-07-13 07:25:45 +00:00
|
|
|
version: '4.2.0',
|
2013-05-28 01:10:05 +00:00
|
|
|
|
|
|
|
settings: {
|
|
|
|
timer_speed: 10000,
|
2013-07-13 07:25:45 +00:00
|
|
|
pause_on_hover: true,
|
|
|
|
resume_on_mouseout: false,
|
2013-05-28 01:10:05 +00:00
|
|
|
animation_speed: 500,
|
|
|
|
bullets: true,
|
|
|
|
stack_on_small: true,
|
|
|
|
navigation_arrows: true,
|
|
|
|
slide_number: true,
|
|
|
|
container_class: 'orbit-container',
|
|
|
|
stack_on_small_class: 'orbit-stack-on-small',
|
|
|
|
next_class: 'orbit-next',
|
|
|
|
prev_class: 'orbit-prev',
|
|
|
|
timer_container_class: 'orbit-timer',
|
|
|
|
timer_paused_class: 'paused',
|
|
|
|
timer_progress_class: 'orbit-progress',
|
|
|
|
slides_container_class: 'orbit-slides-container',
|
|
|
|
bullets_container_class: 'orbit-bullets',
|
|
|
|
bullets_active_class: 'active',
|
|
|
|
slide_number_class: 'orbit-slide-number',
|
|
|
|
caption_class: 'orbit-caption',
|
|
|
|
active_slide_class: 'active',
|
|
|
|
orbit_transition_class: 'orbit-transitioning'
|
|
|
|
},
|
|
|
|
|
|
|
|
init: function (scope, method, options) {
|
|
|
|
var self = this;
|
|
|
|
Foundation.inherit(self, 'data_options');
|
|
|
|
|
|
|
|
if (typeof method === 'object') {
|
|
|
|
$.extend(true, self.settings, method);
|
|
|
|
}
|
|
|
|
|
2013-07-13 07:25:45 +00:00
|
|
|
if ($(scope).is('[data-orbit]')) {
|
|
|
|
var scoped_self = $.extend(true, {}, self);
|
|
|
|
scoped_self._init(idx, el);
|
|
|
|
}
|
|
|
|
|
2013-05-28 01:10:05 +00:00
|
|
|
$('[data-orbit]', scope).each(function(idx, el) {
|
|
|
|
var scoped_self = $.extend(true, {}, self);
|
|
|
|
scoped_self._init(idx, el);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
_container_html: function() {
|
|
|
|
var self = this;
|
|
|
|
return '<div class="' + self.settings.container_class + '"></div>';
|
|
|
|
},
|
|
|
|
|
|
|
|
_bullets_container_html: function($slides) {
|
|
|
|
var self = this,
|
|
|
|
$list = $('<ol class="' + self.settings.bullets_container_class + '"></ol>');
|
|
|
|
$slides.each(function(idx, slide) {
|
|
|
|
var $item = $('<li data-orbit-slide-number="' + (idx+1) + '" class=""></li>');
|
|
|
|
if (idx === 0) {
|
|
|
|
$item.addClass(self.settings.bullets_active_class);
|
|
|
|
}
|
|
|
|
$list.append($item);
|
|
|
|
});
|
|
|
|
return $list;
|
|
|
|
},
|
|
|
|
|
|
|
|
_slide_number_html: function(slide_number, total_slides) {
|
|
|
|
var self = this,
|
|
|
|
$container = $('<div class="' + self.settings.slide_number_class + '"></div>');
|
|
|
|
$container.append('<span>' + slide_number + '</span> of <span>' + total_slides + '</span>');
|
|
|
|
return $container;
|
|
|
|
},
|
|
|
|
|
|
|
|
_timer_html: function() {
|
|
|
|
var self = this;
|
|
|
|
if (typeof self.settings.timer_speed === 'number' && self.settings.timer_speed > 0) {
|
|
|
|
return '<div class="' + self.settings.timer_container_class
|
|
|
|
+ '"><span></span><div class="' + self.settings.timer_progress_class
|
|
|
|
+ '"></div></div>';
|
|
|
|
} else {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_next_html: function() {
|
|
|
|
var self = this;
|
|
|
|
return '<a href="#" class="' + self.settings.next_class + '">Next <span></span></a>';
|
|
|
|
},
|
|
|
|
|
|
|
|
_prev_html: function() {
|
|
|
|
var self = this;
|
|
|
|
return '<a href="#" class="' + self.settings.prev_class + '">Prev <span></span></a>';
|
|
|
|
},
|
|
|
|
|
|
|
|
_init: function (idx, slider) {
|
|
|
|
var self = this,
|
|
|
|
$slides_container = $(slider),
|
|
|
|
$container = $slides_container.wrap(self._container_html()).parent(),
|
|
|
|
$slides = $slides_container.children();
|
|
|
|
|
|
|
|
$.extend(true, self.settings, self.data_options($slides_container));
|
|
|
|
|
|
|
|
if (self.settings.navigation_arrows) {
|
|
|
|
$container.append(self._prev_html());
|
|
|
|
$container.append(self._next_html());
|
|
|
|
}
|
|
|
|
$slides_container.addClass(self.settings.slides_container_class);
|
|
|
|
if (self.settings.stack_on_small) {
|
|
|
|
$container.addClass(self.settings.stack_on_small_class);
|
|
|
|
}
|
|
|
|
if (self.settings.slide_number) {
|
|
|
|
$container.append(self._slide_number_html(1, $slides.length));
|
|
|
|
}
|
|
|
|
$container.append(self._timer_html());
|
|
|
|
if (self.settings.bullets) {
|
|
|
|
$container.after(self._bullets_container_html($slides));
|
|
|
|
}
|
|
|
|
// To better support the "sliding" effect it's easier
|
|
|
|
// if we just clone the first and last slides
|
|
|
|
$slides_container.append($slides.first().clone().attr('data-orbit-slide',''));
|
|
|
|
$slides_container.prepend($slides.last().clone().attr('data-orbit-slide',''));
|
|
|
|
// Make the first "real" slide active
|
2013-07-13 07:25:45 +00:00
|
|
|
$slides_container.css(Foundation.rtl ? 'marginRight' : 'marginLeft', '-100%');
|
2013-05-28 01:10:05 +00:00
|
|
|
$slides.first().addClass(self.settings.active_slide_class);
|
|
|
|
|
|
|
|
self._init_events($slides_container);
|
|
|
|
self._init_dimensions($slides_container);
|
|
|
|
self._start_timer($slides_container);
|
|
|
|
},
|
|
|
|
|
|
|
|
_init_events: function ($slides_container) {
|
|
|
|
var self = this,
|
|
|
|
$container = $slides_container.parent();
|
|
|
|
|
|
|
|
$(window)
|
|
|
|
.on('load.fndtn.orbit', function() {
|
|
|
|
$slides_container.height('');
|
|
|
|
$slides_container.height($slides_container.height($container.height()));
|
|
|
|
$slides_container.trigger('orbit:ready');
|
|
|
|
})
|
|
|
|
.on('resize.fndtn.orbit', function() {
|
|
|
|
$slides_container.height('');
|
|
|
|
$slides_container.height($slides_container.height($container.height()));
|
|
|
|
});
|
|
|
|
|
|
|
|
$(document).on('click.fndtn.orbit', '[data-orbit-link]', function(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
var id = $(e.currentTarget).attr('data-orbit-link'),
|
|
|
|
$slide = $slides_container.find('[data-orbit-slide=' + id + ']').first();
|
|
|
|
|
|
|
|
if ($slide.length === 1) {
|
|
|
|
self._reset_timer($slides_container, true);
|
|
|
|
self._goto($slides_container, $slide.index(), function() {});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
$container.siblings('.' + self.settings.bullets_container_class)
|
|
|
|
.on('click.fndtn.orbit', '[data-orbit-slide-number]', function(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
self._reset_timer($slides_container, true);
|
|
|
|
self._goto($slides_container, $(e.currentTarget).data('orbit-slide-number'),function() {});
|
|
|
|
});
|
|
|
|
|
|
|
|
$container
|
2013-07-13 07:25:45 +00:00
|
|
|
.on('mouseenter.fndtn.orbit', function(e) {
|
|
|
|
if (self.settings.pause_on_hover) {
|
|
|
|
self._stop_timer($slides_container);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.on('mouseleave.fndtn.orbit', function(e) {
|
|
|
|
if (self.settings.resume_on_mouseout) {
|
|
|
|
self._start_timer($slides_container);
|
|
|
|
}
|
|
|
|
})
|
2013-05-28 01:10:05 +00:00
|
|
|
.on('orbit:after-slide-change.fndtn.orbit', function(e, orbit) {
|
|
|
|
var $slide_number = $container.find('.' + self.settings.slide_number_class);
|
|
|
|
|
|
|
|
if ($slide_number.length === 1) {
|
|
|
|
$slide_number.replaceWith(self._slide_number_html(orbit.slide_number, orbit.total_slides));
|
|
|
|
}
|
|
|
|
})
|
2013-07-13 07:25:45 +00:00
|
|
|
.on('orbit:next-slide.fndtn.orbit click.fndtn.orbit', '.' + self.settings.next_class.split(" ").join("."), function(e) {
|
2013-05-28 01:10:05 +00:00
|
|
|
e.preventDefault();
|
|
|
|
self._reset_timer($slides_container, true);
|
|
|
|
self._goto($slides_container, 'next', function() {});
|
|
|
|
})
|
2013-07-13 07:25:45 +00:00
|
|
|
.on('orbit:prev-slide.fndtn.orbit click.fndtn.orbit', '.' + self.settings.prev_class.split(" ").join("."), function(e) {
|
2013-05-28 01:10:05 +00:00
|
|
|
e.preventDefault();
|
|
|
|
self._reset_timer($slides_container, true);
|
|
|
|
self._goto($slides_container, 'prev', function() {});
|
|
|
|
})
|
|
|
|
.on('orbit:toggle-play-pause.fndtn.orbit click.fndtn.orbit touchstart.fndtn.orbit', '.' + self.settings.timer_container_class, function(e) {
|
|
|
|
e.preventDefault();
|
|
|
|
var $timer = $(e.currentTarget).toggleClass(self.settings.timer_paused_class),
|
|
|
|
$slides_container = $timer.closest('.' + self.settings.container_class)
|
|
|
|
.find('.' + self.settings.slides_container_class);
|
|
|
|
|
|
|
|
if ($timer.hasClass(self.settings.timer_paused_class)) {
|
|
|
|
self._stop_timer($slides_container);
|
|
|
|
} else {
|
|
|
|
self._start_timer($slides_container);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.on('touchstart.fndtn.orbit', function(e) {
|
|
|
|
if (!e.touches) { e = e.originalEvent; }
|
|
|
|
var data = {
|
|
|
|
start_page_x: e.touches[0].pageX,
|
|
|
|
start_page_y: e.touches[0].pageY,
|
|
|
|
start_time: (new Date()).getTime(),
|
|
|
|
delta_x: 0,
|
|
|
|
is_scrolling: undefined
|
|
|
|
};
|
|
|
|
$container.data('swipe-transition', data);
|
|
|
|
e.stopPropagation();
|
|
|
|
})
|
|
|
|
.on('touchmove.fndtn.orbit', function(e) {
|
|
|
|
if (!e.touches) { e = e.originalEvent; }
|
|
|
|
// Ignore pinch/zoom events
|
|
|
|
if(e.touches.length > 1 || e.scale && e.scale !== 1) return;
|
|
|
|
|
|
|
|
var data = $container.data('swipe-transition');
|
|
|
|
if (typeof data === 'undefined') {
|
|
|
|
data = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
data.delta_x = e.touches[0].pageX - data.start_page_x;
|
|
|
|
|
|
|
|
if ( typeof data.is_scrolling === 'undefined') {
|
|
|
|
data.is_scrolling = !!( data.is_scrolling || Math.abs(data.delta_x) < Math.abs(e.touches[0].pageY - data.start_page_y) );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!data.is_scrolling && !data.active) {
|
|
|
|
e.preventDefault();
|
|
|
|
self._stop_timer($slides_container);
|
|
|
|
var direction = (data.delta_x < 0) ? 'next' : 'prev';
|
|
|
|
data.active = true;
|
|
|
|
self._goto($slides_container, direction, function() {});
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.on('touchend.fndtn.orbit', function(e) {
|
|
|
|
$container.data('swipe-transition', {});
|
|
|
|
e.stopPropagation();
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
_init_dimensions: function ($slides_container) {
|
|
|
|
var $container = $slides_container.parent(),
|
|
|
|
$slides = $slides_container.children();
|
|
|
|
|
|
|
|
$slides_container.css('width', $slides.length * 100 + '%');
|
|
|
|
$slides.css('width', 100 / $slides.length + '%');
|
|
|
|
$slides_container.height($container.height());
|
|
|
|
$slides_container.css('width', $slides.length * 100 + '%');
|
|
|
|
},
|
|
|
|
|
|
|
|
_start_timer: function ($slides_container) {
|
|
|
|
var self = this,
|
|
|
|
$container = $slides_container.parent();
|
|
|
|
|
|
|
|
var callback = function() {
|
|
|
|
self._reset_timer($slides_container, false);
|
|
|
|
self._goto($slides_container, 'next', function() {
|
|
|
|
self._start_timer($slides_container);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
var $timer = $container.find('.' + self.settings.timer_container_class),
|
|
|
|
$progress = $timer.find('.' + self.settings.timer_progress_class),
|
|
|
|
progress_pct = ($progress.width() / $timer.width()),
|
|
|
|
delay = self.settings.timer_speed - (progress_pct * self.settings.timer_speed);
|
|
|
|
|
|
|
|
$progress.animate({'width': '100%'}, delay, 'linear', callback);
|
|
|
|
$slides_container.trigger('orbit:timer-started');
|
|
|
|
},
|
|
|
|
|
|
|
|
_stop_timer: function ($slides_container) {
|
|
|
|
var self = this,
|
|
|
|
$container = $slides_container.parent(),
|
|
|
|
$timer = $container.find('.' + self.settings.timer_container_class),
|
|
|
|
$progress = $timer.find('.' + self.settings.timer_progress_class),
|
|
|
|
progress_pct = $progress.width() / $timer.width();
|
|
|
|
self._rebuild_timer($container, progress_pct * 100 + '%');
|
|
|
|
// $progress.stop();
|
|
|
|
$slides_container.trigger('orbit:timer-stopped');
|
|
|
|
$timer = $container.find('.' + self.settings.timer_container_class);
|
|
|
|
$timer.addClass(self.settings.timer_paused_class);
|
|
|
|
},
|
|
|
|
|
|
|
|
_reset_timer: function($slides_container, is_paused) {
|
|
|
|
var self = this,
|
|
|
|
$container = $slides_container.parent();
|
|
|
|
self._rebuild_timer($container, '0%');
|
|
|
|
if (typeof is_paused === 'boolean' && is_paused) {
|
|
|
|
var $timer = $container.find('.' + self.settings.timer_container_class);
|
|
|
|
$timer.addClass(self.settings.timer_paused_class);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_rebuild_timer: function ($container, width_pct) {
|
|
|
|
// Zepto is unable to stop animations since they
|
|
|
|
// are css-based. This is a workaround for that
|
|
|
|
// limitation, which rebuilds the dom element
|
|
|
|
// thus stopping the animation
|
|
|
|
var self = this,
|
|
|
|
$timer = $container.find('.' + self.settings.timer_container_class),
|
|
|
|
$new_timer = $(self._timer_html()),
|
|
|
|
$new_timer_progress = $new_timer.find('.' + self.settings.timer_progress_class);
|
|
|
|
|
|
|
|
if (typeof Zepto === 'function') {
|
|
|
|
$timer.remove();
|
|
|
|
$container.append($new_timer);
|
|
|
|
$new_timer_progress.css('width', width_pct);
|
|
|
|
} else if (typeof jQuery === 'function') {
|
|
|
|
var $progress = $timer.find('.' + self.settings.timer_progress_class);
|
|
|
|
$progress.css('width', width_pct);
|
|
|
|
$progress.stop();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_goto: function($slides_container, index_or_direction, callback) {
|
|
|
|
var self = this,
|
|
|
|
$container = $slides_container.parent(),
|
|
|
|
$slides = $slides_container.children(),
|
|
|
|
$active_slide = $slides_container.find('.' + self.settings.active_slide_class),
|
|
|
|
active_index = $active_slide.index(),
|
|
|
|
margin_position = Foundation.rtl ? 'marginRight' : 'marginLeft';
|
|
|
|
|
|
|
|
if ($container.hasClass(self.settings.orbit_transition_class)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index_or_direction === 'prev') {
|
|
|
|
if (active_index === 0) {
|
|
|
|
active_index = $slides.length - 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
active_index--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (index_or_direction === 'next') {
|
|
|
|
active_index = (active_index+1) % $slides.length;
|
|
|
|
}
|
|
|
|
else if (typeof index_or_direction === 'number') {
|
|
|
|
active_index = (index_or_direction % $slides.length);
|
|
|
|
}
|
|
|
|
if (active_index === ($slides.length - 1) && index_or_direction === 'next') {
|
|
|
|
$slides_container.css(margin_position, '0%');
|
|
|
|
active_index = 1;
|
|
|
|
}
|
|
|
|
else if (active_index === 0 && index_or_direction === 'prev') {
|
|
|
|
$slides_container.css(margin_position, '-' + ($slides.length - 1) * 100 + '%');
|
|
|
|
active_index = $slides.length - 2;
|
|
|
|
}
|
|
|
|
// Start transition, make next slide active
|
|
|
|
$container.addClass(self.settings.orbit_transition_class);
|
|
|
|
$active_slide.removeClass(self.settings.active_slide_class);
|
|
|
|
$($slides[active_index]).addClass(self.settings.active_slide_class);
|
|
|
|
// Make next bullet active
|
|
|
|
var $bullets = $container.siblings('.' + self.settings.bullets_container_class);
|
|
|
|
if ($bullets.length === 1) {
|
|
|
|
$bullets.children().removeClass(self.settings.bullets_active_class);
|
|
|
|
$($bullets.children()[active_index-1]).addClass(self.settings.bullets_active_class);
|
|
|
|
}
|
|
|
|
var new_margin_left = '-' + (active_index * 100) + '%';
|
|
|
|
// Check to see if animation will occur, otherwise perform
|
|
|
|
// callbacks manually
|
|
|
|
$slides_container.trigger('orbit:before-slide-change');
|
|
|
|
if ($slides_container.css(margin_position) === new_margin_left) {
|
|
|
|
$container.removeClass(self.settings.orbit_transition_class);
|
|
|
|
$slides_container.trigger('orbit:after-slide-change', [{slide_number: active_index, total_slides: $slides_container.children().length - 2}]);
|
|
|
|
callback();
|
|
|
|
} else {
|
|
|
|
var properties = {};
|
|
|
|
properties[margin_position] = new_margin_left;
|
|
|
|
|
|
|
|
$slides_container.animate(properties, self.settings.animation_speed, 'linear', function() {
|
|
|
|
$container.removeClass(self.settings.orbit_transition_class);
|
|
|
|
$slides_container.trigger('orbit:after-slide-change', [{slide_number: active_index, total_slides: $slides_container.children().length - 2}]);
|
|
|
|
callback();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}(Foundation.zj, this, this.document));
|