PageSourceSearch

https://hocmai.vn/public/home/js/jquery.elastislide.js

js hocmai.vn collected 2026-09-24 09:16:46 UTC 13,622 bytes, 453 lines download raw bytes

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

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.