867 lines
23 KiB
JavaScript
867 lines
23 KiB
JavaScript
|
|
// -----------------------------------------------------------------------------------
|
||
|
|
//
|
||
|
|
// Simple Lightbox
|
||
|
|
// by Archetyped - http://archetyped.com/tools/simple-lightbox/
|
||
|
|
// Updated: 2011-01-27
|
||
|
|
//
|
||
|
|
// Originally based on Lightbox Slideshow v1.1
|
||
|
|
// by Justin Barkhuff - http://www.justinbarkhuff.com/lab/lightbox_slideshow/
|
||
|
|
// 2007/08/15
|
||
|
|
//
|
||
|
|
// Largely based on Lightbox v2.02
|
||
|
|
// by Lokesh Dhakar - http://huddletogether.com/projects/lightbox2/
|
||
|
|
// 2006/03/31
|
||
|
|
//
|
||
|
|
// Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
|
||
|
|
//
|
||
|
|
// The code inserts HTML at the bottom of the page for displaying content in a non-modal dialog
|
||
|
|
//
|
||
|
|
// -----------------------------------------------------------------------------------
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Lightbox object
|
||
|
|
*/
|
||
|
|
//var SLB = null;
|
||
|
|
(function($) {
|
||
|
|
SLB = {
|
||
|
|
activeImage : null,
|
||
|
|
badObjects : ['select','object','embed'],
|
||
|
|
container : null,
|
||
|
|
enableSlideshow : null,
|
||
|
|
groupName : null,
|
||
|
|
imageArray : [],
|
||
|
|
options : null,
|
||
|
|
overlayDuration : null,
|
||
|
|
overlayOpacity : null,
|
||
|
|
playSlides : null,
|
||
|
|
refTags : ['a'],
|
||
|
|
relAttribute : null,
|
||
|
|
resizeDuration : null,
|
||
|
|
slideShowTimer : null,
|
||
|
|
startImage : null,
|
||
|
|
prefix : 'slb',
|
||
|
|
checkedUrls : {},
|
||
|
|
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Initialize lightbox instance
|
||
|
|
* @param object options Instance options
|
||
|
|
*/
|
||
|
|
initialize: function(options) {
|
||
|
|
this.options = $.extend(true, {
|
||
|
|
animate : true, // resizing animations
|
||
|
|
validateLinks : false, //Validate links before adding them to lightbox
|
||
|
|
captionEnabled: true, //Display caption
|
||
|
|
captionSrc : true, //Use image source URI if title not set
|
||
|
|
autoPlay : true, // should slideshow start automatically
|
||
|
|
borderSize : 10, // if you adjust the padding in the CSS, you will need to update this variable
|
||
|
|
containerID : document, // lightbox container object
|
||
|
|
enableSlideshow : true, // enable slideshow feature
|
||
|
|
googleAnalytics : false, // track individual image views using Google Analytics
|
||
|
|
imageDataLocation : 'south', // location of image caption information
|
||
|
|
initImage : '', // ID of image link to automatically launch when upon script initialization
|
||
|
|
loop : true, // whether to continuously loop slideshow images
|
||
|
|
overlayDuration : .2, // time to fade in shadow overlay
|
||
|
|
overlayOpacity : .8, // transparency of shadow overlay
|
||
|
|
relAttribute : 'lightbox', // specifies the rel attribute value that triggers lightbox
|
||
|
|
resizeSpeed : 400, // controls the speed of the image resizing (milliseconds)
|
||
|
|
showGroupName : false, // show group name of images in image details
|
||
|
|
slideTime : 4, // time to display images during slideshow
|
||
|
|
altsrc : 'src',
|
||
|
|
strings : { // allows for localization
|
||
|
|
closeLink : 'close',
|
||
|
|
loadingMsg : 'loading',
|
||
|
|
nextLink : 'next »',
|
||
|
|
prevLink : '« prev',
|
||
|
|
startSlideshow : 'start slideshow',
|
||
|
|
stopSlideshow : 'stop slideshow',
|
||
|
|
numDisplayPrefix : 'Image',
|
||
|
|
numDisplaySeparator : 'of'
|
||
|
|
},
|
||
|
|
placeholders : {
|
||
|
|
slbContent: '<img id="slb_slbContent" />',
|
||
|
|
slbLoading: '<span id="slb_slbLoading">loading</span>',
|
||
|
|
slbClose: '<a class="slb_slbClose" href="#">close</a>',
|
||
|
|
navPrev: '<a class="slb_navPrev slb_nav" href="#">« prev</a>',
|
||
|
|
navNext: '<a class="slb_navNext slb_nav" href="#">» next</a>',
|
||
|
|
navSlideControl: '<a class="slb_navSlideControl" href="#">Stop</a>',
|
||
|
|
dataCaption: '<span class="slb_dataCaption"></span>',
|
||
|
|
dataNumber: '<span class="slb_dataNumber"></span>'
|
||
|
|
},
|
||
|
|
layout : null
|
||
|
|
}, options);
|
||
|
|
|
||
|
|
//Stop if no layout is defined
|
||
|
|
if (!this.options.layout || this.options.layout.toString().length == 0)
|
||
|
|
this.end();
|
||
|
|
|
||
|
|
//Validate options
|
||
|
|
if ( this.options.animate ) {
|
||
|
|
this.overlayDuration = Math.max(this.options.overlayDuration,0);
|
||
|
|
this.resizeDuration = this.options.resizeSpeed;
|
||
|
|
} else {
|
||
|
|
this.overlayDuration = 0;
|
||
|
|
this.resizeDuration = 0;
|
||
|
|
}
|
||
|
|
this.enableSlideshow = this.options.enableSlideshow;
|
||
|
|
this.overlayOpacity = Math.max(Math.min(this.options.overlayOpacity,1),0);
|
||
|
|
this.playSlides = this.options.autoPlay;
|
||
|
|
this.container = $(this.options.containerID);
|
||
|
|
this.relAttribute = this.options.relAttribute;
|
||
|
|
this.updateImageList();
|
||
|
|
var t = this;
|
||
|
|
var objBody = $(this.container).get(0) != document ? this.container : $('body');
|
||
|
|
|
||
|
|
var objOverlay = $('<div/>', {
|
||
|
|
'id': this.getID('overlay'),
|
||
|
|
'css': {'display': 'none'}
|
||
|
|
}).appendTo(objBody)
|
||
|
|
.click(function() {t.end()});
|
||
|
|
|
||
|
|
var objLightbox = $('<div/>', {
|
||
|
|
'id': this.getID('lightbox'),
|
||
|
|
'css': {'display': 'none'}
|
||
|
|
}).appendTo(objBody)
|
||
|
|
.click(function() {t.end()});
|
||
|
|
|
||
|
|
//Build layout from template
|
||
|
|
var layout = this.getLayout();
|
||
|
|
|
||
|
|
//Append to container
|
||
|
|
$(layout).appendTo(objLightbox);
|
||
|
|
|
||
|
|
//Set UI
|
||
|
|
this.setUI();
|
||
|
|
|
||
|
|
//Add events
|
||
|
|
this.setEvents();
|
||
|
|
|
||
|
|
if (this.options.initImage != '') {
|
||
|
|
this.start($(this.options.initImage));
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Build layout from template
|
||
|
|
* @uses options.layout
|
||
|
|
* @return string Layout markup (HTML)
|
||
|
|
*/
|
||
|
|
getLayout: function() {
|
||
|
|
var l = this.options.layout;
|
||
|
|
|
||
|
|
//Expand placeholders
|
||
|
|
var ph, phs, phr;
|
||
|
|
for (ph in this.options.placeholders) {
|
||
|
|
phs = '{' + ph + '}';
|
||
|
|
//Continue to next placeholder if current one is not in layout
|
||
|
|
if (l.indexOf(phs) == -1)
|
||
|
|
continue;
|
||
|
|
phr = new RegExp(phs, "g");
|
||
|
|
l = l.replace(phr, this.options.placeholders[ph]);
|
||
|
|
}
|
||
|
|
|
||
|
|
//Return final layout
|
||
|
|
return l;
|
||
|
|
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set localized values for UI elements
|
||
|
|
*/
|
||
|
|
setUI: function() {
|
||
|
|
var s = this.options.strings;
|
||
|
|
this.get('slbClose').html(s.closeLink);
|
||
|
|
this.get('navNext').html(s.nextLink);
|
||
|
|
this.get('navPrev').html(s.prevLink);
|
||
|
|
this.get('navSlideControl').html(((this.playSlides) ? s.stopSlideshow : s.startSlideshow));
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Add events to various UI elements
|
||
|
|
*/
|
||
|
|
setEvents: function() {
|
||
|
|
var t = this, delay = 500;
|
||
|
|
this.get('container,details').click(function(ev) {
|
||
|
|
ev.stopPropagation();
|
||
|
|
});
|
||
|
|
|
||
|
|
var clickP = function() {
|
||
|
|
t.get('navPrev').unbind('click').click(false);
|
||
|
|
setTimeout(function() {t.get('navPrev').click(clickP)}, delay);
|
||
|
|
t.showPrev();
|
||
|
|
return false;
|
||
|
|
};
|
||
|
|
this.get('navPrev').click(function(){
|
||
|
|
return clickP();
|
||
|
|
});
|
||
|
|
|
||
|
|
var clickN = function() {
|
||
|
|
t.get('navNext').unbind('click').click(false);
|
||
|
|
setTimeout(function() {t.get('navNext').click(clickN)}, delay);
|
||
|
|
t.showNext();
|
||
|
|
return false;
|
||
|
|
};
|
||
|
|
this.get('navNext').click(function() {
|
||
|
|
return clickN();
|
||
|
|
});
|
||
|
|
|
||
|
|
this.get('navSlideControl').click(function() {
|
||
|
|
t.toggleSlideShow();
|
||
|
|
return false;
|
||
|
|
});
|
||
|
|
this.get('slbClose').click(function() {
|
||
|
|
t.end();
|
||
|
|
return false;
|
||
|
|
});
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Finds all compatible image links on page
|
||
|
|
*/
|
||
|
|
updateImageList: function() {
|
||
|
|
var el, els, rel, t = this;
|
||
|
|
sel = [], selBase = '[href][rel*="' + this.relAttribute + '"]';
|
||
|
|
|
||
|
|
//Define event handler
|
||
|
|
var handler = function() {
|
||
|
|
//Check if element is valid for lightbox
|
||
|
|
t.start(this);
|
||
|
|
return false;
|
||
|
|
};
|
||
|
|
|
||
|
|
//Build selector
|
||
|
|
for (var i = 0; i < this.refTags.length; i++) {
|
||
|
|
sel.push(this.refTags[i] + selBase);
|
||
|
|
}
|
||
|
|
sel = sel.join(',');
|
||
|
|
|
||
|
|
//Add event handler to links
|
||
|
|
$(sel, $(this.container)).live('click', handler);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Build caption for displayed caption
|
||
|
|
* @param {Object} imageLink
|
||
|
|
*/
|
||
|
|
getCaption: function(imageLink) {
|
||
|
|
imageLink = $(imageLink);
|
||
|
|
var caption = '';
|
||
|
|
if (this.options.captionEnabled) {
|
||
|
|
caption = imageLink.attr('title') || '';
|
||
|
|
if (caption == '') {
|
||
|
|
var inner = $(imageLink).find('img').first();
|
||
|
|
if ($(inner).length)
|
||
|
|
caption = $(inner).attr('title') || $(inner).attr('alt');
|
||
|
|
if (!caption) {
|
||
|
|
if (imageLink.text().length)
|
||
|
|
caption = imageLink.text();
|
||
|
|
else
|
||
|
|
if (this.options.captionSrc)
|
||
|
|
caption = imageLink.attr('href');
|
||
|
|
}
|
||
|
|
if (!caption)
|
||
|
|
caption = '';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return caption;
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Display overlay and lightbox. If image is part of a set, add siblings to imageArray.
|
||
|
|
* @param node imageLink Link element containing image URL
|
||
|
|
*/
|
||
|
|
start: function(imageLink) {
|
||
|
|
imageLink = $(imageLink);
|
||
|
|
this.hideBadObjects();
|
||
|
|
|
||
|
|
this.imageArray = [];
|
||
|
|
this.groupName = this.getGroup(imageLink);
|
||
|
|
|
||
|
|
var rel = $(imageLink).attr('rel') || '';
|
||
|
|
var imageTitle = '';
|
||
|
|
var t = this;
|
||
|
|
var groupTemp = {};
|
||
|
|
this.fileExists(this.getSourceFile(imageLink),
|
||
|
|
function() { //File exists
|
||
|
|
// Stretch overlay to fill page and fade in
|
||
|
|
t.get('overlay')
|
||
|
|
.height($(document).height())
|
||
|
|
.fadeTo(t.overlayDuration, t.overlayOpacity);
|
||
|
|
|
||
|
|
// Add image to array closure
|
||
|
|
var addLink = function(el, idx) {
|
||
|
|
groupTemp[idx] = el;
|
||
|
|
return groupTemp.length;
|
||
|
|
};
|
||
|
|
|
||
|
|
//Build final image array & launch lightbox
|
||
|
|
var proceed = function() {
|
||
|
|
t.startImage = 0;
|
||
|
|
//Sort links by document order
|
||
|
|
var order = [], el;
|
||
|
|
for (var x in groupTemp) {
|
||
|
|
order.push(x);
|
||
|
|
}
|
||
|
|
order.sort(function(a, b) { return (a - b); });
|
||
|
|
for (x = 0; x < order.length; x++) {
|
||
|
|
el = groupTemp[order[x]];
|
||
|
|
//Check if link being evaluated is the same as the clicked link
|
||
|
|
if ($(el).get(0) == $(imageLink).get(0)) {
|
||
|
|
t.startImage = x;
|
||
|
|
}
|
||
|
|
t.imageArray.push({'link':t.getSourceFile($(el)), 'title':t.getCaption(el)});
|
||
|
|
}
|
||
|
|
// Calculate top offset for the lightbox and display
|
||
|
|
var lightboxTop = $(document).scrollTop() + ($(window).height() / 15);
|
||
|
|
|
||
|
|
t.get('lightbox').css('top', lightboxTop + 'px').show();
|
||
|
|
t.changeImage(t.startImage);
|
||
|
|
}
|
||
|
|
|
||
|
|
// If image is NOT part of a group..
|
||
|
|
if (null == t.groupName) {
|
||
|
|
// Add single image to imageArray
|
||
|
|
addLink(imageLink, 0);
|
||
|
|
t.startImage = 0;
|
||
|
|
proceed();
|
||
|
|
} else {
|
||
|
|
// If image is part of a group
|
||
|
|
var els = $(t.container).find($(imageLink).get(0).tagName.toLowerCase());
|
||
|
|
// Loop through links on page & find other images in group
|
||
|
|
var grpLinks = [];
|
||
|
|
var i, el;
|
||
|
|
for (i = 0; i < els.length; i++) {
|
||
|
|
el = $(els[i]);
|
||
|
|
if (t.getSourceFile(el) && (t.getGroup(el) == t.groupName)) {
|
||
|
|
//Add links in same group to temp array
|
||
|
|
grpLinks.push(el);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//Loop through group links, validate, and add to imageArray
|
||
|
|
var processed = 0;
|
||
|
|
for (i = 0; i < grpLinks.length; i++) {
|
||
|
|
el = grpLinks[i];
|
||
|
|
t.fileExists(t.getSourceFile($(el)),
|
||
|
|
function(args) { //File exists
|
||
|
|
var el = args.els[args.idx];
|
||
|
|
var il = addLink(el, args.idx);
|
||
|
|
processed++;
|
||
|
|
if (processed == args.els.length)
|
||
|
|
proceed();
|
||
|
|
},
|
||
|
|
function(args) { //File does not exist
|
||
|
|
processed++;
|
||
|
|
if (args.idx == args.els.length)
|
||
|
|
proceed();
|
||
|
|
},
|
||
|
|
{'idx': i, 'els': grpLinks});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
function() { //File does not exist
|
||
|
|
t.end();
|
||
|
|
});
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Retrieve source URI in link
|
||
|
|
* @param {Object} el
|
||
|
|
* @return string Source file URI
|
||
|
|
*/
|
||
|
|
getSourceFile: function(el) {
|
||
|
|
var src = $(el).attr('href');
|
||
|
|
var rel = $(el).attr('rel') || '';
|
||
|
|
var reSrc = new RegExp('\\b' + this.options.altsrc + '\\[(.+?)\\](?:\\b|$)');
|
||
|
|
if ( reSrc.test(rel) ) {
|
||
|
|
src = reSrc.exec(rel)[1];
|
||
|
|
}
|
||
|
|
return src;
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Extract group name from
|
||
|
|
* @param obj el Element to extract group name from
|
||
|
|
* @return string Group name
|
||
|
|
*/
|
||
|
|
getGroup: function(el) {
|
||
|
|
//Get full attribute value
|
||
|
|
var g = null;
|
||
|
|
var rel = $(el).attr('rel') || '';
|
||
|
|
if (rel != '') {
|
||
|
|
var gTmp = '';
|
||
|
|
var gSt = '[';
|
||
|
|
var gEnd = ']';
|
||
|
|
var search = this.relAttribute;
|
||
|
|
var searching = true;
|
||
|
|
var idx;
|
||
|
|
var prefix = ' ';
|
||
|
|
while (searching) {
|
||
|
|
idx = rel.indexOf(search);
|
||
|
|
//Stop processing if value is not found
|
||
|
|
if (idx == -1)
|
||
|
|
return g;
|
||
|
|
//Prefix with space to find whole word
|
||
|
|
if (prefix != search.charAt(0) && idx > 0) {
|
||
|
|
search = prefix + search;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
searching = false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
gTmp = $.trim(rel.substring(idx).replace(search, ''));
|
||
|
|
//Check if group defined
|
||
|
|
if (gTmp.length && gSt == gTmp.charAt(0) && gTmp.indexOf(gEnd) != -1) {
|
||
|
|
//Extract group name
|
||
|
|
g = gTmp.substring(1, gTmp.indexOf(gEnd));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return g;
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Preload requested image prior to displaying it in lightbox
|
||
|
|
* @param int imageNum Index of image in imageArray property
|
||
|
|
* @uses imageArray to retrieve index at specified image
|
||
|
|
* @uses resizeImageContainer() to resize lightbox after image has loaded
|
||
|
|
*/
|
||
|
|
changeImage: function(imageNum) {
|
||
|
|
this.activeImage = imageNum;
|
||
|
|
|
||
|
|
this.disableKeyboardNav();
|
||
|
|
this.pauseSlideShow();
|
||
|
|
|
||
|
|
// hide elements during transition
|
||
|
|
this.get('slbLoading').show();
|
||
|
|
this.get('slbContent').hide();
|
||
|
|
this.get('details').hide();
|
||
|
|
var imgPreloader = new Image();
|
||
|
|
var t = this;
|
||
|
|
// once image is preloaded, resize image container
|
||
|
|
$(imgPreloader).bind('load', function() {
|
||
|
|
t.get('slbContent').attr('src', imgPreloader.src);
|
||
|
|
t.resizeImageContainer(imgPreloader.width, imgPreloader.height);
|
||
|
|
//Restart slideshow if active
|
||
|
|
if ( t.isSlideShowActive() )
|
||
|
|
t.startSlideShow();
|
||
|
|
});
|
||
|
|
|
||
|
|
//Load image
|
||
|
|
imgPreloader.src = this.imageArray[this.activeImage].link;
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Resizes lightbox to fit image
|
||
|
|
* @param int imgWidth Image width in pixels
|
||
|
|
* @param int imgHeight Image height in pixels
|
||
|
|
*/
|
||
|
|
resizeImageContainer: function(imgWidth, imgHeight) {
|
||
|
|
// get current height and width
|
||
|
|
var el = this.get('container');
|
||
|
|
var borderSize = this.options.borderSize * 2;
|
||
|
|
|
||
|
|
this.get('container').animate({width: imgWidth + borderSize, height: imgHeight + borderSize}, this.resizeDuration)
|
||
|
|
|
||
|
|
this.showImage();
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Display image and begin preloading neighbors.
|
||
|
|
*/
|
||
|
|
showImage: function() {
|
||
|
|
this.get('slbLoading').hide();
|
||
|
|
var t = this;
|
||
|
|
this.get('slbContent').fadeIn(500, function() { t.updateDetails(); });
|
||
|
|
this.preloadNeighborImages();
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Display caption, image number, and bottom nav
|
||
|
|
*/
|
||
|
|
updateDetails: function() {
|
||
|
|
if (this.options.captionEnabled) {
|
||
|
|
this.get('dataCaption').text(this.imageArray[this.activeImage].title);
|
||
|
|
this.get('dataCaption').show();
|
||
|
|
} else {
|
||
|
|
this.get('dataCaption').hide();
|
||
|
|
}
|
||
|
|
|
||
|
|
// if image is part of set display 'Image x of y'
|
||
|
|
if (this.hasImages()) {
|
||
|
|
var num_display = this.options.strings.numDisplayPrefix + ' ' + (this.activeImage + 1) + ' ' + this.options.strings.numDisplaySeparator + ' ' + this.imageArray.length;
|
||
|
|
if (this.options.showGroupName && this.groupName != '') {
|
||
|
|
num_display += ' ' + this.options.strings.numDisplaySeparator + ' ' + this.groupName;
|
||
|
|
}
|
||
|
|
this.get('dataNumber')
|
||
|
|
.text(num_display)
|
||
|
|
.show();
|
||
|
|
}
|
||
|
|
|
||
|
|
this.get('details').width(this.get('slbContent').width() + (this.options.borderSize * 2));
|
||
|
|
this.updateNav();
|
||
|
|
var t = this;
|
||
|
|
this.get('details').animate({height: 'show', opacity: 'show'}, 650);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Display appropriate previous and next hover navigation.
|
||
|
|
*/
|
||
|
|
updateNav: function() {
|
||
|
|
if (this.hasImages()) {
|
||
|
|
this.get('navPrev').show();
|
||
|
|
this.get('navNext').show();
|
||
|
|
if (this.enableSlideshow) {
|
||
|
|
this.get('navSlideControl').show();
|
||
|
|
if (this.playSlides) {
|
||
|
|
this.startSlideShow();
|
||
|
|
} else {
|
||
|
|
this.stopSlideShow();
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
this.get('navSlideControl').hide();
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
// Hide navigation controls when only one image exists
|
||
|
|
this.get('dataNumber').hide();
|
||
|
|
this.get('navPrev').hide();
|
||
|
|
this.get('navNext').hide();
|
||
|
|
this.get('navSlideControl').hide();
|
||
|
|
}
|
||
|
|
this.enableKeyboardNav();
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Checks if slideshow is currently activated
|
||
|
|
* @return bool TRUE if slideshow is active, FALSE otherwise
|
||
|
|
* @uses playSlides to check slideshow activation status
|
||
|
|
*/
|
||
|
|
isSlideShowActive: function() {
|
||
|
|
return this.playSlides;
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Start the slideshow
|
||
|
|
*/
|
||
|
|
startSlideShow: function() {
|
||
|
|
this.playSlides = true;
|
||
|
|
var t = this;
|
||
|
|
clearInterval(this.slideShowTimer);
|
||
|
|
this.slideShowTimer = setInterval(function() { t.showNext(); t.pauseSlideShow(); }, this.options.slideTime * 1000);
|
||
|
|
this.get('navSlideControl').text(this.options.strings.stopSlideshow);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Stop the slideshow
|
||
|
|
*/
|
||
|
|
stopSlideShow: function() {
|
||
|
|
this.playSlides = false;
|
||
|
|
if (this.slideShowTimer) {
|
||
|
|
clearInterval(this.slideShowTimer);
|
||
|
|
}
|
||
|
|
this.get('navSlideControl').text(this.options.strings.startSlideshow);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Toggles the slideshow status
|
||
|
|
*/
|
||
|
|
toggleSlideShow: function() {
|
||
|
|
if (this.playSlides) {
|
||
|
|
this.stopSlideShow();
|
||
|
|
}else{
|
||
|
|
this.startSlideShow();
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Pauses the slideshow
|
||
|
|
* Stops the slideshow but does not change the slideshow's activation status
|
||
|
|
*/
|
||
|
|
pauseSlideShow: function() {
|
||
|
|
if (this.slideShowTimer) {
|
||
|
|
clearInterval(this.slideShowTimer);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if there is at least one image to display in the lightbox
|
||
|
|
* @return bool TRUE if at least one image is found
|
||
|
|
* @uses imageArray to check for images
|
||
|
|
*/
|
||
|
|
hasImage: function() {
|
||
|
|
return ( this.imageArray.length > 0 );
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if there are multiple images to display in the lightbox
|
||
|
|
* @return bool TRUE if there are multiple images
|
||
|
|
* @uses imageArray to determine the number of images
|
||
|
|
*/
|
||
|
|
hasImages: function() {
|
||
|
|
return ( this.imageArray.length > 1 );
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if the current image is the first image in the list
|
||
|
|
* @return bool TRUE if image is first
|
||
|
|
* @uses activeImage to check index of current image
|
||
|
|
*/
|
||
|
|
isFirstImage: function() {
|
||
|
|
return ( this.activeImage == 0 );
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if the current image is the last image in the list
|
||
|
|
* @return bool TRUE if image is last
|
||
|
|
* @uses activeImage to check index of current image
|
||
|
|
* @uses imageArray to compare current image to total number of images
|
||
|
|
*/
|
||
|
|
isLastImage: function() {
|
||
|
|
return ( this.activeImage == this.imageArray.length - 1 );
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Show the next image in the list
|
||
|
|
*/
|
||
|
|
showNext : function() {
|
||
|
|
if (this.hasImages()) {
|
||
|
|
if ( !this.options.loop && this.isLastImage() ) {
|
||
|
|
return this.end();
|
||
|
|
}
|
||
|
|
if ( this.isLastImage() ) {
|
||
|
|
this.showFirst();
|
||
|
|
} else {
|
||
|
|
this.changeImage(this.activeImage + 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Show the previous image in the list
|
||
|
|
*/
|
||
|
|
showPrev : function() {
|
||
|
|
if (this.hasImages()) {
|
||
|
|
if ( !this.options.loop && this.isFirstImage() )
|
||
|
|
return this.end();
|
||
|
|
if (this.activeImage == 0) {
|
||
|
|
this.showLast();
|
||
|
|
} else {
|
||
|
|
this.changeImage(this.activeImage - 1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Show the first image in the list
|
||
|
|
*/
|
||
|
|
showFirst : function() {
|
||
|
|
if (this.hasImages()) {
|
||
|
|
this.changeImage(0);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Show the last image in the list
|
||
|
|
*/
|
||
|
|
showLast : function() {
|
||
|
|
if (this.hasImages()) {
|
||
|
|
this.changeImage(this.imageArray.length - 1);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Enable image navigation via the keyboard
|
||
|
|
*/
|
||
|
|
enableKeyboardNav: function() {
|
||
|
|
var t = this;
|
||
|
|
$(document).keydown(function(e) {
|
||
|
|
t.keyboardAction(e);
|
||
|
|
});
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Disable image navigation via the keyboard
|
||
|
|
*/
|
||
|
|
disableKeyboardNav: function() {
|
||
|
|
$(document).unbind('keydown');
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Handler for keyboard events
|
||
|
|
* @param event e Keyboard event data
|
||
|
|
*/
|
||
|
|
keyboardAction: function(e) {
|
||
|
|
if (e == null) { // ie
|
||
|
|
keycode = event.keyCode;
|
||
|
|
} else { // mozilla
|
||
|
|
keycode = e.which;
|
||
|
|
}
|
||
|
|
|
||
|
|
key = String.fromCharCode(keycode).toLowerCase();
|
||
|
|
|
||
|
|
if (keycode == 27 || key == 'x' || key == 'o' || key == 'c') { // close lightbox
|
||
|
|
this.end();
|
||
|
|
} else if (key == 'p' || key == '%') { // display previous image
|
||
|
|
this.showPrev();
|
||
|
|
} else if (key == 'n' || key =='\'') { // display next image
|
||
|
|
this.showNext();
|
||
|
|
} else if (key == 'f') { // display first image
|
||
|
|
this.showFirst();
|
||
|
|
} else if (key == 'l') { // display last image
|
||
|
|
this.showLast();
|
||
|
|
} else if (key == 's') { // toggle slideshow
|
||
|
|
if (this.hasImage() && this.options.enableSlideshow) {
|
||
|
|
this.toggleSlideShow();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Preloads images before/after current image
|
||
|
|
*/
|
||
|
|
preloadNeighborImages: function() {
|
||
|
|
var nextImageID = this.imageArray.length - 1 == this.activeImage ? 0 : this.activeImage + 1;
|
||
|
|
nextImage = new Image();
|
||
|
|
nextImage.src = this.imageArray[nextImageID].link;
|
||
|
|
|
||
|
|
var prevImageID = this.activeImage == 0 ? this.imageArray.length - 1 : this.activeImage - 1;
|
||
|
|
prevImage = new Image();
|
||
|
|
prevImage.src = this.imageArray[prevImageID].link;
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Close the lightbox
|
||
|
|
*/
|
||
|
|
end: function() {
|
||
|
|
this.disableKeyboardNav();
|
||
|
|
this.pauseSlideShow();
|
||
|
|
this.get('lightbox').hide();
|
||
|
|
this.get('overlay').fadeOut(this.overlayDuration);
|
||
|
|
this.showBadObjects();
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Displays objects that may conflict with the lightbox
|
||
|
|
* @param bool show (optional) Whether or not to show objects (Default: TRUE)
|
||
|
|
*/
|
||
|
|
showBadObjects: function (show) {
|
||
|
|
show = ( typeof(show) == 'undefined' ) ? true : !!show;
|
||
|
|
var vis = (show) ? 'visible' : 'hidden';
|
||
|
|
$(this.badObjects.join(',')).css('visibility', vis);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Hides objects that may conflict with the lightbox
|
||
|
|
* @uses showBadObjects() to hide objects
|
||
|
|
*/
|
||
|
|
hideBadObjects: function () {
|
||
|
|
this.showBadObjects(false);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Add prefix to text
|
||
|
|
* @param string txt Text to add prefix to
|
||
|
|
* @return string Prefixed text
|
||
|
|
*/
|
||
|
|
addPrefix: function(txt) {
|
||
|
|
return this.prefix + '_' + txt;
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Generate formatted ID for lightbox-specific elements
|
||
|
|
* @param string id Base ID of element
|
||
|
|
* @return string Formatted ID
|
||
|
|
*/
|
||
|
|
getID: function(id) {
|
||
|
|
return this.addPrefix(id);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Generate formatted selector for lightbox-specific elements
|
||
|
|
* Compares specified ID to placeholders first, then named elements
|
||
|
|
* Multiple selectors can be included and separated by commas (',')
|
||
|
|
* @param string id Base ID of element
|
||
|
|
* @uses options.placeholders to compare id to placeholder names
|
||
|
|
* @return string Formatted selector
|
||
|
|
*/
|
||
|
|
getSel: function(id) {
|
||
|
|
//Process multiple selectors
|
||
|
|
var delim = ',', prefix = '#', sel;
|
||
|
|
if (id.toString().indexOf(delim) != -1) {
|
||
|
|
//Split
|
||
|
|
var sels = id.toString().split(delim);
|
||
|
|
//Build selector
|
||
|
|
for (var x = 0; x < sels.length; x++) {
|
||
|
|
sels[x] = this.getSel($.trim(sels[x]));
|
||
|
|
}
|
||
|
|
//Join
|
||
|
|
sel = sels.join(delim);
|
||
|
|
} else {
|
||
|
|
//Single selector
|
||
|
|
if (id in this.options.placeholders) {
|
||
|
|
var ph = $(this.options.placeholders[id]);
|
||
|
|
if (!ph.attr('id')) {
|
||
|
|
//Class selector
|
||
|
|
prefix = '.';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
sel = prefix + this.getID(id);
|
||
|
|
}
|
||
|
|
|
||
|
|
return sel;
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Retrieve lightbox-specific element
|
||
|
|
* @param string id Base ID of element
|
||
|
|
* @uses getSel() to generate formatted selector for element
|
||
|
|
* @return object jQuery object of selected element(s)
|
||
|
|
*/
|
||
|
|
get: function(id) {
|
||
|
|
return $(this.getSel(id));
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Checks if file exists using AJAX request
|
||
|
|
* @param string url File URL
|
||
|
|
* @param callback success Callback to run if file exists
|
||
|
|
* @param callback failure Callback to run if file does not exist
|
||
|
|
* @param obj args Arguments for callback
|
||
|
|
*/
|
||
|
|
fileExists: function(url, success, failure, args) {
|
||
|
|
if (!this.options.validateLinks)
|
||
|
|
return success(args);
|
||
|
|
var statusFail = 400;
|
||
|
|
var stateCheck = 4;
|
||
|
|
var t = this;
|
||
|
|
var proceed = function(res) {
|
||
|
|
if (res.status < statusFail) {
|
||
|
|
if ($.isFunction(success))
|
||
|
|
success(args);
|
||
|
|
} else {
|
||
|
|
if ($.isFunction(failure))
|
||
|
|
failure(args);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
//Check if URL already processed
|
||
|
|
if (url in this.checkedUrls) {
|
||
|
|
proceed(this.checkedUrls[url]);
|
||
|
|
} else {
|
||
|
|
var req = new XMLHttpRequest();
|
||
|
|
req.open('HEAD', url, true);
|
||
|
|
req.onreadystatechange = function() {
|
||
|
|
if (stateCheck == this.readyState) {
|
||
|
|
t.addUrl(url, this);
|
||
|
|
proceed(this);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
req.send();
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
addUrl: function(url, res) {
|
||
|
|
if (!(url in this.checkedUrls))
|
||
|
|
this.checkedUrls[url] = res;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
})(jQuery);
|