PageSourceSearch

https://festiwalpolskaodkuchni.pl/inc/imageflow.js

js festiwalpolskaodkuchni.pl collected 2026-10-04 11:49:48 UTC 39,100 bytes, 1,463 lines download raw bytes

1/*
2Name:       ImageFlow
3Version:    1.3.0 (March 9 2010)
4Author:     Finn Rudolph
5Support:    http://finnrudolph.de/ImageFlow
6
7License:    ImageFlow is licensed under a Creative Commons
8            Attribution-Noncommercial 3.0 Unported License
9            (http://creativecommons.org/licenses/by-nc/3.0/).
10
11            You are free:
12                + to Share - to copy, distribute and transmit the work
13                + to Remix - to adapt the work
14
15            Under the following conditions:
16                + Attribution. You must attribute the work in the manner specified by the author or licensor
17                  (but not in any way that suggests that they endorse you or your use of the work).
18                + Noncommercial. You may not use this work for commercial purposes.
19
20            + For any reuse or distribution, you must make clear to others the license terms of this work.
21            + Any of the above conditions can be waived if you get permission from the copyright holder.
22            + Nothing in this license impairs or restricts the author's moral rights.
23
24Credits:    This script is based on Michael L. Perrys Cover flow in Javascript [1].
25            The reflections are generated server-sided by a slightly hacked version
26            of Richard Daveys easyreflections [2] written in PHP. The mouse wheel
27            support is an implementation of Adomas Paltanavicius JavaScript mouse
28            wheel code [3]. It also uses the domReadyEvent from Tanny O'Haley [4].
29
30            [1] http://www.adventuresinsoftware.com/blog/?p=104#comment-1981
31            [2] http://reflection.corephp.co.uk/v2.php
32            [3] http://adomas.org/javascript-mouse-wheel/
33            [4] http://tanny.ica.com/ICA/TKO/tkoblog.nsf/dx/domcontentloaded-for-browsers-part-v
34*/
35
36/* ImageFlow constructor */
37function ImageFlow ()
38{
39	/* Setting option defaults */
40	this.defaults =
41	{
42		animationSpeed:     100,             /* Animation speed in ms */
43		aspectRatio:        1.964,          /* Aspect ratio of the ImageFlow container (width divided by height) */
44		buttons:            false,          /* Toggle navigation buttons */
45		captions:           false,           /* Toggle captions */
46		circular:           true,          /* Toggle circular rotation */
47		imageCursor:        'default',      /* Cursor type for all images - default is 'default' */
48		ImageFlowID:        'imageflow',    /* Default id of the ImageFlow container */
49		imageFocusM:        0.2,            /* Multiplicator for the focussed image size in percent */
50		imageFocusMax:      4,              /* Max number of images on each side of the focussed one */
51		imagePath:          '',             /* Path to the images relative to the reflect_.php script */
52		imageScaling:       true,           /* Toggle image scaling */ 
53		imagesHeight:       0.67,           /* Height of the images div container in percent */
54		imagesM:            0.6,            /* Multiplicator for all images in percent */
55		onClick:            function() { },   /* Onclick behaviour */
56		opacity:            false,          /* Toggle image opacity */
57		opacityArray:       [10,8,6,4,2],   /* Image opacity (range: 0 to 10) first value is for the focussed image */
58		percentLandscape:   118,            /* Scale landscape format */
59		percentOther:       100,            /* Scale portrait and square format */
60		preloadImages:      true,           /* Toggles loading bar (false: requires img attributes height and width) */
61		reflections:        false,           /* Toggle reflections */
62		reflectionGET:      '',             /* Pass variables via the GET method to the reflect_.php script */
63		reflectionP:        0.5,            /* Height of the reflection in percent of the source image */
64		reflectionPNG:      false,          /* Toggle reflect2.php or reflect3.php */
65		reflectPath:        '',             /* Path to the reflect_.php script */
66		scrollbarP:         0.6,            /* Width of the scrollbar in percent */
67		slider:             false,           /* Toggle slider */
68		sliderCursor:       'e-resize',     /* Slider cursor type - default is 'default' */
69		sliderWidth:        14,             /* Width of the slider in px */
70		slideshow:          true,          /* Toggle slideshow */
71		slideshowSpeed:     2500,           /* Time between slides in ms */
72		slideshowAutoplay:  true,          /* Toggle automatic slideshow play on startup */
73		startID:            1,              /* Image ID to begin with */
74		glideToStartID:     true,           /* Toggle glide animation to start ID */
75		startAnimation:     true,          /* Animate images moving in from the right on startup */
76		xStep:              150             /* Step width on the x-axis in px */
77	};
78
79
80	/* Closure for this */
81	var my = this;
82
83
84	/* Initiate ImageFlow */
85	this.init = function (options)
86	{
87		/* Evaluate options */
88		for(var name in my.defaults) 
89		{
90			this[name] = (options !== undefined && options[name] !== undefined) ? options[name] : my.defaults[name];
91		}
92
93		/* Try to get ImageFlow div element */
94		var ImageFlowDiv = document.getElementById(my.ImageFlowID);
95		if(ImageFlowDiv)
96		{
97			/* Set it global within the ImageFlow scope */
98			ImageFlowDiv.style.visibility = 'visible';
99			this.ImageFlowDiv = ImageFlowDiv;
100
101			/* Try to create XHTML structure */
102			if(this.createStructure())
103			{
104				this.imagesDiv = document.getElementById(my.ImageFlowID+'_images');
105				this.captionDiv = document.getElementById(my.ImageFlowID+'_caption');
106				this.navigationDiv = document.getElementById(my.ImageFlowID+'_navigation');
107				this.scrollbarDiv = document.getElementById(my.ImageFlowID+'_scrollbar');
108				this.sliderDiv = document.getElementById(my.ImageFlowID+'_slider');
109				this.buttonNextDiv = document.getElementById(my.ImageFlowID+'_next');
110				this.buttonPreviousDiv = document.getElementById(my.ImageFlowID+'_previous');
111				this.buttonSlideshow = document.getElementById(my.ImageFlowID+'_slideshow');
112
113				this.indexArray = [];
114				this.current = 0;
115				this.imageID = 0;
116				this.target = 0;
117				this.memTarget = 0;
118				this.firstRefresh = true;
119				this.firstCheck = true;
120				this.busy = false;
121
122				/* Set height of the ImageFlow container and center the loading bar */
123				var width = this.ImageFlowDiv.offsetWidth;
124				var height = Math.round(width / my.aspectRatio);
125				document.getElementById(my.ImageFlowID+'_loading_txt').style.paddingTop = ((height * 0.5) -22) + 'px';
126				ImageFlowDiv.style.height = height + 'px';
127
128				/* Init loading progress */
129				this.loadingProgress();
130			}
131		}
132	};
133
134
135	/* Create HTML Structure */
136	this.createStructure = function()
137	{
138		/* Create images div container */
139		var imagesDiv = my.Helper.createDocumentElement('div','images');
140
141		/* Shift all images into the images div */
142		var node, version, src, imageNode;
143		var max = my.ImageFlowDiv.childNodes.length;
144		for(var index = 0; index < max; index++)
145		{
146			node = my.ImageFlowDiv.childNodes[index];
147			if (node && node.nodeType == 1 && node.nodeName == 'IMG')
148			{
149				/* Add 'reflect.php?img=' */
150				if(my.reflections === true)
151				{
152					version = (my.reflectionPNG) ? '3' : '2';
153					src = my.imagePath+node.getAttribute('src',2);
154					src = my.reflectPath+'reflect'+version+'.php?img='+src+my.reflectionGET;
155					node.setAttribute('src',src);
156				}
157
158				/* Clone image nodes and append them to the images div */
159				imageNode = node.cloneNode(true);
160				imagesDiv.appendChild(imageNode);
161			}
162		}
163
164		/* Clone some more images to make a circular animation possible */
165		if(my.circular)
166		{
167			/* Create temporary elements to hold the cloned images */
168			var first = my.Helper.createDocumentElement('div','images');
169			var last = my.Helper.createDocumentElement('div','images');
170			
171			/* Make sure, that there are enough images to use circular mode */
172			max = imagesDiv.childNodes.length;
173			if(max < my.imageFocusMax)
174			{
175				my.imageFocusMax = max;
176			}
177
178			/* Do not clone anything if there is only one image */
179			if(max > 1)
180			{
181				/* Clone the first and last images */
182				var i;
183				for(i = 0; i < max; i++)
184				{
185					/* Number of clones on each side equals the imageFocusMax */
186					node = imagesDiv.childNodes[i];
187					if(i < my.imageFocusMax)
188					{
189						imageNode = node.cloneNode(true);
190						first.appendChild(imageNode);
191					}
192					if(max-i < my.imageFocusMax+1)
193					{
194						imageNode = node.cloneNode(true);
195						last.appendChild(imageNode);
196					}
197				}
198
199				/* Sort the image nodes in the following order: last | originals | first */
200				for(i = 0; i < max; i++)
201				{
202					node = imagesDiv.childNodes[i];
203					imageNode = node.cloneNode(true);
204					last.appendChild(imageNode);
205				}
206				for(i = 0; i < my.imageFocusMax; i++)
207				{
208					node = first.childNodes[i];
209					imageNode = node.cloneNode(true);
210					last.appendChild(imageNode);
211				}
212				
213				/* Overwrite the imagesDiv with the new order */
214				imagesDiv = last;
215			}
216		}
217
218		/* Create slideshow button div and append it to the images div */
219		if(my.slideshow)
220		{
221			var slideshowButton = my.Helper.createDocumentElement('div','slideshow');
222			imagesDiv.appendChild(slideshowButton);
223		}
224
225		/* Create loading text container */
226		var loadingP = my.Helper.createDocumentElement('p','loading_txt');
227		var loadingText = document.createTextNode(' ');
228		loadingP.appendChild(loadingText);
229
230		/* Create loading div container */
231		var loadingDiv = my.Helper.createDocumentElement('div','loading');
232
233		/* Create loading bar div container inside the loading div */
234		var loadingBarDiv = my.Helper.createDocumentElement('div','loading_bar');
235		loadingDiv.appendChild(loadingBarDiv);
236
237		/* Create captions div container */
238		var captionDiv = my.Helper.createDocumentElement('div','caption');
239
240		/* Create slider and button div container inside the scrollbar div */
241		var scrollbarDiv = my.Helper.createDocumentElement('div','scrollbar');
242		var sliderDiv = my.Helper.createDocumentElement('div','slider');
243		scrollbarDiv.appendChild(sliderDiv);
244		if(my.buttons)
245		{
246			var buttonPreviousDiv = my.Helper.createDocumentElement('div','previous', 'button');
247			var buttonNextDiv = my.Helper.createDocumentElement('div','next', 'button');
248			scrollbarDiv.appendChild(buttonPreviousDiv);
249			scrollbarDiv.appendChild(buttonNextDiv);
250		}
251
252		/* Create navigation div container beneath images div */
253		var navigationDiv = my.Helper.createDocumentElement('div','navigation');
254		navigationDiv.appendChild(captionDiv);
255		navigationDiv.appendChild(scrollbarDiv);
256	
257		/* Update document structure and return true on success */
258		var success = false;
259		if (my.ImageFlowDiv.appendChild(imagesDiv) &&
260			my.ImageFlowDiv.appendChild(loadingP) &&
261			my.ImageFlowDiv.appendChild(loadingDiv) &&
262			my.ImageFlowDiv.appendChild(navigationDiv))
263		{
264			/* Remove image nodes outside the images div */
265			max = my.ImageFlowDiv.childNodes.length;
266			for(index = 0; index < max; index++)
267			{
268				node = my.ImageFlowDiv.childNodes[index];
269				if (node && node.nodeType == 1 && node.nodeName == 'IMG')
270				{
271					my.ImageFlowDiv.removeChild(node);
272				}
273			}
274			success = true;
275		}
276		return success;
277	};
278
279
280	/* Manage loading progress and call the refresh function */
281	this.loadingProgress = function()
282	{
283		var p = my.loadingStatus();
284		if((p < 100 || my.firstCheck) && my.preloadImages)
285		{
286			/* Insert a short delay if the browser loads rapidly from its cache */
287			if(my.firstCheck && p == 100)
288			{
289				my.firstCheck = false;
290				window.setTimeout(my.loadingProgress, 100);
291			}
292			else
293			{
294				window.setTimeout(my.loadingProgress, 40);
295			}
296		}
297		else
298		{
299			/* Hide loading elements */
300			document.getElementById(my.ImageFlowID+'_loading_txt').style.display = 'none';
301			document.getElementById(my.ImageFlowID+'_loading').style.display = 'none';
302
303			/* Refresh ImageFlow on window resize - delay adding this event for the IE */
304			window.setTimeout(my.Helper.addResizeEvent, 1000);
305
306			/* Call refresh once on startup to display images */
307			my.refresh();
308
309			/* Only initialize navigation elements if there is more than one image */
310			if(my.max > 1)
311			{
312				/* Initialize mouse, touch and key support */
313				my.MouseWheel.init();
314				my.MouseDrag.init();
315				my.Touch.init();
316				my.Key.init();
317				
318				/* Toggle slideshow */
319				if(my.slideshow)
320				{
321					my.Slideshow.init();
322				}
323
324				/* Toggle scrollbar visibility */
325				if(my.slider)
326				{
327					my.scrollbarDiv.style.visibility = 'visible';
328				}
329			}
330		}
331	};
332
333
334	/* Return loaded images in percent, set loading bar width and loading text */
335	this.loadingStatus = function()
336	{
337		var max = my.imagesDiv.childNodes.length;
338		var i = 0, completed = 0;
339		var image = null;
340		for(var index = 0; index < max; index++)
341		{
342			image = my.imagesDiv.childNodes[index];
343			if(image && image.nodeType == 1 && image.nodeName == 'IMG')
344			{
345				if(image.complete)
346				{
347					completed++;
348				}
349				i++;
350			}
351		}
352
353		var finished = Math.round((completed/i)*100);
354		var loadingBar = document.getElementById(my.ImageFlowID+'_loading_bar');
355		loadingBar.style.width = finished+'%';
356
357		/* Do not count the cloned images */
358		if(my.circular)
359		{
360			i = i - (my.imageFocusMax*2);
361			completed = (finished < 1) ? 0 : Math.round((i/100)*finished);
362		}
363
364		var loadingP = document.getElementById(my.ImageFlowID+'_loading_txt');
365		var loadingTxt = document.createTextNode('loading images '+completed+'/'+i);
366		loadingP.replaceChild(loadingTxt,loadingP.firstChild);
367		return finished;
368	};
369
370
371	/* Cache EVERYTHING that only changes on refresh or resize of the window */
372	this.refresh = function()
373	{
374		/* Cache global variables */
375		this.imagesDivWidth = my.imagesDiv.offsetWidth+my.imagesDiv.offsetLeft;
376		this.maxHeight = Math.round(my.imagesDivWidth / my.aspectRatio);
377		this.maxFocus = my.imageFocusMax * my.xStep;
378		this.size = my.imagesDivWidth * 0.5;
379		this.sliderWidth = my.sliderWidth * 0.5;
380		this.scrollbarWidth = (my.imagesDivWidth - ( Math.round(my.sliderWidth) * 2)) * my.scrollbarP;
381		this.imagesDivHeight = Math.round(my.maxHeight * my.imagesHeight);
382
383		/* Change imageflow div properties */
384		my.ImageFlowDiv.style.height = my.maxHeight + 'px';
385
386		/* Change images div properties */
387		my.imagesDiv.style.height =  my.imagesDivHeight + 'px'; 
388		
389		/* Change images div properties */
390		my.navigationDiv.style.height =  (my.maxHeight - my.imagesDivHeight) + 'px'; 
391
392		/* Change captions div properties */
393		my.captionDiv.style.width = my.imagesDivWidth + 'px';
394		my.captionDiv.style.paddingTop = Math.round(my.imagesDivWidth * 0.02) + 'px';
395
396		/* Change scrollbar div properties */
397		my.scrollbarDiv.style.width = my.scrollbarWidth + 'px';
398		my.scrollbarDiv.style.marginTop = Math.round(my.imagesDivWidth * 0.02) + 'px';
399		my.scrollbarDiv.style.marginLeft = Math.round(my.sliderWidth + ((my.imagesDivWidth - my.scrollbarWidth)/2)) + 'px';
400
401		/* Set slider attributes */
402		my.sliderDiv.style.cursor = my.sliderCursor;
403		my.sliderDiv.onmousedown = function () { my.MouseDrag.start(this); return false;};
404
405		if(my.buttons)
406		{
407			my.buttonPreviousDiv.onclick = function () { my.MouseWheel.handle(1); };
408			my.buttonNextDiv.onclick = function () { my.MouseWheel.handle(-1); };
409		}
410
411		/* Set the reflection multiplicator */
412		var multi = (my.reflections === true) ? my.reflectionP + 1 : 1;
413
414		/* Set image attributes */
415		var max = my.imagesDiv.childNodes.length;
416		var i = 0;
417		var image = null;
418		for (var index = 0; index < max; index++)
419		{
420			image = my.imagesDiv.childNodes[index];
421			if(image !== null && image.nodeType == 1 && image.nodeName == 'IMG')
422			{
423				this.indexArray[i] = index;
424
425				/* Set image attributes to store values */
426				image.url = image.getAttribute('longdesc');
427				image.xPosition = (-i * my.xStep);
428				image.i = i;
429
430				/* Add width and height as attributes only once */
431				if(my.firstRefresh)
432				{
433					if(image.getAttribute('width') !== null && image.getAttribute('height') !== null)
434					{
435						image.w = image.getAttribute('width');
436						image.h = image.getAttribute('height') * multi;
437					}
438					else{
439						image.w = image.width;
440						image.h = image.height;
441					}
442				}
443
444				/* Check source image format. Get image height minus reflection height! */
445				if((image.w) > (image.h / (my.reflectionP + 1)))
446				{
447					/* Landscape format */
448					image.pc = my.percentLandscape;
449					image.pcMem = my.percentLandscape;
450				}
451				else
452				{
453					/* Portrait and square format */
454					image.pc = my.percentOther;
455					image.pcMem = my.percentOther;
456				}
457				
458				/* Change image positioning */
459				if(my.imageScaling === false)
460				{
461					image.style.position = 'relative';
462					image.style.display = 'inline';
463				}
464
465				/* Set image cursor type */
466				image.style.cursor = my.imageCursor;
467				i++;
468			}
469		}
470		this.max = my.indexArray.length;
471
472		/* Override dynamic sizes based on the first image */
473		if(my.imageScaling === false)
474		{
475			image = my.imagesDiv.childNodes[my.indexArray[0]];
476
477			/* Set left padding for the first image */
478			this.totalImagesWidth = image.w * my.max;
479			image.style.paddingLeft = (my.imagesDivWidth/2) + (image.w/2) + 'px';
480
481			/* Override images and navigation div height */
482			my.imagesDiv.style.height =  image.h + 'px';
483			my.navigationDiv.style.height =  (my.maxHeight - image.h) + 'px'; 
484		}
485
486		/* Handle startID on the first refresh */
487		if(my.firstRefresh)
488		{
489			/* Reset variable */
490			my.firstRefresh = false;
491
492			/* Set imageID to the startID */
493			my.imageID = my.startID-1;
494			if (my.imageID < 0 )
495			{
496				my.imageID = 0;
497			}
498
499			/* Map image id range in cicular mode (ignore the cloned images) */
500			if(my.circular)
501			{	
502				my.imageID = my.imageID + my.imageFocusMax;
503			}
504
505			/* Make sure, that the id is smaller than the image count  */
506			maxId = (my.circular) ?  (my.max-(my.imageFocusMax))-1 : my.max-1;
507			if (my.imageID > maxId)
508			{
509				my.imageID = maxId;
510			}
511
512			/* Toggle glide animation to start ID */
513			if(my.glideToStartID === false)
514			{
515				my.moveTo(-my.imageID * my.xStep);
516			}
517
518			/* Animate images moving in from the right */
519			if(my.startAnimation)
520			{
521				my.moveTo(5000);
522			}
523		}
524
525		/* Only animate if there is more than one image */
526		if(my.max > 1)
527		{
528			my.glideTo(my.imageID);
529		}
530
531		/* Display images in current order */
532		my.moveTo(my.current);
533	};
534
535
536	/* Main animation function */
537	this.moveTo = function(x)
538	{
539		this.current = x;
540		this.zIndex = my.max;
541
542		/* Main loop */
543		for (var index = 0; index < my.max; index++)
544		{
545			var image = my.imagesDiv.childNodes[my.indexArray[index]];
546			var currentImage = index * -my.xStep;
547
548			/* Enabled image scaling */
549			if(my.imageScaling)
550			{
551				/* Don't display images that are not conf_focussed */
552				if ((currentImage + my.maxFocus) < my.memTarget || (currentImage - my.maxFocus) > my.memTarget)
553				{
554					image.style.visibility = 'hidden';
555					image.style.display = 'none';
556				}
557				else
558				{
559					var z = (Math.sqrt(10000 + x * x) + 100) * my.imagesM;
560					var xs = x / z * my.size + my.size;
561
562					/* Still hide images until they are processed, but set display style to block */
563					image.style.display = 'block';
564
565					/* Process new image height and width */
566					var newImageH = (image.h / image.w * image.pc) / z * my.size;
567					var newImageW = 0;
568					switch (newImageH > my.maxHeight)
569					{
570						case false:
571							newImageW = image.pc / z * my.size;
572							break;
573
574						default:
575							newImageH = my.maxHeight;
576							newImageW = image.w * newImageH / image.h;
577							break;
578					}
579
580					var newImageTop = (my.imagesDivHeight - newImageH) + ((newImageH / (my.reflectionP + 1)) * my.reflectionP);
581
582					/* Set new image properties */
583					image.style.left = xs - (image.pc / 2) / z * my.size + 'px';
584					if(newImageW && newImageH)
585					{
586						image.style.height = newImageH + 'px';
587						image.style.width = newImageW + 'px';
588						image.style.top = newImageTop + 'px';
589					}
590					image.style.visibility = 'visible';
591
592					/* Set image layer through zIndex */
593					switch ( x < 0 )
594					{
595						case true:
596							this.zIndex++;
597							break;
598
599						default:
600							this.zIndex = my.zIndex - 1;
601							break;
602					}
603
604					/* Change zIndex and onclick function of the focussed image */
605					switch ( image.i == my.imageID )
606					{
607						case false:
608							image.onclick = function() { my.glideTo(this.i);};
609							break;
610
611						default:
612							this.zIndex = my.zIndex + 1;
613							if(image.url !== '')
614							{
615								image.onclick = my.onClick;
616							}
617							break;
618					}
619					image.style.zIndex = my.zIndex;
620				}
621			}
622
623			/* Disabled image scaling */
624			else
625			{
626				if ((currentImage + my.maxFocus) < my.memTarget || (currentImage - my.maxFocus) > my.memTarget)
627				{
628					image.style.visibility = 'hidden';
629				}
630				else
631				{
632					image.style.visibility = 'visible';
633
634					/* Change onclick function of the focussed image */
635					switch ( image.i == my.imageID )
636					{
637						case false:
638							image.onclick = function() { my.glideTo(this.i);};
639							break;
640
641						default:
642							if(image.url !== '')
643							{
644								image.onclick = my.onClick;
645							}
646							break;
647					}
648				}	
649				my.imagesDiv.style.marginLeft = (x - my.totalImagesWidth) + 'px';
650			}
651
652			x += my.xStep;
653		}
654	};
655
656
657	/* Initializes image gliding animation */
658	this.glideTo = function(imageID)
659	{
660		/* Check for jumppoints */
661		var jumpTarget, clonedImageID;
662		if(my.circular)
663		{
664			/* Trigger left jumppoint */
665			if(imageID+1 === my.imageFocusMax)
666			{
667				/* Set jump target to the same cloned image on the right */
668				clonedImageID = my.max - my.imageFocusMax;
669				jumpTarget = -clonedImageID * my.xStep;
670
671				/* Set the imageID to the last image */
672				imageID = clonedImageID-1 ;
673			}
674
675			/* Trigger right jumppoint */
676			if(imageID === (my.max - my.imageFocusMax))
677			{
678				/* Set jump target to the same cloned image on the left */
679				clonedImageID = my.imageFocusMax-1;
680				jumpTarget = -clonedImageID * my.xStep;
681				
682				/* Set the imageID to the first image */
683				imageID = clonedImageID+1;
684			}
685		}
686
687		/* Calculate new image position target */
688		var x = -imageID * my.xStep;
689		this.target = x;
690		this.memTarget = x;
691		this.imageID = imageID;
692
693		/* Display new caption */
694		var caption = my.imagesDiv.childNodes[imageID].getAttribute('alt');
695		if (caption === '' || my.captions === false)
696		{
697			caption = '&nbsp;';
698		}
699		my.captionDiv.innerHTML = caption;
700
701		/* Set scrollbar slider to new position */
702		if (my.MouseDrag.busy === false)
703		{
704			if(my.circular)
705			{
706				this.newSliderX = ((imageID-my.imageFocusMax) * my.scrollbarWidth) / (my.max-(my.imageFocusMax*2)-1) - my.MouseDrag.newX;
707			}
708			else
709			{
710				this.newSliderX = (imageID * my.scrollbarWidth) / (my.max-1) - my.MouseDrag.newX;
711			}
712			my.sliderDiv.style.marginLeft = (my.newSliderX - my.sliderWidth) + 'px';
713		}
714
715		/* Only process if opacity or a multiplicator for the focussed image has been set */
716		if(my.opacity === true || my.imageFocusM !== my.defaults.imageFocusM)
717		{
718			/* Set opacity for centered image */
719			my.Helper.setOpacity(my.imagesDiv.childNodes[imageID], my.opacityArray[0]);
720			my.imagesDiv.childNodes[imageID].pc = my.imagesDiv.childNodes[imageID].pc * my.imageFocusM;
721
722			/* Set opacity for the other images that are displayed */
723			var opacityValue = 0;
724			var rightID = 0;
725			var leftID = 0;
726			var last = my.opacityArray.length;
727
728			for (var i = 1; i < (my.imageFocusMax+1); i++)
729			{
730				if((i+1) > last)
731				{
732					opacityValue = my.opacityArray[last-1];
733				}
734				else
735				{
736					opacityValue = my.opacityArray[i];
737				}
738
739				rightID = imageID + i;
740				leftID = imageID - i;
741
742				if (rightID < my.max)
743				{
744					my.Helper.setOpacity(my.imagesDiv.childNodes[rightID], opacityValue);
745					my.imagesDiv.childNodes[rightID].pc = my.imagesDiv.childNodes[rightID].pcMem;
746				}
747				if (leftID >= 0)
748				{
749					my.Helper.setOpacity(my.imagesDiv.childNodes[leftID], opacityValue);
750					my.imagesDiv.childNodes[leftID].pc = my.imagesDiv.childNodes[leftID].pcMem;
751				}
752			}
753		}
754
755		/* Move the images to the jump target */
756		if(jumpTarget)
757		{
758			my.moveTo(jumpTarget);
759		}
760
761		/* Animate gliding to new x position */
762		if (my.busy === false)
763		{
764			my.busy = true;
765			my.animate();
766		}
767	};
768
769
770	/* Animates image gliding */
771	this.animate = function()
772	{
773		switch (my.target < my.current-1 || my.target > my.current+1)
774		{
775			case true:
776				my.moveTo(my.current + (my.target-my.current)/3);
777				window.setTimeout(my.animate, my.animationSpeed);
778				my.busy = true;
779				break;
780
781			default:
782				my.busy = false;
783				break;
784		}
785	};
786
787
788	/* Used by user events to call the glideTo function */
789	this.glideOnEvent = function(imageID)
790	{
791		/* Interrupt slideshow on mouse wheel, keypress, touch and mouse drag */
792		if(my.slideshow)
793		{
794			my.Slideshow.interrupt();
795		}
796		
797		/* Glide to new imageID */
798		my.glideTo(imageID);
799	};
800
801
802	/* Slideshow function */
803	this.Slideshow =
804	{
805		direction: 1,
806		
807		init: function()
808		{
809			/* Call start() if autoplay is enabled, stop() if it is disabled */
810			(my.slideshowAutoplay) ? my.Slideshow.start() : my.Slideshow.stop();	
811		},
812
813		interrupt: function()
814		{	
815			/* Remove interrupt event */
816			my.Helper.removeEvent(my.ImageFlowDiv,'click',my.Slideshow.interrupt);
817			
818			/* Interrupt the slideshow */
819			my.Slideshow.stop();
820		},
821
822		addInterruptEvent: function()
823		{
824			/* A click anywhere inside the ImageFlow div interrupts the slideshow */
825			my.Helper.addEvent(my.ImageFlowDiv,'click',my.Slideshow.interrupt);
826		},
827
828		start: function()
829		{
830			/* Set button style to pause */
831			my.Helper.setClassName(my.buttonSlideshow, 'slideshow pause');
832
833			/* Set onclick behaviour to stop */
834			my.buttonSlideshow.onclick = function () { my.Slideshow.stop(); };
835
836			/* Set slide interval */
837			my.Slideshow.action = window.setInterval(my.Slideshow.slide, my.slideshowSpeed);
838
839			/* Allow the user to always interrupt the slideshow */
840			window.setTimeout(my.Slideshow.addInterruptEvent, 100);
841		},
842
843		stop: function()
844		{
845			/* Set button style to play */
846			my.Helper.setClassName(my.buttonSlideshow, 'slideshow play');
847			
848			/* Set onclick behaviour to start */
849			my.buttonSlideshow.onclick = function () { my.Slideshow.start(); };
850			
851			/* Clear slide interval */
852			window.clearInterval(my.Slideshow.action);
853		},
854
855		slide: function()
856		{
857			var newImageID = my.imageID + my.Slideshow.direction;
858			var reverseDirection = false;
859			
860			/* Reverse direction at the last image on the right */
861			if(newImageID === my.max)
862			{
863				my.Slideshow.direction = -1;
864				reverseDirection = true;
865			}
866			
867			/* Reverse direction at the last image on the left */
868			if(newImageID < 0)
869			{
870				my.Slideshow.direction = 1;
871				reverseDirection = true;
872			}
873			
874			/* If direction is reversed recall this method, else call the glideTo method */
875			(reverseDirection) ? my.Slideshow.slide() : my.glideTo(newImageID);
876		}
877	};
878
879
880	/* Mouse Wheel support */
881	this.MouseWheel =
882	{
883		init: function()
884		{
885			/* Init mouse wheel listener */
886			if(window.addEventListener)
887			{
888				my.ImageFlowDiv.addEventListener('DOMMouseScroll', my.MouseWheel.get, false);
889			}
890			my.Helper.addEvent(my.ImageFlowDiv,'mousewheel',my.MouseWheel.get);
891		},
892
893		get: function(event)
894		{
895			var delta = 0;
896			if (!event)
897			{
898				event = window.event;
899			}
900			if (event.wheelDelta)
901			{
902				delta = event.wheelDelta / 120;
903			}
904			else if (event.detail)
905			{
906				delta = -event.detail / 3;
907			}
908			if (delta)
909			{
910				my.MouseWheel.handle(delta);
911			}
912			my.Helper.suppressBrowserDefault(event);
913		},
914
915		handle: function(delta)
916		{
917			var change = false;
918			var newImageID = 0;
919			if(delta > 0)
920			{
921				if(my.imageID >= 1)
922				{
923					newImageID = my.imageID -1;
924					change = true;
925				}
926			}
927			else
928			{
929				if(my.imageID < (my.max-1))
930				{
931					newImageID = my.imageID +1;
932					change = true;
933				}
934			}
935
936			/* Glide to next (mouse wheel down) / previous (mouse wheel up) image  */
937			if(change)
938			{
939				my.glideOnEvent(newImageID);
940			}
941		}
942	};
943
944
945	/* Mouse Dragging */
946	this.MouseDrag =
947	{
948		object: null,
949		objectX: 0,
950		mouseX: 0,
951		newX: 0,
952		busy: false,
953
954		/* Init mouse event listener */
955		init: function()
956		{
957			my.Helper.addEvent(my.ImageFlowDiv,'mousemove',my.MouseDrag.drag);
958			my.Helper.addEvent(my.ImageFlowDiv,'mouseup',my.MouseDrag.stop);
959			my.Helper.addEvent(document,'mouseup',my.MouseDrag.stop);
960
961			/* Avoid text and image selection while dragging  */
962			my.ImageFlowDiv.onselectstart = function ()
963			{
964				var selection = true;
965				if (my.MouseDrag.busy)
966				{
967					selection = false;
968				}
969				return selection;
970			};
971		},
972
973		start: function(o)
974		{
975			my.MouseDrag.object = o;
976			my.MouseDrag.objectX = my.MouseDrag.mouseX - o.offsetLeft + my.newSliderX;
977		},
978
979		stop: function()
980		{
981			my.MouseDrag.object = null;
982			my.MouseDrag.busy = false;
983		},
984
985		drag: function(e)
986		{
987			var posx = 0;
988			if (!e)
989			{
990				e = window.event;
991			}
992			if (e.pageX)
993			{
994				posx = e.pageX;
995			}
996			else if (e.clientX)
997			{
998				posx = e.clientX + document.body.scrollLeft	+ document.documentElement.scrollLeft;
999			}
1000			my.MouseDrag.mouseX = posx;
1001
1002			if(my.MouseDrag.object !== null)
1003			{
1004				var newX = (my.MouseDrag.mouseX - my.MouseDrag.objectX) + my.sliderWidth;
1005
1006				/* Make sure, that the slider is moved in proper relation to previous movements by the glideTo function */
1007				if(newX < ( - my.newSliderX))
1008				{
1009					newX = - my.newSliderX;
1010				}
1011				if(newX > (my.scrollbarWidth - my.newSliderX))
1012				{
1013					newX = my.scrollbarWidth - my.newSliderX;
1014				}
1015
1016				/* Set new slider position */
1017				var step, imageID;
1018				if(my.circular)
1019				{
1020					step = (newX + my.newSliderX) / (my.scrollbarWidth / (my.max-(my.imageFocusMax*2)-1));
1021					imageID = Math.round(step)+my.imageFocusMax;
1022				}
1023				else
1024				{
1025					step = (newX + my.newSliderX) / (my.scrollbarWidth / (my.max-1));
1026					imageID = Math.round(step);
1027				}
1028				my.MouseDrag.newX = newX;
1029				my.MouseDrag.object.style.left = newX + 'px';
1030				if(my.imageID !== imageID)
1031				{
1032					my.glideOnEvent(imageID);
1033				}
1034				my.MouseDrag.busy = true;
1035			}
1036		}
1037	};
1038
1039
1040	/* Safari touch events on the iPhone and iPod Touch */
1041	this.Touch =
1042	{
1043		x: 0,
1044		startX: 0,
1045		stopX: 0,
1046		busy: false,
1047		first: true,
1048
1049		/* Init touch event listener */
1050		init: function()
1051		{
1052			my.Helper.addEvent(my.navigationDiv,'touchstart',my.Touch.start);
1053			my.Helper.addEvent(document,'touchmove',my.Touch.handle);
1054			my.Helper.addEvent(document,'touchend',my.Touch.stop);	
1055		},
1056		
1057		isOnNavigationDiv: function(e)
1058		{
1059			var state = false;
1060			if(e.touches)
1061			{
1062				var target = e.touches[0].target;
1063				if(target === my.navigationDiv || target === my.sliderDiv || target === my.scrollbarDiv)
1064				{
1065					state = true;
1066				}
1067			}
1068			return state;
1069		},
1070
1071		getX: function(e)
1072		{
1073			var x = 0;
1074			if(e.touches)
1075			{
1076				x = e.touches[0].pageX;
1077			}
1078			return x;
1079		},
1080
1081		start: function(e)
1082		{
1083			my.Touch.startX = my.Touch.getX(e);
1084			my.Touch.busy = true;
1085			my.Helper.suppressBrowserDefault(e);
1086		},
1087
1088		isBusy: function()
1089		{
1090			var busy = false;
1091			if(my.Touch.busy)
1092			{
1093				busy = true;
1094			}
1095			return busy;
1096		},
1097
1098		/* Handle touch event position within the navigation div */
1099		handle: function(e)
1100		{
1101			if(my.Touch.isBusy && my.Touch.isOnNavigationDiv(e))
1102			{
1103				var max = (my.circular) ? (my.max-(my.imageFocusMax*2)-1) : (my.max-1);
1104				if(my.Touch.first)
1105				{
1106					my.Touch.stopX = (max - my.imageID) * (my.imagesDivWidth / max);
1107					my.Touch.first = false;
1108				}
1109				var newX = -(my.Touch.getX(e) - my.Touch.startX - my.Touch.stopX);
1110
1111				/* Map x-axis touch coordinates in range of the ImageFlow width */
1112				if(newX < 0)
1113				{
1114					newX = 0;
1115				}
1116				if(newX > my.imagesDivWidth)
1117				{
1118					newX = my.imagesDivWidth;
1119				}
1120
1121				my.Touch.x = newX;
1122				
1123				var imageID = Math.round(newX / (my.imagesDivWidth / max));
1124				imageID = max - imageID;
1125				if(my.imageID !== imageID)
1126				{
1127					if(my.circular)
1128					{
1129						imageID = imageID + my.imageFocusMax;
1130					}
1131					my.glideOnEvent(imageID);
1132				}
1133				my.Helper.suppressBrowserDefault(e);
1134			}
1135		},
1136
1137		stop: function()
1138		{
1139			my.Touch.stopX = my.Touch.x;
1140			my.Touch.busy = false;
1141		}
1142	};
1143
1144
1145	/* Key support */
1146	this.Key =
1147	{
1148		/* Init key event listener */
1149		init: function()
1150		{
1151			document.onkeydown = function(event){ my.Key.handle(event); };
1152		},
1153
1154		/* Handle the arrow keys */
1155		handle: function(event)
1156		{
1157			var charCode  = my.Key.get(event);
1158			switch (charCode)
1159			{
1160				/* Right arrow key */
1161				case 39:
1162					my.MouseWheel.handle(-1);
1163					break;
1164
1165				/* Left arrow key */
1166				case 37:
1167					my.MouseWheel.handle(1);
1168					break;
1169			}
1170		},
1171
1172		/* Get the current keycode */
1173		get: function(event)
1174		{
1175			event = event || window.event;
1176			return event.keyCode;
1177		}
1178	};
1179
1180
1181	/* Helper functions */
1182	this.Helper =
1183	{
1184		/* Add events */
1185		addEvent: function(obj, type, fn)
1186		{
1187			if(obj.addEventListener)
1188			{
1189				obj.addEventListener(type, fn, false);
1190			}
1191			else if(obj.attachEvent)
1192			{
1193				obj["e"+type+fn] = fn;
1194				obj[type+fn] = function() { obj["e"+type+fn]( window.event ); };
1195				obj.attachEvent( "on"+type, obj[type+fn] );
1196			}
1197		},
1198
1199		/* Remove events */
1200		removeEvent: function( obj, type, fn )
1201		{
1202			if (obj.removeEventListener)
1203			{
1204				obj.removeEventListener( type, fn, false );
1205			}
1206			else if (obj.detachEvent)
1207			{
1208				/* The IE breaks if you're trying to detach an unattached event http://msdn.microsoft.com/en-us/library/ms536411(VS.85).aspx */
1209				if(obj[type+fn] === undefined)
1210				{
1211					alert('Helper.removeEvent » Pointer to detach event is undefined - perhaps you are trying to detach an unattached event?');
1212				}
1213				obj.detachEvent( 'on'+type, obj[type+fn] );
1214				obj[type+fn] = null;
1215				obj['e'+type+fn] = null;
1216			}
1217		},
1218
1219		/* Set image opacity */
1220		setOpacity: function(object, value)
1221		{
1222			if(my.opacity === true)
1223			{
1224				object.style.opacity = value/10;
1225				object.style.filter = 'alpha(opacity=' + value*10 + ')';
1226			}
1227		},
1228
1229		/* Create HTML elements */
1230		createDocumentElement: function(type, id, optionalClass)
1231		{
1232			var element = document.createElement(type);
1233			element.setAttribute('id', my.ImageFlowID+'_'+id);
1234			if(optionalClass !== undefined)
1235			{
1236				id += ' '+optionalClass;
1237			}
1238			my.Helper.setClassName(element, id);
1239			return element;
1240		},
1241
1242		/* Set CSS class */
1243		setClassName: function(element, className)
1244		{
1245			if(element)
1246			{
1247				element.setAttribute('class', className);
1248				element.setAttribute('className', className);
1249			}
1250		},
1251
1252		/* Suppress default browser behaviour to avoid image/text selection while dragging */
1253		suppressBrowserDefault: function(e)
1254		{
1255			if(e.preventDefault)
1256			{
1257				e.preventDefault();
1258			}
1259			else
1260			{
1261				e.returnValue = false;
1262			}
1263			return false;
1264		},
1265
1266		/* Add functions to the window.onresize event - can not be done by addEvent */
1267		addResizeEvent: function()
1268		{
1269			var otherFunctions = window.onresize;
1270			if(typeof window.onresize != 'function')
1271			{
1272				window.onresize = function()
1273				{
1274					my.refresh();
1275				};
1276			}
1277			else
1278			{
1279				window.onresize = function(){
1280					if (otherFunctions)
1281					{
1282						otherFunctions();
1283					}
1284					my.refresh();
1285				};
1286			}
1287		}
1288	};
1289}
1290
1291/* DOMContentLoaded event handler - by Tanny O'Haley [4] */
1292var domReadyEvent =
1293{
1294	name: "domReadyEvent",
1295	/* Array of DOMContentLoaded event handlers.*/
1296	events: {},
1297	domReadyID: 1,
1298	bDone: false,
1299	DOMContentLoadedCustom: null,
1300
1301	/* Function that adds DOMContentLoaded listeners to the array.*/
1302	add: function(handler)
1303	{
1304		/* Assign each event handler a unique ID. If the handler has an ID, it has already been added to the events object or been run.*/
1305		if (!handler.$$domReadyID)
1306		{
1307			handler.$$domReadyID = this.domReadyID++;
1308
1309			/* If the DOMContentLoaded event has happened, run the function. */
1310			if(this.bDone)
1311			{
1312				handler();
1313			}
1314
1315			/* store the event handler in the hash table */
1316			this.events[handler.$$domReadyID] = handler;
1317		}
1318	},
1319
1320	remove: function(handler)
1321	{
1322		/* Delete the event handler from the hash table */
1323		if (handler.$$domReadyID)
1324		{
1325			delete this.events[handler.$$domReadyID];
1326		}
1327	},
1328
1329	/* Function to process the DOMContentLoaded events array. */
1330	run: function()
1331	{
1332		/* quit if this function has already been called */
1333		if (this.bDone)
1334		{
1335			return;
1336		}
1337
1338		/* Flag this function so we don't do the same thing twice */
1339		this.bDone = true;
1340
1341		/* iterates through array of registered functions */
1342		for (var i in this.events)
1343		{
1344			this.events[i]();
1345		}
1346	},
1347
1348	schedule: function()
1349	{
1350		/* Quit if the init function has already been called*/
1351		if (this.bDone)
1352		{
1353			return;
1354		}
1355
1356		/* First, check for Safari or KHTML.*/
1357		if(/KHTML|WebKit/i.test(navigator.userAgent))
1358		{
1359			if(/loaded|complete/.test(document.readyState))
1360			{
1361				this.run();
1362			}
1363			else
1364			{
1365				/* Not ready yet, wait a little more.*/
1366				setTimeout(this.name + ".schedule()", 100);
1367			}
1368		}
1369		else if(document.getElementById("__ie_onload"))
1370		{
1371			/* Second, check for IE.*/
1372			return true;
1373		}
1374
1375		/* Check for custom developer provided function.*/
1376		if(typeof this.DOMContentLoadedCustom === "function")
1377		{
1378			/* if DOM methods are supported, and the body element exists (using a double-check
1379			including document.body, for the benefit of older moz builds [eg ns7.1] in which
1380			getElementsByTagName('body')[0] is undefined, unless this script is in the body section) */
1381			if(typeof document.getElementsByTagName !== 'undefined' && (document.getElementsByTagName('body')[0] !== null || document.body !== null))
1382			{
1383				/* Call custom function. */
1384				if(this.DOMContentLoadedCustom())
1385				{
1386					this.run();
1387				}
1388				else
1389				{
1390					/* Not ready yet, wait a little more. */
1391					setTimeout(this.name + ".schedule()", 250);
1392				}
1393			}
1394		}
1395		return true;
1396	},
1397
1398	init: function()
1399	{
1400		/* If addEventListener supports the DOMContentLoaded event.*/
1401		if(document.addEventListener)
1402		{
1403			document.addEventListener("DOMContentLoaded", function() { domReadyEvent.run(); }, false);
1404		}
1405
1406		/* Schedule to run the init function.*/
1407		setTimeout("domReadyEvent.schedule()", 100);
1408
1409		function run()
1410		{
1411			domReadyEvent.run();
1412		}
1413
1414		/* Just in case window.onload happens first, add it to onload using an available method.*/
1415		if(typeof addEvent !== "undefined")
1416		{
1417			addEvent(window, "load", run);
1418		}
1419		else if(document.addEventListener)
1420		{
1421			document.addEventListener("load", run, false);
1422		}
1423		else if(typeof window.onload === "function")
1424		{
1425			var oldonload = window.onload;
1426			window.onload = function()
1427			{
1428				domReadyEvent.run();
1429				oldonload();
1430			};
1431		}
1432		else
1433		{
1434			window.onload = run;
1435		}
1436
1437		/* for Internet Explorer */
1438		/*@cc_on
1439			@if (@_win32 || @_win64)
1440			document.write("<script id=__ie_onload defer src=\"//:\"><\/script>");
1441			var script = document.getElementById("__ie_onload");
1442			script.onreadystatechange = function()
1443			{
1444				if (this.readyState == "complete")
1445				{
1446					domReadyEvent.run(); // call the onload handler
1447				}
1448			};
1449			@end
1450		@*/
1451	}
1452};
1453
1454var domReady = function(handler) { domReadyEvent.add(handler); };
1455domReadyEvent.init();
1456
1457
1458/* Create ImageFlow instances when the DOM structure has been loaded */
1459domReady(function()
1460{
1461	var instanceOne = new ImageFlow();
1462	instanceOne.init({ ImageFlowID:'myImageFlow' });
1463});

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.