Projet

Général

Profil

Paste
Télécharger (53,6 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / libraries / flexslider-2.5.0 / jquery.flexslider.js @ 99781f3b

1
/*
2
 * jQuery FlexSlider v2.5.0
3
 * Copyright 2012 WooThemes
4
 * Contributing Author: Tyler Smith
5
 */
6
;
7
(function ($) {
8

    
9
  //FlexSlider: Object Instance
10
  $.flexslider = function(el, options) {
11
    var slider = $(el);
12

    
13
    // making variables public
14
    slider.vars = $.extend({}, $.flexslider.defaults, options);
15

    
16
    var namespace = slider.vars.namespace,
17
        msGesture = window.navigator && window.navigator.msPointerEnabled && window.MSGesture,
18
        touch = (( "ontouchstart" in window ) || msGesture || window.DocumentTouch && document instanceof DocumentTouch) && slider.vars.touch,
19
        // depricating this idea, as devices are being released with both of these events
20
        //eventType = (touch) ? "touchend" : "click",
21
        eventType = "click touchend MSPointerUp keyup",
22
        watchedEvent = "",
23
        watchedEventClearTimer,
24
        vertical = slider.vars.direction === "vertical",
25
        reverse = slider.vars.reverse,
26
        carousel = (slider.vars.itemWidth > 0),
27
        fade = slider.vars.animation === "fade",
28
        asNav = slider.vars.asNavFor !== "",
29
        methods = {},
30
        focused = true;
31

    
32
    // Store a reference to the slider object
33
    $.data(el, "flexslider", slider);
34

    
35
    // Private slider methods
36
    methods = {
37
      init: function() {
38
        slider.animating = false;
39
        // Get current slide and make sure it is a number
40
        slider.currentSlide = parseInt( ( slider.vars.startAt ? slider.vars.startAt : 0), 10 );
41
        if ( isNaN( slider.currentSlide ) ) { slider.currentSlide = 0; }
42
        slider.animatingTo = slider.currentSlide;
43
        slider.atEnd = (slider.currentSlide === 0 || slider.currentSlide === slider.last);
44
        slider.containerSelector = slider.vars.selector.substr(0,slider.vars.selector.search(' '));
45
        slider.slides = $(slider.vars.selector, slider);
46
        slider.container = $(slider.containerSelector, slider);
47
        slider.count = slider.slides.length;
48
        // SYNC:
49
        slider.syncExists = $(slider.vars.sync).length > 0;
50
        // SLIDE:
51
        if (slider.vars.animation === "slide") { slider.vars.animation = "swing"; }
52
        slider.prop = (vertical) ? "top" : "marginLeft";
53
        slider.args = {};
54
        // SLIDESHOW:
55
        slider.manualPause = false;
56
        slider.stopped = false;
57
        //PAUSE WHEN INVISIBLE
58
        slider.started = false;
59
        slider.startTimeout = null;
60
        // TOUCH/USECSS:
61
        slider.transitions = !slider.vars.video && !fade && slider.vars.useCSS && (function() {
62
          var obj = document.createElement('div'),
63
              props = ['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];
64
          for (var i in props) {
65
            if ( obj.style[ props[i] ] !== undefined ) {
66
              slider.pfx = props[i].replace('Perspective','').toLowerCase();
67
              slider.prop = "-" + slider.pfx + "-transform";
68
              return true;
69
            }
70
          }
71
          return false;
72
        }());
73
        slider.ensureAnimationEnd = '';
74
        // CONTROLSCONTAINER:
75
        if (slider.vars.controlsContainer !== "") slider.controlsContainer = $(slider.vars.controlsContainer).length > 0 && $(slider.vars.controlsContainer);
76
        // MANUAL:
77
        if (slider.vars.manualControls !== "") slider.manualControls = $(slider.vars.manualControls).length > 0 && $(slider.vars.manualControls);
78

    
79
        // CUSTOM DIRECTION NAV:
80
        if (slider.vars.customDirectionNav !== "") slider.customDirectionNav = $(slider.vars.customDirectionNav).length === 2 && $(slider.vars.customDirectionNav);
81

    
82
        // RANDOMIZE:
83
        if (slider.vars.randomize) {
84
          slider.slides.sort(function() { return (Math.round(Math.random())-0.5); });
85
          slider.container.empty().append(slider.slides);
86
        }
87

    
88
        slider.doMath();
89

    
90
        // INIT
91
        slider.setup("init");
92

    
93
        // CONTROLNAV:
94
        if (slider.vars.controlNav) { methods.controlNav.setup(); }
95

    
96
        // DIRECTIONNAV:
97
        if (slider.vars.directionNav) { methods.directionNav.setup(); }
98

    
99
        // KEYBOARD:
100
        if (slider.vars.keyboard && ($(slider.containerSelector).length === 1 || slider.vars.multipleKeyboard)) {
101
          $(document).bind('keyup', function(event) {
102
            var keycode = event.keyCode;
103
            if (!slider.animating && (keycode === 39 || keycode === 37)) {
104
              var target = (keycode === 39) ? slider.getTarget('next') :
105
                           (keycode === 37) ? slider.getTarget('prev') : false;
106
              slider.flexAnimate(target, slider.vars.pauseOnAction);
107
            }
108
          });
109
        }
110
        // MOUSEWHEEL:
111
        if (slider.vars.mousewheel) {
112
          slider.bind('mousewheel', function(event, delta, deltaX, deltaY) {
113
            event.preventDefault();
114
            var target = (delta < 0) ? slider.getTarget('next') : slider.getTarget('prev');
115
            slider.flexAnimate(target, slider.vars.pauseOnAction);
116
          });
117
        }
118

    
119
        // PAUSEPLAY
120
        if (slider.vars.pausePlay) { methods.pausePlay.setup(); }
121

    
122
        //PAUSE WHEN INVISIBLE
123
        if (slider.vars.slideshow && slider.vars.pauseInvisible) { methods.pauseInvisible.init(); }
124

    
125
        // SLIDSESHOW
126
        if (slider.vars.slideshow) {
127
          if (slider.vars.pauseOnHover) {
128
            slider.hover(function() {
129
              if (!slider.manualPlay && !slider.manualPause) { slider.pause(); }
130
            }, function() {
131
              if (!slider.manualPause && !slider.manualPlay && !slider.stopped) { slider.play(); }
132
            });
133
          }
134
          // initialize animation
135
          //If we're visible, or we don't use PageVisibility API
136
          if(!slider.vars.pauseInvisible || !methods.pauseInvisible.isHidden()) {
137
            (slider.vars.initDelay > 0) ? slider.startTimeout = setTimeout(slider.play, slider.vars.initDelay) : slider.play();
138
          }
139
        }
140

    
141
        // ASNAV:
142
        if (asNav) { methods.asNav.setup(); }
143

    
144
        // TOUCH
145
        if (touch && slider.vars.touch) { methods.touch(); }
146

    
147
        // FADE&&SMOOTHHEIGHT || SLIDE:
148
        if (!fade || (fade && slider.vars.smoothHeight)) { $(window).bind("resize orientationchange focus", methods.resize); }
149

    
150
        slider.find("img").attr("draggable", "false");
151

    
152
        // API: start() Callback
153
        setTimeout(function(){
154
          slider.vars.start(slider);
155
        }, 200);
156
      },
157
      asNav: {
158
        setup: function() {
159
          slider.asNav = true;
160
          slider.animatingTo = Math.floor(slider.currentSlide/slider.move);
161
          slider.currentItem = slider.currentSlide;
162
          slider.slides.removeClass(namespace + "active-slide").eq(slider.currentItem).addClass(namespace + "active-slide");
163
          if(!msGesture){
164
              slider.slides.on(eventType, function(e){
165
                e.preventDefault();
166
                var $slide = $(this),
167
                    target = $slide.index();
168
                var posFromLeft = $slide.offset().left - $(slider).scrollLeft(); // Find position of slide relative to left of slider container
169
                if( posFromLeft <= 0 && $slide.hasClass( namespace + 'active-slide' ) ) {
170
                  slider.flexAnimate(slider.getTarget("prev"), true);
171
                } else if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass(namespace + "active-slide")) {
172
                  slider.direction = (slider.currentItem < target) ? "next" : "prev";
173
                  slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);
174
                }
175
              });
176
          }else{
177
              el._slider = slider;
178
              slider.slides.each(function (){
179
                  var that = this;
180
                  that._gesture = new MSGesture();
181
                  that._gesture.target = that;
182
                  that.addEventListener("MSPointerDown", function (e){
183
                      e.preventDefault();
184
                      if(e.currentTarget._gesture) {
185
                        e.currentTarget._gesture.addPointer(e.pointerId);
186
                      }
187
                  }, false);
188
                  that.addEventListener("MSGestureTap", function (e){
189
                      e.preventDefault();
190
                      var $slide = $(this),
191
                          target = $slide.index();
192
                      if (!$(slider.vars.asNavFor).data('flexslider').animating && !$slide.hasClass('active')) {
193
                          slider.direction = (slider.currentItem < target) ? "next" : "prev";
194
                          slider.flexAnimate(target, slider.vars.pauseOnAction, false, true, true);
195
                      }
196
                  });
197
              });
198
          }
199
        }
200
      },
201
      controlNav: {
202
        setup: function() {
203
          if (!slider.manualControls) {
204
            methods.controlNav.setupPaging();
205
          } else { // MANUALCONTROLS:
206
            methods.controlNav.setupManual();
207
          }
208
        },
209
        setupPaging: function() {
210
          var type = (slider.vars.controlNav === "thumbnails") ? 'control-thumbs' : 'control-paging',
211
              j = 1,
212
              item,
213
              slide;
214

    
215
          slider.controlNavScaffold = $('<ol class="'+ namespace + 'control-nav ' + namespace + type + '"></ol>');
216

    
217
          if (slider.pagingCount > 1) {
218
            for (var i = 0; i < slider.pagingCount; i++) {
219
              slide = slider.slides.eq(i);
220
              item = (slider.vars.controlNav === "thumbnails") ? '<img src="' + slide.attr( 'data-thumb' ) + '"/>' : '<a>' + j + '</a>';
221
              if ( 'thumbnails' === slider.vars.controlNav && true === slider.vars.thumbCaptions ) {
222
                var captn = slide.attr( 'data-thumbcaption' );
223
                if ( '' !== captn && undefined !== captn ) { item += '<span class="' + namespace + 'caption">' + captn + '</span>'; }
224
              }
225
              slider.controlNavScaffold.append('<li>' + item + '</li>');
226
              j++;
227
            }
228
          }
229

    
230
          // CONTROLSCONTAINER:
231
          (slider.controlsContainer) ? $(slider.controlsContainer).append(slider.controlNavScaffold) : slider.append(slider.controlNavScaffold);
232
          methods.controlNav.set();
233

    
234
          methods.controlNav.active();
235

    
236
          slider.controlNavScaffold.delegate('a, img', eventType, function(event) {
237
            event.preventDefault();
238

    
239
            if (watchedEvent === "" || watchedEvent === event.type) {
240
              var $this = $(this),
241
                  target = slider.controlNav.index($this);
242

    
243
              if (!$this.hasClass(namespace + 'active')) {
244
                slider.direction = (target > slider.currentSlide) ? "next" : "prev";
245
                slider.flexAnimate(target, slider.vars.pauseOnAction);
246
              }
247
            }
248

    
249
            // setup flags to prevent event duplication
250
            if (watchedEvent === "") {
251
              watchedEvent = event.type;
252
            }
253
            methods.setToClearWatchedEvent();
254

    
255
          });
256
        },
257
        setupManual: function() {
258
          slider.controlNav = slider.manualControls;
259
          methods.controlNav.active();
260

    
261
          slider.controlNav.bind(eventType, function(event) {
262
            event.preventDefault();
263

    
264
            if (watchedEvent === "" || watchedEvent === event.type) {
265
              var $this = $(this),
266
                  target = slider.controlNav.index($this);
267

    
268
              if (!$this.hasClass(namespace + 'active')) {
269
                (target > slider.currentSlide) ? slider.direction = "next" : slider.direction = "prev";
270
                slider.flexAnimate(target, slider.vars.pauseOnAction);
271
              }
272
            }
273

    
274
            // setup flags to prevent event duplication
275
            if (watchedEvent === "") {
276
              watchedEvent = event.type;
277
            }
278
            methods.setToClearWatchedEvent();
279
          });
280
        },
281
        set: function() {
282
          var selector = (slider.vars.controlNav === "thumbnails") ? 'img' : 'a';
283
          slider.controlNav = $('.' + namespace + 'control-nav li ' + selector, (slider.controlsContainer) ? slider.controlsContainer : slider);
284
        },
285
        active: function() {
286
          slider.controlNav.removeClass(namespace + "active").eq(slider.animatingTo).addClass(namespace + "active");
287
        },
288
        update: function(action, pos) {
289
          if (slider.pagingCount > 1 && action === "add") {
290
            slider.controlNavScaffold.append($('<li><a>' + slider.count + '</a></li>'));
291
          } else if (slider.pagingCount === 1) {
292
            slider.controlNavScaffold.find('li').remove();
293
          } else {
294
            slider.controlNav.eq(pos).closest('li').remove();
295
          }
296
          methods.controlNav.set();
297
          (slider.pagingCount > 1 && slider.pagingCount !== slider.controlNav.length) ? slider.update(pos, action) : methods.controlNav.active();
298
        }
299
      },
300
      directionNav: {
301
        setup: function() {
302
          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>');
303

    
304
          // CUSTOM DIRECTION NAV:
305
          if (slider.customDirectionNav) {
306
            slider.directionNav = slider.customDirectionNav;
307
          // CONTROLSCONTAINER:
308
          } else if (slider.controlsContainer) {
309
            $(slider.controlsContainer).append(directionNavScaffold);
310
            slider.directionNav = $('.' + namespace + 'direction-nav li a', slider.controlsContainer);
311
          } else {
312
            slider.append(directionNavScaffold);
313
            slider.directionNav = $('.' + namespace + 'direction-nav li a', slider);
314
          }
315

    
316
          methods.directionNav.update();
317

    
318
          slider.directionNav.bind(eventType, function(event) {
319
            event.preventDefault();
320
            var target;
321

    
322
            if (watchedEvent === "" || watchedEvent === event.type) {
323
              target = ($(this).hasClass(namespace + 'next')) ? slider.getTarget('next') : slider.getTarget('prev');
324
              slider.flexAnimate(target, slider.vars.pauseOnAction);
325
            }
326

    
327
            // setup flags to prevent event duplication
328
            if (watchedEvent === "") {
329
              watchedEvent = event.type;
330
            }
331
            methods.setToClearWatchedEvent();
332
          });
333
        },
334
        update: function() {
335
          var disabledClass = namespace + 'disabled';
336
          if (slider.pagingCount === 1) {
337
            slider.directionNav.addClass(disabledClass).attr('tabindex', '-1');
338
          } else if (!slider.vars.animationLoop) {
339
            if (slider.animatingTo === 0) {
340
              slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "prev").addClass(disabledClass).attr('tabindex', '-1');
341
            } else if (slider.animatingTo === slider.last) {
342
              slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "next").addClass(disabledClass).attr('tabindex', '-1');
343
            } else {
344
              slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');
345
            }
346
          } else {
347
            slider.directionNav.removeClass(disabledClass).removeAttr('tabindex');
348
          }
349
        }
350
      },
351
      pausePlay: {
352
        setup: function() {
353
          var pausePlayScaffold = $('<div class="' + namespace + 'pauseplay"><a></a></div>');
354

    
355
          // CONTROLSCONTAINER:
356
          if (slider.controlsContainer) {
357
            slider.controlsContainer.append(pausePlayScaffold);
358
            slider.pausePlay = $('.' + namespace + 'pauseplay a', slider.controlsContainer);
359
          } else {
360
            slider.append(pausePlayScaffold);
361
            slider.pausePlay = $('.' + namespace + 'pauseplay a', slider);
362
          }
363

    
364
          methods.pausePlay.update((slider.vars.slideshow) ? namespace + 'pause' : namespace + 'play');
365

    
366
          slider.pausePlay.bind(eventType, function(event) {
367
            event.preventDefault();
368

    
369
            if (watchedEvent === "" || watchedEvent === event.type) {
370
              if ($(this).hasClass(namespace + 'pause')) {
371
                slider.manualPause = true;
372
                slider.manualPlay = false;
373
                slider.pause();
374
              } else {
375
                slider.manualPause = false;
376
                slider.manualPlay = true;
377
                slider.play();
378
              }
379
            }
380

    
381
            // setup flags to prevent event duplication
382
            if (watchedEvent === "") {
383
              watchedEvent = event.type;
384
            }
385
            methods.setToClearWatchedEvent();
386
          });
387
        },
388
        update: function(state) {
389
          (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);
390
        }
391
      },
392
      touch: function() {
393
        var startX,
394
          startY,
395
          offset,
396
          cwidth,
397
          dx,
398
          startT,
399
          onTouchStart,
400
          onTouchMove,
401
          onTouchEnd,
402
          scrolling = false,
403
          localX = 0,
404
          localY = 0,
405
          accDx = 0;
406

    
407
        if(!msGesture){
408
            onTouchStart = function(e) {
409
              if (slider.animating) {
410
                e.preventDefault();
411
              } else if ( ( window.navigator.msPointerEnabled ) || e.touches.length === 1 ) {
412
                slider.pause();
413
                // CAROUSEL:
414
                cwidth = (vertical) ? slider.h : slider. w;
415
                startT = Number(new Date());
416
                // CAROUSEL:
417

    
418
                // Local vars for X and Y points.
419
                localX = e.touches[0].pageX;
420
                localY = e.touches[0].pageY;
421

    
422
                offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :
423
                         (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
424
                         (carousel && slider.currentSlide === slider.last) ? slider.limit :
425
                         (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :
426
                         (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;
427
                startX = (vertical) ? localY : localX;
428
                startY = (vertical) ? localX : localY;
429

    
430
                el.addEventListener('touchmove', onTouchMove, false);
431
                el.addEventListener('touchend', onTouchEnd, false);
432
              }
433
            };
434

    
435
            onTouchMove = function(e) {
436
              // Local vars for X and Y points.
437

    
438
              localX = e.touches[0].pageX;
439
              localY = e.touches[0].pageY;
440

    
441
              dx = (vertical) ? startX - localY : startX - localX;
442
              scrolling = (vertical) ? (Math.abs(dx) < Math.abs(localX - startY)) : (Math.abs(dx) < Math.abs(localY - startY));
443

    
444
              var fxms = 500;
445

    
446
              if ( ! scrolling || Number( new Date() ) - startT > fxms ) {
447
                e.preventDefault();
448
                if (!fade && slider.transitions) {
449
                  if (!slider.vars.animationLoop) {
450
                    dx = dx/((slider.currentSlide === 0 && dx < 0 || slider.currentSlide === slider.last && dx > 0) ? (Math.abs(dx)/cwidth+2) : 1);
451
                  }
452
                  slider.setProps(offset + dx, "setTouch");
453
                }
454
              }
455
            };
456

    
457
            onTouchEnd = function(e) {
458
              // finish the touch by undoing the touch session
459
              el.removeEventListener('touchmove', onTouchMove, false);
460

    
461
              if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {
462
                var updateDx = (reverse) ? -dx : dx,
463
                    target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');
464

    
465
                if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth/2)) {
466
                  slider.flexAnimate(target, slider.vars.pauseOnAction);
467
                } else {
468
                  if (!fade) { slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true); }
469
                }
470
              }
471
              el.removeEventListener('touchend', onTouchEnd, false);
472

    
473
              startX = null;
474
              startY = null;
475
              dx = null;
476
              offset = null;
477
            };
478

    
479
            el.addEventListener('touchstart', onTouchStart, false);
480
        }else{
481
            el.style.msTouchAction = "none";
482
            el._gesture = new MSGesture();
483
            el._gesture.target = el;
484
            el.addEventListener("MSPointerDown", onMSPointerDown, false);
485
            el._slider = slider;
486
            el.addEventListener("MSGestureChange", onMSGestureChange, false);
487
            el.addEventListener("MSGestureEnd", onMSGestureEnd, false);
488

    
489
            function onMSPointerDown(e){
490
                e.stopPropagation();
491
                if (slider.animating) {
492
                    e.preventDefault();
493
                }else{
494
                    slider.pause();
495
                    el._gesture.addPointer(e.pointerId);
496
                    accDx = 0;
497
                    cwidth = (vertical) ? slider.h : slider. w;
498
                    startT = Number(new Date());
499
                    // CAROUSEL:
500

    
501
                    offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :
502
                        (carousel && reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
503
                            (carousel && slider.currentSlide === slider.last) ? slider.limit :
504
                                (carousel) ? ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.currentSlide :
505
                                    (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;
506
                }
507
            }
508

    
509
            function onMSGestureChange(e) {
510
                e.stopPropagation();
511
                var slider = e.target._slider;
512
                if(!slider){
513
                    return;
514
                }
515
                var transX = -e.translationX,
516
                    transY = -e.translationY;
517

    
518
                //Accumulate translations.
519
                accDx = accDx + ((vertical) ? transY : transX);
520
                dx = accDx;
521
                scrolling = (vertical) ? (Math.abs(accDx) < Math.abs(-transX)) : (Math.abs(accDx) < Math.abs(-transY));
522

    
523
                if(e.detail === e.MSGESTURE_FLAG_INERTIA){
524
                    setImmediate(function (){
525
                        el._gesture.stop();
526
                    });
527

    
528
                    return;
529
                }
530

    
531
                if (!scrolling || Number(new Date()) - startT > 500) {
532
                    e.preventDefault();
533
                    if (!fade && slider.transitions) {
534
                        if (!slider.vars.animationLoop) {
535
                            dx = accDx / ((slider.currentSlide === 0 && accDx < 0 || slider.currentSlide === slider.last && accDx > 0) ? (Math.abs(accDx) / cwidth + 2) : 1);
536
                        }
537
                        slider.setProps(offset + dx, "setTouch");
538
                    }
539
                }
540
            }
541

    
542
            function onMSGestureEnd(e) {
543
                e.stopPropagation();
544
                var slider = e.target._slider;
545
                if(!slider){
546
                    return;
547
                }
548
                if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {
549
                    var updateDx = (reverse) ? -dx : dx,
550
                        target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');
551

    
552
                    if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth/2)) {
553
                        slider.flexAnimate(target, slider.vars.pauseOnAction);
554
                    } else {
555
                        if (!fade) { slider.flexAnimate(slider.currentSlide, slider.vars.pauseOnAction, true); }
556
                    }
557
                }
558

    
559
                startX = null;
560
                startY = null;
561
                dx = null;
562
                offset = null;
563
                accDx = 0;
564
            }
565
        }
566
      },
567
      resize: function() {
568
        if (!slider.animating && slider.is(':visible')) {
569
          if (!carousel) { slider.doMath(); }
570

    
571
          if (fade) {
572
            // SMOOTH HEIGHT:
573
            methods.smoothHeight();
574
          } else if (carousel) { //CAROUSEL:
575
            slider.slides.width(slider.computedW);
576
            slider.update(slider.pagingCount);
577
            slider.setProps();
578
          }
579
          else if (vertical) { //VERTICAL:
580
            slider.viewport.height(slider.h);
581
            slider.setProps(slider.h, "setTotal");
582
          } else {
583
            // SMOOTH HEIGHT:
584
            if (slider.vars.smoothHeight) { methods.smoothHeight(); }
585
            slider.newSlides.width(slider.computedW);
586
            slider.setProps(slider.computedW, "setTotal");
587
          }
588
        }
589
      },
590
      smoothHeight: function(dur) {
591
        if (!vertical || fade) {
592
          var $obj = (fade) ? slider : slider.viewport;
593
          (dur) ? $obj.animate({"height": slider.slides.eq(slider.animatingTo).height()}, dur) : $obj.height(slider.slides.eq(slider.animatingTo).height());
594
        }
595
      },
596
      sync: function(action) {
597
        var $obj = $(slider.vars.sync).data("flexslider"),
598
            target = slider.animatingTo;
599

    
600
        switch (action) {
601
          case "animate": $obj.flexAnimate(target, slider.vars.pauseOnAction, false, true); break;
602
          case "play": if (!$obj.playing && !$obj.asNav) { $obj.play(); } break;
603
          case "pause": $obj.pause(); break;
604
        }
605
      },
606
      uniqueID: function($clone) {
607
        // Append _clone to current level and children elements with id attributes
608
        $clone.filter( '[id]' ).add($clone.find( '[id]' )).each(function() {
609
          var $this = $(this);
610
          $this.attr( 'id', $this.attr( 'id' ) + '_clone' );
611
        });
612
        return $clone;
613
      },
614
      pauseInvisible: {
615
        visProp: null,
616
        init: function() {
617
          var visProp = methods.pauseInvisible.getHiddenProp();
618
          if (visProp) {
619
            var evtname = visProp.replace(/[H|h]idden/,'') + 'visibilitychange';
620
            document.addEventListener(evtname, function() {
621
              if (methods.pauseInvisible.isHidden()) {
622
                if(slider.startTimeout) {
623
                  clearTimeout(slider.startTimeout); //If clock is ticking, stop timer and prevent from starting while invisible
624
                } else { 
625
                  slider.pause(); //Or just pause
626
                }
627
              }
628
              else {
629
                if(slider.started) {
630
                  slider.play(); //Initiated before, just play
631
                } else { 
632
                  if (slider.vars.initDelay > 0) { 
633
                    setTimeout(slider.play, slider.vars.initDelay);
634
                  } else {
635
                    slider.play(); //Didn't init before: simply init or wait for it
636
                  } 
637
                }
638
              }
639
            });
640
          }
641
        },
642
        isHidden: function() {
643
          var prop = methods.pauseInvisible.getHiddenProp();
644
          if (!prop) {
645
            return false;
646
          }
647
          return document[prop];
648
        },
649
        getHiddenProp: function() {
650
          var prefixes = ['webkit','moz','ms','o'];
651
          // if 'hidden' is natively supported just return it
652
          if ('hidden' in document) {
653
            return 'hidden';
654
          }
655
          // otherwise loop over all the known prefixes until we find one
656
          for ( var i = 0; i < prefixes.length; i++ ) {
657
              if ((prefixes[i] + 'Hidden') in document) {
658
                return prefixes[i] + 'Hidden';
659
              }
660
          }
661
          // otherwise it's not supported
662
          return null;
663
        }
664
      },
665
      setToClearWatchedEvent: function() {
666
        clearTimeout(watchedEventClearTimer);
667
        watchedEventClearTimer = setTimeout(function() {
668
          watchedEvent = "";
669
        }, 3000);
670
      }
671
    };
672

    
673
    // public methods
674
    slider.flexAnimate = function(target, pause, override, withSync, fromNav) {
675
      if (!slider.vars.animationLoop && target !== slider.currentSlide) {
676
        slider.direction = (target > slider.currentSlide) ? "next" : "prev";
677
      }
678

    
679
      if (asNav && slider.pagingCount === 1) slider.direction = (slider.currentItem < target) ? "next" : "prev";
680

    
681
      if (!slider.animating && (slider.canAdvance(target, fromNav) || override) && slider.is(":visible")) {
682
        if (asNav && withSync) {
683
          var master = $(slider.vars.asNavFor).data('flexslider');
684
          slider.atEnd = target === 0 || target === slider.count - 1;
685
          master.flexAnimate(target, true, false, true, fromNav);
686
          slider.direction = (slider.currentItem < target) ? "next" : "prev";
687
          master.direction = slider.direction;
688

    
689
          if (Math.ceil((target + 1)/slider.visible) - 1 !== slider.currentSlide && target !== 0) {
690
            slider.currentItem = target;
691
            slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
692
            target = Math.floor(target/slider.visible);
693
          } else {
694
            slider.currentItem = target;
695
            slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
696
            return false;
697
          }
698
        }
699

    
700
        slider.animating = true;
701
        slider.animatingTo = target;
702

    
703
        // SLIDESHOW:
704
        if (pause) { slider.pause(); }
705

    
706
        // API: before() animation Callback
707
        slider.vars.before(slider);
708

    
709
        // SYNC:
710
        if (slider.syncExists && !fromNav) { methods.sync("animate"); }
711

    
712
        // CONTROLNAV
713
        if (slider.vars.controlNav) { methods.controlNav.active(); }
714

    
715
        // !CAROUSEL:
716
        // CANDIDATE: slide active class (for add/remove slide)
717
        if (!carousel) { slider.slides.removeClass(namespace + 'active-slide').eq(target).addClass(namespace + 'active-slide'); }
718

    
719
        // INFINITE LOOP:
720
        // CANDIDATE: atEnd
721
        slider.atEnd = target === 0 || target === slider.last;
722

    
723
        // DIRECTIONNAV:
724
        if (slider.vars.directionNav) { methods.directionNav.update(); }
725

    
726
        if (target === slider.last) {
727
          // API: end() of cycle Callback
728
          slider.vars.end(slider);
729
          // SLIDESHOW && !INFINITE LOOP:
730
          if (!slider.vars.animationLoop) { slider.pause(); }
731
        }
732

    
733
        // SLIDE:
734
        if (!fade) {
735
          var dimension = (vertical) ? slider.slides.filter(':first').height() : slider.computedW,
736
              margin, slideString, calcNext;
737

    
738
          // INFINITE LOOP / REVERSE:
739
          if (carousel) {
740
            //margin = (slider.vars.itemWidth > slider.w) ? slider.vars.itemMargin * 2 : slider.vars.itemMargin;
741
            margin = slider.vars.itemMargin;
742
            calcNext = ((slider.itemW + margin) * slider.move) * slider.animatingTo;
743
            slideString = (calcNext > slider.limit && slider.visible !== 1) ? slider.limit : calcNext;
744
          } else if (slider.currentSlide === 0 && target === slider.count - 1 && slider.vars.animationLoop && slider.direction !== "next") {
745
            slideString = (reverse) ? (slider.count + slider.cloneOffset) * dimension : 0;
746
          } else if (slider.currentSlide === slider.last && target === 0 && slider.vars.animationLoop && slider.direction !== "prev") {
747
            slideString = (reverse) ? 0 : (slider.count + 1) * dimension;
748
          } else {
749
            slideString = (reverse) ? ((slider.count - 1) - target + slider.cloneOffset) * dimension : (target + slider.cloneOffset) * dimension;
750
          }
751
          slider.setProps(slideString, "", slider.vars.animationSpeed);
752
          if (slider.transitions) {
753
            if (!slider.vars.animationLoop || !slider.atEnd) {
754
              slider.animating = false;
755
              slider.currentSlide = slider.animatingTo;
756
            }
757
            
758
            // Unbind previous transitionEnd events and re-bind new transitionEnd event
759
            slider.container.unbind("webkitTransitionEnd transitionend");
760
            slider.container.bind("webkitTransitionEnd transitionend", function() {
761
              clearTimeout(slider.ensureAnimationEnd);
762
              slider.wrapup(dimension);
763
            });
764

    
765
            // Insurance for the ever-so-fickle transitionEnd event
766
            clearTimeout(slider.ensureAnimationEnd);
767
            slider.ensureAnimationEnd = setTimeout(function() {
768
              slider.wrapup(dimension);
769
            }, slider.vars.animationSpeed + 100);
770

    
771
          } else {
772
            slider.container.animate(slider.args, slider.vars.animationSpeed, slider.vars.easing, function(){
773
              slider.wrapup(dimension);
774
            });
775
          }
776
        } else { // FADE:
777
          if (!touch) {
778
            //slider.slides.eq(slider.currentSlide).fadeOut(slider.vars.animationSpeed, slider.vars.easing);
779
            //slider.slides.eq(target).fadeIn(slider.vars.animationSpeed, slider.vars.easing, slider.wrapup);
780

    
781
            slider.slides.eq(slider.currentSlide).css({"zIndex": 1}).animate({"opacity": 0}, slider.vars.animationSpeed, slider.vars.easing);
782
            slider.slides.eq(target).css({"zIndex": 2}).animate({"opacity": 1}, slider.vars.animationSpeed, slider.vars.easing, slider.wrapup);
783

    
784
          } else {
785
            slider.slides.eq(slider.currentSlide).css({ "opacity": 0, "zIndex": 1 });
786
            slider.slides.eq(target).css({ "opacity": 1, "zIndex": 2 });
787
            slider.wrapup(dimension);
788
          }
789
        }
790
        // SMOOTH HEIGHT:
791
        if (slider.vars.smoothHeight) { methods.smoothHeight(slider.vars.animationSpeed); }
792
      }
793
    };
794
    slider.wrapup = function(dimension) {
795
      // SLIDE:
796
      if (!fade && !carousel) {
797
        if (slider.currentSlide === 0 && slider.animatingTo === slider.last && slider.vars.animationLoop) {
798
          slider.setProps(dimension, "jumpEnd");
799
        } else if (slider.currentSlide === slider.last && slider.animatingTo === 0 && slider.vars.animationLoop) {
800
          slider.setProps(dimension, "jumpStart");
801
        }
802
      }
803
      slider.animating = false;
804
      slider.currentSlide = slider.animatingTo;
805
      // API: after() animation Callback
806
      slider.vars.after(slider);
807
    };
808

    
809
    // SLIDESHOW:
810
    slider.animateSlides = function() {
811
      if (!slider.animating && focused ) { slider.flexAnimate(slider.getTarget("next")); }
812
    };
813
    // SLIDESHOW:
814
    slider.pause = function() {
815
      clearInterval(slider.animatedSlides);
816
      slider.animatedSlides = null;
817
      slider.playing = false;
818
      // PAUSEPLAY:
819
      if (slider.vars.pausePlay) { methods.pausePlay.update("play"); }
820
      // SYNC:
821
      if (slider.syncExists) { methods.sync("pause"); }
822
    };
823
    // SLIDESHOW:
824
    slider.play = function() {
825
      if (slider.playing) { clearInterval(slider.animatedSlides); }
826
      slider.animatedSlides = slider.animatedSlides || setInterval(slider.animateSlides, slider.vars.slideshowSpeed);
827
      slider.started = slider.playing = true;
828
      // PAUSEPLAY:
829
      if (slider.vars.pausePlay) { methods.pausePlay.update("pause"); }
830
      // SYNC:
831
      if (slider.syncExists) { methods.sync("play"); }
832
    };
833
    // STOP:
834
    slider.stop = function () {
835
      slider.pause();
836
      slider.stopped = true;
837
    };
838
    slider.canAdvance = function(target, fromNav) {
839
      // ASNAV:
840
      var last = (asNav) ? slider.pagingCount - 1 : slider.last;
841
      return (fromNav) ? true :
842
             (asNav && slider.currentItem === slider.count - 1 && target === 0 && slider.direction === "prev") ? true :
843
             (asNav && slider.currentItem === 0 && target === slider.pagingCount - 1 && slider.direction !== "next") ? false :
844
             (target === slider.currentSlide && !asNav) ? false :
845
             (slider.vars.animationLoop) ? true :
846
             (slider.atEnd && slider.currentSlide === 0 && target === last && slider.direction !== "next") ? false :
847
             (slider.atEnd && slider.currentSlide === last && target === 0 && slider.direction === "next") ? false :
848
             true;
849
    };
850
    slider.getTarget = function(dir) {
851
      slider.direction = dir;
852
      if (dir === "next") {
853
        return (slider.currentSlide === slider.last) ? 0 : slider.currentSlide + 1;
854
      } else {
855
        return (slider.currentSlide === 0) ? slider.last : slider.currentSlide - 1;
856
      }
857
    };
858

    
859
    // SLIDE:
860
    slider.setProps = function(pos, special, dur) {
861
      var target = (function() {
862
        var posCheck = (pos) ? pos : ((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo,
863
            posCalc = (function() {
864
              if (carousel) {
865
                return (special === "setTouch") ? pos :
866
                       (reverse && slider.animatingTo === slider.last) ? 0 :
867
                       (reverse) ? slider.limit - (((slider.itemW + slider.vars.itemMargin) * slider.move) * slider.animatingTo) :
868
                       (slider.animatingTo === slider.last) ? slider.limit : posCheck;
869
              } else {
870
                switch (special) {
871
                  case "setTotal": return (reverse) ? ((slider.count - 1) - slider.currentSlide + slider.cloneOffset) * pos : (slider.currentSlide + slider.cloneOffset) * pos;
872
                  case "setTouch": return (reverse) ? pos : pos;
873
                  case "jumpEnd": return (reverse) ? pos : slider.count * pos;
874
                  case "jumpStart": return (reverse) ? slider.count * pos : pos;
875
                  default: return pos;
876
                }
877
              }
878
            }());
879

    
880
            return (posCalc * -1) + "px";
881
          }());
882

    
883
      if (slider.transitions) {
884
        target = (vertical) ? "translate3d(0," + target + ",0)" : "translate3d(" + target + ",0,0)";
885
        dur = (dur !== undefined) ? (dur/1000) + "s" : "0s";
886
        slider.container.css("-" + slider.pfx + "-transition-duration", dur);
887
         slider.container.css("transition-duration", dur);
888
      }
889

    
890
      slider.args[slider.prop] = target;
891
      if (slider.transitions || dur === undefined) { slider.container.css(slider.args); }
892

    
893
      slider.container.css('transform',target);
894
    };
895

    
896
    slider.setup = function(type) {
897
      // SLIDE:
898
      if (!fade) {
899
        var sliderOffset, arr;
900

    
901
        if (type === "init") {
902
          slider.viewport = $('<div class="' + namespace + 'viewport"></div>').css({"overflow": "hidden", "position": "relative"}).appendTo(slider).append(slider.container);
903
          // INFINITE LOOP:
904
          slider.cloneCount = 0;
905
          slider.cloneOffset = 0;
906
          // REVERSE:
907
          if (reverse) {
908
            arr = $.makeArray(slider.slides).reverse();
909
            slider.slides = $(arr);
910
            slider.container.empty().append(slider.slides);
911
          }
912
        }
913
        // INFINITE LOOP && !CAROUSEL:
914
        if (slider.vars.animationLoop && !carousel) {
915
          slider.cloneCount = 2;
916
          slider.cloneOffset = 1;
917
          // clear out old clones
918
          if (type !== "init") { slider.container.find('.clone').remove(); }
919
          slider.container.append(methods.uniqueID(slider.slides.first().clone().addClass('clone')).attr('aria-hidden', 'true'))
920
                          .prepend(methods.uniqueID(slider.slides.last().clone().addClass('clone')).attr('aria-hidden', 'true'));
921
        }
922
        slider.newSlides = $(slider.vars.selector, slider);
923

    
924
        sliderOffset = (reverse) ? slider.count - 1 - slider.currentSlide + slider.cloneOffset : slider.currentSlide + slider.cloneOffset;
925
        // VERTICAL:
926
        if (vertical && !carousel) {
927
          slider.container.height((slider.count + slider.cloneCount) * 200 + "%").css("position", "absolute").width("100%");
928
          setTimeout(function(){
929
            slider.newSlides.css({"display": "block"});
930
            slider.doMath();
931
            slider.viewport.height(slider.h);
932
            slider.setProps(sliderOffset * slider.h, "init");
933
          }, (type === "init") ? 100 : 0);
934
        } else {
935
          slider.container.width((slider.count + slider.cloneCount) * 200 + "%");
936
          slider.setProps(sliderOffset * slider.computedW, "init");
937
          setTimeout(function(){
938
            slider.doMath();
939
            slider.newSlides.css({"width": slider.computedW, "float": "left", "display": "block"});
940
            // SMOOTH HEIGHT:
941
            if (slider.vars.smoothHeight) { methods.smoothHeight(); }
942
          }, (type === "init") ? 100 : 0);
943
        }
944
      } else { // FADE:
945
        slider.slides.css({"width": "100%", "float": "left", "marginRight": "-100%", "position": "relative"});
946
        if (type === "init") {
947
          if (!touch) {
948
            //slider.slides.eq(slider.currentSlide).fadeIn(slider.vars.animationSpeed, slider.vars.easing);
949
            if (slider.vars.fadeFirstSlide == false) {
950
              slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({"zIndex": 2}).css({"opacity": 1});
951
            } else {
952
              slider.slides.css({ "opacity": 0, "display": "block", "zIndex": 1 }).eq(slider.currentSlide).css({"zIndex": 2}).animate({"opacity": 1},slider.vars.animationSpeed,slider.vars.easing);
953
            }
954
          } else {
955
            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});
956
          }
957
        }
958
        // SMOOTH HEIGHT:
959
        if (slider.vars.smoothHeight) { methods.smoothHeight(); }
960
      }
961
      // !CAROUSEL:
962
      // CANDIDATE: active slide
963
      if (!carousel) { slider.slides.removeClass(namespace + "active-slide").eq(slider.currentSlide).addClass(namespace + "active-slide"); }
964

    
965
      //FlexSlider: init() Callback
966
      slider.vars.init(slider);
967
    };
968

    
969
    slider.doMath = function() {
970
      var slide = slider.slides.first(),
971
          slideMargin = slider.vars.itemMargin,
972
          minItems = slider.vars.minItems,
973
          maxItems = slider.vars.maxItems;
974

    
975
      slider.w = (slider.viewport===undefined) ? slider.width() : slider.viewport.width();
976
      slider.h = slide.height();
977
      slider.boxPadding = slide.outerWidth() - slide.width();
978

    
979
      // CAROUSEL:
980
      if (carousel) {
981
        slider.itemT = slider.vars.itemWidth + slideMargin;
982
        slider.minW = (minItems) ? minItems * slider.itemT : slider.w;
983
        slider.maxW = (maxItems) ? (maxItems * slider.itemT) - slideMargin : slider.w;
984
        slider.itemW = (slider.minW > slider.w) ? (slider.w - (slideMargin * (minItems - 1)))/minItems :
985
                       (slider.maxW < slider.w) ? (slider.w - (slideMargin * (maxItems - 1)))/maxItems :
986
                       (slider.vars.itemWidth > slider.w) ? slider.w : slider.vars.itemWidth;
987

    
988
        slider.visible = Math.floor(slider.w/(slider.itemW));
989
        slider.move = (slider.vars.move > 0 && slider.vars.move < slider.visible ) ? slider.vars.move : slider.visible;
990
        slider.pagingCount = Math.ceil(((slider.count - slider.visible)/slider.move) + 1);
991
        slider.last =  slider.pagingCount - 1;
992
        slider.limit = (slider.pagingCount === 1) ? 0 :
993
                       (slider.vars.itemWidth > slider.w) ? (slider.itemW * (slider.count - 1)) + (slideMargin * (slider.count - 1)) : ((slider.itemW + slideMargin) * slider.count) - slider.w - slideMargin;
994
      } else {
995
        slider.itemW = slider.w;
996
        slider.pagingCount = slider.count;
997
        slider.last = slider.count - 1;
998
      }
999
      slider.computedW = slider.itemW - slider.boxPadding;
1000
    };
1001

    
1002
    slider.update = function(pos, action) {
1003
      slider.doMath();
1004

    
1005
      // update currentSlide and slider.animatingTo if necessary
1006
      if (!carousel) {
1007
        if (pos < slider.currentSlide) {
1008
          slider.currentSlide += 1;
1009
        } else if (pos <= slider.currentSlide && pos !== 0) {
1010
          slider.currentSlide -= 1;
1011
        }
1012
        slider.animatingTo = slider.currentSlide;
1013
      }
1014

    
1015
      // update controlNav
1016
      if (slider.vars.controlNav && !slider.manualControls) {
1017
        if ((action === "add" && !carousel) || slider.pagingCount > slider.controlNav.length) {
1018
          methods.controlNav.update("add");
1019
        } else if ((action === "remove" && !carousel) || slider.pagingCount < slider.controlNav.length) {
1020
          if (carousel && slider.currentSlide > slider.last) {
1021
            slider.currentSlide -= 1;
1022
            slider.animatingTo -= 1;
1023
          }
1024
          methods.controlNav.update("remove", slider.last);
1025
        }
1026
      }
1027
      // update directionNav
1028
      if (slider.vars.directionNav) { methods.directionNav.update(); }
1029

    
1030
    };
1031

    
1032
    slider.addSlide = function(obj, pos) {
1033
      var $obj = $(obj);
1034

    
1035
      slider.count += 1;
1036
      slider.last = slider.count - 1;
1037

    
1038
      // append new slide
1039
      if (vertical && reverse) {
1040
        (pos !== undefined) ? slider.slides.eq(slider.count - pos).after($obj) : slider.container.prepend($obj);
1041
      } else {
1042
        (pos !== undefined) ? slider.slides.eq(pos).before($obj) : slider.container.append($obj);
1043
      }
1044

    
1045
      // update currentSlide, animatingTo, controlNav, and directionNav
1046
      slider.update(pos, "add");
1047

    
1048
      // update slider.slides
1049
      slider.slides = $(slider.vars.selector + ':not(.clone)', slider);
1050
      // re-setup the slider to accomdate new slide
1051
      slider.setup();
1052

    
1053
      //FlexSlider: added() Callback
1054
      slider.vars.added(slider);
1055
    };
1056
    slider.removeSlide = function(obj) {
1057
      var pos = (isNaN(obj)) ? slider.slides.index($(obj)) : obj;
1058

    
1059
      // update count
1060
      slider.count -= 1;
1061
      slider.last = slider.count - 1;
1062

    
1063
      // remove slide
1064
      if (isNaN(obj)) {
1065
        $(obj, slider.slides).remove();
1066
      } else {
1067
        (vertical && reverse) ? slider.slides.eq(slider.last).remove() : slider.slides.eq(obj).remove();
1068
      }
1069

    
1070
      // update currentSlide, animatingTo, controlNav, and directionNav
1071
      slider.doMath();
1072
      slider.update(pos, "remove");
1073

    
1074
      // update slider.slides
1075
      slider.slides = $(slider.vars.selector + ':not(.clone)', slider);
1076
      // re-setup the slider to accomdate new slide
1077
      slider.setup();
1078

    
1079
      // FlexSlider: removed() Callback
1080
      slider.vars.removed(slider);
1081
    };
1082

    
1083
    //FlexSlider: Initialize
1084
    methods.init();
1085
  };
