foundation.orbit.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. ;(function ($, window, document, undefined) {
  2. 'use strict';
  3. var noop = function() {};
  4. var Orbit = function(el, settings) {
  5. // Don't reinitialize plugin
  6. if (el.hasClass(settings.slides_container_class)) {
  7. return this;
  8. }
  9. var self = this,
  10. container,
  11. slides_container = el,
  12. number_container,
  13. bullets_container,
  14. timer_container,
  15. idx = 0,
  16. animate,
  17. timer,
  18. locked = false,
  19. adjust_height_after = false;
  20. self.slides = function() {
  21. return slides_container.children(settings.slide_selector);
  22. };
  23. self.slides().first().addClass(settings.active_slide_class);
  24. self.update_slide_number = function(index) {
  25. if (settings.slide_number) {
  26. number_container.find('span:first').text(parseInt(index)+1);
  27. number_container.find('span:last').text(self.slides().length);
  28. }
  29. if (settings.bullets) {
  30. bullets_container.children().removeClass(settings.bullets_active_class);
  31. $(bullets_container.children().get(index)).addClass(settings.bullets_active_class);
  32. }
  33. };
  34. self.update_active_link = function(index) {
  35. var link = $('a[data-orbit-link="'+self.slides().eq(index).attr('data-orbit-slide')+'"]');
  36. link.siblings().removeClass(settings.bullets_active_class);
  37. link.addClass(settings.bullets_active_class);
  38. };
  39. self.build_markup = function() {
  40. slides_container.wrap('<div class="'+settings.container_class+'"></div>');
  41. container = slides_container.parent();
  42. slides_container.addClass(settings.slides_container_class);
  43. if (settings.navigation_arrows) {
  44. container.append($('<a href="#"><span></span></a>').addClass(settings.prev_class));
  45. container.append($('<a href="#"><span></span></a>').addClass(settings.next_class));
  46. }
  47. if (settings.timer) {
  48. timer_container = $('<div>').addClass(settings.timer_container_class);
  49. timer_container.append('<span>');
  50. timer_container.append($('<div>').addClass(settings.timer_progress_class));
  51. timer_container.addClass(settings.timer_paused_class);
  52. container.append(timer_container);
  53. }
  54. if (settings.slide_number) {
  55. number_container = $('<div>').addClass(settings.slide_number_class);
  56. number_container.append('<span></span> ' + settings.slide_number_text + ' <span></span>');
  57. container.append(number_container);
  58. }
  59. if (settings.bullets) {
  60. bullets_container = $('<ol>').addClass(settings.bullets_container_class);
  61. container.append(bullets_container);
  62. bullets_container.wrap('<div class="orbit-bullets-container"></div>');
  63. self.slides().each(function(idx, el) {
  64. var bullet = $('<li>').attr('data-orbit-slide', idx);
  65. bullets_container.append(bullet);
  66. });
  67. }
  68. if (settings.stack_on_small) {
  69. container.addClass(settings.stack_on_small_class);
  70. }
  71. };
  72. self._goto = function(next_idx, start_timer) {
  73. // if (locked) {return false;}
  74. if (next_idx === idx) {return false;}
  75. if (typeof timer === 'object') {timer.restart();}
  76. var slides = self.slides();
  77. var dir = 'next';
  78. locked = true;
  79. if (next_idx < idx) {dir = 'prev';}
  80. if (next_idx >= slides.length) {
  81. if (!settings.circular) return false;
  82. next_idx = 0;
  83. } else if (next_idx < 0) {
  84. if (!settings.circular) return false;
  85. next_idx = slides.length - 1;
  86. }
  87. var current = $(slides.get(idx));
  88. var next = $(slides.get(next_idx));
  89. current.css('zIndex', 2);
  90. current.removeClass(settings.active_slide_class);
  91. next.css('zIndex', 4).addClass(settings.active_slide_class);
  92. slides_container.trigger('before-slide-change.fndtn.orbit');
  93. settings.before_slide_change();
  94. self.update_active_link(next_idx);
  95. var callback = function() {
  96. var unlock = function() {
  97. idx = next_idx;
  98. locked = false;
  99. if (start_timer === true) {timer = self.create_timer(); timer.start();}
  100. self.update_slide_number(idx);
  101. slides_container.trigger('after-slide-change.fndtn.orbit',[{slide_number: idx, total_slides: slides.length}]);
  102. settings.after_slide_change(idx, slides.length);
  103. };
  104. if (slides_container.height() != next.height() && settings.variable_height) {
  105. slides_container.animate({'height': next.height()}, 250, 'linear', unlock);
  106. } else {
  107. unlock();
  108. }
  109. };
  110. if (slides.length === 1) {callback(); return false;}
  111. var start_animation = function() {
  112. if (dir === 'next') {animate.next(current, next, callback);}
  113. if (dir === 'prev') {animate.prev(current, next, callback);}
  114. };
  115. if (next.height() > slides_container.height() && settings.variable_height) {
  116. slides_container.animate({'height': next.height()}, 250, 'linear', start_animation);
  117. } else {
  118. start_animation();
  119. }
  120. };
  121. self.next = function(e) {
  122. e.stopImmediatePropagation();
  123. e.preventDefault();
  124. self._goto(idx + 1);
  125. };
  126. self.prev = function(e) {
  127. e.stopImmediatePropagation();
  128. e.preventDefault();
  129. self._goto(idx - 1);
  130. };
  131. self.link_custom = function(e) {
  132. e.preventDefault();
  133. var link = $(this).attr('data-orbit-link');
  134. if ((typeof link === 'string') && (link = $.trim(link)) != "") {
  135. var slide = container.find('[data-orbit-slide='+link+']');
  136. if (slide.index() != -1) {self._goto(slide.index());}
  137. }
  138. };
  139. self.link_bullet = function(e) {
  140. var index = $(this).attr('data-orbit-slide');
  141. if ((typeof index === 'string') && (index = $.trim(index)) != "") {
  142. if(isNaN(parseInt(index)))
  143. {
  144. var slide = container.find('[data-orbit-slide='+index+']');
  145. if (slide.index() != -1) {self._goto(slide.index() + 1);}
  146. }
  147. else
  148. {
  149. self._goto(parseInt(index));
  150. }
  151. }
  152. }
  153. self.timer_callback = function() {
  154. self._goto(idx + 1, true);
  155. }
  156. self.compute_dimensions = function() {
  157. var current = $(self.slides().get(idx));
  158. var h = current.height();
  159. if (!settings.variable_height) {
  160. self.slides().each(function(){
  161. if ($(this).height() > h) { h = $(this).height(); }
  162. });
  163. }
  164. slides_container.height(h);
  165. };
  166. self.create_timer = function() {
  167. var t = new Timer(
  168. container.find('.'+settings.timer_container_class),
  169. settings,
  170. self.timer_callback
  171. );
  172. return t;
  173. };
  174. self.stop_timer = function() {
  175. if (typeof timer === 'object') timer.stop();
  176. };
  177. self.toggle_timer = function() {
  178. var t = container.find('.'+settings.timer_container_class);
  179. if (t.hasClass(settings.timer_paused_class)) {
  180. if (typeof timer === 'undefined') {timer = self.create_timer();}
  181. timer.start();
  182. }
  183. else {
  184. if (typeof timer === 'object') {timer.stop();}
  185. }
  186. };
  187. self.init = function() {
  188. self.build_markup();
  189. if (settings.timer) {
  190. timer = self.create_timer();
  191. Foundation.utils.image_loaded(this.slides().children('img'), timer.start);
  192. }
  193. animate = new FadeAnimation(settings, slides_container);
  194. if (settings.animation === 'slide')
  195. animate = new SlideAnimation(settings, slides_container);
  196. container.on('click', '.'+settings.next_class, self.next);
  197. container.on('click', '.'+settings.prev_class, self.prev);
  198. container.on('click', '[data-orbit-slide]', self.link_bullet);
  199. container.on('click', self.toggle_timer);
  200. if (settings.swipe) {
  201. container.on('touchstart.fndtn.orbit', function(e) {
  202. if (!e.touches) {e = e.originalEvent;}
  203. var data = {
  204. start_page_x: e.touches[0].pageX,
  205. start_page_y: e.touches[0].pageY,
  206. start_time: (new Date()).getTime(),
  207. delta_x: 0,
  208. is_scrolling: undefined
  209. };
  210. container.data('swipe-transition', data);
  211. e.stopPropagation();
  212. })
  213. .on('touchmove.fndtn.orbit', function(e) {
  214. if (!e.touches) { e = e.originalEvent; }
  215. // Ignore pinch/zoom events
  216. if(e.touches.length > 1 || e.scale && e.scale !== 1) return;
  217. var data = container.data('swipe-transition');
  218. if (typeof data === 'undefined') {data = {};}
  219. data.delta_x = e.touches[0].pageX - data.start_page_x;
  220. if ( typeof data.is_scrolling === 'undefined') {
  221. data.is_scrolling = !!( data.is_scrolling || Math.abs(data.delta_x) < Math.abs(e.touches[0].pageY - data.start_page_y) );
  222. }
  223. if (!data.is_scrolling && !data.active) {
  224. e.preventDefault();
  225. var direction = (data.delta_x < 0) ? (idx+1) : (idx-1);
  226. data.active = true;
  227. self._goto(direction);
  228. }
  229. })
  230. .on('touchend.fndtn.orbit', function(e) {
  231. container.data('swipe-transition', {});
  232. e.stopPropagation();
  233. })
  234. }
  235. container.on('mouseenter.fndtn.orbit', function(e) {
  236. if (settings.timer && settings.pause_on_hover) {
  237. self.stop_timer();
  238. }
  239. })
  240. .on('mouseleave.fndtn.orbit', function(e) {
  241. if (settings.timer && settings.resume_on_mouseout) {
  242. timer.start();
  243. }
  244. });
  245. $(document).on('click', '[data-orbit-link]', self.link_custom);
  246. $(window).on('resize', self.compute_dimensions);
  247. Foundation.utils.image_loaded(this.slides().children('img'), self.compute_dimensions);
  248. Foundation.utils.image_loaded(this.slides().children('img'), function() {
  249. container.prev('.preloader').css('display', 'none');
  250. self.update_slide_number(0);
  251. self.update_active_link(0);
  252. slides_container.trigger('ready.fndtn.orbit');
  253. });
  254. };
  255. self.init();
  256. };
  257. var Timer = function(el, settings, callback) {
  258. var self = this,
  259. duration = settings.timer_speed,
  260. progress = el.find('.'+settings.timer_progress_class),
  261. start,
  262. timeout,
  263. left = -1;
  264. this.update_progress = function(w) {
  265. var new_progress = progress.clone();
  266. new_progress.attr('style', '');
  267. new_progress.css('width', w+'%');
  268. progress.replaceWith(new_progress);
  269. progress = new_progress;
  270. };
  271. this.restart = function() {
  272. clearTimeout(timeout);
  273. el.addClass(settings.timer_paused_class);
  274. left = -1;
  275. self.update_progress(0);
  276. };
  277. this.start = function() {
  278. if (!el.hasClass(settings.timer_paused_class)) {return true;}
  279. left = (left === -1) ? duration : left;
  280. el.removeClass(settings.timer_paused_class);
  281. start = new Date().getTime();
  282. progress.animate({'width': '100%'}, left, 'linear');
  283. timeout = setTimeout(function() {
  284. self.restart();
  285. callback();
  286. }, left);
  287. el.trigger('timer-started.fndtn.orbit')
  288. };
  289. this.stop = function() {
  290. if (el.hasClass(settings.timer_paused_class)) {return true;}
  291. clearTimeout(timeout);
  292. el.addClass(settings.timer_paused_class);
  293. var end = new Date().getTime();
  294. left = left - (end - start);
  295. var w = 100 - ((left / duration) * 100);
  296. self.update_progress(w);
  297. el.trigger('timer-stopped.fndtn.orbit');
  298. };
  299. };
  300. var SlideAnimation = function(settings, container) {
  301. var duration = settings.animation_speed;
  302. var is_rtl = ($('html[dir=rtl]').length === 1);
  303. var margin = is_rtl ? 'marginRight' : 'marginLeft';
  304. var animMargin = {};
  305. animMargin[margin] = '0%';
  306. this.next = function(current, next, callback) {
  307. current.animate({marginLeft:'-100%'}, duration);
  308. next.animate(animMargin, duration, function() {
  309. current.css(margin, '100%');
  310. callback();
  311. });
  312. };
  313. this.prev = function(current, prev, callback) {
  314. current.animate({marginLeft:'100%'}, duration);
  315. prev.css(margin, '-100%');
  316. prev.animate(animMargin, duration, function() {
  317. current.css(margin, '100%');
  318. callback();
  319. });
  320. };
  321. };
  322. var FadeAnimation = function(settings, container) {
  323. var duration = settings.animation_speed;
  324. var is_rtl = ($('html[dir=rtl]').length === 1);
  325. var margin = is_rtl ? 'marginRight' : 'marginLeft';
  326. this.next = function(current, next, callback) {
  327. next.css({'margin':'0%', 'opacity':'0.01'});
  328. next.animate({'opacity':'1'}, duration, 'linear', function() {
  329. current.css('margin', '100%');
  330. callback();
  331. });
  332. };
  333. this.prev = function(current, prev, callback) {
  334. prev.css({'margin':'0%', 'opacity':'0.01'});
  335. prev.animate({'opacity':'1'}, duration, 'linear', function() {
  336. current.css('margin', '100%');
  337. callback();
  338. });
  339. };
  340. };
  341. Foundation.libs = Foundation.libs || {};
  342. Foundation.libs.orbit = {
  343. name: 'orbit',
  344. version: '5.1.1',
  345. settings: {
  346. animation: 'slide',
  347. timer_speed: 10000,
  348. pause_on_hover: true,
  349. resume_on_mouseout: false,
  350. animation_speed: 500,
  351. stack_on_small: false,
  352. navigation_arrows: true,
  353. slide_number: true,
  354. slide_number_text: 'of',
  355. container_class: 'orbit-container',
  356. stack_on_small_class: 'orbit-stack-on-small',
  357. next_class: 'orbit-next',
  358. prev_class: 'orbit-prev',
  359. timer_container_class: 'orbit-timer',
  360. timer_paused_class: 'paused',
  361. timer_progress_class: 'orbit-progress',
  362. slides_container_class: 'orbit-slides-container',
  363. slide_selector: '*',
  364. bullets_container_class: 'orbit-bullets',
  365. bullets_active_class: 'active',
  366. slide_number_class: 'orbit-slide-number',
  367. caption_class: 'orbit-caption',
  368. active_slide_class: 'active',
  369. orbit_transition_class: 'orbit-transitioning',
  370. bullets: true,
  371. circular: true,
  372. timer: true,
  373. variable_height: false,
  374. swipe: true,
  375. before_slide_change: noop,
  376. after_slide_change: noop
  377. },
  378. init : function (scope, method, options) {
  379. var self = this;
  380. this.bindings(method, options);
  381. },
  382. events : function (instance) {
  383. var orbit_instance = new Orbit(this.S(instance), this.S(instance).data('orbit-init'));
  384. this.S(instance).data(self.name + '-instance', orbit_instance);
  385. },
  386. reflow : function () {
  387. var self = this;
  388. if (self.S(self.scope).is('[data-orbit]')) {
  389. var $el = self.S(self.scope);
  390. var instance = $el.data(self.name + '-instance');
  391. instance.compute_dimensions();
  392. } else {
  393. self.S('[data-orbit]', self.scope).each(function(idx, el) {
  394. var $el = self.S(el);
  395. var opts = self.data_options($el);
  396. var instance = $el.data(self.name + '-instance');
  397. instance.compute_dimensions();
  398. });
  399. }
  400. }
  401. };
  402. }(jQuery, this, this.document));