PageSourceSearch

https://www.thebatman.com/js/jquery.elastislide.js

js thebatman.com collected 2026-10-02 08:13:44 UTC 13,142 bytes, 472 lines download raw bytes

1$(function () {
2	
3
4
5	// http://www.netcu.de/jquery-touchwipe-iphone-ipad-library
6	$.fn.touchwipe = function (settings) {
7
8		var config = {
9			min_move_x: 20,
10			min_move_y: 20,
11			wipeLeft: function () {},
12			wipeRight: function () {},
13			wipeUp: function () {},
14			wipeDown: function () {},
15			preventDefaultEvents: true
16		};
17
18		if (settings) $.extend(config, settings);
19
20		this.each(function () {
21			var startX;
22			var startY;
23			var isMoving = false;
24
25			function cancelTouch() {
26				this.removeEventListener('touchmove', onTouchMove);
27				startX = null;
28				isMoving = false;
29			}
30
31			function onTouchMove(e) {
32				if (config.preventDefaultEvents) {
33					e.preventDefault();
34				}
35				if (isMoving) {
36					var x = e.touches[0].pageX;
37					var y = e.touches[0].pageY;
38					var dx = startX - x;
39					var dy = startY - y;
40					if (Math.abs(dx) >= config.min_move_x) {
41						cancelTouch();
42						if (dx > 0) {
43							config.wipeLeft();
44						} else {
45							config.wipeRight();
46						}
47					} else if (Math.abs(dy) >= config.min_move_y) {
48						cancelTouch();
49						if (dy > 0) {
50							config.wipeDown();
51						} else {
52							config.wipeUp();
53						}
54					}
55				}
56			}
57
58			function onTouchStart(e) {
59				if (e.touches.length == 1) {
60					startX = e.touches[0].pageX;
61					startY = e.touches[0].pageY;
62					isMoving = true;
63					this.addEventListener('touchmove', onTouchMove, false);
64				}
65			}
66			if ('ontouchstart' in document.documentElement) {
67				this.addEventListener('touchstart', onTouchStart, false);
68			}
69		});
70
71		return this;
72	};
73
74	$.elastislide = function (options, element) {
75		this.$el = $(element);
76		this._init(options);
77	};
78
79	$.elastislide.defaults = {
80		speed: 450, // animation speed
81		easing: '', // animation easing effect
82		imageW: 280, // the images width
83		margin: 3, // image margin right
84		border: 2, // image border
85		minItems: 1, // the minimum number of items to show. 
86		// when we resize the window, this will make sure minItems are always shown 
87		// (unless of course minItems is higher than the total number of elements)
88		current: 0, // index of the current item
89		// when we resize the window, the carousel will make sure this item is visible 
90		onClick: function () {
91				return false;
92			} // click item callback
93	};
94
95	$.elastislide.prototype = {
96		_init: function (options) {
97
98			this.options = $.extend(true, {}, $.elastislide.defaults, options);
99
100			// <ul>
101			this.$slider = this.$el.find('ul');
102
103			// <li>
104			this.$items = this.$slider.children('li');
105
106			// total number of elements / images
107			this.itemsCount = this.$items.length;
108
109			// cache the <ul>'s parent, since we will eventually need to recalculate its width on window resize
110			this.$esCarousel = this.$slider.parent();
111
112			// validate options
113			this._validateOptions();
114
115			// set sizes and initialize some vars...
116			this._configure();
117
118			// add navigation buttons
119			this._addControls();
120
121			// initialize the events
122			this._initEvents();
123
124			// show the <ul>
125			this.$slider.show();
126
127			// slide to current's position
128			this._slideToCurrent(false);
129
130		},
131		_validateOptions: function () {
132
133			if (this.options.speed < 0)
134				this.options.speed = 450;
135			if (this.options.margin < 0)
136				this.options.margin = 4;
137			if (this.options.border < 0)
138				this.options.border = 1;
139			if (this.options.minItems < 1 || this.options.minItems > this.itemsCount)
140				this.options.minItems = 1;
141			if (this.options.current > this.itemsCount - 1)
142				this.options.current = 0;
143
144		},
145		_configure: function () {
146
147			// current item's index
148			this.current = this.options.current;
149
150			// the ul's parent's (div.es-carousel) width is the "visible" width
151			this.visibleWidth = this.$esCarousel.width();
152		
153
154			// test to see if we need to initially resize the items
155			if (this.visibleWidth < this.options.minItems * (this.options.imageW + 2 * this.options.border) + (this.options.minItems - 1) * this.options.margin) {
156				this._setDim((this.visibleWidth - (this.options.minItems - 1) * this.options.margin) / this.options.minItems);
157				this._setCurrentValues();
158				// how many items fit with the current width
159				this.fitCount = this.options.minItems;
160			} else {
161				this._setDim();
162				this._setCurrentValues();
163			}
164
165			// set the <ul> width
166			this.$slider.css({
167				width: this.sliderW
168			});
169
170		},
171		_setDim: function (elW) {
172
173			// <li> style
174			this.$items.css({
175				marginRight: this.options.margin,
176				width: (elW) ? elW : this.options.imageW + 2 * this.options.border
177			}).children('a').css({ // <a> style
178				borderWidth: this.options.border
179			});
180
181		},
182		_setCurrentValues: function () {
183
184			// the total space occupied by one item
185			this.itemW = this.$items.outerWidth(true);
186
187			// total width of the slider / <ul>
188			// this will eventually change on window resize
189			this.sliderW = this.itemW * this.itemsCount;
190
191			// the ul parent's (div.es-carousel) width is the "visible" width
192			this.visibleWidth = this.$esCarousel.width();
193
194			// how many items fit with the current width
195			this.fitCount = Math.floor(this.visibleWidth / this.itemW);
196
197		},
198		_addControls: function () {
199
200			/*this.$navNext = $('<span class="es-nav-next">Next</span>');
201			this.$navPrev = $('<span class="es-nav-prev">Previous</span>');
202			$('<div class="es-nav"/>')
203				.append(this.$navPrev)
204				.append(this.$navNext)
205				.appendTo(this.$el);*/
206			this.$navNext = $('<div class="es-nav-next"><img src="images/icons/right-arrow-thumb.png" alt="Previous"/></div>');
207			this.$navPrev = $('<div class="es-nav-prev"><img src="images/icons/left-arrow-thumb.png" alt="Next"/></div>');
208			$('<div class="es-nav"/>')
209				.append(this.$navPrev)
210				.append(this.$navNext)
211				.appendTo(this.$el);
212
213			//this._toggleControls();
214
215		},
216		_toggleControls: function (dir, status) {
217
218			// show / hide navigation buttons
219			if (dir && status) {
220				if (status === 1)
221					(dir === 'right') ? this.$navNext.show() : this.$navPrev.show();
222				else
223					(dir === 'right') ? this.$navNext.hide() : this.$navPrev.hide();
224			} else if (this.current === this.itemsCount - 1 || this.fitCount >= this.itemsCount)
225				this.$navNext.hide();
226
227		},
228		_initEvents: function () {
229
230			var instance = this;
231
232			// window resize
233			$(window).on('resize.elastislide', function (event) {
234
235				instance._reload();
236
237				// slide to the current element
238				clearTimeout(instance.resetTimeout);
239				instance.resetTimeout = setTimeout(function () {
240					instance._slideToCurrent();
241				}, 200);
242
243			});
244
245			// navigation buttons events
246			this.$navNext.on('click.elastislide', function (event) {
247				instance._slide('right');
248			});
249
250			this.$navPrev.on('click.elastislide', function (event) {
251				instance._slide('left');
252			});
253
254			// item click event
255			this.$slider.on('click.elastislide', 'li', function (event) {
256				instance.options.onClick($(this));
257				return false;
258			});
259
260			// touch events
261			instance.$slider.touchwipe({
262				wipeLeft: function () {
263					instance._slide('right');
264				},
265				wipeRight: function () {
266					instance._slide('left');
267				}
268			});
269
270		},
271		reload: function (callback) {
272			this._reload();
273			if (callback) callback.call();
274
275		},
276		_reload: function () {
277
278			var instance = this;
279
280			// set values again
281			instance._setCurrentValues();
282
283			// need to resize items
284			if (instance.visibleWidth < instance.options.minItems * (instance.options.imageW + 2 * instance.options.border) + (instance.options.minItems - 1) * instance.options.margin) {
285				instance._setDim((instance.visibleWidth - (instance.options.minItems - 1) * instance.options.margin) / instance.options.minItems);
286				instance._setCurrentValues();
287				instance.fitCount = instance.options.minItems;
288			} else {
289				instance._setDim();
290				instance._setCurrentValues();
291			}
292
293			instance.$slider.css({
294				width: instance.sliderW + 10 // TODO: +10px seems to solve a firefox "bug" :S
295			});
296
297		},
298		_slide: function (dir, val, anim, callback) {
299
300			// if animating return
301			//if( this.$slider.is(':animated') )
302			//return false;
303
304			// current margin left
305			var ml = parseFloat(this.$slider.css('margin-left'));
306
307			// val is just passed when we want an exact value for the margin left (used in the _slideToCurrent function)
308			if (val === undefined) {
309
310				// how much to slide?
311				var amount = this.fitCount * this.itemW,
312					val;
313
314				if (amount < 0) return false;
315
316				// make sure not to leave a space between the last item / first item and the end / beggining of the slider available width
317				if (dir === 'right' && this.sliderW - (Math.abs(ml) + amount) < this.visibleWidth) {
318					amount = this.sliderW - (Math.abs(ml) + this.visibleWidth) - this.options.margin; // decrease the margin left
319					// show / hide navigation buttons
320					this._toggleControls('right', -1);
321					this._toggleControls('left', 1);
322				} else if (dir === 'left' && Math.abs(ml) - amount < 0) {
323					amount = Math.abs(ml);
324					// show / hide navigation buttons
325					this._toggleControls('left', -1);
326					this._toggleControls('right', 1);
327				} else {
328					var fml; // future margin left
329					(dir === 'right') ?
330					fml = Math.abs(ml) + this.options.margin + Math.abs(amount): fml = Math.abs(ml) - this.options.margin - Math.abs(amount);
331
332					// show / hide navigation buttons
333					if (fml > 0)
334						this._toggleControls('left', 1);
335					else
336						this._toggleControls('left', -1);
337
338					if (fml < this.sliderW - this.visibleWidth)
339						this._toggleControls('right', 1);
340					else
341						this._toggleControls('right', -1);
342
343				}
344
345				(dir === 'right') ? val = '-=' + amount: val = '+=' + amount
346
347			} else {
348				var fml = Math.abs(val); // future margin left
349
350				if (Math.max(this.sliderW, this.visibleWidth) - fml < this.visibleWidth) {
351					val = -(Math.max(this.sliderW, this.visibleWidth) - this.visibleWidth);
352					if (val !== 0)
353						val += this.options.margin; // decrease the margin left if not on the first position
354
355					// show / hide navigation buttons
356					this._toggleControls('right', -1);
357					fml = Math.abs(val);
358				}
359
360				// show / hide navigation buttons
361				if (fml > 0)
362					this._toggleControls('left', 1);
363				else
364					this._toggleControls('left', -1);
365
366				if (Math.max(this.sliderW, this.visibleWidth) - this.visibleWidth > fml + this.options.margin)
367					this._toggleControls('right', 1);
368				else
369					this._toggleControls('right', -1);
370
371			}
372
373			$.fn.applyStyle = (anim === undefined) ? $.fn.animate : $.fn.css;
374
375			var sliderCSS = {
376				marginLeft: val
377			};
378
379			var instance = this;
380
381			this.$slider.stop().applyStyle(sliderCSS, $.extend(true, [], {
382				duration: this.options.speed,
383				easing: this.options.easing,
384				complete: function () {
385					if (callback) callback.call();
386				}
387			}));
388
389		},
390		_slideToCurrent: function (anim) {
391
392			// how much to slide?
393			var amount = this.current * this.itemW;
394			this._slide('', -amount, anim);
395
396		},
397		add: function ($newelems, callback) {
398
399			// adds new items to the carousel
400			this.$items = this.$items.add($newelems);
401			this.itemsCount = this.$items.length;
402			this._setDim();
403			this._setCurrentValues();
404			this.$slider.css({
405				width: this.sliderW
406			});
407			this._slideToCurrent();
408
409			if (callback) callback.call($newelems);
410
411		},
412		setCurrent: function (idx, callback) {
413
414			this.current = idx;
415
416			var ml = Math.abs(parseFloat(this.$slider.css('margin-left'))),
417				posR = ml + this.visibleWidth,
418				fml = Math.abs(this.current * this.itemW);
419
420			if (fml + this.itemW > posR || fml < ml) {
421				this._slideToCurrent();
422			}
423
424			if (callback) callback.call();
425
426		},
427		destroy: function (callback) {
428
429			this._destroy(callback);
430
431		},
432		_destroy: function (callback) {
433			this.$el.off('.elastislide').removeData('elastislide');
434			$(window).off('.elastislide');
435			if (callback) callback.call();
436		}
437	};
438
439	var logError = function (message) {
440		if (this.console) {
441			console.error(message);
442		}
443	};
444
445	$.fn.elastislide = function (options) {
446		if (typeof options === 'string') {
447			var args = Array.prototype.slice.call(arguments, 1);
448
449			this.each(function () {
450				var instance = $.data(this, 'elastislide');
451				if (!instance) {
452					logError("cannot call methods on elastislide prior to initialization; " +
453						"attempted to call method '" + options + "'");
454					return;
455				}
456				if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
457					logError("no such method '" + options + "' for elastislide instance");
458					return;
459				}
460				instance[options].apply(instance, args);
461			});
462		} else {
463			this.each(function () {
464				var instance = $.data(this, 'elastislide');
465				if (!instance) {
466					$.data(this, 'elastislide', new $.elastislide(options, this));
467				}
468			});
469		}
470		return this;
471	};
472});

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.