1086

    
1087
  // Ensure the slider isn't focussed if the window loses focus.
1088
  $( window ).blur( function ( e ) {
1089
    focused = false;
1090
  }).focus( function ( e ) {
1091
    focused = true;
1092
  });
1093

    
1094
  //FlexSlider: Default Settings
1095
  $.flexslider.defaults = {
1096
    namespace: "flex-",             //{NEW} String: Prefix string attached to the class of every element generated by the plugin
1097
    selector: ".slides > li",       //{NEW} Selector: Must match a simple pattern. '{container} > {slide}' -- Ignore pattern at your own peril
1098
    animation: "fade",              //String: Select your animation type, "fade" or "slide"
1099
    easing: "swing",                //{NEW} String: Determines the easing method used in jQuery transitions. jQuery easing plugin is supported!
1100
    direction: "horizontal",        //String: Select the sliding direction, "horizontal" or "vertical"
1101
    reverse: false,                 //{NEW} Boolean: Reverse the animation direction
1102
    animationLoop: true,            //Boolean: Should the animation loop? If false, directionNav will received "disable" classes at either end
1103
    smoothHeight: false,            //{NEW} Boolean: Allow height of the slider to animate smoothly in horizontal mode
1104
    startAt: 0,                     //Integer: The slide that the slider should start on. Array notation (0 = first slide)
1105
    slideshow: true,                //Boolean: Animate slider automatically
1106
    slideshowSpeed: 7000,           //Integer: Set the speed of the slideshow cycling, in milliseconds
1107
    animationSpeed: 600,            //Integer: Set the speed of animations, in milliseconds
1108
    initDelay: 0,                   //{NEW} Integer: Set an initialization delay, in milliseconds
1109
    randomize: false,               //Boolean: Randomize slide order
1110
    fadeFirstSlide: true,           //Boolean: Fade in the first slide when animation type is "fade"
1111
    thumbCaptions: false,           //Boolean: Whether or not to put captions on thumbnails when using the "thumbnails" controlNav.
1112

    
1113
    // Usability features
1114
    pauseOnAction: true,            //Boolean: Pause the slideshow when interacting with control elements, highly recommended.
1115
    pauseOnHover: false,            //Boolean: Pause the slideshow when hovering over slider, then resume when no longer hovering
1116
    pauseInvisible: true,                   //{NEW} Boolean: Pause the slideshow when tab is invisible, resume when visible. Provides better UX, lower CPU usage.
1117
    useCSS: true,                   //{NEW} Boolean: Slider will use CSS3 transitions if available
1118
    touch: true,                    //{NEW} Boolean: Allow touch swipe navigation of the slider on touch-enabled devices
1119
    video: false,                   //{NEW} Boolean: If using video in the slider, will prevent CSS3 3D Transforms to avoid graphical glitches
1120

    
1121
    // Primary Controls
1122
    controlNav: true,               //Boolean: Create navigation for paging control of each slide? Note: Leave true for manualControls usage
1123
    directionNav: true,             //Boolean: Create navigation for previous/next navigation? (true/false)
1124
    prevText: "Previous",           //String: Set the text for the "previous" directionNav item
1125
    nextText: "Next",               //String: Set the text for the "next" directionNav item
1126

    
1127
    // Secondary Navigation
1128
    keyboard: true,                 //Boolean: Allow slider navigating via keyboard left/right keys
1129
    multipleKeyboard: false,        //{NEW} Boolean: Allow keyboard navigation to affect multiple sliders. Default behavior cuts out keyboard navigation with more than one slider present.
1130
    mousewheel: false,              //{UPDATED} Boolean: Requires jquery.mousewheel.js (https://github.com/brandonaaron/jquery-mousewheel) - Allows slider navigating via mousewheel
1131
    pausePlay: false,               //Boolean: Create pause/play dynamic element
1132
    pauseText: "Pause",             //String: Set the text for the "pause" pausePlay item
1133
    playText: "Play",               //String: Set the text for the "play" pausePlay item
1134

    
1135
    // Special properties
1136
    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.
1137
    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.
1138
    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)
