wp/wp-content/themes/themeforest-2964855-scrn-responsive-single-page-portfolio/SCRN/js/jquery.flexslider.js
changeset 8 c7c34916027a
parent 7 cf61fcea0001
child 9 177826044cd9
equal deleted inserted replaced
7:cf61fcea0001 8:c7c34916027a
     1 /*
       
     2  * jQuery FlexSlider v2.1
       
     3  * http://www.woothemes.com/flexslider/
       
     4  *
       
     5  * Copyright 2012 WooThemes
       
     6  * Free to use under the GPLv2 license.
       
     7  * http://www.gnu.org/licenses/gpl-2.0.html
       
     8  *
       
     9  * Contributing author: Tyler Smith (@mbmufffin)
       
    10  */
       
    11 
       
    12 ;(function ($) {
       
    13 
       
    14   //FlexSlider: Object Instance
       
    15   $.flexslider = function(el, options) {
       
    16     var slider = $(el),
       
    17         vars = $.extend({}, $.flexslider.defaults, options),
       
    18         namespace = vars.namespace,
       
    19         touch = ("ontouchstart" in window) || window.DocumentTouch && document instanceof DocumentTouch,
       
    20         eventType = (touch) ? "touchend" : "click",
       
    21         vertical = vars.direction === "vertical",
       
    22         reverse = vars.reverse,
       
    23         carousel = (vars.itemWidth > 0),
       
    24         fade = vars.animation === "fade",
       
    25         asNav = vars.asNavFor !== "",
       
    26         methods = {};
       
    27     
       
    28     // Store a reference to the slider object
       
    29     $.data(el, "flexslider", slider);
       
    30     
       
    31     // Privat slider methods
       
    32     methods = {
       
    33       init: function() {
       
    34         slider.animating = false;
       
    35         slider.currentSlide = vars.startAt;
       
    36         slider.animatingTo = slider.currentSlide;
       
    37         slider.atEnd = (slider.currentSlide === 0 || slider.currentSlide === slider.last);
       
    38         slider.containerSelector = vars.selector.substr(0,vars.selector.search(' '));
       
    39         slider.slides = $(vars.selector, slider);
       
    40         slider.container = $(slider.containerSelector, slider);
       
    41         slider.count = slider.slides.length;
       
    42         // SYNC:
       
    43         slider.syncExists = $(vars.sync).length > 0;
       
    44         // SLIDE:
       
    45         if (vars.animation === "slide") vars.animation = "swing";
       
    46         slider.prop = (vertical) ? "top" : "marginLeft";
       
    47         slider.args = {};
       
    48         // SLIDESHOW:
       
    49         slider.manualPause = false;
       
    50         // TOUCH/USECSS:
       
    51         slider.transitions = !vars.video && !fade && vars.useCSS && (function() {
       
    52           var obj = document.createElement('div'),
       
    53               props = ['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];
       
    54           for (var i in props) {
       
    55             if ( obj.style[ props[i] ] !== undefined ) {
       
    56               slider.pfx = props[i].replace('Perspective','').toLowerCase();
       
    57               slider.prop = "-" + slider.pfx + "-transform";
       
    58               return true;
       
    59             }
       
    60           }
       
    61           return false;
       
    62         }());
       
    63         // CONTROLSCONTAINER:
       
    64         if (vars.controlsContainer !== "") slider.controlsContainer = $(vars.controlsContainer).length > 0 && $(vars.controlsContainer);
       
    65         // MANUAL:
       
    66         if (vars.manualControls !== "") slider.manualControls = $(vars.manualControls).length > 0 && $(vars.manualControls);
       
    67         
       
    68         // RANDOMIZE:
       
    69         if (vars.randomize) {
       
    70           slider.slides.sort(function() { return (Math.round(Math.random())-0.5); });
       
    71           slider.container.empty().append(slider.slides);
       
    72         }
       
    73         
       
    74         slider.doMath();
       
    75         
       
    76         // ASNAV:
       
    77         if (asNav) methods.asNav.setup();
       
    78         
       
    79         // INIT
       
    80         slider.setup("init");
       
    81         
       
    82         // CONTROLNAV:
       
    83         if (vars.controlNav) methods.controlNav.setup();
       
    84         
       
    85         // DIRECTIONNAV:
       
    86         if (vars.directionNav) methods.directionNav.setup();
       
    87         
       
    88         // KEYBOARD:
       
    89         if (vars.keyboard && ($(slider.containerSelector).length === 1 || vars.multipleKeyboard)) {
       
    90           $(document).bind('keyup', function(event) {
       
    91             var keycode = event.keyCode;
       
    92             if (!slider.animating && (keycode === 39 || keycode === 37)) {
       
    93               var target = (keycode === 39) ? slider.getTarget('next') :
       
    94                            (keycode === 37) ? slider.getTarget('prev') : false;
       
    95               slider.flexAnimate(target, vars.pauseOnAction);
       
    96             }
       
    97           });
       
    98         }
       
    99         // MOUSEWHEEL:
       
   100         if (vars.mousewheel) {
       
   101           slider.bind('mousewheel', function(event, delta, deltaX, deltaY) {
       
   102             event.preventDefault();
       
   103             var target = (delta < 0) ? slider.getTarget('next') : slider.getTarget('prev');
       
   104             slider.flexAnimate(target, vars.pauseOnAction);
       
   105           });
       
   106         }
       
   107         
       
   108         // PAUSEPLAY
       
   109         if (vars.pausePlay) methods.pausePlay.setup();
       
   110         
       
   111         // SLIDSESHOW
       
   112         if (vars.slideshow) {
       
   113           if (vars.pauseOnHover) {
       
   114             slider.hover(function() {
       
   115               if (!slider.manualPlay && !slider.manualPause) slider.pause();
       
   116             }, function() {
       
   117               if (!slider.manualPause && !slider.manualPlay) slider.play();
       
   118             });
       
   119           }
       
   120           // initialize animation
       
   121           (vars.initDelay > 0) ? setTimeout(slider.play, vars.initDelay) : slider.play();
       
   122         }
       
   123         
       
   124         // TOUCH
       
   125         if (touch && vars.touch) methods.touch();
       
   126         
       
   127         // FADE&&SMOOTHHEIGHT || SLIDE:
       
   128         if (!fade || (fade && vars.smoothHeight)) $(window).bind("resize focus", methods.resize);
       
   129         
       
   130         
       
   131         // API: start() Callback
       
   132         setTimeout(function(){
       
   133           vars.start(slider);
       
   134         }, 200);
       
   135       },
       
   136       asNav: {
       
   137         setup: function() {
       
   138           slider.asNav = true;
       
   139           slider.animatingTo = Math.floor(slider.currentSlide/slider.move);
       
   140           slider.currentItem = slider.currentSlide;
       
   141           slider.slides.removeClass(namespace + "active-slide").eq(slider.currentItem).addClass(namespace + "active-slide");
       
   142           slider.slides.click(function(e){
       
   143             e.preventDefault();
       
   144             var $slide = $(this),
       
   145                 target = $slide.index();
       
   146             if (!$(vars.asNavFor).data('flexslider').animating && !$slide.hasClass('active')) {
       
   147               slider.direction = (slider.currentItem < target) ? "next" : "prev";
       
   148               slider.flexAnimate(target, vars.pauseOnAction, false, true, true);
       
   149             }
       
   150           });
       
   151         }
       
   152       },
       
   153       controlNav: {
       
   154         setup: function() {
       
   155           if (!slider.manualControls) {
       
   156             methods.controlNav.setupPaging();
       
   157           } else { // MANUALCONTROLS:
       
   158             methods.controlNav.setupManual();
       
   159           }
       
   160         },
       
   161         setupPaging: function() {
       
   162           var type = (vars.controlNav === "thumbnails") ? 'control-thumbs' : 'control-paging',
       
   163               j = 1,
       
   164               item;
       
   165           
       
   166           slider.controlNavScaffold = $('<ol class="'+ namespace + 'control-nav ' + namespace + type + '"></ol>');
       
   167           
       
   168           if (slider.pagingCount > 1) {
       
   169             for (var i = 0; i < slider.pagingCount; i++) {
       
   170               item = (vars.controlNav === "thumbnails") ? '<img src="' + slider.slides.eq(i).attr("data-thumb") + '"/>' : '<a>' + j + '</a>';
       
   171               slider.controlNavScaffold.append('<li>' + item + '</li>');
       
   172               j++;
       
   173             }
       
   174           }
       
   175           
       
   176           // CONTROLSCONTAINER:
       
   177           (slider.controlsContainer) ? $(slider.controlsContainer).append(slider.controlNavScaffold) : slider.append(slider.controlNavScaffold);
       
   178           methods.controlNav.set();
       
   179           
       
   180           methods.controlNav.active();
       
   181         
       
   182           slider.controlNavScaffold.delegate('a, img', eventType, function(event) {
       
   183             event.preventDefault();
       
   184             var $this = $(this),
       
   185                 target = slider.controlNav.index($this);
       
   186 
       
   187             if (!$this.hasClass(namespace + 'active')) {
       
   188               slider.direction = (target > slider.currentSlide) ? "next" : "prev";
       
   189               slider.flexAnimate(target, vars.pauseOnAction);
       
   190             }
       
   191           });
       
   192           // Prevent iOS click event bug
       
   193           if (touch) {
       
   194             slider.controlNavScaffold.delegate('a', "click touchstart", function(event) {
       
   195               event.preventDefault();
       
   196             });
       
   197           }
       
   198         },
       
   199         setupManual: function() {
       
   200           slider.controlNav = slider.manualControls;
       
   201           methods.controlNav.active();
       
   202           
       
   203           slider.controlNav.live(eventType, function(event) {
       
   204             event.preventDefault();
       
   205             var $this = $(this),
       
   206                 target = slider.controlNav.index($this);
       
   207                 
       
   208             if (!$this.hasClass(namespace + 'active')) {
       
   209               (target > slider.currentSlide) ? slider.direction = "next" : slider.direction = "prev";
       
   210               slider.flexAnimate(target, vars.pauseOnAction);
       
   211             }
       
   212           });
       
   213           // Prevent iOS click event bug
       
   214           if (touch) {
       
   215             slider.controlNav.live("click touchstart", function(event) {
       
   216               event.preventDefault();
       
   217             });
       
   218           }
       
   219         },
       
   220         set: function() {
       
   221           var selector = (vars.controlNav === "thumbnails") ? 'img' : 'a';
       
   222           slider.controlNav = $('.' + namespace + 'control-nav li ' + selector, (slider.controlsContainer) ? slider.controlsContainer : slider);
       
   223         },
       
   224         active: function() {
       
   225           slider.controlNav.removeClass(namespace + "active").eq(slider.animatingTo).addClass(namespace + "active");
       
   226         },
       
   227         update: function(action, pos) {
       
   228           if (slider.pagingCount > 1 && action === "add") {
       
   229             slider.controlNavScaffold.append($('<li><a>' + slider.count + '</a></li>'));
       
   230           } else if (slider.pagingCount === 1) {
       
   231             slider.controlNavScaffold.find('li').remove();
       
   232           } else {
       
   233             slider.controlNav.eq(pos).closest('li').remove();
       
   234           }
       
   235           methods.controlNav.set();
       
   236           (slider.pagingCount > 1 && slider.pagingCount !== slider.controlNav.length) ? slider.update(pos, action) : methods.controlNav.active();
       
   237         }
       
   238       },
       
   239       directionNav: {
       
   240         setup: function() {
       
   241           var directionNavScaffold = $('<ul class="' + namespace + 'direction-nav"><li><a class="' + namespace + 'prev" href="#">' + vars.prevText + '</a></li><li><a class="' + namespace + 'next" href="#">' + vars.nextText + '</a></li></ul>');
       
   242         
       
   243           // CONTROLSCONTAINER:
       
   244           if (slider.controlsContainer) {
       
   245             $(slider.controlsContainer).append(directionNavScaffold);
       
   246             slider.directionNav = $('.' + namespace + 'direction-nav li a', slider.controlsContainer);
       
   247           } else {
       
   248             slider.append(directionNavScaffold);
       
   249             slider.directionNav = $('.' + namespace + 'direction-nav li a', slider);
       
   250           }
       
   251         
       
   252           methods.directionNav.update();
       
   253         
       
   254           slider.directionNav.bind(eventType, function(event) {
       
   255             event.preventDefault();
       
   256             var target = ($(this).hasClass(namespace + 'next')) ? slider.getTarget('next') : slider.getTarget('prev');
       
   257             slider.flexAnimate(target, vars.pauseOnAction);
       
   258           });
       
   259           // Prevent iOS click event bug
       
   260           if (touch) {
       
   261             slider.directionNav.bind("click touchstart", function(event) {
       
   262               event.preventDefault();
       
   263             });
       
   264           }
       
   265         },
       
   266         update: function() {
       
   267           var disabledClass = namespace + 'disabled';
       
   268           if (slider.pagingCount === 1) {
       
   269             slider.directionNav.addClass(disabledClass);
       
   270           } else if (!vars.animationLoop) {
       
   271             if (slider.animatingTo === 0) {
       
   272               slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "prev").addClass(disabledClass);
       
   273             } else if (slider.animatingTo === slider.last) {
       
   274               slider.directionNav.removeClass(disabledClass).filter('.' + namespace + "next").addClass(disabledClass);
       
   275             } else {
       
   276               slider.directionNav.removeClass(disabledClass);
       
   277             }
       
   278           } else {
       
   279             slider.directionNav.removeClass(disabledClass);
       
   280           }
       
   281         }
       
   282       },
       
   283       pausePlay: {
       
   284         setup: function() {
       
   285           var pausePlayScaffold = $('<div class="' + namespace + 'pauseplay"><a></a></div>');
       
   286         
       
   287           // CONTROLSCONTAINER:
       
   288           if (slider.controlsContainer) {
       
   289             slider.controlsContainer.append(pausePlayScaffold);
       
   290             slider.pausePlay = $('.' + namespace + 'pauseplay a', slider.controlsContainer);
       
   291           } else {
       
   292             slider.append(pausePlayScaffold);
       
   293             slider.pausePlay = $('.' + namespace + 'pauseplay a', slider);
       
   294           }
       
   295 
       
   296           methods.pausePlay.update((vars.slideshow) ? namespace + 'pause' : namespace + 'play');
       
   297 
       
   298           slider.pausePlay.bind(eventType, function(event) {
       
   299             event.preventDefault();
       
   300             if ($(this).hasClass(namespace + 'pause')) {
       
   301               slider.manualPause = true;
       
   302               slider.manualPlay = false;
       
   303               slider.pause();
       
   304             } else {
       
   305               slider.manualPause = false;
       
   306               slider.manualPlay = true;
       
   307               slider.play();
       
   308             }
       
   309           });
       
   310           // Prevent iOS click event bug
       
   311           if (touch) {
       
   312             slider.pausePlay.bind("click touchstart", function(event) {
       
   313               event.preventDefault();
       
   314             });
       
   315           }
       
   316         },
       
   317         update: function(state) {
       
   318           (state === "play") ? slider.pausePlay.removeClass(namespace + 'pause').addClass(namespace + 'play').text(vars.playText) : slider.pausePlay.removeClass(namespace + 'play').addClass(namespace + 'pause').text(vars.pauseText);
       
   319         }
       
   320       },
       
   321       touch: function() {
       
   322         var startX,
       
   323           startY,
       
   324           offset,
       
   325           cwidth,
       
   326           dx,
       
   327           startT,
       
   328           scrolling = false;
       
   329               
       
   330         el.addEventListener('touchstart', onTouchStart, false);
       
   331         function onTouchStart(e) {
       
   332           if (slider.animating) {
       
   333             e.preventDefault();
       
   334           } else if (e.touches.length === 1) {
       
   335             slider.pause();
       
   336             // CAROUSEL: 
       
   337             cwidth = (vertical) ? slider.h : slider. w;
       
   338             startT = Number(new Date());
       
   339             // CAROUSEL:
       
   340             offset = (carousel && reverse && slider.animatingTo === slider.last) ? 0 :
       
   341                      (carousel && reverse) ? slider.limit - (((slider.itemW + vars.itemMargin) * slider.move) * slider.animatingTo) :
       
   342                      (carousel && slider.currentSlide === slider.last) ? slider.limit :
       
   343                      (carousel) ? ((slider.itemW + vars.itemMargin) * slider.move) * slider.currentSlide : 
       
   344                      (reverse) ? (slider.last - slider.currentSlide + slider.cloneOffset) * cwidth : (slider.currentSlide + slider.cloneOffset) * cwidth;
       
   345             startX = (vertical) ? e.touches[0].pageY : e.touches[0].pageX;
       
   346             startY = (vertical) ? e.touches[0].pageX : e.touches[0].pageY;
       
   347 
       
   348             el.addEventListener('touchmove', onTouchMove, false);
       
   349             el.addEventListener('touchend', onTouchEnd, false);
       
   350           }
       
   351         }
       
   352 
       
   353         function onTouchMove(e) {
       
   354           dx = (vertical) ? startX - e.touches[0].pageY : startX - e.touches[0].pageX;
       
   355           scrolling = (vertical) ? (Math.abs(dx) < Math.abs(e.touches[0].pageX - startY)) : (Math.abs(dx) < Math.abs(e.touches[0].pageY - startY));
       
   356           
       
   357           if (!scrolling || Number(new Date()) - startT > 500) {
       
   358             e.preventDefault();
       
   359             if (!fade && slider.transitions) {
       
   360               if (!vars.animationLoop) {
       
   361                 dx = dx/((slider.currentSlide === 0 && dx < 0 || slider.currentSlide === slider.last && dx > 0) ? (Math.abs(dx)/cwidth+2) : 1);
       
   362               }
       
   363               slider.setProps(offset + dx, "setTouch");
       
   364             }
       
   365           }
       
   366         }
       
   367         
       
   368         function onTouchEnd(e) {
       
   369           if (slider.animatingTo === slider.currentSlide && !scrolling && !(dx === null)) {
       
   370             var updateDx = (reverse) ? -dx : dx,
       
   371                 target = (updateDx > 0) ? slider.getTarget('next') : slider.getTarget('prev');
       
   372             
       
   373             if (slider.canAdvance(target) && (Number(new Date()) - startT < 550 && Math.abs(updateDx) > 50 || Math.abs(updateDx) > cwidth/2)) {
       
   374               slider.flexAnimate(target, vars.pauseOnAction);
       
   375             } else {
       
   376               slider.flexAnimate(slider.currentSlide, vars.pauseOnAction, true);
       
   377             }
       
   378           }
       
   379           // finish the touch by undoing the touch session
       
   380           el.removeEventListener('touchmove', onTouchMove, false);
       
   381           el.removeEventListener('touchend', onTouchEnd, false);
       
   382           startX = null;
       
   383           startY = null;
       
   384           dx = null;
       
   385           offset = null;
       
   386         }
       
   387       },
       
   388       resize: function() {
       
   389         if (!slider.animating && slider.is(':visible')) {
       
   390           if (!carousel) slider.doMath();
       
   391           
       
   392           if (fade) {
       
   393             // SMOOTH HEIGHT:
       
   394             methods.smoothHeight();
       
   395           } else if (carousel) { //CAROUSEL:
       
   396             slider.slides.width(slider.computedW);
       
   397             slider.update(slider.pagingCount);
       
   398             slider.setProps();
       
   399           }
       
   400           else if (vertical) { //VERTICAL:
       
   401             slider.viewport.height(slider.h);
       
   402             slider.setProps(slider.h, "setTotal");
       
   403           } else {
       
   404             // SMOOTH HEIGHT:
       
   405             if (vars.smoothHeight) methods.smoothHeight();
       
   406             slider.newSlides.width(slider.computedW);
       
   407             slider.setProps(slider.computedW, "setTotal");
       
   408           }
       
   409         }
       
   410       },
       
   411       smoothHeight: function(dur) {
       
   412         if (!vertical || fade) {
       
   413           var $obj = (fade) ? slider : slider.viewport;
       
   414           (dur) ? $obj.animate({"height": slider.slides.eq(slider.animatingTo).height()}, dur) : $obj.height(slider.slides.eq(slider.animatingTo).height());
       
   415         }
       
   416       },
       
   417       sync: function(action) {
       
   418         var $obj = $(vars.sync).data("flexslider"),
       
   419             target = slider.animatingTo;
       
   420         
       
   421         switch (action) {
       
   422           case "animate": $obj.flexAnimate(target, vars.pauseOnAction, false, true); break;
       
   423           case "play": if (!$obj.playing && !$obj.asNav) { $obj.play(); } break;
       
   424           case "pause": $obj.pause(); break;
       
   425         }
       
   426       }
       
   427     }
       
   428     
       
   429     // public methods
       
   430     slider.flexAnimate = function(target, pause, override, withSync, fromNav) {
       
   431       if (asNav && slider.pagingCount === 1) slider.direction = (slider.currentItem < target) ? "next" : "prev";
       
   432 
       
   433       if (!slider.animating && (slider.canAdvance(target, fromNav) || override) && slider.is(":visible")) {
       
   434         if (asNav && withSync) {
       
   435           var master = $(vars.asNavFor).data('flexslider');
       
   436           slider.atEnd = target === 0 || target === slider.count - 1;
       
   437           master.flexAnimate(target, true, false, true, fromNav);
       
   438           slider.direction = (slider.currentItem < target) ? "next" : "prev";
       
   439           master.direction = slider.direction;
       
   440           
       
   441           if (Math.ceil((target + 1)/slider.visible) - 1 !== slider.currentSlide && target !== 0) {
       
   442             slider.currentItem = target;
       
   443             slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
       
   444             target = Math.floor(target/slider.visible);
       
   445           } else {
       
   446             slider.currentItem = target;
       
   447             slider.slides.removeClass(namespace + "active-slide").eq(target).addClass(namespace + "active-slide");
       
   448             return false;
       
   449           }
       
   450         }
       
   451         
       
   452         slider.animating = true;
       
   453         slider.animatingTo = target;
       
   454         // API: before() animation Callback
       
   455         vars.before(slider);
       
   456         
       
   457         // SLIDESHOW:
       
   458         if (pause) slider.pause();
       
   459         
       
   460         // SYNC:
       
   461         if (slider.syncExists && !fromNav) methods.sync("animate");
       
   462         
       
   463         // CONTROLNAV
       
   464         if (vars.controlNav) methods.controlNav.active();
       
   465         
       
   466         // !CAROUSEL:
       
   467         // CANDIDATE: slide active class (for add/remove slide)
       
   468         if (!carousel) slider.slides.removeClass(namespace + 'active-slide').eq(target).addClass(namespace + 'active-slide');
       
   469         
       
   470         // INFINITE LOOP:
       
   471         // CANDIDATE: atEnd
       
   472         slider.atEnd = target === 0 || target === slider.last;
       
   473         
       
   474         // DIRECTIONNAV:
       
   475         if (vars.directionNav) methods.directionNav.update();
       
   476         
       
   477         if (target === slider.last) {
       
   478           // API: end() of cycle Callback
       
   479           vars.end(slider);
       
   480           // SLIDESHOW && !INFINITE LOOP:
       
   481           if (!vars.animationLoop) slider.pause();
       
   482         }
       
   483         
       
   484         // SLIDE:
       
   485         if (!fade) {
       
   486           var dimension = (vertical) ? slider.slides.filter(':first').height() : slider.computedW,
       
   487               margin, slideString, calcNext;
       
   488           
       
   489           // INFINITE LOOP / REVERSE:
       
   490           if (carousel) {
       
   491             margin = (vars.itemWidth > slider.w) ? vars.itemMargin * 2 : vars.itemMargin;
       
   492             calcNext = ((slider.itemW + margin) * slider.move) * slider.animatingTo;
       
   493             slideString = (calcNext > slider.limit && slider.visible !== 1) ? slider.limit : calcNext;
       
   494           } else if (slider.currentSlide === 0 && target === slider.count - 1 && vars.animationLoop && slider.direction !== "next") {
       
   495             slideString = (reverse) ? (slider.count + slider.cloneOffset) * dimension : 0;
       
   496           } else if (slider.currentSlide === slider.last && target === 0 && vars.animationLoop && slider.direction !== "prev") {
       
   497             slideString = (reverse) ? 0 : (slider.count + 1) * dimension;
       
   498           } else {
       
   499             slideString = (reverse) ? ((slider.count - 1) - target + slider.cloneOffset) * dimension : (target + slider.cloneOffset) * dimension;
       
   500           }
       
   501           slider.setProps(slideString, "", vars.animationSpeed);
       
   502           if (slider.transitions) {
       
   503             if (!vars.animationLoop || !slider.atEnd) {
       
   504               slider.animating = false;
       
   505               slider.currentSlide = slider.animatingTo;
       
   506             }
       
   507             slider.container.unbind("webkitTransitionEnd transitionend");
       
   508             slider.container.bind("webkitTransitionEnd transitionend", function() {
       
   509               slider.wrapup(dimension);
       
   510             });
       
   511           } else {
       
   512             slider.container.animate(slider.args, vars.animationSpeed, vars.easing, function(){
       
   513               slider.wrapup(dimension);
       
   514             });
       
   515           }
       
   516         } else { // FADE:
       
   517           slider.slides.eq(slider.currentSlide).fadeOut(vars.animationSpeed, vars.easing);
       
   518           slider.slides.eq(target).fadeIn(vars.animationSpeed, vars.easing, slider.wrapup);
       
   519         }
       
   520         // SMOOTH HEIGHT:
       
   521         if (vars.smoothHeight) methods.smoothHeight(vars.animationSpeed);
       
   522       }
       
   523     } 
       
   524     slider.wrapup = function(dimension) {
       
   525       // SLIDE:
       
   526       if (!fade && !carousel) {
       
   527         if (slider.currentSlide === 0 && slider.animatingTo === slider.last && vars.animationLoop) {
       
   528           slider.setProps(dimension, "jumpEnd");
       
   529         } else if (slider.currentSlide === slider.last && slider.animatingTo === 0 && vars.animationLoop) {
       
   530           slider.setProps(dimension, "jumpStart");
       
   531         }
       
   532       }
       
   533       slider.animating = false;
       
   534       slider.currentSlide = slider.animatingTo;
       
   535       // API: after() animation Callback
       
   536       vars.after(slider);
       
   537     }
       
   538     
       
   539     // SLIDESHOW:
       
   540     slider.animateSlides = function() {
       
   541       if (!slider.animating) slider.flexAnimate(slider.getTarget("next"));
       
   542     }
       
   543     // SLIDESHOW:
       
   544     slider.pause = function() {
       
   545       clearInterval(slider.animatedSlides);
       
   546       slider.playing = false;
       
   547       // PAUSEPLAY:
       
   548       if (vars.pausePlay) methods.pausePlay.update("play");
       
   549       // SYNC:
       
   550       if (slider.syncExists) methods.sync("pause");
       
   551     }
       
   552     // SLIDESHOW:
       
   553     slider.play = function() {
       
   554       slider.animatedSlides = setInterval(slider.animateSlides, vars.slideshowSpeed);
       
   555       slider.playing = true;
       
   556       // PAUSEPLAY:
       
   557       if (vars.pausePlay) methods.pausePlay.update("pause");
       
   558       // SYNC:
       
   559       if (slider.syncExists) methods.sync("play");
       
   560     }
       
   561     slider.canAdvance = function(target, fromNav) {
       
   562       // ASNAV:
       
   563       var last = (asNav) ? slider.pagingCount - 1 : slider.last;
       
   564       return (fromNav) ? true :
       
   565              (asNav && slider.currentItem === slider.count - 1 && target === 0 && slider.direction === "prev") ? true :
       
   566              (asNav && slider.currentItem === 0 && target === slider.pagingCount - 1 && slider.direction !== "next") ? false :
       
   567              (target === slider.currentSlide && !asNav) ? false :
       
   568              (vars.animationLoop) ? true :
       
   569              (slider.atEnd && slider.currentSlide === 0 && target === last && slider.direction !== "next") ? false :
       
   570              (slider.atEnd && slider.currentSlide === last && target === 0 && slider.direction === "next") ? false :
       
   571              true;
       
   572     }
       
   573     slider.getTarget = function(dir) {
       
   574       slider.direction = dir; 
       
   575       if (dir === "next") {
       
   576         return (slider.currentSlide === slider.last) ? 0 : slider.currentSlide + 1;
       
   577       } else {
       
   578         return (slider.currentSlide === 0) ? slider.last : slider.currentSlide - 1;
       
   579       }
       
   580     }
       
   581     
       
   582     // SLIDE:
       
   583     slider.setProps = function(pos, special, dur) {
       
   584       var target = (function() {
       
   585         var posCheck = (pos) ? pos : ((slider.itemW + vars.itemMargin) * slider.move) * slider.animatingTo,
       
   586             posCalc = (function() {
       
   587               if (carousel) {
       
   588                 return (special === "setTouch") ? pos :
       
   589                        (reverse && slider.animatingTo === slider.last) ? 0 :
       
   590                        (reverse) ? slider.limit - (((slider.itemW + vars.itemMargin) * slider.move) * slider.animatingTo) :
       
   591                        (slider.animatingTo === slider.last) ? slider.limit : posCheck;
       
   592               } else {
       
   593                 switch (special) {
       
   594                   case "setTotal": return (reverse) ? ((slider.count - 1) - slider.currentSlide + slider.cloneOffset) * pos : (slider.currentSlide + slider.cloneOffset) * pos;
       
   595                   case "setTouch": return (reverse) ? pos : pos;
       
   596                   case "jumpEnd": return (reverse) ? pos : slider.count * pos;
       
   597                   case "jumpStart": return (reverse) ? slider.count * pos : pos;
       
   598                   default: return pos;
       
   599                 }
       
   600               }
       
   601             }());
       
   602             return (posCalc * -1) + "px";
       
   603           }());
       
   604 
       
   605       if (slider.transitions) {
       
   606         target = (vertical) ? "translate3d(0," + target + ",0)" : "translate3d(" + target + ",0,0)";
       
   607         dur = (dur !== undefined) ? (dur/1000) + "s" : "0s";
       
   608         slider.container.css("-" + slider.pfx + "-transition-duration", dur);
       
   609       }
       
   610       
       
   611       slider.args[slider.prop] = target;
       
   612       if (slider.transitions || dur === undefined) slider.container.css(slider.args);
       
   613     }
       
   614     
       
   615     slider.setup = function(type) {
       
   616       // SLIDE:
       
   617       if (!fade) {
       
   618         var sliderOffset, arr;
       
   619             
       
   620         if (type === "init") {
       
   621           slider.viewport = $('<div class="' + namespace + 'viewport"></div>').css({"overflow": "hidden", "position": "relative"}).appendTo(slider).append(slider.container);
       
   622           // INFINITE LOOP:
       
   623           slider.cloneCount = 0;
       
   624           slider.cloneOffset = 0;
       
   625           // REVERSE:
       
   626           if (reverse) {
       
   627             arr = $.makeArray(slider.slides).reverse();
       
   628             slider.slides = $(arr);
       
   629             slider.container.empty().append(slider.slides);
       
   630           }
       
   631         }
       
   632         // INFINITE LOOP && !CAROUSEL:
       
   633         if (vars.animationLoop && !carousel) {
       
   634           slider.cloneCount = 2;
       
   635           slider.cloneOffset = 1;
       
   636           // clear out old clones
       
   637           if (type !== "init") slider.container.find('.clone').remove();
       
   638           slider.container.append(slider.slides.first().clone().addClass('clone')).prepend(slider.slides.last().clone().addClass('clone'));
       
   639         }
       
   640         slider.newSlides = $(vars.selector, slider);
       
   641         
       
   642         sliderOffset = (reverse) ? slider.count - 1 - slider.currentSlide + slider.cloneOffset : slider.currentSlide + slider.cloneOffset;
       
   643         // VERTICAL:
       
   644         if (vertical && !carousel) {
       
   645           slider.container.height((slider.count + slider.cloneCount) * 200 + "%").css("position", "absolute").width("100%");
       
   646           setTimeout(function(){
       
   647             slider.newSlides.css({"display": "block"});
       
   648             slider.doMath();
       
   649             slider.viewport.height(slider.h);
       
   650             slider.setProps(sliderOffset * slider.h, "init");
       
   651           }, (type === "init") ? 100 : 0);
       
   652         } else {
       
   653           slider.container.width((slider.count + slider.cloneCount) * 200 + "%");
       
   654           slider.setProps(sliderOffset * slider.computedW, "init");
       
   655           setTimeout(function(){
       
   656             slider.doMath();
       
   657             slider.newSlides.css({"width": slider.computedW, "float": "left", "display": "block"});
       
   658             // SMOOTH HEIGHT:
       
   659             if (vars.smoothHeight) methods.smoothHeight();
       
   660           }, (type === "init") ? 100 : 0);
       
   661         }
       
   662       } else { // FADE: 
       
   663         slider.slides.css({"width": "100%", "float": "left", "marginRight": "-100%", "position": "relative"});
       
   664         if (type === "init") slider.slides.eq(slider.currentSlide).fadeIn(vars.animationSpeed, vars.easing);
       
   665         // SMOOTH HEIGHT:
       
   666         if (vars.smoothHeight) methods.smoothHeight();
       
   667       }
       
   668       // !CAROUSEL:
       
   669       // CANDIDATE: active slide
       
   670       if (!carousel) slider.slides.removeClass(namespace + "active-slide").eq(slider.currentSlide).addClass(namespace + "active-slide");
       
   671     }
       
   672     
       
   673     slider.doMath = function() {
       
   674       var slide = slider.slides.first(),
       
   675           slideMargin = vars.itemMargin,
       
   676           minItems = vars.minItems,
       
   677           maxItems = vars.maxItems;
       
   678       
       
   679       slider.w = slider.width();
       
   680       slider.h = slide.height();
       
   681       slider.boxPadding = slide.outerWidth() - slide.width();
       
   682 
       
   683       // CAROUSEL:
       
   684       if (carousel) {
       
   685         slider.itemT = vars.itemWidth + slideMargin;
       
   686         slider.minW = (minItems) ? minItems * slider.itemT : slider.w;
       
   687         slider.maxW = (maxItems) ? maxItems * slider.itemT : slider.w;
       
   688         slider.itemW = (slider.minW > slider.w) ? (slider.w - (slideMargin * minItems))/minItems :
       
   689                        (slider.maxW < slider.w) ? (slider.w - (slideMargin * maxItems))/maxItems :
       
   690                        (vars.itemWidth > slider.w) ? slider.w : vars.itemWidth;
       
   691         slider.visible = Math.floor(slider.w/(slider.itemW + slideMargin));
       
   692         slider.move = (vars.move > 0 && vars.move < slider.visible ) ? vars.move : slider.visible;
       
   693         slider.pagingCount = Math.ceil(((slider.count - slider.visible)/slider.move) + 1);
       
   694         slider.last =  slider.pagingCount - 1;
       
   695         slider.limit = (slider.pagingCount === 1) ? 0 :
       
   696                        (vars.itemWidth > slider.w) ? ((slider.itemW + (slideMargin * 2)) * slider.count) - slider.w - slideMargin : ((slider.itemW + slideMargin) * slider.count) - slider.w - slideMargin;
       
   697       } else {
       
   698         slider.itemW = slider.w;
       
   699         slider.pagingCount = slider.count;
       
   700         slider.last = slider.count - 1;
       
   701       }
       
   702       slider.computedW = slider.itemW - slider.boxPadding;
       
   703     }
       
   704     
       
   705     slider.update = function(pos, action) {
       
   706       slider.doMath();
       
   707       
       
   708       // update currentSlide and slider.animatingTo if necessary
       
   709       if (!carousel) {
       
   710         if (pos < slider.currentSlide) {
       
   711           slider.currentSlide += 1;
       
   712         } else if (pos <= slider.currentSlide && pos !== 0) {
       
   713           slider.currentSlide -= 1;
       
   714         }
       
   715         slider.animatingTo = slider.currentSlide;
       
   716       }
       
   717       
       
   718       // update controlNav
       
   719       if (vars.controlNav && !slider.manualControls) {
       
   720         if ((action === "add" && !carousel) || slider.pagingCount > slider.controlNav.length) {
       
   721           methods.controlNav.update("add");
       
   722         } else if ((action === "remove" && !carousel) || slider.pagingCount < slider.controlNav.length) {
       
   723           if (carousel && slider.currentSlide > slider.last) {
       
   724             slider.currentSlide -= 1;
       
   725             slider.animatingTo -= 1;
       
   726           }
       
   727           methods.controlNav.update("remove", slider.last);
       
   728         }
       
   729       }
       
   730       // update directionNav
       
   731       if (vars.directionNav) methods.directionNav.update();
       
   732       
       
   733     }
       
   734     
       
   735     slider.addSlide = function(obj, pos) {
       
   736       var $obj = $(obj);
       
   737       
       
   738       slider.count += 1;
       
   739       slider.last = slider.count - 1;
       
   740       
       
   741       // append new slide
       
   742       if (vertical && reverse) {
       
   743         (pos !== undefined) ? slider.slides.eq(slider.count - pos).after($obj) : slider.container.prepend($obj);
       
   744       } else {
       
   745         (pos !== undefined) ? slider.slides.eq(pos).before($obj) : slider.container.append($obj);
       
   746       }
       
   747       
       
   748       // update currentSlide, animatingTo, controlNav, and directionNav
       
   749       slider.update(pos, "add");
       
   750       
       
   751       // update slider.slides
       
   752       slider.slides = $(vars.selector + ':not(.clone)', slider);
       
   753       // re-setup the slider to accomdate new slide
       
   754       slider.setup();
       
   755       
       
   756       //FlexSlider: added() Callback
       
   757       vars.added(slider);
       
   758     }
       
   759     slider.removeSlide = function(obj) {
       
   760       var pos = (isNaN(obj)) ? slider.slides.index($(obj)) : obj;
       
   761       
       
   762       // update count
       
   763       slider.count -= 1;
       
   764       slider.last = slider.count - 1;
       
   765       
       
   766       // remove slide
       
   767       if (isNaN(obj)) {
       
   768         $(obj, slider.slides).remove();
       
   769       } else {
       
   770         (vertical && reverse) ? slider.slides.eq(slider.last).remove() : slider.slides.eq(obj).remove();
       
   771       }
       
   772       
       
   773       // update currentSlide, animatingTo, controlNav, and directionNav
       
   774       slider.doMath();
       
   775       slider.update(pos, "remove");
       
   776       
       
   777       // update slider.slides
       
   778       slider.slides = $(vars.selector + ':not(.clone)', slider);
       
   779       // re-setup the slider to accomdate new slide
       
   780       slider.setup();
       
   781       
       
   782       // FlexSlider: removed() Callback
       
   783       vars.removed(slider);
       
   784     }
       
   785     
       
   786     //FlexSlider: Initialize
       
   787     methods.init();
       
   788   }
       
   789   
       
   790   //FlexSlider: Default Settings
       
   791   $.flexslider.defaults = {
       
   792     namespace: "flex-",             //{NEW} String: Prefix string attached to the class of every element generated by the plugin
       
   793     selector: ".slides > li",       //{NEW} Selector: Must match a simple pattern. '{container} > {slide}' -- Ignore pattern at your own peril
       
   794     animation: "fade",              //String: Select your animation type, "fade" or "slide"
       
   795     easing: "swing",               //{NEW} String: Determines the easing method used in jQuery transitions. jQuery easing plugin is supported!
       
   796     direction: "horizontal",        //String: Select the sliding direction, "horizontal" or "vertical"
       
   797     reverse: false,                 //{NEW} Boolean: Reverse the animation direction
       
   798     animationLoop: true,             //Boolean: Should the animation loop? If false, directionNav will received "disable" classes at either end
       
   799     smoothHeight: false,            //{NEW} Boolean: Allow height of the slider to animate smoothly in horizontal mode  
       
   800     startAt: 0,                     //Integer: The slide that the slider should start on. Array notation (0 = first slide)
       
   801     slideshow: true,                //Boolean: Animate slider automatically
       
   802     slideshowSpeed: 7000,           //Integer: Set the speed of the slideshow cycling, in milliseconds
       
   803     animationSpeed: 600,            //Integer: Set the speed of animations, in milliseconds
       
   804     initDelay: 0,                   //{NEW} Integer: Set an initialization delay, in milliseconds
       
   805     randomize: false,               //Boolean: Randomize slide order
       
   806     
       
   807     // Usability features
       
   808     pauseOnAction: true,            //Boolean: Pause the slideshow when interacting with control elements, highly recommended.
       
   809     pauseOnHover: false,            //Boolean: Pause the slideshow when hovering over slider, then resume when no longer hovering
       
   810     useCSS: true,                   //{NEW} Boolean: Slider will use CSS3 transitions if available
       
   811     touch: true,                    //{NEW} Boolean: Allow touch swipe navigation of the slider on touch-enabled devices
       
   812     video: false,                   //{NEW} Boolean: If using video in the slider, will prevent CSS3 3D Transforms to avoid graphical glitches
       
   813     
       
   814     // Primary Controls
       
   815     controlNav: true,               //Boolean: Create navigation for paging control of each clide? Note: Leave true for manualControls usage
       
   816     directionNav: true,             //Boolean: Create navigation for previous/next navigation? (true/false)
       
   817     prevText: "Previous",           //String: Set the text for the "previous" directionNav item
       
   818     nextText: "Next",               //String: Set the text for the "next" directionNav item
       
   819     
       
   820     // Secondary Navigation
       
   821     keyboard: true,                 //Boolean: Allow slider navigating via keyboard left/right keys
       
   822     multipleKeyboard: false,        //{NEW} Boolean: Allow keyboard navigation to affect multiple sliders. Default behavior cuts out keyboard navigation with more than one slider present.
       
   823     mousewheel: false,              //{UPDATED} Boolean: Requires jquery.mousewheel.js (https://github.com/brandonaaron/jquery-mousewheel) - Allows slider navigating via mousewheel
       
   824     pausePlay: false,               //Boolean: Create pause/play dynamic element
       
   825     pauseText: "Pause",             //String: Set the text for the "pause" pausePlay item
       
   826     playText: "Play",               //String: Set the text for the "play" pausePlay item
       
   827     
       
   828     // Special properties
       
   829     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.
       
   830     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.
       
   831     sync: "",                       //{NEW} Selector: Mirror the actions performed on this slider with another slider. Use with care.
       
   832     asNavFor: "",                   //{NEW} Selector: Internal property exposed for turning the slider into a thumbnail navigation for another slider
       
   833     
       
   834     // Carousel Options
       
   835     itemWidth: 0,                   //{NEW} Integer: Box-model width of individual carousel items, including horizontal borders and padding.
       
   836     itemMargin: 0,                  //{NEW} Integer: Margin between carousel items.
       
   837     minItems: 0,                    //{NEW} Integer: Minimum number of carousel items that should be visible. Items will resize fluidly when below this.
       
   838     maxItems: 0,                    //{NEW} Integer: Maxmimum number of carousel items that should be visible. Items will resize fluidly when above this limit.
       
   839     move: 0,                        //{NEW} Integer: Number of carousel items that should move on animation. If 0, slider will move all visible items.
       
   840                                     
       
   841     // Callback API
       
   842     start: function(){},            //Callback: function(slider) - Fires when the slider loads the first slide
       
   843     before: function(){},           //Callback: function(slider) - Fires asynchronously with each slider animation
       
   844     after: function(){},            //Callback: function(slider) - Fires after each slider animation completes
       
   845     end: function(){},              //Callback: function(slider) - Fires when the slider reaches the last slide (asynchronous)
       
   846     added: function(){},            //{NEW} Callback: function(slider) - Fires after a slide is added
       
   847     removed: function(){}           //{NEW} Callback: function(slider) - Fires after a slide is removed
       
   848   }
       
   849 
       
   850 
       
   851   //FlexSlider: Plugin Function
       
   852   $.fn.flexslider = function(options) {
       
   853     if (options === undefined) options = {};
       
   854     
       
   855     if (typeof options === "object") {
       
   856       return this.each(function() {
       
   857         var $this = $(this),
       
   858             selector = (options.selector) ? options.selector : ".slides > li",
       
   859             $slides = $this.find(selector);
       
   860 
       
   861         if ($slides.length === 1) {
       
   862           $slides.fadeIn(400);
       
   863           if (options.start) options.start($this);
       
   864         } else if ($this.data('flexslider') === undefined) {
       
   865           new $.flexslider(this, options);
       
   866         }
       
   867       });
       
   868     } else {
       
   869       // Helper strings to quickly perform functions on the slider
       
   870       var $slider = $(this).data('flexslider');
       
   871       switch (options) {
       
   872         case "play": $slider.play(); break;
       
   873         case "pause": $slider.pause(); break;
       
   874         case "next": $slider.flexAnimate($slider.getTarget("next"), true); break;
       
   875         case "prev":
       
   876         case "previous": $slider.flexAnimate($slider.getTarget("prev"), true); break;
       
   877         default: if (typeof options === "number") $slider.flexAnimate(options, true);
       
   878       }
       
   879     }
       
   880   }  
       
   881 
       
   882 })(jQuery);