jquery.flexslider.js 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218
  1. /*
  2. * jQuery FlexSlider v2.7.0
  3. * Copyright 2012 WooThemes
  4. * Contributing Author: Tyler Smith
  5. */
  6. ;
  7. (function ($) {
  8. var focused = true;
  9. //FlexSlider: Object Instance
  10. $.flexslider = function(el, options) {
  11. var slider = $(el);
  12. // making variables public
  13. //if rtl value was not passed and html is in rtl..enable it by default.
  14. if(typeof options.rtl=='undefined' && $('html').attr('dir')=='rtl'){
  15. options.rtl=true;
  16. }
  17. slider.vars = $.extend({}, $.flexslider.defaults, options);
  18. var namespace = slider.vars.namespace,
  19. msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,
  20. touch = (( "ontouchstart" in window ) || msGesture || window.DocumentTouch && document instanceof DocumentTouch) && slider.vars.touch,
  21. // deprecating this idea, as devices are being released with both of these events
  22. eventType = "click touchend MSPointerUp keyup",
  23. watchedEvent = "",
  24. watchedEventClearTimer,
  25. vertical = slider.vars.direction === "vertical",
  26. reverse = slider.vars.reverse,
  27. carousel = (slider.vars.itemWidth > 0),
  28. fade = slider.vars.animation === "fade",
  29. asNav = slider.vars.asNavFor !== "",
  30. methods = {};
  31. // Store a reference to the slider object
  32. $.data(el, "flexslider", slider);
  33. // Private slider methods
  34. methods = {
  35. init: function() {
  36. slider.animating = false;
  37. // Get current slide and make sure it is a number
  38. slider.currentSlide = parseInt( ( slider.vars.startAt ? slider.vars.startAt : 0), 10 );
  39. if ( isNaN( slider.currentSlide ) ) { slider.currentSlide = 0; }
  40. slider.animatingTo = slider.currentSlide;
  41. slider.atEnd = (slider.currentSlide === 0 || slider.currentSlide === slider.last);
  42. slider.containerSelector = slider.vars.selector.substr(0,slider.vars.selector.search(' '));
  43. slider.slides = $(slider.vars.selector, slider);
  44. slider.container = $(slider.containerSelector, slider);
  45. slider.count = slider.slides.length;
  46. // SYNC:
  47. slider.syncExists = $(slider.vars.sync).length > 0;
  48. // SLIDE:
  49. if (slider.vars.animation === "slide") { slider.vars.animation = "swing"; }
  50. slider.prop = (vertical) ? "top" : ( slider.vars.rtl ? "marginRight" : "marginLeft" );
  51. slider.args = {};
  52. // SLIDESHOW:
  53. slider.manualPause = false;
  54. slider.stopped = false;
  55. //PAUSE WHEN INVISIBLE
  56. slider.started = false;
  57. slider.startTimeout = null;
  58. // TOUCH/USECSS:
  59. slider.transitions = !slider.vars.video && !fade && slider.vars.useCSS && (function() {
  60. var obj = document.createElement('div'),
  61. props = ['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];
  62. for (var i in props) {
  63. if ( obj.style[ props[i] ] !== undefined ) {
  64. slider.pfx = props[i].replace('Perspective','').toLowerCase();
  65. slider.prop = "-" + slider.pfx + "-transform";
  66. return true;
  67. }
  68. }
  69. return false;
  70. }());
  71. slider.ensureAnimationEnd = '';
  72. // CONTROLSCONTAINER:
  73. if (slider.vars.controlsContainer !== "") slider.controlsContainer = $(slider.vars.controlsContainer).length > 0 && $(slider.vars.controlsContainer);
  74. // MANUAL:
  75. if (slider.vars.manualControls !== "") slider.manualControls = $(slider.vars.manualControls).length > 0 && $(slider.vars.manualControls);
  76. // CUSTOM DIRECTION NAV:
  77. if (slider.vars.customDirectionNav !== "") slider.customDirectionNav = $(slider.vars.customDirectionNav).length === 2 && $(slider.vars.customDirectionNav);
  78. // RANDOMIZE:
  79. if (slider.vars.randomize) {
  80. slider.slides.sort(function() { return (Math.round(Math.random())-0.5); });
  81. slider.container.empty().append(slider.slides);
  82. }
  83. slider.doMath();
  84. // INIT
  85. slider.setup("init");
  86. // CONTROLNAV:
  87. if (slider.vars.controlNav) { methods.controlNav.setup(); }
  88. // DIRECTIONNAV:
  89. if (slider.vars.directionNav) { methods.directionNav.setup(); }
  90. // KEYBOARD:
  91. if (slider.vars.keyboard && ($(slider.containerSelector).length === 1 || slider.vars.multipleKeyboard)) {
  92. $(document).bind('keyup', function(event) {
  93. var keycode = event.keyCode;
  94. if (!slider.animating && (keycode === 39 || keycode === 37)) {
  95. var target = (slider.vars.rtl?
  96. ((keycode === 37) ? slider.getTarget('next') :
  97. (keycode === 39) ? slider.getTarget('prev') : false)
  98. :
  99. ((keycode === 39) ? slider.getTarget('next') :
  100. (keycode === 37) ? slider.getTarget('prev') : false)
  101. )
  102. ;
  103. slider.flexAnimate(target, slider.vars.pauseOnAction);
  104. }
  105. });
  106. }
  107. // MOUSEWHEEL:
  108. if (slider.vars.mousewheel) {
  109. slider.bind('mousewheel', function(event, delta, deltaX, deltaY) {
  110. event.preventDefault();
  111. var target = (delta < 0) ? slider.getTarget('next') : slider.getTarget('prev');
  112. slider.flexAnimate(target, slider.vars.pauseOnAction);
  113. });
  114. }
  115. // PAUSEPLAY
  116. if (slider.vars.pausePlay) { methods.pausePlay.setup(); }
  117. //PAUSE WHEN INVISIBLE
  118. if (slider.vars.slideshow && slider.vars.pauseInvisible) { methods.pauseInvisible.init(); }
  119. // SLIDSESHOW
  120. if (slider.vars.slideshow) {
  121. if (slider.vars.pauseOnHover) {
  122. slider.hover(function() {
  123. if (!slider.manualPlay && !slider.manualPause) { slider.pause(); }
  124. }, function() {
  125. if (!slider.manualPause && !slider.manualPlay && !slider.stopped) { slider.play(); }
  126. });
  127. }
  128. // initialize animation
  129. //If we're visible, or we don't use PageVisibility API
  130. if(!slider.vars.pauseInvisible || !methods.pauseInvisible.isHidden()) {
  131. (slider.vars.initDelay > 0) ? slider.startTimeout = setTimeout(slider.play, slider.vars.initDelay) : slider.play();
  132. }
  133. }
  134. // ASNAV:
  135. if (asNav) { methods.asNav.setup(); }
  136. // TOUCH
  137. if (touch && slider.vars.touch) { methods.touch(); }
  138. // FADE&&SMOOTHHEIGHT || SLIDE:
  139. if (!fade || (fade && slider.vars.smoothHeight)) { $(window).bind("resize orientationchange focus", methods.resize); }
  140. slider.find("img").attr("draggable", "false");
  141. // API: start() Callback
  142. setTimeout(function(){
  143. slider.vars.start(slider);
  144. }, 200);
  145. },
  146. asNav: {
  147. setup: function() {
  148. slider.asNav = true;
  149. slider.animatingTo = Math.floor(slider.currentSlide/slider.move);
  150. slider.currentItem = slider.currentSlide;
  151. slider.slides.removeClass(namespace + "active-slide").eq(slider.currentItem).addClass(namespace + "active-slide");
  152. if(!msGesture){
  153. slider.slides.on(eventType, function(e){
  154. e.preventDefault();
  155. var $slide = $(this),
  156. target = $slide.index();
  157. var posFromX;
  158. if(slider.vars.rtl){
  159. posFromX = -1*($slide.offset().right - $(slider).scrollLeft()); // Find position of slide relative to right of slider container
  160. }
  161. else
  162. {
  163. posFromX = $slide.offset().left - $(slider).scrollLeft(); // Find position of slide relative to left of slider container
  164. }
  165. if( posFromX <= 0 && $slide.hasClass( namespace + 'active-slide' ) ) {
  166. slider.flexAnimate(slider.getTarget("prev"), true);
  167. } else if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass(namespace + "active-slide")) {
  168. slider.direction = (slider.currentItem < target) ? "next" : "prev";
  169. slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);
  170. }
  171. });
  172. }else{
  173. el._slider = slider;
  174. slider.slides.each(function (){
  175. var that = this;
  176. that._gesture = new MSGesture();
  177. that._gesture.target = that;
  178. that.addEventListener("MSPointerDown", function (e){
  179. e.preventDefault();
  180. if(e.currentTarget._gesture) {
  181. e.currentTarget._gesture.addPointer(e.pointerId);
  182. }
  183. }, false);
  184. that.addEventListener("MSGestureTap", function (e){
  185. e.preventDefault();
  186. var $slide = $(this),
  187. target = $slide.index();
  188. if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass('active')) {
  189. slider.direction = (slider.currentItem < target) ? "next" : "prev";
  190. slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);
  191. }
  192. });
  193. });
  194. }
  195. }
  196. },
  197. controlNav: {
  198. setup: function() {
  199. if (!slider.manualControls) {
  200. methods.controlNav.setupPaging();
  201. } else { // MANUALCONTROLS:
  202. methods.controlNav.setupManual();
  203. }
  204. },
  205. setupPaging: function() {
  206. var type = (slider.vars.controlNav === "thumbnails") ? 'control-thumbs' : 'control-paging',
  207. j = 1,
  208. item,
  209. slide;
  210. slider.controlNavScaffold = $('<ol class="'+ namespace + 'control-nav ' + namespace + type + '"></ol>');
  211. if (slider.pagingCount > 1) {
  212. for (var i = 0; i < slider.pagingCount; i++) {
  213. slide = slider.slides.eq(i);
  214. if ( undefined === slide.attr( 'data-thumb-alt' ) ) { slide.attr( 'data-thumb-alt', '' ); }
  215. var altText = ( '' !== slide.attr( 'data-thumb-alt' ) ) ? altText = ' alt="' + slide.attr( 'data-thumb-alt' ) + '"' : '';
  216. item = (slider.vars.controlNav === "thumbnails") ? '<img src="' + slide.attr( 'data-thumb' ) + '"' + altText + '/>' : '<a href="#">' + j + '</a>';
  217. if ( 'thumbnails' === slider.vars.controlNav && true === slider.vars.thumbCaptions ) {
  218. var captn = slide.attr( 'data-thumbcaption' );
  219. if ( '' !== captn && undefined !== captn ) { item += '<span class="' + namespace + 'caption">' + captn + '</span>'; }
  220. }
  221. slider.controlNavScaffold.append('<li>' + item + '</li>');
  222. j++;
  223. }
  224. }
  225. // CONTROLSCONTAINER:
  226. (slider.controlsContainer) ? $(slider.controlsContainer).append(slider.controlNavScaffold) : slider.append(slider.controlNavScaffold);
  227. methods.controlNav.set();
  228. methods.controlNav.active();
  229. slider.controlNavScaffold.delegate('a, img', eventType, function(event) {
  230. event.preventDefault();
  231. if (watchedEvent === "" || watchedEvent === event.type) {
  232. var $this = $(this),
  233. target = slider.controlNav.index($this);
  234. if (!$this.hasClass(namespace + 'active')) {
  235. slider.direction = (target > slider.currentSlide) ? "next" : "prev";
  236. slider.flexAnimate(target, slider.vars.pauseOnAction);
  237. }
  238. }
  239. // setup flags to prevent event duplication
  240. if (watchedEvent === "") {
  241. watchedEvent = event.type;
  242. }
  243. methods.setToClearWatchedEvent();
  244. });
  245. },
  246. setupManual: function() {
  247. slider.controlNav = slider.manualControls;
  248. methods.controlNav.active();
  249. slider.controlNav.bind(eventType, function(event) {
  250. event.preventDefault();
  251. if (watchedEvent === "" || watchedEvent === event.type) {
  252. var $this = $(this),
  253. target = slider.controlNav.index($this);
  254. if (!$this.hasClass(namespace + 'active')) {
  255. (target > slider.currentSlide) ? slider.direction = "next" : slider.direction = "prev";
  256. slider.flexAnimate(target, slider.vars.pauseOnAction);
  257. }
  258. }
  259. // setup flags to prevent event duplication
  260. if (watchedEvent === "") {
  261. watchedEvent = event.type;
  262. }
  263. methods.setToClearWatchedEvent();
  264. });
  265. },
  266. set: function() {
  267. var selector = (slider.vars.controlNav === "thumbnails") ? 'img' : 'a';
  268. slider.controlNav = $('.' + namespace + 'control-nav li ' + selector, (slider.controlsContainer) ? slider.controlsContainer : slider);
  269. },
  270. active: function() {
  271. slider.controlNav.removeClass(namespace + "active").eq(slider.animatingTo).addClass(namespace + "active");
  272. },
  273. update: function(action, pos) {
  274. if (slider.pagingCount > 1 && action === "add") {
  275. slider.controlNavScaffold.append($('<li><a href="#">' + slider.count + '</a></li>'));
  276. } else if (slider.pagingCount === 1) {
  277. slider.controlNavScaffold.find('li').remove();
  278. } else {
  279. slider.controlNav.eq(pos).closest('li').remove();
  280. }
  281. methods.controlNav.set();
  282. (slider.pagingCount > 1 && slider.pagingCount !== slider.controlNav.length) ? slider.update(pos, action) : methods.controlNav.active();
  283. }
  284. },
  285. directionNav: {
  286. setup: function() {
  287. var directionNavScaffold = $('<ul class="' + namespace + 'direction-nav"><li class="' + namespace + 'nav-prev"><a class="' + namespace + 'prev" href="#">' + slider.vars.prevText + '</a></li><li class="' + namespace + 'nav-next"><a class="' + namespace + 'next" href="#">' + slider.vars.nextText + '</a></li></ul>');
  288. // CUSTOM DIRECTION NAV:
  289. if (slider.customDirectionNav) {
  290. slider.directionNav = slider.customDirectionNav;
  291. // CONTROLSCONTAINER:
  292. } else if (slider.controlsContainer) {
  293. $(slider.controlsContainer).append(directionNavScaffold);
  294. slider.directionNav = $('.' + namespace + 'direction-nav li a', slider.controlsContainer);
  295. } else {
  296. slider.append(directionNavScaffold);
  297. slider.directionNav = $('.' + namespace + 'direction-nav li a', slider);
  298. }
  299. methods.directionNav.update();
  300. slider.directionNav.bind(eventType, function(event) {
  301. event.preventDefault();
  302. var target;
  303. if (watchedEvent === "" || watchedEvent === event.type) {
  304. target = ($(this).hasClass(namespace + 'next')) ? slider.getTarget('next') : slider.getTarget('prev');
  305. slider.flexAnimate(target, slider.vars.pauseOnAction);
  306. }
  307. // setup flags to prevent event duplication
  308. if (watchedEvent === "") {
  309. watchedEvent = event.type;
  310. }
  311. methods.setToClearWatchedEvent();
  312. });
  313. },
  314. update: function() {
  315. var disabledClass = namespace + 'disabled';
  316. if (slider.pagingCount === 1) {
  317. slider.directionNav.addClass(disabledClass).attr('tabindex', '-1');
  318. } else if (!slider.vars.animationLoop) {
  319. if (slider.animatingTo === 0) {
  320. slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "prev").addClass(disabledClass).attr('tabindex', '-1');
  321. } else if (slider.animatingTo === slider.last) {
  322. slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "next").addClass(disabledClass).attr('tabindex', '-1');
  323. } else {
  324. slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');
  325. }
  326. } else {
  327. slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');
  328. }
  329. }
  330. },
  331. pausePlay: {
  332. setup: function() {
  333. var pausePlayScaffold = $('<div class="' + namespace + 'pauseplay"><a href="#"></a></div>');
  334. // CONTROLSCONTAINER:
  335. if (slider.controlsContainer) {
  336. slider.controlsContainer.append(pausePlayScaffold);
  337. slider.pausePlay = $('.' + namespace + 'pauseplay a', slider.controlsContainer);
  338. } else {
  339. slider.append(pausePlayScaffold);
  340. slider.pausePlay = $('.' + namespace + 'pauseplay a', slider);
  341. }
  342. methods.pausePlay.update((slider.vars.slideshow) ? namespace + 'pause' : namespace + 'play');
  343. slider.pausePlay.bind(eventType, function(event) {
  344. event.preventDefault();
  345. if (watchedEvent === "" || watchedEvent === event.type) {
  346. if ($(this).hasClass(namespace + 'pause')) {
  347. slider.manualPause = true;
  348. slider.manualPlay = false;
  349. slider.pause();
  350. } else {
  351. slider.manualPause = false;
  352. slider.manualPlay = true;
  353. slider.play();
  354. }
  355. }
  356. // setup flags to prevent event duplication
  357. if (watchedEvent === "") {
  358. watchedEvent = event.type;
  359. }
  360. methods.setToClearWatchedEvent();
  361. });
  362. },
  363. update: function(state) {
  364. (state === "play") ? slider.pausePlay.removeClass(namespace + 'pause').addClass(namespace + 'play').html(slider.vars.playText) : slider.pausePlay.removeClass(namespace + 'play').addClass(namespace + 'pause').html(slider.vars.pauseText);
  365. }
  366. },
  367. touch: function() {
  368. var startX,
  369. startY,
  370. offset,
  371. cwidth,
  372. dx,
  373. startT,
  374. onTouchStart,
  375. onTouchMove,
  376. onTouchEnd,
  377. scrolling = false,
  378. localX = 0,
  379. localY = 0,
  380. accDx = 0;
  381. if(!msGesture){
  382. onTouchStart = function(e) {
  383. if (slider.animating) {
  384. e.preventDefault();
  385. } else if ( ( window.navigator.msPointerEnabled ) || e.touches.length === 1 ) {
  386. slider.pause();
  387. // CAROUSEL:
  388. cwidth = (vertical) ? slider.h : slider. w;
  389. startT = Number(new Date());
  390. // CAROUSEL:
  391. // Local vars for X and Y points.
  392. localX = e.touches[0].pageX;
  393. localY = e.touches[0].pageY;
  394. offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :
  395. (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
  396. (carousel && slider.currentSlide === slider.last) ? slider.limit :
  397. (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :
  398. (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;
  399. startX = (vertical) ? localY : localX;
  400. startY = (vertical) ? localX : localY;
  401. el.addEventListener('touchmove', onTouchMove, false);
  402. el.addEventListener('touchend', onTouchEnd, false);
  403. }
  404. };
  405. onTouchMove = function(e) {
  406. // Local vars for X and Y points.
  407. localX = e.touches[0].pageX;
  408. localY = e.touches[0].pageY;
  409. dx = (vertical) ? startX - localY : (slider.vars.rtl?-1:1)*(startX - localX);
  410. scrolling = (vertical) ? (Math.abs(dx) < Math.abs(localX - startY)) : (Math.abs(dx) < Math.abs(localY - startY));
  411. var fxms = 500;
  412. if ( ! scrolling || Number( new Date() ) - startT > fxms ) {
  413. e.preventDefault();
  414. if (!fade && slider.transitions) {
  415. if (!slider.vars.animationLoop) {
  416. dx = dx/((slider.currentSlide === 0 && dx < 0 || slider.currentSlide === slider.last && dx > 0) ? (Math.abs(dx)/cwidth+2) : 1);
  417. }
  418. slider.setProps(offset + dx, "setTouch");
  419. }
  420. }
  421. };
  422. onTouchEnd = function(e) {
  423. // finish the touch by undoing the touch session
  424. el.removeEventListener('touchmove', onTouchMove, false);
  425. if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {
  426. var updateDx = (reverse) ? -dx : dx,
  427. target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');
  428. if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth/2)) {
  429. slider.flexAnimate(target, slider.vars.pauseOnAction);
  430. } else {
  431. if (!fade) { slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true); }
  432. }
  433. }
  434. el.removeEventListener('touchend', onTouchEnd, false);
  435. startX = null;
  436. startY = null;
  437. dx = null;
  438. offset = null;
  439. };
  440. el.addEventListener('touchstart', onTouchStart, false);
  441. }else{
  442. el.style.msTouchAction = "none";
  443. el._gesture = new MSGesture();
  444. el._gesture.target = el;
  445. el.addEventListener("MSPointerDown", onMSPointerDown, false);
  446. el._slider = slider;
  447. el.addEventListener("MSGestureChange", onMSGestureChange, false);
  448. el.addEventListener("MSGestureEnd", onMSGestureEnd, false);
  449. function onMSPointerDown(e){
  450. e.stopPropagation();
  451. if (slider.animating) {
  452. e.preventDefault();
  453. }else{
  454. slider.pause();
  455. el._gesture.addPointer(e.pointerId);
  456. accDx = 0;
  457. cwidth = (vertical) ? slider.h : slider. w;
  458. startT = Number(new Date());
  459. // CAROUSEL:
  460. offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :
  461. (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
  462. (carousel && slider.currentSlide === slider.last) ? slider.limit :
  463. (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :
  464. (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;
  465. }
  466. }
  467. function onMSGestureChange(e) {
  468. e.stopPropagation();
  469. var slider = e.target._slider;
  470. if(!slider){
  471. return;
  472. }
  473. var transX = -e.translationX,
  474. transY = -e.translationY;
  475. //Accumulate translations.
  476. accDx = accDx + ((vertical) ? transY : transX);
  477. dx = (slider.vars.rtl?-1:1)*accDx;
  478. scrolling = (vertical) ? (Math.abs(accDx) < Math.abs(-transX)) : (Math.abs(accDx) < Math.abs(-transY));
  479. if(e.detail === e.MSGESTURE_FLAG_INERTIA){
  480. setImmediate(function (){
  481. el._gesture.stop();
  482. });
  483. return;
  484. }
  485. if (!scrolling || Number(new Date()) - startT > 500) {
  486. e.preventDefault();
  487. if (!fade && slider.transitions) {
  488. if (!slider.vars.animationLoop) {
  489. dx = accDx / ((slider.currentSlide === 0 && accDx < 0 || slider.currentSlide === slider.last && accDx > 0) ? (Math.abs(accDx) / cwidth + 2) : 1);
  490. }
  491. slider.setProps(offset + dx, "setTouch");
  492. }
  493. }
  494. }
  495. function onMSGestureEnd(e) {
  496. e.stopPropagation();
  497. var slider = e.target._slider;
  498. if(!slider){
  499. return;
  500. }
  501. if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {
  502. var updateDx = (reverse) ? -dx : dx,
  503. target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');
  504. if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth/2)) {
  505. slider.flexAnimate(target, slider.vars.pauseOnAction);
  506. } else {
  507. if (!fade) { slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true); }
  508. }
  509. }
  510. startX = null;
  511. startY = null;
  512. dx = null;
  513. offset = null;
  514. accDx = 0;
  515. }
  516. }
  517. },
  518. resize: function() {
  519. if (!slider.animating && slider.is(':visible')) {
  520. if (!carousel) { slider.doMath(); }
  521. if (fade) {
  522. // SMOOTH HEIGHT:
  523. methods.smoothHeight();
  524. } else if (carousel) { //CAROUSEL:
  525. slider.slides.width(slider.computedW);
  526. slider.update(slider.pagingCount);
  527. slider.setProps();
  528. }
  529. else if (vertical) { //VERTICAL:
  530. slider.viewport.height(slider.h);
  531. slider.setProps(slider.h, "setTotal");
  532. } else {
  533. // SMOOTH HEIGHT:
  534. if (slider.vars.smoothHeight) { methods.smoothHeight(); }
  535. slider.newSlides.width(slider.computedW);
  536. slider.setProps(slider.computedW, "setTotal");
  537. }
  538. }
  539. },
  540. smoothHeight: function(dur) {
  541. if (!vertical || fade) {
  542. var $obj = (fade) ? slider : slider.viewport;
  543. (dur) ? $obj.animate({"height": slider.slides.eq(slider.animatingTo).innerHeight()}, dur) : $obj.innerHeight(slider.slides.eq(slider.animatingTo).innerHeight());
  544. }
  545. },
  546. sync: function(action) {
  547. var $obj = $(slider.vars.sync).data("flexslider"),
  548. target = slider.animatingTo;
  549. switch (action) {
  550. case "animate": $obj.flexAnimate(target, slider.vars.pauseOnAction, false, true); break;
  551. case "play": if (!$obj.playing && !$obj.asNav) { $obj.play(); } break;
  552. case "pause": $obj.pause(); break;
  553. }
  554. },
  555. uniqueID: function($clone) {
  556. // Append _clone to current level and children elements with id attributes
  557. $clone.filter( '[id]' ).add($clone.find( '[id]' )).each(function() {
  558. var $this = $(this);
  559. $this.attr( 'id', $this.attr( 'id' ) + '_clone' );
  560. });
  561. return $clone;
  562. },
  563. pauseInvisible: {
  564. visProp: null,
  565. init: function() {
  566. var visProp = methods.pauseInvisible.getHiddenProp();
  567. if (visProp) {
  568. var evtname = visProp.replace(/[H|h]idden/,'') + 'visibilitychange';
  569. document.addEventListener(evtname, function() {
  570. if (methods.pauseInvisible.isHidden()) {
  571. if(slider.startTimeout) {
  572. clearTimeout(slider.startTimeout); //If clock is ticking, stop timer and prevent from starting while invisible
  573. } else {
  574. slider.pause(); //Or just pause
  575. }
  576. }
  577. else {
  578. if(slider.started) {
  579. slider.play(); //Initiated before, just play
  580. } else {
  581. if (slider.vars.initDelay > 0) {
  582. setTimeout(slider.play, slider.vars.initDelay);
  583. } else {
  584. slider.play(); //Didn't init before: simply init or wait for it
  585. }
  586. }
  587. }
  588. });
  589. }
  590. },
  591. isHidden: function() {
  592. var prop = methods.pauseInvisible.getHiddenProp();
  593. if (!prop) {
  594. return false;
  595. }
  596. return document[prop];
  597. },
  598. getHiddenProp: function() {
  599. var prefixes = ['webkit','moz','ms','o'];
  600. // if 'hidden' is natively supported just return it
  601. if ('hidden' in document) {
  602. return 'hidden';
  603. }
  604. // otherwise loop over all the known prefixes until we find one
  605. for ( var i = 0; i < prefixes.length; i++ ) {
  606. if ((prefixes[i] + 'Hidden') in document) {
  607. return prefixes[i] + 'Hidden';
  608. }
  609. }
  610. // otherwise it's not supported
  611. return null;
  612. }
  613. },
  614. setToClearWatchedEvent: function() {
  615. clearTimeout(watchedEventClearTimer);
  616. watchedEventClearTimer = setTimeout(function() {
  617. watchedEvent = "";
  618. }, 3000);
  619. }
  620. };
  621. // public methods
  622. slider.flexAnimate = function(target, pause, override, withSync, fromNav) {
  623. if (!slider.vars.animationLoop && target !== slider.currentSlide) {
  624. slider.direction = (target > slider.currentSlide) ? "next" : "prev";
  625. }
  626. if (asNav && slider.pagingCount === 1) slider.direction = (slider.currentItem < target) ? "next" : "prev";
  627. if (!slider.animating && (slider.canAdvance(target, fromNav) || override) && slider.is(":visible")) {
  628. if (asNav && withSync) {
  629. var master = $(slider.vars.asNavFor).data('flexslider');
  630. slider.atEnd = target === 0 || target === slider.count - 1;
  631. master.flexAnimate(target, true, false, true, fromNav);
  632. slider.direction = (slider.currentItem < target) ? "next" : "prev";
  633. master.direction = slider.direction;
  634. if (Math.ceil((target + 1)/slider.visible) - 1 !== slider.currentSlide && target !== 0) {
  635. slider.currentItem = target;
  636. slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
  637. target = Math.floor(target/slider.visible);
  638. } else {
  639. slider.currentItem = target;
  640. slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
  641. return false;
  642. }
  643. }
  644. slider.animating = true;
  645. slider.animatingTo = target;
  646. // SLIDESHOW:
  647. if (pause) { slider.pause(); }
  648. // API: before() animation Callback
  649. slider.vars.before(slider);
  650. // SYNC:
  651. if (slider.syncExists && !fromNav) { methods.sync("animate"); }
  652. // CONTROLNAV
  653. if (slider.vars.controlNav) { methods.controlNav.active(); }
  654. // !CAROUSEL:
  655. // CANDIDATE: slide active class (for add/remove slide)
  656. if (!carousel) { slider.slides.removeClass(namespace + 'active-slide').eq(target).addClass(namespace + 'active-slide'); }
  657. // INFINITE LOOP:
  658. // CANDIDATE: atEnd
  659. slider.atEnd = target === 0 || target === slider.last;
  660. // DIRECTIONNAV:
  661. if (slider.vars.directionNav) { methods.directionNav.update(); }
  662. if (target === slider.last) {
  663. // API: end() of cycle Callback
  664. slider.vars.end(slider);
  665. // SLIDESHOW && !INFINITE LOOP:
  666. if (!slider.vars.animationLoop) { slider.pause(); }
  667. }
  668. // SLIDE:
  669. if (!fade) {
  670. var dimension = (vertical) ? slider.slides.filter(':first').height() : slider.computedW,
  671. margin, slideString, calcNext;
  672. // INFINITE LOOP / REVERSE:
  673. if (carousel) {
  674. margin = slider.vars.itemMargin;
  675. calcNext = ((slider.itemW + margin) * slider.move) * slider.animatingTo;
  676. slideString = (calcNext > slider.limit && slider.visible !== 1) ? slider.limit : calcNext;
  677. } else if (slider.currentSlide === 0 && target === slider.count - 1 && slider.vars.animationLoop && slider.direction !== "next") {
  678. slideString = (reverse) ? (slider.count + slider.cloneOffset) * dimension : 0;
  679. } else if (slider.currentSlide === slider.last && target === 0 && slider.vars.animationLoop && slider.direction !== "prev") {
  680. slideString = (reverse) ? 0 : (slider.count + 1) * dimension;
  681. } else {
  682. slideString = (reverse) ? ((slider.count - 1) - target + slider.cloneOffset) * dimension : (target + slider.cloneOffset) * dimension;
  683. }
  684. slider.setProps(slideString, "", slider.vars.animationSpeed);
  685. if (slider.transitions) {
  686. if (!slider.vars.animationLoop || !slider.atEnd) {
  687. slider.animating = false;
  688. slider.currentSlide = slider.animatingTo;
  689. }
  690. // Unbind previous transitionEnd events and re-bind new transitionEnd event
  691. slider.container.unbind("webkitTransitionEnd transitionend");
  692. slider.container.bind("webkitTransitionEnd transitionend", function() {
  693. clearTimeout(slider.ensureAnimationEnd);
  694. slider.wrapup(dimension);
  695. });
  696. // Insurance for the ever-so-fickle transitionEnd event
  697. clearTimeout(slider.ensureAnimationEnd);
  698. slider.ensureAnimationEnd = setTimeout(function() {
  699. slider.wrapup(dimension);
  700. }, slider.vars.animationSpeed + 100);
  701. } else {
  702. slider.container.animate(slider.args, slider.vars.animationSpeed, slider.vars.easing, function(){
  703. slider.wrapup(dimension);
  704. });
  705. }
  706. } else { // FADE:
  707. if (!touch) {
  708. slider.slides.eq(slider.currentSlide).css({"zIndex": 1}).animate({"opacity": 0}, slider.vars.animationSpeed, slider.vars.easing);
  709. slider.slides.eq(target).css({"zIndex": 2}).animate({"opacity": 1}, slider.vars.animationSpeed, slider.vars.easing, slider.wrapup);
  710. } else {
  711. slider.slides.eq(slider.currentSlide).css({ "opacity": 0, "zIndex": 1 });
  712. slider.slides.eq(target).css({ "opacity": 1, "zIndex": 2 });
  713. slider.wrapup(dimension);
  714. }
  715. }
  716. // SMOOTH HEIGHT:
  717. if (slider.vars.smoothHeight) { methods.smoothHeight(slider.vars.animationSpeed); }
  718. }
  719. };
  720. slider.wrapup = function(dimension) {
  721. // SLIDE:
  722. if (!fade && !carousel) {
  723. if (slider.currentSlide === 0 && slider.animatingTo === slider.last && slider.vars.animationLoop) {
  724. slider.setProps(dimension, "jumpEnd");
  725. } else if (slider.currentSlide === slider.last && slider.animatingTo === 0 && slider.vars.animationLoop) {
  726. slider.setProps(dimension, "jumpStart");
  727. }
  728. }
  729. slider.animating = false;
  730. slider.currentSlide = slider.animatingTo;
  731. // API: after() animation Callback
  732. slider.vars.after(slider);
  733. };
  734. // SLIDESHOW:
  735. slider.animateSlides = function() {
  736. if (!slider.animating && focused ) { slider.flexAnimate(slider.getTarget("next")); }
  737. };
  738. // SLIDESHOW:
  739. slider.pause = function() {
  740. clearInterval(slider.animatedSlides);
  741. slider.animatedSlides = null;
  742. slider.playing = false;
  743. // PAUSEPLAY:
  744. if (slider.vars.pausePlay) { methods.pausePlay.update("play"); }
  745. // SYNC:
  746. if (slider.syncExists) { methods.sync("pause"); }
  747. };
  748. // SLIDESHOW:
  749. slider.play = function() {
  750. if (slider.playing) { clearInterval(slider.animatedSlides); }
  751. slider.animatedSlides = slider.animatedSlides || setInterval(slider.animateSlides, slider.vars.slideshowSpeed);
  752. slider.started = slider.playing = true;
  753. // PAUSEPLAY:
  754. if (slider.vars.pausePlay) { methods.pausePlay.update("pause"); }
  755. // SYNC:
  756. if (slider.syncExists) { methods.sync("play"); }
  757. };
  758. // STOP:
  759. slider.stop = function () {
  760. slider.pause();
  761. slider.stopped = true;
  762. };
  763. slider.canAdvance = function(target, fromNav) {
  764. // ASNAV:
  765. var last = (asNav) ? slider.pagingCount - 1 : slider.last;
  766. return (fromNav) ? true :
  767. (asNav && slider.currentItem === slider.count - 1 && target === 0 && slider.direction === "prev") ? true :
  768. (asNav && slider.currentItem === 0 && target === slider.pagingCount - 1 && slider.direction !== "next") ? false :
  769. (target === slider.currentSlide && !asNav) ? false :
  770. (slider.vars.animationLoop) ? true :
  771. (slider.atEnd && slider.currentSlide === 0 && target === last && slider.direction !== "next") ? false :
  772. (slider.atEnd && slider.currentSlide === last && target === 0 && slider.direction === "next") ? false :
  773. true;
  774. };
  775. slider.getTarget = function(dir) {
  776. slider.direction = dir;
  777. if (dir === "next") {
  778. return (slider.currentSlide === slider.last) ? 0 : slider.currentSlide + 1;
  779. } else {
  780. return (slider.currentSlide === 0) ? slider.last : slider.currentSlide - 1;
  781. }
  782. };
  783. // SLIDE:
  784. slider.setProps = function(pos, special, dur) {
  785. var target = (function() {
  786. var posCheck = (pos) ? pos : ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo,
  787. posCalc = (function() {
  788. if (carousel) {
  789. return (special === "setTouch") ? pos :
  790. (reverse && slider.animatingTo === slider.last) ? 0 :
  791. (reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
  792. (slider.animatingTo === slider.last) ? slider.limit : posCheck;
  793. } else {
  794. switch (special) {
  795. case "setTotal": return (reverse) ? ((slider.count - 1) - slider.currentSlide + slider.cloneOffset) * pos : (slider.currentSlide + slider.cloneOffset) * pos;
  796. case "setTouch": return (reverse) ? pos : pos;
  797. case "jumpEnd": return (reverse) ? pos : slider.count * pos;
  798. case "jumpStart": return (reverse) ? slider.count * pos : pos;
  799. default: return pos;
  800. }
  801. }
  802. }());
  803. return (posCalc * ((slider.vars.rtl)?1:-1)) + "px";
  804. }());
  805. if (slider.transitions) {
  806. target = (vertical) ? "translate3d(0," + target + ",0)" : "translate3d(" + ((slider.vars.rtl?-1:1)*parseInt(target)+'px') + ",0,0)";
  807. dur = (dur !== undefined) ? (dur/1000) + "s" : "0s";
  808. slider.container.css("-" + slider.pfx + "-transition-duration", dur);
  809. slider.container.css("transition-duration", dur);
  810. }
  811. slider.args[slider.prop] = target;
  812. if (slider.transitions || dur === undefined) { slider.container.css(slider.args); }
  813. slider.container.css('transform',target);
  814. };
  815. slider.setup = function(type) {
  816. // SLIDE:
  817. if (!fade) {
  818. var sliderOffset, arr;
  819. if (type === "init") {
  820. slider.viewport = $('<div class="' + namespace + 'viewport"></div>').css({"overflow": "hidden", "position": "relative"}).appendTo(slider).append(slider.container);
  821. // INFINITE LOOP:
  822. slider.cloneCount = 0;
  823. slider.cloneOffset = 0;
  824. // REVERSE:
  825. if (reverse) {
  826. arr = $.makeArray(slider.slides).reverse();
  827. slider.slides = $(arr);
  828. slider.container.empty().append(slider.slides);
  829. }
  830. }
  831. // INFINITE LOOP && !CAROUSEL:
  832. if (slider.vars.animationLoop && !carousel) {
  833. slider.cloneCount = 2;
  834. slider.cloneOffset = 1;
  835. // clear out old clones
  836. if (type !== "init") { slider.container.find('.clone').remove(); }
  837. slider.container.append(methods.uniqueID(slider.slides.first().clone().addClass('clone')).attr('aria-hidden', 'true'))
  838. .prepend(methods.uniqueID(slider.slides.last().clone().addClass('clone')).attr('aria-hidden', 'true'));
  839. }
  840. slider.newSlides = $(slider.vars.selector, slider);
  841. sliderOffset = (reverse) ? slider.count - 1 - slider.currentSlide + slider.cloneOffset : slider.currentSlide + slider.cloneOffset;
  842. // VERTICAL:
  843. if (vertical && !carousel) {
  844. slider.container.height((slider.count + slider.cloneCount) * 200 + "%").css("position", "absolute").width("100%");
  845. setTimeout(function(){
  846. slider.newSlides.css({"display": "block"});
  847. slider.doMath();
  848. slider.viewport.height(slider.h);
  849. slider.setProps(sliderOffset * slider.h, "init");
  850. }, (type === "init") ? 100 : 0);
  851. } else {
  852. slider.container.width((slider.count + slider.cloneCount) * 200 + "%");
  853. slider.setProps(sliderOffset * slider.computedW, "init");
  854. setTimeout(function(){
  855. slider.doMath();
  856. if(slider.vars.rtl){
  857. slider.newSlides.css({"width": slider.computedW, "marginRight" : slider.computedM, "float": "left", "display": "block"});
  858. }
  859. else{
  860. slider.newSlides.css({"width": slider.computedW, "marginRight" : slider.computedM, "float": "left", "display": "block"});
  861. }
  862. // SMOOTH HEIGHT:
  863. if (slider.vars.smoothHeight) { methods.smoothHeight(); }
  864. }, (type === "init") ? 100 : 0);
  865. }
  866. } else { // FADE:
  867. if(slider.vars.rtl){
  868. slider.slides.css({"width": "100%", "float": 'right', "marginLeft": "-100%", "position": "relative"});
  869. }
  870. else{
  871. slider.slides.css({"width": "100%", "float": 'left', "marginRight": "-100%", "position": "relative"});
  872. }
  873. if (type === "init") {
  874. if (!touch) {
  875. //slider.slides.eq(slider.currentSlide).fadeIn(slider.vars.animationSpeed, slider.vars.easing);
  876. if (slider.vars.fadeFirstSlide == false) {
  877. slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({"zIndex": 2}).css({"opacity": 1});
  878. } else {
  879. slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({"zIndex": 2}).animate({"opacity": 1},slider.vars.animationSpeed,slider.vars.easing);
  880. }
  881. } else {
  882. slider.slides.css({ "opacity": 0, "display": "block", "webkitTransition": "opacity " + slider.vars.animationSpeed / 1000 + "s ease", "zIndex": 1 }).eq(slider.currentSlide).css({ "opacity": 1, "zIndex": 2});
  883. }
  884. }
  885. // SMOOTH HEIGHT:
  886. if (slider.vars.smoothHeight) { methods.smoothHeight(); }
  887. }
  888. // !CAROUSEL:
  889. // CANDIDATE: active slide
  890. if (!carousel) { slider.slides.removeClass(namespace + "active-slide").eq(slider.currentSlide).addClass(namespace + "active-slide"); }
  891. //FlexSlider: init() Callback
  892. slider.vars.init(slider);
  893. };
  894. slider.doMath = function() {
  895. var slide = slider.slides.first(),
  896. slideMargin = slider.vars.itemMargin,
  897. minItems = slider.vars.minItems,
  898. maxItems = slider.vars.maxItems;
  899. slider.w = (slider.viewport===undefined) ? slider.width() : slider.viewport.width();
  900. slider.h = slide.height();
  901. slider.boxPadding = slide.outerWidth() - slide.width();
  902. // CAROUSEL:
  903. if (carousel) {
  904. slider.itemT = slider.vars.itemWidth + slideMargin;
  905. slider.itemM = slideMargin;
  906. slider.minW = (minItems) ? minItems * slider.itemT : slider.w;
  907. slider.maxW = (maxItems) ? (maxItems * slider.itemT) - slideMargin : slider.w;
  908. slider.itemW = (slider.minW > slider.w) ? (slider.w - (slideMargin * (minItems - 1)))/minItems :
  909. (slider.maxW < slider.w) ? (slider.w - (slideMargin * (maxItems - 1)))/maxItems :
  910. (slider.vars.itemWidth > slider.w) ? slider.w : slider.vars.itemWidth;
  911. slider.visible = Math.floor(slider.w/(slider.itemW));
  912. slider.move = (slider.vars.move > 0 && slider.vars.move < slider.visible ) ? slider.vars.move : slider.visible;
  913. slider.pagingCount = Math.ceil(((slider.count - slider.visible)/slider.move) + 1);
  914. slider.last = slider.pagingCount - 1;
  915. slider.limit = (slider.pagingCount === 1) ? 0 :
  916. (slider.vars.itemWidth > slider.w) ? (slider.itemW * (slider.count - 1)) + (slideMargin * (slider.count - 1)) : ((slider.itemW + slideMargin) * slider.count) - slider.w - slideMargin;
  917. } else {
  918. slider.itemW = slider.w;
  919. slider.itemM = slideMargin;
  920. slider.pagingCount = slider.count;
  921. slider.last = slider.count - 1;
  922. }
  923. slider.computedW = slider.itemW - slider.boxPadding;
  924. slider.computedM = slider.itemM;
  925. };
  926. slider.update = function(pos, action) {
  927. slider.doMath();
  928. // update currentSlide and slider.animatingTo if necessary
  929. if (!carousel) {
  930. if (pos < slider.currentSlide) {
  931. slider.currentSlide += 1;
  932. } else if (pos <= slider.currentSlide && pos !== 0) {
  933. slider.currentSlide -= 1;
  934. }
  935. slider.animatingTo = slider.currentSlide;
  936. }
  937. // update controlNav
  938. if (slider.vars.controlNav && !slider.manualControls) {
  939. if ((action === "add" && !carousel) || slider.pagingCount > slider.controlNav.length) {
  940. methods.controlNav.update("add");
  941. } else if ((action === "remove" && !carousel) || slider.pagingCount < slider.controlNav.length) {
  942. if (carousel && slider.currentSlide > slider.last) {
  943. slider.currentSlide -= 1;
  944. slider.animatingTo -= 1;
  945. }
  946. methods.controlNav.update("remove", slider.last);
  947. }
  948. }
  949. // update directionNav
  950. if (slider.vars.directionNav) { methods.directionNav.update(); }
  951. };
  952. slider.addSlide = function(obj, pos) {
  953. var $obj = $(obj);
  954. slider.count += 1;
  955. slider.last = slider.count - 1;
  956. // append new slide
  957. if (vertical && reverse) {
  958. (pos !== undefined) ? slider.slides.eq(slider.count - pos).after($obj) : slider.container.prepend($obj);
  959. } else {
  960. (pos !== undefined) ? slider.slides.eq(pos).before($obj) : slider.container.append($obj);
  961. }
  962. // update currentSlide, animatingTo, controlNav, and directionNav
  963. slider.update(pos, "add");
  964. // update slider.slides
  965. slider.slides = $(slider.vars.selector + ':not(.clone)', slider);
  966. // re-setup the slider to accomdate new slide
  967. slider.setup();
  968. //FlexSlider: added() Callback
  969. slider.vars.added(slider);
  970. };
  971. slider.removeSlide = function(obj) {
  972. var pos = (isNaN(obj)) ? slider.slides.index($(obj)) : obj;
  973. // update count
  974. slider.count -= 1;
  975. slider.last = slider.count - 1;
  976. // remove slide
  977. if (isNaN(obj)) {
  978. $(obj, slider.slides).remove();
  979. } else {
  980. (vertical && reverse) ? slider.slides.eq(slider.last).remove() : slider.slides.eq(obj).remove();
  981. }
  982. // update currentSlide, animatingTo, controlNav, and directionNav
  983. slider.doMath();
  984. slider.update(pos, "remove");
  985. // update slider.slides
  986. slider.slides = $(slider.vars.selector + ':not(.clone)', slider);
  987. // re-setup the slider to accomdate new slide
  988. slider.setup();
  989. // FlexSlider: removed() Callback
  990. slider.vars.removed(slider);
  991. };
  992. //FlexSlider: Initialize
  993. methods.init();
  994. };
  995. // Ensure the slider isn't focussed if the window loses focus.
  996. $( window ).blur( function ( e ) {
  997. focused = false;
  998. }).focus( function ( e ) {
  999. focused = true;
  1000. });
  1001. //FlexSlider: Default Settings
  1002. $.flexslider.defaults = {
  1003. namespace: "flex-", //{NEW} String: Prefix string attached to the class of every element generated by the plugin
  1004. selector: ".slides > li", //{NEW} Selector: Must match a simple pattern. '{container} > {slide}' -- Ignore pattern at your own peril
  1005. animation: "fade", //String: Select your animation type, "fade" or "slide"
  1006. easing: "swing", //{NEW} String: Determines the easing method used in jQuery transitions. jQuery easing plugin is supported!
  1007. direction: "horizontal", //String: Select the sliding direction, "horizontal" or "vertical"
  1008. reverse: false, //{NEW} Boolean: Reverse the animation direction
  1009. animationLoop: true, //Boolean: Should the animation loop? If false, directionNav will received "disable" classes at either end
  1010. smoothHeight: false, //{NEW} Boolean: Allow height of the slider to animate smoothly in horizontal mode
  1011. startAt: 0, //Integer: The slide that the slider should start on. Array notation (0 = first slide)
  1012. slideshow: true, //Boolean: Animate slider automatically
  1013. slideshowSpeed: 7000, //Integer: Set the speed of the slideshow cycling, in milliseconds
  1014. animationSpeed: 600, //Integer: Set the speed of animations, in milliseconds
  1015. initDelay: 0, //{NEW} Integer: Set an initialization delay, in milliseconds
  1016. randomize: false, //Boolean: Randomize slide order
  1017. fadeFirstSlide: true, //Boolean: Fade in the first slide when animation type is "fade"
  1018. thumbCaptions: false, //Boolean: Whether or not to put captions on thumbnails when using the "thumbnails" controlNav.
  1019. // Usability features
  1020. pauseOnAction: true, //Boolean: Pause the slideshow when interacting with control elements, highly recommended.
  1021. pauseOnHover: false, //Boolean: Pause the slideshow when hovering over slider, then resume when no longer hovering
  1022. pauseInvisible: true, //{NEW} Boolean: Pause the slideshow when tab is invisible, resume when visible. Provides better UX, lower CPU usage.
  1023. useCSS: true, //{NEW} Boolean: Slider will use CSS3 transitions if available
  1024. touch: true, //{NEW} Boolean: Allow touch swipe navigation of the slider on touch-enabled devices
  1025. video: false, //{NEW} Boolean: If using video in the slider, will prevent CSS3 3D Transforms to avoid graphical glitches
  1026. // Primary Controls
  1027. controlNav: true, //Boolean: Create navigation for paging control of each slide? Note: Leave true for manualControls usage
  1028. directionNav: true, //Boolean: Create navigation for previous/next navigation? (true/false)
  1029. prevText: "Previous", //String: Set the text for the "previous" directionNav item
  1030. nextText: "Next", //String: Set the text for the "next" directionNav item
  1031. // Secondary Navigation
  1032. keyboard: true, //Boolean: Allow slider navigating via keyboard left/right keys
  1033. multipleKeyboard: false, //{NEW} Boolean: Allow keyboard navigation to affect multiple sliders. Default behavior cuts out keyboard navigation with more than one slider present.
  1034. mousewheel: false, //{UPDATED} Boolean: Requires jquery.mousewheel.js (https://github.com/brandonaaron/jquery-mousewheel) - Allows slider navigating via mousewheel
  1035. pausePlay: false, //Boolean: Create pause/play dynamic element
  1036. pauseText: "Pause", //String: Set the text for the "pause" pausePlay item
  1037. playText: "Play", //String: Set the text for the "play" pausePlay item
  1038. // Special properties
  1039. controlsContainer: "", //{UPDATED} jQuery Object/Selector: Declare which container the navigation elements should be appended too. Default container is the FlexSlider element. Example use would be $(".flexslider-container"). Property is ignored if given element is not found.
  1040. manualControls: "", //{UPDATED} jQuery Object/Selector: Declare custom control navigation. Examples would be $(".flex-control-nav li") or "#tabs-nav li img", etc. The number of elements in your controlNav should match the number of slides/tabs.
  1041. customDirectionNav: "", //{NEW} jQuery Object/Selector: Custom prev / next button. Must be two jQuery elements. In order to make the events work they have to have the classes "prev" and "next" (plus namespace)
  1042. sync: "", //{NEW} Selector: Mirror the actions performed on this slider with another slider. Use with care.
  1043. asNavFor: "", //{NEW} Selector: Internal property exposed for turning the slider into a thumbnail navigation for another slider
  1044. // Carousel Options
  1045. itemWidth: 0, //{NEW} Integer: Box-model width of individual carousel items, including horizontal borders and padding.
  1046. itemMargin: 0, //{NEW} Integer: Margin between carousel items.
  1047. minItems: 1, //{NEW} Integer: Minimum number of carousel items that should be visible. Items will resize fluidly when below this.
  1048. maxItems: 0, //{NEW} Integer: Maxmimum number of carousel items that should be visible. Items will resize fluidly when above this limit.
  1049. move: 0, //{NEW} Integer: Number of carousel items that should move on animation. If 0, slider will move all visible items.
  1050. allowOneSlide: true, //{NEW} Boolean: Whether or not to allow a slider comprised of a single slide
  1051. // Callback API
  1052. start: function(){}, //Callback: function(slider) - Fires when the slider loads the first slide
  1053. before: function(){}, //Callback: function(slider) - Fires asynchronously with each slider animation
  1054. after: function(){}, //Callback: function(slider) - Fires after each slider animation completes
  1055. end: function(){}, //Callback: function(slider) - Fires when the slider reaches the last slide (asynchronous)
  1056. added: function(){}, //{NEW} Callback: function(slider) - Fires after a slide is added
  1057. removed: function(){}, //{NEW} Callback: function(slider) - Fires after a slide is removed
  1058. init: function() {}, //{NEW} Callback: function(slider) - Fires after the slider is initially setup
  1059. rtl: false //{NEW} Boolean: Whether or not to enable RTL mode
  1060. };
  1061. //FlexSlider: Plugin Function
  1062. $.fn.flexslider = function(options) {
  1063. if (options === undefined) { options = {}; }
  1064. if (typeof options === "object") {
  1065. return this.each(function() {
  1066. var $this = $(this),
  1067. selector = (options.selector) ? options.selector : ".slides > li",
  1068. $slides = $this.find(selector);
  1069. if ( ( $slides.length === 1 && options.allowOneSlide === false ) || $slides.length === 0 ) {
  1070. $slides.fadeIn(400);
  1071. if (options.start) { options.start($this); }
  1072. } else if ($this.data('flexslider') === undefined) {
  1073. new $.flexslider(this, options);
  1074. }
  1075. });
  1076. } else {
  1077. // Helper strings to quickly perform functions on the slider
  1078. var $slider = $(this).data('flexslider');
  1079. switch (options) {
  1080. case "play": $slider.play(); break;
  1081. case "pause": $slider.pause(); break;
  1082. case "stop": $slider.stop(); break;
  1083. case "next": $slider.flexAnimate($slider.getTarget("next"), true); break;
  1084. case "prev":
  1085. case "previous": $slider.flexAnimate($slider.getTarget("prev"), true); break;
  1086. default: if (typeof options === "number") { $slider.flexAnimate(options, true); }
  1087. }
  1088. }
  1089. };
  1090. })(jQuery);