PageSourceSearch

https://iabtechlab.com/wp-content/themes/modality/js/ideal-image-slider.js?ver=20160115

js iabtechlab.com collected 2026-09-24 06:46:05 UTC 28,284 bytes, 833 lines download raw bytes

1/*
2 * Ideal Image Slider v1.5.0
3 *
4 * By Gilbert Pellegrom
5 * http://gilbert.pellegrom.me
6 *
7 * Copyright (C) 2014 Dev7studios
8 * https://raw.githubusercontent.com/gilbitron/Ideal-Image-Slider/master/LICENSE
9 */
10
11var IdealImageSlider = (function() {
12	"use strict";
13
14	/*
15	 * requestAnimationFrame polyfill
16	 */
17	var _requestAnimationFrame = function(win, t) {
18		return win["r" + t] || win["webkitR" + t] || win["mozR" + t] || win["msR" + t] || function(fn) {
19			setTimeout(fn, 1000 / 60);
20		};
21	}(window, 'equestAnimationFrame');
22
23	/**
24	 * Behaves the same as setTimeout except uses requestAnimationFrame() where possible for better performance
25	 * @param {function} fn The callback function
26	 * @param {int} delay The delay in milliseconds
27	 */
28	var _requestTimeout = function(fn, delay) {
29		var start = new Date().getTime(),
30			handle = {};
31
32		function loop() {
33			var current = new Date().getTime(),
34				delta = current - start;
35
36			if (delta >= delay) {
37				fn.call();
38			} else {
39				handle.value = _requestAnimationFrame(loop);
40			}
41		}
42
43		handle.value = _requestAnimationFrame(loop);
44		return handle;
45	};
46
47	/*
48	 * Helper functions
49	 */
50	var _isType = function(type, obj) {
51		var _class = Object.prototype.toString.call(obj).slice(8, -1);
52		return obj !== undefined && obj !== null && _class === type;
53	};
54
55	var _isInteger = function(x) {
56		return Math.round(x) === x;
57	};
58
59	var _deepExtend = function(out) {
60		out = out || {};
61		for (var i = 1; i < arguments.length; i++) {
62			var obj = arguments[i];
63			if (!obj)
64				continue;
65			for (var key in obj) {
66				if (obj.hasOwnProperty(key)) {
67					if (_isType('Object', obj[key]) && obj[key] !== null)
68						_deepExtend(out[key], obj[key]);
69					else
70						out[key] = obj[key];
71				}
72			}
73		}
74		return out;
75	};
76
77	var _hasClass = function(el, className) {
78		if (!className) return false;
79		if (el.classList) {
80			return el.classList.contains(className);
81		} else {
82			return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className);
83		}
84	};
85
86	var _addClass = function(el, className) {
87		if (!className) return;
88		if (el.classList) {
89			el.classList.add(className);
90		} else {
91			el.className += ' ' + className;
92		}
93	};
94
95	var _removeClass = function(el, className) {
96		if (!className) return;
97		if (el.classList) {
98			el.classList.remove(className);
99		} else {
100			el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
101		}
102	};
103
104	var _toArray = function(obj) {
105		return Array.prototype.slice.call(obj);
106	};
107
108	var _arrayRemove = function(array, from, to) {
109		var rest = array.slice((to || from) + 1 || array.length);
110		array.length = from < 0 ? array.length + from : from;
111		return array.push.apply(array, rest);
112	};
113
114	var _addEvent = function(object, type, callback) {
115		if (object === null || typeof(object) === 'undefined') return;
116
117		if (object.addEventListener) {
118			object.addEventListener(type, callback, false);
119		} else if (object.attachEvent) {
120			object.attachEvent("on" + type, callback);
121		} else {
122			object["on" + type] = callback;
123		}
124	};
125
126	var _loadImg = function(slide, callback) {
127		if (!slide.style.backgroundImage) {
128			var img = new Image();
129			img.setAttribute('src', slide.getAttribute('data-src'));
130			img.onload = function() {
131				slide.style.backgroundImage = 'url(' + slide.getAttribute('data-src') + ')';
132				slide.setAttribute('data-actual-width', this.naturalWidth);
133				slide.setAttribute('data-actual-height', this.naturalHeight);
134				if (typeof(callback) === 'function') callback(this);
135			};
136		}
137	};
138
139	var _isHighDPI = function() {
140		var mediaQuery = "(-webkit-min-device-pixel-ratio: 1.5),(min--moz-device-pixel-ratio: 1.5),(-o-min-device-pixel-ratio: 3/2),(min-resolution: 1.5dppx)";
141		if (window.devicePixelRatio > 1)
142			return true;
143		if (window.matchMedia && window.matchMedia(mediaQuery).matches)
144			return true;
145		return false;
146	};
147
148	var _translate = function(slide, dist, speed) {
149		slide.style.webkitTransitionDuration =
150			slide.style.MozTransitionDuration =
151			slide.style.msTransitionDuration =
152			slide.style.OTransitionDuration =
153			slide.style.transitionDuration = speed + 'ms';
154
155		slide.style.webkitTransform =
156			slide.style.MozTransform =
157			slide.style.msTransform =
158			slide.style.OTransform = 'translateX(' + dist + 'px)';
159	};
160
161	var _unTranslate = function(slide) {
162		slide.style.removeProperty('-webkit-transition-duration');
163		slide.style.removeProperty('transition-duration');
164
165		slide.style.removeProperty('-webkit-transform');
166		slide.style.removeProperty('-ms-transform');
167		slide.style.removeProperty('transform');
168	};
169
170	var _animate = function(item) {
171		var duration = item.time,
172			end = +new Date() + duration;
173
174		var step = function() {
175			var current = +new Date(),
176				remaining = end - current;
177
178			if (remaining < 60) {
179				item.run(1); //1 = progress is at 100%
180				return;
181			} else {
182				var progress = 1 - remaining / duration;
183				item.run(progress);
184			}
185
186			_requestAnimationFrame(step);
187		};
188		step();
189	};
190
191	var _setContainerHeight = function(slider, shouldAnimate) {
192		if (typeof shouldAnimate === 'undefined') {
193			shouldAnimate = true;
194		}
195
196		// If it's a fixed height then don't change the height
197		if (_isInteger(slider.settings.height)) {
198			return;
199		}
200
201		var currentHeight = Math.round(slider._attributes.container.offsetHeight),
202			newHeight = currentHeight;
203
204		if (slider._attributes.aspectWidth && slider._attributes.aspectHeight) {
205			// Aspect ratio
206			newHeight = (slider._attributes.aspectHeight / slider._attributes.aspectWidth) * slider._attributes.container.offsetWidth;
207		} else {
208			// Auto
209			var width = slider._attributes.currentSlide.getAttribute('data-actual-width');
210			var height = slider._attributes.currentSlide.getAttribute('data-actual-height');
211
212			if (width && height) {
213				newHeight = (height / width) * slider._attributes.container.offsetWidth;
214			}
215		}
216
217		var maxHeight = parseInt(slider.settings.maxHeight, 10);
218		if (maxHeight && newHeight > maxHeight) {
219			newHeight = maxHeight;
220		}
221
222		newHeight = Math.round(newHeight);
223		if (newHeight === currentHeight) {
224			return;
225		}
226
227		if (shouldAnimate) {
228			_animate({
229				time: slider.settings.transitionDuration,
230				run: function(progress) {
231					slider._attributes.container.style.height = Math.round(progress * (newHeight - currentHeight) + currentHeight) + 'px';
232				}
233			});
234		} else {
235			slider._attributes.container.style.height = newHeight + 'px';
236		}
237	};
238
239	var _touch = {
240
241		vars: {
242			start: {},
243			delta: {},
244			isScrolling: undefined,
245			direction: null
246		},
247
248		start: function(event) {
249			if (_hasClass(this._attributes.container, this.settings.classes.animating)) return;
250
251			var touches = event.touches[0];
252			_touch.vars.start = {
253				x: touches.pageX,
254				y: touches.pageY,
255				time: +new Date()
256			};
257			_touch.vars.delta = {};
258			_touch.vars.isScrolling = undefined;
259			_touch.vars.direction = null;
260
261			this.stop(); // Stop slider
262
263			this.settings.beforeChange.apply(this);
264			_addClass(this._attributes.container, this.settings.classes.touching);
265		},
266
267		move: function(event) {
268			if (_hasClass(this._attributes.container, this.settings.classes.animating)) return;
269			// Ensure swiping with one touch and not pinching
270			if (event.touches.length > 1 || event.scale && event.scale !== 1) return;
271
272			var touches = event.touches[0];
273			_touch.vars.delta = {
274				x: touches.pageX - _touch.vars.start.x,
275				y: touches.pageY - _touch.vars.start.y
276			};
277
278			if (typeof _touch.vars.isScrolling == 'undefined') {
279				_touch.vars.isScrolling = !!(_touch.vars.isScrolling || Math.abs(_touch.vars.delta.x) < Math.abs(_touch.vars.delta.y));
280			}
281
282			// If user is not trying to scroll vertically
283			if (!_touch.vars.isScrolling) {
284				event.preventDefault(); // Prevent native scrolling
285
286				_translate(this._attributes.previousSlide, _touch.vars.delta.x - this._attributes.previousSlide.offsetWidth, 0);
287				_translate(this._attributes.currentSlide, _touch.vars.delta.x, 0);
288				_translate(this._attributes.nextSlide, _touch.vars.delta.x + this._attributes.currentSlide.offsetWidth, 0);
289			}
290		},
291
292		end: function(event) {
293			if (_hasClass(this._attributes.container, this.settings.classes.animating)) return;
294
295			var duration = +new Date() - _touch.vars.start.time;
296
297			// Determine if slide attempt triggers next/prev slide
298			var isChangeSlide = Number(duration) < 250 && Math.abs(_touch.vars.delta.x) > 20 || Math.abs(_touch.vars.delta.x) > this._attributes.currentSlide.offsetWidth / 2;
299
300			var direction = _touch.vars.delta.x < 0 ? 'next' : 'previous';
301			var speed = this.settings.transitionDuration ? this.settings.transitionDuration / 2 : 0;
302
303			// If not scrolling vertically
304			if (!_touch.vars.isScrolling) {
305				if (isChangeSlide) {
306					_touch.vars.direction = direction;
307
308					if (_touch.vars.direction == 'next') {
309						_translate(this._attributes.currentSlide, -this._attributes.currentSlide.offsetWidth, speed);
310						_translate(this._attributes.nextSlide, 0, speed);
311					} else {
312						_translate(this._attributes.previousSlide, 0, speed);
313						_translate(this._attributes.currentSlide, this._attributes.currentSlide.offsetWidth, speed);
314					}
315
316					_requestTimeout(_touch.transitionEnd.bind(this), speed);
317				} else {
318					// Slides return to original position
319					if (direction == 'next') {
320						_translate(this._attributes.currentSlide, 0, speed);
321						_translate(this._attributes.nextSlide, this._attributes.currentSlide.offsetWidth, speed);
322					} else {
323						_translate(this._attributes.previousSlide, -this._attributes.previousSlide.offsetWidth, speed);
324						_translate(this._attributes.currentSlide, 0, speed);
325					}
326				}
327
328				if (speed) {
329					_addClass(this._attributes.container, this.settings.classes.animating);
330					_requestTimeout(function() {
331						_removeClass(this._attributes.container, this.settings.classes.animating);
332					}.bind(this), speed);
333				}
334			}
335		},
336
337		transitionEnd: function(event) {
338			if (_touch.vars.direction) {
339				_unTranslate(this._attributes.previousSlide);
340				_unTranslate(this._attributes.currentSlide);
341				_unTranslate(this._attributes.nextSlide);
342				_removeClass(this._attributes.container, this.settings.classes.touching);
343
344				_removeClass(this._attributes.previousSlide, this.settings.classes.previousSlide);
345				_removeClass(this._attributes.currentSlide, this.settings.classes.currentSlide);
346				_removeClass(this._attributes.nextSlide, this.settings.classes.nextSlide);
347				this._attributes.currentSlide.setAttribute('aria-hidden', 'true');
348
349				var slides = this._attributes.slides,
350					index = slides.indexOf(this._attributes.currentSlide);
351
352				if (_touch.vars.direction == 'next') {
353					this._attributes.previousSlide = this._attributes.currentSlide;
354					this._attributes.currentSlide = slides[index + 1];
355					this._attributes.nextSlide = slides[index + 2];
356					if (typeof this._attributes.currentSlide === 'undefined' &&
357						typeof this._attributes.nextSlide === 'undefined') {
358						this._attributes.currentSlide = slides[0];
359						this._attributes.nextSlide = slides[1];
360					} else {
361						if (typeof this._attributes.nextSlide === 'undefined') {
362							this._attributes.nextSlide = slides[0];
363						}
364					}
365
366					_loadImg(this._attributes.nextSlide);
367				} else {
368					this._attributes.nextSlide = this._attributes.currentSlide;
369					this._attributes.previousSlide = slides[index - 2];
370					this._attributes.currentSlide = slides[index - 1];
371					if (typeof this._attributes.currentSlide === 'undefined' &&
372						typeof this._attributes.previousSlide === 'undefined') {
373						this._attributes.currentSlide = slides[slides.length - 1];
374						this._attributes.previousSlide = slides[slides.length - 2];
375					} else {
376						if (typeof this._attributes.previousSlide === 'undefined') {
377							this._attributes.previousSlide = slides[slides.length - 1];
378						}
379					}
380
381					_loadImg(this._attributes.previousSlide);
382				}
383
384				_addClass(this._attributes.previousSlide, this.settings.classes.previousSlide);
385				_addClass(this._attributes.currentSlide, this.settings.classes.currentSlide);
386				_addClass(this._attributes.nextSlide, this.settings.classes.nextSlide);
387				this._attributes.currentSlide.setAttribute('aria-hidden', 'false');
388
389				_setContainerHeight(this);
390				this.settings.afterChange.apply(this);
391			}
392		}
393
394	};
395
396	/*
397	 * Slider class
398	 */
399	var Slider = function(args) {
400		// Defaults
401		this.settings = {
402			selector: '',
403			height: 'auto', // "auto" | px value (e.g. 400) | aspect ratio (e.g. "16:9")
404			initialHeight: 400, // for "auto" and aspect ratio
405			maxHeight: null, // for "auto" and aspect ratio
406			interval: 4000,
407			transitionDuration: 700,
408			effect: 'slide',
409			disableNav: false,
410			keyboardNav: true,
411			previousNavSelector: '',
412			nextNavSelector: '',
413			classes: {
414				container: 'ideal-image-slider',
415				slide: 'iis-slide',
416				previousSlide: 'iis-previous-slide',
417				currentSlide: 'iis-current-slide',
418				nextSlide: 'iis-next-slide',
419				previousNav: 'iis-previous-nav',
420				nextNav: 'iis-next-nav',
421				animating: 'iis-is-animating',
422				touchEnabled: 'iis-touch-enabled',
423				touching: 'iis-is-touching',
424				directionPrevious: 'iis-direction-previous',
425				directionNext: 'iis-direction-next'
426			},
427			onInit: function() {},
428			onStart: function() {},
429			onStop: function() {},
430			onDestroy: function() {},
431			beforeChange: function() {},
432			afterChange: function() {}
433		};
434
435		// Parse args
436		if (typeof args === 'string') {
437			this.settings.selector = args;
438		} else if (typeof args === 'object') {
439			_deepExtend(this.settings, args);
440		}
441
442		// Slider (container) element
443		var sliderEl = document.querySelector(this.settings.selector);
444		if (!sliderEl) return null;
445
446		// Slides
447		var origChildren = _toArray(sliderEl.children),
448			validSlides = [];
449		sliderEl.innerHTML = '';
450		Array.prototype.forEach.call(origChildren, function(slide, i) {
451			if (slide instanceof HTMLImageElement || slide instanceof HTMLAnchorElement) {
452				var slideEl = document.createElement('a'),
453					href = '',
454					target = '';
455
456				if (slide instanceof HTMLAnchorElement) {
457					href = slide.getAttribute('href');
458					target = slide.getAttribute('target');
459
460					var img = slide.querySelector('img');
461					if (img !== null) {
462						slide = img;
463					} else {
464						return;
465					}
466				}
467
468				if (typeof slide.dataset !== 'undefined') {
469					_deepExtend(slideEl.dataset, slide.dataset);
470					if (slide.dataset.src) {
471						// Use data-src for on-demand loading
472						slideEl.dataset.src = slide.dataset.src;
473					} else {
474						slideEl.dataset.src = slide.src;
475					}
476
477					// HiDPI support
478					if (_isHighDPI() && slide.dataset['src-2x']) {
479						slideEl.dataset.src = slide.dataset['src-2x'];
480					}
481				} else {
482					// IE
483					if (slide.getAttribute('data-src')) {
484						slideEl.setAttribute('data-src', slide.getAttribute('data-src'));
485					} else {
486						slideEl.setAttribute('data-src', slide.getAttribute('src'));
487					}
488				}
489
490				if (href) slideEl.setAttribute('href', href);
491				if (target) slideEl.setAttribute('target', target);
492				if (slide.getAttribute('className')) _addClass(slideEl, slide.getAttribute('className'));
493				if (slide.getAttribute('id')) slideEl.setAttribute('id', slide.getAttribute('id'));
494				if (slide.getAttribute('title')) slideEl.setAttribute('title', slide.getAttribute('title'));
495				if (slide.getAttribute('link')) slideEl.setAttribute('link', slide.getAttribute('link'));
496				if (slide.getAttribute('alt')) slideEl.innerHTML = slide.getAttribute('alt');
497				slideEl.setAttribute('role', 'tabpanel');
498				slideEl.setAttribute('aria-hidden', 'true');
499
500				slideEl.style.cssText += '-webkit-transition-duration:' + this.settings.transitionDuration + 'ms;-moz-transition-duration:' + this.settings.transitionDuration + 'ms;-o-transition-duration:' + this.settings.transitionDuration + 'ms;transition-duration:' + this.settings.transitionDuration + 'ms;';
501
502				sliderEl.appendChild(slideEl);
503				validSlides.push(slideEl);
504			}
505		}.bind(this));
506
507		var slides = validSlides;
508		if (slides.length <= 1) {
509			sliderEl.innerHTML = '';
510			Array.prototype.forEach.call(origChildren, function(child, i) {
511				sliderEl.appendChild(child);
512			});
513			return null;
514		}
515
516		// Create navigation
517		if (!this.settings.disableNav) {
518			var previousNav, nextNav;
519			if (this.settings.previousNavSelector) {
520				previousNav = document.querySelector(this.settings.previousNavSelector);
521			} else {
522				previousNav = document.createElement('a');
523				sliderEl.appendChild(previousNav);
524			}
525			if (this.settings.nextNavSelector) {
526				nextNav = document.querySelector(this.settings.nextNavSelector);
527			} else {
528				nextNav = document.createElement('a');
529				sliderEl.appendChild(nextNav);
530			}
531
532			_addClass(previousNav, this.settings.classes.previousNav);
533			_addClass(nextNav, this.settings.classes.nextNav);
534			_addEvent(previousNav, 'click', function() {
535				if (_hasClass(this._attributes.container, this.settings.classes.animating)) return false;
536				this.stop();
537				this.previousSlide();
538			}.bind(this));
539			_addEvent(nextNav, 'click', function() {
540				if (_hasClass(this._attributes.container, this.settings.classes.animating)) return false;
541				this.stop();
542				this.nextSlide();
543			}.bind(this));
544
545			// Touch Navigation
546			if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
547				this.settings.effect = 'slide';
548				previousNav.style.display = 'none';
549				nextNav.style.display = 'none';
550				_addClass(sliderEl, this.settings.classes.touchEnabled);
551
552				_addEvent(sliderEl, 'touchstart', _touch.start.bind(this), false);
553				_addEvent(sliderEl, 'touchmove', _touch.move.bind(this), false);
554				_addEvent(sliderEl, 'touchend', _touch.end.bind(this), false);
555			}
556
557			// Keyboard Navigation
558			if (this.settings.keyboardNav) {
559				_addEvent(document, 'keyup', function(e) {
560					e = e || window.event;
561					var button = (typeof e.which == 'number') ? e.which : e.keyCode;
562					if (button == 37) {
563						if (_hasClass(this._attributes.container, this.settings.classes.animating)) return false;
564						this.stop();
565						this.previousSlide();
566					} else if (button == 39) {
567						if (_hasClass(this._attributes.container, this.settings.classes.animating)) return false;
568						this.stop();
569						this.nextSlide();
570					}
571				}.bind(this));
572			}
573		}
574
575		// Create internal attributes
576		this._attributes = {
577			container: sliderEl,
578			slides: slides,
579			previousSlide: typeof slides[slides.length - 1] !== 'undefined' ? slides[slides.length - 1] : slides[0],
580			currentSlide: slides[0],
581			nextSlide: typeof slides[1] !== 'undefined' ? slides[1] : slides[0],
582			timerId: 0,
583			origChildren: origChildren, // Used in destroy()
584			aspectWidth: 0,
585			aspectHeight: 0
586		};
587
588		// Set height
589		if (_isInteger(this.settings.height)) {
590			this._attributes.container.style.height = this.settings.height + 'px';
591		} else {
592			if (_isInteger(this.settings.initialHeight)) {
593				this._attributes.container.style.height = this.settings.initialHeight + 'px';
594			}
595
596			// If aspect ratio parse and store
597			if (this.settings.height.indexOf(':') > -1) {
598				var aspectRatioParts = this.settings.height.split(':');
599				if (aspectRatioParts.length == 2 && _isInteger(parseInt(aspectRatioParts[0], 10)) && _isInteger(parseInt(aspectRatioParts[1], 10))) {
600					this._attributes.aspectWidth = parseInt(aspectRatioParts[0], 10);
601					this._attributes.aspectHeight = parseInt(aspectRatioParts[1], 10);
602				}
603			}
604
605			_addEvent(window, 'resize', function() {
606				_setContainerHeight(this, false);
607			}.bind(this));
608		}
609
610		// Add classes
611		_addClass(sliderEl, this.settings.classes.container);
612		_addClass(sliderEl, 'iis-effect-' + this.settings.effect);
613		Array.prototype.forEach.call(this._attributes.slides, function(slide, i) {
614			_addClass(slide, this.settings.classes.slide);
615		}.bind(this));
616		_addClass(this._attributes.previousSlide, this.settings.classes.previousSlide);
617		_addClass(this._attributes.currentSlide, this.settings.classes.currentSlide);
618		_addClass(this._attributes.nextSlide, this.settings.classes.nextSlide);
619
620		// ARIA
621		this._attributes.currentSlide.setAttribute('aria-hidden', 'false');
622
623		// Load first image
624		_loadImg(this._attributes.currentSlide, (function() {
625			this.settings.onInit.apply(this);
626			_setContainerHeight(this, false);
627		}).bind(this));
628		// Preload next images
629		_loadImg(this._attributes.previousSlide);
630		_loadImg(this._attributes.nextSlide);
631	};
632
633	Slider.prototype.get = function(attribute) {
634		if (!this._attributes) return null;
635		if (this._attributes.hasOwnProperty(attribute)) {
636			return this._attributes[attribute];
637		}
638	};
639
640	Slider.prototype.set = function(attribute, value) {
641		if (!this._attributes) return null;
642		return (this._attributes[attribute] = value);
643	};
644
645	Slider.prototype.start = function() {
646		if (!this._attributes) return;
647		this._attributes.timerId = setInterval(this.nextSlide.bind(this), this.settings.interval);
648		this.settings.onStart.apply(this);
649
650		// Stop if window blur
651		window.onblur = function() {
652			this.stop();
653		}.bind(this);
654	};
655
656	Slider.prototype.stop = function() {
657		if (!this._attributes) return;
658		clearInterval(this._attributes.timerId);
659		this._attributes.timerId = 0;
660		this.settings.onStop.apply(this);
661	};
662
663	Slider.prototype.previousSlide = function() {
664		this.settings.beforeChange.apply(this);
665		_removeClass(this._attributes.previousSlide, this.settings.classes.previousSlide);
666		_removeClass(this._attributes.currentSlide, this.settings.classes.currentSlide);
667		_removeClass(this._attributes.nextSlide, this.settings.classes.nextSlide);
668		this._attributes.currentSlide.setAttribute('aria-hidden', 'true');
669
670		var slides = this._attributes.slides,
671			index = slides.indexOf(this._attributes.currentSlide);
672		this._attributes.nextSlide = this._attributes.currentSlide;
673		this._attributes.previousSlide = slides[index - 2];
674		this._attributes.currentSlide = slides[index - 1];
675		if (typeof this._attributes.currentSlide === 'undefined' &&
676			typeof this._attributes.previousSlide === 'undefined') {
677			this._attributes.currentSlide = slides[slides.length - 1];
678			this._attributes.previousSlide = slides[slides.length - 2];
679		} else {
680			if (typeof this._attributes.previousSlide === 'undefined') {
681				this._attributes.previousSlide = slides[slides.length - 1];
682			}
683		}
684
685		// Preload next image
686		_loadImg(this._attributes.previousSlide);
687
688		_addClass(this._attributes.previousSlide, this.settings.classes.previousSlide);
689		_addClass(this._attributes.currentSlide, this.settings.classes.currentSlide);
690		_addClass(this._attributes.nextSlide, this.settings.classes.nextSlide);
691		this._attributes.currentSlide.setAttribute('aria-hidden', 'false');
692
693		_addClass(this._attributes.container, this.settings.classes.directionPrevious);
694		_requestTimeout(function() {
695			_removeClass(this._attributes.container, this.settings.classes.directionPrevious);
696		}.bind(this), this.settings.transitionDuration);
697
698		if (this.settings.transitionDuration) {
699			_addClass(this._attributes.container, this.settings.classes.animating);
700			_requestTimeout(function() {
701				_removeClass(this._attributes.container, this.settings.classes.animating);
702			}.bind(this), this.settings.transitionDuration);
703		}
704
705		_setContainerHeight(this);
706		this.settings.afterChange.apply(this);
707	};
708
709	Slider.prototype.nextSlide = function() {
710		this.settings.beforeChange.apply(this);
711		_removeClass(this._attributes.previousSlide, this.settings.classes.previousSlide);
712		_removeClass(this._attributes.currentSlide, this.settings.classes.currentSlide);
713		_removeClass(this._attributes.nextSlide, this.settings.classes.nextSlide);
714		this._attributes.currentSlide.setAttribute('aria-hidden', 'true');
715
716		var slides = this._attributes.slides,
717			index = slides.indexOf(this._attributes.currentSlide);
718		this._attributes.previousSlide = this._attributes.currentSlide;
719		this._attributes.currentSlide = slides[index + 1];
720		this._attributes.nextSlide = slides[index + 2];
721		if (typeof this._attributes.currentSlide === 'undefined' &&
722			typeof this._attributes.nextSlide === 'undefined') {
723			this._attributes.currentSlide = slides[0];
724			this._attributes.nextSlide = slides[1];
725		} else {
726			if (typeof this._attributes.nextSlide === 'undefined') {
727				this._attributes.nextSlide = slides[0];
728			}
729		}
730
731		// Preload next image
732		_loadImg(this._attributes.nextSlide);
733
734		_addClass(this._attributes.previousSlide, this.settings.classes.previousSlide);
735		_addClass(this._attributes.currentSlide, this.settings.classes.currentSlide);
736		_addClass(this._attributes.nextSlide, this.settings.classes.nextSlide);
737		this._attributes.currentSlide.setAttribute('aria-hidden', 'false');
738
739		_addClass(this._attributes.container, this.settings.classes.directionNext);
740		_requestTimeout(function() {
741			_removeClass(this._attributes.container, this.settings.classes.directionNext);
742		}.bind(this), this.settings.transitionDuration);
743
744		if (this.settings.transitionDuration) {
745			_addClass(this._attributes.container, this.settings.classes.animating);
746			_requestTimeout(function() {
747				_removeClass(this._attributes.container, this.settings.classes.animating);
748			}.bind(this), this.settings.transitionDuration);
749		}
750
751		_setContainerHeight(this);
752		this.settings.afterChange.apply(this);
753	};
754
755	Slider.prototype.gotoSlide = function(index) {
756		this.settings.beforeChange.apply(this);
757		this.stop();
758
759		_removeClass(this._attributes.previousSlide, this.settings.classes.previousSlide);
760		_removeClass(this._attributes.currentSlide, this.settings.classes.currentSlide);
761		_removeClass(this._attributes.nextSlide, this.settings.classes.nextSlide);
762		this._attributes.currentSlide.setAttribute('aria-hidden', 'true');
763
764		index--; // Index should be 1-indexed
765		var slides = this._attributes.slides,
766			oldIndex = slides.indexOf(this._attributes.currentSlide);
767		this._attributes.previousSlide = slides[index - 1];
768		this._attributes.currentSlide = slides[index];
769		this._attributes.nextSlide = slides[index + 1];
770		if (typeof this._attributes.previousSlide === 'undefined') {
771			this._attributes.previousSlide = slides[slides.length - 1];
772		}
773		if (typeof this._attributes.nextSlide === 'undefined') {
774			this._attributes.nextSlide = slides[0];
775		}
776
777		// Load images
778		_loadImg(this._attributes.previousSlide);
779		_loadImg(this._attributes.currentSlide);
780		_loadImg(this._attributes.nextSlide);
781
782		_addClass(this._attributes.previousSlide, this.settings.classes.previousSlide);
783		_addClass(this._attributes.currentSlide, this.settings.classes.currentSlide);
784		_addClass(this._attributes.nextSlide, this.settings.classes.nextSlide);
785		this._attributes.currentSlide.setAttribute('aria-hidden', 'false');
786
787		if (index < oldIndex) {
788			_addClass(this._attributes.container, this.settings.classes.directionPrevious);
789			_requestTimeout(function() {
790				_removeClass(this._attributes.container, this.settings.classes.directionPrevious);
791			}.bind(this), this.settings.transitionDuration);
792		} else {
793			_addClass(this._attributes.container, this.settings.classes.directionNext);
794			_requestTimeout(function() {
795				_removeClass(this._attributes.container, this.settings.classes.directionNext);
796			}.bind(this), this.settings.transitionDuration);
797		}
798
799		if (this.settings.transitionDuration) {
800			_addClass(this._attributes.container, this.settings.classes.animating);
801			_requestTimeout(function() {
802				_removeClass(this._attributes.container, this.settings.classes.animating);
803			}.bind(this), this.settings.transitionDuration);
804		}
805
806		_setContainerHeight(this);
807		this.settings.afterChange.apply(this);
808	};
809
810	Slider.prototype.destroy = function() {
811		clearInterval(this._attributes.timerId);
812		this._attributes.timerId = 0;
813
814		this._attributes.container.innerHTML = '';
815		Array.prototype.forEach.call(this._attributes.origChildren, function(child, i) {
816			this._attributes.container.appendChild(child);
817		}.bind(this));
818
819		_removeClass(this._attributes.container, this.settings.classes.container);
820		_removeClass(this._attributes.container, 'iis-effect-' + this.settings.effect);
821		this._attributes.container.style.height = '';
822
823		this.settings.onDestroy.apply(this);
824	};
825
826	return {
827		_hasClass: _hasClass,
828		_addClass: _addClass,
829		_removeClass: _removeClass,
830		Slider: Slider
831	};
832
833})();

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.