jquery-unslider-rails 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +19 -0
- data/README.md +16 -0
- data/lib/jquery-unslider-rails.rb +8 -0
- data/lib/jquery-unslider-rails/version.rb +5 -0
- data/vendor/assets/javascripts/jquery-unslider.js +651 -0
- data/vendor/assets/javascripts/jquery-unslider.min.js +1 -0
- metadata +52 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a70b38df6accd06831f86e04323ef4769d0974ad
|
4
|
+
data.tar.gz: 96fe4c2da750b90fb50cd515937d9be63ae5c2f3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1fbaa393e7e173a472308373e553ed9d8fa70c7ed1d2e80da86643c57b04b7b02f02a54cfd349ea5f41466f226dfc9b290128244f51774ac707802d0a5edf5e9
|
7
|
+
data.tar.gz: f912f537d24df7f262c3a13b590756be84417f868955b9cdade67b11822109db64cccb69ecbce88a2eacb9e1919aae612d9515ad593c43c2f14280db96715f0e
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# jquery-unslider-rails
|
2
|
+
|
3
|
+
[jQuery Unslider](https://github.com/idiot/unslider) plugin for jQuery, written by [Visual Idiot](https://github.com/idiot), packaged for the Rails asset pipeline.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
This gem ships with with a minified version of the library. Feel free to use either of the following:
|
8
|
+
|
9
|
+
```
|
10
|
+
//= require jquery-unslider
|
11
|
+
//= require jquery-unslider.min
|
12
|
+
```
|
13
|
+
|
14
|
+
## Disclaimer
|
15
|
+
|
16
|
+
This repo is a Rails gem package. All issues with the library should be reported on the library's [GitHub page](https://github.com/idiot/unslider). This repo will be updated each time a new version of the library is released.
|
@@ -0,0 +1,651 @@
|
|
1
|
+
/**
|
2
|
+
* Unslider
|
3
|
+
* version 2.0
|
4
|
+
* by @idiot and friends
|
5
|
+
*/
|
6
|
+
|
7
|
+
(function(factory) {
|
8
|
+
if (typeof module === 'object' && typeof module.exports === 'object') {
|
9
|
+
factory(require('jquery'));
|
10
|
+
} else if (typeof define === 'function' && define.amd) {
|
11
|
+
// AMD. Register as an anonymous module.
|
12
|
+
define([], factory(window.jQuery));
|
13
|
+
} else {
|
14
|
+
factory(window.jQuery);
|
15
|
+
}
|
16
|
+
}(function($) {
|
17
|
+
// Don't throw any errors when jQuery
|
18
|
+
if(!$) {
|
19
|
+
return console.warn('Unslider needs jQuery');
|
20
|
+
}
|
21
|
+
|
22
|
+
$.Unslider = function(context, options) {
|
23
|
+
var self = this;
|
24
|
+
|
25
|
+
// Create an Unslider reference we can use everywhere
|
26
|
+
self._ = 'unslider';
|
27
|
+
|
28
|
+
// Store our default options in here
|
29
|
+
// Everything will be overwritten by the jQuery plugin though
|
30
|
+
self.defaults = {
|
31
|
+
// Should the slider move on its own or only when
|
32
|
+
// you interact with the nav/arrows?
|
33
|
+
// Only accepts boolean true/false.
|
34
|
+
autoplay: false,
|
35
|
+
|
36
|
+
// 3 second delay between slides moving, pass
|
37
|
+
// as a number in milliseconds.
|
38
|
+
delay: 3000,
|
39
|
+
|
40
|
+
// Animation speed in millseconds
|
41
|
+
speed: 750,
|
42
|
+
|
43
|
+
// An easing string to use. If you're using Velocity, use a
|
44
|
+
// Velocity string otherwise you can use jQuery/jQ UI options.
|
45
|
+
easing: 'swing', // [.42, 0, .58, 1],
|
46
|
+
|
47
|
+
// Does it support keyboard arrows?
|
48
|
+
// Can pass either true or false -
|
49
|
+
// or an object with the keycodes, like so:
|
50
|
+
// {
|
51
|
+
// prev: 37,
|
52
|
+
// next: 39
|
53
|
+
// }
|
54
|
+
// You can call any internal method name
|
55
|
+
// before the keycode and it'll be called.
|
56
|
+
keys: {
|
57
|
+
prev: 37,
|
58
|
+
next: 39
|
59
|
+
},
|
60
|
+
|
61
|
+
// Do you want to generate clickable navigation
|
62
|
+
// to skip to each slide? Accepts boolean true/false or
|
63
|
+
// a callback function per item to generate.
|
64
|
+
nav: true,
|
65
|
+
|
66
|
+
// Should there be left/right arrows to go back/forth?
|
67
|
+
// -> This isn't keyboard support.
|
68
|
+
// Either set true/false, or an object with the HTML
|
69
|
+
// elements for each arrow like below:
|
70
|
+
arrows: {
|
71
|
+
prev: '<a class="' + self._ + '-arrow prev">Prev</a>',
|
72
|
+
next: '<a class="' + self._ + '-arrow next">Next</a>'
|
73
|
+
},
|
74
|
+
|
75
|
+
// How should Unslider animate?
|
76
|
+
// It can do one of the following types:
|
77
|
+
// "fade": each slide fades in to each other
|
78
|
+
// "horizontal": each slide moves from left to right
|
79
|
+
// "vertical": each slide moves from top to bottom
|
80
|
+
animation: 'horizontal',
|
81
|
+
|
82
|
+
// If you don't want to use a list to display your slides,
|
83
|
+
// you can change it here. Not recommended and you'll need
|
84
|
+
// to adjust the CSS accordingly.
|
85
|
+
selectors: {
|
86
|
+
container: 'ul:first',
|
87
|
+
slides: 'li'
|
88
|
+
},
|
89
|
+
|
90
|
+
// Do you want to animate the heights of each slide as
|
91
|
+
// it moves
|
92
|
+
animateHeight: false,
|
93
|
+
|
94
|
+
// Active class for the nav
|
95
|
+
activeClass: self._ + '-active',
|
96
|
+
|
97
|
+
// Have swipe support?
|
98
|
+
// You can set this here with a boolean and always use
|
99
|
+
// initSwipe/destroySwipe later on.
|
100
|
+
swipe: true,
|
101
|
+
// Swipe threshold -
|
102
|
+
// lower float for enabling short swipe
|
103
|
+
swipeThreshold: 0.2
|
104
|
+
};
|
105
|
+
|
106
|
+
// Set defaults
|
107
|
+
self.$context = context;
|
108
|
+
self.options = {};
|
109
|
+
|
110
|
+
// Leave our elements blank for now
|
111
|
+
// Since they get changed by the options, we'll need to
|
112
|
+
// set them in the init method.
|
113
|
+
self.$parent = null;
|
114
|
+
self.$container = null;
|
115
|
+
self.$slides = null;
|
116
|
+
self.$nav = null;
|
117
|
+
self.$arrows = [];
|
118
|
+
|
119
|
+
// Set our indexes and totals
|
120
|
+
self.total = 0;
|
121
|
+
self.current = 0;
|
122
|
+
|
123
|
+
// Generate a specific random ID so we don't dupe events
|
124
|
+
self.prefix = self._ + '-';
|
125
|
+
self.eventSuffix = '.' + self.prefix + ~~(Math.random() * 2e3);
|
126
|
+
|
127
|
+
// In case we're going to use the autoplay
|
128
|
+
self.interval = null;
|
129
|
+
|
130
|
+
// Get everything set up innit
|
131
|
+
self.init = function(options) {
|
132
|
+
// Set up our options inside here so we can re-init at
|
133
|
+
// any time
|
134
|
+
self.options = $.extend({}, self.defaults, options);
|
135
|
+
|
136
|
+
// Our elements
|
137
|
+
self.$container = self.$context.find(self.options.selectors.container).addClass(self.prefix + 'wrap');
|
138
|
+
self.$slides = self.$container.children(self.options.selectors.slides);
|
139
|
+
|
140
|
+
// We'll manually init the container
|
141
|
+
self.setup();
|
142
|
+
|
143
|
+
// We want to keep this script as small as possible
|
144
|
+
// so we'll optimise some checks
|
145
|
+
$.each(['nav', 'arrows', 'keys', 'infinite'], function(index, module) {
|
146
|
+
self.options[module] && self['init' + $._ucfirst(module)]();
|
147
|
+
});
|
148
|
+
|
149
|
+
// Add swipe support
|
150
|
+
if(jQuery.event.special.swipe && self.options.swipe) {
|
151
|
+
self.initSwipe();
|
152
|
+
}
|
153
|
+
|
154
|
+
// If autoplay is set to true, call self.start()
|
155
|
+
// to start calling our timeouts
|
156
|
+
self.options.autoplay && self.start();
|
157
|
+
|
158
|
+
// We should be able to recalculate slides at will
|
159
|
+
self.calculateSlides();
|
160
|
+
|
161
|
+
// Listen to a ready event
|
162
|
+
self.$context.trigger(self._ + '.ready');
|
163
|
+
|
164
|
+
// Everyday I'm chainin'
|
165
|
+
return self.animate(self.options.index || self.current, 'init');
|
166
|
+
};
|
167
|
+
|
168
|
+
self.setup = function() {
|
169
|
+
// Add a CSS hook to the main element
|
170
|
+
self.$context.addClass(self.prefix + self.options.animation).wrap('<div class="' + self._ + '" />');
|
171
|
+
self.$parent = self.$context.parent('.' + self._);
|
172
|
+
|
173
|
+
// We need to manually check if the container is absolutely
|
174
|
+
// or relatively positioned
|
175
|
+
var position = self.$context.css('position');
|
176
|
+
|
177
|
+
// If we don't already have a position set, we'll
|
178
|
+
// automatically set it ourselves
|
179
|
+
if(position === 'static') {
|
180
|
+
self.$context.css('position', 'relative');
|
181
|
+
}
|
182
|
+
|
183
|
+
self.$context.css('overflow', 'hidden');
|
184
|
+
};
|
185
|
+
|
186
|
+
// Set up the slide widths to animate with
|
187
|
+
// so the box doesn't float over
|
188
|
+
self.calculateSlides = function() {
|
189
|
+
// update slides before recalculating the total
|
190
|
+
self.$slides = self.$container.children(self.options.selectors.slides);
|
191
|
+
|
192
|
+
self.total = self.$slides.length;
|
193
|
+
|
194
|
+
// Set the total width
|
195
|
+
if(self.options.animation !== 'fade') {
|
196
|
+
var prop = 'width';
|
197
|
+
|
198
|
+
if(self.options.animation === 'vertical') {
|
199
|
+
prop = 'height';
|
200
|
+
}
|
201
|
+
|
202
|
+
self.$container.css(prop, (self.total * 100) + '%').addClass(self.prefix + 'carousel');
|
203
|
+
self.$slides.css(prop, (100 / self.total) + '%');
|
204
|
+
}
|
205
|
+
};
|
206
|
+
|
207
|
+
|
208
|
+
// Start our autoplay
|
209
|
+
self.start = function() {
|
210
|
+
self.interval = setTimeout(function() {
|
211
|
+
// Move on to the next slide
|
212
|
+
self.next();
|
213
|
+
|
214
|
+
// If we've got autoplay set up
|
215
|
+
// we don't need to keep starting
|
216
|
+
// the slider from within our timeout
|
217
|
+
// as .animate() calls it for us
|
218
|
+
}, self.options.delay);
|
219
|
+
|
220
|
+
return self;
|
221
|
+
};
|
222
|
+
|
223
|
+
// And pause our timeouts
|
224
|
+
// and force stop the slider if needed
|
225
|
+
self.stop = function() {
|
226
|
+
clearTimeout(self.interval);
|
227
|
+
|
228
|
+
return self;
|
229
|
+
};
|
230
|
+
|
231
|
+
|
232
|
+
// Set up our navigation
|
233
|
+
self.initNav = function() {
|
234
|
+
var $nav = $('<nav class="' + self.prefix + 'nav"><ol /></nav>');
|
235
|
+
|
236
|
+
// Build our click navigation item-by-item
|
237
|
+
self.$slides.each(function(key) {
|
238
|
+
// If we've already set a label, let's use that
|
239
|
+
// instead of generating one
|
240
|
+
var label = this.getAttribute('data-nav') || key + 1;
|
241
|
+
|
242
|
+
// Listen to any callback functions
|
243
|
+
if($.isFunction(self.options.nav)) {
|
244
|
+
label = self.options.nav.call(self.$slides.eq(key), key, label);
|
245
|
+
}
|
246
|
+
|
247
|
+
// And add it to our navigation item
|
248
|
+
$nav.children('ol').append('<li data-slide="' + key + '">' + label + '</li>');
|
249
|
+
});
|
250
|
+
|
251
|
+
// Keep a copy of the nav everywhere so we can use it
|
252
|
+
self.$nav = $nav.insertAfter(self.$context);
|
253
|
+
|
254
|
+
// Now our nav is built, let's add it to the slider and bind
|
255
|
+
// for any click events on the generated links
|
256
|
+
self.$nav.find('li').on('click' + self.eventSuffix, function() {
|
257
|
+
// Cache our link and set it to be active
|
258
|
+
var $me = $(this).addClass(self.options.activeClass);
|
259
|
+
|
260
|
+
// Set the right active class, remove any other ones
|
261
|
+
$me.siblings().removeClass(self.options.activeClass);
|
262
|
+
|
263
|
+
// Move the slide
|
264
|
+
self.animate($me.attr('data-slide'));
|
265
|
+
});
|
266
|
+
};
|
267
|
+
|
268
|
+
|
269
|
+
// Set up our left-right arrow navigation
|
270
|
+
// (Not keyboard arrows, prev/next buttons)
|
271
|
+
self.initArrows = function() {
|
272
|
+
if(self.options.arrows === true) {
|
273
|
+
self.options.arrows = self.defaults.arrows;
|
274
|
+
}
|
275
|
+
|
276
|
+
// Loop our options object and bind our events
|
277
|
+
$.each(self.options.arrows, function(key, val) {
|
278
|
+
// Add our arrow HTML and bind it
|
279
|
+
self.$arrows.push(
|
280
|
+
$(val).insertAfter(self.$context).on('click' + self.eventSuffix, self[key])
|
281
|
+
);
|
282
|
+
});
|
283
|
+
};
|
284
|
+
|
285
|
+
|
286
|
+
// Set up our keyboad navigation
|
287
|
+
// Allow binding to multiple keycodes
|
288
|
+
self.initKeys = function() {
|
289
|
+
if(self.options.keys === true) {
|
290
|
+
self.options.keys = self.defaults.keys;
|
291
|
+
}
|
292
|
+
|
293
|
+
$(document).on('keyup' + self.eventSuffix, function(e) {
|
294
|
+
$.each(self.options.keys, function(key, val) {
|
295
|
+
if(e.which === val) {
|
296
|
+
$.isFunction(self[key]) && self[key].call(self);
|
297
|
+
}
|
298
|
+
});
|
299
|
+
});
|
300
|
+
};
|
301
|
+
|
302
|
+
// Requires jQuery.event.swipe
|
303
|
+
// -> stephband.info/jquery.event.swipe
|
304
|
+
self.initSwipe = function() {
|
305
|
+
var width = self.$slides.width();
|
306
|
+
|
307
|
+
// We don't want to have a tactile swipe in the slider
|
308
|
+
// in the fade animation, as it can cause some problems
|
309
|
+
// with layout, so we'll just disable it.
|
310
|
+
if(self.options.animation !== 'fade') {
|
311
|
+
|
312
|
+
self.$container.on({
|
313
|
+
|
314
|
+
movestart: function(e) {
|
315
|
+
// If the movestart heads off in a upwards or downwards
|
316
|
+
// direction, prevent it so that the browser scrolls normally.
|
317
|
+
if((e.distX > e.distY && e.distX < -e.distY) || (e.distX < e.distY && e.distX > -e.distY)) {
|
318
|
+
return !!e.preventDefault();
|
319
|
+
}
|
320
|
+
|
321
|
+
self.$container.css('position', 'relative');
|
322
|
+
},
|
323
|
+
|
324
|
+
move: function(e) {
|
325
|
+
self.$container.css('left', -(100 * self.current) + (100 * e.distX / width) + '%');
|
326
|
+
},
|
327
|
+
|
328
|
+
moveend: function(e) {
|
329
|
+
// Check if swiped distance is greater than threshold.
|
330
|
+
// If yes slide to next/prev slide. If not animate to
|
331
|
+
// starting point.
|
332
|
+
|
333
|
+
if((Math.abs(e.distX) / width) > self.options.swipeThreshold) {
|
334
|
+
|
335
|
+
self[e.distX < 0 ? 'next' : 'prev']();
|
336
|
+
}
|
337
|
+
else {
|
338
|
+
|
339
|
+
self.$container.animate({left: -(100 * self.current) + '%' }, self.options.speed / 2 );
|
340
|
+
}
|
341
|
+
}
|
342
|
+
});
|
343
|
+
}
|
344
|
+
};
|
345
|
+
|
346
|
+
// Infinite scrolling is a massive pain in the arse
|
347
|
+
// so we need to create a whole bloody function to set
|
348
|
+
// it up. Argh.
|
349
|
+
self.initInfinite = function() {
|
350
|
+
var pos = ['first', 'last'];
|
351
|
+
|
352
|
+
$.each(pos, function(index, item) {
|
353
|
+
self.$slides.push.apply(
|
354
|
+
self.$slides,
|
355
|
+
|
356
|
+
// Exclude all cloned slides and call .first() or .last()
|
357
|
+
// depending on what `item` is.
|
358
|
+
self.$slides.filter(':not(".' + self._ + '-clone")')[item]()
|
359
|
+
|
360
|
+
// Make a copy of it and identify it as a clone
|
361
|
+
.clone().addClass(self._ + '-clone')
|
362
|
+
|
363
|
+
// Either insert before or after depending on whether we're
|
364
|
+
// the first or last clone
|
365
|
+
['insert' + (index === 0 ? 'After' : 'Before')](
|
366
|
+
// Return the other element in the position array
|
367
|
+
// if item = first, return "last"
|
368
|
+
self.$slides[pos[~~!index]]()
|
369
|
+
)
|
370
|
+
);
|
371
|
+
});
|
372
|
+
};
|
373
|
+
|
374
|
+
// Remove any trace of arrows
|
375
|
+
// Loop our array of arrows and use jQuery to remove
|
376
|
+
// It'll unbind any event handlers for us
|
377
|
+
self.destroyArrows = function() {
|
378
|
+
$.each(self.$arrows, function(i, $arrow) {
|
379
|
+
$arrow.remove();
|
380
|
+
});
|
381
|
+
};
|
382
|
+
|
383
|
+
// Remove any swipe events and reset the position
|
384
|
+
self.destroySwipe = function() {
|
385
|
+
// We bind to 4 events, so we'll unbind those
|
386
|
+
self.$container.off('movestart move moveend');
|
387
|
+
};
|
388
|
+
|
389
|
+
// Unset the keyboard navigation
|
390
|
+
// Remove the handler
|
391
|
+
self.destroyKeys = function() {
|
392
|
+
// Remove the event handler
|
393
|
+
$(document).off('keyup' + self.eventSuffix);
|
394
|
+
};
|
395
|
+
|
396
|
+
self.setIndex = function(to) {
|
397
|
+
if(to < 0) {
|
398
|
+
to = self.total - 1;
|
399
|
+
}
|
400
|
+
|
401
|
+
self.current = Math.min(Math.max(0, to), self.total - 1);
|
402
|
+
|
403
|
+
if(self.options.nav) {
|
404
|
+
self.$nav.find('[data-slide="' + self.current + '"]')._active(self.options.activeClass);
|
405
|
+
}
|
406
|
+
|
407
|
+
self.$slides.eq(self.current)._active(self.options.activeClass);
|
408
|
+
|
409
|
+
return self;
|
410
|
+
};
|
411
|
+
|
412
|
+
// Despite the name, this doesn't do any animation - since there's
|
413
|
+
// now three different types of animation, we let this method delegate
|
414
|
+
// to the right type, keeping the name for backwards compat.
|
415
|
+
self.animate = function(to, dir) {
|
416
|
+
// Animation shortcuts
|
417
|
+
// Instead of passing a number index, we can now
|
418
|
+
// use .data('unslider').animate('last');
|
419
|
+
// or .unslider('animate:last')
|
420
|
+
// to go to the very last slide
|
421
|
+
if(to === 'first') to = 0;
|
422
|
+
if(to === 'last') to = self.total;
|
423
|
+
|
424
|
+
// Don't animate if it's not a valid index
|
425
|
+
if(isNaN(to)) {
|
426
|
+
return self;
|
427
|
+
}
|
428
|
+
|
429
|
+
if(self.options.autoplay) {
|
430
|
+
self.stop().start();
|
431
|
+
}
|
432
|
+
|
433
|
+
self.setIndex(to);
|
434
|
+
|
435
|
+
// Add a callback method to do stuff with
|
436
|
+
self.$context.trigger(self._ + '.change', [to, self.$slides.eq(to)]);
|
437
|
+
|
438
|
+
// Delegate the right method - everything's named consistently
|
439
|
+
// so we can assume it'll be called "animate" +
|
440
|
+
var fn = 'animate' + $._ucfirst(self.options.animation);
|
441
|
+
|
442
|
+
// Make sure it's a valid animation method, otherwise we'll get
|
443
|
+
// a load of bug reports that'll be really hard to report
|
444
|
+
if($.isFunction(self[fn])) {
|
445
|
+
self[fn](self.current, dir);
|
446
|
+
}
|
447
|
+
|
448
|
+
return self;
|
449
|
+
};
|
450
|
+
|
451
|
+
|
452
|
+
// Shortcuts for animating if we don't know what the current
|
453
|
+
// index is (i.e back/forward)
|
454
|
+
// For moving forward we need to make sure we don't overshoot.
|
455
|
+
self.next = function() {
|
456
|
+
var target = self.current + 1;
|
457
|
+
|
458
|
+
// If we're at the end, we need to move back to the start
|
459
|
+
if(target >= self.total) {
|
460
|
+
target = 0;
|
461
|
+
}
|
462
|
+
|
463
|
+
return self.animate(target, 'next');
|
464
|
+
};
|
465
|
+
|
466
|
+
// Previous is a bit simpler, we can just decrease the index
|
467
|
+
// by one and check if it's over 0.
|
468
|
+
self.prev = function() {
|
469
|
+
return self.animate(self.current - 1, 'prev');
|
470
|
+
};
|
471
|
+
|
472
|
+
|
473
|
+
// Our default animation method, the old-school left-to-right
|
474
|
+
// horizontal animation
|
475
|
+
self.animateHorizontal = function(to) {
|
476
|
+
var prop = 'left';
|
477
|
+
|
478
|
+
// Add RTL support, slide the slider
|
479
|
+
// the other way if the site is right-to-left
|
480
|
+
if(self.$context.attr('dir') === 'rtl') {
|
481
|
+
prop = 'right';
|
482
|
+
}
|
483
|
+
|
484
|
+
if(self.options.infinite) {
|
485
|
+
// So then we need to hide the first slide
|
486
|
+
self.$container.css('margin-' + prop, '-100%');
|
487
|
+
}
|
488
|
+
|
489
|
+
return self.slide(prop, to);
|
490
|
+
};
|
491
|
+
|
492
|
+
// The same animation methods, but vertical support
|
493
|
+
// RTL doesn't affect the vertical direction so we
|
494
|
+
// can just call as is
|
495
|
+
self.animateVertical = function(to) {
|
496
|
+
self.options.animateHeight = true;
|
497
|
+
|
498
|
+
// Normal infinite CSS fix doesn't work for
|
499
|
+
// vertical animation so we need to manually set it
|
500
|
+
// with pixels. Ah well.
|
501
|
+
if(self.options.infinite) {
|
502
|
+
self.$container.css('margin-top', -self.$slides.outerHeight());
|
503
|
+
}
|
504
|
+
|
505
|
+
return self.slide('top', to);
|
506
|
+
};
|
507
|
+
|
508
|
+
// Actually move the slide now
|
509
|
+
// We have to pass a property to animate as there's
|
510
|
+
// a few different directions it can now move, but it's
|
511
|
+
// otherwise unchanged from before.
|
512
|
+
self.slide = function(prop, to) {
|
513
|
+
// If we want to change the height of the slider
|
514
|
+
// to match the current slide, you can set
|
515
|
+
// {animateHeight: true}
|
516
|
+
self.animateHeight(to);
|
517
|
+
|
518
|
+
// For infinite sliding we add a dummy slide at the end and start
|
519
|
+
// of each slider to give the appearance of being infinite
|
520
|
+
if(self.options.infinite) {
|
521
|
+
var dummy;
|
522
|
+
|
523
|
+
// Going backwards to last slide
|
524
|
+
if(to === self.total - 1) {
|
525
|
+
// We're setting a dummy position and an actual one
|
526
|
+
// the dummy is what the index looks like
|
527
|
+
// (and what we'll silently update to afterwards),
|
528
|
+
// and the actual is what makes it not go backwards
|
529
|
+
dummy = self.total - 3;
|
530
|
+
to = -1;
|
531
|
+
}
|
532
|
+
|
533
|
+
// Going forwards to first slide
|
534
|
+
if(to === self.total - 2) {
|
535
|
+
dummy = 0;
|
536
|
+
to = self.total - 2;
|
537
|
+
}
|
538
|
+
|
539
|
+
// If it's a number we can safely set it
|
540
|
+
if(typeof dummy === 'number') {
|
541
|
+
self.setIndex(dummy);
|
542
|
+
|
543
|
+
// Listen for when the slide's finished transitioning so
|
544
|
+
// we can silently move it into the right place and clear
|
545
|
+
// this whole mess up.
|
546
|
+
self.$context.on(self._ + '.moved', function() {
|
547
|
+
if(self.current === dummy) {
|
548
|
+
self.$container.css(prop, -(100 * dummy) + '%').off(self._ + '.moved');
|
549
|
+
}
|
550
|
+
});
|
551
|
+
}
|
552
|
+
}
|
553
|
+
|
554
|
+
// We need to create an object to store our property in
|
555
|
+
// since we don't know what it'll be.
|
556
|
+
var obj = {};
|
557
|
+
|
558
|
+
// Manually create it here
|
559
|
+
obj[prop] = -(100 * to) + '%';
|
560
|
+
|
561
|
+
// And animate using our newly-created object
|
562
|
+
return self._move(self.$container, obj);
|
563
|
+
};
|
564
|
+
|
565
|
+
|
566
|
+
// Fade between slides rather than, uh, sliding it
|
567
|
+
self.animateFade = function(to) {
|
568
|
+
// If we want to change the height of the slider
|
569
|
+
// to match the current slide, you can set
|
570
|
+
// {animateHeight: true}
|
571
|
+
self.animateHeight(to);
|
572
|
+
|
573
|
+
var $active = self.$slides.eq(to).addClass(self.options.activeClass);
|
574
|
+
|
575
|
+
// Toggle our classes
|
576
|
+
self._move($active.siblings().removeClass(self.options.activeClass), {opacity: 0});
|
577
|
+
self._move($active, {opacity: 1}, false);
|
578
|
+
};
|
579
|
+
|
580
|
+
// Animate height of slider
|
581
|
+
self.animateHeight = function(to) {
|
582
|
+
// If we want to change the height of the slider
|
583
|
+
// to match the current slide, you can set
|
584
|
+
// {animateHeight: true}
|
585
|
+
if (self.options.animateHeight) {
|
586
|
+
self._move(self.$context, {height: self.$slides.eq(to).outerHeight()}, false);
|
587
|
+
}
|
588
|
+
};
|
589
|
+
|
590
|
+
self._move = function($el, obj, callback, speed) {
|
591
|
+
if(callback !== false) {
|
592
|
+
callback = function() {
|
593
|
+
self.$context.trigger(self._ + '.moved');
|
594
|
+
};
|
595
|
+
}
|
596
|
+
|
597
|
+
return $el._move(obj, speed || self.options.speed, self.options.easing, callback);
|
598
|
+
};
|
599
|
+
|
600
|
+
// Allow daisy-chaining of methods
|
601
|
+
return self.init(options);
|
602
|
+
};
|
603
|
+
|
604
|
+
// Internal (but global) jQuery methods
|
605
|
+
// They're both just helpful types of shorthand for
|
606
|
+
// anything that might take too long to write out or
|
607
|
+
// something that might be used more than once.
|
608
|
+
$.fn._active = function(className) {
|
609
|
+
return this.addClass(className).siblings().removeClass(className);
|
610
|
+
};
|
611
|
+
|
612
|
+
// The equivalent to PHP's ucfirst(). Take the first
|
613
|
+
// character of a string and make it uppercase.
|
614
|
+
// Simples.
|
615
|
+
$._ucfirst = function(str) {
|
616
|
+
// Take our variable, run a regex on the first letter
|
617
|
+
return (str + '').toLowerCase().replace(/^./, function(match) {
|
618
|
+
// And uppercase it. Simples.
|
619
|
+
return match.toUpperCase();
|
620
|
+
});
|
621
|
+
};
|
622
|
+
|
623
|
+
$.fn._move = function() {
|
624
|
+
this.stop(true, true);
|
625
|
+
return $.fn[$.fn.velocity ? 'velocity' : 'animate'].apply(this, arguments);
|
626
|
+
};
|
627
|
+
|
628
|
+
// And set up our jQuery plugin
|
629
|
+
$.fn.unslider = function(opts) {
|
630
|
+
return this.each(function() {
|
631
|
+
var $this = $(this);
|
632
|
+
|
633
|
+
// Allow usage of .unslider('function_name')
|
634
|
+
// as well as using .data('unslider') to access the
|
635
|
+
// main Unslider object
|
636
|
+
if(typeof opts === 'string' && $this.data('unslider')) {
|
637
|
+
opts = opts.split(':');
|
638
|
+
|
639
|
+
var call = $this.data('unslider')[opts[0]];
|
640
|
+
|
641
|
+
// Do we have arguments to pass to the string-function?
|
642
|
+
if($.isFunction(call)) {
|
643
|
+
return call.apply($this, opts[1] ? opts[1].split(',') : null);
|
644
|
+
}
|
645
|
+
}
|
646
|
+
|
647
|
+
return $this.data('unslider', new $.Unslider($this, opts));
|
648
|
+
});
|
649
|
+
};
|
650
|
+
|
651
|
+
}));
|
@@ -0,0 +1 @@
|
|
1
|
+
!function($){return $?($.Unslider=function(t,n){var e=this;return e._="unslider",e.defaults={autoplay:!1,delay:3e3,speed:750,easing:"swing",keys:{prev:37,next:39},nav:!0,arrows:{prev:'<a class="'+e._+'-arrow prev">Prev</a>',next:'<a class="'+e._+'-arrow next">Next</a>'},animation:"horizontal",selectors:{container:"ul:first",slides:"li"},animateHeight:!1,activeClass:e._+"-active",swipe:!0,swipeThreshold:.2},e.$context=t,e.options={},e.$parent=null,e.$container=null,e.$slides=null,e.$nav=null,e.$arrows=[],e.total=0,e.current=0,e.prefix=e._+"-",e.eventSuffix="."+e.prefix+~~(2e3*Math.random()),e.interval=null,e.init=function(t){return e.options=$.extend({},e.defaults,t),e.$container=e.$context.find(e.options.selectors.container).addClass(e.prefix+"wrap"),e.$slides=e.$container.children(e.options.selectors.slides),e.setup(),$.each(["nav","arrows","keys","infinite"],function(t,n){e.options[n]&&e["init"+$._ucfirst(n)]()}),jQuery.event.special.swipe&&e.options.swipe&&e.initSwipe(),e.options.autoplay&&e.start(),e.calculateSlides(),e.$context.trigger(e._+".ready"),e.animate(e.options.index||e.current,"init")},e.setup=function(){e.$context.addClass(e.prefix+e.options.animation).wrap('<div class="'+e._+'" />'),e.$parent=e.$context.parent("."+e._);var t=e.$context.css("position");"static"===t&&e.$context.css("position","relative"),e.$context.css("overflow","hidden")},e.calculateSlides=function(){if(e.total=e.$slides.length,"fade"!==e.options.animation){var t="width";"vertical"===e.options.animation&&(t="height"),e.$container.css(t,100*e.total+"%").addClass(e.prefix+"carousel"),e.$slides.css(t,100/e.total+"%")}},e.start=function(){return e.interval=setTimeout(function(){e.next()},e.options.delay),e},e.stop=function(){return clearTimeout(e.interval),e},e.initNav=function(){var t=$('<nav class="'+e.prefix+'nav"><ol /></nav>');e.$slides.each(function(n){var i=this.getAttribute("data-nav")||n+1;$.isFunction(e.options.nav)&&(i=e.options.nav.call(e.$slides.eq(n),n,i)),t.children("ol").append('<li data-slide="'+n+'">'+i+"</li>")}),e.$nav=t.insertAfter(e.$context),e.$nav.find("li").on("click"+e.eventSuffix,function(){var t=$(this).addClass(e.options.activeClass);t.siblings().removeClass(e.options.activeClass),e.animate(t.attr("data-slide"))})},e.initArrows=function(){e.options.arrows===!0&&(e.options.arrows=e.defaults.arrows),$.each(e.options.arrows,function(t,n){e.$arrows.push($(n).insertAfter(e.$context).on("click"+e.eventSuffix,e[t]))})},e.initKeys=function(){e.options.keys===!0&&(e.options.keys=e.defaults.keys),$(document).on("keyup"+e.eventSuffix,function(t){$.each(e.options.keys,function(n,i){t.which===i&&$.isFunction(e[n])&&e[n].call(e)})})},e.initSwipe=function(){var t=e.$slides.width();"fade"!==e.options.animation&&e.$container.on({movestart:function(t){return t.distX>t.distY&&t.distX<-t.distY||t.distX<t.distY&&t.distX>-t.distY?!!t.preventDefault():void e.$container.css("position","relative")},move:function(n){e.$container.css("left",-(100*e.current)+100*n.distX/t+"%")},moveend:function(n){Math.abs(n.distX)/t>e.options.swipeThreshold?e[n.distX<0?"next":"prev"]():e.$container.animate({left:-(100*e.current)+"%"},e.options.speed/2)}})},e.initInfinite=function(){var t=["first","last"];$.each(t,function(n,i){e.$slides.push.apply(e.$slides,e.$slides.filter(':not(".'+e._+'-clone")')[i]().clone().addClass(e._+"-clone")["insert"+(0===n?"After":"Before")](e.$slides[t[~~!n]]()))})},e.destroyArrows=function(){$.each(e.$arrows,function(t,n){n.remove()})},e.destroySwipe=function(){e.$container.off("movestart move moveend")},e.destroyKeys=function(){$(document).off("keyup"+e.eventSuffix)},e.setIndex=function(t){return 0>t&&(t=e.total-1),e.current=Math.min(Math.max(0,t),e.total-1),e.options.nav&&e.$nav.find('[data-slide="'+e.current+'"]')._active(e.options.activeClass),e.$slides.eq(e.current)._active(e.options.activeClass),e},e.animate=function(t,n){if("first"===t&&(t=0),"last"===t&&(t=e.total),isNaN(t))return e;e.options.autoplay&&e.stop().start(),e.setIndex(t),e.$context.trigger(e._+".change",[t,e.$slides.eq(t)]);var i="animate"+$._ucfirst(e.options.animation);return $.isFunction(e[i])&&e[i](e.current,n),e},e.next=function(){var t=e.current+1;return t>=e.total&&(t=0),e.animate(t,"next")},e.prev=function(){return e.animate(e.current-1,"prev")},e.animateHorizontal=function(t){var n="left";return"rtl"===e.$context.attr("dir")&&(n="right"),e.options.infinite&&e.$container.css("margin-"+n,"-100%"),e.slide(n,t)},e.animateVertical=function(t){return e.options.animateHeight=!0,e.options.infinite&&e.$container.css("margin-top",-e.$slides.outerHeight()),e.slide("top",t)},e.slide=function(t,n){if(e.options.animateHeight&&e._move(e.$context,{height:e.$slides.eq(n).outerHeight()},!1),e.options.infinite){var i;n===e.total-1&&(i=e.total-3,n=-1),n===e.total-2&&(i=0,n=e.total-2),"number"==typeof i&&(e.setIndex(i),e.$context.on(e._+".moved",function(){e.current===i&&e.$container.css(t,-(100*i)+"%").off(e._+".moved")}))}var o={};return o[t]=-(100*n)+"%",e._move(e.$container,o)},e.animateFade=function(t){var n=e.$slides.eq(t).addClass(e.options.activeClass);e._move(n.siblings().removeClass(e.options.activeClass),{opacity:0}),e._move(n,{opacity:1},!1)},e._move=function(t,n,i,o){return i!==!1&&(i=function(){e.$context.trigger(e._+".moved")}),t._move(n,o||e.options.speed,e.options.easing,i)},e.init(n)},$.fn._active=function(t){return this.addClass(t).siblings().removeClass(t)},$._ucfirst=function(t){return(t+"").toLowerCase().replace(/^./,function(t){return t.toUpperCase()})},$.fn._move=function(){return this.stop(!0,!0),$.fn[$.fn.velocity?"velocity":"animate"].apply(this,arguments)},void($.fn.unslider=function(t){return this.each(function(){var n=$(this);if("string"==typeof t&&n.data("unslider")){t=t.split(":");var e=n.data("unslider")[t[0]];if($.isFunction(e))return e.apply(n,t[1]?t[1].split(","):null)}return n.data("unslider",new $.Unslider(n,t))})})):console.warn("Unslider needs jQuery")}(window.jQuery);
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jquery-unslider-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Curt Howard
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-06-13 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A build of the jQuery Unslider Plugin, written by written by Visual Idiot,
|
14
|
+
packaged for the Rails asset pipeline.
|
15
|
+
email:
|
16
|
+
- curt@meows.us
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- LICENSE
|
22
|
+
- README.md
|
23
|
+
- lib/jquery-unslider-rails.rb
|
24
|
+
- lib/jquery-unslider-rails/version.rb
|
25
|
+
- vendor/assets/javascripts/jquery-unslider.js
|
26
|
+
- vendor/assets/javascripts/jquery-unslider.min.js
|
27
|
+
homepage: https://github.com/meowsus/jquery-unslider-rails
|
28
|
+
licenses:
|
29
|
+
- MIT
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubyforge_project:
|
47
|
+
rubygems_version: 2.5.1
|
48
|
+
signing_key:
|
49
|
+
specification_version: 4
|
50
|
+
summary: A build of the jQuery Unslider Plugin, written by written by Visual Idiot,
|
51
|
+
packaged for the Rails asset pipeline.
|
52
|
+
test_files: []
|