PageSourceSearch

https://sugamo-lc.jp/js/jquery.galleryview-3.0-dev.js

js sugamo-lc.jp collected 2026-09-30 15:09:11 UTC 35,261 bytes, 1,079 lines download raw bytes

1/*
2
3	GalleryView - jQuery Content Gallery Plugin
4	Author:		Jack Anderson
5	Version:	3.0 DEVELOPMENT
6
7  	See README.txt for instructions on how to markup your HTML
8*/
9
10// Make sure Object.create is available in the browser (for our prototypal inheritance)
11// Courtesy of Douglas Crockford
12if (typeof Object.create !== 'function') {
13    Object.create = function (o) {
14        function F() {}
15        F.prototype = o;
16        return new F();
17    };
18}
19
20(function ($) {
21	// custom image object
22	var gvImage = function (img) {
23
24		this.src = { 
25			panel: img.attr('src'),
26			frame: img.data('frame') || img.attr('src')
27		};
28		this.scale = {
29			panel: null,
30			frame: null
31		};
32		this.height = 0;
33		this.width = 0;
34		this.attrs = {
35			title: img.attr('title') || img.attr('alt'),
36			description: img.data('description')
37		};
38		this.href = null;
39		this.dom_obj = null;
40		
41		return this;
42	},
43	
44	// utility function wrapper
45	gv = {
46		getInt: function(i) {
47			i = parseInt(i, 10);
48			return isNaN(i) ? 0 : i;
49		},
50		innerWidth: function(elem) {
51			return this.getInt(elem.css('width')) || 0;	
52		},
53		outerWidth: function(elem) {
54			return 	this.innerWidth(elem) + 
55					this.extraWidth(elem);
56		},
57		extraWidth: function(elem) {
58			return	this.getInt(elem.css('paddingLeft')) +
59					this.getInt(elem.css('paddingRight')) +
60					this.getInt(elem.css('borderLeftWidth')) +
61					this.getInt(elem.css('borderRightWidth'));	
62		},
63		innerHeight: function(elem) {
64			return this.getInt(elem.css('height'))|| 0;
65		},
66		outerHeight: function(elem) {
67			return 	this.innerHeight(elem) + 
68					this.extraHeight(elem);
69		},
70		extraHeight: function(elem) {
71			return 	this.getInt(elem.css('paddingTop')) +
72					this.getInt(elem.css('paddingBottom')) +
73					this.getInt(elem.css('borderTopWidth')) +
74					this.getInt(elem.css('borderBottomWidth'));
75		}
76	},
77	
78	/*
79		GalleryView - Object
80			The main gallery class
81	*/		
82	GalleryView = {
83		// array of dom elements
84		elems: [
85			'.gv_galleryWrap',	'.gv_gallery',		'.gv_panelWrap',		'.gv_panel',
86			'img.gv_image',		'.gv_infobar',		'.gv_filmstripWrap',	'.gv_filmstrip',
87			'.gv_frame',		'.gv_thumbnail', 	'.gv_caption', 			'img.gv_thumb',
88			'.gv_navWrap',		'.gv_navNext',		'.gv_navPrev',			'.gv_navPlay',
89			'.gv_panelNavNext',	'.gv_panelNavPrev',	'.gv_overlay',			'.gv_showOverlay',
90			'.gv_imageStore'
91		],
92		
93		// create a jQuery element and apply attributes
94		createElem: function(attrs,elem) {
95			elem = document.createElement(elem);
96			var $elem = $(elem);
97			return $elem.attr(attrs);
98		},
99		
100		// get the position of an element with respect
101		// to the gallery wrapper
102		getPos: function (el) {
103			var self = this,
104				dom = this.dom,
105				el = el[0],
106				el_id = el.id,
107				left = 0,
108				top = 0,
109				gPos, gLeft, gTop;
110				
111			if (!el) { return { top: 0, left: 0 }; }
112			
113			if (el.offsetParent) {
114				do {
115					left += el.offsetLeft;
116					top += el.offsetTop;
117				} while (el = el.offsetParent);
118			}
119			
120			//If we want the position of the gallery itself, return it
121			if (el_id === self.id) { return { left: left, top: top }; }
122			
123			//Otherwise, get position of element relative to gallery
124			else {
125				gPos = self.getPos(dom.galleryWrap);
126				gLeft = gPos.left;
127				gTop = gPos.top;
128				return { left: left - gLeft, top: top - gTop };
129			}
130		},
131		
132		// determine if mouse is within the boundary of the gallery wrapper
133		mouseIsOverGallery: function (x, y) {
134			var self = this,
135				dom = this.dom,
136				pos = this.getPos(dom.gv_galleryWrap),
137				top = pos.top,
138				left = pos.left;
139				
140			return x > left && x < left + gv.outerWidth(dom.gv_galleryWrap) && y > top && y < top + gv.outerHeight(dom.gv_galleryWrap);
141		},
142		
143		// determine if mouse is within the boundary of the panel
144		mouseIsOverPanel: function (x, y) {
145			var self = this,
146				dom = this.dom,
147				pos = this.getPos(dom.gv_panelWrap),
148				gPos = this.getPos(dom.gv_galleryWrap),
149				top = pos.top + gPos.top,
150				left = pos.left + gPos.left;
151				
152			return x > left && x < left + gv.outerWidth(dom.gv_panelWrap) && y > top && y < top + gv.outerHeight(dom.gv_panelWrap);
153		},
154		
155		// create gvImage objects for each image in gallery
156		storeImages: function() {
157			var self = this;
158			this.sourceImgs = $('li>img',this.$el);
159			this.numImages = this.sourceImgs.length;
160			this.gvImages = [];
161			this.sourceImgs.each(function(i,img) {
162				self.gvImages[i] = new gvImage($(img));
163			});
164		},
165		
166		setDimensions: function() {
167			var self = this,
168				dom = this.dom,
169				widths = {
170					prev: gv.innerWidth(dom.gv_navPrev),
171					play: gv.innerWidth(dom.gv_navPlay),
172					next: gv.innerWidth(dom.gv_navNext),
173					filmstrip: this.opts.frame_width,
174					fsMax: 0,
175					fsFull: 0
176				},
177				heights = {
178					prev: gv.innerHeight(dom.gv_navPrev),
179					play: gv.innerHeight(dom.gv_navPlay),
180					next: gv.innerHeight(dom.gv_navNext),
181					filmstrip: this.opts.frame_height + (this.opts.show_captions ? gv.outerHeight(dom.gv_caption) : 0),
182					fsMax: 0,
183					fsFull: 0
184				},
185				panels = [];
186			
187			// nav
188			if(this.filmstripOrientation === 'horizontal') {
189				dom.gv_navWrap.css({
190					width: widths.prev + widths.play + widths.next,
191					height: Math.max(heights.prev,heights.play,heights.next)
192				});
193			} else {
194				if(this.opts.filmstrip_style === 'scroll' && this.opts.frame_width < (widths.prev + widths.play + widths.next)) {
195					dom.gv_navWrap.css({
196						width: Math.max(widths.prev, widths.play, widths.next),
197						height: heights.prev + heights.play + heights.next
198					});
199				} else {
200					dom.gv_navWrap.css({
201						width: widths.prev + widths.play + widths.next,
202						height: Math.max(heights.prev,heights.play,heights.next)
203					});
204				}
205			}
206			
207			if(this.filmstripOrientation === 'vertical' && widths.filmstrip < (widths.prev + widths.play + widths.next)) {
208				dom.gv_navWrap.css({
209					width: Math.max(widths.prev, widths.play, widths.next),
210					height: heights.prev + heights.play + heights.next
211				});
212			} else {
213				dom.gv_navWrap.css({
214					width: widths.prev + widths.play + widths.next,
215					height: Math.max(heights.prev,heights.play,heights.next)
216				});
217			}
218			
219			// panels
220			dom.gv_panel.css({
221				width: this.opts.panel_width,
222				height: this.opts.panel_height
223			});
224			dom.gv_panelWrap.css({
225				width: gv.outerWidth(dom.gv_panel),
226				height: gv.outerHeight(dom.gv_panel)
227			});
228			dom.gv_overlay.css({
229				width: this.opts.panel_width
230			});
231			
232			
233			
234			$.each(this.gvImages,function(i,img) {
235				dom.gv_panelWrap.append(dom.gv_panel.clone(true));
236			});
237			
238			dom.gv_panels = dom.gv_panelWrap.find('.gv_panel');
239			dom.gv_panels.remove();
240			
241			// filmstrip
242			dom.gv_thumbnail.css({
243				width: this.opts.frame_width,
244				height: this.opts.frame_height
245			});
246			dom.gv_frame.css({
247				width: gv.outerWidth(dom.gv_thumbnail),
248				height: gv.outerHeight(dom.gv_thumbnail) + (this.opts.show_captions ? gv.outerHeight(dom.gv_caption) : 0),
249				marginRight: this.opts.frame_gap,
250				marginBottom: this.opts.frame_gap
251			});
252			
253			
254			if(this.filmstripOrientation === 'horizontal') {
255				this.filmstripSize = Math.floor((gv.outerWidth(dom.gv_panelWrap) - gv.outerWidth(dom.gv_navWrap)) / (gv.outerWidth(dom.gv_frame) + this.opts.frame_gap));
256				widths.fsMax = this.filmstripSize * (gv.outerWidth(dom.gv_frame) + this.opts.frame_gap);
257				widths.fsFull = this.gvImages.length * (gv.outerWidth(dom.gv_frame) + this.opts.frame_gap);
258				widths.filmstrip = Math.min(widths.fsMax,widths.fsFull);
259				if(this.opts.filmstrip_style !== 'scroll') {
260					heights.filmstrip = (Math.ceil(this.gvImages.length / this.filmstripSize) * (gv.outerHeight(dom.gv_frame) + this.opts.frame_gap)) - this.opts.frame_gap;
261				}
262			} else {
263				this.filmstripSize = Math.floor((gv.outerHeight(dom.gv_panelWrap) - gv.outerHeight(dom.gv_navWrap)) / (gv.outerHeight(dom.gv_frame) + this.opts.frame_gap));
264				heights.fsMax = this.filmstripSize * (gv.outerHeight(dom.gv_frame) + this.opts.frame_gap);
265				heights.fsFull = this.gvImages.length * (gv.outerHeight(dom.gv_frame) + this.opts.frame_gap);
266				heights.filmstrip = Math.min(heights.fsMax,heights.fsFull);
267				if(this.opts.filmstrip_style !== 'scroll') {
268					widths.filmstrip = (Math.ceil(this.gvImages.length / this.filmstripSize) * (gv.outerWidth(dom.gv_frame) + this.opts.frame_gap)) - this.opts.frame_gap;
269				}
270			}
271			dom.gv_filmstripWrap.css({
272				width: widths.filmstrip,
273				height: heights.filmstrip
274			});
275			
276			// gallery
277			if(this.opts.show_filmstrip) {
278				if(this.filmstripOrientation === 'horizontal') {
279					dom.gv_gallery.css({
280						width: gv.outerWidth(dom.gv_panelWrap),
281						height: gv.outerHeight(dom.gv_panelWrap) + this.opts.frame_gap + (this.opts.show_filmstrip ? Math.max(gv.outerHeight(dom.gv_filmstripWrap),gv.outerHeight(dom.gv_navWrap)) : gv.outerHeight(dom.gv_filmstripWrap))
282					});
283				} else {
284					dom.gv_gallery.css({
285						width: gv.outerWidth(dom.gv_panelWrap) + this.opts.frame_gap + (this.opts.show_filmstrip ? Math.max(gv.outerWidth(dom.gv_filmstripWrap),gv.outerWidth(dom.gv_navWrap)) : gv.outerWidth(dom.gv_filmstripWrap)),
286						height: gv.outerHeight(dom.gv_panelWrap)
287					});	
288				}
289			} else {
290				dom.gv_gallery.css({
291					width: gv.outerWidth(dom.gv_panelWrap),
292					height: gv.outerHeight(dom.gv_panelWrap)
293				});	
294			}
295			
296			dom.gv_galleryWrap.css({
297					width: gv.outerWidth(dom.gv_gallery),
298					height: gv.outerHeight(dom.gv_gallery),
299					padding: this.opts.frame_gap
300			});
301		},
302		
303		setPositions: function() {
304			var self = this,
305				dom = this.dom,
306				navVert = 0, fsVert = 0,
307				navHorz = 0, fsHorz = 0,
308				vert, horz;
309			
310			// determine vertical or horizontal offset
311			// if negative, apply to filmstrip, otherwise apply to navbar
312			if(this.filmstripOrientation === 'horizontal') {
313				vert = Math.round((gv.outerHeight(dom.gv_filmstripWrap) - gv.outerHeight(dom.gv_navWrap)) / 2);
314				if(vert < 0) { fsVert = -1 * vert; }
315				else { navVert = vert; }
316			} else {
317				horz = Math.round((gv.outerWidth(dom.gv_filmstripWrap) - gv.outerWidth(dom.gv_navWrap)) / 2);
318				if(horz < 0) { fsHorz = -1 * horz; }
319				else { navHorz = horz; }
320			}
321			
322			// for horizontal filmstrips w/o navigation, center the filmstrip under the panel
323			if(!this.opts.show_filmstrip_nav && this.filmstripOrientation === 'horizontal') {
324				fsHorz = Math.floor((gv.outerWidth(dom.gv_panelWrap) - gv.outerWidth(dom.gv_filmstripWrap)) / 2);
325			}
326			
327			dom.gv_panelNavNext.css({ top: (gv.outerHeight(dom.gv_panel) - gv.outerHeight(dom.gv_panelNavNext)) / 2, right: 10 });
328			dom.gv_panelNavPrev.css({ top: (gv.outerHeight(dom.gv_panel) - gv.outerHeight(dom.gv_panelNavPrev)) / 2, left: 10 });
329			
330			// pin elements to gallery corners according to filmstrip position
331			switch(this.opts.filmstrip_position) {
332				case 'top':
333					dom.gv_navWrap.css({ top: navVert, right: navHorz });
334					dom.gv_panelWrap.css({ bottom: 0, left: 0 });
335					dom.gv_filmstripWrap.css({ top: fsVert, left: fsHorz });
336					break;
337				
338				case 'right':
339					dom.gv_navWrap.css({ bottom: navVert, right: navHorz });
340					dom.gv_panelWrap.css({ top: 0, left: 0 });
341					dom.gv_filmstripWrap.css({ top: fsVert, right: fsHorz });
342					break;
343				
344				case 'left':
345					dom.gv_navWrap.css({ bottom: navVert, left: navHorz });
346					dom.gv_panelWrap.css({ top: 0, right: 0 });
347					dom.gv_filmstripWrap.css({ top: fsVert, left: fsHorz });
348					break;
349				
350				default:
351					dom.gv_navWrap.css({ bottom: navVert, right: navHorz });
352					dom.gv_panelWrap.css({ top: 0, left: 0 });
353					dom.gv_filmstripWrap.css({ bottom: fsVert, left: fsHorz });
354					break;
355			}
356			
357			if(this.opts.overlay_position === 'top') {
358				dom.gv_overlay.css({ top: 0, left: -99999 });
359				dom.gv_showOverlay.css({ top: 0, left: 0 });
360			} else {
361				dom.gv_overlay.css({ bottom: 0, left: -99999 });
362				dom.gv_showOverlay.css({ bottom: 0, left: 0 });
363			}
364			
365			if(!this.opts.show_filmstrip_nav) {
366				dom.gv_navWrap.remove();	
367			}
368		},
369		
370		buildFilmstrip: function() {
371			var self = this,
372				dom = this.dom,
373				framesLength = this.gvImages.length * ((this.filmstripOrientation === 'horizontal' ? this.opts.frame_width : this.opts.frame_height) + this.opts.frame_gap);
374			
375			dom.gv_frame.append(dom.gv_thumbnail);
376			if(this.opts.show_captions) { 
377				dom.gv_frame.append(dom.gv_caption);
378			}
379			dom.gv_thumbnail.css('opacity',this.opts.frame_opacity);
380			
381			dom.gv_thumbnail.bind({
382				mouseover: function() {
383					if(!$(this).hasClass('current')) {
384						$(this).stop().animate({opacity:1},250);
385					}
386				},
387				mouseout: function() {
388					if(!$(this).hasClass('current')) {
389						$(this).stop().animate({opacity:self.opts.frame_opacity},250);
390					}
391				}
392			});
393			
394			// Drop a clone of the frame element into the filmstrip for each source image
395			$.each(this.gvImages,function(i,img) {
396				dom.gv_frame.clone(true).prependTo(dom.gv_filmstrip);
397			});
398			
399			dom.gv_filmstrip.css({
400				width: gv.outerWidth(dom.gv_frame),
401				height: gv.outerHeight(dom.gv_frame)
402			});
403			
404			// If we are scrolling the filmstrip, and we can't show all frames at once,
405			// make two additional copies of each frame
406			if(this.opts.filmstrip_style === 'scroll') {
407				if(this.filmstripOrientation === 'horizontal') {
408					if(framesLength > gv.innerWidth(dom.gv_filmstripWrap)) {
409						dom.gv_filmstrip.find('.gv_frame').clone(true).appendTo(dom.gv_filmstrip).clone(true).appendTo(dom.gv_filmstrip);
410						dom.gv_filmstrip.css('width',framesLength * 3);
411						this.scrolling = true;
412					} else {
413						dom.gv_filmstrip.css('width',framesLength);
414					}
415				} else {
416					if(framesLength >
416 gv.innerHeight(dom.gv_filmstripWrap)) {
417						dom.gv_filmstrip.find('.gv_frame').clone(true).appendTo(dom.gv_filmstrip).clone(true).appendTo(dom.gv_filmstrip);
418						dom.gv_filmstrip.css('height',framesLength * 3);
419						this.scrolling = true;
420					} else {
421						dom.gv_filmstrip.css('height',framesLength);
422					}
423				}
424			} else {
425				dom.gv_filmstrip.css({
426					width: parseInt(dom.gv_filmstripWrap.css('width'),10)+this.opts.frame_gap,
427					height: parseInt(dom.gv_filmstripWrap.css('height'),10)+this.opts.frame_gap
428				});
429			}
430			dom.gv_frames = dom.gv_filmstrip.find('.gv_frame');
431			$.each(dom.gv_frames,function(i,frame) {
432				$(frame).data('frameIndex',i);						  
433			});
434			dom.gv_thumbnails = dom.gv_filmstrip.find('div.gv_thumbnail');
435		},
436		
437		buildGallery: function() {
438			var self = this,
439				dom = this.dom;
440			
441			this.setDimensions();
442			this.setPositions();
443			
444			if(this.opts.show_filmstrip) {
445				this.buildFilmstrip();
446			}
447		},
448		
449		showInfoBar: function() {
450			if(!this.opts.show_infobar) { return; }
451			var self = this,
452				dom = this.dom;
453			
454			dom.gv_infobar.stop().stopTime('hideInfoBar_' + self.id).html((this.iterator+1) + ' of ' + this.numImages).show().css('opacity',this.opts.infobar_opacity);
455			
456			dom.gv_infobar.oneTime(2000 + this.opts.transition_speed,'hideInfoBar_' + self.id,function() {
457					dom.gv_infobar.fadeOut(1000);
458				});
459		},
460		
461		initImages: function() {
462			var self = this,
463				dom = this.dom;
464			$.each(this.gvImages,function(i,gvImage) {
465				var img = $('<img/>');
466				img.css('visibility','hidden').data('index',i);
467				img.bind('load.galleryview',function() {
468					var _img = $(this),
469						index = _img.data('index'),
470						width = this.width,
471						height = this.height,
472						parent = dom[(_img.data('parent')).type].eq((_img.data('parent')).index),
473						widthFactor = gv.innerWidth(parent) / width,
474						heightFactor = gv.innerHeight(parent) / height,
475						parentType = parent.hasClass('gv_panel') ? 'panel' : 'frame',
476						heightOffset = 0, widthOffset = 0;
477					
478					gvImage.scale[parentType] = self.opts[parentType+'_scale'] === 'fit' ? Math.min(widthFactor,heightFactor) : Math.max(widthFactor,heightFactor);
479					
480					widthOffset = Math.round((gv.innerWidth(parent) - (width * gvImage.scale[parentType])) / 2);
481					heightOffset = Math.round((gv.innerHeight(parent) - (height * gvImage.scale[parentType])) / 2);	
482					
483					_img.css({
484						width: width * gvImage.scale[parentType],
485						height: height * gvImage.scale[parentType],
486						top: heightOffset,
487						left: widthOffset
488					});
489					_img.hide().css('visibility','visible');
490					_img.remove().appendTo(parent);
491					
492					if(parentType === 'frame') {
493						_img.fadeIn();
494						parent.parent().removeClass('gv_frame-loading');
495						parent.parent().find('.gv_caption').html(gvImage.attrs.title);
496					} else if(index === self.opts.start_frame - 1) {
497						parent.prependTo(dom.gv_panelWrap);
498						parent.removeClass('gv_panel-loading');
499						_img.fadeIn();
500						self.showInfoBar();
501					} else {
502						parent.removeClass('gv_panel-loading');
503						_img.show();
504					}
505				});
506				
507				// store eventual image container as data property
508				// append to temporary storage element and set src
509				if(self.opts.show_panels) {
510					img.clone(true)
511						.data('parent',{type:'gv_panels',index:i})
512						.appendTo(dom.gv_imageStore)
513						.attr('src',gvImage.src.panel);
514				}
515				
516				if(self.opts.show_filmstrip) {
517					img.clone(true)
518						.data('parent',{type:'gv_thumbnails',index:i})
519						.appendTo(dom.gv_imageStore)
520						.attr('src',gvImage.src.frame);
521					
522					if(dom.gv_frames.length > dom.gv_panels.length) {
523						img.clone(true)
524							.data('parent',{type:'gv_thumbnails',index:i+self.numImages})
525							.appendTo(dom.gv_imageStore)
526							.attr('src',gvImage.src.frame);
527							
528						img.clone(true)
529							.data('parent',{type:'gv_thumbnails',index:i+self.numImages+self.numImages})
530							.appendTo(dom.gv_imageStore)
531							.attr('src',gvImage.src.frame);
532					}
533				}
534			});
535		},
536		
537		showNext: function() {
538			this.navAction = 'next';
539			this.showItem(this.frameIterator+1);
540		},
541		
542		showPrev: function() {
543			this.navAction = 'prev';
544			this.showItem(this.frameIterator-1);
545		},
546		
547		showItem: function(i) {
548			if(isNaN(i)) { return; }
549			if(!this.opts.show_filmstrip) { i = i % this.numImages; }
550			
551			var self = this,
552				dom = this.dom,
553				frame_i = i,
554				newPanelStart,
555				oldPanelEnd,
556				oldIterator,
557				panel,
558				playing = false;
559				
560			// don't go out of bounds
561			if(i >= this.numImages) {
562				i = i % this.numImages;
563			} else if(i < 0) {
564				i = this.numImages - 1;
565				if(dom.gv_frames != undefined) {
566					frame_i = dom.gv_frames.length - 1;
567				} else {
568					frame_i = dom.gv_panels.length - 1;
569				}
570			}
571			
572			panel = dom.gv_panels.eq(i);
573			
574			playing = this.playing;
575			
576			if(playing) {
577				this.stopSlideshow(false);
578			}
579			
580			this.unbindActions();
581			
582			dom.gv_gallery.oneTime(this.opts.transition_speed,'bindActions_' + self.id,function(){ if(playing) { self.startSlideshow(false); } self.bindActions(); });
583			
584			switch(this.opts.panel_animation) {
585				case 'crossfade':
586					dom.gv_panels.eq(this.iterator).fadeOut(this.opts.transition_speed,function(){$(this).remove();});
587					panel.hide().prependTo(dom.gv_panelWrap).fadeIn(this.opts.transition_speed);
588					break;
589				case 'fade':
590					dom.gv_panels.eq(this.iterator).remove();
591					panel.hide().prependTo(dom.gv_panelWrap).fadeIn(this.opts.transition_speed);
592					break;
593				case 'slide':
594					if(this.navAction === 'next' || (this.navAction === 'frame' && frame_i > this.iterator)) {
595						newPanelStart = gv.outerWidth(dom.gv_panel);
596						oldPanelEnd = -1 * gv.outerWidth(dom.gv_panel);
597					} else {
598						newPanelStart = -1 * gv.outerWidth(dom.gv_panel);
599						oldPanelEnd = gv.outerWidth(dom.gv_panel);
600					}
601					
602					panel.css({ left:newPanelStart }).appendTo(dom.gv_panelWrap).animate(
603						{ left:0 },
604						{ duration: this.opts.transition_speed,easing: this.opts.easing }
605					);
606					
607					dom.gv_panels.eq(this.iterator).animate(
608						{ left: oldPanelEnd },
609						{ duration: this.opts.transition_speed, easing: this.opts.easing, complete: function(){ $(this).remove(); } }
610					);
611					break;
612				default:
613					dom.gv_panels.eq(this.iterator).remove();
614					panel.prependTo(dom.gv_panelWrap);
615					break;
616			}
617			
618			this.updateOverlay(i);
619			
620			this.iterator = i;
621			this.updateFilmstrip(frame_i);
622			this.showInfoBar();
623			
624			
625		},
626		
627		updateOverlay: function(i) {
628			var self = this,
629				dom = this.dom;
630			
631			if(this.overlayVisible) {
632				this.hideOverlay(null,function(){
633					dom.gv_overlay.html('<h4>'+self.gvImages[i].attrs.title+'</h4><p>'+self.gvImages[i].attrs.description+'</p>');
634					self.showOverlay();
635				});
636			} else {
637				dom.gv_overlay.html('<h4>'+self.gvImages[i].attrs.title+'</h4><p>'+self.gvImages[i].attrs.description+'</p>');
638				dom.gv_overlay.css(this.opts.overlay_position,-1 * dom.gv_overlay.outerHeight());
639			}
640			
641		},
642		
643		hideOverlay: function(s,callback) {
644			var self = this,
645				dom = this.dom,
646				endOverlay = {},
647				endButton = {},
648				speed = s || self.opts.transition_speed / 2;
649				
650			callback = callback || function(){};
651			
652			endOverlay[this.opts.overlay_position] = -1 * dom.gv_overlay.outerHeight();
653			endButton[this.opts.overlay_position] = 0;
654			
655			dom.gv_overlay.animate(endOverlay,{ 
656				duration: speed, 
657				easing: 'swing', 
658				complete: callback
659			});
660			dom.gv_showOverlay.animate(endButton,{
661				duration: speed,
662				easing: 'swing'
663			});
664			
665			this.overlayVisible = false;
666		},
667		
668		showOverlay: function(s) {
669			var self = this,
670				dom = this.dom,
671				startOverlay = {},
672				endOverlay = {},
673				endButton = {},
674				speed = s || self.opts.transition_speed / 2;
675			
676			startOverlay[this.opts.overlay_position] = -1 * dom.gv_overlay.outerHeight();
677			startOverlay.left = 0;
678			
679			endOverlay[this.opts.overlay_position] = 0;
680			
681			endButton[this.opts.overlay_position] = dom.gv_overlay.outerHeight();
682			
683			dom.gv_overlay.css(startOverlay);
684			dom.gv_overlay.animate(endOverlay,{ duration: speed, easing: 'swing' });
685			dom.gv_showOverlay.animate(endButton,{ duration: speed, easing: 'swing' });
686			
687			this.overlayVisible = true;
688		},
689		
690		updateFilmstrip: function(to) {
691			if(!this.opts.show_filmstrip) { this.frameIterator = to; return; }
692			var self = this,
693				dom = this.dom,
694				targetThumbs = dom.gv_thumbnails.eq(this.iterator),
695				filmstripIterator,
696				distance;
697			
698			if(this.scrolling) {
699				targetThumbs = targetThumbs.
700								add(dom.gv_thumbnails.eq(this.iterator + this.numImages)).
701								add(dom.gv_thumbnails.eq(this.iterator + (2 * this.numImages)));	
702			}
703			
704			dom.gv_thumbnails.removeClass('current').animate({ opacity: this.opts.frame_opacity });
705			targetThumbs.stop().addClass('current').animate({ opacity: 1 },500);
706			
707			
708			if(this.scrolling) {
709				if(this.filmstripOrientation === 'horizontal') {
710					distance = (gv.outerWidth(dom.gv_frame) + this.opts.frame_gap) * (this.frameIterator - to);
711					
712					if(distance > 0) {
713						distance = '+=' + Math.abs(distance);
714					} else {
715						distance = '-=' + Math.abs(distance);
716					}
717					dom.gv_filmstrip.animate({
718						left: distance
719					},{
720						duration: this.opts.transition_speed, 
721						easing: this.opts.easing, 
722						complete: function(){
723							if(to < self.numImages) {
724								dom.gv_filmstrip.css('left',gv.getInt(dom.gv_filmstrip.css('left'))-(self.numImages*(gv.outerWidth(dom.gv_frame)+self.opts.frame_gap)));	
725							} else if(to >= (self.numImages * 2)) {
726								dom.gv_filmstrip.css('left',gv.getInt(dom.gv_filmstrip.css('left'))+(self.numImages*(gv.outerWidth(dom.gv_frame)+self.opts.frame_gap)));	
727							}
728							self.frameIterator = (to % self.numImages) + self.numImages;
729						}
730					});
731				} else {
732					distance = (gv.outerHeight(dom.gv_frame) + this.opts.frame_gap) * (this.frameIterator - to);
733					
734					if(distance > 0) {
735						distance = '+=' + Math.abs(distance);
736					} else {
737						distance = '-=' + Math.abs(distance);
738					}
739					dom.gv_filmstrip.animate({
740						top: distance
741					},{
742						duration: this.opts.transition_speed, 
743						easing: this.opts.easing, 
744						complete: function(){
745							// adjust filmstrip position to ensure that there is always at least one frame behind
746							// and (2 * filmstripSize) ahead
747							if(to === 0) {
748								dom.gv_filmstrip.css('top',gv.getInt(dom.gv_filmstrip.css('top'))-(self.numImages*(gv.outerHeight(dom.gv_frame)+self.opts.frame_gap)));	
749								self.frameIterator = self.numImages;
750							} else if(to > ((self.numImages * 3) - (self.filmstripSize * 2))) {
751								dom.gv_filmstrip.css('top',gv.getInt(dom.gv_filmstrip.css('top'))+(self.numImages*(gv.outerHeight(dom.gv_frame)+self.opts.frame_gap)));	
752								self.frameIterator = to - self.numImages;
753							} else {
754								self.frameIterator = to;
755							}
756						}
757					});
758				}
759				
760			} else {
761				this.frameIterator = to;
762			}
763		},
764		
765		startSlideshow: function(changeIcon) {
766			var self = this,
767				dom = this.dom;
768				
769			if(!self.opts.enable_slideshow) { return; }
770			
771			if(changeIcon) {
772				dom.gv_navPlay.removeClass('gv_navPlay').addClass('gv_navPause');
773			}
774			this.playing = true;
775			dom.gv_galleryWrap.everyTime(this.opts.transition_interval,'slideshow_'+this.id,function(){ self.showNext(); });
776		},
777		
778		stopSlideshow: function(changeIcon) {
779			var self = this,
780				dom = this.dom;
781				
782			if(changeIcon) {
783				dom.gv_navPlay.removeClass('gv_navPause').addClass('gv_navPlay');
784			}
785			this.playing = false;
786			dom.gv_galleryWrap.stopTime('slideshow_'+this.id);
787		},
788		
789		enablePanning: function() {
790			var self = this,
791				dom = this.dom;
792				
793			if(!self.opts.enable_slideshow) { return; }
794			
795			dom.gv_panel.css('cursor','url(http://www.google.com/intl/en_ALL/mapfiles/openhand.cur), n-resize');
796			if(this.opts.pan_style === 'drag') {
797				dom.gv_panelWrap.delegate('.gv_panel img','mousedown.galleryview',function(e) {
798					self.isMouseDown = true;
799					$(this).css('cursor','url(http://www.google.com/intl/en_ALL/mapfiles/closedhand.cur), n-resize');
800				}).delegate('.gv_panel img','mouseup.galleryview',function(e) {
801					self.isMouseDown = false;
802					$(this).css('cursor','url(http://www.google.com/intl/en_ALL/mapfiles/openhand.cur), n-resize');
803				}).delegate('.gv_panel img','mousemove.galleryview',function(e) {
804					var distY, distX,
805						image = $(this),
806						new_top, new_left;
807
808					if(self.isMouseDown) {
809						distY = e.pageY - self.mouse.y;
810						distX = e.pageX - self.mouse.x;
811						new_top = gv.getInt(image.css('top')) + distY;
812						new_left = gv.getInt(image.css('left')) + distX;
813							
814						image.css('cursor','url(http://www.google.com/intl/en_ALL/mapfiles/closedhand.cur), n-resize');
815						
816						if(new_top > 0) new_top = 0;
817						if(new_left > 0) new_left = 0;
818						
819						if(new_top < (-1 * (gv.outerHeight(image) - gv.innerHeight(dom.gv_panel)))) { new_top = -1 * (gv.outerHeight(image) - gv.innerHeight(dom.gv_panel)); }
820						if(new_left < (-1 * (gv.outerWidth(image) - gv.innerWidth(dom.gv_panel)))) { new_left = -1 * (gv.outerWidth(image) - gv.innerWidth(dom.gv_panel)); }
821						
822						image.css('top',new_top);
823						image.css('left',new_left);
824					} else {
825						image.css('cursor','url(http://www.google.com/intl/en_ALL/mapfiles/openhand.cur), n-resize');	
826					}
827				});
828			} else {
829				
830			}
831		},
832		
833		bindActions: function() {
834			var self = this,
835				dom = this.dom;
836			
837			dom.gv_showOverlay.bind('click.galleryview',function(){
838				if(self.overlayVisible) {
839					self.hideOverlay(250);
840				} else {
841					self.showOverlay(250);
842				}
843			});
844			
845			dom.gv_navWrap.delegate('div','click.galleryview',function(){
846				var el = $(this);
847				if(el.hasClass('gv_navNext')) {
848					self.showNext();
849				} else if(el.hasClass('gv_navPrev')) {
850					self.showPrev();
851				} else if(el.hasClass('gv_navPlay')) {
852					self.startSlideshow(true);
853				} else if(el.hasClass('gv_navPause')) {
854					self.stopSlideshow(true);
855				}
856				return false;
857			});
858			
859			dom.gv_panelNavNext.bind('click.galleryview',function(){ 
860				self.showNext(); 
861				return false;
862			});
863			dom.gv_panelNavPrev.bind('click.galleryview',function(){
864				self.showPrev(); 
865				return false;
866			});
867			
868			dom.gv_filmstripWrap.delegate('.gv_frame','click.galleryview',function(){
869				var el = $(this),
870					i = el.data('frameIndex');
871				
872				this.navAction = 'frame';
873				self.showItem(i);
874				return false;
875			});
876			
877			dom.gv_panelWrap.bind('mouseover.galleryview',function(){
878				self.showPanelNav();
879			}).bind('mouseout.galleryview',function(){
880				self.hidePanelNav();
881			});
882		},
883		
884		unbindActions: function() {
885			var self = this,
886				dom = this.dom;
887				
888			dom.gv_showOverlay.unbind('click.galleryview');
889			dom.gv_panelNavNext.unbind('click.galleryview');
890			dom.gv_panelNavPrev.unbind('click.galleryview');
891			dom.gv_navWrap.undelegate('div','click.galleryview');
892			dom.gv_filmstripWrap.undelegate('.gv_frame','click.galleryview');
893		},
894		
895		showPanelNav: function() {
896			var self = this,
897				dom = this.dom;
898				
899			dom.gv_panelNavNext.show();
900			dom.gv_panelNavPrev.show();	
901		},
902		
903		hidePanelNav: function() {
904			var self = this,
905				dom = this.dom;
906				
907			dom.gv_panelNavNext.hide();
908			dom.gv_panelNavPrev.hide();	
909		},
910		
911		init: function(options,el) {
912			var self = this,
913				dom = this.dom = {};
914				
915			this.opts = $.extend({},$.fn.galleryView.defaults,options);
916			this.el = el;
917			this.$el = $(el);
918			this.id = el.id;
919			this.iterator = this.frameIterator = this.opts.start_frame - 1;
920			this.overlayVisible = false;
921			this.playing = false;
922			this.scrolling = false;
923			this.isMouseDown = false;
924			this.mouse = { x: 0, y: 0 };
925			this.filmstripOrientation = (this.opts.filmstrip_position === 'top' || this.opts.filmstrip_position === 'bottom') ? 'horizontal' : 'vertical';
926			
927			$(document).bind('mousemove.galleryview',function(e) {
928				self.mouse = {x: e.pageX, y: e.pageY};	   
929			});
930			
931			// create all necessary DOM elements
932			$.each(this.elems,function(i,elem) {
933				var elem = elem.split('.');
934				
935				// if there is no tag name, assume <div>
936				if(elem[0] === '') { elem[0] = 'div'; }
937				
938				// add jQuery element to dom object
939				dom[elem[1]] = self.createElem({'class':elem[1]},elem[0]);
940			});
941			
942			dom.gv_imageStore.appendTo($('body'));
943			
944			dom.gv_galleryWrap.delegate('img','mousedown.galleryview',function(e){ if(e.preventDefault) { e.preventDefault(); } });
945			
946			dom.gv_panel.addClass('gv_panel-loading');
947			dom.gv_frame.addClass('gv_frame-loading');
948			
949			// nest DOM elements
950			dom.gv_galleryWrap.hide().append(dom.gv_gallery);
951			
952			if(this.opts.show_panels) {
953				dom.gv_gallery.append(dom.gv_panelWrap);
954				if(this.opts.show_panel_nav) {
955					dom.gv_panelWrap.append(dom.gv_panelNavNext,dom.gv_panelNavPrev);
956				}
957				if(this.opts.show_infobar) {
958					dom.gv_panelWrap.append(dom.gv_infobar);
959				}
960			}
961			
962			if(this.opts.show_filmstrip) {
963				dom.gv_gallery.append(
964					dom.gv_filmstripWrap.append(
965						dom.gv_filmstrip
966					)
967				);
968				
969				if(this.opts.show_filmstrip_nav) {
970					dom.gv_gallery.append(
971						dom.gv_navWrap.append(
972							dom.gv_navPrev,
973							(this.opts.enable_slideshow?dom.gv_navPlay:$('<span></span>')),
974							dom.gv_navNext
975						)
976					);
977				}
978			}
979			
980			if(this.opts.enable_overlays) {
981				dom.gv_panelWrap.append(dom.gv_overlay,dom.gv_showOverlay);	
982			}
983			
984			if(this.opts.show_captions) {
985				dom.gv_frame.append(dom.gv_caption).appendTo(dom.gv_gallery);	
986			}
987			
988			//swap out source element with gallery
989			this.$el.replaceWith(dom.gv_galleryWrap);
990			
991			if(this.opts.pan_images) {
992				this.enablePanning();
993			}
994			
995			// convert source images into gvImage objects
996			this.storeImages();
997			
998			// block out dimensions/positions of gallery elements
999			this.buildGallery();
1000			
1001			// begin loading images into gallery
1002			this.initImages();
1003			
1004			// set up transitions, buttons
1005			this.bindActions();
1006			
1007			// remove temporary frame element
1008			dom.gv_frame.remove();
1009			
1010			// show gallery
1011			dom.gv_galleryWrap.show();
1012			
1013			if(this.opts.autoplay) {
1014				this.startSlideshow(true);
1015			}
1016			
1017			this.updateOverlay(this.iterator);
1018			this.updateFilmstrip(this.frameIterator);
1019		}
1020		
1021	}; // END GalleryView
1022	
1023	/*
1024		MAIN PLUGIN CODE
1025	*/
1026	$.fn.galleryView = function (options) {
1027		if (this.length) {
1028			return this.each(function () {
1029				var gallery = Object.create(GalleryView);
1030				gallery.init(options,this);
1031			});
1032		}
1033	};
1034	
1035	/*
1036		Default Options
1037			Object literal storing default plugin options
1038	*/
1039	$.fn.galleryView.defaults = {
1040	
1041		// General Options
1042		transition_speed: 1000, 		//INT - duration of panel/frame transition (in milliseconds)
1043		transition_interval: 5000, 		//INT - delay between panel/frame transitions (in milliseconds)
1044		easing: 'swing', 				//STRING - easing method to use for animations (jQuery provides 'swing' or 'linear', more available with jQuery UI or Easing plugin)
1045		
1046		// Panel Options
1047		show_panels: true, 				//BOOLEAN - flag to show or hide panel portion of gallery
1048		show_panel_nav: true, 			//BOOLEAN - flag to show or hide panel navigation buttons
1049		enable_overlays: false, 			//BOOLEAN - flag to show or hide panel overlays
1050		panel_width: 800, 				//INT - width of gallery panel (in pixels)
1051		panel_height: 400, 				//INT - height of gallery panel (in pixels)
1052		panel_animation: 'fade', 		//STRING - animation method for panel transitions (crossfade,fade,slide,none)
1053		panel_scale: 'crop', 			//STRING - cropping option for panel images (crop = scale image and fit to aspect ratio determined by panel_width and panel_height, fit = scale image and preserve original aspect ratio)
1054		overlay_position: 'bottom', 	//STRING - position of panel overlay (bottom, top)
1055		pan_images: false,				//BOOLEAN - flag to allow user to grab/drag oversized images within gallery
1056		pan_style: 'drag',				//STRING - panning method (drag = user clicks and drags image to pan, track = image automatically pans based on mouse position
1057		pan_smoothness: 15,				//INT - determines smoothness of tracking pan animation (higher number = smoother)
1058		
1059		// Filmstrip Options
1060		start_frame: 1, 				//INT - index of panel/frame to show first when gallery loads
1061		show_filmstrip: true, 			//BOOLEAN - flag to show or hide filmstrip portion of gallery
1062		show_filmstrip_nav: true, 		//BOOLEAN - flag indicating whether to display navigation buttons
1063		enable_slideshow: true,			//BOOLEAN - flag indicating whether to display slideshow play/pause button
1064		autoplay: false,				//BOOLEAN - flag to start slideshow on gallery load
1065		show_captions: false, 			//BOOLEAN - flag to show or hide frame captions	
1066		filmstrip_size: 3, 				//INT - number of frames to show in filmstrip-only gallery
1067		filmstrip_style: 'scroll', 		//STRING - type of filmstrip to use (scroll = display one line of frames, scroll filmstrip if necessary, showall = display multiple rows of frames if necessary)
1068		filmstrip_position: 'bottom', 	//STRING - position of filmstrip within gallery (bottom, top, left, right)
1069		frame_width: 80, 				//INT - width of filmstrip frames (in pixels)
1070		frame_height: 40, 				//INT - width of filmstrip frames (in pixels)
1071		frame_opacity: 0.4, 			//FLOAT - transparency of non-active frames (1.0 = opaque, 0.0 = transparent)
1072		frame_scale: 'crop', 			//STRING - cropping option for filmstrip images (same as above)
1073		frame_gap: 5, 					//INT - spacing between frames within filmstrip (in pixels)
1074		
1075		// Info Bar Options
1076		show_infobar: true,				//BOOLEAN - flag to show or hide infobar
1077		infobar_opacity: 1				//FLOAT - transparency for info bar
1078	};
1079})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.