PageSourceSearch

https://forexrebate.me/assets/js/slider/jquery.ui.rcarousel.js

js forexrebate.me collected 2026-10-07 00:22:17 UTC 21,502 bytes, 800 lines download raw bytes

1(function ($) {
2	$.widget("ui.rcarousel", {
3		_create: function() {
4			var data,
5				$root = $( this.element ),
6				_self = this,
7				options = this.options;
8
9			// if options were default there should be no problem
10            // check if user set options before init: $('element').rcarousel({with: "foo", visible: 3});
11            // in above example exception will be thrown because 'with' should be a number!
12            this._checkOptionsValidity( this.options );
13
14			// for every carousel create a data object and keeps it in the element
15			this._createDataObject();
16			data = $root.data( "data" );
17
18			// create wrapper inside root element; this is needed for animating
19			$root
20				.addClass( "ui-carousel" )
21				.children()
22				.wrapAll( "<div class='wrapper'></div>" );
23			
24			// save all children of root element in ‘paths’ array
25			this._saveElements();
26
27			// make pages using paginate algorithm
28			this._generatePages();		
29			
30			this._loadElements();
31				
32			this._setCarouselWidth();
33			this._setCarouselHeight();
34			
35			// handle default event handlers
36			$( options.navigation.next ).click(
37				function( event ) {
38					_self.next();
39					event.preventDefault();
40				}
41			);
42			
43			$( options.navigation.prev ).click(
44				function( event ) {
45					_self.prev();
46					event.preventDefault();
47				}
48			);			
49			
50			data.navigation.next = $( options.navigation.next );
51			data.navigation.prev = $( options.navigation.prev );
52			
53			// stop on hover feature
54			$root.hover(
55				function() {
56					if ( options.auto.enabled ) {
57						clearInterval( data.interval );
58						data.hoveredOver = true;
59					}
60				},
61				function() {
62					if ( options.auto.enabled ) {
63						data.hoveredOver = false;
64						_self._autoMode( options.auto.direction );
65					}
66				}
67			);
68			
69			this._setStep();
70			
71			// if auto mode is enabled run it
72			if ( options.auto.enabled ) {
73				this._autoMode( options.auto.direction );
74			}
75			
76			// broadcast event
77			this._trigger( "start" );
78		},
79		
80		_addElement: function( jQueryElement, direction ) {
81			var $root = $( this.element ),
82				$content = $root.find( "div.wrapper" ),
83				options = this.options;
84
85			jQueryElement
86				.width( options.width )
87				.height( options.height );
88				
89			if ( options.orientation === "horizontal" ) {
90				$( jQueryElement ).css( "marginRight", options.margin );
91			} else {
92				$( jQueryElement ).css({
93					marginBottom: options.margin,
94					"float": "none"
95				});
96			}
97			
98			if ( direction === "prev" ) {
99				
100				// clone event handlers and data as well
101				$content.prepend( jQueryElement.clone(true, true) );
102			} else {
103				$content.append( jQueryElement.clone(true, true) );
104			}			
105		},
106		
107		append: function( jqElements ) {
108			var $root = $( this.element ),
109				data = $root.data( "data" );
110				
111			// add new elements
112			jqElements.each(
113				function( i, el ) {
114					data.paths.push( $(el) );
115				}
116			);
117			
118			data.oldPage = data.pages[data.oldPageIndex].slice(0);
119			data.appended = true;
120			
121			// rebuild pages
122			this._generatePages();
123		},
124		
125		_autoMode: function( direction ) {
126			var options = this.options,
127				data = $( this.element ).data( "data" );
128
129			if ( direction === "next" ) {
130				data.interval = setTimeout( $.proxy(this.next, this), options.auto.interval );
131			} else {
132				data.interval = setTimeout( $.proxy(this.prev, this), options.auto.interval );
133			}
134		},
135		
136		_checkOptionsValidity: function( options ) {
137			var i,
138				self = this,
139				_correctSteps = "";
140			
141			// for every element in options object check its validity
142			$.each(options,
143				function( key, value ) {
144
145					switch ( key ) {
146						case "visible":
147							// visible should be a positive integer
148							if ( !value || typeof value !== "number" || value <= 0 || (Math.ceil(value) - value > 0) ) {
149								throw new Error( "visible should be defined as a positive integer" );
150							}
151							break;
152	
153						case "step":
154							if ( !value || typeof value !== "number" || value <= 0 || (Math.ceil(value) - value > 0) ) {
155								throw new Error( "step should be defined as a positive integer" );
156							} else if ( value > self.options.visible )  {
157								// for example for visible: 3 the following array of values for 'step' is valid
158								// 3 <= step >= 1 by 1 ==> [1,2,3]
159								// output correct values
160								for ( i = 1; i <= Math.floor(options.visible); i++ ) {
161									_correctSteps += ( i < Math.floor(value) ) ? i + ", " : i;
162								}
163								
164								throw new Error( "Only following step values are correct: " + _correctSteps );
165							}
166							break;
167	
168						case "width":
169							// width & height is defined by default so you can omit them to some extent
170							if ( !value || typeof value !== "number" || value <= 0 || Math.ceil(value) - value > 0 ) {
171								throw new Error( "width should be defined as a positive integer" );
172							}
173							break;
174		
175						case "height":
176							if ( !value || typeof value !== "number" || value <= 0 || Math.ceil(value) - value > 0 ) {
177								throw new Error("height should be defined as a positive integer");
178							}
179							break;
180		
181						case "speed":
182							if ( !value && value !== 0 ) {
183								throw new Error("speed should be defined as a number or a string");
184							}
185		
186							if ( typeof value === "number" && value < 0 ) {
187								throw new Error( "speed should be a positive number" );
188							} else if ( typeof value === "string" && !(value === "slow" || value === "normal" || value === "fast") ) {
189								throw new Error( 'Only "slow", "normal" and "fast" values are valid' );
190							}
191							break;
192		
193						case "navigation":
194							if ( !value || $.isPlainObject(value) === false ) {
195								throw new Error( "navigation should be defined as an object with at least one of the properties: 'prev' or 'next' in it");
196							}
197		
198							if ( value.prev && typeof value.prev !== "string" ) {
199								throw new Error( "navigation.prev should be defined as a string and point to '.class' or '#id' of an element" );
200							}
201		
202							if ( value.next && typeof value.next !== "string" ) {
203								throw new Error(" navigation.next should be defined as a string and point to '.class' or '#id' of an element" );
204							}
205							break;
206		
207						case "auto":
208							if ( typeof value.direction !== "string" ) {
209								throw new Error( "direction should be defined as a string" );
210							}
211		
212							if ( !(value.direction === "next" || value.direction === "prev") ) {
213								throw new Error( "direction: only 'right' and 'left' values are valid" );
214							}
215		
216							if ( isNaN(value.interval) || typeof value.interval !== "number" || value.interval < 0 || Math.ceil(value.interval) - value.interval > 0 ) {
217								throw new Error( "interval should be a positive number" );
218							}
219							break;
220		
221						case "margin":
222							if ( isNaN(value) || typeof value !== "number" || value < 0 || Math.ceil(value) - value > 0 ) {
223								throw new Error( "margin should be a positive number" );
224							}
225							break;
226						}
227				}
228			);
229		},
230		
231		_createDataObject: function() {
232			var $root = $( this.element );
233
234			$root.data("data",
235				{
236					paths: [],
237					pathsLen: 0,
238					pages: [],
239					lastPage: [],
240					oldPageIndex: 0,
241					pageIndex: 0,
242					navigation: {},
243					animated: false,
244					appended: false,
245					hoveredOver: false
246				}
247			);
248		},
249		
250		_generatePages: function() {
251			var self = this,
252				options = this.options,
253				data = $( this.element ).data( "data" ),
254				_visible = options.visible,
255				_pathsLen = data.paths.length;
256				
257			// having 10 elements: A, B, C, D, E, F, G, H, I, J the algorithm
258			// creates 3 pages for ‘visible: 5’ and ‘step: 4’:
259			// [ABCDE], [EFGHI], [FGHIJ]
260
261			function _init() {
262				// init creates the last page [FGHIJ] and remembers it
263
264				data.pages = [];
265				data.lastPage = [];
266				data.pages[0] = [];
267
268				// init last page
269				for ( var i = _pathsLen - 1; i >= _pathsLen - _visible; i-- ) {
270					data.lastPage.unshift( data.paths[i] );
271				}
272				
273				// and first page
274				for ( var i = 0; i < _visible; i++ ) {
275					data.pages[0][data.pages[0].length] = data.paths[i];
276				}				
277			}
278
279			function _islastPage( page ) {
280				var _isLast = false;
281
282				for ( var i = 0; i < data.lastPage.length; i++ ) {
283					if ( data.lastPage[i].get(0) === page[i].get(0) ) {
284						_isLast = true;
285					} else {
286						_isLast = false;
287						break;
288					}
289				}
290				
291				return _isLast;
292			}
293
294			function _append( start, end, atIndex ) {
295				var _index = atIndex || data.pages.length;
296
297				if ( !atIndex ) {
298					data.pages[_index] = [];
299				}
300
301				for ( var i = start; i < end; i++ ) {
302					data.pages[_index].push( data.paths[i] );
303				}
304				return _index;
305			}
306
307			function _paginate() {
308				var _isBeginning = true,
309					_complement = false,
310					_start = options.step,
311					_end, _index, _oldFirstEl, _oldLastEl;
312
313				// continue until you reach the last page
314				// we start from the 2nd page (1st page has been already initiated)
315				while ( !_islastPage(data.pages[data.pages.length - 1]) || _isBeginning ) {
316					_isBeginning = false;
317
318					_end = _start + _visible;
319
320					// we cannot exceed _pathsLen
321					if ( _end > _pathsLen ) {
322						_end = _pathsLen;
323					}
324					
325					// when we run ouf of elements (_end - _start < _visible) we must add the difference at the begining
326					// in our example the 3rd page is [FGHIJ] and J element is added in the second step
327					// first we add [FGHI] as old elements
328					// we must assure that we have always ‘visible’ (5 in our example) elements
329					if ( _end - _start < _visible ) {
330						_complement = true;
331					} else {
332						_complement = false;
333					}
334
335					if ( _complement ) {
336						
337						// first add old elemets; for 3rd page it adds [FGHI…]
338						// remember the page we add to (_index)
339						_oldFirstEl = _start - ( _visible - (_end - _start) );
340						_oldLastEl = _oldFirstEl + ( _visible - (_end - _start) );
341						_index = _append( _oldFirstEl, _oldLastEl );
342						
343						// then add new elements; for 3th page it is J element:
344						// [fghiJ]
345						_append( _start, _end, _index );
346
347					} else {
348						
349						// normal pages like [ABCDE], [EFGHI]
350						_append( _start, _end );
351						
352						// next step
353						_start += options.step;
354					}
355				}
356			}
357
358			// go!
359			_init();
360			_paginate();
361		},
362		
363		getCurrentPage: function() {
364			var data = $( this.element ).data( "data" );
365			return data.pageIndex + 1;
366		},
367		
368		getTotalPages: function() {
369			var data = $( this.element ).data( "data" );
370			return data.pages.length;
371		},
372		
373		goToPage: function( page ) {
374			var	_by,
375				data = $( this.element ).data( "data" );
376
377			if ( !data.animated && page !== data.pageIndex ) {
378				data.animated = true;
379
380				if ( page > data.pages.length - 1 ) {
381					page = data.pages.length - 1;
382				} else if ( page < 0 ) {
383					page = 0;
384				}
385				
386				data.pageIndex = page;
387				_by = page - data.oldPageIndex;
388				
389				if ( _by >= 0 ) {
390					//move by n elements from current index
391					this._goToNextPage( _by );
392				} else {
393					this._goToPrevPage( _by );
394				}
395				
396				data.oldPageIndex = page;
397			}
398		},
399		
400		_loadElements: function(elements, direction) {
401			var options = this.options,
402				data = $( this.element ).data( "data" ),
403				_dir = direction || "next",
404				_elem = elements || data.pages[options.startAtPage],
405				_start = 0,
406				_end = _elem.length;
407
408			if ( _dir === "next" ) {
409				for ( var i = _start; i < _end; i++ ) {
410					this._addElement( _elem[i], _dir );
411				}
412			} else {
413				for ( var i = _end - 1; i >= _start; i-- ) {
414					this._addElement( _elem[i], _dir );
415				}
416			}
417		},
418		
419		_goToPrevPage: function( by ) {
420			var _page, _oldPage, _dist, _index, _animOpts, $lastEl, _unique, _pos, _theSame,
421				$root = $( this.element ),
422				self = this,
423				options = this.options,
424				data = $( this.element ).data( "data" );
425
426			// pick pages
427			if ( data.appended ) {
428				_oldPage = data.oldPage;
429			} else {				
430				_oldPage = data.pages[data.oldPageIndex];
431			}
432			
433			_index = data.oldPageIndex + by;			
434			_page = data.pages[_index].slice( 0 );
435
436			// For example, the first time widget was initiated there were 5
437			// elements: A, B, C, D, E and 3 pages for visible 2 and step 2:
438			// AB, CD, DE. Then a user loaded next 5 elements so there were
439			// 10 already: A, B, C, D, E, F, G, H, I, J and 5 pages:
440			// AB, CD, EF, GH and IJ. If the other elemets were loaded when
441			// CD page was shown (from 5 elements) ‘_theSame’ is true because
442			// we compare the same
443			// pages, that is, the 2nd page from 5 elements and the 2nd from
444			// 10 elements. Thus what we do next is to decrement the index and
445			// loads the first page from 10 elements.			
446			$( _page ).each(
447				function( i, el ) {
448					if ( el.get(0) === $(_oldPage[i]).get(0) ) {
449						_theSame = true;
450					} else {
451						_theSame = false;
452					}
453				}
454			);
455			
456			if ( data.appended && _theSame ) {
457				if ( data.pageIndex === 0 ) {
458					_index = data.pageIndex = data.pages.length - 1;
459				} else {
460					_index = --data.pageIndex;
461				}
462				
463				_page = data.pages[_index].slice( 0 );
464			}			
465
466			// check if last element from _page appears in _oldPage
467			// for [ABCDFGHIJ] elements there are 3 pages for ‘visible’ = 6 and
468			// ‘step’ = 2: [ABCDEF], [CDEFGH] and [EFGHIJ]; going from the 3rd
469			// to the 2nd page we only loads 2 elements: [CD] because all
470			// remaining were loaded already
471			$lastEl = _page[_page.length - 1].get( 0 );
472			for ( var i = _oldPage.length - 1; i >= 0; i-- ) {
473				if ( $lastEl === $(_oldPage[i]).get(0) ) {
474					_unique = false;
475					_pos = i;
476					break;
477				} else {
478					_unique = true;
479				}
480			}
481
482			if ( !_unique ) {
483				while ( _pos >= 0 ) {
484					if ( _page[_page.length - 1].get(0) === _oldPage[_pos].get(0) ) {
485						// this element is unique
486						_page.pop();
487					}
488					--_pos;
489				}
490			}			
491
492			// load new elements
493			self._loadElements( _page, "prev" );
494
495			// calculate the distance
496			_dist = options.width * _page.length + ( options.margin * _page.length );
497
498			if (options.orientation === "horizontal") {
499				_animOpts = {scrollLeft: 0};
500				$root.scrollLeft( _dist );
501			} else {
502				_animOpts = {scrollTop: 0};
503				$root.scrollTop( _dist );
504			}
505
506			$root
507				.animate(_animOpts, options.speed, function () {
508					self._removeOldElements( "last", _page.length );
509					data.animated = false;
510
511					if ( !data.hoveredOver && options.auto.enabled ) {
512						// if autoMode is on and you change page manually
513						clearInterval( data.interval );
514						
515						self._autoMode( options.auto.direction );
516					}
517
518					// scrolling is finished, send an event
519					self._trigger("pageLoaded", null, {page: _index});
520				});
521				
522			// reset to deafult
523			data.appended = false;				
524		},
525		
526		_goToNextPage: function( by ) {
527			var _page, _oldPage, _dist, _index, _animOpts, $firstEl, _unique, _pos, _theSame,
528				$root = $( this.element ),
529				options = this.options,
530				data = $root.data( "data" ),				
531				self = this;
532
533			// pick pages
534			if ( data.appended ) {
535				_oldPage = data.oldPage;
536			} else {				
537				_oldPage = data.pages[data.oldPageIndex];
538			}
539			
540			_index = data.oldPageIndex + by;			
541			_page = data.pages[_index].slice( 0 );
542			
543			// For example, the first time widget was initiated there were 5
544			// elements: A, B, C, D, E and 2 pages for visible 4 and step 3:
545			// ABCD and BCDE. Then a user loaded next 5 elements so there were
546			// 10 already: A, B, C, D, E, F, G, H, I, J and 3 pages:
547			// ABCD, DEFG and GHIJ. If the other elemets were loaded when
548			// ABCD page was shown (from 5 elements) ‘_theSame’ is true because
549			// we compare the same
550			// pages, that is, the first pages from 5 elements and the first from
551			// 10 elements. Thus what we do next is to increment the index and
552			// loads the second page from 10 elements.
553			$( _page ).each(
554				function( i, el ) {
555					if ( el.get(0) === $(_oldPage[i]).get(0) ) {
556						_theSame = true;
557					} else {
558						_theSame = false;
559					}
560				}
561			);
562	
563			if ( data.appended && _theSame ) {
564				_page = data.pages[++data.pageIndex].slice( 0 );
565			}
566
567			// check if 1st element from _page appears in _oldPage
568			// for [ABCDFGHIJ] elements there are 3 pages for ‘visible’ = 6 and
569			// ‘step’ = 2: [ABCDEF], [CDEFGH] and [EFGHIJ]; going from the 2nd
570			// to the 3rd page we only loads 2 elements: [IJ] because all
571			// remaining were loaded already
572			$firstEl = _page[0].get( 0 );
573			for ( var i = 0; i < _page.length; i++) {
574				if ( $firstEl === $(_oldPage[i]).get(0) ) {
575					_unique = false;
576					_pos = i;
577					break;
578				} else {
579					_unique = true;
580				}
581			}
582
583			if ( !_unique ) {
584				while ( _pos < _oldPage.length ) {
585					if ( _page[0].get(0) === _oldPage[_pos].get(0) ) {
586						_page.shift();
587					}
588					++_pos;
589				}
590			}
591			
592			// load new elements			
593			this._loadElements( _page, "next" );
594
595			// calculate the distance
596			_dist = options.width * _page.length + ( options.margin * _page.length );
597			
598			if ( options.orientation === "horizontal" ) {
599				_animOpts = {scrollLeft: "+=" + _dist};
600			} else {
601				_animOpts = {scrollTop: "+=" + _dist};
602			}
603			
604			$root
605				.animate(_animOpts, options.speed, function() {
606					self._removeOldElements( "first", _page.length );
607					
608					if ( options.orientation === "horizontal" ) {
609						$root.scrollLeft( 0 );
610					} else {
611						$root.scrollTop( 0 );
612					}
613					
614					data.animated = false;
615
616					if ( !data.hoveredOver && options.auto.enabled ) {
617						// if autoMode is on and you change page manually
618						clearInterval( data.interval );
619						
620						self._autoMode( options.auto.direction );
621					}
622
623					// scrolling is finished, send an event
624					self._trigger( "pageLoaded", null, {page: _index});
625
626			});
627				
628			// reset to deafult
629			data.appended = false;
630		},
631		
632		next: function() {
633			var	options = this.options,
634				data = $( this.element ).data( "data" );
635
636			if ( !data.animated ) {
637				data.animated = true;
638				
639				if ( !data.appended  ) {
640					++data.pageIndex;
641				}				
642				
643				if ( data.pageIndex > data.pages.length - 1 ) {
644					data.pageIndex = 0;
645				}
646
647				// move by one element from current index
648				this._goToNextPage( data.pageIndex - data.oldPageIndex );
649				data.oldPageIndex = data.pageIndex;
650			}
651		},
652		
653		prev: function() {
654			var	options = this.options,
655				data = $( this.element ).data( "data" );
656
657			if ( !data.animated ) {
658				data.animated = true;
659
660				if ( !data.appended ) {
661					--data.pageIndex;
662				}
663				
664				if ( data.pageIndex < 0 ) {
665					data.pageIndex = data.pages.length - 1;
666				}
667
668				// move left by one element from current index
669				this._goToPrevPage( data.pageIndex - data.oldPageIndex );
670				data.oldPageIndex = data.pageIndex;
671			}
672		},
673		
674		_removeOldElements: function(position, length) {
675			// remove 'step' elements
676			var	$root = $( this.element );
677
678			for ( var i = 0; i < length; i++ ) {
679				if ( position === "first" ) {
680					$root
681						.find( "div.wrapper" )
682							.children()
683							.first()
684							.remove();
685				} else {
686					$root
687						.find( "div.wrapper" )
688							.children()
689							.last()
690							.remove();
691				}
692			}
693		},
694		
695		_saveElements: function() {
696			var $el,
697				$root = $( this.element ),
698				$elements = $root.find( "div.wrapper" ).children(),
699				data = $root.data( "data" );
700				
701			$elements.each(
702				function( i, el ) {
703					$el = $( el );
704					
705					// keep element’s data and events
706					data.paths.push( $el.clone(true, true) );
707					$el.remove();
708				}
709			);		
710		},
711		
712		_setOption: function( key, value ) {
713			var _newOptions,
714				options = this.options,
715				data = $( this.element ).data( "data" );
716
717			switch (key) {
718				case "speed":
719					this._checkOptionsValidity({speed: value});
720					options.speed = value;
721					$.Widget.prototype._setOption.apply( this, arguments );
722					break;
723	
724				case "auto":
725					_newOptions = $.extend( options.auto, value );
726					this._checkOptionsValidity({auto: _newOptions});
727	
728					if ( options.auto.enabled ) {
729						this._autoMode( options.auto.direction );
730					}
731				}
732
733		},
734		_setStep: function(s) {
735			// calculate a step
736			var _step,
737				options = this.options,
738				data = $( this.element ).data( "data" );
739
740			_step = s || options.step;
741
742			options.step = _step;
743			data.step = options.width * _step;
744		},
745		
746		_setCarouselHeight: function() {
747			var _newHeight,
748				$root = $( this.element ),
749				data = $( this.element ).data( "data" ),			
750				options = this.options;
751
752			if ( options.orientation === "vertical" ) {
753				_newHeight = options.visible * options.height + options.margin * (options.visible - 1);
754			} else {
755				_newHeight = options.height;
756			}
757
758			$root.height(_newHeight);
759		},
760		
761		_setCarouselWidth: function() {
762			var _newWidth,
763				$root = $( this.element ),
764				options = this.options,
765				data = $( this.element ).data( "data" );
766
767			if ( options.orientation === "horizontal" ) {
768				_newWidth = options.visible * options.width + options.margin * (options.visible - 1);
769			} else {
770				_newWidth = options.width;
771			}
772
773			// set carousel width and disable overflow: auto
774			$root.css({
775				width: _newWidth,
776				overflow: "hidden"
777			});
778		},
779		
780		options: {
781			visible: 3,
782			step: 3,
783			width: 100,
784			height: 100,
785			speed: 1000,
786			margin: 0,
787			orientation: "horizontal",
788			auto: {
789				enabled: false,
790				direction: "next",
791				interval: 5000
792			},
793			startAtPage: 0,
794			navigation: {
795				next: "#ui-carousel-next",
796				prev: "#ui-carousel-prev"
797			}
798		}
799	});
800}(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.