-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjquery.carousel.js
More file actions
392 lines (324 loc) · 11.7 KB
/
Copy pathjquery.carousel.js
File metadata and controls
392 lines (324 loc) · 11.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
/*
* jQuery Ultimate Carousel 2.0
* Creates a carousel from a set of elements, allowing for pagers.
*
* Based on:
* jQuery Infinite Carousel Plugin (http://code.google.com/p/jquery-infinite-carousel)
*/
;(function($){
$.fn.carousel = function(options)
{
// iterate through each item
this.addClass('carousel').each(function(i){
// create instance
var inst = $(this);
// create carousel data object if not set
if (inst.data('carousel') == null)
{
inst.data('carousel', {
options: $.fn.carousel.options,
initialized: false,
animating: false
});
}
// create carousel data object minipulation
var carousel = inst.data('carousel');
// merge options for carousel object with that of the supplied options
carousel.options = $.extend(true, carousel.options, (typeof options == 'undefined') ? {} : options);
// set easing mode to default if easing mode is not available
carousel.options.easing = $.isFunction($.easing[carousel.options.easing]) ? carousel.options.easing : $.fn.carousel.options.easing;
// initialize carousel for instance
$.fn.carousel.init(inst);
});
return this;
}
// initilize carousel, making any nescessary calculations and adding nescessary markup
$.fn.carousel.init = function(inst)
{
// ensure inst is a jQuery object
var inst = $(inst);
// get carousel object for instance
var carousel = inst.data('carousel');
var options = carousel.options;
// set the carousel's width and height
carousel.width = (typeof carousel.width == 'number' && carousel.width > 0) ? carousel.width : parseInt(inst.width());
// continue only if carousel's width is greater than 0
if (carousel.width > 0 && !carousel.initialized)
{
// get all slides within instance
var slides = inst.children();
// set references for slides
carousel.slides = {
current: 1,
count: slides.length,
width: 0,
height: 0,
outerWidth: 0,
outerHeight: 0,
shown: 1,
template: $(slides.get(0)).clone().addClass('empty').empty()
};
// iterate through each slide
slides.each(function(i){
// get the dimensions of the current slide
var width = parseInt($(this).width());
var height = parseInt($(this).height());
var outerWidth = parseInt($(this).outerWidth(true));
var outerHeight = parseInt($(this).outerHeight(true));
// increase the width/height values of slides if the current slide's is greater
carousel.slides.width = (width > carousel.slides.width) ? width : carousel.slides.width;
carousel.slides.height = (height > carousel.slides.height) ? height : carousel.slides.height;
// increase the outerWidth/outerHeight values of slides if the current slide's is greater
carousel.slides.outerWidth = (outerWidth > carousel.slides.outerWidth) ? outerWidth : carousel.slides.outerWidth;
carousel.slides.outerHeight = (outerHeight > carousel.slides.outerHeight) ? outerHeight : carousel.slides.outerHeight;
});
// if more than one slide may be shown, determine slides shown based on width of carousel and outerWidth of slides
if (inst.width() > carousel.slides.outerWidth)
{
carousel.slides.shown = Math.floor(inst.width() / carousel.slides.outerWidth);
}
// set the height of the instance
inst.height(carousel.slides.outerHeight);
// set the width of the instance
inst.width(carousel.width);
// continue if the number of slides is greater than the number of slides shown
if (carousel.slides.count > carousel.slides.shown)
{
// add the viewport division if it does not exist and set it's width explicitly
if (inst.parent('div.carousel-viewport').length <= 0)
{
inst.wrap('<div class="carousel-viewport"></div>').parent('.carousel-viewport').width((carousel.slides.outerWidth * carousel.slides.shown) - (carousel.slides.outerWidth - carousel.slides.width));
}
// set the width and height of all slides
slides.width(carousel.slides.width);
slides.height(carousel.slides.height);
// set the width and height of the slide template
carousel.slides.template.width(carousel.slides.width).height(carousel.slides.height);
// calculate the number of empty slides to create
carousel.slides.empty = (carousel.slides.shown - (carousel.slides.count % carousel.slides.shown)) % carousel.slides.shown;
// add number of empty slides needed to create
for (i = 0; i < carousel.slides.empty; i++)
{
inst.append(carousel.slides.template.clone());
}
// add duplicate slides for purposes of facilitating an infinite scroll
for (i = 0; i < carousel.slides.shown; i++)
{
inst.append($(slides[i]).clone());
}
// calculate the new width of the carousel based on the number of slides now present
carousel.width = inst.children().length * carousel.slides.outerWidth;
// set the width of the instance
inst.width(carousel.width);
// add the carousel pager
$.fn.carousel.pagerAdd(inst);
// set carousel as initialized
carousel.initialized = true;
}
}
};
// add pager for carousel
$.fn.carousel.pagerAdd = function(inst)
{
// ensure inst is a jQuery object
var inst = $(inst);
// get carousel object for instance
var carousel = inst.data('carousel');
var options = carousel.options;
// add the pager list if it should be shown and it doesn't already exist
if (options.pager.show && inst.siblings('ul.carousel-pager').length <= 0)
{
// create pager list
var pager = $('<ul class="carousel-pager"></ul>').width((carousel.slides.outerWidth * carousel.slides.shown) - (carousel.slides.outerWidth - carousel.slides.width)).bind('click', function(e){
// set references to target and the target's parent
target = $(e.target);
parentEl = target.parent();
// check if the target is an anchor
if (target.is('a'))
{
// prevent the default click behavior
e.preventDefault();
var fromPager = false;
// handle the click based on whether it is a page button or prev/next button
if (parentEl.hasClass('prev'))
{
i = carousel.slides.current - carousel.slides.shown;
}
else if (parentEl.hasClass('next'))
{
i = carousel.slides.current + carousel.slides.shown;
}
else
{
var page = $('li:not(.prev, .next)', this).index(parentEl) + 1;
i = (page * carousel.slides.shown) - (carousel.slides.shown - 1);
fromPager = true;
}
$.fn.carousel.goTo(inst, i, fromPager);
}
});
// create template for pager button
var pagerTemplate = $('<li><a href="#"></a></li>');
// calculate number of pages
carousel.pages = Math.ceil(carousel.slides.count / carousel.slides.shown);
// add page button for each page
for (i = 1; i <= carousel.pages; i++)
{
// build the button
var pageButton = pagerTemplate.clone().find('a').parent();
// add active class to first pager button
if (i == 1)
{
pageButton.addClass('active');
}
// add the button
pager.append(pageButton);
}
// add previous button to pager
if (options.pager.prevButton.show)
{
// build the button
var pagerPrev = pagerTemplate.clone().addClass('prev').find('a').html(options.pager.prevButton.text).parent();
if (options.pager.nexPrevPosition == 'after')
{
// add the button
pager.append(pagerPrev);
}
else
{
// add the button
pager.prepend(pagerPrev);
}
}
// add next button to pager
if (options.pager.nextButton.show)
{
// build the button
var pagerNext = pagerTemplate.clone().addClass('next').find('a').html(options.pager.nextButton.text).parent();
// add the button
pager.append(pagerNext);
}
// add the pager
if (options.pager.position == 'before')
{
inst.parent('.carousel-viewport').before(pager);
}
else
{
inst.parent('.carousel-viewport').after(pager);
}
// create reference to pager
carousel.pager = inst.addClass('carousel-with-pager').parent('.carousel-viewport').siblings('ul.carousel-pager');
}
}
// advance to a specific item within the carousel
$.fn.carousel.goTo = function(inst, i, fromPager)
{
// define default fromPager value
var fromPager = (typeof fromPager == 'undefined') ? false : fromPager;
// ensure inst is a jQuery object
var inst = $(inst);
// get carousel object for instance
var carousel = inst.data('carousel');
var options = carousel.options;
// set index to valid slide index
var firstToLast = false;
var lastToFirst = false;
if (i > carousel.slides.count)
{
i = i - carousel.slides.count - carousel.slides.empty;
lastToFirst = true;
}
else if (i <= 0)
{
i = i + carousel.slides.count + carousel.slides.empty;
firstToLast = true;
}
// only animate if the carousel is not animating and the current slide is not the same as requested
if (!(carousel.slides.current == i) && !carousel.animating)
{
var distance = {
left: {
slides: carousel.slides.current - i
},
right: {
slides: carousel.slides.count + carousel.slides.empty + i - carousel.slides.current
}
}
if (i > carousel.slides.current)
{
distance.left.slides = carousel.slides.count + carousel.slides.empty - i + carousel.slides.current;
distance.right.slides = i - carousel.slides.current;
}
distance.left.pages = Math.ceil(distance.left.slides / carousel.slides.shown);
distance.right.pages = Math.ceil(distance.right.slides / carousel.slides.shown);
var currentPage = Math.ceil(carousel.slides.current / carousel.slides.shown);
var goToPage = Math.ceil(i / carousel.slides.shown);
var animateProperties = {};
// animate right
if (((goToPage > currentPage && distance.right.pages < carousel.pages) || (distance.right.pages == 1 && currentPage == carousel.pages && !fromPager) && !(firstToLast || (!firstToLast && !lastToFirst))) && !(currentPage == 1 && distance.left.pages == 1 && !fromPager && !(lastToFirst || (!firstToLast && !lastToFirst))))
{
if (carousel.slides.current <= carousel.slides.shown)
{
var left = - (carousel.slides.outerWidth * (carousel.slides.current - 1));
}
var rightAnimate = '-=' + (carousel.slides.outerWidth * distance.right.slides);
animateProperties = {left:rightAnimate}
}
// animate left
else
{
if (carousel.slides.current <= carousel.slides.shown)
{
var left = - (carousel.slides.outerWidth * (carousel.slides.count + carousel.slides.empty + carousel.slides.current - 1));
}
var leftAnimate = '+=' + (carousel.slides.outerWidth * distance.left.slides);
animateProperties = {left:leftAnimate}
}
// set initial state if left value is set
if (typeof left != 'undefined')
{
inst.css('left', left + 'px');
}
// set the active pager item
if (options.pager.show)
{
eq = Math.ceil(i / carousel.slides.shown) - 1;
$('li:not(.prev, .next)', carousel.pager).removeClass('active').filter(':eq(' + eq + ')').addClass('active');
}
// set slider to animating
carousel.animating = true;
// call slideStart function
carousel.options.slideStart(inst);
// animate slider
inst.animate(animateProperties, options.duration, options.easing, function(){
// set slider to not animating
carousel.animating = false;
// call slideComplete function
carousel.options.slideComplete(inst);
});
// set first slide reference
carousel.slides.current = i;
}
};
// set default options
$.fn.carousel.options = {
pager: {
show: true,
position: 'before',
nexPrevPosition: '',
prevButton: {
show: true,
text: 'Previous'
},
nextButton: {
show: true,
text: 'Next'
}
},
slideStart: function(inst){},
slideComplete: function(inst){},
easing: 'swing',
duration: 300
};
})(jQuery);