/** * elixon theatre * project homepage: http://www.webdevelopers.eu/jquery/theatre * * license * http://www.webdevelopers.eu/jquery/theatre/license * commons attribution-noncommercial 3.0 * * get a commercial license at * http://www.webdevelopers.eu/jquery/theatre/buy * * demo * http://www.webdevelopers.eu/jquery/theatre/demo * * documentation * http://www.webdevelopers.eu/jquery/theatre/documentation * * @project elixon cms, http://www.webdevelopers.eu/ * @package jquery * @subpackage theatre * @author daniel sevcik * @version 1.0.10 * @copyright 2010 daniel sevcik * @since 2010-11-11t22:10:07+0100 * @revision $revision: 4711 $ * @changed $date: 2011-05-02 16:14:53 +0200 (mon, 02 may 2011) $ * @access public */ (function($) { var effects={}; var methods={}; var urlbase; $.fn.theatre=function() { var currarguments=arguments; (this.length ? this : $(document)).each(function() { methods.initall.apply($(this), currarguments); }); return this; } // name:string - 'file:effect' or 'effect', one file may register effect or multiple effect prefixed by file string methods.loadeffect=function(name) { if (!urlbase) { // find the locations $('script[src*="jquery.theatre-"], link[href*="theatre.css"]').first().each(function() { urlbase=(this.href || this.src).replace(/\/[^\/]*(#.*)?$/, ''); }); } var url=urlbase+'/effect.'+name.split(':')[0]+'.js'; $('head').append(''); return effects[name]; } methods.initall=function(method) { // init theatre if (typeof method == 'object' || !method || method == 'init') { return methods.init.apply(this, arguments); } // register effect if (method == 'effect') { // register new effect if (typeof arguments[2] == 'function') { return effects[arguments[1]]=arguments[2]; } else { $.error("elixon theatre cannot register effect object unless it is a function."); } } var theatre=this.data('theatre'); if (!theatre) return false; // not initialized yet switch(method) { case 'jump': var jumpto; switch(jumpto) { case 'first': jumpto=0; break; case 'last' : jumpto=theatre.actors.length - 1; break; default : jumpto=(parseint(arguments[1]) - 1) % theatre.actors.length; jumpto=(math.abs(math.floor(jumpto / theatre.actors.length) * theatre.actors.length) + jumpto) % theatre.actors.length; //normalize } if (typeof arguments[2] != 'undefined') { if (typeof theatre.settings.speedorig == 'undefined') theatre.settings.speedorig=theatre.settings.speed; theatre.settings.speed=arguments[2]; } while(theatre.index != jumpto) { if (theatre.effect.jump) { theatre.effect.jump(jumpto); theatre.index=jumpto; } else { this.theatre(theatre.index < jumpto ? 'next' : 'prev'); } } methods.onmove.apply(this); if (typeof theatre.settings.speedorig != 'undefined') theatre.settings.speed=theatre.settings.speedorig; break; case 'next': case 'prev': // call next/prev custom effects if (!arguments[1]) this.theatre('stop'); // stop animation if no second param == true theatre.index=(theatre.index + (method == 'next' ? 1 : -1)) % theatre.actors.length; theatre.index=(math.abs(math.floor(theatre.index / theatre.actors.length) * theatre.actors.length) + theatre.index) % theatre.actors.length; //normalize methods.onmove.apply(this); methods.updatepaging.apply(this); theatre.effect[method].apply(theatre.effect, array.prototype.slice.call(arguments, 1)); break; case 'play': case 'stop': methods[method].apply(this, arguments); break; default: // unsupported $.error('elixon theatre method "'+method+'" does not exist on jquery.theatre!'); } } methods.init=function(options) { methods.destroy.apply(this); // reset old if any // default settings var settings={ selector: '> *:not(".theatre-control")', effect: 'horizontal', // 'horizontal'|'vertical'|'fade'|'show'|'slide'|'3d'|custom effect name|object with constructor implementing the init,next,prev methods speed: 1000, // transition speed still: 3000, // time between transitions autoplay: true, controls: 'horizontal', // display control buttons 'horizontal' or 'vertical' or 'none' itemwidth: false, // width of the item or 'max' or false. itemheight: false, // height of the item or 'max' or false. width: false, // set the height of the container. by default honors the already set size using css height: false, // set the height of the container. by default honors the already set size using css onmove: false // function(index) {}, execution context is the stage } if (options) { $.extend(settings, options); } // init effect object var actors=$(settings.selector, this); var theatre={paging: settings.paging && $(settings.paging), actors: actors, effect: false, settings: settings, interval: false, index: 0}; var effect=(typeof settings.effect == 'function' ? settings.effect : effects[settings.effect] || methods.loadeffect(settings.effect)); if (!effect) $.error('elixon theatre does not support effect "'+settings.effect+'"!'); theatre.effect=new effects[settings.effect](this, actors, settings, theatre); // stage this.addclass('theatre').data('theatre', theatre); this.addclass('theatre-'+settings.effect.replace(/[^a-z0-9]+/ig, '-')); if (settings.width) this.css('width', settings.width); if (settings.height) this.css('height', settings.height); // actors actors.each(function(){var $this=$(this); if (!$this.data('theatre')) $this.data('theatre', {width: $this.width(), height: $this.height()});}); if (settings.itemwidth || settings.itemheight) { var thisobj=this; actors.each(function() { var $this=$(this); if (settings.itemwidth) { $this.css('width', settings.itemwidth == 'max' ? (thisobj.width() - $this.outerwidth() + $this.width())+'px' : settings.itemwidth); } if (settings.itemheight) { $this.css('height', settings.itemheight == 'max' ? (thisobj.height() - $this.outerheight() + $this.height())+'px' : settings.itemheight); } }); } actors.addclass('theatre-actor').stop(true, true); theatre.effect.init(); if (settings.autoplay) { methods.play.apply(this); } // controls methods.appendcontrols.apply(this); methods.onmove.apply(this); methods.generatepaging.apply(this); } methods.onmove=function() { var theatre=this.data('theatre'); if (typeof theatre.settings.onmove != 'function') return; theatre.settings.onmove.apply(this, [theatre.index, theatre.actors[theatre.index], theatre]); this.trigger('theatremove', [theatre.index, theatre.actors[theatre.index], theatre]); } methods.generatepaging=function() { var stage=this; var theatre=this.data('theatre'); if (!theatre.paging) return; theatre.paging.each(function() { var $this=$(this); var jumpers=[]; $('> *', $this).each(function() {jumpers.push($('
').append(this).html());}); var template=jumpers[jumpers.length - 1]; // re-generate for(var i=0; i < theatre.actors.length; i++) { var jumphtml=jumpers.length < i + 1 ? template : jumpers[i]; (function (pos) { $this.append(jumphtml.replace('{#}', pos)+"\n"); $this.children().last().click(function() {stage.theatre('jump', pos);}); })(i+1); } }); methods.updatepaging.apply(this); } methods.updatepaging=function() { var theatre=this.data('theatre'); if (!theatre.paging) return; theatre.paging.each(function() { var $this=$(this); $('> *', $this).removeclass('active').eq(theatre.index).addclass('active'); }); } methods.appendcontrols=function() { settings=this.data('theatre').settings; // controls if (settings.controls == 'horizontal' || settings.controls == 'vertical') { var thisobj=this; this.append(''); this.append(''); this.append(''); this.append(''); $('.theatre-next', this).click(function() {thisobj.theatre('next');}); $('.theatre-prev', this).click(function() {thisobj.theatre('prev');}); $('.theatre-play', this).click(function() {thisobj.theatre('play');}); $('.theatre-stop', this).click(function() {thisobj.theatre('stop');}); this.mouseenter(function() {$('.theatre-control', thisobj).fadein();}); this.mouseleave(function() {$('.theatre-control', thisobj).fadeout();}); $('.theatre-control', this).fadeout(0); } this.append('elixon theatre jquery plugin'); } methods.destroy=function() { var theatre=this.data('theatre'); if (theatre) { clearinterval(theatre.interval); this.theatre('jump', 0); if (typeof theatre.effect.destroy == 'function') theatre.effect.destroy(); this.removeclass('theatre-'+theatre.settings.effect.replace(/[^a-z0-9]+/ig, '-')); theatre.actors.each(function(){ // restore original sizes var $this=$(this); var theatre=$this.data('theatre'); $this.width(theatre.width); $this.height(theatre.height); }) } $('.theatre-control', this).remove(); } methods.play=function() { var theatre=this.data('theatre'); var stage=this; //methods.stop.apply(this); //stage.theatre('next'); stage.theatre('stop'); theatre.interval=setinterval(function() {stage.theatre('next', true);}, theatre.settings.speed + theatre.settings.still); } methods.stop=function() { var theatre=this.data('theatre'); clearinterval(theatre.interval); theatre.interval=false; } effects['fade']= effects['slide']= effects['show']=function(stage, actors, settings, theatre) { var x={ fade: {show: 'fadein', hide: 'fadeout', initstyle: {margin: 0, top: 0, left: 0, position: 'absolute', display: 'none'}}, slide: {show: 'slidedown', hide: 'slideup', initstyle: {}}, show: {show: 'show', hide:'hide', initstyle: {}} }[settings.effect]; this.init=function() { actors[x.hide](0).css(x.initstyle).first()[x.show](0); // actors.fadeout(0) - does not hide it if stage has height=0 - assigning 'display:none' } this.next=function() { actors.stop(true, true).css('z-index', 0)[x.hide](settings.speed) .eq(theatre.index).css('z-index', 10)[x.show](settings.speed); } this.prev=function() { actors.stop(true, true).css('z-index', 0)[x.hide](settings.speed) .eq(theatre.index).css('z-index', 10)[x.show](settings.speed); } this.destroy=function() { actors.stop(true, true).css({zindex: '', top: '', left: '', position: '', margin: ''})[x.show](0); } } effects['vertical']= effects['horizontal']=function(stage, actors, settings) { var x={ horizontal: {'size': 'outerwidth', 'direction': 'left'}, vertical: {'size': 'outerheight', 'direction': 'top'} }[settings.effect]; this.init=function() { actors.fadeout(0); this.align(0, 0); actors.fadein(); } this.next=function() { // $(settings.selector, stage).last().stop(true, true); // to prevent visual contra-direction transition var curr=$(settings.selector, stage).first(); var offset=this.align(-curr[x.size](true)); curr.appendto(stage); } this.prev=function() { var curr=$(settings.selector, stage).last().prependto(stage); curr.stop(true, true).css(x.direction, -curr[x.size](true)); this.align(0); } this.destroy=function() { actors.stop(true, true).css(x.direction, '').css({opacity: '', left: '', top: ''}); } this.align=function(offset, speed) { var sacked=false; $(settings.selector, stage).each(function() { var callback=null; var $this=$(this); if (offset < 0) { callback=function() {$this.css(x.direction, offset);} } var props={}; props[x.direction]=offset; $this.stop(true, true).animate(props, isnan(speed) ? settings.speed : speed, callback); offset+=$this[x.size](true); }); return offset; } } effects['3d']=function(stage, actors, settings) { // override custom/default settings settings.resize=false; var currindex=0; var pivots=[]; var maxwidth; var maxheight; this.init=function() { var thisobj=this; maxwidth=stage.width() * 0.5; maxheight=stage.height() * 0.8; actors.each(function(pos) { var rad=(2 * math.pi * pos / actors.length) + math.pi / 2; var x=math.cos(rad); var y=math.sin(rad); var margin=10; var sizemin=0.2; var size=(y + 1) / 2 * (1 - sizemin) + sizemin; var x2=x * (stage.width() - margin) / 2 + stage.width() / 2; var y2=y * (stage.height() - margin) / 2 + stage.height() / 2; pivots.push({left: x2, top: y2, x: x, y: y, size: size, rad: rad}); }); this.animate(); //console.log(pivots); } this.next=function() { if (++currindex > actors.length - 1) currindex=0; this.animate(); } this.prev=function() { if (--currindex < 0) currindex=actors.length - 1; this.animate(); } this.destroy=function() { actors.stop(true, true).css({'z-index': '', opacity: '', left: '', top: ''}); } this.animate=function() { var thisobj=this; actors.stop(); actors.each(function(pos) { var pivot=pivots[(pos - currindex + actors.length) % actors.length]; var dim=thisobj.calcdim($(this), maxwidth, maxheight, pivot.size); var left=math.round(pivot.left - pivot.x * dim[0] / 2 - dim[0] / 2); var top=math.round(pivot.top - pivot.y * dim[1] / 2 - dim[1] / 2); // use transitions where applicable for skew() or scale() http://www.alistapart.com/articles/understanding-css3-transitions/ // https://github.com/brandonaaron/jquery-csshooks/blob/master/boxreflect.js for jquery 1.4.3 $(this).css({'z-index': math.round(pivot.size * 1000)}).animate({opacity: pivot.size, left: left, top: top, width: dim[0], height: dim[1]}, settings.speed); }); } this.calcdim=function(obj, maxwidth, maxheight, size) { var dim=obj.data('theatre'); var w=maxwidth; var h=dim.height / dim.width * w; if (h > maxheight) { w=maxwidth * (maxheight / h); h=maxheight; } return [math.round(w * size), math.round(h * size)]; } } })(jquery);