PageSourceSearch

https://www.tbl.com.pk/wp-content/plugins/wp-imageflow2/js/wpflowplus.js?ver=1611729398

js tbl.com.pk collected 2026-10-05 10:58:25 UTC 51,480 bytes, 1,400 lines download raw bytes

1/**
2 *	WPFlowPlus 3.4
3 *
4 *	This is the bonus version of the WP Flow Plus WordPress plugin javascript.
5 *
6 *  This provides a Flow style gallery with the following features:
7 *  - Lightbox pop-ups when linking to an image
8 *  - Optional linking to an external url rather than an image
9 *	- Supports multiple instances and avoid collisions with other scripts by using object-oriented code
10 *
11 *  Copyright Spiffy Plugins http://www.spiffyplugins.ca
12 *
13 *	Version 1.1 adds auto-rotation option (May 3, 2010)
14 *	Version 1.2 adds startimg option, longdesc may be link or text description (May 13, 2010)
15 *	Version 1.3 fixes bug when gallery has only one image
16 *	Version 1.4 don't display top box caption if it is the same as the top box title
17 *	Version 1.5 fix image load in lightbox and slider width calculations
18 *	Version 1.6 adds support for touch screen, sameWindow option, add class to centered image (Nov. 2012)
19 *	Version 1.7 improves support when no images are included, change longdesc to data-link and rel to data-style
20 *	Version 1.8 use data-description for passing description
21 *	Version 2.0 move to image block format, swipe on image support
22 *  Version 2.1 modify tap to open data-link instead of image URL
23 *  Version 2.2 fix issue when mobile device resize runs before initial onload
24 *	Version 3.0 circular carousel (June, 2015)
25 *  Version 3.1 fix circular carousel issues (January, 2016)
26 *  Version 3.2 add format extensions, fix resize for multiple funcs (June 2016)
27 *  Version 3.3 only reset the current image on the first load to avoid gallery jumping to start point when screen resized
28 *  Version 3.4 call loaded on init if document loaded before this script had a chance to run
29 *
30 *  Resources ----------------------------------------------------
31 *	[1] http://www.adventuresinsoftware.com/blog/?p=104#comment-1981, Michael L. Perry's Cover Flow
32 *	[2] http://www.finnrudolph.de/, Finn Rudolph's imageflow, version 0.9 
33 *	[3] http://reflection.corephp.co.uk/v2.php, Richard Davey's easyreflections in PHP
34 *	[4] http://adomas.org/javascript-mouse-wheel, Adomas Paltanavicius JavaScript mouse wheel code
35 *	[5] Touch screen control derived from scripts courtesy of PADILICIOUS.COM and MACOSXAUTOMATION.COM
36 *    --------------------------------------------------------------
37 */
38
39function flowplus(instance) {
40
41	/* Options */
42	this.defaults =
43	{
44		aspectRatio:		1.9,		// Gallery div width / height
45		autoRotate:			'off',		// Sets auto-rotate option 'on' or 'off', default is 'off'
46		autoRotatepause: 	3000,		// Set the pause delay in the auto-rotation
47		circular:			false,		// Circular carousel option
48		focus:				4,			// Sets the numbers of images on each side of the focused one
49		imagesCursor:		'pointer',  // Sets the cursor type for all images default is 'default'
50		reflectPC:			1,			// Percentage of image height in reflection, 0 = no reflection, 1 = full reflection
51		sameWindow:			false,		// Open links in same window vs the default of opening in new window
52		sliderWidth:		14,         // Sets the px width of the slider div
53		startImg:			1,			// Starting focused image
54		sliderCursor:		'default',	// Sets the slider cursor type: try "e-resize" default is 'default'
55		sliderStyle:		'baseline'	// Slider style, default is the original carousel
56	};
57
58
59	/* HTML div ids that we manipulate here */
60	this.ifp_flowplusdiv =		'wpif2_flowplus_' + instance;
61	this.ifp_loadingdiv =		'wpif2_loading_' + instance;
62	this.ifp_imagesdiv =		'wpif2_images_' + instance;
63	this.ifp_captionsdiv =		'wpif2_captions_' + instance;
64	this.ifp_sliderdiv =		'wpif2_slider_' + instance;
65	this.ifp_scrollbardiv =		'wpif2_scrollbar_' + instance;
66	/* The overlay is shared among all instances */
67	this.ifp_overlaydiv =		'wpif2_overlay';
68	this.ifp_overlayclosediv =	'wpif2_overlayclose';
69	this.ifp_topboxdiv =		'wpif2_topbox';
70	this.ifp_topboximgdiv =		'wpif2_topboximg';
71	this.ifp_topboxcaptiondiv =	'wpif2_topboxcaption';
72	this.ifp_topboxprevdiv =	'wpif2_topboxprev';
73	this.ifp_topboxclosediv =	'wpif2_topboxclose';
74	this.ifp_topboxnextdiv =	'wpif2_topboxnext';
75
76	/* Define global variables */
77	this.image_id =		0;
78	this.new_image_id =	0;
79	this.current =		0;
80	this.target =		0;
81	this.mem_target =	0;
82	this.timer =		0;				// set when timeout is active, we are gliding
83	this.array_images =	[];
84	this.ifp_slider_width =	0;
85	this.new_slider_pos =	0;
86	this.dragging =		false;
87	this.dragobject =	null;
88	this.dragx =		0;
89	this.posx =			0;
90	this.new_posx =		0;
91	this.xstep =		150;			// step size in px
92	this.autorotate = 	'off';
93	this.rotatestarted = 'false';
94	this.first_refresh = true;
95	this.image_offset =	0;
96	this.slider_type =	'carousel';		// 'carousel' or 'book'
97
98	var thisObject = this;
99
100	/* Initialize */
101	this.init = function(options) {
102		/* Evaluate options */
103		for (var name in thisObject.defaults) {
104			this[name] = (options !== undefined && options[name] !== undefined) ? options[name] : thisObject.defaults[name];
105		}		
106		
107		/* Set style to baseline if the browser can't handle advanced styles */
108		if (((this.sliderStyle == 'flip') || (this.sliderStyle == 'explode')) && !this.supports_3d()) {
109			thisObject.sliderStyle = thisObject.defaults['sliderStyle'];
110		}
111		
112		/* Define slider orientation */
113		if ((this.sliderStyle == 'flip') || (this.sliderStyle == 'explode')) this.slider_type = 'book';
114		
115		/* Create circular list */
116		thisObject.load_circular();
117
118		/* Catch case where page loads before this script has time to run */
119		if (document.readyState === 'complete') {
120			thisObject.loaded();
121		  }			
122	};
123
124	/* Check if browser supports 3D transform */
125	this.supports_3d = function () {
126		if (!window.getComputedStyle) {
127			return false;
128		}
129
130		var el = document.createElement('p'), 
131			has3d,
132			transforms = {
133				'webkitTransform':'-webkit-transform',
134				'OTransform':'-o-transform',
135				'msTransform':'-ms-transform',
136				'MozTransform':'-moz-transform',
137				'transform':'transform'
138			};
139
140		// Add it to the body to get the computed style.
141		document.body.insertBefore(el, null);
142
143		for (var t in transforms) {
144			if (el.style[t] !== undefined) {
145				el.style[t] = "translate3d(1px,1px,1px)";
146				has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
147			}
148		}
149
150		document.body.removeChild(el);
151
152		return (has3d !== undefined && has3d.length > 0 && has3d !== "none");
153	}
154		
155	/* Show/hide element functions */
156	this.show = function(id) {
157		var element = document.getElementById(id);
158		element.style.visibility = 'visible';
159	};
160	this.hide = function(id) {
161		var element = document.getElementById(id);
162		element.style.visibility = 'hidden';
163		element.style.display = 'none';
164	};
165
166	/* Animation step control */
167	this.step = function() {
168		if (thisObject.target < thisObject.current-1 || thisObject.target > thisObject.current+1) 
169		{
170			if (thisObject.slider_type == 'book') {
171				/* Jump directly to target */
172				thisObject.moveTo(thisObject.target, true);
173				thisObject.timer = 0;				
174			} else {
175				/* Animate steps to target */
176				thisObject.moveTo(thisObject.current + (thisObject.target-thisObject.current)/3, true);
177				setTimeout(thisObject.step, 50);
178				thisObject.timer = 1;
179			}
180		} else {
181			thisObject.timer = 0;
182		}
183	};
184
185	/*
186	**	Specify new focussed image ID (0 to max-1)
187	*/
188	this.glideTo = function(new_image_id) {
189		
190		if (this.max <= 1) return;
191		
192		var jumpTarget, clonedImageID;
193		if (thisObject.circular) {
194			
195			/* If we are moving to a cloned image, jump to the original version of the image. */
196			
197			/* New image is part of beginning cloned set, jump to the right */
198			if (new_image_id < thisObject.focus) {
199				
200				/* Set jump target to the same (current) image on the right */
201				//clonedImageID = thisObject.max - thisObject.focus;
202				clonedImageID = thisObject.max - 2*thisObject.focus + new_image_id + 1;
203				jumpTarget = -clonedImageID * this.xstep;
204
205				/* Set the imageID to glide to the original version of the target image */
206				new_image_id = clonedImageID-1;
207			}
208
209			/* New image is part of end cloned set, jump to the left */
210			if (new_image_id >= (thisObject.max - thisObject.focus)) {
211				
212				/* Set jump target to the same (current) image on the left */
213				clonedImageID = 2 * thisObject.focus - (thisObject.max - new_image_id + 1);
214				jumpTarget = -clonedImageID * this.xstep;
215				
216				/* Set the imageID to glide to the original version of the target image */
217				new_image_id = clonedImageID+1;
218			}
219		}
220		/* Move the images to the jump target to position properly before gliding */
221		if (jumpTarget) {
222			this.mem_target = jumpTarget;
223			this.image_id = clonedImageID;
224			thisObject.moveTo(jumpTarget, false);
225		}
226		
227		/* Record our new target position */
228		var x = (-new_image_id * this.xstep);
229		this.target = x;
230		this.mem_target = x;
231		this.image_id = new_image_id;
232			
233		/* Animate gliding to new image */
234		if (this.timer == 0)
235		{
236			window.setTimeout(thisObject.step, 50);
237			this.timer = 1;
238		}
239		
240		/* Display new caption */
241		var caption = this.imgs_div.childNodes.item(this.array_images[this.image_id]).childNodes.item(0).getAttribute('alt');
242		if (caption == '') { caption = '&nbsp;'; }
243		this.caption_div.innerHTML = caption;
244
245		/* Set scrollbar slider to new position */
246		if (this.dragging === false)
247		{
248			this.new_slider_pos = ((new_image_id-this.image_offset) * this.scrollbar_width) / (this.max-(this.image_offset*2)-1) - this.new_posx;
249			this.slider_div.style.marginLeft = (this.new_slider_pos - this.ifp_slider_width) + 'px';
250		}
251	};
252
253	/* Handle automatic rotation */
254	this.rotate = function()
255	{
256		/* Do nothing if autorotate has been turned off */
257		if (thisObject.autorotate == "on") {
258			if (thisObject.image_id >= thisObject.max-1) {
259				thisObject.glideTo(0);
260			} else {
261				thisObject.glideTo(thisObject.image_id+1);
262			}
263		}
264
265		if (thisObject.autoRotate == 'on') {
266			/* Set up next auto-glide */
267			window.setTimeout (thisObject.rotate, thisObject.autoRotatepause);
268		}
269	}
270
271	/* 
272	** Animation step 
273	**
274	** x = image_id * step
275	** animated = true/false to animate the transition
276	*/
277	this.moveTo = function(x, animated)
278	{
279		this.current = x;
280		var zIndex = this.max;
281		var book_angle = 10;
282		
283		/* Main loop */
284		for (var index = 0; index < this.max; index++)
285		{
286			var image_block = this.imgs_div.childNodes.item(this.array_images[index]);
287			var image = image_block.childNodes.item(0);
288			var current_image = index * -this.xstep;
289
290			if (animated == false) {
291				image_block.style.transition = '0s';
292			} else {
293				image_block.style.removeProperty('transition');
294				image_block.style.visibility = 'visible';
295			}
296			image_block.style.removeProperty('transform');
297
298			/* Don't display images that are not focused */
299			if ((current_image+this.max_focus) < this.mem_target || (current_image-this.max_focus) > this.mem_target)
300			{
301				jQuery(image_block).removeClass("wpif2-centered wpif2-right wpif2-left");
302				image_block.style.visibility = 'hidden';
303				image_block.style.display = 'none';
304			}
305			else 
306			{
307				var z = Math.sqrt(10000 + x * x) + 100;
308				var xs = x / z * this.size + this.size;
309
310				/* Still hide images until they are processed, but set display style to block */
311				image_block.style.display = 'block';
312
313				/* Calculate new image height and image width */
314				var current_pc = image_block.pc;
315				if (image_block.i == thisObject.image_id) {
316					current_pc = 120;
317				}
318
319				if (this.slider_type == 'book') {
320					// all images equal width and centered
321					var new_img_w = this.size;
322					var new_img_h = Math.round(image_block.h / (image_block.w / new_img_w));
323					image_block.style.left = this.images_width / 2 - new_img_w / 2 + 'px';
324				} else {
325					var new_img_h = Math.round((image_block.h / image_block.w * current_pc) / z * this.size);
326					var new_img_w = Math.round(current_pc / z * this.size);
327					image_block.style.left = Math.round(xs - (current_pc / 2) / z * this.size) + 'px';
328				}
329				
330				if (this.sliderStyle == 'midline') {
331					var new_img_top = Math.round(this.images_height/2 - new_img_h/(2 + 2*this.reflectPC));
332				} else {
333					var new_img_top = Math.round(this.images_height - new_img_h/(1 + this.reflectPC));
334				}
335				/* Set new image properties */
336				if (new_img_w && new_img_h)
337				{ 
338					image_block.style.height = new_img_h + 'px'; 
339					image_block.style.width = new_img_w + 'px'; 
340					image_block.style.top = new_img_top + 'px';
341
342					/* this is needed to make IE8 behave */
343					image.style.width = new_img_w + 'px';
344					image.style.height = 'auto';
345				}
346
347				/* Set image layer through zIndex */
348				if (this.slider_type == 'book'){
349					zIndex--;
350				} else {
351					if ( x < 0 ) {
352						zIndex++;
353					} else {
354						zIndex = zIndex - 1;
355					}
356				}
357				
358				/* Change zIndex, class and onclick function of the focused image */
359				if (image_block.i == thisObject.image_id ) { 
360					if (this.slider_type != 'book') zIndex = zIndex + 1;
361					image_block.style.zIndex = zIndex;
362					
363					// update class
364					if (!jQuery(image_block).hasClass("wpif2-centered")) {
365						// Set new centered image class and attributes
366						jQuery(image_block).addClass("wpif2-centered");
367						jQuery(image_block).removeClass("wpif2-right wpif2-left");
368						
369						if (image.getAttribute("data-style") && (image.getAttribute("data-style") == 'wpif2_lightbox')) {
370							image.setAttribute("title",image.getAttribute('alt'));
371							image_block.onclick = function () { thisObject.autoRotate = "off"; thisObject.showTop(this); return false; };
372						} else if (this.sameWindow) {
373							image_block.onclick = function() { window.location = this.url; return false; };
374						} else {
375							image_block.onclick = function() { window.open (this.url); return false; };
376						}	
377												
378						// time to make the image visible
379						image_block.style.visibility = 'visible';
380					}
381				} else {
382					image_block.onclick = function() { thisObject.autorotate = "off"; thisObject.glideTo(this.i); return false; };
383					image_block.style.zIndex = zIndex;
384					var was_centered = false;
385					
386					if (jQuery(image_block).hasClass("wpif2-centered")) {
387						jQuery(image_block).removeClass("wpif2-centered");
388						was_centered = true;
389					}
390					if (image_block.i < thisObject.image_id) {
391						// if flipping from centered to left, animate the transition (default is instant)
392						if ((this.slider_type == 'book') && was_centered) {
393							image_block.style.transition = 'transform .5s, visibility .3s, opacity .3s, width 0s';
394						}
395
396						jQuery(image_block).addClass("wpif2-left");
397						jQuery(image_block).removeClass("wpif2-right");
398						if (this.slider_type != 'book') {
399							image_block.style.visibility = 'visible';
400						} else {
401							image_block.style.visibility = 'hidden';							
402						}
403					} else {
404						// if flipping from left to right, hide the transition
405						if ((this.slider_type == 'book') && (jQuery(image_block).hasClass("wpif2-left"))) {
406							image_block.style.transition = '0s';
407						}
408						
409						// fix firefox z-index issues
410						if (this.slider_type == 'book') { 
411							image_block.style.transform = 'rotateX('+book_angle+'deg)';
412							if (book_angle < 90) book_angle += 10;
413						}
414						jQuery(image_block).addClass("wpif2-right");
415						jQuery(image_block).removeClass("wpif2-left");
416						image_block.style.visibility = 'visible';
417					}
418				}
419
420				
421
422			}
423			x += this.xstep;
424		}
425	};
426
427	/* Main setup once loaded or window resizes */
428	this.refresh = function(onload)
429	{
430		/* Ignore refresh until the first onload is done */
431		if (this.first_refresh && !onload) return;
432		this.first_refresh = false;
433		
434		/* Cache document objects in global variables */
435		this.flowplus_div = document.getElementById(this.ifp_flowplusdiv);
436		//this.imgs_div = document.getElementById(this.ifp_imagesdiv); // set in load_circular
437		this.scrollbar_div = document.getElementById(this.ifp_scrollbardiv);
438		this.slider_div = document.getElementById(this.ifp_sliderdiv);
439		this.caption_div = document.getElementById(this.ifp_captionsdiv);
440
441		/* Cache global variables, that only change on refresh */
442		this.images_width = this.imgs_div.offsetWidth;
443		this.images_top = this.flowplus_div.offsetTop;
444		this.images_left = this.flowplus_div.offsetLeft;
445
446		this.max_focus = this.focus * this.xstep;
447		this.scrollbar_width = Math.round(this.images_width * 0.6);
448		this.ifp_slider_width = this.sliderWidth * 0.5;
449		this.max_height = Math.round(thisObject.images_width / thisObject.aspectRatio);
450		if (this.reflectPC == 0) {
451			this.images_height = Math.round(thisObject.max_height * .8);
452			
453		} else {
454			this.images_height = Math.round(thisObject.max_height * .67);
455		}
456		this.size = this.images_width * 0.5;
457
458		/* Adjust size of book style galleries to fit all images height with equal width */
459		if (this.slider_type == 'book') {
460			var maxHeight = 0;
461			jQuery(this.imgs_div).find('.wpif2_image_block > img').each(function() { 
462				var scaledHeight = jQuery(this).height() * thisObject.size / jQuery(this).width()
463				maxHeight = Math.max(maxHeight, scaledHeight);
464			});
465			if (maxHeight > this.images_height) {
466				this.size = (this.size * this.images_height / maxHeight) - 10;
467			}
468		} 
469		
470		/* Change flowplus div properties */
471		this.flowplus_div.className += " wpif2-" + this.sliderStyle;
472		this.flowplus_div.onmouseover = function () { thisObject.autorotate = 'off'; return false; };
473		this.flowplus_div.onmouseout = function () { thisObject.autorotate = thisObject.autoRotate; return false; };
474		this.flowplus_div.style.height = this.max_height + 'px';
475
476		/* Change images div properties */
477		if (this.slider_type == 'book') this.imgs_div.className += ' wpif2-book';
478		this.imgs_div.style.height = this.images_height + 'px';
479
480		/* Change captions div properties */
481		this.caption_div.style.width = this.images_width + 'px';
482		this.caption_div.style.marginTop = this.images_width * 0.03 + 'px';
483
484		/* Change and record scrollbar div properties */
485		this.scrollbar_div.style.marginTop = this.images_width * 0.02 + 'px';
486		this.scrollbar_div.style.marginLeft = this.images_width * 0.2 + 'px';
487		this.scrollbar_div.style.width = this.scrollbar_width + 'px';
488		
489		this.scrollbar_left = this.scrollbar_div.offsetLeft;
490		this.scrollbar_right = this.scrollbar_div.offsetLeft + this.scrollbar_div.offsetWidth;
491
492		/* Set slider attributes */
493		this.slider_div.onmousedown = function () { thisObject.dragstart(this); return false; };
494		this.slider_div.style.cursor = this.sliderCursor;
495
496		/* Cache EVERYTHING! */
497		this.max = this.imgs_div.childNodes.length;
498		var i = 0;
499		for (var index = 0; index < this.max; index++)
500		{ 
501			var image_block = this.imgs_div.childNodes.item(index);
502			if ((image_block.nodeType == 1) && (image_block.nodeName != "NOSCRIPT"))
503			{
504				this.array_images[i] = index;
505				
506				/* First child of image block is the image */
507				var image = image_block.childNodes.item(0);
508				
509				/* Set image block onclick to glide to this image */
510				image_block.onclick = function() { thisObject.autoRotate = "off"; thisObject.glideTo(this.i); return false; };
511				image_block.x_pos = (-i * this.xstep);
512				image_block.i = i;
513				
514				/* Add width and height as attributes ONLY once onload */
515				if (onload === true)
516				{
517					image_block.w = jQuery(image_block).width();
518					image_block.h = jQuery(image_block).height();
519				}
520
521				/* Check source image format. */
522				if ((image_block.w + 1) > (image_block.h)) 
523				{
524					/* Landscape format */
525					image_block.pc = 118;
526				} else {
527					/* Portrait and square format */
528					image_block.pc = 100;
529				}
530
531				/* Set ondblclick event */
532				image_block.url = image.getAttribute('data-link');
533				if (image.getAttribute("data-style") && (image.getAttribute("data-style") == 'wpif2_lightbox')) {
534					image_block.setAttribute("title",image.getAttribute('alt'));
535
536					image_block.ondblclick = function () { thisObject.autoRotate = 'off'; thisObject.showTop(this);return false; }
537				} else if (this.sameWindow) {
538					image_block.ondblclick = function() { window.location = this.url; }
539				} else { 
540					image_block.ondblclick = function() { window.open (this.url); }
541				}
542				/* Set image cursor type */
543				image_block.style.cursor = this.imagesCursor;
544
545				i++;
546			}
547		}
548		this.max = this.array_images.length;
549
550		/* Display images in current order */
551		if (onload) {
552			if ((this.startImg > 0) && (this.startImg <= this.max))	{
553				this.image_id = this.startImg + this.image_offset - 1;
554				this.mem_target = (-this.image_id * this.xstep);
555				this.current = this.mem_target;
556			} else {
557				this.image_id = this.image_offset;
558			}
559		}
560		
561		this.moveTo(this.current, false);
562		this.glideTo(this.image_id);
563
564		/* If autorotate on, set up next glide */
565		this.autorotate = this.autoRotate;
566		if ((this.autorotate == "on") && (this.rotatestarted == "false")) {
567			window.setTimeout (thisObject.rotate, thisObject.autoRotatepause);
568			this.rotatestarted = 'true';
569		}
570	};
571
572	/* Action to take when loaded */
573	this.loaded = function()
574	{
575		if(document.getElementById(thisObject.ifp_flowplusdiv))
576		{
577			if (document.getElementById(thisObject.ifp_overlaydiv) === null) {
578				/* Append overlay divs to the page - the overlay is shared by all instances */
579				var objBody = document.getElementsByTagName("body").item(0);
580
581				/* -- overlay div */
582				var objOverlay = document.createElement('div');
583				objOverlay.setAttribute('id',thisObject.ifp_overlaydiv);
584				objOverlay.onclick = function() { thisObject.closeTop(); return false; };
585				objBody.appendChild(objOverlay);
586				jQuery("#"+thisObject.ifp_overlaydiv).fadeTo("fast", .7);
587		
588				/* -- top box div */
589				var objLightbox = document.createElement('div');
590				objLightbox.setAttribute('id',thisObject.ifp_topboxdiv);
591				objBody.appendChild(objLightbox);
592
593				/* ---- image div */
594				var objLightboxImage = document.createElement("img");
595				//objLightboxImage.onclick = function() { thisObject.closeTop(); return false; };
596				objLightboxImage.setAttribute('id',thisObject.ifp_topboximgdiv);
597				objLightbox.appendChild(objLightboxImage);
598
599				/* ---- prev link */
600				var objPrev = document.createElement("a");
601				objPrev.setAttribute('id',thisObject.ifp_topboxprevdiv);
602				objPrev.setAttribute('href','#');
603				objLightbox.appendChild(objPrev);
604
605				/* ---- next link */
606				var objNext = document.createElement("a");
607				objNext.setAttribute('id',thisObject.ifp_topboxnextdiv);
608				objNext.setAttribute('href','#');
609				objLightbox.appendChild(objNext);
610
611				/* ---- caption div */
612				var objCaption = document.createElement("div");
613				objCaption.setAttribute('id',thisObject.ifp_topboxcaptiondiv);
614				objLightbox.appendChild(objCaption);
615
616				/* ---- close link */
617				var objClose = document.createElement("a");
618				objClose.setAttribute('id',thisObject.ifp_topboxclosediv);
619				objClose.setAttribute('href','#');
620				objLightbox.appendChild(objClose);
621
622				objClose.onclick = function () { thisObject.closeTop(); return false; };
623				objClose.innerHTML = "Close";
624			}
625
626			/* hide loading bar, show content and initialize mouse event listening after loading */
627			thisObject.hide(thisObject.ifp_loadingdiv);
628			//thisObject.load_circular(); moved to init() for OS X 10.10 Safari 9
629			thisObject.refresh(true);
630			thisObject.show(thisObject.ifp_imagesdiv);
631			thisObject.show(thisObject.ifp_scrollbardiv);
632			thisObject.initMouseWheel();
633			thisObject.initMouseDrag();
634			thisObject.Touch.touch_init();
635		}
636	};
637
638	this.unloaded = function()
639	{
640		/* Fixes the back button issue */
641		document = null;
642	};
643	
644	/* Set up image list */
645	this.load_circular = function() {
646		
647		thisObject.imgs_div = document.getElementById(this.ifp_imagesdiv);
648		
649		/* Clone images for circular carousel */
650		if (thisObject.circular) {
651
652			/* Remove nodes that are not image blocks (extraneous CR, etc) */
653			for (var n = 0; n < thisObject.imgs_div.childNodes.length; n++) {
654				if ((thisObject.imgs_div.childNodes[n].nodeType != 1) || (thisObject.imgs_div.childNodes[n].nodeName == "NOSCRIPT")) {
655					thisObject.imgs_div.removeChild(thisObject.imgs_div.childNodes[n]);
656					n --;
657				}
658			}
659			
660			/* Make sure, that there are enough images to use circular mode */
661			max = thisObject.imgs_div.childNodes.length;
662			if (max < thisObject.focus) {
663				thisObject.focus = max;
664			}
665
666			/* Do not clone anything if there is only one image */
667			if (max > 1) {
668				/* Create temporary element to hold the front cloned images */
669				var last = document.createElement("div");
670
671				/* Clone the first and last images. First image clones go to the end of the list, 
672				** last images clones go to the front */
673				for (i = 0; i < max; i++)
674				{
675					/* Number of clones on each side equals the focus */
676					node = thisObject.imgs_div.childNodes[i];
677					if (i < thisObject.focus) {
678						imageNode = node.cloneNode(true);
679						thisObject.imgs_div.appendChild(imageNode);
680					}
681					if (max-i < thisObject.focus+1) {
682						imageNode = node.cloneNode(true);
683						last.appendChild(imageNode);
684					}
685				}
686
687				/* Insert the last image clones at the front */
688				for (i = this.focus-1; i >= 0; i--) {
689					thisObject.imgs_div.insertBefore(last.childNodes[i], thisObject.imgs_div.childNodes[0]);
690				}
691								
692				/* Define image offset used throughout the script to account for the extra images at the front */
693				thisObject.image_offset = thisObject.focus;
694			}
695		}
696	}
697
698	/* Handle the wheel angle change (delta) of the mouse wheel */
699	this.handle = function(delta)
700	{
701		var change = false;
702		if (delta > 0)
703		{
704			if(this.image_id >= 1)
705			{
706				this.target = this.target + this.xstep;
707				this.new_image_id = this.image_id - 1;
708				change = true;
709			}
710		} else {
711			if(this.image_id < (this.max-1))
712			{
713				this.target = this.target - this.xstep;
714				this.new_image_id = this.image_id + 1;
715				change = true;
716			}
717		}
718
719		/* Glide to next (mouse wheel down) / previous (mouse wheel up) image */
720		if (change === true)
721		{
722			this.glideTo(this.new_image_id);
723			this.autorotate = "off";
724		}
725	};
726
727	/* Event handler for mouse wheel event */
728	this.wheel = function(event)
729	{
730		var delta = 0;
731		if (!event) event = window.event;
732		if (event.wheelDelta)
733		{
734			delta = event.wheelDelta / 120;
735		}
736		else if (event.detail)
737		{
738			delta = -event.detail / 3;
739		}
740		if (delta) thisObject.handle(delta);
741		if (event.preventDefault) event.preventDefault();
742		event.returnValue = false;
743	};
744
745	/* Initialize mouse wheel event listener */
746	this.initMouseWheel = function()
747	{
748		if(window.addEventListener) {
749			this.flowplus_div.addEventListener('DOMMouseScroll', this.wheel, false);
750		}
751		this.flowplus_div.onmousewheel = this.wheel;
752	};
753
754	/* This function is called to drag an object (= slider div) */
755	this.dragstart = function(element)
756	{
757		thisObject.dragobject = element;
758		thisObject.dragx = thisObject.posx - thisObject.dragobject.offsetLeft + thisObject.new_slider_pos;
759
760		thisObject.autorotate = "off";
761	};
762
763	/* This function is called to stop dragging an object */
764	this.dragstop = function()
765	{
766		thisObject.dragobject = null;
767		thisObject.dragging = false;
768	};
769
770	/* This function is called on mouse movement and moves an object (= slider div) on user action */
771	this.drag = function(e)
772	{
773		thisObject.posx = document.all ? window.event.clientX : e.pageX;
774		if(thisObject.dragobject != null)
775		{
776			thisObject.dragging = true;
777			thisObject.new_posx = (thisObject.posx - thisObject.dragx) + thisObject.ifp_slider_width;
778
779			/* Make sure, that the slider is moved in proper relation to previous movements by the glideTo function */
780			if(thisObject.new_posx < ( - thisObject.new_slider_pos)) thisObject.new_posx = 
780- thisObject.new_slider_pos;
781			if(thisObject.new_posx > (thisObject.scrollbar_width - thisObject.new_slider_pos)) thisObject.new_posx = thisObject.scrollbar_width - thisObject.new_slider_pos;
782			
783			var slider_pos = (thisObject.new_posx + thisObject.new_slider_pos);
784			var step_width = slider_pos / ((thisObject.scrollbar_width) / (thisObject.max-(thisObject.image_offset*2)-1));
785			var image_number = Math.round(step_width) + thisObject.image_offset;
786			var new_target = (image_number) * -thisObject.xstep;
787			var new_image_id = image_number;
788
789			thisObject.dragobject.style.left = thisObject.new_posx + 'px';
790			thisObject.glideTo(new_image_id);
791		}
792	};
793
794	/* Initialize mouse event listener */
795	this.initMouseDrag = function()
796	{
797		thisObject.flowplus_div.onmousemove = thisObject.drag;
798		thisObject.flowplus_div.onmouseup = thisObject.dragstop;
799
800		/* Avoid text and image selection while this.dragging  */
801		document.onselectstart = function () 
802		{
803			if (thisObject.dragging === true)
804			{
805				return false;
806			}
807			else
808			{
809				return true;
810			}
811		}
812	};
813
814	this.getKeyCode = function(event)
815	{
816		event = event || window.event;
817		return event.keyCode;
818	};
819
820
821	this.Touch = {
822		// TOUCH-EVENTS SINGLE-FINGER SWIPE-SENSING JAVASCRIPT
823		// Courtesy of PADILICIOUS.COM and MACOSXAUTOMATION.COM
824		
825		// this script can be used with one or more page elements to perform actions based on them being swiped with a single finger
826
827		triggerElementID : null, // this variable is used to identity the triggering element
828		fingerCount : 0,
829		startX : 0,
830		startY : 0,
831		curX : 0,
832		curY : 0,
833		deltaX : 0,
834		deltaY : 0,
835		horzDiff : 0,
836		vertDiff : 0,
837		minLength : 10, // the shortest distance the user may swipe
838		swipeLength : 0,
839		swipeAngle : null,
840		swipeDirection : null,
841		
842		// The 4 Touch Event Handlers
843		
844		// NOTE: the touch_start handler should also receive the ID of the triggering element
845		// make sure its ID is passed in the event call placed in the element declaration, like:
846		// <div id="picture-frame" ontouchstart="touch_start(event,'picture-frame');"  
847		//	ontouchend="touch_end(event);" ontouchmove="touch_move(event);" ontouchcancel="touch_cancel(event);">
848
849		touch_init : function() { 
850			thisObject.slider_div.ontouchstart = function(event) { thisObject.Touch.touch_start(event,thisObject.ifp_sliderdiv); return false; };
851			thisObject.slider_div.ontouchend = function(event) { thisObject.Touch.touch_end(event); return false; };
852			thisObject.slider_div.ontouchmove = function(event) { thisObject.Touch.touch_move(event); return false; };
853			thisObject.slider_div.ontouchcancel = function(event) { thisObject.Touch.touch_cancel(event); return false; };
854			
855			thisObject.imgs_div.ontouchstart = function(event) { thisObject.Touch.touch_start(event,thisObject.ifp_imagesdiv); return false; };
856			thisObject.imgs_div.ontouchend = function(event) { thisObject.Touch.touch_end(event); return false; };
857			thisObject.imgs_div.ontouchmove = function(event) { thisObject.Touch.touch_move(event); return false; };
858			thisObject.imgs_div.ontouchcancel = function(event) { thisObject.Touch.touch_cancel(event); return false; };
859
860			topbox_div = document.getElementById(thisObject.ifp_topboxdiv);
861			topbox_div.ontouchstart = function(event) { thisObject.Touch.touch_start(event,thisObject.ifp_topboxdiv); return false; };
862			topbox_div.ontouchend = function(event) { thisObject.Touch.touch_end(event); return false; };
863			//topbox_div.ontouchmove = function(event) { thisObject.Touch.touch_move(event); return false; };
864			topbox_div.ontouchcancel = function(event) { thisObject.Touch.touch_cancel(event); return false; };
865		},
866
867		touch_start : function (event,passedName) { 
868			this.touch_reset(event);
869	 
870			// disable the standard ability to select the touched object
871			event.preventDefault();
872			// get the total number of fingers touching the screen
873			this.fingerCount = event.touches.length;
874			// since we're looking for a swipe (single finger) and not a gesture (multiple fingers),
875			// check that only one finger was used
876			if ( this.fingerCount == 1 ) {
877				// get the coordinates of the touch
878				this.startX = event.touches[0].pageX;
879				this.startY = event.touches[0].pageY;
880				// store the triggering element ID
881				this.triggerElementID = passedName;
882			} else {
883				// more than one finger touched so cancel
884				//this.touch_cancel(event);
885			}
886		},
887
888		touch_move : function (event) { 
889			event.preventDefault();
890			if ( event.touches.length == 1 ) {
891				this.curX = event.touches[0].pageX;
892				this.curY = event.touches[0].pageY;
893				
894				// glide during move only if this is the scrollbar
895				if ( jQuery(document.getElementById(this.triggerElementID)).hasClass('wpif2_slider') ) {
896					this.touch_glide(event);
897				}
898			} else { 
899				//this.touch_cancel(event);
900			}
901		},	
902		
903		touch_end : function (event) { 
904			// clean up at end of swipe
905			event.preventDefault(); 
906			this.touch_glide(event);
907			return false;
908		},
909
910		touch_glide : function (event) { 
911			// check to see if more than one finger was used and that there is an ending coordinate
912			if ( this.fingerCount == 1 && this.curX != 0 ) {
913				// use the Distance Formula to determine the length of the swipe
914				this.swipeLength = Math.round(Math.sqrt(Math.pow(this.curX - this.startX,2) + Math.pow(this.curY - this.startY,2)));
915				// if the user swiped more than the minimum length, perform the appropriate action
916				if ( this.swipeLength >= this.minLength ) { 
917					this.calculate_angle();
918					this.determine_swipe_direction();
919					this.processing_routine();
920					//this.touch_cancel(event); // reset the variables (nope - process while swiping)
921				} else { 
922					//this.touch_cancel(event); // nope - process while swiping
923					// perform the click action related to the focussed image
924					this.tap();
925				}	
926			} else { 
927				this.tap();
928			}
929		},
930
931		touch_reset : function (event) {
932			// reset the variables back to default values
933			this.fingerCount = 0;
934			this.startX = 0;
935			this.startY = 0;
936			this.curX = 0;
937			this.curY = 0;
938			this.deltaX = 0;
939			this.deltaY = 0;
940			this.horzDiff = 0;
941			this.vertDiff = 0;
942			this.swipeLength = 0;
943			this.swipeAngle = null;
944			this.swipeDirection = null;
945			this.triggerElementID = null;
946		},
947		
948		calculate_angle : function () {
949			var X = this.startX-this.curX;
950			var Y = this.curY-this.startY;
951			var Z = Math.round(Math.sqrt(Math.pow(X,2)+Math.pow(Y,2))); //the distance - rounded - in pixels
952			var r = Math.atan2(Y,X); //angle in radians (Cartesian system)
953			this.swipeAngle = Math.round(r*180/Math.PI); //angle in degrees
954			if ( this.swipeAngle < 0 ) { this.swipeAngle =  360 - Math.abs(this.swipeAngle); }
955		},
956		
957		determine_swipe_direction : function () {
958			if ( (this.swipeAngle <= 45) && (this.swipeAngle >= 0) ) {
959				this.swipeDirection = 'left';
960			} else if ( (this.swipeAngle <= 360) && (this.swipeAngle >= 315) ) {
961				this.swipeDirection = 'left';
962			} else if ( (this.swipeAngle >= 135) && (this.swipeAngle <= 225) ) {
963				this.swipeDirection = 'right';
964			} else if ( (this.swipeAngle > 45) && (this.swipeAngle < 135) ) {
965				this.swipeDirection = 'down';
966			} else {
967				this.swipeDirection = 'up';
968			}
969		},
970		
971		processing_routine : function () {
972			var swipedElement = document.getElementById(this.triggerElementID);
973			if (( this.swipeDirection == 'left' ) || ( this.swipeDirection == 'right' ) ||
974			    ( this.swipeDirection == 'up' ) || ( this.swipeDirection == 'down' )) {
975				var X;
976				if ( this.triggerElementID == thisObject.ifp_topboxdiv) {
977					// move one lightbox image at a time on swipe
978					if (this.swipeDirection == 'left') {
979						var element = document.getElementById(thisObject.ifp_topboxnextdiv);
980						jQuery(element).click();
981					} else if (this.swipeDirection == 'right') {
982						var element = document.getElementById(thisObject.ifp_topboxprevdiv);
983						jQuery(element).click();
984					}
985				} else if ( jQuery(swipedElement).hasClass('wpif2-book') ) {
986					// move one book image at a time on swipe
987					if (this.swipeDirection == 'down') X = thisObject.image_id + 1;
988					if (this.swipeDirection == 'up') X = thisObject.image_id - 1;
989					if (X < 0) X = 0;
990					if (X >= thisObject.max) X = thisObject.max - 1;
991					thisObject.glideTo(X); 				} else if ( jQuery(swipedElement).hasClass('wpif2_images') ) {
992					// move one carousel image at a time on swipe
993					if (this.swipeDirection == 'left') X = thisObject.image_id + 1;
994					if (this.swipeDirection == 'right') X = thisObject.image_id - 1;
995					if (X < 0) X = 0;
996					if (X >= thisObject.max) X = thisObject.max - 1;
997					thisObject.glideTo(X); 
998				} else { 
999					// drag images according to the scrollbar position
1000					X = Math.round(thisObject.max * (this.curX - thisObject.scrollbar_left)/(thisObject.scrollbar_right - thisObject.scrollbar_left));
1001					if (X < 0) X = 0;
1002					if (X >= thisObject.max) X = thisObject.max - 1;
1003					thisObject.glideTo(X); 
1004				} 
1005			} else {
1006				//this.tap();
1007			}
1008		},
1009		
1010		tap : function () {
1011			var swipedElement = document.getElementById(this.triggerElementID);
1012			
1013			// taps in the carousel open the lightbox
1014			if ( jQuery(swipedElement).hasClass('wpif2_images') ) {
1015				var image_block = thisObject.imgs_div.childNodes.item(thisObject.array_images[thisObject.image_id]);
1016				var image = image_block.childNodes.item(0);
1017				
1018				if (image.getAttribute("data-style") && (image.getAttribute("data-style") == 'wpif2_lightbox')) {
1019					thisObject.autoRotate = "off"; 
1020					thisObject.showTop(image_block);
1021				} else if (thisObject.sameWindow) {
1022					window.location = image.getAttribute('data-link')
1023					//window.location = image.url;
1024				} else {
1025					window.open (image.getAttribute('data-link'));
1026					//window.open (image.url);
1027				}
1028			}
1029			
1030			// taps in the lightbox move to prev/next image or close the lightbox
1031			if (  this.triggerElementID == thisObject.ifp_topboxdiv ) {
1032				var image_div = document.getElementById(thisObject.ifp_topboximgdiv);
1033				if (this.startY >= (jQuery(image_div)).offset().top + jQuery(image_div).height()) {
1034					// taps below the image close the lightbox
1035					thisObject.closeTop();
1036				} else if (this.startX >= (jQuery(swipedElement).offset().left + jQuery(swipedElement).width()/2)) {
1037					// taps on the right go to the next slide
1038					var element = document.getElementById(thisObject.ifp_topboxnextdiv);
1039					jQuery(element).click();
1040				} else {
1041					// otherwise go to the previous slide
1042					var element = document.getElementById(thisObject.ifp_topboxprevdiv);
1043					jQuery(element).click();
1044				}			
1045			}
1046			
1047		}
1048	};
1049
1050	this.getPageScroll = function(){
1051		var xScroll, yScroll;
1052		if (self.pageYOffset) {
1053			yScroll = self.pageYOffset;
1054			xScroll = self.pageXOffset;
1055		} else if (document.documentElement && document.documentElement.scrollTop){	 // Explorer 6 Strict
1056			yScroll = document.documentElement.scrollTop;
1057			xScroll = document.documentElement.scrollLeft;
1058		} else if (document.body) {// all other Explorers
1059			yScroll = document.body.scrollTop;
1060			xScroll = document.body.scrollLeft;	
1061		}
1062		arrayPageScroll = new Array(xScroll,yScroll) 
1063		return arrayPageScroll;
1064	};
1065
1066	this.getPageSize = function(){
1067		var xScroll, yScroll;
1068		if (window.innerHeight && window.scrollMaxY) {	
1069			xScroll = window.innerWidth + window.scrollMaxX;
1070			yScroll = window.innerHeight + window.scrollMaxY;
1071		} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
1072			xScroll = document.body.scrollWidth;
1073			yScroll = document.body.scrollHeight;
1074		} else if (document.documentElement.scrollHeight > document.body.offsetHeight){ // IE7, 6 standards compliant mode
1075			xScroll = document.documentElement.scrollWidth;
1076			yScroll = document.documentElement.scrollHeight;
1077		} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
1078			xScroll = document.body.offsetWidth;
1079			yScroll = document.body.offsetHeight;
1080		}
1081		var windowWidth, windowHeight;
1082		if (self.innerHeight) {	// all except Explorer
1083			if(document.documentElement.clientWidth){
1084				windowWidth = document.documentElement.clientWidth; 
1085			} else {
1086				windowWidth = self.innerWidth;
1087			}
1088			windowHeight = self.innerHeight;
1089		} else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
1090			windowWidth = document.documentElement.clientWidth;
1091			windowHeight = document.documentElement.clientHeight;
1092		} else if (document.body) { // other Explorers
1093			windowWidth = document.body.clientWidth;
1094			windowHeight = document.body.clientHeight;
1095		}
1096		// for small pages with total height less then height of the viewport
1097		if(yScroll < windowHeight){
1098			pageHeight = windowHeight;
1099		} else { 
1100			pageHeight = yScroll;
1101		}
1102		// for small pages with total width less then width of the viewport
1103		if(xScroll < windowWidth){	
1104			pageWidth = xScroll;		
1105		} else {
1106			pageWidth = windowWidth;
1107		}
1108		arrayPageSize = new Array(pageWidth,pageHeight,windowWidth,windowHeight) 
1109		return arrayPageSize;
1110	};
1111
1112	this.showFlash = function(){
1113		var flashObjects = document.getElementsByTagName("object");
1114		for (i = 0; i < flashObjects.length; i++) {
1115			flashObjects[i].style.visibility = "visible";
1116		}
1117		var flashEmbeds = document.getElementsByTagName("embed");
1118		for (i = 0; i < flashEmbeds.length; i++) {
1119			flashEmbeds[i].style.visibility = "visible";
1120		}
1121	};
1122
1123	this.hideFlash = function(){
1124		var flashObjects = document.getElementsByTagName("object");
1125		for (i = 0; i < flashObjects.length; i++) {
1126			flashObjects[i].style.visibility = "hidden";
1127		}
1128		var flashEmbeds = document.getElementsByTagName("embed");
1129		for (i = 0; i < flashEmbeds.length; i++) {
1130			flashEmbeds[i].style.visibility = "hidden";
1131		}
1132	};
1133
1134	this.showTop = function(image_block)
1135	{
1136		var topbox_div = document.getElementById(this.ifp_topboxdiv);
1137		var overlay_div = document.getElementById(this.ifp_overlaydiv);
1138		var topboximgs_div = document.getElementById(this.ifp_topboximgdiv);
1139
1140		// this.hide flash objects
1141		this.hideFlash();
1142
1143		// this.show the background overlay ...
1144		var arrayPageSize = this.getPageSize();
1145		overlay_div.style.width = arrayPageSize[0] + "px";
1146		overlay_div.style.height = arrayPageSize[1] + "px";
1147		overlay_div.style.display = 'none';
1148		overlay_div.style.visibility = 'visible';
1149		jQuery("#"+this.ifp_overlaydiv).show();
1150
1151		// Get the top box data set up first
1152		topboximgs_div.src = image_block.url;
1153		document.getElementById(this.ifp_topboxcaptiondiv).innerHTML = image_block.getAttribute('title');
1154
1155		// get the image actual size by preloading into 't'
1156		var t = new Image();
1157		  t.onload = (function(){	thisObject.showImg(image_block, t, t.width, t.height); });
1158		t.src = image_block.url;
1159
1160		// Now wait until 't' is loaded
1161	};
1162
1163
1164	this.showImg = function(image_block, img, img_width, img_height) 
1165	{	
1166		// Wait for image to preload
1167		if (img_width == 0 || img_height == 0) {
1168			img.onload = (function(){ thisObject.showImg(image_block, img, img.width, img.height); });
1169			return;
1170		}
1171
1172		// Do nothing if the overlay was closed in the meantime
1173		if (document.getElementById(this.ifp_overlaydiv).style.visibility == 'hidden') return;
1174
1175		var topbox_div = document.getElementById(this.ifp_topboxdiv);
1176		var overlay_div = document.getElementById(this.ifp_overlaydiv);
1177		var topboximgs_div = document.getElementById(this.ifp_topboximgdiv);
1178		var prev_div = document.getElementById(this.ifp_topboxprevdiv);
1179		var next_div = document.getElementById(this.ifp_topboxnextdiv);
1180		var caption_div = document.getElementById(this.ifp_topboxcaptiondiv);
1181
1182		// The image should be preloaded at this point
1183		topboximgs_div.src = image_block.url;
1184
1185		// Find previous image that doesn't link to an url
1186		prev_div.style.visibility = 'hidden';
1187		if (image_block.i > 0) {
1188			for (index = image_block.i-1; index >= 0; index--) {
1189				prev_image_block = this.imgs_div.childNodes.item(this.array_images[index]);
1190				prev_image = prev_image_block.childNodes.item(0);
1191				if (prev_image.getAttribute("data-style") && (prev_image.getAttribute("data-style") == 'wpif2_lightbox')) {
1192					// Found one
1193					
1194					if (thisObject.circular) {
1195						
1196						/* If we found a cloned image, switch to the original version of the image. */
1197						if (index+1 === thisObject.focus) {
1198							
1199							/* Set prev to the same cloned image on the right */
1200							index = thisObject.max - thisObject.focus - 1;
1201							prev_image_block = this.imgs_div.childNodes.item(this.array_images[index]);
1202							prev_image = prev_image_block.childNodes.item(0);
1203						}
1204
1205						if (index === (thisObject.max - thisObject.focus)) {
1206							
1207							/* Set prev to the same cloned image on the left */
1208							index = thisObject.focus;
1209							prev_image_block = this.imgs_div.childNodes.item(this.array_images[index]);
1210							prev_image = prev_image_block.childNodes.item(0);
1211						}
1212					}
1213
1214					// Preload and set the previous link
1215					var p = new Image();
1216					p.src = prev_image_block.url;
1217					prev_div.onclick = (function(){ thisObject.showImg(prev_image_block, p, p.width, p.height); return false;});
1218					prev_div.style.visibility = 'visible';
1219					break;
1220				}
1221			} 
1222		}
1223
1224		// Find next image that doesn't link to a URL
1225		next_div.style.visibility = 'hidden';
1226		if (image_block.i < this.max-1) {
1227			for (index = image_block.i+1; index < this.max; index++) {
1228				next_image_block = this.imgs_div.childNodes.item(this.array_images[index]);
1229				next_image = next_image_block.childNodes.item(0);
1230				if (next_image.getAttribute("data-style") && (next_image.getAttribute("data-style") == 'wpif2_lightbox')) {
1231					// Found one
1232
1233					if (thisObject.circular) {
1234						
1235						/* If we found a cloned image, switch to the original version of the image. */
1236						if (index+1 === thisObject.focus) {
1237							
1238							/* Set next to the same cloned image on the right */
1239							index = thisObject.max - thisObject.focus - 1;
1240							next_image_block = this.imgs_div.childNodes.item(this.array_images[index]);
1241							next_image = next_image_block.childNodes.item(0);
1242						}
1243
1244						if (index === (thisObject.max - thisObject.focus)) {
1245							
1246							/* Set next to the same cloned image on the left */
1247							index = thisObject.focus;
1248							next_image_block = this.imgs_div.childNodes.item(this.array_images[index]);
1249							next_image = next_image_block.childNodes.item(0);
1250						}
1251					}
1252
1253					// Preload and set the next link
1254					var n = new Image();
1255					n.src = next_image_block.url;
1256					next_div.onclick = (function(){ thisObject.showImg(next_image_block, n, n.width, n.height); return false;});
1257					next_div.style.visibility = 'visible';
1258					break;
1259				} 
1260			}
1261		}
1262
1263		// Size the box to fit the image plus estimate caption height plus some space
1264		var boxWidth = img_width;
1265		var boxHeight = img_height + 30;
1266
1267		topboximgs_div.width = boxWidth;	
1268
1269		// Add description and include its height in the calculations
1270		var description = '';
1271		image = image_block.childNodes.item(0);
1272		if (image.getAttribute('data-description')) description = image.getAttribute('data-description');
1273		if (description == image.getAttribute('title')) description = '';
1274		if (description != '') { description = '<p>' + description + '</p>'; }
1275		caption_div.innerHTML = image_block.getAttribute('title') + description;
1276		if (description != '') {
1277			jQuery('#'+this.ifp_topboxcaptiondiv).width(boxWidth);	// do this now to estimate the description height
1278			boxHeight += jQuery('#'+this.ifp_topboxcaptiondiv).height();
1279		}
1280
1281		// scale the box if the image is larger than the screen
1282		var arrayPageSize = this.getPageSize();
1283		var screenWidth = arrayPageSize[2];
1284		var screenHeight = arrayPageSize[3];
1285
1286		var arrayPageScroll = this.getPageScroll();
1287
1288		if (boxWidth > screenWidth) {
1289			boxHeight = Math.floor(boxHeight * (screenWidth-100) / boxWidth);
1290			boxWidth = screenWidth - 100;
1291			topboximgs_div.width = boxWidth;
1292		}
1293		if (boxHeight > screenHeight) {
1294			boxWidth = Math.floor(boxWidth * (screenHeight-100) / boxHeight);
1295			boxHeight = screenHeight - 100;
1296			topboximgs_div.width = boxWidth;
1297		}
1298		jQuery('#'+this.ifp_topboxcaptiondiv).width(boxWidth);
1299
1300		var xPos = Math.floor((screenWidth - boxWidth) * 0.5) + arrayPageScroll[0];
1301		var yPos = Math.floor((screenHeight - boxHeight) * 0.5) + arrayPageScroll[1];
1302
1303		topbox_div.style.left = xPos + 'px';
1304		topbox_div.style.top = yPos + 'px';
1305		topbox_div.style.width = boxWidth + 'px';
1306
1307		prev_div.style.height = boxHeight + 'px';
1308		next_div.style.height = boxHeight + 'px';
1309
1310
1311		// Finally show the topbox...
1312		topbox_div.style.display = 'none';
1313		topbox_div.style.visibility = 'visible';
1314		jQuery("#"+this.ifp_topboxdiv).fadeIn("slow");
1315
1316	};
1317
1318	this.closeTop = function()
1319	{
1320		//hide the overlay and topbox...
1321		document.getElementById(this.ifp_overlaydiv).style.visibility='hidden';
1322		document.getElementById(this.ifp_topboxdiv).style.visibility='hidden';
1323		document.getElementById(this.ifp_topboxnextdiv).style.visibility='hidden';
1324		document.getElementById(this.ifp_topboxprevdiv).style.visibility='hidden';
1325
1326		// this.show hidden objects
1327		this.showFlash();
1328	};
1329
1330	// Setup
1331	if (document.getElementById(thisObject.ifp_flowplusdiv) === null) { return; }
1332
1333	/* show loading bar while page is loading */
1334	thisObject.show (thisObject.ifp_loadingdiv);
1335
1336	if (typeof window.onunload === "function")
1337	  {
1338		var oldonunload = window.onunload;
1339		window.onunload = function()
1340		{
1341			thisObject.unloaded();
1342			oldonunload();
1343		};
1344	} else { 
1345		window.onunload = this.unloaded; 
1346	}
1347
1348	if (typeof window.onload === "function")
1349	  {
1350		var oldonload = window.onload;
1351		window.onload = function()
1352		{
1353			thisObject.loaded();
1354			oldonload();
1355		};
1356	} else {
1357		window.onload = thisObject.loaded;
1358	}
1359
1360	/* refresh on window resize */
1361	if (typeof window.onresize === "function") {
1362		var oldresize = window.onresize;
1363		window.onresize = function() {
1364			if (document.getElementById(thisObject.ifp_flowplusdiv)) { thisObject.refresh(false); }
1365			oldresize();
1366		}
1367	} else {
1368		window.onresize = function() {
1369			if (document.getElementById(thisObject.ifp_flowplusdiv)) { thisObject.refresh(false); }
1370		};
1371	}	
1372
1373	/* key handler */
1374	if (typeof document.onkeydown === "function") {
1375		var oldkeyfunc = document.onkeydown;
1376		document.onkeydown = function(event) {
1377			handle_keys(event);
1378			oldkeyfunc(event);
1379		}
1380	} else {
1381		document.onkeydown = handle_keys;
1382	}
1383	
1384	function handle_keys(event)	{
1385		var charCode  = thisObject.getKeyCode(event);
1386		switch (charCode)
1387		{
1388			/* Right arrow key */
1389			case 39:
1390				thisObject.handle(-1);
1391				break;
1392		
1393			/* Left arrow key */
1394			case 37:
1395				thisObject.handle(1);
1396				break;
1397		}
1398	};
1399
1400}

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.