1139
    sync: "",                       //{NEW} Selector: Mirror the actions performed on this slider with another slider. Use with care.
1140
    asNavFor: "",                   //{NEW} Selector: Internal property exposed for turning the slider into a thumbnail navigation for another slider
1141

    
1142
    // Carousel Options
1143
    itemWidth: 0,                   //{NEW} Integer: Box-model width of individual carousel items, including horizontal borders and padding.
1144
    itemMargin: 0,                  //{NEW} Integer: Margin between carousel items.
1145
    minItems: 1,                    //{NEW} Integer: Minimum number of carousel items that should be visible. Items will resize fluidly when below this.
1146
    maxItems: 0,                    //{NEW} Integer: Maxmimum number of carousel items that should be visible. Items will resize fluidly when above this limit.
1147
    move: 0,                        //{NEW} Integer: Number of carousel items that should move on animation. If 0, slider will move all visible items.
1148
    allowOneSlide: true,           //{NEW} Boolean: Whether or not to allow a slider comprised of a single slide
1149

    
1150
    // Callback API
1151
    start: function(){},            //Callback: function(slider) - Fires when the slider loads the first slide
1152
    before: function(){},           //Callback: function(slider) - Fires asynchronously with each slider animation
1153
    after: function(){},            //Callback: function(slider) - Fires after each slider animation completes
