spree_multi_slideshow 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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);