spree_multi_slideshow 1.2.1 → 1.3.0

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.
Files changed (61) hide show
  1. data/README.md +14 -12
  2. data/app/assets/images/store/bx_loader.gif +0 -0
  3. data/app/assets/images/store/controls.png +0 -0
  4. data/app/assets/javascripts/admin/slide_settings.js.erb +41 -0
  5. data/app/assets/javascripts/admin/slides/index.js.coffee +15 -0
  6. data/app/assets/javascripts/admin/slides/new.js.coffee +7 -0
  7. data/app/assets/javascripts/admin/spree_multi_slideshow.js +3 -1
  8. data/app/assets/javascripts/store/spree_multi_slideshow.js +1284 -1
  9. data/app/assets/stylesheets/store/spree_multi_slideshow.css +197 -3
  10. data/app/controllers/spree/admin/slide_settings_controller.rb +50 -0
  11. data/app/controllers/spree/admin/slides_controller.rb +15 -14
  12. data/app/controllers/spree/admin/slideshows_controller.rb +31 -0
  13. data/app/helpers/spree/slideshows_helper.rb +68 -0
  14. data/app/models/spree/app_configuration_decorator.rb +25 -0
  15. data/app/models/spree/product_decorator.rb +3 -0
  16. data/app/models/spree/slide.rb +23 -25
  17. data/app/models/spree/slideshow.rb +17 -0
  18. data/app/models/spree/taxon_decorator.rb +3 -0
  19. data/app/overrides/slideshow_admin_tab.rb +10 -0
  20. data/app/views/spree/admin/shared/_slideshow_sub_menu.html.erb +6 -0
  21. data/app/views/spree/admin/shared/_slideshow_tabs.html.erb +21 -0
  22. data/app/views/spree/admin/slide_settings/edit.html.erb +74 -0
  23. data/app/views/spree/admin/slides/_form.html.erb +29 -9
  24. data/app/views/spree/admin/slides/edit.html.erb +26 -16
  25. data/app/views/spree/admin/slides/index.html.erb +47 -31
  26. data/app/views/spree/admin/slides/new.html.erb +12 -9
  27. data/app/views/spree/admin/slideshows/_form.html.erb +59 -0
  28. data/app/views/spree/admin/slideshows/edit.html.erb +17 -0
  29. data/app/views/spree/admin/slideshows/index.html.erb +51 -0
  30. data/app/views/spree/admin/slideshows/new.html.erb +80 -0
  31. data/app/views/spree/admin/slideshows/new.js.erb +2 -0
  32. data/config/locales/en.yml +53 -85
  33. data/config/locales/it.yml +56 -90
  34. data/config/routes.rb +3 -1
  35. data/db/migrate/20120116081431_create_slideshows.rb +17 -0
  36. data/db/migrate/20120116083546_create_slides.rb +5 -4
  37. data/db/migrate/20120323164044_multi_slideshow_namespace.rb +1 -1
  38. data/lib/generators/spree_multi_slideshow/install/install_generator.rb +1 -21
  39. data/lib/spree_multi_slideshow.rb +0 -2
  40. metadata +26 -73
  41. data/app/assets/images/store/slides/bg-gallery.png +0 -0
  42. data/app/assets/images/store/slides/bg-text02.png +0 -0
  43. data/app/assets/images/store/slides/sprite01.png +0 -0
  44. data/app/assets/javascripts/admin/slides/index.js +0 -10
  45. data/app/assets/javascripts/admin/slides/new.js +0 -5
  46. data/app/assets/javascripts/store/fadeGallery.js +0 -229
  47. data/app/assets/stylesheets/admin/spree_multi_slideshow.css +0 -16
  48. data/app/assets/stylesheets/store/carousel_slideshow.css.scss +0 -73
  49. data/app/controllers/spree/admin/slideshow_types_controller.rb +0 -11
  50. data/app/controllers/spree/slides_controller.rb +0 -5
  51. data/app/controllers/spree/slideshow_types_controller.rb +0 -5
  52. data/app/helpers/spree/slides_helper.rb +0 -4
  53. data/app/helpers/spree/slideshow_types_helper.rb +0 -53
  54. data/app/models/spree/slideshow_type.rb +0 -18
  55. data/app/overrides/slideshow_type_admin_tab.rb +0 -4
  56. data/app/views/spree/admin/shared/_slideshow_type_tabs.html.erb +0 -16
  57. data/app/views/spree/admin/slideshow_types/_form.html.erb +0 -8
  58. data/app/views/spree/admin/slideshow_types/edit.html.erb +0 -8
  59. data/app/views/spree/admin/slideshow_types/index.html.erb +0 -32
  60. data/app/views/spree/admin/slideshow_types/new.html.erb +0 -7
  61. data/db/migrate/20120116081431_create_slideshow_types.rb +0 -15
data/README.md CHANGED
@@ -9,7 +9,7 @@ Basic Installation
9
9
 
10
10
  1. Add the following to your Gemfile
11
11
  <pre>
12
- gem 'spree_multi_slideshow', '~> 1.2.1'
12
+ gem 'spree_multi_slideshow', '~> 1.3.0'
13
13
  </pre>
14
14
  2. Run `bundle install`
15
15
  3. To copy and apply migrations run:
@@ -22,21 +22,23 @@ Example
22
22
 
23
23
  1. add slideshow helper method in your view:
24
24
  <pre>
25
- <%= insert_slideshow %>
25
+ <%= insert_slideshow(:category => "my_category") %>
26
26
  </pre>
27
27
  add slides for the slideshow in the admin section
28
28
  2. Additional options:
29
29
  <pre>
30
- <%= insert_slideshow(:category => "my_category") %>
31
- </pre>
32
- displays slides for which the category column, dafault is "home"
33
- <pre>
34
- <%= insert_slideshow(:style => "small") %>
35
- </pre>
36
- style layout for slideshow: [small, medium, slide, default => custom]
37
- <pre>
38
- <%= insert_slideshow(:enable_content => true/false :style => "custom", :category => "custom") %>
30
+ {
31
+ :id => "my_id"
32
+ :class => "my_class"
33
+ :style => "my_style"
34
+ :auto => true|false
35
+ :next_text => ">>"
36
+ :prev_text => "<<"
37
+ :next_selector => "bx-next"
38
+ :prev_selector => "bx-prev"
39
+ :pagination_class => "my_pagination"
40
+ :show_content => true|false
41
+ }
39
42
  </pre>
40
- added a content_tag for display title and description of slide
41
43
 
42
44
  Copyright (c) 2012 [Damiano Giacomello], released under the New BSD License