1154
    end: function(){},              //Callback: function(slider) - Fires when the slider reaches the last slide (asynchronous)
1155
    added: function(){},            //{NEW} Callback: function(slider) - Fires after a slide is added
1156
    removed: function(){},           //{NEW} Callback: function(slider) - Fires after a slide is removed
1157
    init: function() {}             //{NEW} Callback: function(slider) - Fires after the slider is initially setup
1158
  };
1159

    
1160
  //FlexSlider: Plugin Function
1161
  $.fn.flexslider = function(options) {
1162
    if (options === undefined) { options = {}; }
1163

    
1164
    if (typeof options === "object") {
1165
      return this.each(function() {
1166
        var $this = $(this),
1167
            selector = (options.selector) ? options.selector : ".slides > li",
1168
            $slides = $this.find(selector);
1169

    
1170
      if ( ( $slides.length === 1 && options.allowOneSlide === true ) || $slides.length === 0 ) {
1171
          $slides.fadeIn(400);
1172
          if (options.start) { options.start($this); }
1173
        } else if ($this.data('flexslider') === undefined) {
1174
          new $.flexslider(this, options);
1175
        }
1176
      });
1177
    } else {
1178
      // Helper strings to quickly perform functions on the slider
1179
      var $slider = $(this).data('flexslider');
1180
      switch (options) {
1181
        case "play": $slider.play(); break;
1182
        case "pause": $slider.pause(); break;
1183
        case "stop": $slider.stop(); break;
1184
        case "next": $slider.flexAnimate($slider.getTarget("next"), true); break;
1185
        case "prev":
1186
        case "previous": $slider.flexAnimate($slider.getTarget("prev"), true); break;
1187
        default: if (typeof options === "number") { $slider.flexAnimate(options, true); }
1188
      }
1189
    }
1190
  };
1191
})(jQuery);