/*
GalleryView - jQuery Content Gallery Plugin
Author: Jack Anderson
Version: 3.0 DEVELOPMENT
See README.txt for instructions on how to markup your HTML
*/
// Make sure Object.create is available in the browser (for our prototypal inheritance)
// Courtesy of Douglas Crockford
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() { }
F.prototype = o;
return new F();
};
}
(function ($) {
// custom image object
var gvImage = function (img) {
this.src = {
panel: img.attr('src'),
frame: img.data('frame') || img.attr('src')
};
this.scale = {
panel: null,
frame: null
};
this.height = 0;
this.width = 0;
this.attrs = {
title: img.attr('title') || img.attr('alt'),
description: img.data('description')
};
this.href = img.data('href'); // Important for clickable links
this.dom_obj = null;
return this;
},
// utility function wrapper
gv = {
getInt: function (i) {
i = parseInt(i, 10);
return isNaN(i) ? 0 : i;
},
innerWidth: function (elem) {
return this.getInt(elem.css('width')) || 0;
},
outerWidth: function (elem) {
return this.innerWidth(elem) +
this.extraWidth(elem);
},
extraWidth: function (elem) {
return this.getInt(elem.css('paddingLeft')) +
this.getInt(elem.css('paddingRight')) +
this.getInt(elem.css('borderLeftWidth')) +
this.getInt(elem.css('borderRightWidth'));
},
innerHeight: function (elem) {
return this.getInt(elem.css('height')) || 0;
},
outerHeight: function (elem) {
return this.innerHeight(elem) +
this.extraHeight(elem);
},
extraHeight: function (elem) {
return this.getInt(elem.css('paddingTop')) +
this.getInt(elem.css('paddingBottom')) +
this.getInt(elem.css('borderTopWidth')) +
this.getInt(elem.css('borderBottomWidth'));
}
},
/*
GalleryView - Object
The main gallery class
*/
GalleryView = {
// array of dom elements
elems: [
'.gv_galleryWrap', '.gv_gallery', '.gv_panelWrap', '.gv_panel',
'img.gv_image', '.gv_infobar', '.gv_filmstripWrap', '.gv_filmstrip',
'.gv_frame', '.gv_thumbnail', '.gv_caption', 'img.gv_thumb',
'.gv_navWrap', '.gv_navNext', '.gv_navPrev', '.gv_navPlay',
'.gv_panelNavNext', '.gv_panelNavPrev', '.gv_overlay', '.gv_showOverlay',
'.gv_imageStore'
],
// create a jQuery element and apply attributes
createElem: function (attrs, elem) {
elem = document.createElement(elem);
var $elem = $(elem);
return $elem.attr(attrs);
},
// get the position of an element with respect
// to the gallery wrapper
getPos: function (el) {
var self = this,
dom = this.dom,
el = el[0],
el_id = el.id,
left = 0,
top = 0,
gPos, gLeft, gTop;
if (!el) { return { top: 0, left: 0 }; }
if (el.offsetParent) {
do {
left += el.offsetLeft;
top += el.offsetTop;
} while (el = el.offsetParent);
}
//If we want the position of the gallery itself, return it
if (el_id === self.id) { return { left: left, top: top }; }
//Otherwise, get position of element relative to gallery
else {
gPos = self.getPos(dom.galleryWrap);
gLeft = gPos.left;
gTop = gPos.top;
return { left: left - gLeft, top: top - gTop };
}
},
// determine if mouse is within the boundary of the gallery wrapper
mouseIsOverGallery: function (x, y) {
var self = this,
dom = this.dom,
pos = this.getPos(dom.gv_galleryWrap),
top = pos.top,
left = pos.left;
return x > left && x < left + gv.outerWidth(dom.gv_galleryWrap) && y > top && y < top + gv.outerHeight(dom.gv_galleryWrap);
},
// determine if mouse is within the boundary of the panel
mouseIsOverPanel: function (x, y) {
var self = this,
dom = this.dom,
pos = this.getPos(dom.gv_panelWrap),
gPos = this.getPos(dom.gv_galleryWrap),
top = pos.top + gPos.top,
left = pos.left + gPos.left;
return x > left && x < left + gv.outerWidth(dom.gv_panelWrap) && y > top && y < top + gv.outerHeight(dom.gv_panelWrap);
},
// create gvImage objects for each image in gallery
storeImages: function () {
var self = this;
this.sourceImgs = $('li>img', this.$el);
this.numImages = this.sourceImgs.length;
this.gvImages = [];
this.sourceImgs.each(function (i, img) {
self.gvImages[i] = new gvImage($(img));
});
},
setDimensions: function () {
var self = this,
dom = this.dom,
widths = {
prev: gv.innerWidth(dom.gv_navPrev),
play: gv.innerWidth(dom.gv_navPlay),
next: gv.innerWidth(dom.gv_navNext),
filmstrip: this.opts.frame_width,
fsMax: 0,
fsFull: 0
},
heights = {
prev: gv.innerHeight(dom.gv_navPrev),
play: gv.innerHeight(dom.gv_navPlay),
next: gv.innerHeight(dom.gv_navNext),
filmstrip: this.opts.frame_height + (this.opts.show_captions ? gv.outerHeight(dom.gv_caption) : 0),
fsMax: 0,
fsFull: 0
},
panels = [];
// nav
if (this.filmstripOrientation === 'horizontal') {
dom.gv_navWrap.css({
width: widths.prev + widths.play + widths.next,
height: Math.max(heights.prev, heights.play, heights.next)
});
} else {
if (this.opts.filmstrip_style === 'scroll' && this.opts.frame_width < (widths.prev + widths.play + widths.next)) {
dom.gv_navWrap.css({
width: Math.max(widths.prev, widths.play, widths.next),
height: heights.prev + heights.play + heights.next
});
} else {
dom.gv_navWrap.css({
width: widths.prev + widths.play + widths.next,
height: Math.max(heights.prev, heights.play, heights.next)
});
}
}
if (this.filmstripOrientation === 'vertical' && widths.filmstrip < (widths.prev + widths.play + widths.next)) {
dom.gv_navWrap.css({
width: Math.max(widths.prev, widths.play, widths.next),
height: heights.prev + heights.play + heights.next
});
} else {
dom.gv_navWrap.css({
width: widths.prev + widths.play + widths.next,
height: Math.max(heights.prev, heights.play, heights.next)
});
}
// panels
dom.gv_panel.css({
width: this.opts.panel_width,
height: this.opts.panel_height
});
dom.gv_panelWrap.css({
width: gv.outerWidth(dom.gv_panel),
height: gv.outerHeight(dom.gv_panel)
});
dom.gv_overlay.css({
width: this.opts.panel_width
});
$.each(this.gvImages, function (i, img) {
dom.gv_panelWrap.append(dom.gv_panel.clone(true));
});
dom.gv_panels = dom.gv_panelWrap.find('.gv_panel');
dom.gv_panels.remove();
// filmstrip
dom.gv_thumbnail.css({
width: this.opts.frame_width,
height: this.opts.frame_height
});
dom.gv_frame.css({
width: gv.outerWidth(dom.gv_thumbnail),
height: gv.outerHeight(dom.gv_thumbnail) + (this.opts.show_captions ? gv.outerHeight(dom.gv_caption) : 0),
marginRight: this.opts.frame_gap,
marginBottom: this.opts.frame_gap
});
if (this.filmstripOrientation === 'horizontal') {
this.filmstripSize = Math.floor((gv.outerWidth(dom.gv_panelWrap) - gv.outerWidth(dom.gv_navWrap)) / (gv.outerWidth(dom.gv_frame) + this.opts.frame_gap));
widths.fsMax = this.filmstripSize * (gv.outerWidth(dom.gv_frame) + this.opts.frame_gap);
widths.fsFull = this.gvImages.length * (gv.outerWidth(dom.gv_frame) + this.opts.frame_gap);
widths.filmstrip = Math.min(widths.fsMax, widths.fsFull);
if (this.opts.filmstrip_style !== 'scroll') {
heights.filmstrip = (Math.ceil(this.gvImages.length / this.filmstripSize) * (gv.outerHeight(dom.gv_frame) + this.opts.frame_gap)) - this.opts.frame_gap;
}
} else {
this.filmstripSize = Math.floor((gv.outerHeight(dom.gv_panelWrap) - gv.outerHeight(dom.gv_navWrap)) / (gv.outerHeight(dom.gv_frame) + this.opts.frame_gap));
heights.fsMax = this.filmstripSize * (gv.outerHeight(dom.gv_frame) + this.opts.frame_gap);
heights.fsFull = this.gvImages.length * (gv.outerHeight(dom.gv_frame) + this.opts.frame_gap);
heights.filmstrip = Math.min(heights.fsMax, heights.fsFull);
if (this.opts.filmstrip_style !== 'scroll') {
widths.filmstrip = (Math.ceil(this.gvImages.length / this.filmstripSize) * (gv.outerWidth(dom.gv_frame) + this.opts.frame_gap)) - this.opts.frame_gap;
}
}
dom.gv_filmstripWrap.css({
width: widths.filmstrip,
height: heights.filmstrip
});
// gallery
if (this.opts.show_filmstrip) {
if (this.filmstripOrientation === 'horizontal') {
dom.gv_gallery.css({
width: gv.outerWidth(dom.gv_panelWrap),
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))
});
} else {
dom.gv_gallery.css({
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)),
height: gv.outerHeight(dom.gv_panelWrap)
});
}
} else {
dom.gv_gallery.css({
width: gv.outerWidth(dom.gv_panelWrap),
height: gv.outerHeight(dom.gv_panelWrap)
});
}
dom.gv_galleryWrap.css({
width: gv.outerWidth(dom.gv_gallery),
height: gv.outerHeight(dom.gv_gallery),
padding: this.opts.frame_gap
});
},
setPositions: function () {
var self = this,
dom = this.dom,
navVert = 0, fsVert = 0,
navHorz = 0, fsHorz = 0,
vert, horz;
// determine vertical or horizontal offset
// if negative, apply to filmstrip, otherwise apply to navbar
if (this.filmstripOrientation === 'horizontal') {
vert = Math.round((gv.outerHeight(dom.gv_filmstripWrap) - gv.outerHeight(dom.gv_navWrap)) / 2);
if (vert < 0) { fsVert = -1 * vert; }
else { navVert = vert; }
} else {
horz = Math.round((gv.outerWidth(dom.gv_filmstripWrap) - gv.outerWidth(dom.gv_navWrap)) / 2);
if (horz < 0) { fsHorz = -1 * horz; }
else { navHorz = horz; }
}
// for horizontal filmstrips w/o navigation, center the filmstrip under the panel
if (!this.opts.show_filmstrip_nav && this.filmstripOrientation === 'horizontal') {
fsHorz = Math.floor((gv.outerWidth(dom.gv_panelWrap) - gv.outerWidth(dom.gv_filmstripWrap)) / 2);
}
dom.gv_panelNavNext.css({ top: (gv.outerHeight(dom.gv_panel) - gv.outerHeight(dom.gv_panelNavNext)) / 2, right: 10 });
dom.gv_panelNavPrev.css({ top: (gv.outerHeight(dom.gv_panel) - gv.outerHeight(dom.gv_panelNavPrev)) / 2, left: 10 });
// pin elements to gallery corners according to filmstrip position
switch (this.opts.filmstrip_position) {
case 'top':
dom.gv_navWrap.css({ top: navVert, right: navHorz });
dom.gv_panelWrap.css({ bottom: 0, left: 0 });
dom.gv_filmstripWrap.css({ top: fsVert, left: fsHorz });
break;
case 'right':
dom.gv_navWrap.css({ bottom: navVert, right: navHorz });
dom.gv_panelWrap.css({ top: 0, left: 0 });
dom.gv_filmstripWrap.css({ top: fsVert, right: fsHorz });
break;
case 'left':
dom.gv_navWrap.css({ bottom: navVert, left: navHorz });
dom.gv_panelWrap.css({ top: 0, right: 0 });
dom.gv_filmstripWrap.css({ top: fsVert, left: fsHorz });
break;
default:
dom.gv_navWrap.css({ bottom: navVert, right: navHorz });
dom.gv_panelWrap.css({ top: 0, left: 0 });
dom.gv_filmstripWrap.css({ bottom: fsVert, left: fsHorz });
break;
}
if (this.opts.overlay_position === 'top') {
dom.gv_overlay.css({ top: 0, left: -99999 });
dom.gv_showOverlay.css({ top: 0, left: 0 });
} else {
dom.gv_overlay.css({ bottom: 0, left: -99999 });
dom.gv_showOverlay.css({ bottom: 0, left: 0 });
}
if (!this.opts.show_filmstrip_nav) {
dom.gv_navWrap.remove();
}
},
buildFilmstrip: function () {
var self = this,
dom = this.dom,
framesLength = this.gvImages.length * ((this.filmstripOrientation === 'horizontal' ? this.opts.frame_width : this.opts.frame_height) + this.opts.frame_gap);
dom.gv_frame.append(dom.gv_thumbnail);
if (this.opts.show_captions) {
dom.gv_frame.append(dom.gv_caption);
}
dom.gv_thumbnail.css('opacity', this.opts.frame_opacity);
dom.gv_thumbnail.bind({
mouseover: function () {
if (!$(this).hasClass('current')) {
$(this).stop().animate({ opacity: 1 }, 250);
}
},
mouseout: function () {
if (!$(this).hasClass('current')) {
$(this).stop().animate({ opacity: self.opts.frame_opacity }, 250);
}
}
});
// Drop a clone of the frame element into the filmstrip for each source image
$.each(this.gvImages, function (i, img) {
dom.gv_frame.clone(true).prependTo(dom.gv_filmstrip);
});
dom.gv_filmstrip.css({
width: gv.outerWidth(dom.gv_frame),
height: gv.outerHeight(dom.gv_frame)
});
// If we are scrolling the filmstrip, and we can't show all frames at once,
// make two additional copies of each frame
if (this.opts.filmstrip_style === 'scroll') {
if (this.filmstripOrientation === 'horizontal') {
if (framesLength > gv.innerWidth(dom.gv_filmstripWrap)) {
dom.gv_filmstrip.find('.gv_frame').clone(true).appendTo(dom.gv_filmstrip).clone(true).appendTo(dom.gv_filmstrip);
dom.gv_filmstrip.css('width', framesLength * 3);
this.scrolling = true;
} else {
dom.gv_filmstrip.css('width', framesLength);
}
} else {
if (framesLength > gv.innerHeight(dom.gv_filmstripWrap)) {
dom.gv_filmstrip.find('.gv_frame').clone(true).appendTo(dom.gv_filmstrip).clone(true).appendTo(dom.gv_filmstrip);
dom.gv_filmstrip.css('height', framesLength * 3);
this.scrolling = true;
} else {
dom.gv_filmstrip.css('height', framesLength);
}
}
} else {
dom.gv_filmstrip.css({
width: parseInt(dom.gv_filmstripWrap.css('width'), 10) + this.opts.frame_gap,
height: parseInt(dom.gv_filmstripWrap.css('height'), 10) + this.opts.frame_gap
});
}
dom.gv_frames = dom.gv_filmstrip.find('.gv_frame');
$.each(dom.gv_frames, function (i, frame) {
$(frame).data('frameIndex', i);
});
dom.gv_thumbnails = dom.gv_filmstrip.find('div.gv_thumbnail');
},
buildGallery: function () {
var self = this,
dom = this.dom;
this.setDimensions();
this.setPositions();
if (this.opts.show_filmstrip) {
this.buildFilmstrip();
}
},
showInfoBar: function () {
if (!this.opts.show_infobar) { return; }
var self = this,
dom = this.dom;
dom.gv_infobar.stop().stopTime('hideInfoBar_' + self.id).html((this.iterator + 1) + ' of ' + this.numImages).show().css('opacity', this.opts.infobar_opacity);
dom.gv_infobar.oneTime(2000 + this.opts.transition_speed, 'hideInfoBar_' + self.id, function () {
dom.gv_infobar.fadeOut(1000);
});
},
initImages: function () {
var self = this,
dom = this.dom;
$.each(this.gvImages, function (i, gvImage) {
var img = $('');
img.css('visibility', 'hidden').data('index', i);
img.bind('load.galleryview', function () {
var _img = $(this),
index = _img.data('index'),
width = this.width,
height = this.height,
parent = dom[(_img.data('parent')).type].eq((_img.data('parent')).index),
widthFactor = gv.innerWidth(parent) / width,
heightFactor = gv.innerHeight(parent) / height,
parentType = parent.hasClass('gv_panel') ? 'panel' : 'frame',
heightOffset = 0, widthOffset = 0;
gvImage.scale[parentType] = self.opts[parentType + '_scale'] === 'fit' ? Math.min(widthFactor, heightFactor) : Math.max(widthFactor, heightFactor);
widthOffset = Math.round((gv.innerWidth(parent) - (width * gvImage.scale[parentType])) / 2);
heightOffset = Math.round((gv.innerHeight(parent) - (height * gvImage.scale[parentType])) / 2);
_img.css({
width: width * gvImage.scale[parentType],
height: height * gvImage.scale[parentType],
top: heightOffset,
left: widthOffset
});
_img.hide().css('visibility', 'visible');
_img.remove().appendTo(parent);
if (parentType === 'frame') {
_img.fadeIn();
parent.parent().removeClass('gv_frame-loading');
parent.parent().find('.gv_caption').html(gvImage.attrs.title);
} else if (index === self.opts.start_frame - 1) {
parent.prependTo(dom.gv_panelWrap);
parent.removeClass('gv_panel-loading');
_img.fadeIn();
self.showInfoBar();
} else {
parent.removeClass('gv_panel-loading');
_img.show();
}
});
// store eventual image container as data property
// append to temporary storage element and set src
if (self.opts.show_panels) {
img.clone(true)
.data('parent', { type: 'gv_panels', index: i })
.appendTo(dom.gv_imageStore)
.attr('src', gvImage.src.panel);
}
if (self.opts.show_filmstrip) {
img.clone(true)
.data('parent', { type: 'gv_thumbnails', index: i })
.appendTo(dom.gv_imageStore)
.attr('src', gvImage.src.frame);
if (dom.gv_frames.length > dom.gv_panels.length) {
img.clone(true)
.data('parent', { type: 'gv_thumbnails', index: i + self.numImages })
.appendTo(dom.gv_imageStore)
.attr('src', gvImage.src.frame);
img.clone(true)
.data('parent', { type: 'gv_thumbnails', index: i + self.numImages + self.numImages })
.appendTo(dom.gv_imageStore)
.attr('src', gvImage.src.frame);
}
}
});
},
showNext: function () {
this.navAction = 'next';
if (this.playing && this.opts.play_random_order) {
var nextImage = this.frameIterator;
while (nextImage == this.frameIterator) {
nextImage = Math.floor(Math.random()*(this.numImages + 1));
}
this.showItem(nextImage);
} else {
this.showItem(this.frameIterator + 1);
}
},
showPrev: function () {
this.navAction = 'prev';
this.showItem(this.frameIterator - 1);
},
showItem: function (i) {
if (isNaN(i)) { return; }
if (!this.opts.show_filmstrip) { i = i % this.numImages; }
var self = this,
dom = this.dom,
frame_i = i,
newPanelStart,
oldPanelEnd,
oldIterator,
panel,
playing = false;
// don't go out of bounds
i = self.getTrueImageIndex(i);
panel = dom.gv_panels.eq(i);
playing = this.playing;
if (playing) {
this.stopSlideshow(false);
}
this.unbindActions();
dom.gv_gallery.oneTime(this.opts.transition_speed, 'bindActions_' + self.id, function () { if (playing) { self.startSlideshow(false); } self.bindActions(); });
switch (this.opts.panel_animation) {
case 'crossfade':
dom.gv_panels.eq(this.iterator).fadeOut(this.opts.transition_speed, function () { $(this).remove(); });
panel.hide().prependTo(dom.gv_panelWrap).fadeIn(this.opts.transition_speed);
break;
case 'fade':
dom.gv_panels.eq(this.iterator).remove();
panel.hide().prependTo(dom.gv_panelWrap).fadeIn(this.opts.transition_speed);
break;
case 'slide':
if (this.navAction === 'next' || (this.navAction === 'frame' && frame_i > this.iterator)) {
newPanelStart = gv.outerWidth(dom.gv_panel);
oldPanelEnd = -1 * gv.outerWidth(dom.gv_panel);
} else {
newPanelStart = -1 * gv.outerWidth(dom.gv_panel);
oldPanelEnd = gv.outerWidth(dom.gv_panel);
}
panel.css({ left: newPanelStart }).appendTo(dom.gv_panelWrap).animate(
{ left: 0 },
{ duration: this.opts.transition_speed, easing: this.opts.easing }
);
dom.gv_panels.eq(this.iterator).animate(
{ left: oldPanelEnd },
{ duration: this.opts.transition_speed, easing: this.opts.easing, complete: function () { $(this).remove(); } }
);
break;
default:
dom.gv_panels.eq(this.iterator).remove();
panel.prependTo(dom.gv_panelWrap);
break;
}
this.updateOverlay(i);
this.updateClickable(i);
this.iterator = i;
this.updateFilmstrip(frame_i);
this.showInfoBar();
},
// given an index i, it will adjust i to an appropriate
// index that is within the bounds of the images array
// pulled out of showItem so it could be re-used for
// other methods and events
getTrueImageIndex: function (i) {
if (i >= this.numImages) {
i = i % this.numImages;
} else if (i < 0) {
i = this.numImages - 1;
if (dom.gv_frames != undefined) {
frame_i = dom.gv_frames.length - 1;
} else {
frame_i = dom.gv_panels.length - 1;
}
}
return i;
},
updateOverlay: function (i) {
var self = this,
dom = this.dom;
var cursorStyle = '';
if (this.opts.clickable == 'overlay' || this.opts.clickable == 'all') {
cursorStyle = ' class="cursor_pointer"';
}
var overlayHtml = '
' + self.gvImages[i].attrs.description + '
'; if (this.overlayVisible) { this.hideOverlay(null, function () { dom.gv_overlay.html(overlayHtml); self.showOverlay(); }); } else { dom.gv_overlay.html(overlayHtml); dom.gv_overlay.css(this.opts.overlay_position, -1 * dom.gv_overlay.outerHeight()); } if (this.opts.clickable == 'overlay' || this.opts.clickable == 'all') { dom.gv_panelWrap.undelegate('.gv_overlay h4', 'click.galleryview'); dom.gv_panelWrap.delegate('.gv_overlay h4', 'click.galleryview', this.doClick(self.gvImages[i].href)); } }, hideOverlay: function (s, callback) { var self = this, dom = this.dom, endOverlay = {}, endButton = {}, speed = s || self.opts.transition_speed / 2; callback = callback || function () { }; endOverlay[this.opts.overlay_position] = -1 * dom.gv_overlay.outerHeight(); endButton[this.opts.overlay_position] = 0; dom.gv_overlay.animate(endOverlay, { duration: speed, easing: 'swing', complete: callback }); dom.gv_showOverlay.animate(endButton, { duration: speed, easing: 'swing' }); this.overlayVisible = false; }, showOverlay: function (s) { var self = this, dom = this.dom, startOverlay = {}, endOverlay = {}, endButton = {}, speed = s || self.opts.transition_speed / 2; startOverlay[this.opts.overlay_position] = -1 * dom.gv_overlay.outerHeight(); startOverlay.left = 0; endOverlay[this.opts.overlay_position] = 0; endButton[this.opts.overlay_position] = dom.gv_overlay.outerHeight(); dom.gv_overlay.css(startOverlay); dom.gv_overlay.animate(endOverlay, { duration: speed, easing: 'swing' }); dom.gv_showOverlay.animate(endButton, { duration: speed, easing: 'swing' }); this.overlayVisible = true; }, updateFilmstrip: function (to) { if (!this.opts.show_filmstrip) { this.frameIterator = to; return; } var self = this, dom = this.dom, targetThumbs = dom.gv_thumbnails.eq(this.iterator), filmstripIterator, distance; if (this.scrolling) { targetThumbs = targetThumbs. add(dom.gv_thumbnails.eq(this.iterator + this.numImages)). add(dom.gv_thumbnails.eq(this.iterator + (2 * this.numImages))); } dom.gv_thumbnails.removeClass('current').animate({ opacity: this.opts.frame_opacity }); targetThumbs.stop().addClass('current').animate({ opacity: 1 }, 500); if (this.scrolling) { if (this.filmstripOrientation === 'horizontal') { distance = (gv.outerWidth(dom.gv_frame) + this.opts.frame_gap) * (this.frameIterator - to); if (distance > 0) { distance = '+=' + Math.abs(distance); } else { distance = '-=' + Math.abs(distance); } dom.gv_filmstrip.animate({ left: distance }, { duration: this.opts.transition_speed, easing: this.opts.easing, complete: function () { if (to < self.numImages) { dom.gv_filmstrip.css('left', gv.getInt(dom.gv_filmstrip.css('left')) - (self.numImages * (gv.outerWidth(dom.gv_frame) + self.opts.frame_gap))); } else if (to >= (self.numImages * 2)) { dom.gv_filmstrip.css('left', gv.getInt(dom.gv_filmstrip.css('left')) + (self.numImages * (gv.outerWidth(dom.gv_frame) + self.opts.frame_gap))); } self.frameIterator = (to % self.numImages) + self.numImages; } }); } else { distance = (gv.outerHeight(dom.gv_frame) + this.opts.frame_gap) * (this.frameIterator - to); if (distance > 0) { distance = '+=' + Math.abs(distance); } else { distance = '-=' + Math.abs(distance); } dom.gv_filmstrip.animate({ top: distance }, { duration: this.opts.transition_speed, easing: this.opts.easing, complete: function () { // adjust filmstrip position to ensure that there is always at least one frame behind // and (2 * filmstripSize) ahead if (to === 0) { dom.gv_filmstrip.css('top', gv.getInt(dom.gv_filmstrip.css('top')) - (self.numImages * (gv.outerHeight(dom.gv_frame) + self.opts.frame_gap))); self.frameIterator = self.numImages; } else if (to > ((self.numImages * 3) - (self.filmstripSize * 2))) { dom.gv_filmstrip.css('top', gv.getInt(dom.gv_filmstrip.css('top')) + (self.numImages * (gv.outerHeight(dom.gv_frame) + self.opts.frame_gap))); self.frameIterator = to - self.numImages; } else { self.frameIterator = to; } } }); } } else { this.frameIterator = to; } }, startSlideshow: function (changeIcon) { var self = this, dom = this.dom; if (!self.opts.enable_slideshow) { return; } if (changeIcon) { dom.gv_navPlay.removeClass('gv_navPlay').addClass('gv_navPause'); } this.playing = true; dom.gv_galleryWrap.everyTime(this.opts.transition_interval, 'slideshow_' + this.id, function () { self.showNext(); }); }, stopSlideshow: function (changeIcon) { var self = this, dom = this.dom; if (changeIcon) { dom.gv_navPlay.removeClass('gv_navPause').addClass('gv_navPlay'); } this.playing = false; dom.gv_galleryWrap.stopTime('slideshow_' + this.id); }, enablePanning: function () { var self = this, dom = this.dom; if (!self.opts.enable_slideshow) { return; } dom.gv_panel.css('cursor', 'url(http://www.google.com/intl/en_ALL/mapfiles/openhand.cur), n-resize'); if (this.opts.pan_style === 'drag') { dom.gv_panelWrap.delegate('.gv_panel img', 'mousedown.galleryview', function (e) { self.isMouseDown = true; $(this).css('cursor', 'url(http://www.google.com/intl/en_ALL/mapfiles/closedhand.cur), n-resize'); }).delegate('.gv_panel img', 'mouseup.galleryview', function (e) { self.isMouseDown = false; $(this).css('cursor', 'url(http://www.google.com/intl/en_ALL/mapfiles/openhand.cur), n-resize'); }).delegate('.gv_panel img', 'mousemove.galleryview', function (e) { var distY, distX, image = $(this), new_top, new_left; if (self.isMouseDown) { distY = e.pageY - self.mouse.y; distX = e.pageX - self.mouse.x; new_top = gv.getInt(image.css('top')) + distY; new_left = gv.getInt(image.css('left')) + distX; image.css('cursor', 'url(http://www.google.com/intl/en_ALL/mapfiles/closedhand.cur), n-resize'); if (new_top > 0) new_top = 0; if (new_left > 0) new_left = 0; if (new_top < (-1 * (gv.outerHeight(image) - gv.innerHeight(dom.gv_panel)))) { new_top = -1 * (gv.outerHeight(image) - gv.innerHeight(dom.gv_panel)); } if (new_left < (-1 * (gv.outerWidth(image) - gv.innerWidth(dom.gv_panel)))) { new_left = -1 * (gv.outerWidth(image) - gv.innerWidth(dom.gv_panel)); } image.css('top', new_top); image.css('left', new_left); } else { image.css('cursor', 'url(http://www.google.com/intl/en_ALL/mapfiles/openhand.cur), n-resize'); } }); } else { } }, bindActions: function () { var self = this, dom = this.dom; dom.gv_showOverlay.bind('click.galleryview', function () { if (self.overlayVisible) { self.hideOverlay(250); } else { self.showOverlay(250); } }); dom.gv_navWrap.delegate('div', 'click.galleryview', function () { var el = $(this); if (el.hasClass('gv_navNext')) { self.showNext(); } else if (el.hasClass('gv_navPrev')) { self.showPrev(); } else if (el.hasClass('gv_navPlay')) { self.startSlideshow(true); } else if (el.hasClass('gv_navPause')) { self.stopSlideshow(true); } return false; }); dom.gv_panelNavNext.bind('click.galleryview', function () { self.showNext(); return false; }); dom.gv_panelNavPrev.bind('click.galleryview', function () { self.showPrev(); return false; }); dom.gv_filmstripWrap.delegate('.gv_frame', 'click.galleryview', function () { var el = $(this), i = self.getTrueImageIndex(el.data('frameIndex')); if (self.opts.filmstrip_use_alt_click && self.gvImages[i].href != "") { self.doClick(self.gvImages[i].href)(); } else { this.navAction = 'frame'; self.showItem(i); } return false; }); dom.gv_panelWrap.bind('mouseover.galleryview', function () { self.showPanelNav(); }).bind('mouseout.galleryview', function () { self.hidePanelNav(); }); }, unbindActions: function () { var self = this, dom = this.dom; dom.gv_showOverlay.unbind('click.galleryview'); dom.gv_panelNavNext.unbind('click.galleryview'); dom.gv_panelNavPrev.unbind('click.galleryview'); dom.gv_navWrap.undelegate('div', 'click.galleryview'); dom.gv_filmstripWrap.undelegate('.gv_frame', 'click.galleryview'); }, showPanelNav: function () { var self = this, dom = this.dom; dom.gv_panelNavNext.show(); dom.gv_panelNavPrev.show(); }, hidePanelNav: function () { var self = this, dom = this.dom; dom.gv_panelNavNext.hide(); dom.gv_panelNavPrev.hide(); }, // There's no need to repeat code, so let's just // abstract the click stuff a little doClick: function (link) { var self = this, dom = this.dom; if (link != '') { var action; if (this.opts.link_newwindow) { action = function () { window.open(link, "_blank"); }; } else { action = function () { window.location = link; }; } return action; } // Just in case we have an empty href return null; }, // Added to provide clickable link support for panels updateClickable: function (i) { var self = this, dom = this.dom; // If we don't undelegate here, we'll stack // up click actions and cycling through the // gallery can end up opening LOTS of links dom.gv_panelWrap.undelegate('.gv_panel', 'click.galleryview'); dom.gv_panelWrap.delegate('.gv_panel', 'click.galleryview', this.doClick(self.gvImages[i].href)); return false; }, init: function (options, el) { var self = this, dom = this.dom = {}; this.opts = $.extend({}, $.fn.galleryView.defaults, options); this.el = el; this.$el = $(el); this.id = el.id; this.iterator = this.frameIterator = this.opts.start_frame - 1; this.overlayVisible = false; this.playing = false; this.scrolling = false; this.isMouseDown = false; this.mouse = { x: 0, y: 0 }; this.filmstripOrientation = (this.opts.filmstrip_position === 'top' || this.opts.filmstrip_position === 'bottom') ? 'horizontal' : 'vertical'; $(document).bind('mousemove.galleryview', function (e) { self.mouse = { x: e.pageX, y: e.pageY }; }); // create all necessary DOM elements $.each(this.elems, function (i, elem) { var elem = elem.split('.'); // if there is no tag name, assume