foundation.orbit.js 15 KB

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