@@ -0,0 +1,41 @@
1
+ $(document).ready(function() {
2
+
3
+ $('.destroy_style').live("click", function(e) {
4
+ e.preventDefault();
5
+ $(this).parent().remove();
6
+ });
7
+
8
+ $('.destroy_new_slide_styles').live("click", function(e) {
9
+ e.preventDefault();
10
+ $(this).closest('.new_slide_styles').remove();
11
+ });
12
+
13
+ // Handle adding new styles
14
+ var styles_hash_index = 1;
15
+ $('.add_new_slide_style').live("click", function(e) {
16
+ e.preventDefault();
17
+ $('#new-slide-styles').append(generate_html_for_hash("new_slide_styles", styles_hash_index));
18
+ });
19
+
20
+ // Generates html for new paperclip styles form fields
21
+ generate_html_for_hash = function(hash_name, index) {
22
+ var html = '<div class="' + hash_name + ' row"><div class="field">';
23
+ html += '<div class="five columns">';
24
+ html += '<label for="' + hash_name + '_' + index + '_name">';
25
+ html += Spree.translations.name + '</label>';
26
+ html += '<input id="' + hash_name + '_' + index + '_name" name="' + hash_name + '[' + index + '][name]" type="text" class="fullwidth"><br>';
27
+ html += '</div><div class="five columns">'
28
+ html += '<label for="' + hash_name + '_' + index + '_value">';
29
+ html += Spree.translations.value + '</label>';
30
+ html += '<input id="' + hash_name + '_' + index + '_value" name="' + hash_name + '[' + index + '][value]" type="text" class="fullwidth">';
31
+ html += '</div><div class="two columns">'
32
+ html += '<a href="#" title="' + Spree.translations.destroy + '" class="destroy_' + hash_name + ' with-tip button" style="margin-top: 19px;"><i class="icon-trash"></i> &nbsp; ' + Spree.translations.destroy + '</a>';
33
+ html += '</div></div></div>';
34
+
35
+ index += 1;
36
+ return html;
37
+ };
38
+
39
+
40
+
41
+ });
@@ -0,0 +1,15 @@
1
+ $ ->
2
+ ($ '#new_slide_link').click (event) ->
3
+ event.preventDefault()
4
+
5
+ ($ '.no-objects-found').hide()
6
+
7
+ ($ this).hide()
8
+ $.ajax
9
+ type: 'GET'
10
+ url: @href
11
+ data: (
12
+ authenticity_token: AUTH_TOKEN
13
+ )
14
+ success: (r) ->
15
+ ($ '#slides').html r
@@ -0,0 +1,7 @@
1
+ ($ '#cancel_link').click (event) ->
2
+ event.preventDefault()
3
+
4
+ ($ '.no-objects-found').show()
5
+
6
+ ($ '#new_slide_link').show()
7
+ ($ '#slides').html('')
@@ -1 +1,3 @@
1
- //= require ckeditor/init
1
+ //= require admin/slides/index
2
+ //= require admin/slide_settings
3
+ //= require_self
@@ -1 +1,1284 @@
1
- //= require store/fadeGallery
1
+ /**
2
+ * BxSlider v4.1 - Fully loaded, responsive content slider
3
+ * http://bxslider.com
4
+ *
5
+ * Copyright 2012, Steven Wanderski - http://stevenwanderski.com - http://bxcreative.com
6
+ * Written while drinking Belgian ales and listening to jazz
7
+ *
8
+ * Released under the WTFPL license - http://sam.zoy.org/wtfpl/
9
+ */
10
+
11
+ ;(function($){
12
+
13
+ var plugin = {};
14
+
15
+ var defaults = {
16
+
17
+ // GENERAL
18
+ mode: 'horizontal',
19
+ slideSelector: '',
20
+ infiniteLoop: true,
21
+ hideControlOnEnd: false,
22
+ speed: 500,
23
+ easing: null,
24
+ slideMargin: 0,
25
+ startSlide: 0,
26
+ randomStart: false,
27
+ captions: false,
28
+ ticker: false,
29
+ tickerHover: false,
30
+ adaptiveHeight: false,
31
+ adaptiveHeightSpeed: 500,
32
+ video: false,
33
+ useCSS: true,
34
+ preloadImages: 'visible',
35
+
36
+ // TOUCH
37
+ touchEnabled: true,
38
+ swipeThreshold: 50,
39
+ oneToOneTouch: true,
40
+ preventDefaultSwipeX: true,
41
+ preventDefaultSwipeY: false,
42
+
43
+ // PAGER
44
+ pager: true,
45
+ pagerType: 'full',
46
+ pagerShortSeparator: ' / ',
47
+ pagerSelector: null,
48
+ buildPager: null,
49
+ pagerCustom: null,
50
+
51
+ // CONTROLS
52
+ controls: true,
53
+ nextText: 'Next',
54
+ prevText: 'Prev',
55
+ nextSelector: null,
56
+ prevSelector: null,
57
+ autoControls: false,
58
+ startText: 'Start',
59
+ stopText: 'Stop',
60
+ autoControlsCombine: false,
61
+ autoControlsSelector: null,
62
+
63
+ // AUTO
64
+ auto: false,
65
+ pause: 4000,
66
+ autoStart: true,
67
+ autoDirection: 'next',
68
+ autoHover: false,
69
+ autoDelay: 0,
70
+
71
+ // CAROUSEL
72
+ minSlides: 1,
73
+ maxSlides: 1,
74
+ moveSlides: 0,
75
+ slideWidth: 0,
76
+
77
+ // CALLBACKS
78
+ onSliderLoad: function() {},
79
+ onSlideBefore: function() {},
80
+ onSlideAfter: function() {},
81
+ onSlideNext: function() {},
82
+ onSlidePrev: function() {}
83
+ }
84
+
85
+ $.fn.bxSlider = function(options){
86
+
87
+ if(this.length == 0) return;
88
+
89
+ // support mutltiple elements
90
+ if(this.length > 1){
91
+ this.each(function(){$(this).bxSlider(options)});
92
+ return this;
93
+ }
94
+
95
+ // create a namespace to be used throughout the plugin
96
+ var slider = {};
97
+ // set a reference to our slider element
98
+ var el = this;
99
+ plugin.el = this;
100
+
101
+ /**
102
+ * Makes slideshow responsive
103
+ */
104
+ // first get the original window dimens (thanks alot IE)
105
+ var windowWidth = $(window).width();
106
+ var windowHeight = $(window).height();
107
+
108
+
109
+
110
+ /**
111
+ * ===================================================================================
112
+ * = PRIVATE FUNCTIONS
113
+ * ===================================================================================
114
+ */
115
+
116
+ /**
117
+ * Initializes namespace settings to be used throughout plugin
118
+ */
119
+ var init = function(){
120
+ // merge user-supplied options with the defaults
121
+ slider.settings = $.extend({}, defaults, options);
122
+ // parse slideWidth setting
123
+ slider.settings.slideWidth = parseInt(slider.settings.slideWidth);
124
+ // store the original children
125
+ slider.children = el.children(slider.settings.slideSelector);
126
+ // check if actual number of slides is less than minSlides / maxSlides
127
+ if(slider.children.length < slider.settings.minSlides) slider.settings.minSlides = slider.children.length;
128
+ if(slider.children.length < slider.settings.maxSlides) slider.settings.maxSlides = slider.children.length;
129
+ // if random start, set the startSlide setting to random number
130
+ if(slider.settings.randomStart) slider.settings.startSlide = Math.floor(Math.random() * slider.children.length);
131
+ // store active slide information
132
+ slider.active = { index: slider.settings.startSlide }
133
+ // store if the slider is in carousel mode (displaying / moving multiple slides)
134
+ slider.carousel = slider.settings.minSlides > 1 || slider.settings.maxSlides > 1;
135
+ // if carousel, force preloadImages = 'all'
136
+ if(slider.carousel) slider.settings.preloadImages = 'all';
137
+ // calculate the min / max width thresholds based on min / max number of slides
138
+ // used to setup and update carousel slides dimensions
139
+ slider.minThreshold = (slider.settings.minSlides * slider.settings.slideWidth) + ((slider.settings.minSlides - 1) * slider.settings.slideMargin);
140
+ slider.maxThreshold = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin);
141
+ // store the current state of the slider (if currently animating, working is true)
142
+ slider.working = false;
143
+ // initialize the controls object
144
+ slider.controls = {};
145
+ // initialize an auto interval
146
+ slider.interval = null;
147
+ // determine which property to use for transitions
148
+ slider.animProp = slider.settings.mode == 'vertical' ? 'top' : 'left';
149
+ // determine if hardware acceleration can be used
150
+ slider.usingCSS = slider.settings.useCSS && slider.settings.mode != 'fade' && (function(){
151
+ // create our test div element
152
+ var div = document.createElement('div');
153
+ // css transition properties
154
+ var props = ['WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective'];
155
+ // test for each property
156
+ for(var i in props){
157
+ if(div.style[props[i]] !== undefined){
158
+ slider.cssPrefix = props[i].replace('Perspective', '').toLowerCase();
159
+ slider.animProp = '-' + slider.cssPrefix + '-transform';
160
+ return true;
161
+ }
162
+ }
163
+ return false;
164
+ }());
165
+ // if vertical mode always make maxSlides and minSlides equal
166
+ if(slider.settings.mode == 'vertical') slider.settings.maxSlides = slider.settings.minSlides;
167
+ // perform all DOM / CSS modifications
168
+ setup();
169
+ }
170
+
171
+ /**
172
+ * Performs all DOM and CSS modifications
173
+ */
174
+ var setup = function(){
175
+ // wrap el in a wrapper
176
+ el.wrap('<div class="bx-wrapper"><div class="bx-viewport"></div></div>');
177
+ // store a namspace reference to .bx-viewport
178
+ slider.viewport = el.parent();
179
+ // add a loading div to display while images are loading
180
+ slider.loader = $('<div class="bx-loading" />');
181
+ slider.viewport.prepend(slider.loader);
182
+ // set el to a massive width, to hold any needed slides
183
+ // also strip any margin and padding from el
184
+ el.css({
185
+ width: slider.settings.mode == 'horizontal' ? slider.children.length * 215 + '%' : 'auto',
186
+ position: 'relative'
187
+ });
188
+ // if using CSS, add the easing property
189
+ if(slider.usingCSS && slider.settings.easing){
190
+ el.css('-' + slider.cssPrefix + '-transition-timing-function', slider.settings.easing);
191
+ // if not using CSS and no easing value was supplied, use the default JS animation easing (swing)
192
+ }else if(!slider.settings.easing){
193
+ slider.settings.easing = 'swing';
194
+ }
195
+ var slidesShowing = getNumberSlidesShowing();
196
+ // make modifications to the viewport (.bx-viewport)
197
+ slider.viewport.css({
198
+ width: '100%',
199
+ overflow: 'hidden',
200
+ position: 'relative'
201
+ });
202
+ slider.viewport.parent().css({
203
+ maxWidth: getViewportMaxWidth()
204
+ });
205
+ // apply css to all slider children
206
+ slider.children.css({
207
+ 'float': slider.settings.mode == 'horizontal' ? 'left' : 'none',
208
+ listStyle: 'none',
209
+ position: 'relative'
210
+ });
211
+ // apply the calculated width after the float is applied to prevent scrollbar interference
212
+ slider.children.width(getSlideWidth());
213
+ // if slideMargin is supplied, add the css
214
+ if(slider.settings.mode == 'horizontal' && slider.settings.slideMargin > 0) slider.children.css('marginRight', slider.settings.slideMargin);
215
+ if(slider.settings.mode == 'vertical' && slider.settings.slideMargin > 0) slider.children.css('marginBottom', slider.settings.slideMargin);
216
+ // if "fade" mode, add positioning and z-index CSS
217
+ if(slider.settings.mode == 'fade'){
218
+ slider.children.css({
219
+ position: 'absolute',
220
+ zIndex: 0,
221
+ display: 'none'
222
+ });
223
+ // prepare the z-index on the showing element
224
+ slider.children.eq(slider.settings.startSlide).css({zIndex: 50, display: 'block'});
225
+ }
226
+ // create an element to contain all slider controls (pager, start / stop, etc)
227
+ slider.controls.el = $('<div class="bx-controls" />');
228
+ // if captions are requested, add them
229
+ if(slider.settings.captions) appendCaptions();
230
+ // if infinite loop, prepare additional slides
231
+ if(slider.settings.infiniteLoop && slider.settings.mode != 'fade' && !slider.settings.ticker){
232
+ var slice = slider.settings.mode == 'vertical' ? slider.settings.minSlides : slider.settings.maxSlides;
233
+ var sliceAppend = slider.children.slice(0, slice).clone().addClass('bx-clone');
234
+ var slicePrepend = slider.children.slice(-slice).clone().addClass('bx-clone');
235
+ el.append(sliceAppend).prepend(slicePrepend);
236
+ }
237
+ // check if startSlide is last slide
238
+ slider.active.last = slider.settings.startSlide == getPagerQty() - 1;
239
+ // if video is true, set up the fitVids plugin
240
+ if(slider.settings.video) el.fitVids();
241
+ // set the default preload selector (visible)
242
+ var preloadSelector = slider.children.eq(slider.settings.startSlide);
243
+ if (slider.settings.preloadImages == "all") preloadSelector = el.children();
244
+ // only check for control addition if not in "ticker" mode
245
+ if(!slider.settings.ticker){
246
+ // if pager is requested, add it
247
+ if(slider.settings.pager) appendPager();
248
+ // if controls are requested, add them
249
+ if(slider.settings.controls) appendControls();
250
+ // if auto is true, and auto controls are requested, add them
251
+ if(slider.settings.auto && slider.settings.autoControls) appendControlsAuto();
252
+ // if any control option is requested, add the controls wrapper
253
+ if(slider.settings.controls || slider.settings.autoControls || slider.settings.pager) slider.viewport.after(slider.controls.el);
254
+ }
255
+ // preload all images, then perform final DOM / CSS modifications that depend on images being loaded
256
+ preloadSelector.imagesLoaded(start);
257
+ }
258
+
259
+ /**
260
+ * Start the slider
261
+ */
262
+ var start = function(){
263
+ // remove the loading DOM element
264
+ slider.loader.remove();
265
+ // set the left / top position of "el"
266
+ setSlidePosition();
267
+ // if "vertical" mode, always use adaptiveHeight to prevent odd behavior
268
+ if (slider.settings.mode == 'vertical') slider.settings.adaptiveHeight = true;
269
+ // set the viewport height
270
+ slider.viewport.height(getViewportHeight());
271
+ // make sure everything is positioned just right (same as a window resize)
272
+ el.redrawSlider();
273
+ // onSliderLoad callback
274
+ slider.settings.onSliderLoad(slider.active.index);
275
+ // slider has been fully initialized
276
+ slider.initialized = true;
277
+ // bind the resize call to the window
278
+ $(window).bind('resize', resizeWindow);
279
+ // if auto is true, start the show
280
+ if (slider.settings.auto && slider.settings.autoStart) initAuto();
281
+ // if ticker is true, start the ticker
282
+ if (slider.settings.ticker) initTicker();
283
+ // if pager is requested, make the appropriate pager link active
284
+ if (slider.settings.pager) updatePagerActive(slider.settings.startSlide);
285
+ // check for any updates to the controls (like hideControlOnEnd updates)
286
+ if (slider.settings.controls) updateDirectionControls();
287
+ // if touchEnabled is true, setup the touch events
288
+ if (slider.settings.touchEnabled && !slider.settings.ticker) initTouch();
289
+ }
290
+
291
+ /**
292
+ * Returns the calculated height of the viewport, used to determine either adaptiveHeight or the maxHeight value
293
+ */
294
+ var getViewportHeight = function(){
295
+ var height = 0;
296
+ // first determine which children (slides) should be used in our height calculation
297
+ var children = $();
298
+ // if mode is not "vertical" and adaptiveHeight is false, include all children
299
+ if(slider.settings.mode != 'vertical' && !slider.settings.adaptiveHeight){
300
+ children = slider.children;
301
+ }else{
302
+ // if not carousel, return the single active child
303
+ if(!slider.carousel){
304
+ children = slider.children.eq(slider.active.index);
305
+ // if carousel, return a slice of children
306
+ }else{
307
+ // get the individual slide index
308
+ var currentIndex = slider.settings.moveSlides == 1 ? slider.active.index : slider.active.index * getMoveBy();
309
+ // add the current slide to the children
310
+ children = slider.children.eq(currentIndex);
311
+ // cycle through the remaining "showing" slides
312
+ for (i = 1; i <= slider.settings.maxSlides - 1; i++){
313
+ // if looped back to the start
314
+ if(currentIndex + i >= slider.children.length){
315
+ children = children.add(slider.children.eq(i - 1));
316
+ }else{
317
+ children = children.add(slider.children.eq(currentIndex + i));
318
+ }
319
+ }
320
+ }
321
+ }
322
+ // if "vertical" mode, calculate the sum of the heights of the children
323
+ if(slider.settings.mode == 'vertical'){
324
+ children.each(function(index) {
325
+ height += $(this).outerHeight();
326
+ });
327
+ // add user-supplied margins
328
+ if(slider.settings.slideMargin > 0){
329
+ height += slider.settings.slideMargin * (slider.settings.minSlides - 1);
330
+ }
331
+ // if not "vertical" mode, calculate the max height of the children
332
+ }else{
333
+ height = Math.max.apply(Math, children.map(function(){
334
+ return $(this).outerHeight(false);
335
+ }).get());
336
+ }
337
+ return height;
338
+ }
339
+
340
+ /**
341
+ * Returns the calculated width to be used for the outer wrapper / viewport
342
+ */
343
+ var getViewportMaxWidth = function(){
344
+ var width = '100%';
345
+ if(slider.settings.slideWidth > 0){
346
+ if(slider.settings.mode == 'horizontal'){
347
+ width = (slider.settings.maxSlides * slider.settings.slideWidth) + ((slider.settings.maxSlides - 1) * slider.settings.slideMargin);
348
+ }else{
349
+ width = slider.settings.slideWidth;
350
+ }
351
+ }
352
+ return width;
353
+ }
354
+
355
+ /**
356
+ * Returns the calculated width to be applied to each slide
357
+ */
358
+ var getSlideWidth = function(){
359
+ // start with any user-supplied slide width
360
+ var newElWidth = slider.settings.slideWidth;
361
+ // get the current viewport width
362
+ var wrapWidth = slider.viewport.width();
363
+ // if slide width was not supplied, or is larger than the viewport use the viewport width
364
+ if(slider.settings.slideWidth == 0 ||
365
+ (slider.settings.slideWidth > wrapWidth && !slider.carousel) ||
366
+ slider.settings.mode == 'vertical'){
367
+ newElWidth = wrapWidth;
368
+ // if carousel, use the thresholds to determine the width
369
+ }else if(slider.settings.maxSlides > 1 && slider.settings.mode == 'horizontal'){
370
+ if(wrapWidth > slider.maxThreshold){
371
+ // newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.maxSlides - 1))) / slider.settings.maxSlides;
372
+ }else if(wrapWidth < slider.minThreshold){
373
+ newElWidth = (wrapWidth - (slider.settings.slideMargin * (slider.settings.minSlides - 1))) / slider.settings.minSlides;
374
+ }
375
+ }
376
+ return newElWidth;
377
+ }
378
+
379
+ /**
380
+ * Returns the number of slides currently visible in the viewport (includes partially visible slides)
381
+ */
382
+ var getNumberSlidesShowing = function(){
383
+ var slidesShowing = 1;
384
+ if(slider.settings.mode == 'horizontal' && slider.settings.slideWidth > 0){
385
+ // if viewport is smaller than minThreshold, return minSlides
386
+ if(slider.viewport.width() < slider.minThreshold){
387
+ slidesShowing = slider.settings.minSlides;
388
+ // if viewport is larger than minThreshold, return maxSlides
389
+ }else if(slider.viewport.width() > slider.maxThreshold){
390
+ slidesShowing = slider.settings.maxSlides;
391
+ // if viewport is between min / max thresholds, divide viewport width by first child width
392
+ }else{
393
+ var childWidth = slider.children.first().width();
394
+ slidesShowing = Math.floor(slider.viewport.width() / childWidth);
395
+ }
396
+ // if "vertical" mode, slides showing will always be minSlides
397
+ }else if(slider.settings.mode == 'vertical'){
398
+ slidesShowing = slider.settings.minSlides;
399
+ }
400
+ return slidesShowing;
401
+ }
402
+
403
+ /**
404
+ * Returns the number of pages (one full viewport of slides is one "page")
405
+ */
406
+ var getPagerQty = function(){
407
+ var pagerQty = 0;
408
+ // if moveSlides is specified by the user
409
+ if(slider.settings.moveSlides > 0){
410
+ if(slider.settings.infiniteLoop){
411
+ pagerQty = slider.children.length / getMoveBy();
412
+ }else{
413
+ // use a while loop to determine pages
414
+ var breakPoint = 0;
415
+ var counter = 0
416
+ // when breakpoint goes above children length, counter is the number of pages
417
+ while (breakPoint < slider.children.length){
418
+ ++pagerQty;
419
+ breakPoint = counter + getNumberSlidesShowing();
420
+ counter += slider.settings.moveSlides <= getNumberSlidesShowing() ? slider.settings.moveSlides : getNumberSlidesShowing();
421
+ }
422
+ }
423
+ // if moveSlides is 0 (auto) divide children length by sides showing, then round up
424
+ }else{
425
+ pagerQty = Math.ceil(slider.children.length / getNumberSlidesShowing());
426
+ }
427
+ return pagerQty;
428
+ }
429
+
430
+ /**
431
+ * Returns the number of indivual slides by which to shift the slider
432
+ */
433
+ var getMoveBy = function(){
434
+ // if moveSlides was set by the user and moveSlides is less than number of slides showing
435
+ if(slider.settings.moveSlides > 0 && slider.settings.moveSlides <= getNumberSlidesShowing()){
436
+ return slider.settings.moveSlides;
437
+ }
438
+ // if moveSlides is 0 (auto)
439
+ return getNumberSlidesShowing();
440
+ }
441
+
442
+ /**
443
+ * Sets the slider's (el) left or top position
444
+ */
445
+ var setSlidePosition = function(){
446
+ // if last slide, not infinite loop, and number of children is larger than specified maxSlides
447
+ if(slider.children.length > slider.settings.maxSlides && slider.active.last && !slider.settings.infiniteLoop){
448
+ if (slider.settings.mode == 'horizontal'){
449
+ // get the last child's position
450
+ var lastChild = slider.children.last();
451
+ var position = lastChild.position();
452
+ // set the left position
453
+ setPositionProperty(-(position.left - (slider.viewport.width() - lastChild.width())), 'reset', 0);
454
+ }else if(slider.settings.mode == 'vertical'){
455
+ // get the last showing index's position
456
+ var lastShowingIndex = slider.children.length - slider.settings.minSlides;
457
+ var position = slider.children.eq(lastShowingIndex).position();
458
+ // set the top position
459
+ setPositionProperty(-position.top, 'reset', 0);
460
+ }
461
+ // if not last slide
462
+ }else{
463
+ // get the position of the first showing slide
464
+ var position = slider.children.eq(slider.active.index * getMoveBy()).position();
465
+ // check for last slide
466
+ if (slider.active.index == getPagerQty() - 1) slider.active.last = true;
467
+ // set the repective position
468
+ if (position != undefined){
469
+ if (slider.settings.mode == 'horizontal') setPositionProperty(-position.left, 'reset', 0);
470
+ else if (slider.settings.mode == 'vertical') setPositionProperty(-position.top, 'reset', 0);
471
+ }
472
+ }
473
+ }
474
+
475
+ /**
476
+ * Sets the el's animating property position (which in turn will sometimes animate el).
477
+ * If using CSS, sets the transform property. If not using CSS, sets the top / left property.
478
+ *
479
+ * @param value (int)
480
+ * - the animating property's value
481
+ *
482
+ * @param type (string) 'slider', 'reset', 'ticker'
483
+ * - the type of instance for which the function is being
484
+ *
485
+ * @param duration (int)
486
+ * - the amount of time (in ms) the transition should occupy
487
+ *
488
+ * @param params (array) optional
489
+ * - an optional parameter containing any variables that need to be passed in
490
+ */
491
+ var setPositionProperty = function(value, type, duration, params){
492
+ // use CSS transform
493
+ if(slider.usingCSS){
494
+ // determine the translate3d value
495
+ var propValue = slider.settings.mode == 'vertical' ? 'translate3d(0, ' + value + 'px, 0)' : 'translate3d(' + value + 'px, 0, 0)';
496
+ // add the CSS transition-duration
497
+ el.css('-' + slider.cssPrefix + '-transition-duration', duration / 1000 + 's');
498
+ if(type == 'slide'){
499
+ // set the property value
500
+ el.css(slider.animProp, propValue);
501
+ // bind a callback method - executes when CSS transition completes
502
+ el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){
503
+ // unbind the callback
504
+ el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
505
+ updateAfterSlideTransition();
506
+ });
507
+ }else if(type == 'reset'){
508
+ el.css(slider.animProp, propValue);
509
+ }else if(type == 'ticker'){
510
+ // make the transition use 'linear'
511
+ el.css('-' + slider.cssPrefix + '-transition-timing-function', 'linear');
512
+ el.css(slider.animProp, propValue);
513
+ // bind a callback method - executes when CSS transition completes
514
+ el.bind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(){
515
+ // unbind the callback
516
+ el.unbind('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd');
517
+ // reset the position
518
+ setPositionProperty(params['resetValue'], 'reset', 0);
519
+ // start the loop again
520
+ tickerLoop();
521
+ });
522
+ }
523
+ // use JS animate
524
+ }else{
525
+ var animateObj = {};
526
+ animateObj[slider.animProp] = value;
527
+ if(type == 'slide'){
528
+ el.animate(animateObj, duration, slider.settings.easing, function(){
529
+ updateAfterSlideTransition();
530
+ });
531
+ }else if(type == 'reset'){
532
+ el.css(slider.animProp, value)
533
+ }else if(type == 'ticker'){
534
+ el.animate(animateObj, speed, 'linear', function(){
535
+ setPositionProperty(params['resetValue'], 'reset', 0);
536
+ // run the recursive loop after animation
537
+ tickerLoop();
538
+ });
539
+ }
540
+ }
541
+ }
542
+
543
+ /**
544
+ * Populates the pager with proper amount of pages
545
+ */
546
+ var populatePager = function(){
547
+ var pagerHtml = '';
548
+ pagerQty = getPagerQty();
549
+ // loop through each pager item
550
+ for(var i=0; i < pagerQty; i++){
551
+ var linkContent = '';
552
+ // if a buildPager function is supplied, use it to get pager link value, else use index + 1
553
+ if(slider.settings.buildPager && $.isFunction(slider.settings.buildPager)){
554
+ linkContent = slider.settings.buildPager(i);
555
+ slider.pagerEl.addClass('bx-custom-pager');
556
+ }else{
557
+ linkContent = i + 1;
558
+ slider.pagerEl.addClass('bx-default-pager');
559
+ }
560
+ // var linkContent = slider.settings.buildPager && $.isFunction(slider.settings.buildPager) ? slider.settings.buildPager(i) : i + 1;
561
+ // add the markup to the string
562
+ pagerHtml += '<div class="bx-pager-item"><a href="" data-slide-index="' + i + '" class="bx-pager-link">' + linkContent + '</a></div>';
563
+ };
564
+ // populate the pager element with pager links
565
+ slider.pagerEl.html(pagerHtml);
566
+ }
567
+
568
+ /**
569
+ * Appends the pager to the controls element
570
+ */
571
+ var appendPager = function(){
572
+ if(!slider.settings.pagerCustom){
573
+ // create the pager DOM element
574
+ slider.pagerEl = $('<div class="bx-pager" />');
575
+ // if a pager selector was supplied, populate it with the pager
576
+ if(slider.settings.pagerSelector){
577
+ $(slider.settings.pagerSelector).html(slider.pagerEl);
578
+ // if no pager selector was supplied, add it after the wrapper
579
+ }else{
580
+ slider.controls.el.addClass('bx-has-pager').append(slider.pagerEl);
581
+ }
582
+ // populate the pager
583
+ populatePager();
584
+ }else{
585
+ slider.pagerEl = $(slider.settings.pagerCustom);
586
+ }
587
+ // assign the pager click binding
588
+ slider.pagerEl.delegate('a', 'click', clickPagerBind);
589
+ }
590
+
591
+ /**
592
+ * Appends prev / next controls to the controls element
593
+ */
594
+ var appendControls = function(){
595
+ slider.controls.next = $('<a class="bx-next" href="">' + slider.settings.nextText + '</a>');
596
+ slider.controls.prev = $('<a class="bx-prev" href="">' + slider.settings.prevText + '</a>');
597
+ // bind click actions to the controls
598
+ slider.controls.next.bind('click', clickNextBind);
599
+ slider.controls.prev.bind('click', clickPrevBind);
600
+ // if nextSlector was supplied, populate it
601
+ if(slider.settings.nextSelector){
602
+ $(slider.settings.nextSelector).append(slider.controls.next);
603
+ }
604
+ // if prevSlector was supplied, populate it
605
+ if(slider.settings.prevSelector){
606
+ $(slider.settings.prevSelector).append(slider.controls.prev);
607
+ }
608
+ // if no custom selectors were supplied
609
+ if(!slider.settings.nextSelector && !slider.settings.prevSelector){
610
+ // add the controls to the DOM
611
+ slider.controls.directionEl = $('<div class="bx-controls-direction" />');
612
+ // add the control elements to the directionEl
613
+ slider.controls.directionEl.append(slider.controls.prev).append(slider.controls.next);
614
+ // slider.viewport.append(slider.controls.directionEl);
615
+ slider.controls.el.addClass('bx-has-controls-direction').append(slider.controls.directionEl);
616
+ }
617
+ }
618
+
619
+ /**
620
+ * Appends start / stop auto controls to the controls element
621
+ */
622
+ var appendControlsAuto = function(){
623
+ slider.controls.start = $('<div class="bx-controls-auto-item"><a class="bx-start" href="">' + slider.settings.startText + '</a></div>');
624
+ slider.controls.stop = $('<div class="bx-controls-auto-item"><a class="bx-stop" href="">' + slider.settings.stopText + '</a></div>');
625
+ // add the controls to the DOM
626
+ slider.controls.autoEl = $('<div class="bx-controls-auto" />');
627
+ // bind click actions to the controls
628
+ slider.controls.autoEl.delegate('.bx-start', 'click', clickStartBind);
629
+ slider.controls.autoEl.delegate('.bx-stop', 'click', clickStopBind);
630
+ // if autoControlsCombine, insert only the "start" control
631
+ if(slider.settings.autoControlsCombine){
632
+ slider.controls.autoEl.append(slider.controls.start);
633
+ // if autoControlsCombine is false, insert both controls
634
+ }else{
635
+ slider.controls.autoEl.append(slider.controls.start).append(slider.controls.stop);
636
+ }
637
+ // if auto controls selector was supplied, populate it with the controls
638
+ if(slider.settings.autoControlsSelector){
639
+ $(slider.settings.autoControlsSelector).html(slider.controls.autoEl);
640
+ // if auto controls selector was not supplied, add it after the wrapper
641
+ }else{
642
+ slider.controls.el.addClass('bx-has-controls-auto').append(slider.controls.autoEl);
643
+ }
644
+ // update the auto controls
645
+ updateAutoControls(slider.settings.autoStart ? 'stop' : 'start');
646
+ }
647
+
648
+ /**
649
+ * Appends image captions to the DOM
650
+ */
651
+ var appendCaptions = function(){
652
+ // cycle through each child
653
+ slider.children.each(function(index){
654
+ // get the image title attribute
655
+ var title = $(this).find('img:first').attr('title');
656
+ // append the caption
657
+ if (title != undefined) $(this).append('<div class="bx-caption"><span>' + title + '</span></div>');
658
+ });
659
+ }
660
+
661
+ /**
662
+ * Click next binding
663
+ *
664
+ * @param e (event)
665
+ * - DOM event object
666
+ */
667
+ var clickNextBind = function(e){
668
+ // if auto show is running, stop it
669
+ if (slider.settings.auto) el.stopAuto();
670
+ el.goToNextSlide();
671
+ e.preventDefault();
672
+ }
673
+
674
+ /**
675
+ * Click prev binding
676
+ *
677
+ * @param e (event)
678
+ * - DOM event object
679
+ */
680
+ var clickPrevBind = function(e){
681
+ // if auto show is running, stop it
682
+ if (slider.settings.auto) el.stopAuto();
683
+ el.goToPrevSlide();
684
+ e.preventDefault();
685
+ }
686
+
687
+ /**
688
+ * Click start binding
689
+ *
690
+ * @param e (event)
691
+ * - DOM event object
692
+ */
693
+ var clickStartBind = function(e){
694
+ el.startAuto();
695
+ e.preventDefault();
696
+ }
697
+
698
+ /**
699
+ * Click stop binding
700
+ *
701
+ * @param e (event)
702
+ * - DOM event object
703
+ */
704
+ var clickStopBind = function(e){
705
+ el.stopAuto();
706
+ e.preventDefault();
707
+ }
708
+
709
+ /**
710
+ * Click pager binding
711
+ *
712
+ * @param e (event)
713
+ * - DOM event object
714
+ */
715
+ var clickPagerBind = function(e){
716
+ // if auto show is running, stop it
717
+ if (slider.settings.auto) el.stopAuto();
718
+ var pagerLink = $(e.currentTarget);
719
+ var pagerIndex = parseInt(pagerLink.attr('data-slide-index'));
720
+ // if clicked pager link is not active, continue with the goToSlide call
721
+ if(pagerIndex != slider.active.index) el.goToSlide(pagerIndex);
722
+ e.preventDefault();
723
+ }
724
+
725
+ /**
726
+ * Updates the pager links with an active class
727
+ *
728
+ * @param slideIndex (int)
729
+ * - index of slide to make active
730
+ */
731
+ var updatePagerActive = function(slideIndex){
732
+ // if "short" pager type
733
+ if(slider.settings.pagerType == 'short'){
734
+ slider.pagerEl.html((slideIndex + 1) + slider.settings.pagerShortSeparator + slider.children.length);
735
+ return;
736
+ }
737
+ // remove all pager active classes
738
+ slider.pagerEl.find('a').removeClass('active');
739
+ // apply the active class for all pagers
740
+ slider.pagerEl.each(function(i, el) { $(el).find('a').eq(slideIndex).addClass('active'); });
741
+ }
742
+
743
+ /**
744
+ * Performs needed actions after a slide transition
745
+ */
746
+ var updateAfterSlideTransition = function(){
747
+ // if infinte loop is true
748
+ if(slider.settings.infiniteLoop){
749
+ var position = '';
750
+ // first slide
751
+ if(slider.active.index == 0){
752
+ // set the new position
753
+ position = slider.children.eq(0).position();
754
+ // carousel, last slide
755
+ }else if(slider.active.index == getPagerQty() - 1 && slider.carousel){
756
+ position = slider.children.eq((getPagerQty() - 1) * getMoveBy()).position();
757
+ // last slide
758
+ }else if(slider.active.index == slider.children.length - 1){
759
+ position = slider.children.eq(slider.children.length - 1).position();
760
+ }
761
+ if (slider.settings.mode == 'horizontal') { setPositionProperty(-position.left, 'reset', 0);; }
762
+ else if (slider.settings.mode == 'vertical') { setPositionProperty(-position.top, 'reset', 0);; }
763
+ }
764
+ // declare that the transition is complete
765
+ slider.working = false;
766
+ // onSlideAfter callback
767
+ slider.settings.onSlideAfter(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
768
+ }
769
+
770
+ /**
771
+ * Updates the auto controls state (either active, or combined switch)
772
+ *
773
+ * @param state (string) "start", "stop"
774
+ * - the new state of the auto show
775
+ */
776
+ var updateAutoControls = function(state){
777
+ // if autoControlsCombine is true, replace the current control with the new state
778
+ if(slider.settings.autoControlsCombine){
779
+ slider.controls.autoEl.html(slider.controls[state]);
780
+ // if autoControlsCombine is false, apply the "active" class to the appropriate control
781
+ }else{
782
+ slider.controls.autoEl.find('a').removeClass('active');
783
+ slider.controls.autoEl.find('a:not(.bx-' + state + ')').addClass('active');
784
+ }
785
+ }
786
+
787
+ /**
788
+ * Updates the direction controls (checks if either should be hidden)
789
+ */
790
+ var updateDirectionControls = function(){
791
+ // if infiniteLoop is false and hideControlOnEnd is true
792
+ if(!slider.settings.infiniteLoop && slider.settings.hideControlOnEnd){
793
+ // if first slide
794
+ if (slider.active.index == 0){
795
+ slider.controls.prev.addClass('disabled');
796
+ slider.controls.next.removeClass('disabled');
797
+ // if last slide
798
+ }else if(slider.active.index == getPagerQty() - 1){
799
+ slider.controls.next.addClass('disabled');
800
+ slider.controls.prev.removeClass('disabled');
801
+ // if any slide in the middle
802
+ }else{
803
+ slider.controls.prev.removeClass('disabled');
804
+ slider.controls.next.removeClass('disabled');
805
+ }
806
+ // if slider has only one page, disable controls
807
+ }else if(getPagerQty() == 1){
808
+ slider.controls.prev.addClass('disabled');
809
+ slider.controls.next.addClass('disabled');
810
+ }
811
+ }
812
+
813
+ /**
814
+ * Initialzes the auto process
815
+ */
816
+ var initAuto = function(){
817
+ // if autoDelay was supplied, launch the auto show using a setTimeout() call
818
+ if(slider.settings.autoDelay > 0){
819
+ var timeout = setTimeout(el.startAuto, slider.settings.autoDelay);
820
+ // if autoDelay was not supplied, start the auto show normally
821
+ }else{
822
+ el.startAuto();
823
+ }
824
+ // if autoHover is requested
825
+ if(slider.settings.autoHover){
826
+ // on el hover
827
+ el.hover(function(){
828
+ // if the auto show is currently playing (has an active interval)
829
+ if(slider.interval){
830
+ // stop the auto show and pass true agument which will prevent control update
831
+ el.stopAuto(true);
832
+ // create a new autoPaused value which will be used by the relative "mouseout" event
833
+ slider.autoPaused = true;
834
+ }
835
+ }, function(){
836
+ // if the autoPaused value was created be the prior "mouseover" event
837
+ if(slider.autoPaused){
838
+ // start the auto show and pass true agument which will prevent control update
839
+ el.startAuto(true);
840
+ // reset the autoPaused value
841
+ slider.autoPaused = null;
842
+ }
843
+ });
844
+ }
845
+ }
846
+
847
+ /**
848
+ * Initialzes the ticker process
849
+ */
850
+ var initTicker = function(){
851
+ var startPosition = 0;
852
+ // if autoDirection is "next", append a clone of the entire slider
853
+ if(slider.settings.autoDirection == 'next'){
854
+ el.append(slider.children.clone().addClass('bx-clone'));
855
+ // if autoDirection is "prev", prepend a clone of the entire slider, and set the left position
856
+ }else{
857
+ el.prepend(slider.children.clone().addClass('bx-clone'));
858
+ var position = slider.children.first().position();
859
+ startPosition = slider.settings.mode == 'horizontal' ? -position.left : -position.top;
860
+ }
861
+ setPositionProperty(startPosition, 'reset', 0);
862
+ // do not allow controls in ticker mode
863
+ slider.settings.pager = false;
864
+ slider.settings.controls = false;
865
+ slider.settings.autoControls = false;
866
+ // if autoHover is requested
867
+ if(slider.settings.tickerHover && !slider.usingCSS){
868
+ // on el hover
869
+ slider.viewport.hover(function(){
870
+ el.stop();
871
+ }, function(){
872
+ // calculate the total width of children (used to calculate the speed ratio)
873
+ var totalDimens = 0;
874
+ slider.children.each(function(index){
875
+ totalDimens += slider.settings.mode == 'horizontal' ? $(this).outerWidth(true) : $(this).outerHeight(true);
876
+ });
877
+ // calculate the speed ratio (used to determine the new speed to finish the paused animation)
878
+ var ratio = slider.settings.speed / totalDimens;
879
+ // determine which property to use
880
+ var property = slider.settings.mode == 'horizontal' ? 'left' : 'top';
881
+ // calculate the new speed
882
+ var newSpeed = ratio * (totalDimens - (Math.abs(parseInt(el.css(property)))));
883
+ tickerLoop(newSpeed);
884
+ });
885
+ }
886
+ // start the ticker loop
887
+ tickerLoop();
888
+ }
889
+
890
+ /**
891
+ * Runs a continuous loop, news ticker-style
892
+ */
893
+ var tickerLoop = function(resumeSpeed){
894
+ speed = resumeSpeed ? resumeSpeed : slider.settings.speed;
895
+ var position = {left: 0, top: 0};
896
+ var reset = {left: 0, top: 0};
897
+ // if "next" animate left position to last child, then reset left to 0
898
+ if(slider.settings.autoDirection == 'next'){
899
+ position = el.find('.bx-clone').first().position();
900
+ // if "prev" animate left position to 0, then reset left to first non-clone child
901
+ }else{
902
+ reset = slider.children.first().position();
903
+ }
904
+ var animateProperty = slider.settings.mode == 'horizontal' ? -position.left : -position.top;
905
+ var resetValue = slider.settings.mode == 'horizontal' ? -reset.left : -reset.top;
906
+ var params = {resetValue: resetValue};
907
+ setPositionProperty(animateProperty, 'ticker', speed, params);
908
+ }
909
+
910
+ /**
911
+ * Initializes touch events
912
+ */
913
+ var initTouch = function(){
914
+ // initialize object to contain all touch values
915
+ slider.touch = {
916
+ start: {x: 0, y: 0},
917
+ end: {x: 0, y: 0}
918
+ }
919
+ slider.viewport.bind('touchstart', onTouchStart);
920
+ }
921
+
922
+ /**
923
+ * Event handler for "touchstart"
924
+ *
925
+ * @param e (event)
926
+ * - DOM event object
927
+ */
928
+ var onTouchStart = function(e){
929
+ if(slider.working){
930
+ e.preventDefault();
931
+ }else{
932
+ // record the original position when touch starts
933
+ slider.touch.originalPos = el.position();
934
+ var orig = e.originalEvent;
935
+ // record the starting touch x, y coordinates
936
+ slider.touch.start.x = orig.changedTouches[0].pageX;
937
+ slider.touch.start.y = orig.changedTouches[0].pageY;
938
+ // bind a "touchmove" event to the viewport
939
+ slider.viewport.bind('touchmove', onTouchMove);
940
+ // bind a "touchend" event to the viewport
941
+ slider.viewport.bind('touchend', onTouchEnd);
942
+ }
943
+ }
944
+
945
+ /**
946
+ * Event handler for "touchmove"
947
+ *
948
+ * @param e (event)
949
+ * - DOM event object
950
+ */
951
+ var onTouchMove = function(e){
952
+ var orig = e.originalEvent;
953
+ // if scrolling on y axis, do not prevent default
954
+ var xMovement = Math.abs(orig.changedTouches[0].pageX - slider.touch.start.x);
955
+ var yMovement = Math.abs(orig.changedTouches[0].pageY - slider.touch.start.y);
956
+ // x axis swipe
957
+ if((xMovement * 3) > yMovement && slider.settings.preventDefaultSwipeX){
958
+ e.preventDefault();
959
+ // y axis swipe
960
+ }else if((yMovement * 3) > xMovement && slider.settings.preventDefaultSwipeY){
961
+ e.preventDefault();
962
+ }
963
+ if(slider.settings.mode != 'fade' && slider.settings.oneToOneTouch){
964
+ var value = 0;
965
+ // if horizontal, drag along x axis
966
+ if(slider.settings.mode == 'horizontal'){
967
+ var change = orig.changedTouches[0].pageX - slider.touch.start.x;
968
+ value = slider.touch.originalPos.left + change;
969
+ // if vertical, drag along y axis
970
+ }else{
971
+ var change = orig.changedTouches[0].pageY - slider.touch.start.y;
972
+ value = slider.touch.originalPos.top + change;
973
+ }
974
+ setPositionProperty(value, 'reset', 0);
975
+ }
976
+ }
977
+
978
+ /**
979
+ * Event handler for "touchend"
980
+ *
981
+ * @param e (event)
982
+ * - DOM event object
983
+ */
984
+ var onTouchEnd = function(e){
985
+ slider.viewport.unbind('touchmove', onTouchMove);
986
+ var orig = e.originalEvent;
987
+ var value = 0;
988
+ // record end x, y positions
989
+ slider.touch.end.x = orig.changedTouches[0].pageX;
990
+ slider.touch.end.y = orig.changedTouches[0].pageY;
991
+ // if fade mode, check if absolute x distance clears the threshold
992
+ if(slider.settings.mode == 'fade'){
993
+ var distance = Math.abs(slider.touch.start.x - slider.touch.end.x);
994
+ if(distance >= slider.settings.swipeThreshold){
995
+ slider.touch.start.x > slider.touch.end.x ? el.goToNextSlide() : el.goToPrevSlide();
996
+ el.stopAuto();
997
+ }
998
+ // not fade mode
999
+ }else{
1000
+ var distance = 0;
1001
+ // calculate distance and el's animate property
1002
+ if(slider.settings.mode == 'horizontal'){
1003
+ distance = slider.touch.end.x - slider.touch.start.x;
1004
+ value = slider.touch.originalPos.left;
1005
+ }else{
1006
+ distance = slider.touch.end.y - slider.touch.start.y;
1007
+ value = slider.touch.originalPos.top;
1008
+ }
1009
+ // if not infinite loop and first / last slide, do not attempt a slide transition
1010
+ if(!slider.settings.infiniteLoop && ((slider.active.index == 0 && distance > 0) || (slider.active.last && distance < 0))){
1011
+ setPositionProperty(value, 'reset', 200);
1012
+ }else{
1013
+ // check if distance clears threshold
1014
+ if(Math.abs(distance) >= slider.settings.swipeThreshold){
1015
+ distance < 0 ? el.goToNextSlide() : el.goToPrevSlide();
1016
+ el.stopAuto();
1017
+ }else{
1018
+ // el.animate(property, 200);
1019
+ setPositionProperty(value, 'reset', 200);
1020
+ }
1021
+ }
1022
+ }
1023
+ slider.viewport.unbind('touchend', onTouchEnd);
1024
+ }
1025
+
1026
+ /**
1027
+ * Window resize event callback
1028
+ */
1029
+ var resizeWindow = function(e){
1030
+ // get the new window dimens (again, thank you IE)
1031
+ var windowWidthNew = $(window).width();
1032
+ var windowHeightNew = $(window).height();
1033
+ // make sure that it is a true window resize
1034
+ // *we must check this because our dinosaur friend IE fires a window resize event when certain DOM elements
1035
+ // are resized. Can you just die already?*
1036
+ if(windowWidth != windowWidthNew || windowHeight != windowHeightNew){
1037
+ // set the new window dimens
1038
+ windowWidth = windowWidthNew;
1039
+ windowHeight = windowHeightNew;
1040
+ // update all dynamic elements
1041
+ el.redrawSlider();
1042
+ }
1043
+ }
1044
+
1045
+ /**
1046
+ * ===================================================================================
1047
+ * = PUBLIC FUNCTIONS
1048
+ * ===================================================================================
1049
+ */
1050
+
1051
+ /**
1052
+ * Performs slide transition to the specified slide
1053
+ *
1054
+ * @param slideIndex (int)
1055
+ * - the destination slide's index (zero-based)
1056
+ *
1057
+ * @param direction (string)
1058
+ * - INTERNAL USE ONLY - the direction of travel ("prev" / "next")
1059
+ */
1060
+ el.goToSlide = function(slideIndex, direction){
1061
+ // if plugin is currently in motion, ignore request
1062
+ if(slider.working || slider.active.index == slideIndex) return;
1063
+ // declare that plugin is in motion
1064
+ slider.working = true;
1065
+ // store the old index
1066
+ slider.oldIndex = slider.active.index;
1067
+ // if slideIndex is less than zero, set active index to last child (this happens during infinite loop)
1068
+ if(slideIndex < 0){
1069
+ slider.active.index = getPagerQty() - 1;
1070
+ // if slideIndex is greater than children length, set active index to 0 (this happens during infinite loop)
1071
+ }else if(slideIndex >= getPagerQty()){
1072
+ slider.active.index = 0;
1073
+ // set active index to requested slide
1074
+ }else{
1075
+ slider.active.index = slideIndex;
1076
+ }
1077
+ // onSlideBefore, onSlideNext, onSlidePrev callbacks
1078
+ slider.settings.onSlideBefore(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
1079
+ if(direction == 'next'){
1080
+ slider.settings.onSlideNext(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
1081
+ }else if(direction == 'prev'){
1082
+ slider.settings.onSlidePrev(slider.children.eq(slider.active.index), slider.oldIndex, slider.active.index);
1083
+ }
1084
+ // check if last slide
1085
+ slider.active.last = slider.active.index >= getPagerQty() - 1;
1086
+ // update the pager with active class
1087
+ if(slider.settings.pager) updatePagerActive(slider.active.index);
1088
+ // // check for direction control update
1089
+ if(slider.settings.controls) updateDirectionControls();
1090
+ // if slider is set to mode: "fade"
1091
+ if(slider.settings.mode == 'fade'){
1092
+ // if adaptiveHeight is true and next height is different from current height, animate to the new height
1093
+ if(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()){
1094
+ slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed);
1095
+ }
1096
+ // fade out the visible child and reset its z-index value
1097
+ slider.children.filter(':visible').fadeOut(slider.settings.speed).css({zIndex: 0});
1098
+ // fade in the newly requested slide
1099
+ slider.children.eq(slider.active.index).css('zIndex', 51).fadeIn(slider.settings.speed, function(){
1100
+ $(this).css('zIndex', 50);
1101
+ updateAfterSlideTransition();
1102
+ });
1103
+ // slider mode is not "fade"
1104
+ }else{
1105
+ // if adaptiveHeight is true and next height is different from current height, animate to the new height
1106
+ if(slider.settings.adaptiveHeight && slider.viewport.height() != getViewportHeight()){
1107
+ slider.viewport.animate({height: getViewportHeight()}, slider.settings.adaptiveHeightSpeed);
1108
+ }
1109
+ var moveBy = 0;
1110
+ var position = {left: 0, top: 0};
1111
+ // if carousel and not infinite loop
1112
+ if(!slider.settings.infiniteLoop && slider.carousel && slider.active.last){
1113
+ if(slider.settings.mode == 'horizontal'){
1114
+ // get the last child position
1115
+ var lastChild = slider.children.eq(slider.children.length - 1);
1116
+ position = lastChild.position();
1117
+ // calculate the position of the last slide
1118
+ moveBy = slider.viewport.width() - lastChild.width();
1119
+ }else{
1120
+ // get last showing index position
1121
+ var lastShowingIndex = slider.children.length - slider.settings.minSlides;
1122
+ position = slider.children.eq(lastShowingIndex).position();
1123
+ }
1124
+ // horizontal carousel, going previous while on first slide (infiniteLoop mode)
1125
+ }else if(slider.carousel && slider.active.last && direction == 'prev'){
1126
+ // get the last child position
1127
+ var eq = slider.settings.moveSlides == 1 ? slider.settings.maxSlides - getMoveBy() : ((getPagerQty() - 1) * getMoveBy()) - (slider.children.length - slider.settings.maxSlides);
1128
+ var lastChild = el.children('.bx-clone').eq(eq);
1129
+ position = lastChild.position();
1130
+ // if infinite loop and "Next" is clicked on the last slide
1131
+ }else if(direction == 'next' && slider.active.index == 0){
1132
+ // get the last clone position
1133
+ position = el.find('.bx-clone').eq(slider.settings.maxSlides).position();
1134
+ slider.active.last = false;
1135
+ // normal non-zero requests
1136
+ }else if(slideIndex >= 0){
1137
+ var requestEl = slideIndex * getMoveBy();
1138
+ position = slider.children.eq(requestEl).position();
1139
+ }
1140
+ // plugin values to be animated
1141
+ var value = slider.settings.mode == 'horizontal' ? -(position.left - moveBy) : -position.top;
1142
+ setPositionProperty(value, 'slide', slider.settings.speed);
1143
+ }
1144
+ }
1145
+
1146
+ /**
1147
+ * Transitions to the next slide in the show
1148
+ */
1149
+ el.goToNextSlide = function(){
1150
+ // if infiniteLoop is false and last page is showing, disregard call
1151
+ if (!slider.settings.infiniteLoop && slider.active.last) return;
1152
+ var pagerIndex = parseInt(slider.active.index) + 1;
1153
+ el.goToSlide(pagerIndex, 'next');
1154
+ }
1155
+
1156
+ /**
1157
+ * Transitions to the prev slide in the show
1158
+ */
1159
+ el.goToPrevSlide = function(){
1160
+ // if infiniteLoop is false and last page is showing, disregard call
1161
+ if (!slider.settings.infiniteLoop && slider.active.index == 0) return;
1162
+ var pagerIndex = parseInt(slider.active.index) - 1;
1163
+ el.goToSlide(pagerIndex, 'prev');
1164
+ }
1165
+
1166
+ /**
1167
+ * Starts the auto show
1168
+ *
1169
+ * @param preventControlUpdate (boolean)
1170
+ * - if true, auto controls state will not be updated
1171
+ */
1172
+ el.startAuto = function(preventControlUpdate){
1173
+ // if an interval already exists, disregard call
1174
+ if(slider.interval) return;
1175
+ // create an interval
1176
+ slider.interval = setInterval(function(){
1177
+ slider.settings.autoDirection == 'next' ? el.goToNextSlide() : el.goToPrevSlide();
1178
+ }, slider.settings.pause);
1179
+ // if auto controls are displayed and preventControlUpdate is not true
1180
+ if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('stop');
1181
+ }
1182
+
1183
+ /**
1184
+ * Stops the auto show
1185
+ *
1186
+ * @param preventControlUpdate (boolean)
1187
+ * - if true, auto controls state will not be updated
1188
+ */
1189
+ el.stopAuto = function(preventControlUpdate){
1190
+ // if no interval exists, disregard call
1191
+ if(!slider.interval) return;
1192
+ // clear the interval
1193
+ clearInterval(slider.interval);
1194
+ slider.interval = null;
1195
+ // if auto controls are displayed and preventControlUpdate is not true
1196
+ if (slider.settings.autoControls && preventControlUpdate != true) updateAutoControls('start');
1197
+ }
1198
+
1199
+ /**
1200
+ * Returns current slide index (zero-based)
1201
+ */
1202
+ el.getCurrentSlide = function(){
1203
+ return slider.active.index;
1204
+ }
1205
+
1206
+ /**
1207
+ * Returns number of slides in show
1208
+ */
1209
+ el.getSlideCount = function(){
1210
+ return slider.children.length;
1211
+ }
1212
+
1213
+ /**
1214
+ * Update all dynamic slider elements
1215
+ */
1216
+ el.redrawSlider = function(){
1217
+ // resize all children in ratio to new screen size
1218
+ slider.children.add(el.find('.bx-clone')).width(getSlideWidth());
1219
+ // adjust the height
1220
+ slider.viewport.css('height', getViewportHeight());
1221
+ // update the slide position
1222
+ if(!slider.settings.ticker) setSlidePosition();
1223
+ // if active.last was true before the screen resize, we want
1224
+ // to keep it last no matter what screen size we end on
1225
+ if (slider.active.last) slider.active.index = getPagerQty() - 1;
1226
+ // if the active index (page) no longer exists due to the resize, simply set the index as last
1227
+ if (slider.active.index >= getPagerQty()) slider.active.last = true;
1228
+ // if a pager is being displayed and a custom pager is not being used, update it
1229
+ if(slider.settings.pager && !slider.settings.pagerCustom){
1230
+ populatePager();
1231
+ updatePagerActive(slider.active.index);
1232
+ }
1233
+ }
1234
+
1235
+ /**
1236
+ * Destroy the current instance of the slider (revert everything back to original state)
1237
+ */
1238
+ el.destroySlider = function(){
1239
+ // don't do anything if slider has already been destroyed
1240
+ if(!slider.initialized) return;
1241
+ slider.initialized = false;
1242
+ $('.bx-clone', this).remove();
1243
+ slider.children.removeAttr('style');
1244
+ this.removeAttr('style').unwrap().unwrap();
1245
+ if(slider.controls.el) slider.controls.el.remove();
1246
+ if(slider.controls.next) slider.controls.next.remove();
1247
+ if(slider.controls.prev) slider.controls.prev.remove();
1248
+ if(slider.pagerEl) slider.pagerEl.remove();
1249
+ $('.bx-caption', this).remove();
1250
+ if(slider.controls.autoEl) slider.controls.autoEl.remove();
1251
+ clearInterval(slider.interval);
1252
+ $(window).unbind('resize', resizeWindow);
1253
+ }
1254
+
1255
+ /**
1256
+ * Reload the slider (revert all DOM changes, and re-initialize)
1257
+ */
1258
+ el.reloadSlider = function(settings){
1259
+ if (settings != undefined) options = settings;
1260
+ el.destroySlider();
1261
+ init();
1262
+ }
1263
+
1264
+ init();
1265
+
1266
+ // returns the current jQuery object
1267
+ return this;
1268
+ }
1269
+
1270
+ })(jQuery);
1271
+
1272
+ /*!
1273
+ * jQuery imagesLoaded plugin v2.1.0
1274
+ * http://github.com/desandro/imagesloaded
1275
+ *
1276
+ * MIT License. by Paul Irish et al.
1277
+ */
1278
+
1279
+ /*jshint curly: true, eqeqeq: true, noempty: true, strict: true, undef: true, browser: true */
1280
+ /*global jQuery: false */
1281
+
1282
+ (function(c,n){var l="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";c.fn.imagesLoaded=function(f){function m(){var b=c(i),a=c(h);d&&(h.length?d.reject(e,b,a):d.resolve(e));c.isFunction(f)&&f.call(g,e,b,a)}function j(b,a){b.src===l||-1!==c.inArray(b,k)||(k.push(b),a?h.push(b):i.push(b),c.data(b,"imagesLoaded",{isBroken:a,src:b.src}),o&&d.notifyWith(c(b),[a,e,c(i),c(h)]),e.length===k.length&&(setTimeout(m),e.unbind(".imagesLoaded")))}var g=this,d=c.isFunction(c.Deferred)?c.Deferred():
1283
+ 0,o=c.isFunction(d.notify),e=g.find("img").add(g.filter("img")),k=[],i=[],h=[];c.isPlainObject(f)&&c.each(f,function(b,a){if("callback"===b)f=a;else if(d)d[b](a)});e.length?e.bind("load.imagesLoaded error.imagesLoaded",function(b){j(b.target,"error"===b.type)}).each(function(b,a){var d=a.src,e=c.data(a,"imagesLoaded");if(e&&e.src===d)j(a,e.isBroken);else if(a.complete&&a.naturalWidth!==n)j(a,0===a.naturalWidth||0===a.naturalHeight);else if(a.readyState||a.complete)a.src=l,a.src=d}):m();return d?d.promise(g):
1284
+ g}})(jQuery);