PageSourceSearch

https://bhm.or.kr/js/ajax/lightbox/js/jquery.lightbox.js

js bhm.or.kr collected 2026-10-07 15:50:04 UTC 43,333 bytes, 1,533 lines download raw bytes

1
2/**
3 * jQuery Lightbox Plugin (balupton edition) - Lightboxes for jQuery
4 * Copyright (C) 2008 Benjamin Arthur Lupton
5 * http://jquery.com/plugins/project/jquerylightbox_bal
6 *
7 * This file is part of jQuery Lightbox (balupton edition).
8 * 
9 * jQuery Lightbox (balupton edition) is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as
11 * published by the Free Software Foundation, either version 3 of the
12 * License, or (at your option) any later version.
13 * 
14 * jQuery Lightbox (balupton edition) is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU Affero General Public License for more details.
18 * 
19 * You should have received a copy of the GNU Affero General Public License
20 * along with jQuery Lightbox (balupton edition).  If not, see <http://www.gnu.org/licenses/>.
21 *
22 * @name jquery_lightbox: jquery.lightbox.js
23 * @package jQuery Lightbox Plugin (balupton edition)
24 * @version 1.3.6-final
25 * @date March 08, 2009
26 * @category jQuery plugin
27 * @author Benjamin "balupton" Lupton {@link http://www.balupton.com}
28 * @copyright (c) 2008 Benjamin Arthur Lupton {@link http://www.balupton.com}
29 * @license GNU Affero General Public License - {@link http://www.gnu.org/licenses/agpl.html}
30 * @example Visit {@link http://jquery.com/plugins/project/jquerylightbox_bal} for more information.
31 */
32
33// Start of our jQuery Plugin
34(function($)
35{	// Create our Plugin function, with $ as the argument (we pass the jQuery object over later)
36	// More info: http://docs.jquery.com/Plugins/Authoring#Custom_Alias
37	
38	// Debug
39	if ( typeof $.log === 'undefined' ) {
40		if ( !$.browser.safari && typeof window.console !== 'undefined' && typeof window.console.log === 'function' )
41		{	// Use window.console
42			$.log = function(){
43				var args = [];
44			    for(var i = 0; i < arguments.length; i++) {
45			        args.push(arguments[i]);
46			    }
47			    window.console.log.apply(window.console, args);
48			}
49			$.console = {
50				log:	$.log,
51				debug:	window.console.debug	|| $.log,
52				warn:	window.console.warn		|| $.log,
53				error:	window.console.error	|| $.log,
54				trace:	window.console.trace	|| $.log
55			}
56		}
57		else
58		{	// Don't use anything
59			$.log = function ( ) { };
60			$.console = {
61				log:	$.log,
62				debug:	$.log,
63				warn:	$.log,
64				error:	alert,
65				trace:	$.log
66			};
67		}
68	}
69	
70	// Pre-Req
71	$.params_to_json = $.params_to_json || function ( params )
72	{	// Turns a params string or url into an array of params
73		// Adjust
74		params = String(params);
75		// Remove url if need be
76		params = params.substring(params.indexOf('?')+1);
77		// params = params.substring(params.indexOf('#')+1);
78		// Change + to %20, the %20 is fixed up later with the decode
79		params = params.replace(/\+/g, '%20');
80		// Do we have JSON string
81		if ( params.substring(0,1) === '{' && params.substring(params.length-1) === '}' )
82		{	// We have a JSON string
83			return eval(decodeURIComponent(params));
84		}
85		// We have a params string
86		params = params.split(/\&|\&amp\;/);
87		var json = {};
88		// We have params
89		for ( var i = 0, n = params.length; i < n; ++i )
90		{
91			// Adjust
92			var param = params[i] || null;
93			if ( param === null ) { continue; }
94			param = param.split('=');
95			if ( param === null ) { continue; }
96			// ^ We now have "var=blah" into ["var","blah"]
97			
98			// Get
99			var key = param[0] || null;
100			if ( key === null ) { continue; }
101			if ( typeof param[1] === 'undefined' ) { continue; }
102			var value = param[1];
103			// ^ We now have the parts
104			
105			// Fix
106			key = decodeURIComponent(key);
107			value = decodeURIComponent(value);
108			try {
109			    // value can be converted
110			    value = eval(value);
111			} catch ( e ) {
112			    // value is a normal string
113			}
114			
115			// Set
116			// console.log({'key':key,'value':value}, split);
117			var keys = key.split('.');
118			if ( keys.length === 1 )
119			{	// Simple
120				json[key] = value;
121			}
122			else
123			{	// Advanced
124				var path = '';
125				for ( ii in keys )
126				{	//
127					key = keys[ii];
128					path += '.'+key;
129					eval('json'+path+' = json'+path+' || {}');
130				}
131				eval('json'+path+' = value');
132			}
133			// ^ We now have the parts added to your JSON object
134		}
135		return json;
136	};
137	
138	// Declare our class
139	$.LightboxClass = function ( )
140	{	// This is the handler for our constructor
141		this.construct();
142	};
143
144	// Extend jQuery elements for Lightbox
145	$.fn.lightbox = function ( options )
146	{	// Init a el for Lightbox
147		// Eg. $('#gallery a').lightbox();
148		
149		// If need be: Instantiate $.LightboxClass to $.Lightbox
150		$.Lightbox = $.Lightbox || new $.LightboxClass();
151		
152		// Handle IE6 appropriatly
153		if ( $.Lightbox.ie6 && !$.Lightbox.ie6_support )
154		{	// We are IE6 and we want to ignore
155			return this; // chain
156		}
157		
158		// Establish options
159		options = $.extend({start:false,events:true} /* default options */, options);
160		
161		// Get group
162		var group = $(this);
163		
164		// Events?
165		if ( options.events )
166		{	// Add events
167			$(group).unbind().click(function(){
168				// Get obj
169				var obj = $(this);
170				// Get rel
171				// var rel = $(obj).attr('rel');
172				// Init group
173				if ( !$.Lightbox.init($(obj)[0], group) )
174				{	return false;	}
175				// Display lightbox
176				if ( !$.Lightbox.start() )
177				{	return false;	}
178				// Cancel href
179				return false;
180			});
181			// Add style
182			$(group).addClass('lightbox-enabled');
183		}
184		
185		// Start?
186		if ( options.start )
187		{	// Start
188			// Get obj
189			var obj = $(this);
190			// Get rel
191			// var rel = $(obj).attr('rel');
192			// Init group
193			if ( !$.Lightbox.init($(obj)[0], group) )
194			{	return this;	}
195			// Display lightbox
196			if ( !$.Lightbox.start() )
197			{	return this;	}
198		}
199		
200		// And chain
201		return this;
202	};
203	
204	// Define our class
205	$.extend($.LightboxClass.prototype,
206	{	// Our LightboxClass definition
207		
208		// -----------------
209		// Everyting to do with images
210		
211		images: {
212			
213			// -----------------
214			// Variables
215			
216			// Our array of images
217			list:[], /* [ {
218				src: 'url to image',
219				link: 'a link to a page',
220				title: 'title of the image',
221				name: 'name of the image',
222				description: 'description of the image'
223			} ], */
224			
225			// The current active image
226			image: false,
227			
228			// -----------------
229			// Functions
230			
231			prev: function ( image )
232			{	// Get previous image
233				
234				// Get previous from current?
235				if ( typeof image === 'undefined' )
236				{	image = this.active();
237					if ( !image ) { return image; }
238				}
239				
240				// Is there a previous?
241				if ( this.first(image) )
242				{	return false;	}
243				
244				// Get the previous
245				return this.get(image.index-1);
246			},
247			
248			next: function ( image )
249			{	// Get next image
250				
251				// Get next from current?
252				if ( typeof image === 'undefined' )
253				{	image = this.active();
254					if ( !image ) { return image; }
255				}
256				
257				// Is there a next?
258				if ( this.last(image) )
259				{	return false;	}
260				
261				// Get the next
262				return this.get(image.index+1);
263			},
264			
265			first: function ( image )
266			{	//
267				// Get the first image?
268				if ( typeof image === 'undefined' )
269				{	return this.get(0);	}
270				
271				// Are we the first?
272				return image.index === 0;
273			},
274			
275			last: function ( image )
276			{	//
277				// Get the last image?
278				if ( typeof image === 'undefined' )
279				{	return this.get(this.size()-1);	}
280				
281				// Are we the last?
282				return image.index === this.size()-1;
283			},
284		
285			single: function ( )
286			{	// Are we only one
287				return this.size() === 1;
288			},
289			
290			size: function ( )
291			{	// How many images do we have
292				return this.list.length;
293			},
294			
295			empty: function ( )
296			{	// Are we empty
297				return this.size() === 0;
298			},
299			
300			clear: function ( )
301			{	// Clear image arrray
302				this.list = [];
303				this.image = false;
304			},
305		
306			active: function ( image )
307			{	// Set or get the active image
308				// Use false to reset
309				
310				// Get the active image?
311				if ( typeof image === 'undefined' )
312				{	return this.image;	}
313				
314				// Set the ative image
315				if ( image !== false )
316				{	// Make sure image exists
317					image = this.get(image);
318					if ( !image )
319					{	// Error
320						return image;
321					}
322				}
323				
324				// Set the active image
325				this.image = image;
326				return true;
327			},
328		
329			add: function ( obj )
330			{
331				// Do we need to recurse?
332				if ( obj[0] )
333				{	// We have a lot of images
334					for ( var i = 0; i < obj.length; i++ )
335					{	this.add(obj[i]);	}
336					return true;
337				}
338				
339				// Default image
340				
341				// Try and create a image
342				var image = this.create(obj);
343				if ( !image ) { return image; }
344				
345				// Set image index
346				image.index = this.size();
347				
348				// Push image
349				this.list.push(image);
350				
351				// Success
352				return true;
353			},
354			
355			create: function ( obj )
356			{	// Create image
357				
358				// Define
359				var image = { // default
360					src:	'',
361					title:	'Untitled',
362					description:	'',
363					name:	'',
364					index:	-1,
365					color:	null,
366					width:	null,
367					height:	null,
368					image:	true
369				};
370				
371				// Create
372				if ( obj.image )
373				{	// Already a image, so copy over values
374					image.src = obj.src || image.src;
375					image.title = obj.title || image.title;
376					image.description = obj.description || image.description;
377					image.name = obj.name || image.name;
378					image.color = obj.color || image.color;
379					image.width = obj.width || image.width;
380					image.height = obj.height || image.height;
381					image.index = obj.index || image.index;
382				}
383				else if ( obj.tagName )
384				{	// We are an element
385					obj = $(obj);
386					if ( obj.attr('src') || obj.attr('href') )
387					{
388						image.src = obj.attr('src') || obj.attr('href');
389						image.title = obj.attr('title') || obj.attr('alt') || image.title;
390						image.name = obj.attr('name') || '';
391						image.color = obj.css('backgroundColor');
392						// Extract description from title
393						var s = image.title.indexOf(': ');
394						if ( s > 0 )
395						{	// Description exists
396							image.description = image.title.substring(s+2) || image.description;
397							image.title = image.title.substring(0,s) || image.title;
398						}
399					}
400					else
401					{	// Unsupported element
402						image = false;
403					}
404				}
405				else
406				{	// Unknown
407					image = false;
408				}
409				
410				if ( !image )
411				{	// Error
412					$.console.error('We dont know what we have:', obj);
413					return false;
414				}
415				
416				// Success
417				return image;
418			},
419			
420			get: function ( image )
421			{	// Get the active, or specified image
422				
423				// Establish image
424				if ( typeof image === 'undefined' || image === null )
425				{	// Get the active image
426					return this.active();
427				}
428				else
429				if ( typeof image === 'number' )
430				{	// We have a index
431					
432					// Get image
433					image = this.list[image] || false;
434				}
435				else
436				{	// Create
437					image = this.create(image);
438					if ( !image ) { return false; }
439					
440					// Find
441					var f = false;
442					for ( var i = 0; i < this.size(); i++ )
443					{
444						var c = this.list[i];
445						if ( c.src === image.src && c.title === image.title && c.description === image.description )
446						{	f = c;	}
447					}
448					
449					// Found?
450					image = f;
451				}
452				
453				// Determine image
454				if ( !image )
455				{	// Image doesn't exist
456					$.console.error('The desired image doesn\'t exist: ', image, this.list);
457					return false;
458				}
459				
460				// Return image
461				return image;
462			},
463			
464			debug: function ( )
465			{
466				return $.Lightbox.debug(arguments);
467			}
468			
469		},
470		
471		// -----------------
472		// Variables
473		
474		constructed:		false,
475		compressed:			null,
476		
477		// -----------------
478		// Options
479		
480		src:				null,		// the source location of our js file
481		baseurl:			null,
482		
483		files: {
484			compressed: {
485				js: {
486					lightbox:	'/js/ajax/lightbox/js/jquery.lightbox.min.js',
487					colorBlend:	'/js/ajax/lightbox/js/jquery.color.min.js'
488				},
489				css: {
490					lightbox:	'/js/ajax/lightbox/css/jquery.lightbox.css'
491				}
492			},
493			uncompressed: {
494				js: {
495					lightbox:	'/js/ajax/lightbox/js/jquery.lightbox.js',
496					colorBlend:	'/js/ajax/lightbox/js/jquery.color.js'
497				},
498				css: {
499					lightbox:	'/js/ajax/lightbox/css/jquery.lightbox.css'
500				}
501			},
502			images: {
503				prev:		'/js/ajax/lightbox/images/prev.gif',
504				next:		'/js/ajax/lightbox/images/next.gif',
505				blank:		'/js/ajax/lightbox/images/blank.gif',
506				loading:	'/js/ajax/lightbox/images/loading.gif'
507			}
508		},
509		
510		text: {
511			// For translating
512			image:		'Image',
513			of:			'of',
514			close:		'Close X',
515			closeInfo:	'Ŭ¸¯ÇÏ½Ã¸é ´ÝÈü´Ï´Ù.',
516			download:	'Direct link to download the image.',
517			help: {
518				close:		'',
519				interact:	''
520			},
521			about: {
522				text: 	'',
523				title:	'',
524				link:	''
525			}
526		},
527		
528		keys: {
529			close:	'c',
530			prev:	'p',
531			next:	'n'
532		},
533		
534		handlers: {
535			// For custom actions
536			show:	null
537		},
538		
539		opacity:		0.5,
540		padding:		null,		// if null - autodetect
541		
542		speed:			400,		// Duration of effect, milliseconds
543		
544		rel:			'lightbox',	// What to look for in the rels
545		
546		auto_relify:	true,		// should we automaticly do the rels?
547		
548		auto_scroll:	'follow',	// should the lightbox scroll with the page? follow, disabled, ignore
549		auto_resize:	true,		// true or false
550		
551		ie6:			null,		// are we ie6?
552		ie6_support:	true,		// have ie6 support
553		ie6_upgrade:	true,		// show ie6 upgrade message
554		
555		colorBlend:		null,		// null - auto-detect, true - force, false - no
556		
557		download_link:	true,		// Display the download link
558		
559		show_linkback:		true,	// true, false
560		show_info:			'auto',	// auto - automaticly handle, true - force
561		show_extended_info:	'auto',	// auto - automaticly handle, true - force	
562		
563		// names of the options that can be modified
564		options:	['auto_scroll', 'auto_resize', 'download_link', 'show_info', 'show_extended_info', 'ie6_support', 'ie6_upgrade', 'colorBlend', 'baseurl', 'files', 'text', 'show_linkback', 'keys', 'opacity', 'padding', 'speed', 'rel', 'auto_relify'],
565		
566		// -----------------
567		// Functions
568		
569		construct: function ( options )
570		{	// Construct our Lightbox
571			
572			// -------------------
573			// Prepare
574			
575			// Initial construct
576			var initial = typeof this.constructed === 'undefined' || this.constructed === false;
577			this.constructed = true;
578			
579			// Perform domReady
580			var domReady = initial;
581			
582			// Prepare options
583			options = options || {};
584			
585			// -------------------
586			// Handle files
587			
588			// Prepend function to use later
589			var prepend = function(item, value) {
590				if ( typeof item === 'object' ) {
591					for (var i in item) {
592						item[i] = prepend(item[i], value);
593					}
594				} else if ( typeof value === 'array' ) {
595					for (var i=0,n=item.length; i<n; ++i) {
596						item[i] = prepend(item[i], value);
597					}
598				} else {
599					item = value+item;
600				}
601				return item;
602			}
603			
604			// Add baseurl
605			if ( initial && (typeof options.files === 'undefined') )
606			{	// Load the files like default
607				
608				// Reset compressed
609				this.compressed = null;
610				
611				// Get the src of the first script tag that includes our js file (with or without an appendix)
612				var $script = $('script[src*='+this.files.compressed.js.lightbox+']:first');
613				if ( $script.length !== 0 ) {
614					// Compressed
615					$.extend(true, this.files, this.files.compressed);
616					this.compressed = true;
617				} else {
618					// Uncompressed
619					$script = $('script[src*='+this.files.uncompressed.js.lightbox+']:first');
620					if ( $script.length !== 0 ) {
621						// Uncompressed
622						$.extend(true, this.files, this.files.uncompressed);
623						this.compressed = false;
624					} else {
625						// Nothing
626					}
627				}
628				
629				// Make sure we found ourselves
630				if ( this.compressed === null )
631				{	// We didn't
632					$.console.error('Lightbox was not able to find it\'s javascript script tag necessary for auto-inclusion.');
633					// We don't work with files anymore, so don't care for domReady
634					domReady = false;
635				}
636				else
637				{	// We found ourself
638					
639					// Grab the script src
640					this.src = $script.attr('src');
641					
642					// The baseurl is the src up until the start of our js file
643					this.baseurl = this.src.substring(0, this.src.indexOf(this.files.js.lightbox));
644					
645					// Prepend baseurl to files
646					this.files = prepend(this.files, this.baseurl);
647					
648					// Now as we have source, we may have more params
649					options = $.extend(options, $.params_to_json(this.src));
650				}
651				
652			}
653			else
654			if ( typeof options.files === 'object' )
655			{	// We have custom files
656				// Prepend baseurl to files
657				options.files = prepend(options.files, this.baseurl);
658			}
659			else
660			{	// Don't have any files, so no need to perform domReady
661				domReady = false;
662			}
663			
664			// -------------------
665			// Apply options
666			
667			for ( var i in this.options )
668			{	// Cycle through the options
669				var name = this.options[i];
670				if ( (typeof options[name] === 'object') && (typeof this[name] === 'object') )
671				{	// We have a group like text or files
672					this[name] = $.extend(true, this[name], options[name]);
673				}
674				else if ( typeof options[name] !== 'undefined' )
675				{	// We have that option, so apply it
676					this[name] = options[name];
677				}
678			}	delete i;
679			
680			// -------------------
681			// Figure out what to do
682			
683			// Handle IE6
684			if ( initial && navigator.userAgent.indexOf('MSIE 6') >= 0 )
685			{	// Is IE6
686				this.ie6 = true;
687			}
688			else
689			{	// We are not IE6
690				this.ie6 = false;
691			}
692			
693			// -------------------
694			// Handle our DOM
695			
696			if ( domReady || typeof options.download_link !== 'undefined' ||  typeof options.colorBlend !== 'undefined' || typeof options.files === 'object' || typeof options.text === 'object' || typeof options.show_linkback !== 'undefined' || typeof options.scroll_with !== 'undefined' )
697			{	// We have reason to handle the dom
698				$(function() {
699					// DOM is ready, so fire our DOM handler
700					$.Lightbox.domReady();
701				});
702			}
703			
704			// -------------------
705			// Finish Up
706			
707			// All good
708			return true;
709		},
710		
711		domReady: function ( )
712		{
713			// -------------------
714			// Include resources
715			
716			// Grab resources
717			var bodyEl = document.getElementsByTagName($.browser.safari ? 'head' : 'body')[0];
718			var stylesheets = this.files.css;
719			var scripts = this.files.js;
720			
721			// Handle IE6 appropriatly
722			if ( this.ie6 && this.ie6_upgrade )
723			{	// Add the upgrade message
724				scripts.ie6 = 'http://www.savethedevelopers.org/say.no.to.ie.6.js';
725			}
726			
727			// colorBlend
728			if ( this.colorBlend === true && typeof $.colorBlend === 'undefined' )
729			{	// Force colorBlend
730				this.colorBlend = true;
731				// Leave file in place to be loaded
732			}
733			else
734			{	// We either have colorBlend or we don't
735				this.colorBlend = typeof $.colorBlend !== 'undefined';
736				// Remove colorBlend file
737				delete scripts.colorBlend;
738			}
739			
740			// Include stylesheets
741			for ( stylesheet in stylesheets )
742			{
743				var linkEl = document.createElement('link');
744				linkEl.type = 'text/css';
745				linkEl.rel = 'stylesheet';
746				linkEl.media = 'screen';
747				linkEl.href = stylesheets[stylesheet];
748				linkEl.id = 'lightbox-stylesheet-'+stylesheet.replace(/[^a-zA-Z0-9]/g, '');
749				$('#'+linkEl.id).remove();
750				bodyEl.appendChild(linkEl);
751			}
752			
753			// Include javascripts
754			for ( script in scripts )
755			{
756				var scriptEl = document.createElement('script');
757				scriptEl.type = 'text/javascript';
758				scriptEl.src = scripts[script];
759				scriptEl.id = 'lightbox-script-'+script.replace(/[^a-zA-Z0-9]/g, '');
760				$('#'+scriptEl.id).remove();
761				bodyEl.appendChild(scriptEl);
762			}
763			
764			// Cleanup
765			delete scripts;
766			delete stylesheets;
767			delete bodyEl;
768			
769			// -------------------
770			// Append display
771			
772			// Append markup
773			$('#lightbox,#lightbox-overlay').remove();
774			$('body').append('<div id="lightbox-overlay"><div id="lightbox-overlay-text">'+(this.show_linkback?'<p><span id="lightbox-overlay-text-about"><a href="#" title="'+this.text.about.title+'">'+this.text.about.text+'</a></span></p><p>&nbsp;</p>':'')+'<p><span id="lightbox-overlay-text-close">'+this.text.help.close+'</span><br/>&nbsp;<span id="lightbox-overlay-text-interact">'+this.text.help.interact+'</span></p></div></div><div id="lightbox"><div id="lightbox-imageBox"><div id="lightbox-imageContainer"><img id="lightbox-image" alt="lightbox-image" /><div id="lightbox-nav"><a href="#" id="lightbox-nav-btnPrev"></a><a href="#" id="lightbox-nav-btnNext"></a></div><div id="lightbox-loading"><a href="#" id="lightbox-loading-link"><img src="' + this.files.images.loading + '" alt="' + this.files.images.loading + '" /></a></div></div></div><div id="lightbox-infoBox"><div id="lightbox-infoContainer"><div id="lightbox-infoHeader"><span id="lightbox-caption">'+(this.download_link ? '<a href="#" title="' + this.text.download + '" id="lightbox-caption-title"></a>' : '<span id="lightbox-caption-title"></span>')+'<span id="lightbox-caption-seperator"></span><span id="lightbox-caption-description"></span></span></div><div id="lightbox-infoFooter"><span id="lightbox-currentNumber"></span><span id="lightbox-close"><a href="#" id="lightbox-close-button" title="'+this.text.closeInfo+'">' + this.text.close + '</a></span></div><div id="lightbox-infoContainer-clear"></div></div></div></div>');
775			
776			// Update Boxes - for some crazy reason this has to be before the hide in safari and konqueror
777			this.resizeBoxes();
778			this.repositionBoxes();
779			
780			// Hide
781			$('#lightbox,#lightbox-overlay,#lightbox-overlay-text-interact').hide();
782			
783			// -------------------
784			// Browser specifics
785			
786			// Handle IE6
787			if ( this.ie6 && this.ie6_support )
788			{	// Support IE6
789				// IE6 does not support fixed positioning so absolute it
790				// ^ This is okay as we disable scrolling
791				$('#lightbox-overlay').css({
792					position:	'absolute',
793					top:		'0px',
794					left:		'0px'
795				});
796			}
797			
798			// -------------------
799			// Preload Images
800			
801			// Cycle and preload
802			$.each(this.files.images, function()
803			{	// Proload the image
804				var preloader = new Image();
805				preloader.onload = function() {
806					preloader.onload = null;
807					preloader = null;
808				};	preloader.src = this;
809			});
810			
811			// -------------------
812			// Apply events
813			
814			// If the window resizes, act appropriatly
815			$(window).unbind().resize(function ()
816			{	// The window has been resized
817				$.Lightbox.resizeBoxes('resized');
818			});
819			
820			// If the window scrolls, act appropriatly
821			if ( this.scroll === 'follow' )
822			{	// We want to
823				$(window).scroll(function ()
824				{	// The window has scrolled
825					$.Lightbox.repositionBoxes();
826				});
827			}
828			
829			// Prev
830			$('#lightbox-nav-btnPrev').unbind().hover(function() { // over
831				$(this).css({ 'background' : 'url(' + $.Lightbox.files.images.prev + ') left 45% no-repeat' });
832			},function() { // out
833				$(this).css({ 'background' : 'transparent url(' + $.Lightbox.files.images.blank + ') no-repeat' });
834			}).click(function() {
835				$.Lightbox.showImage($.Lightbox.images.prev());
836				return false;
837			});
838					
839			// Next
840			$('#lightbox-nav-btnNext').unbind().hover(function() { // over
841				$(this).css({ 'background' : 'url(' + $.Lightbox.files.images.next + ') right 45% no-repeat' });
842			},function() { // out
843				$(this).css({ 'background' : 'transparent url(' + $.Lightbox.files.images.blank + ') no-repeat' });
844			}).click(function() {
845				$.Lightbox.showImage($.Lightbox.images.next());
846				return false;
847			});
848			
849			// Help
850			if ( this.show_linkback )
851			{	// Linkback exists so add handler
852				$('#lightbox-overlay-text-about a').click(function(){window.open($.Lightbox.text.about.link); return false;});
853			}
854			$('#lightbox-overlay-text-close').unbind().hover(
855				function(){
856					$('#lightbox-overlay-text-interact').fadeIn();
857				},
858				function(){
859					$('#lightbox-overlay-text-interact').fadeOut();
860				}
861			);
862			
863			// Image link
864			$('#lightbox-caption-title').click(function(){window.open($(this).attr('href')); return false;});
865			
866			// Assign close clicks
867			$('#lightbox-overlay, #lightbox, #lightbox-loading-link, #lightbox-btnClose').unbind().click(function() {
868				$.Lightbox.finish();
869				return false;	
870			});
871			
872			// -------------------
873			// Finish Up
874			
875			// Relify
876			if ( this.auto_relify )
877			{	// We want to relify, no the user
878				this.relify();
879			}
880			
881			// All good
882			return true;
883		},
884		
885		relify: function ( )
886		{	// Create event
887		
888			//
889			var groups = {};
890			var groups_n = 0;
891			var orig_rel = this.rel;
892			// Create the groups
893			$.each($('[rel*='+orig_rel+']'), function(index, obj){
894				// Get the group
895				var rel = $(obj).attr('rel');
896				// Are we really a group
897				if ( rel === orig_rel )
898				{	// We aren't
899					rel = groups_n; // we are individual
900				}
901				// Does the group exist
902				if ( typeof groups[rel] === 'undefined' )
903				{	// Make the group
904					groups[rel] = [];
905					groups_n++;
906				}
907				// Append the image
908				groups[rel].push(obj);
909			});
910			// Lightbox groups
911			$.each(groups, function(index, group){
912				$(group).lightbox();
913			});
914			// Done
915			return true;
916		},
917		
918		init: function ( image, images )
919		{	// Init a batch of lightboxes
920			
921			// Establish images
922			if ( typeof images === 'undefined' )
923			{
924				images = image;
925				image = 0;
926			}
927			
928			// Clear
929			this.images.clear();
930			
931			// Add images
932			if ( !this.images.add(images) )
933			{	return false;	}
934			
935			// Do we need to bother
936			if ( this.images.empty() )
937			{	// No images
938				$.console.warn('WARNING', 'Lightbox started, but no images: ', image, images);
939				return false;
940			}
941			
942			// Set active
943			if ( !this.images.active(image) )
944			{	return false;	}
945			
946			// Done
947			return true;
948		},
949		
950		start: function ( )
951		{	// Display the lightbox
952				
953			// We are alive
954			this.visible = true;
955			
956			// Adjust scrolling
957			if ( this.scroll === 'disable' )
958			{	// 
959				$(document.body).css('overflow', 'hidden');
960			}
961			
962			// Fix attention seekers
963			$('embed, object, select').css('visibility', 'hidden');//.hide(); - don't use this, give it a go, find out why!
964			
965			// Resize the boxes appropriatly
966			this.resizeBoxes('general');
967			
968			// Reposition the Boxes
969			this.repositionBoxes({'speed':0});
970			
971			// Hide things
972			$('#lightbox-infoFooter').hide(); // we hide this here because it makes the display smoother
973			$('#lightbox-image,#lightbox-nav,#lightbox-nav-btnPrev,#lightbox-nav-btnNext,#lightbox-infoBox').hide();
974					
975			// Display the boxes
976			$('#lightbox-overlay').css('opacity',this.opacity).fadeIn(400, function(){
977				// Show the lightbox
978				$('#lightbox').fadeIn(300);
979				
980				// Display first image
981				if ( !$.Lightbox.showImage($.Lightbox.images.active()) )
982				{	$.Lightbox.finish();	return false;	}
983			});
984			
985			// All done
986			return true;
987		},
988		
989		finish: function ( )
990		{	// Get rid of lightbox
991		
992			// Hide lightbox
993			$('#lightbox').hide();
994			$('#lightbox-overlay').fadeOut(function() { $('#lightbox-overlay').hide(); });
995			
996			// Fix attention seekers
997			$('embed, object, select').css({ 'visibility' : 'visible' });//.show();
998			
999			// Kill active image
1000			this.images.active(false);
1001			
1002			// Adjust scrolling
1003			if ( this.scroll === 'disable' )
1004			{	// 
1005				$(document.body).css('overflow', 'visible');
1006			}
1007			
1008			// We are dead
1009			this.visible = false;
1010			
1011		},
1012		
1013		resizeBoxes: function ( type )
1014		{	// Resize the boxes
1015			// Used on transition or window resize
1016			
1017			// Resize Overlay
1018			if ( type !== 'transition' )
1019			{	// We don't care for transition
1020				var $body = $(this.ie6 ? document.body : document);
1021				$('#lightbox-overlay').css({
1022					width:		$body.width(),
1023					height:		$body.height()*1.5
1024				});
1025				delete $body;
1026			}
1027			
1028			// Handle cases
1029			switch ( type )
1030			{
1031				case 'general': // general resize (start of lightbox)
1032					return true;
1033					break;
1034				case 'resized': // window was resized
1035					if ( this.auto_resize === false )
1036					{	// Stop
1037						// Reposition
1038						this.repositionBoxes({'nHeight':nHeight, 'speed':this.speed});
1039						return true;
1040					}
1041				case 'transition': // transition between images
1042				default: // unknown
1043					break;
1044			}
1045			
1046			// Get image
1047			var image = this.images.active();
1048			if ( !image || !image.width || !this.visible )
1049			{	// No image or no visible lightbox, so we don't care
1050				$.console.warn('A resize occured while no image or no lightbox...');
1051				return false;
1052			}
1053			
1054			// Resize image box
1055			// i:image, w:window, b:box, c:current, n:new, d:difference
1056			
1057			// Get image dimensions
1058			var iWidth  = image.width;
1059			var iHeight = image.height;
1060			
1061			// Get window dimensions
1062			var wWidth  = $(window).width();
1063			var wHeight = $(window).height();
1064			
1065			// Check if we are in size
1066			// Lightbox can take up 4/5 of size
1067			if ( this.auto_resize !== false )
1068			{	// We want to auto resize
1069				var maxWidth  = Math.floor(wWidth*(4/5));
1070				var maxHeight = Math.floor(wHeight*(4/5));
1071				var resizeRatio;
1072				while ( iWidth > maxWidth || iHeight > maxHeight )
1073				{	// We need to resize
1074					if ( iWidth > maxWidth )
1075					{	// Resize width, then height proportionally
1076						resizeRatio = maxWidth/iWidth;
1077						iWidth = maxWidth;
1078						iHeight = Math.floor(iHeight*resizeRatio);
1079					}
1080					if ( iHeight > maxHeight )
1081					{	// Resize height, then width proportionally
1082						resizeRatio = maxHeight/iHeight;
1083						iHeight = maxHeight;
1084						iWidth = Math.floor(iWidth*resizeRatio);
1085					}
1086				}
1087			}
1088			
1089			// Get current width and height
1090			var cWidth  = $('#lightbox-imageBox').width();
1091			var cHeight = $('#lightbox-imageBox').height();
1092	
1093			// Get the width and height of the selected image plus the padding
1094			// padding*2 for both sides (left+right || top+bottom)
1095			var nWidth	= (iWidth  + (this.padding * 2));
1096			var nHeight	= (iHeight + (this.padding * 2));
1097			
1098			// Diferences
1099			var dWidth  = cWidth  - nWidth;
1100			var dHeight = cHeight - nHeight;
1101			
1102			// Set the overlay buttons height and the infobox width
1103			// Other dimensions specified by CSS
1104			$('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css('height', nHeight); 
1105			$('#lightbox-infoBox').css('width', nWidth);
1106			
1107			// Handle final action
1108			if ( type === 'transition' )
1109			{	// We are transition
1110				// Do we need to wait? (just a nice effect to counter the other
1111				if ( dWidth === 0 && dHeight === 0 )
1112				{	// We are the same size
1113					this.pause(this.speed/3);
1114					this.showImage(null, 3);
1115				}
1116				else
1117				{	// We are not the same size
1118					// Animate
1119					$('#lightbox-image').width(iWidth).height(iHeight);
1120					$('#lightbox-imageBox').animate({width: nWidth, height: nHeight}, this.speed, function ( ) { $.Lightbox.showImage(null, 3); } );
1121				}
1122			}
1123			else
1124			{	// We are a resize
1125				// Animate Lightbox
1126				$('#lightbox-image').animate({width:iWidth, height:iHeight}, this.speed);
1127				$('#lightbox-imageBox').animate({width: nWidth, height: nHeight}, this.speed);
1128			}
1129			
1130			// Reposition
1131			this.repositionBoxes({'nHeight':nHeight, 'speed':this.speed});
1132			
1133			// Done
1134			return true;
1135		},
1136		
1137		repositioning:			false,	// are we currently repositioning
1138		reposition_failsafe:	false,	// failsafe
1139		repositionBoxes: function ( options )
1140		{
1141			// Prepare
1142			if ( this.repositioning )
1143			{	// Already here
1144				this.reposition_failsafe = true;
1145				return null;
1146			}
1147			this.repositioning = true;
1148			
1149			// Options
1150			options = $.extend({}, options);
1151			options.callback = options.callback || null;
1152			options.speed = options.speed || 'slow';
1153			
1154			// Get page scroll
1155			var pageScroll = this.getPageScroll();
1156			
1157			// Figure it out
1158			// alert($(window).height()+"\n"+$(document.body).height()+"\n"+$(document).height());
1159			// var nHeight = options.nHeight || parseInt($('#lightbox').height(),10) || $(document).height()/3;
1160			var nHeight = options.nHeight || parseInt($('#lightbox').height(),10);
1161			
1162			// Display lightbox in center
1163			// var nTop = pageScroll.yScroll + ($(document.body).height() /*frame height*/ - nHeight) / 2.5;
1164			var nTop = pageScroll.yScroll + ($(window).height() /*frame height*/ - nHeight) / 2.5;
1165			var nLeft = pageScroll.xScroll;
1166			
1167			// Animate
1168			var css = {
1169				left: nLeft,
1170				top: nTop
1171			};
1172			if (options.speed) {
1173				$('#lightbox').animate(css, 'slow', function(){
1174					if ( $.Lightbox.reposition_failsafe )
1175					{	// Fire again
1176						$.Lightbox.repositioning = $.Lightbox.reposition_failsafe = false;
1177						$.Lightbox.repositionBoxes(options);
1178					}
1179					else
1180					{	// Done
1181						$.Lightbox.repositioning = false;
1182						if ( options.callback )
1183						{	// Call the user callback
1184							options.callback();
1185						}
1186					}
1187				});
1188			}
1189			else
1190			{
1191				$('#lightbox').css(css);
1192				if ( this.reposition_failsafe )
1193				{	// Fire again
1194					this.repositioning = this.reposition_failsafe = false;
1195					this.repositionBoxes(options);
1196				}
1197				else
1198				{	// Done
1199					this.repositioning = false;
1200				}
1201			}
1202			
1203			// Done
1204			return true;
1205		},
1206		
1207		visible: false,
1208		showImage: function ( image, step )
1209		{
1210			// Establish image
1211			image = this.images.get(image);
1212			if ( !image ) { return image; }
1213			
1214			// Default step
1215			step = step || 1;
1216			
1217			// Split up below for jsLint compliance
1218			var skipped_step_1 = step > 1 && this.images.active().src !== image.src;
1219			var skipped_step_2 = step > 2 && $('#lightbox-image').attr('src') !== image.src;
1220			if ( skipped_step_1 || skipped_step_2 )
1221			{	// Force step 1
1222				$.console.info('We wanted to skip a few steps: ', image, step, skipped_step_1, skipped_step_2);
1223				step = 1;
1224			}
1225			
1226			// What do we need to do
1227			switch ( step )
1228			{
1229				// ---------------------------------
1230				// We need to preload
1231				case 1:
1232				
1233					// Disable keyboard nav
1234					this.KeyboardNav_Disable();
1235					
1236					// Show the loading image
1237					$('#lightbox-loading').show();
1238					
1239					// Hide things
1240					$('#lightbox-image,#lightbox-nav,#lightbox-nav-btnPrev,#lightbox-nav-btnNext,#lightbox-infoBox').hide();
1241					
1242					// Remove show info events
1243					$('#lightbox-imageBox').unbind();
1244					// ^ Why? Because otherwise when the image is changing, the info pops out, not good!
1245					
1246					// Make the image the active image
1247					if ( !this.images.active(image) ) { return false; }
1248					
1249					// Check if we need to preload
1250					if ( image.width && image.height )
1251					{	// We don't
1252						// Continue to next step
1253						this.showImage(null, 2);
1254					}
1255					else
1256					{	// We do
1257						// Create preloader
1258						var preloader = new Image();
1259						// Set callback
1260						preloader.onload = function()
1261						{	// We have preloaded the image
1262							// Update image with our new info
1263							image.width  = preloader.width;
1264							image.height = preloader.height;
1265							// Continue to next step
1266							$.Lightbox.showImage(null, 2);
1267							// Kill preloader
1268							preloader.onload = null;
1269							preloader = null;
1270						};
1271						// Start preload
1272						preloader.src = image.src;
1273					}
1274					
1275					// Done
1276					break;
1277				
1278				
1279				// ---------------------------------
1280				// Resize the container
1281				case 2:
1282					
1283					// Apply image changes
1284					$('#lightbox-image').attr('src', image.src);
1285					$('#lightbox-image').attr('alt', image.title);
1286					
1287					// Set container border (Moved here for Konqueror fix - Credits to Blueyed)
1288					if ( typeof this.padding === 'undefined' || this.padding === null || isNaN(this.padding) )
1289					{	// Autodetect
1290						this.padding = parseInt($('#lightbox-imageContainer').css('padding-left'), 10) || parseInt($('#lightbox-imageContainer').css('padding'), 10) || 0;
1291					}
1292					
1293					// Use colorBlend?
1294					if ( this.colorBlend )
1295					{	// We have colorBlend
1296						// Background
1297						$('#lightbox-overlay').animate({'backgroundColor':image.color}, this.speed*2);
1298						// Border
1299						$('#lightbox-imageBox').css('borderColor', image.color);
1300					}
1301					
1302					// Resize boxes
1303					this.resizeBoxes('transition');
1304					// ^ contains callback to next step
1305					
1306					// Done
1307					break;
1308				
1309				
1310				// ---------------------------------
1311				// Display the image
1312				case 3:
1313					
1314					// Hide loading
1315					$('#lightbox-loading').hide();
1316					
1317					// Animate image
1318					$('#lightbox-image').fadeIn(this.speed*1.5, function() {$.Lightbox.showImage(null, 4); });
1319					
1320					// Start the proloading of other images
1321					this.preloadNeighbours();
1322					
1323					// Fire custom handler show
1324					if ( this.handlers.show !== null )
1325					{	// Fire it
1326						this.handlers.show(image);
1327					}
1328					
1329					// Done
1330					break;
1331				
1332				
1333				// ---------------------------------
1334				// Set image info / Set navigation
1335				case 4:
1336					
1337					// ---------------------------------
1338					// Set image info
1339					
1340					// Hide and set image info
1341					var $title = $('#lightbox-caption-title').html(image.title || 'Untitled');
1342					if ( this.download_link )
1343					{	$title.attr('href', this.download_link ? image.src : '');	}
1344					delete $title;
1345					$('#lightbox-caption-seperator').html(image.description ? ': ' : '');
1346					$('#lightbox-caption-description').html(image.description || '&nbsp;');
1347					
1348					// If we have a set, display image position
1349					if ( this.images.size() > 1 )
1350					{	// Display
1351						$('#lightbox-currentNumber').html(this.text.image + '&nbsp;' + ( image.index + 1 ) + '&nbsp;' + this.text.of + '&nbsp;' + this.images.size());
1352					} else
1353					{	// Empty
1354						$('#lightbox-currentNumber').html('&nbsp;');
1355					}
1356					
1357					// ---------------------------------
1358					// Info events
1359					
1360					// Apply event
1361					$('#lightbox-imageBox').unbind('mouseover').mouseover(function(){
1362						$('#lightbox-infoBox').slideDown('fast');
1363					});
1364					
1365					// Apply event
1366					$('#lightbox-infoBox').unbind('mouseover').mouseover(function(){
1367						$('#lightbox-infoFooter').slideDown('fast');
1368					});
1369					
1370					// Forced show?
1371					if ( this.show_extended_info === true )
1372					{	// Force show
1373						$('#lightbox-imageBox').trigger('mouseover');
1374						$('#lightbox-infoBox').trigger('mouseover');
1375					}
1376					else if ( this.show_info === true )
1377					{	// Force show
1378						$('#lightbox-imageBox').trigger('mouseover');
1379					}
1380					
1381					// ---------------------------------
1382					// Set navigation
1383		
1384					// Instead to define this configuration in CSS file, we define here. And it's need to IE. Just.
1385					$('#lightbox-nav-btnPrev, #lightbox-nav-btnNext').css({ 'background' : 'transparent url(' + this.files.images.blank + ') no-repeat' });
1386					
1387					// If not first, show previous button
1388					if ( !this.images.first(image) ) {
1389						// Not first, show button
1390						$('#lightbox-nav-btnPrev').show();
1391					}
1392					
1393					// If not last, show next button
1394					if ( !this.images.last(image) ) {
1395						// Not first, show button
1396						$('#lightbox-nav-btnNext').show();
1397					}
1398					
1399					// Make navigation active / show it
1400					$('#lightbox-nav').show();
1401					
1402					// Enable keyboard navigation
1403					this.KeyboardNav_Enable();
1404					
1405					// Done
1406					break;
1407					
1408					
1409				// ---------------------------------
1410				// Error handling
1411				default:
1412					$.log('ERROR', 'Don\'t know what to do: ', image, step);
1413					return this.showImage(image, 1);
1414					// break;
1415				
1416			}
1417			
1418			// All done
1419			return true;
1420		},
1421		
1422		preloadNeighbours: function ( )
1423		{	// Preload all neighbour images
1424			
1425			// Do we need to do this?
1426			if ( this.images.single() || this.images.empty() )
1427			{	return true;	}
1428			
1429			// Get active image
1430			var image = this.images.active();
1431			if ( !image ) { return image; }
1432			
1433			// Load previous
1434			var prev = this.images.prev(image);
1435			var objNext;
1436			if ( prev ) {
1437				objNext = new Image();
1438				objNext.src = prev.src;
1439			}
1440			
1441			// Load next
1442			var next = this.images.next(image);
1443			if ( next ) {
1444				objNext = new Image();
1445				objNext.src = next.src;
1446			}
1447		},
1448		
1449		// --------------------------------------------------
1450		// Things we don't really care about
1451		
1452		KeyboardNav_Enable: function ( ) {
1453			$(document).keydown(function(objEvent) {
1454				$.Lightbox.KeyboardNav_Action(objEvent);
1455			});
1456		},
1457		
1458		KeyboardNav_Disable: function ( ) {
1459			$(document).unbind();
1460		},
1461		
1462		KeyboardNav_Action: function ( objEvent ) {
1463			// Prepare
1464			objEvent = objEvent || window.event;
1465			
1466			// Get the keycode
1467			var keycode = objEvent.keyCode;
1468			var escapeKey = objEvent.DOM_VK_ESCAPE /* moz */ || 27;
1469			
1470			// Get key
1471			var key = String.fromCharCode(keycode).toLowerCase();
1472			
1473			// Close?
1474			if ( key === this.keys.close || keycode === escapeKey )
1475			{	return $.Lightbox.finish();		}
1476			
1477			// Prev?
1478			if ( key === this.keys.prev || keycode === 37 )
1479			{	// We want previous
1480				return $.Lightbox.showImage($.Lightbox.images.prev());
1481			}
1482			
1483			// Next?
1484			if ( key === this.keys.next || keycode === 39 )
1485			{	// We want next
1486				return $.Lightbox.showImage($.Lightbox.images.next());
1487			}
1488			
1489			// Unknown
1490			return true;
1491		},
1492		
1493		getPageScroll: function ( ) {
1494			var xScroll, yScroll;
1495			if (self.pageYOffset)
1496			{	// Some browser
1497				yScroll = self.pageYOffset;
1498				xScroll = self.pageXOffset;
1499			} else if (document.documentElement && document.documentElement.scrollTop)
1500			{	// Explorer 6 Strict
1501				yScroll = document.documentElement.scrollTop;
1502				xScroll = document.documentElement.scrollLeft;
1503			} else if (document.body)
1504			{	// All other browsers
1505				yScroll = document.body.scrollTop;
1506				xScroll = document.body.scrollLeft;	
1507			}
1508			var arrayPageScroll = {'xScroll':xScroll,'yScroll':yScroll};
1509			return arrayPageScroll;
1510		},
1511		
1512		pause: function ( ms ) {
1513			var date = new Date();
1514			var curDate = null;
1515			do { curDate = new Date(); }
1516			while ( curDate - date < ms);
1517		}
1518	
1519	}); // We have finished extending/defining our LightboxClass
1520
1521
1522	// --------------------------------------------------
1523	// Finish up
1524	
1525	// Instantiate
1526	if ( typeof $.Lightbox === 'undefined' )
1527	{	// 
1528		$.Lightbox = new $.LightboxClass();
1529	}
1530
1531// Finished definition
1532
1533})(jQuery); // We are done with our plugin, so lets call it with jQuery as the argument

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.