You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

412 line
13 KiB

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