spree_showcase 0.6.0 → 0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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);