/**
* jQuery (a)Slideshow plugin
*
* Copyright (c) 2009 Anton Shevchuk
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* @author Anton Shevchuk AntonShevchuk@gmail.com
* @version 0.6.9.1
*/
;
(function($) {
defaults = {
width: 320,
// width in px
height: 240,
// height in px
index: 0,
// start from frame number N
time: 8000,
// time out beetwen slides
title: true,
// show title
titleshow: false,
// always show title
callback: null,
// callback function - call when slide changed - receive index and label
panel: true,
// show controls panel
play: false,
// play slideshow
loop: true,
effect: 'fade',
// aviable fade, scrollUp/Down/Left/Right, zoom, zoomFade, growX, growY
effecttime: 1000,
// aviable fast,slow,normal and any valid fx speed value
filter: true,
// remove
, empty
,
and other stuff
nextclick: false,
// bind content click next slide
playclick: false,
// bind content click play/stop
playhover: false,
// bind content hover play/stop
playhoverr: false,
// bind content hover stop/play (reverse of playhover)
playframe: true,
// show frame "Play Now!"
loadframe: true,
// show frame with "loading"
fullscreen: false,
// in full window size
imgresize: false,
// resize image to slideshow window
imgzoom: true,
// zoom image to slideshow window (for smaller side)
imgcenter: true,
// set image to center
imgajax: true,
// load images from links
imglink: true,
// go to external link by click
linkajax: false,
// load html from links
help: '',
controls: { // show/hide controls elements
'hide': true,
// show controls bar on mouse hover
'first': true,
// goto first frame
'prev': true,
// goto previouse frame (if it first go to last)
'play': true,
// play slideshow
'next': true,
// goto next frame (if it last go to first)
'last': true,
// goto last frame
'help': true,
// show help message
'counter': true // show slide counter
}
};
/**
* Create a new instance of slideshow.
*
* @classDescription This class creates a new slideshow and manipulate it
*
* @return {Object} Returns a new slideshow object.
* @constructor
*/
$.fn.slideshow = function(settings) {
var _slideshow = this;
/*
* Construct
*/
this.each(function() {
var ext = $(this);
this.playId = null;
this.playFlag = false;
this.length = 0;
this.inited = new Array();
this.titles = new Array();
/**
* Build Html
* @method
*/
this.build = function() {
var _self = this;
ext.wrapInner('
');
ext = ext.find('.slideshow');
// filter content
if (this.options.filter) {
ext.find('.slideshow-content > br').remove();
ext.find('.slideshow-content > p:empty').remove();
ext.find('.slideshow-content > div:empty').remove();
}
// fullscreen
if (this.options.fullscreen) {
$('body').css({
overflow: 'hidden',
padding: 0
});
this.options.width = $(window).width();
this.options.height = ($(window).height() > $(document).height()) ? $(window).height() : $(document).height();
ext.addClass('slideshow-fullscreen');
}
this.length = ext.find('.slideshow-content > *').length;
// build title
if (this.options.title) {
ext.append('
');
if (!this.options.titleshow) {
ext.find('.slideshow-label-place').hover(function() {
$(this).find('.slideshow-label').fadeIn();
},
function() {
$(this).find('.slideshow-label').fadeOut();
});
ext.find('.slideshow-label').hide();
}
ext.find('.slideshow-label-place').css('width', this.options.width);
}
ext.find('.slideshow-panel-place').css('width', this.options.width);
// build panel
if (this.options.panel) {
ext.append('
');
panel = ext.find('.slideshow-panel');
if (this.options.controls.first) panel.append('
First');
if (this.options.controls.prev) panel.append('
Prev');
if (this.options.controls.play) panel.append('
Play');
if (this.options.controls.next) panel.append('
Next');
if (this.options.controls.last) panel.append('
Last');
if (this.options.controls.help) {
panel.append('
Help');
panel.prepend('
' + this.options.help + '
');
}
if (this.options.controls.counter) {
panel.append('
' + (this.options.index + 1) + ' / ' + this.length + '');
}
if (this.options.controls.hide) {
ext.find('.slideshow-panel-place').hover(function() {
$(this).find('.slideshow-panel').fadeIn();
},
function() {
$(this).find('.slideshow-panel').fadeOut();
});
panel.hide();
}
}
/**
* Set Size Options
*/
ext.css({
width: this.options.width,
height: this.options.height
});
var content = ext.find('.slideshow-content');
content.css({
width: this.options.width,
height: this.options.height
});
// add playframe
if (this.options.playframe) {
ext.append('
');
}
// add loadframe
if (this.options.loadframe) {
ext.append('
');
}
ext.find('.slideshow-shadow').css({
width: this.options.width,
height: this.options.height
});
// bind all events
this.events();
// wrap children
ext.find('.slideshow-content > *').each(function() {
$(this).wrap('
');
});
// check play option
if (this.options.play) {
this.play();
}
// init slide (replace by ajax etc)
this.init(this.options.index);
// show slide
ext.find('.slideshow-slide:eq(' + this.options.index + ')').show();
// update label
this._label();
this.style.display = '';
return true;
};
/**
* Init N-slide
* @method
* @param {Integer} index
*/
this.init = function(index) {
// initialize only ones
for (var i = 0, loopCnt = this.inited.length; i < loopCnt; i++) {
if (this.inited[i] === index) {
return true;
}
}
// index to inited stack
this.inited.push(index);
// current slide
slide = ext.find('.slideshow-slide:eq(' + index + ')');
var _self = this;
var title = '';
var link = false;
var name = slide.contents().attr('name');
if (name != '') {
var rename = new RegExp("^((https?|ftp):\/\/)", "i");
if (rename.test(name)) {
link = name;
}
}
/**
* Replace A to content from HREF
*/
if (slide.contents().is('a')) {
var href = slide.contents().attr('href');
var domain = document.domain;
domain = domain.replace(/\./i, "\."); // for strong check domain name
var reimage = new RegExp("\.(png|gif|jpg|jpeg|svg)$", "i");
var relocal = new RegExp("^((https?:\/\/" + domain + ")|(?!http:\/\/))", "i");
title = slide.contents().attr('title');
if (title.length == 0) title = slide.contents().html();
title = title.replace(/\"/i, '\''); // if you use single quotes for tag attribs
if (this.options.imgajax && reimage.test(href)) {
var img = new Image();
img.alt = title;
this._load($(img), href, index);
slide.contents().replaceWith(img);
} else if (this.options.linkajax && relocal.test(href)) {
$.get(href,
function(data) {
_self.goToSlide(index);
slide.contents().replaceWith('
' + data + '
');
});
} else {
this.goToSlide(index); // why?
}
} else {
if (slide.contents().is("img")) {
if ($.browser.msie) {
var img = new Image();
img.alt = slide.contents().attr("alt");
this._load($(img), slide.contents().attr("src"), index);
slide.contents().replaceWith(img);
} else {
this._load(slide.contents(), slide.contents().attr("src"), index);
}
} else {
if (this.playFlag) {
this.goToSlide(index);
}
}
if (slide.contents().attr('alt')) {
title = slide.contents().attr('alt');
} else if (slide.contents().attr('title')) {
title = slide.contents().attr('title');
title = unescape(title);
} else if (slide.find('label:first').length > 0) {
slide.find('label:first').hide();
title = slide.find('label:first').html();
}
}
if (link) title = '
' + title + '';
this.titles[index] = title;
/**
* Go to external link by click
*/
if (this.options.imglink && link) {
$(slide).css({
cursor: 'pointer'
});
$(slide).click(function() {
document.location = link;
return false;
});
}
/**
* Play/stop on content click (like image and other)
*/
if (this.options.playclick) $(slide).css({
cursor: 'pointer'
});
$(slide).click(function() {
if (_self.playId) {
_self.stop();
} else {
_self.play();
}
return false;
});
return false;
};
/**
* Load Image
*
* @param {Jquery} img
* @param {String} src
* @param {Integer} index
* @return {Jquery} img
*/
this._load = function(img, src, index) {
var _load = ext.find('.slideshow-load').show();
var _self = this;
img.load(function() {
_self._zoom(img);
_self._resize(img);
_self._center(img);
_self.goToSlide(index);
_load.hide();
}).error(function() {
// TODO: notify the user that the image could not be loaded
_load.hide();
}).attr('src', src);
// fix for stupid browsers
if (img.get(0).complete) {
_self._zoom(img);
_self._resize(img);
_self._center(img);
_self.goToSlide(index);
_load.hide();
}
return img;
};
/**
* Resize Image
* @param {Jquery} el
* @return {Jquery} el
*/
this._resize = function(el) {
if (!this.options.imgresize && !this.options.fullscreen) return false;
var size = {};
var width = el.get(0).width;
var height = el.get(0).height;
var scale = 1.0;
if (width > this.options.width) {
scale = this.options.width / width ;
}
if (height > this.options.height) {
var temp = this.options.height / height ;
if (temp < scale) {
scale = temp;
}
}
if (scale < 1.0) {
el.get(0).width = width * scale;
el.get(0).height = height * scale;
el.css({
width: el.get(0).width,
height:el.get(0).height
});
}
return el;
};
/**
* Zoom Image
* @param {Jquery} el
* @return {Jquery} el
*/
this._zoom = function(el) {
if (!this.options.imgzoom) return false;
var nWidth = el.get(0).width;
var nHeight = el.get(0).height;
var Kw = this.options.width / nWidth;
var Kh = this.options.height / nHeight;
var K = (Kh > Kw) ? Kh: Kw;
nWidth = nWidth * K;
nHeight = nHeight * K;
el.css({
width: nWidth,
height: nHeight
});
el.get(0).width = nWidth;
el.get(0).height = nHeight;
return el;
};
/**
* Center Image
* @param {Jquery} el
* @return {Jquery} el
*/
this._center = function(el) {
if (!this.options.imgcenter) return false;
var nWidth = el.get(0).width ? el.get(0).width: el.get(0).offsetWidth;
var nHeight = el.get(0).height ? el.get(0).height: el.get(0).offsetHeight;
var nLeft = 0;
var nTop = 0;
if (nWidth != this.options.width) {
nLeft = (Math.ceil((this.options.width - nWidth) / 2)) + 'px';
}
// Now make sure it isn't taller
if (nHeight != this.options.height) {
nTop = (Math.ceil((this.options.height - nHeight) / 2)) + 'px';
}
el.css({
left: nLeft,
top: nTop,
position: 'relative'
});
return el;
};
/**
* Bind Events
*/
this.events = function() {
var _self = this;
/**
* Go to next slide on content click (optional)
*/
if (_self.options.nextclick) ext.find('.slideshow-content').click(function() {
_self.stop();
_self.next();
return false;
});
/**
* Goto first slide button
*/
if (this.options.controls.first) ext.find('a.first').click(function() {
_self.stop();
_self.goToSlide(0);
return false;
});
/**
* Goto previouse slide button
*/
if (this.options.controls.prev) ext.find('a.prev').click(function() {
_self.stop();
_self.prev();
return false;
});
/**
* Play slideshow button
*/
if (this.options.controls.play) ext.find('a.play').click(function() {
if (_self.playId) {
_self.stop();
} else {
_self.play();
}
return false;
});
/**
* Goto next slide button
*/
if (this.options.controls.next) ext.find('a.next').click(function() {
_self.stop();
_self.next();
return false;
});
/**
* Goto last slide button
*/
if (this.options.controls.last) ext.find('a.last').click(function() {
_self.stop();
_self.goToSlide(_self.length - 1);
return false;
});
/**
* Show help message
*/
if (this.options.controls.help) ext.find('a.help').click(function() {
_self.stop();
ext.find('.slideshow-help').slideToggle();
return false;
});
/**
* Show playframe
*/
if (this.options.playframe) ext.find('.slideshow-frame').click(function() {
ext.find('.slideshow-frame').remove();
if (_self.options.playclick) setTimeout(function() {
_self.play()
},
_self.options.time);
return false;
});
/**
* Play/stop on slideshow hover
*/
if (this.options.playhover) ext.hover(function() {
if (!_self.playId) {
_self.play();
}
},
function() {
if (_self.playId) {
_self.stop();
}
});
/**
* Stop/Play on slideshow hover
*/
if (this.options.playhoverr) ext.hover(function() {
if (_self.playId) {
_self.stop();
}
},
function() {
if (!_self.playId) {
_self.play();
}
});
};
/**
* Update label of slide
* @method
*/
this._label = function() {
var title = this.getTitle();
if (this.options.callback) {
this.options.callback(this.options.index, title);
}
// always load label of slide
if (!this.options.title) return false;
ext.find('.slideshow-label').html(title);
};
/**
* Return title of current slide
* @method
*/
this.getTitle = function() {
return this.titles[this.options.index];
};
/**
* Goto previous slide
* @method
*/
this.prev = function() {
if (this.options.index == 0) {
i = (this.length - 1);
} else {
i = this.options.index - 1;
}
this.goToSlide(i);
};
/**
* Play Slideshow
* @method
*/
this.play = function() {
var _self = this;
this.playFlag = true;
this.playId = setTimeout(function() {
_self.next()
},
this.options.time);
ext.find('a.play').addClass('stop');
};
/**
* Play Slideshow
* @private
* @method
*/
this._play = function() {
var _self = this;
// if it last frame
if (this.options.index == (this.length - 1)) {
this.stop();
// should be restart slideshow
if (this.options.loop) {
this.play();
}
return false;
}
this.playId = setTimeout(function() {
_self.next();
},
this.options.time);
return true;
};
/**
* Stop Slideshow
* @method
*/
this.stop = function() {
this.playFlag = false;
ext.find('a.play').removeClass('stop');
clearTimeout(this.playId);
this.playId = null;
};
/**
* Goto next slide
* @method
*/
this.next = function() {
if (this.options.index == (this.length - 1)) {
i = 0;
} else {
i = this.options.index + 1;
}
this.goToSlide(i);
};
/**
* Goto N-slide
* @method
* @param {Integer} n
*/
this.goToSlide = function(n) {
if (this.options.index == n) return;
if (!this.init(n)) return;
var next = ext.find('.slideshow-content > *:eq(' + n + ')');
var prev = ext.find('.slideshow-content > *:eq(' + this.options.index + ')');
// restore next slide after all effects, set z-index = 0 for prev slide
prev.css({
zIndex: 0
});
next.css({
zIndex: 1,
top: 0,
left: 0,
opacity: 1,
width: this.options.width,
height: this.options.height
});
this.options.index = n;
if (this.options.effect == 'random') {
var r = Math.random();
r = Math.floor(r * 12);
} else {
r = -1;
}
// effect between slides
switch (true) {
case(r == 0 || this.options.effect == 'scrollUp') : prev.css({
width: '100%'
});
next.css({
top: 0,
height: 0
});
prevAni = {
height: 0,
top: this.options.height
};
break;
case (r == 1 || this.options.effect == 'scrollDown') : prev.css({
width: '100%'
});
next.css({
top: this.options.height,
height: 0
});
prevAni = {
height: 0,
top: 0
};
break;
case (r == 2 || this.options.effect == 'scrollRight') : prev.css({
right: 0,
left: '',
height: '100%'
});
next.css({
right: '',
left: 0,
height: '100%',
width: '0%'
});
prevAni = {
width: 0
};
break;
case (r == 3 || this.options.effect == 'scrollLeft') : prev.css({
right: '',
left: 0,
height: '100%'
});
next.css({
right: 0,
left: '',
height: '100%',
width: '0%'
});
prevAni = {
width: 0
};
break;
case (r == 4 || this.options.effect == 'growX') : next.css({
zIndex: 2,
opacity: 1,
left: this.options.width / 2,
width: '0%',
height: '100%'
});
prevAni = {
opacity: 0.8
};
break;
case (r == 5 || this.options.effect == 'growY') : next.css({
opacity: 1,
top: this.options.height / 2,
width: '100%',
height: '0%'
});
prevAni = {
opacity: 0.8
};
break;
case (r == 6 || this.options.effect == 'zoom') : next.css({
width: 0,
height: 0,
top: this.options.height / 2,
left: this.options.width / 2
});
prevAni = {
width: 0,
height: 0,
top: this.options.height / 2,
left: this.options.width / 2
};
break;
case (r == 7 || this.options.effect == 'zoomFade') : next.css({
zIndex: 1,
opacity: 0,
width: 0,
height: 0,
top: this.options.height / 2,
left: this.options.width / 2
});
prevAni = {
opacity: 0,
width: 0,
height: 0,
top: this.options.height / 2,
left: this.options.width / 2
};
break;
case (r == 8 || this.options.effect == 'zoomTL') : next.css({
zIndex: 1,
opacity: 0,
width: this.options.width / 2,
height: this.options.height / 2,
top: 0,
left: 0
});
prevAni = {
opacity: 0,
width: 0,
height: 0,
top: this.options.height,
left: this.options.width
};
break;
case (r == 9 || this.options.effect == 'zoomBR') : next.css({
zIndex: 1,
opacity: 0,
width: this.options.width / 2,
height: this.options.height / 2,
top: this.options.height / 2,
left: this.options.width / 2
});
prevAni = {
opacity: 0,
width: 0,
height: 0,
top: 0,
left: 0
};
break;
case (r == 10 || this.options.effect == 'fade') : default:
prev.css({
zIndex:
0,
opacity: 1
});
next.css({
zIndex: 1,
opacity: 0
});
prevAni = {
opacity: 0
};
break;
}
var _self = this;
prev.animate(prevAni, this.options.effecttime);
// play next slide animation, hide prev slide, update label, update counter
next.show().animate({
top: 0,
left: 0,
opacity: 1,
width: this.options.width,
height: this.options.height
},
this.options.effecttime,
function() {
prev.hide();
if (_self.playFlag) _self._play();
_self._label();
_self._counter();
});
};
/**
* Update counter data
* @method
*/
this._counter = function() {
if (this.options.controls.counter) ext.find('.slideshow-panel span.counter').html((this.options.index + 1) + ' / ' + this.length);
};
// Now initialize the slideshow
this.options = $.extend({},
defaults, settings);
if (typeof(settings) != 'undefined') {
if (typeof(settings.controls) != 'undefined') this.options.controls = $.extend({},
defaults.controls, settings.controls);
}
this.build();
/**
* Show slideshow
*/
ext.show();
return ext;
});
/**
* external functions - append to $
*/
_slideshow.playSlide = function() {
_slideshow.each(function() {
this.play();
})
};
_slideshow.stopSlide = function() {
_slideshow.each(function() {
this.stop();
})
};
_slideshow.nextSlide = function() {
_slideshow.each(function() {
this.next();
})
};
_slideshow.prevSlide = function() {
_slideshow.each(function() {
this.prev();
})
};
_slideshow.getTitle = function() {
_slideshow.each(function() {
this.getTitle();
})
};
_slideshow.goToSlide = function(n) {
_slideshow.each(function() {
this.goToSlide(n);
})
};
return this;
}
})(jQuery);