spree_showcase 0.6.0 → 0.7

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