PageSourceSearch

https://lela-jahrestagung.de/header_fader/jquery.uni-carousel.js

js lela-jahrestagung.de collected 2026-10-04 11:59:35 UTC 21,196 bytes, 654 lines download raw bytes

1/* ========================================================================
2 * UNILIB: uni-carousel.js v0.1
3 * https://stroim-web.ru/demo/uni-carousel/
4 * ========================================================================
5 * Copyright 2016 Aleksey Esev
6 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7 * ======================================================================== */
8
9var UNILIB = (function() {
10	var PFX = 'uni';
11	return {
12		modules: {
13			cache: {
14				carousel: {}
15			}
16		},
17		addScrollEvent: function(params) {
18            var scrollEvent = function (delta) {
19				    if (!params.isEventInProgress()) {
20                        params.fn[((delta > 0) ? 'next' : 'prev')]();
21				    }
22                },
23                wheel = function (e) {
24                    var delta = Math.max(-1, Math.min(1, (e.originalEvent.wheelDelta || -e.originalEvent.detail)));
25                    scrollEvent(delta);
26                    e.preventDefault();
27                };
28			params.tpl
29				.addClass(PFX + '-scrollable')
30            $(params.eventArea)
31			    .on('mousewheel DOMMouseScroll', wheel);
32		},
33		addTouchEvent: function(params) {
34			var inProgress,
35			    coordinate,
36				setCoordinate = function(e) {
37					var touch = e.originalEvent.touches[0];
38					coordinate = (typeof params.orientation === 'undefined' || params.orientation === 'horizontal') ? touch.clientX : touch.clientY;
39				};
40		    if ('ontouchstart' in params.tpl[0]) {
41				params.tpl
42					.addClass(PFX + '-touchable')
43					.on('touchstart', params.eventArea, function(e) {
44						setCoordinate(e);
45						inProgress = false;
46						e.stopPropagation();
47					})
48					.on('touchmove', params.eventArea, function(e) {
49						var oldCoordinate = coordinate,
50					    	delta;
51						setCoordinate(e);
52						delta = oldCoordinate - coordinate;
53						if (delta > 0) {
54							params.fn.next();
55						}
56						else if (delta < 0) {
57							params.fn.prev();
58						}
59						inProgress = true;
60						e.stopPropagation();
61					})
62					.on('touchend', params.eventArea, function(e) {
63						e.stopPropagation();
64						if (inProgress === true) {
65							e.preventDefault();
66						}
67					});
68		    }
69			else {
70				params.tpl
71					.removeClass(PFX + '-touchable');
72			}
73		}
74    };
75})();
76
77(function($, window, document) {
78
79    'use strict';
80
81    // CAROUSEL CLASS DEFINITION
82    // =========================
83
84    var Carousel,
85	    Cache = UNILIB.modules.cache,
86		addScrollEvent = UNILIB.addScrollEvent,
87		addTouchEvent = UNILIB.addTouchEvent;
88
89	Carousel = function (carousel, carouselId, options) {
90		var dataOptions;
91
92		this.autoplayTimerId    = 0;
93		this.playTimerId        = 0;
94		this.showTimerId        = 0;
95        this.$carousel          = $(carousel);
96		dataOptions             = this.$carousel.data(Carousel.PFX + 'Options');
97        this.$carouselInner     = $('.' + Carousel.PFX + '-carousel-inner-limit', this.$carousel);
98		this.options            = (typeof options === 'object') ? $.extend({}, Carousel.DEFAULTS, options) : (typeof dataOptions === 'undefined' ? Carousel.DEFAULTS : $.extend({}, Carousel.DEFAULTS, dataOptions));
99		this.stepLength         = 33.3333;
100		this.cache              = {
101			                        html:   '',
102								    length: 0,
103									data:   {}
104		                        };
105		this.groupId            = 0;
106
107		this.privateMethod('setStepLength');
108
109		this.destroy = function() {
110			this.privateMethod('__destruct', [carouselId]);
111		};
112
113		return (this.privateMethod('__construct')) ? this : false;
114    };
115
116    Carousel.PFX      = 'uni';
117
118    Carousel.VERSION  = '0.1';
119
120    Carousel.DEFAULTS = {
121		width:           'auto',
122		height:          'auto',
123        count:           3,
124        inverse:         false,
125		cycle:           true,
126		orientation:     'horizontal',
127		autoplay:        false,
128		playImmediately: true,
129		pause:           false,
130		time:            600,
131		interval:        2000,
132		mode:            'carousel',
133		controls:   {
134			arrows: {
135				position: 'in'
136			},
137            indicators: {
138				position: 'out'
139            }
140		}
141    };
142
143	Carousel.prototype = (function() {
144
145		// Private properties and methods
146		var privateMethods = (function(privateProperties) {
147			return {
148				onInit: function(e) {
149					var $carousel = $(e.currentTarget),
150						api = e.api;
151					$carousel
152						.css({
153							width: api.options.width,
154							height: api.options.height
155						})[0].className = Carousel.PFX + '-carousel ' + Carousel.PFX + '-carousel_count-' + api.options.count + ' ' + Carousel.PFX + '-carousel_' + api.options.orientation + ' ' + Carousel.PFX + '-carousel_controls-' + api.options.controls.arrows.position;
156				},
157				initEventConstructor: function() {
158					var api = this,
159						htmlCache = '';
160
161					$(api.cache.html)
162						.each(function(i, item) {
163							htmlCache += $(item)
164								.css('transition-duration', api.options.time + 'ms')[0].outerHTML;
165						});
166
167					if (htmlCache) {
168						api.cache.html = htmlCache;
169					}
170
171					api
172						.getItems()
173						.css('transition-duration', api.options.time + 'ms');
174
175					api.$carousel.trigger($.Event('init.' + Carousel.PFX + '.carousel', {
176						currentTarget: api.$carousel[0],
177						relatedTarget: null,
178						api: api
179					}));
180				},
181				onBeforePlay: function(e) {
182					var $carousel = $(e.currentTarget),
183						api = e.api;
184
185					if (privateProperties.initialPlayEvent) {
186						privateProperties.initialPlayEvent = false;
187					}
188
189					if ($carousel.hasClass(Carousel.PFX + '-carousel_before-play')) {
190						$carousel
191							.removeClass(Carousel.PFX + '-carousel_before-play');
192					}
193				},
194				beforePlayEventConstructor: function(control) {
195					var api = this;
196					api.$carousel.trigger($.Event('beforePlay.' + Carousel.PFX + '.carousel', {
197						currentTarget: api.$carousel[0],
198						relatedTarget: control,
199						api: api
200					}));
201					$('.' + Carousel.PFX + '-carousel-control', api.$carousel).off('focus.' + Carousel.PFX + '.carousel');
202				},
203				onPlay: function(e) {
204					var api = e.api,
205						order = e.order,
206						autoplayFn;
207					if (!api.autoplayTimerId) {
208						autoplayFn = function(customTotalTime) {
209							var totalTime = typeof customTotalTime !== 'undefined' ? customTotalTime : api.options.time + api.options.interval;
210							api.autoplayTimerId = setTimeout(function() {
211								api.privateMethod('slideEventConstructor', [order]);
212								if (api.options.autoplay) {
213									autoplayFn();
214								}
215							}, totalTime);
216						};
217						if (api.options.playImmediately) {
218							autoplayFn(0);
219						}
220						else {
221							autoplayFn();
222						}
223					}
224				},
225				playEventConstructor: function(order) {
226					var control,
227						api = this;
228					if (api.options.autoplay) {
229						order = (typeof order === 'undefined') ? 'next' : order;
230						control = $('.' + Carousel.PFX + '-carousel-control_' + order, api.$carousel);
231						api.playTimerId = setTimeout(function() {
232							api.privateMethod('beforePlayEventConstructor', [control[0]]);
233							api.$carousel.trigger($.Event('play.' + Carousel.PFX + '.carousel', {
234								currentTarget: api.$carousel[0],
235								relatedTarget: control[0],
236								order: order,
237								api: api
238							}));
239						}, (privateProperties.initialPlayEvent ? api.options.interval : 0));
240					}
241				},
242				onStop: function(e) {
243					var api = e.api,
244						$carousel = $(e.currentTarget),
245						args;
246					$carousel
247						.addClass(Carousel.PFX + '-carousel_stop');
248					clearTimeout(api.autoplayTimerId);
249					api.autoplayTimerId = 0;
250					clearTimeout(api.playTimerId);
251					api.playTimerId = 0;
252					clearTimeout(api.showTimerId);
253					api.showTimerId = 0;
254					if ($carousel.hasClass(Carousel.PFX + '-carousel_slide')) {
255						args = api.isPrev(api.cache.data.direction) ? ['next'] : ['prev'];
256						api.privateMethod('slideEventConstructor', args);
257					}
258				},
259				stopEventConstructor: function() {
260					var api = this;
261					if (api.options.pause) {
262						if (api.$carousel.hasClass(Carousel.PFX + '-carousel_stop')) {
263							api.$carousel
264								.removeClass(Carousel.PFX + '-carousel_stop');
265							if (api.options.autoplay) {
266								api.privateMethod('playEventConstructor');
267							}
268						}
269						else {
270							api.$carousel.trigger($.Event('stop.' + Carousel.PFX + '.carousel', {
271								currentTarget: api.$carousel[0],
272								relatedTarget: api.$carouselInner[0],
273								api: api
274							}));
275						}
276					}
277				},
278				onSlide: function(e) {
279					var api = e.api,
280						data = api.cache.data;
281
282					api.$carousel
283						.removeClass(Carousel.PFX + '-carousel_show')
284						.addClass(Carousel.PFX + '-carousel_slide');
285
286					if (api.isNext(data.direction)) { // Next slide
287						if (api.options.cycle) {
288							if (data.isFirstVisibleFirstInGroup) {
289								api.addNewGroup(data.direction, data.firstVisible);
290							}
291							setTimeout(function() { api.control(data.currentItem, data.direction); }, 10);
292						}
293						else {
294							if (data.currentIndex > 0) {
295								api.control(data.currentItem, data.direction);
296							}
297							else {
298								api.control(data.currentItem, api.getDirection('prev'), api.getItems().eq(api.getItems().length - 1 - (api.options.count - 1)));
299							}
300						}
301					}
302					else if (api.isPrev(data.direction)) { // Prev slide
303						if (api.options.cycle) {
304							if (data.isLastVisibleLastInGroup) {
305								api.addNewGroup(data.direction, data.lastVisible);
306							}
307							setTimeout(function() { api.control(data.currentItem, data.direction); }, 10);
308						}
309						else {
310							if ((api.getItems().length - data.currentIndex) > api.options.count) {
311								api.control(data.currentItem, data.direction);
312							}
313							else {
314								api.control(data.currentItem, api.getDirection('next'), api.getItems().eq(0));
315							}
316						}
317					}
318
319					api.privateMethod('showEventConstructor');
320				},
321				slideEventConstructor: function(order) {
322					var data = {},
323						api = this;
324
325					data.direction = api.getDirection(order);
326					data.currentIndex = api.getCurrentIndex();
327					data.currentItem = $('.' + Carousel.PFX + '-carousel-item:eq(' + data.currentIndex + ')', api.$carouselInner);
328					data.firstVisible = api.getItems().eq(data.currentIndex);
329					data.lastVisible = api.getItems().eq(data.currentIndex + (api.options.count - 1));
330					data.currentGroupId = data.lastVisible.data(Carousel.PFX  + 'GroupId');
331					data.isFirstVisibleFirstInGroup = data.firstVisible.is(':first-child');
332					data.isLastVisibleLastInGroup = data.lastVisible.is(':last-child');
333
334					api.cache.data = data;
335
336					api.$carousel.trigger($.Event('slide.' + Carousel.PFX + '.carousel', {
337						currentTarget: api.$carousel[0],
338						relatedTarget: data.currentItem[0],
339						api: api
340					}));
341				},
342				onShow: function(e) {
343					var api = e.api;
344
345					api.showTimerId = setTimeout(function() {
346						api.$carousel
347							.removeClass(Carousel.PFX + '-carousel_slide')
348							.addClass(Carousel.PFX + '-carousel_show');
349					}, api.options.time);
350				},
351				showEventConstructor: function() {
352					var api = this,
353						currentItem = api.getItems().eq(api.getCurrentIndex())[0];
354
355					api.$carousel.trigger($.Event('show.' + Carousel.PFX + '.carousel', {
356						currentTarget: api.$carousel[0],
357						relatedTarget: currentItem,
358						api: api
359					}));
360				},
361				resetOptions: function(options) {
362					var api = this;
363
364					api.privateMethod('stopEventConstructor');
365
366					api.options = $.extend({}, Carousel.DEFAULTS, options);
367
368					api.privateMethod('initEventConstructor');
369					api.privateMethod('setStepLength');
370					api.privateMethod('restoreOriginalItems');
371					api.privateMethod('countValues');
372					api.privateMethod('playEventConstructor');
373				},
374				setStepLength: function() {
375					var api = this,
376						stepLength = parseFloat((100 / api.options.count).toFixed(4));
377
378					api.stepLength = stepLength;
379				},
380				countValues: function() {
381					var api = this;
382
383					api.getItems()
384						.each(function(i, item) {
385							var css = (api.options.orientation === 'horizontal') ? {left: (api.stepLength * i) + '%'} : {top: (api.stepLength * i) + '%'};
386							$(item)
387								.attr('data-' + Carousel.PFX + '-group-id', api.groupId)
388								.css(css);
389						});
390				},
391				restoreOriginalItems: function() {
392					var api = this;
393
394					api.$carouselInner
395						.html(api.cache.html)
396						.find('.' + Carousel.PFX + '-carousel-item:eq(0)')
397						.addClass(Carousel.PFX + '-carousel-item_active');
398				},
399				__construct: function() {
400
401					var api = this,
402						additionalEventParams = {
403							tpl: api.$carousel,
404							eventArea: api.$carouselInner,
405							orientation: api.options.orientation,
406							isEventInProgress: function() {
407								return api.$carousel.hasClass(Carousel.PFX + '-carousel_slide');
408							},
409							fn: {
410								prev: function() {
411									api.privateMethod('slideEventConstructor', ['prev']);
412								},
413								next: function() {
414									api.privateMethod('slideEventConstructor', ['next']);
415								}
416							}
417						};
418
419					api.cache.html = api.$carouselInner
420						.clone()
421						.find('.' + Carousel.PFX + '-carousel-item_active')
422						.removeClass(Carousel.PFX + '-carousel-item_active')
423						.end()
424						.html()
425						.replace(/\s+</gm, '<')
426						.replace(/>\s+/gm, '>');
427					api.cache.length = api.getItems().length;
428
429					api.privateMethod('countValues');
430
431					api.$carousel
432						.on('init.' + Carousel.PFX + '.carousel', function(e) {
433							api.privateMethod('onInit', [e]);
434						})
435						.on('beforePlay.' + Carousel.PFX + '.carousel', function(e) {
436							api.privateMethod('onBeforePlay', [e]);
437						})
438						.on('slide.' + Carousel.PFX + '.carousel', function(e) {
439							api.privateMethod('onSlide', [e]);
440						})
441						.on('play.' + Carousel.PFX + '.carousel', function(e) {
442							api.privateMethod('onPlay', [e]);
443						})
444						.on('stop.' + Carousel.PFX + '.carousel', function(e) {
445							api.privateMethod('onStop', [e]);
446						})
447						.on('show.' + Carousel.PFX + '.carousel', function(e) {
448							api.privateMethod('onShow', [e]);
449						});
450
451					$('.' + Carousel.PFX + '-carousel-control', api.$carousel)
452						.on('focus.' + Carousel.PFX + '.carousel', function(e) {
453							api.privateMethod('beforePlayEventConstructor', [e.currentTarget]);
454							return true;
455						})
456						.on('click.' + Carousel.PFX + '.carousel', function(e) {
457							var order = ($(e.currentTarget).hasClass(Carousel.PFX + '-carousel-control_next')) ? 'next' : 'prev';
458							api.privateMethod('slideEventConstructor', [order]);
459							return false;
460						});
461
462					api.$carouselInner
463						.on('mouseenter.' + Carousel.PFX + '.carousel', function(e) {
464							api.privateMethod('stopEventConstructor', [e]);
465						})
466						.on('mouseleave.' + Carousel.PFX + '.carousel', function(e) {
467							api.privateMethod('stopEventConstructor', [e]);
468						});
469
470					addScrollEvent(additionalEventParams);
471
472					addTouchEvent(additionalEventParams);
473
474					api.privateMethod('initEventConstructor');
475					api.privateMethod('playEventConstructor');
476
477					return true;
478
479				},
480				__destruct: function(carouselId) {
481					var api = this;
482
483					api.privateMethod('stopEventConstructor');
484					api.privateMethod('restoreOriginalItems');
485					delete Cache.carousel[carouselId];
486
487				}
488			}
489		})({ // Private properties
490			initialPlayEvent: true
491		});
492
493		// Public methods
494		return {
495			privateMethod: function(methodName, args) {
496				privateMethods[methodName].apply(this, args);
497	    	},
498	    	getItems: function() {
499		    	return $('.' + Carousel.PFX + '-carousel-item', this.$carouselInner);
500	    	},
501	    	getItemValue: function(item) {
502				var style = $(item).attr('style'),
503					value;
504				if (this.options.orientation === 'horizontal') {
505					value = (style === 'left: 0%;') ? ['left: 0%;','0'] : /left:\s{0,}(\S+)%/.exec(style);
506				}
507				else {
508			    	value = (style === 'top: 0%;') ? ['top: 0%;','0'] : /top:\s{0,}(\S+)%/.exec(style);
509				}
510				value = parseFloat(value[1]);
511				return value;
512			},
513	    	getCurrentIndex: function() {
514				return this.getItems().index($('.' + Carousel.PFX + '-carousel-item_active', this.$carouselInner));
515			},
516	    	getDirection: function(order) {
517				var direction;
518				if (this.options.orientation === 'horizontal') {
519					direction = (order === 'next') ? ((this.options.inverse) ? 'left' : 'right') : ((this.options.inverse) ? 'right' : 'left');
520				}
521				else {
522					direction = (order === 'next') ? ((this.options.inverse) ? 'bottom' : 'top') : ((this.options.inverse) ? 'top' : 'bottom');
523				}
524				return direction;
525			},
526			isPrev: function(direction) {
527				return direction === 'left' || direction === 'bottom';
528			},
529			isNext: function(direction) {
530				return direction === 'right' || direction === 'top';
531			},
532			slide: function(direction, multiplier) {
533				var api = this,
534				    width = api.options.mode === 'slider' ? 100 : api.stepLength;
535				multiplier = (typeof multiplier === 'undefined') ? 1 : multiplier;
536				api.getItems()
537					.each(function(i, item) {
538						var value = api.getItemValue(item),
539					    	css;
540						if (api.isNext(direction)) {
541							value += (width * multiplier);
542						}
543						else if (api.isPrev(direction)) {
544							value -= (width * multiplier);
545						}
546						value = (value > -1 && value < 1) ? 0 : value;
547						css = (api.options.orientation === 'horizontal') ? {left: value + '%'} : {top: value + '%'};
548						$(item)
549							.css(css);
550					});
551			},
552			control: function(currentItem, direction, activated) {
553				var itemClass = Carousel.PFX + '-carousel-item',
554				    currentItemIndex = this.getCurrentIndex(),
555					itemLength = this.getItems().length,
556		    		currentItem = currentItem.removeClass(itemClass + '_active'),
557					slideArgs = [direction];
558				if (typeof activated === 'undefined') {
559					if (this.isPrev(direction)) {
560						activated = (this.options.mode === 'slider' ? (currentItemIndex + this.options.count >= itemLength ? this.getItems().eq(itemLength - 1) : this.getItems().eq(currentItemIndex + this.options.count)) : currentItem.next('.' + itemClass))
561						    .addClass(itemClass + '_active');
562					}
563					else {
564						activated = (this.options.mode === 'slider' ? (currentItemIndex - this.options.count < 0 ? this.getItems().eq(0) : this.getItems().eq(currentItemIndex - this.options.count)) : currentItem.prev('.' + itemClass))
565						    .addClass(itemClass + '_active');
566					}
567				}
568				else {
569				    activated
570				        .addClass(itemClass + '_active');
571					slideArgs.push(Math.abs(currentItemIndex - this.getCurrentIndex()));
572				}
573        		this.slide.apply(this, slideArgs);
574			},
575			addNewGroup: function(direction, finalVisible) {
576				this.groupId += 1;
577				var api = this,
578		    		leftValue,
579					css,
580		    		value = api.getItemValue(finalVisible),
581					newItemsLength = api.cache.length,
582					newItems = $(api.cache.html)
583				    	.attr('data-' + Carousel.PFX + '-group-id', api.groupId);
584				if (api.isNext(direction)) {
585					newItems
586						.each(function(i, item) {
587							leftValue = -((newItemsLength - i) * api.stepLength);
588							css = (api.options.orientation === 'horizontal') ? {left: leftValue + '%'} : {top: leftValue + '%'};
589							$(item)
590								.css(css);
591						})
592					.insertBefore(finalVisible);
593				}
594				else if (api.isPrev(direction)) {
595            		newItems
596						.each(function(i, item) {
597							css = (api.options.orientation === 'horizontal') ? {left: value + ((i + 1) * api.stepLength) + '%'} : {top: value + ((i + 1) * api.stepLength) + '%'};
598							$(item)
599								.css(css);
600						})
601					.insertAfter(finalVisible);
602				}
603				api.removeBorderGroup(direction);
604			},
605			removeBorderGroup: function(direction) {
606				var borderItem,
607			    	borderGroupId,
608					borderGroup,
609					groupsLength = this.getItems().length / this.cache.length;
610				if (groupsLength > 2) {
611					borderItem = (this.isPrev(direction)) ? $('.' + Carousel.PFX + '-carousel-item:first-child', this.$carouselInner) : $('.' + Carousel.PFX + '-carousel-item:last-child', this.$carouselInner);
612			    	borderGroupId = borderItem.data(Carousel.PFX + '-group-id');
613					borderGroup = $('[data-' + Carousel.PFX + '-group-id=' + borderGroupId + ']', this.$carouselInner);
614					borderGroup
615				    	.remove();
616				}
617			},
618		    stop: function() {
619			    this.privateMethod('stopEventConstructor');
620		    },
621		    resetOptions: function(options) {
622			    this.privateMethod('resetOptions', [options]);
623		    }
624		}
625	})();
626
627    $.fn.uniCarousel = function(options){
628        return this.each(function(index, carousel) {
629			var carouselId = 'carousel-' + index;
630			if (typeof Cache.carousel[carouselId] === 'undefined') {
631		        Cache.carousel[carouselId] = new Carousel(carousel, carouselId, options);
632				Cache.carousel[carouselId].$carousel.prop('id', carouselId).attr('id', carouselId);
633			}
634			else if (typeof options === 'object') {
635				Cache.carousel[carouselId].resetOptions(options);
636			}
637			else if (typeof options === 'string') {
638				switch (options) {
639					case 'stop':
640				    	Cache.carousel[carouselId].stop();
641					break;
642					case 'destroy':
643				    	Cache.carousel[carouselId].destroy();
644					break;
645				}
646			}
647	    });
648    };
649
650	$(function() {
651		$('.uni-carousel').uniCarousel();
652	});
653
654})(jQuery, window, document);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.