PageSourceSearch

https://shtory-spb.ru/wp-content/themes/classic/js/jquery.roundabout.js

js shtory-spb.ru collected 2026-10-04 20:56:44 UTC 19,672 bytes, 523 lines download raw bytes

1jQuery.extend({
2	roundabout_shape: {
3		def: 'lazySusan',
4		lazySusan: function(r, a, t) {
5			return {
6				x: Math.sin(r + a), 
7				y: (Math.sin(r + 3*Math.PI/2 + a) / 8) * t, 
8				z: (Math.cos(r + a) + 1) / 2,
9				scale: (Math.sin(r + Math.PI/2 + a) / 2) + 0.5
10			};
11		}
12	}
13});
14
15jQuery.fn.roundabout = function() {
16	var options = (typeof arguments[0] != 'object') ? {} : arguments[0];
17
18	// set options and fill in defaults
19	options = {
20		bearing: (typeof options.bearing == 'undefined') ? 0.0 : jQuery.roundabout_toFloat(options.bearing % 360.0),
21		tilt: (typeof options.tilt == 'undefined') ? 0.0 : jQuery.roundabout_toFloat(options.tilt),
22		minZ: (typeof options.minZ == 'undefined') ? 100 : parseInt(options.minZ, 10),
23		maxZ: (typeof options.maxZ == 'undefined') ? 400 : parseInt(options.maxZ, 10),
24		minOpacity: (typeof options.minOpacity == 'undefined') ? 0.40 : jQuery.roundabout_toFloat(options.minOpacity),
25		maxOpacity: (typeof options.maxOpacity == 'undefined') ? 1.00 : jQuery.roundabout_toFloat(options.maxOpacity),
26		minScale: (typeof options.minScale == 'undefined') ? 0.40 : jQuery.roundabout_toFloat(options.minScale),
27		maxScale: (typeof options.maxScale == 'undefined') ? 1.00 : jQuery.roundabout_toFloat(options.maxScale),
28		duration: (typeof options.duration == 'undefined') ? 600 : parseInt(options.duration, 10),
29		btnNext: options.btnNext || null,
30		btnPrev: options.btnPrev || null,
31		easing: options.easing || 'swing',
32		clickToFocus: (options.clickToFocus !== false),
33		focusBearing: (typeof options.focusBearing == 'undefined') ? 0.0 : jQuery.roundabout_toFloat(options.focusBearing % 360.0),
34		shape: options.shape || 'lazySusan',
35		debug: options.debug || false,
36		childSelector: options.childSelector || 'li',
37		startingChild: (typeof options.startingChild == 'undefined') ? null : parseInt(options.startingChild, 10),
38		reflect: (typeof options.reflect == 'undefined' || options.reflect === false) ? false : true,
39		autoplay:(typeof options.autoplay == 'undefined') ? 1000 : jQuery.roundabout_toFloat(options.autoplay)
40	};
41
42	// assign things 
43	this.each(function(i) {
44		var ref = jQuery(this);
45		var period = jQuery.roundabout_toFloat(360.0 / ref.children(options.childSelector).length);
46		var startingBearing = (options.startingChild === null) ? options.bearing : options.startingChild * period;
47		
48		// set starting styles
49		ref
50			.addClass('roundabout-holder')
51			.css('padding', 0)
52			.css('position', 'relative')
53			.css('z-index', options.minZ);
54		
55		// set starting options
56		ref.data('roundabout', {
57			'bearing': startingBearing,
58			'tilt': options.tilt,
59			'minZ': options.minZ,
60			'maxZ': options.maxZ,
61			'minOpacity': options.minOpacity,
62			'maxOpacity': options.maxOpacity,
63			'minScale': options.minScale,
64			'maxScale': options.maxScale,
65			'duration': options.duration,
66			'easing': options.easing,
67			'clickToFocus': options.clickToFocus,
68			'focusBearing': options.focusBearing,
69			'animating': 0,
70			'childInFocus': -1,
71			'shape': options.shape,
72			'period': period,
73			'debug': options.debug,
74			'childSelector': options.childSelector,
75			'reflect': options.reflect,
76			'autoplay': options.autoplay
77		});				
78		// bind click events
79		if (options.clickToFocus === true) {
80			ref.children(options.childSelector).each(function(i) {
81				jQuery(this).click(function(e) {
82					var degrees = (options.reflect === true) ? 360.0 - (period * i) : period * i;
83					degrees = jQuery.roundabout_toFloat(degrees);
84					if (!jQuery.roundabout_isInFocus(ref, degrees)) {
85						e.preventDefault();
86						if (ref.data('roundabout').animating === 0) {
87							ref.roundabout_animateAngleToFocus(degrees);
88							if(e.pageX/$(document).width()>0.5){
89								$('.pagination a.current').addClass('current2');
90								$('.pagination a').each(function(){$(this).removeClass('current')});
91								if($('.pagination a.current2').attr('href')==1){
92									$('.pagination a.current2').removeClass('current2');
93									$('.pagination a:eq(0)').addClass('current')
94								}
95								else {$('.pagination a.current2').removeClass('current2').next().addClass('current');}
96							}
97							else {
98								$('.pagination a.current').addClass('current2');
99								$('.pagination a').each(function(){$(this).removeClass('current')});
100								if($('.pagination a.current2').attr('href')==0){
101									$('.pagination a.current2').removeClass('current2');
102									$('.pagination a:eq(2)').addClass('current')
103								}
104								else {$('.pagination a.current2').removeClass('current2').prev().addClass('current');}
105							}
106						}
107						return false;
108					}
109				});
110			});
111		}	
112		// bind next buttons
113		if (options.btnNext) {
114			jQuery(options.btnNext).bind('click.roundabout', function(e) {
115				e.preventDefault();
116				if (ref.data('roundabout').animating === 0) {
117					ref.roundabout_animateToNextChild();					
118				}
119				return false;
120			});
121		}		
122		// bind previous buttons
123		if (options.btnPrev) {
124			jQuery(options.btnPrev).bind('click.roundabout', function(e) {
125				e.preventDefault();
126				if (ref.data('roundabout').animating === 0) {
127					ref.roundabout_animateToPreviousChild();
128				}
129				return false;
130			});
131		}	
132		function pause() {
133			clearInterval(autoplay);
134				autoplay = setInterval(function(){
135					ref.roundabout_animateToPreviousChild();
136					$('.pagination a.current').addClass('current2');
137					$('.pagination a').each(function(){$(this).removeClass('current')});
138					if($('.pagination a.current2').attr('href')==1){
139						$('.pagination a.current2').removeClass('current2');
140						$('.pagination a:eq(0)').addClass('current')
141					}
142					else {$('.pagination a.current2').removeClass('current2').next().addClass('current');}
143				},options.autoplay);
144		}
145		function stopp(){clearInterval(autoplay);}					
146		if (options.autoplay) {
147			autoplay = setInterval(function(){
148				ref.roundabout_animateToPreviousChild();
149				$('.pagination a.current').addClass('current2');
150				$('.pagination a').each(function(){$(this).removeClass('current')});
151				if($('.pagination a.current2').attr('href')==1){
152					$('.pagination a.current2').removeClass('current2');
153					$('.pagination a:eq(0)').addClass('current')
154				}
155				else {$('.pagination a.current2').removeClass('current2').next().addClass('current');}
156			},options.autoplay);
157		}		
158		$('.pagination a').click(function(e) {
159			e.preventDefault();			
160			$(this).parent().children().removeClass('current');
161			$(this).addClass('current');
162			ref.roundabout_animateToChild($(this).attr('href'));		
163			pause();
164			return false;
165		});
166		ref.hover(function(){stopp()},function(){pause()});
167		$('.pagination a:eq(0)').addClass('current');
168	});
169	// start children
170	this.roundabout_startChildren();
171	// callback once ready
172	if (typeof arguments[1] === 'function') {
173		var callback = arguments[1], ref = this;
174		setTimeout(function() { callback(ref); }, 0);
175	}
176
177	return this;
178};
179
180jQuery.fn.roundabout_startChildren = function() {
181	this.each(function(i) {
182		var ref = jQuery(this);
183		var data = ref.data('roundabout');
184		var children = ref.children(data.childSelector);
185		
186		children.each(function(i) {
187			var degrees = (data.reflect === true) ? 360.0 - (data.period * i) : data.period * i;
188
189			// apply classes and css first
190			jQuery(this)
191				.addClass('roundabout-moveable-item')
192				.css('position', 'absolute');
193			
194			// then measure
195			jQuery(this).data('roundabout', {
196				'startWidth': jQuery(this).width(),
197				'startHeight': jQuery(this).height(),
198				'startFontSize': parseInt(jQuery(this).css('font-size'), 10),
199				'degrees': degrees
200			});
201		});
202		
203		ref.roundabout_updateChildPositions();
204	});
205	return this;
206};
207
208jQuery.fn.roundabout_setTilt = function(newTilt) {
209	this.each(function(i) {
210		jQuery(this).data('roundabout').tilt = newTilt;
211		jQuery(this).roundabout_updateChildPositions();
212	});
213	
214	if (typeof arguments[1] === 'function') {
215		var callback = arguments[1], ref = this;
216		setTimeout(function() { callback(ref); }, 0);
217	}
218	
219	return this;
220};
221
222jQuery.fn.roundabout_setBearing = function(newBearing) {
223	this.each(function(i) {
224		jQuery(this).data('roundabout').bearing = jQuery.roundabout_toFloat(newBearing % 360, 2);
225		jQuery(this).roundabout_updateChildPositions();
226	});
227
228	if (typeof arguments[1] === 'function') {
229		var callback = arguments[1], ref = this;
230		setTimeout(function() { callback(ref); }, 0);
231	}
232	
233	return this;
234};
235
236jQuery.fn.roundabout_adjustBearing = function(delta) {
237	delta = jQuery.roundabout_toFloat(delta);
238	if (delta !== 0) {
239		this.each(function(i) {
240			jQuery(this).data('roundabout').bearing = jQuery.roundabout_getBearing(jQuery(this)) + delta;
241			jQuery(this).roundabout_updateChildPositions();
242		});
243	}
244	
245	if (typeof arguments[1] === 'function') {
246		var callback = arguments[1], ref = this;
247		setTimeout(function() { callback(ref); }, 0);
248	}
249
250	return this;
251};
252
253jQuery.fn.roundabout_adjustTilt = function(delta) {
254	delta = jQuery.roundabout_toFloat(delta);
255	if (delta !== 0) {
256		this.each(function(i) {
257			jQuery(this).data('roundabout').tilt = jQuery.roundabout_toFloat(jQuery(this).roundabout_get('tilt') + delta);
258			jQuery(this).roundabout_updateChildPositions();
259		});
260	}
261	
262	if (typeof arguments[1] === 'function') {
263		var callback = arguments[1], ref = this;
264		setTimeout(function() { callback(ref); }, 0);
265	}
266
267	return this;
268};
269
270jQuery.fn.roundabout_animateToBearing = function(bearing) {
271	bearing = jQuery.roundabout_toFloat(bearing);
272	var currentTime = new Date();
273	var duration    = (typeof arguments[1] == 'undefined') ? null : arguments[1];
274	var easingType  = (typeof arguments[2] == 'undefined') ? null : arguments[2];
275	var passedData  = (typeof arguments[3] !== 'object')   ? null : arguments[3];
276
277	this.each(function(i) {
278		var ref = jQuery(this), data = ref.data('roundabout'), timer, easingFn, newBearing;
279		var thisDuration = (duration === null) ? data.duration : duration;
280		var thisEasingType = (easingType !== null) ? easingType : data.easing || 'swing';
281
282		if (passedData === null) {
283			passedData = {
284				timerStart: currentTime,
285				start: jQuery.roundabout_getBearing(ref),
286				totalTime: thisDuration
287			};
288		}
289		timer = currentTime - passedData.timerStart;
290
291		if (timer < thisDuration) {
292			data.animating = 1;
293			
294			if (typeof jQuery.easing.def == 'string') {
295				easingFn = jQuery.easing[thisEasingType] || jQuery.easing[jQuery.easing.def];
296				newBearing = easingFn(null, timer, passedData.start, bearing - passedData.start, passedData.totalTime);
297			} else {
298				newBearing = jQuery.easing[thisEasingType]((timer / passedData.totalTime), timer, passedData.start, bearing - passedData.start, passedData.totalTime);
299			}
300			
301			ref.roundabout_setBearing(newBearing, function() { ref.roundabout_animateToBearing(bearing, thisDuration, thisEasingType, passedData); });
302		} else {
303			bearing = (bearing < 0) ? bearing + 360 : bearing % 360;
304			data.animating = 0;
305			ref.roundabout_setBearing(bearing);
306		}
307	});	
308	return this;
309};
310
311jQuery.fn.roundabout_animateToDelta = function(delta) {
312	var duration = arguments[1], easing = arguments[2];
313	this.each(function(i) {
314		delta = jQuery.roundabout_getBearing(jQuery(this)) + jQuery.roundabout_toFloat(delta);
315		jQuery(this).roundabout_animateToBearing(delta, duration, easing);
316	});
317	return this;
318};
319
320jQuery.fn.roundabout_animateToChild = function(childPos) {	
321	var duration = arguments[1], easing = arguments[2];	
322	this.each(function(i) {
323		var ref = jQuery(this), data = ref.data('roundabout');
324		if (data.childInFocus !== childPos && data.animating === 0) {		
325			var child = jQuery(ref.children(data.childSelector)[childPos]);
326			ref.roundabout_animateAngleToFocus(child.data('roundabout').degrees, duration, easing);
327		}
328	});
329	return this;
330};
331
332jQuery.fn.roundabout_animateToNearbyChild = function(passedArgs, which) {
333	var duration = passedArgs[0], easing = passedArgs[1];
334	this.each(function(i) {
335		var data     = jQuery(this).data('roundabout');
336		var bearing  = jQuery.roundabout_toFloat(360.0 - jQuery.roundabout_getBearing(jQuery(this)));
337		var period   = data.period, j = 0, range;
338		var reflect  = data.reflect;
339		var length   = jQuery(this).children(data.childSelector).length;
340
341		bearing = (reflect === true) ? bearing % 360.0 : bearing;
342		
343		if (data.animating === 0) {
344			// if we're not reflecting and we're moving to next or
345			//    we are reflecting and we're moving previous
346			if ((reflect === false && which === 'next') || (reflect === true && which !== 'next')) {
347				bearing = (bearing === 0) ? 360 : bearing;
348							
349				// counterclockwise
350				while (true && j < length) {
351					range = { lower: jQuery.roundabout_toFloat(period * j), upper: jQuery.roundabout_toFloat(period * (j + 1)) };
352					range.upper = (j == length - 1) ? 360.0 : range.upper;  // adjust for javascript being bad at floats
353
354					if (bearing <= range.upper && bearing > range.lower) {
355						jQuery(this).roundabout_animateToDelta(bearing - range.lower, duration, easing);
356						break;
357					}
358					j++;
359				}
360			} else {
361				// clockwise
362				while (true) {
363					range = { lower: jQuery.roundabout_toFloat(period * j), upper: jQuery.roundabout_toFloat(period * (j + 1)) };
364					range.upper = (j == length - 1) ? 360.0 : range.upper;  // adjust for javascript being bad at floats
365
366					if (bearing >= range.lower && bearing < range.upper) {
367						jQuery(this).roundabout_animateToDelta(bearing - range.upper, duration, easing);
368						break;
369					}
370					j++;
371				}
372			}
373		}
374	});
375	return this;
376};
377
378jQuery.fn.roundabout_animateToNextChild = function() {	
379	return this.roundabout_animateToNearbyChild(arguments, 'next');
380};
381
382jQuery.fn.roundabout_animateToPreviousChild = function() {	
383	return this.roundabout_animateToNearbyChild(arguments, 'previous');
384};
385
386// moves a given angle to the focus by the shortest means possible
387jQuery.fn.roundabout_animateAngleToFocus = function(target) {
388	var duration = arguments[1], easing = arguments[2];
389	this.each(function(i) {
390		var delta = jQuery.roundabout_getBearing(jQuery(this)) - target;
391		delta = (Math.abs(360.0 - delta) < Math.abs(0.0 - delta)) ? 360.0 - delta : 0.0 - delta;
392		delta = (delta > 180) ? -(360.0 - delta) : delta;
393		
394		if (delta !== 0) {
395			jQuery(this).roundabout_animateToDelta(delta, duration, easing);	
396		}
397	});
398	return this;
399};
400
401jQuery.fn.roundabout_updateChildPositions = function() {
402	this.each(function(i) {
403		var ref = jQuery(this), data = ref.data('roundabout');
404		var inFocus = -1;
405		var info = {
406			bearing: jQuery.roundabout_getBearing(ref),
407			tilt: data.tilt,
408			stage: { width: Math.floor(ref.width() * 0.9), height: Math.floor(ref.height() * 0.9) },
409			animating: data.animating,
410			inFocus: data.childInFocus,
411			focusBearingRad: jQuery.roundabout_degToRad(data.focusBearing),
412			shape: jQuery.roundabout_shape[data.shape] || jQuery.roundabout_shape[jQuery.roundabout_shape.def]
413		};
414		info.midStage = { width: info.stage.width / 2, height: info.stage.height / 2 };
415		info.nudge = { width: info.midStage.width + info.stage.width * 0.05, height: info.midStage.height + info.stage.height * 0.05 };
416		info.zValues = { min: data.minZ, max: data.maxZ, diff: data.maxZ - data.minZ };
417		info.opacity = { min: data.minOpacity, max: data.maxOpacity, diff: data.maxOpacity - data.minOpacity };
418		info.scale = { min: data.minScale, max: data.maxScale, diff: data.maxScale - data.minScale };
419
420		// update child positions
421		ref.children(data.childSelector).each(function(i) {
422			if (jQuery.roundabout_updateChildPosition(jQuery(this), ref, info, i) && info.animating === 0) {
423				inFocus = i;
424				jQuery(this).addClass('roundabout-in-focus');
425			} else {
426				jQuery(this).removeClass('roundabout-in-focus');
427			}
428		});
429
430		// update status of who is in focus
431		if (inFocus !== info.inFocus) {
432			jQuery.roundabout_triggerEvent(ref, info.inFocus, 'blur');
433
434			if (inFocus !== -1) {
435				jQuery.roundabout_triggerEvent(ref, inFocus, 'focus');
436			}
437
438			data.childInFocus = inFocus;
439		}
440	});	
441	return this;	
442};
443
444//----------------
445
446jQuery.roundabout_getBearing = function(el) {
447	return jQuery.roundabout_toFloat(el.data('roundabout').bearing) % 360;
448};
449
450jQuery.roundabout_degToRad = function(degrees) {
451	return (degrees % 360.0) * Math.PI / 180.0;
452};
453
454jQuery.roundabout_isInFocus = function(el, target) {
455	return (jQuery.roundabout_getBearing(el) % 360 === (target % 360));
456};
457
458jQuery.roundabout_triggerEvent = function(el, child, eventType) {
459	return (child < 0) ? this : jQuery(el.children(el.data('roundabout').childSelector)[child]).trigger(eventType);
460};
461
462jQuery.roundabout_toFloat = function(number) {
463	number = Math.round(parseFloat(number) * 1000) / 1000;
464	return parseFloat(number.toFixed(2));
465};
466
467jQuery.roundabout_updateChildPosition = function(child, container, info, childPos) {
468	var ref = jQuery(child), data = ref.data('roundabout'), out = [];
469	var rad = jQuery.roundabout_degToRad((360.0 - ref.data('roundabout').degrees) + info.bearing);
470	
471	// adjust radians to be between 0 and Math.PI * 2
472	while (rad < 0) {
473		rad = rad + Math.PI * 2;
474	}
475	while (rad > Math.PI * 2) {
476		rad = rad - Math.PI * 2;
477	}
478	
479	var factors = info.shape(rad, info.focusBearingRad, info.tilt); // obj with x, y, z, and scale values
480
481	// correct
482	factors.scale = (factors.scale > 1) ? 1 : factors.scale;
483	factors.adjustedScale = (info.scale.min + (info.scale.diff * factors.scale)).toFixed(4);
484	factors.width = (factors.adjustedScale * data.startWidth).toFixed(4);
485	factors.height = (factors.adjustedScale * data.startHeight).toFixed(4);
486	
487	// alter item
488	ref
489		.css('left', ((factors.x * info.midStage.width + info.nudge.width) - factors.width / 2.0).toFixed(1) + 'px')
490		.css('top', ((factors.y * info.midStage.height + info.nudge.height) - factors.height / 2.0).toFixed(1) + 'px')
491		.css('width', factors.width + 'px')
492		.css('height', factors.height + 'px')
493		.css('opacity', (info.opacity.min + (info.opacity.diff * factors.scale)).toFixed(2))
494		.css('z-index', Math.round(info.zValues.min + (info.zValues.diff * factors.z)))
495		.css('font-size', (factors.adjustedScale * data.startFontSize).toFixed(2) + 'px')
496		.attr('current-scale', factors.adjustedScale);
497	
498	if (container.data('roundabout').debug === true) {
499		out.push('<div style="font-weight: normal; font-size: 10px; padding: 2px; width: ' + ref.css('width') + '; background-color: #ffc;">');
500		out.push('<strong style="font-size: 12px; white-space: nowrap;">Child ' + childPos + '</strong><br />');
501		out.push('<strong>left:</strong> ' + ref.css('left') + '<br /><strong>top:</strong> ' + ref.css('top') + '<br />');
502		out.push('<strong>width:</strong> ' + ref.css('width') + '<br /><strong>opacity:</strong> ' + ref.css('opacity') + '<br />');
503		out.push('<strong>z-index:</strong> ' + ref.css('z-index') + '<br /><strong>font-size:</strong> ' + ref.css('font-size') + '<br />');
504		out.push('<strong>scale:</strong> ' + ref.attr('current-scale'));
505		out.push('</div>');
506		
507		ref.html(out.join(''));
508	}
509
510	return jQuery.roundabout_isInFocus(container, ref.data('roundabout').degrees);
511};
512
513/*****************************************initialization*****************************************/
514
515$(document).ready(function(){
516	$('ul#myRoundabout').roundabout({
517		minOpacity: 1,
518		minScale: 0.80,
519		easing:'easeOutBack',
520		duration:600,
521		autoplay:7000
522	});
523})

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.