slideshow-s6-blank
Version:
S6 Blank - Slide Show (S9) Template Pack
535 lines (427 loc) • 14.2 kB
JavaScript
var Slideshow = {};
/************************************
* lets you define your own "global" transition function
* passes in a reference to from and to slide wrapped in jQuery wrapper
*/
Slideshow.transition = function( $from, $to ) {
// $from.hide();
// $to.show();
$from.hide('fast');
$to.show('fast');
}
/***********************
* sample custom transition using scrollUp effect
* inspired by Karl Swedberg's Scroll Up Headline Reader jQuery Tutorial[1]
* [1] http://docs.jquery.com/Tutorials:Scroll_Up_Headline_Reader
*/
function transitionSlideUpSlideDown( $from, $to ) {
$from.slideUp( 500, function() { $to.slideDown( 1000 ); } );
}
function transitionFadeOutFadeIn( $from, $to ) {
$from.fadeOut( 500 );
$to.fadeIn( 500 );
}
function transitionScrollUp( $from, $to ) {
var cheight = $from.outerHeight();
// hide scrollbar during animation
$( 'body' ).css( 'overflow-y', 'hidden' );
$to.css( 'top', cheight+'px' );
$to.show();
$from.animate( {top: -cheight}, 'slow' );
$to.animate( {top: 0}, 'slow', function() {
$from.hide().css( 'top', '0px');
// restore possible scrollbar
$( 'body' ).css( 'overflow-y', 'auto' );
});
}
Slideshow.init = function( options ) {
var settings = $.extend({
mode : 'slideshow', // slideshow | outline | autoplay
projectionStyleId : '#styleProjection',
screenStyleId : '#styleScreen',
titleSelector : 'h1',
slideSelector : '.slide', // dummy (not yet working)
stepSelector : '.step', // dummy (not yet working)
debug : false,
change : null // todo: change to use a custom event and trigger
}, options || {});
settings.isProjection = true; // are we in projection (slideshow) mode (in contrast to screen (outline) mode)?
settings.snum = 1; // current slide # (non-zero based index e.g. starting with 1)
settings.smax = 1; // max number of slides
settings.incpos = 0; // current step in slide
settings.steps = null;
settings.autoplayInterval = null;
function debug( msg )
{
if( settings.debug && window.console && window.console.log )
window.console.log( '[debug] ' + msg );
}
function showHide( action )
{
var $navLinks = $( '#navLinks' )
switch( action ) {
case 's': $navLinks.css( 'visibility', 'visible' ); break;
case 'h': $navLinks.css( 'visibility', 'hidden' ); break;
case 'c': /* toggle control panel */
if( $navLinks.css( 'visibility' ) != 'visible' )
$navLinks.css( 'visibility', 'visible' );
else
$navLinks.css( 'visibility', 'hidden' );
break;
}
}
function updateCurrentSlideCounter()
{
$( '#currentSlide' ).html( settings.snum + '/' + settings.smax );
}
function updateJumpList()
{
$('#jumplist').get(0).selectedIndex = (settings.snum-1);
}
function updatePermaLink()
{
// todo: unify hash marks??; use #1 for div ids instead of #slide1?
window.location.hash = '#'+settings.snum;
}
function goTo( target )
{
if( target > settings.smax || target == settings.snum ) return;
go( target - settings.snum );
}
function go( dir )
{
debug( 'go: ' + dir );
if( dir == 0 ) return; /* same slide; nothing to do */
var cid = '#slide' + settings.snum; /* current slide (selector) id */
var csteps = settings.steps[settings.snum-1]; /* current slide steps array */
/* remove all step and stepcurrent classes from current slide */
if( csteps.length > 0) {
$( csteps ).each( function() {
$(this).removeClass( 'step' ).removeClass( 'stepcurrent' );
} );
}
/* set snum to next slide */
settings.snum += dir;
if( settings.snum > settings.smax ) settings.snum = settings.smax;
if( settings.snum < 1 ) settings.snum = 1;
var nid = '#slide' + settings.snum; /* next slide (selector) id */
var nsteps = settings.steps[settings.snum-1]; /* next slide steps array */
if( dir < 0 ) /* go backwards? */
{
settings.incpos = nsteps.length;
/* mark last step as current step */
if( nsteps.length > 0 )
$( nsteps[settings.incpos-1] ).addClass( 'stepcurrent' );
}
else /* go forwards? */
{
settings.incpos = 0;
if( nsteps.length > 0 ) {
$( nsteps ).each( function() {
$(this).addClass( 'step' ).removeClass( 'stepcurrent' );
} );
}
}
if( !(cid == nid) ) {
debug( "transition from " + cid + " to " + nid );
Slideshow.transition( $( cid ), $( nid ) );
}
updateJumpList();
updateCurrentSlideCounter();
updatePermaLink();
if (settings.change) { settings.change(); }
}
function subgo( dir )
{
debug( 'subgo: ' + dir + ', incpos before: ' + settings.incpos + ', after: ' + (settings.incpos+dir) );
var csteps = settings.steps[settings.snum-1]; /* current slide steps array */
if( dir > 0)
{ /* go forward? */
if( settings.incpos > 0 )
$( csteps[settings.incpos-1] ).removeClass( 'stepcurrent' );
$( csteps[settings.incpos] ).removeClass( 'step').addClass( 'stepcurrent' );
settings.incpos++;
}
else
{ /* go backwards? */
settings.incpos--;
$( csteps[settings.incpos] ).removeClass( 'stepcurrent' ).addClass( 'step' );
if( settings.incpos > 0 )
$( csteps[settings.incpos-1] ).addClass( 'stepcurrent' );
}
}
function notOperaFix()
{
$( settings.projectionStyleId ).attr( 'media','screen' );
var styleScreen = $( settings.screenStyleId ).get(0);
styleScreen.disabled = true;
}
function toggle()
{
// toggle between projection (slide show) mode
// and screen (outline) mode
// get stylesheets
var styleProjection = $( settings.projectionStyleId ).get(0);
var styleScreen = $( settings.screenStyleId ).get(0);
if( !styleProjection.disabled )
{
styleProjection.disabled = true;
styleScreen.disabled = false;
settings.isProjection = false;
$('.slide').each( function() { $(this).show(); } );
}
else
{
styleProjection.disabled = false;
styleScreen.disabled = true;
settings.isProjection = true;
$('.slide').each( function(i) {
if( i == (settings.snum-1) )
$(this).show();
else
$(this).hide();
});
}
}
function populateJumpList() {
var list = $('#jumplist').get(0);
$( '.slide' ).each( function(i) {
var text = $(this).find( settings.titleSelector ).text();
list.options[list.length] = new Option( (i+1)+' : '+ text, (i+1) );
});
}
function createControls()
{
// todo: make layout into an id (not class?)
// do we need or allow more than one element?
// if no div.layout exists, create one
if( $( '.layout' ).length == 0 )
$( "<div class='layout'></div>").appendTo( 'body' );
$( '.layout' )
.append( "<div id='controls'>" )
.append( "<div id='currentSlide'>" );
var $controls = $( '#controls' )
$controls.html( '<div id="navLinks">'
+ '<a accesskey="t" id="toggle" href="#">Ø<\/a>'
+ '<a accesskey="z" id="prev" href="#">«<\/a>'
+ '<a accesskey="x" id="next" href="#">»<\/a>'
+ '<div id="navList"><select id="jumplist" /><\/div>'
+ '<\/div>' );
$controls.hover( function() { showHide('s') }, function() { showHide('h') });
$('#toggle').click( function() { toggle(); } );
$('#prev').click( function() { go(-1); } );
$('#next').click( function() { go(1); } );
$('#jumplist').change( function() { goTo( parseInt( $( '#jumplist' ).val() )); } );
populateJumpList();
updateCurrentSlideCounter();
updatePermaLink();
}
function toggleSlideNumber()
{
// toggle slide number/counter
$( '#currentSlide' ).toggle();
}
function toggleFooter()
{
$( '#footer').toggle();
}
function keys(key)
{
if (!key) {
key = event;
key.which = key.keyCode;
}
if (key.which == 84) {
toggle(); // toggle between project and screen css media mode
return;
}
if( settings.isProjection ) {
switch (key.which) {
case 32: // spacebar
case 34: // page down
case 39: // rightkey
case 40: // downkey
var csteps = settings.steps[settings.snum-1]; /* current slide steps array */
if ( !csteps || settings.incpos >= csteps.length ) {
go(1);
} else {
subgo(1);
}
break;
case 33: // page up
case 37: // leftkey
case 38: // upkey
if( !settings.steps[settings.snum-1] || settings.incpos <= 0 ) {
go(-1);
} else {
subgo(-1);
}
break;
case 36: // home
goTo(1);
break;
case 35: // end
goTo(settings.smax);
break;
case 67: // c
showHide('c'); // toggle controls (navlinks,navlist)
break;
case 65: //a
case 80: //p
case 83: //s
toggleAutoplay();
break;
case 70: //f
toggleFooter();
break;
case 78: // n
toggleSlideNumber();
break;
case 68: // d
toggleDebug();
break;
}
}
}
function autoplay()
{
// suspend autoplay in outline view (just slideshow view)
if( !settings.isProjection )
return;
// next slide/step, please
var csteps = settings.steps[settings.snum-1]; // current slide steps array
if( !csteps || settings.incpos >= csteps.length ) {
if( settings.snum >= settings.smax )
goTo( 1 ); // reached end of show? start with 1st slide again (for endless cycle)
else
go(1);
}
else {
subgo(1);
}
}
function toggleDebug()
{
settings.debug = !settings.debug;
doDebug();
}
function doDebug()
{
// fix/todo: save background into oldbackground
// so we can restore later
if( settings.debug == true )
{
$( '#header' ).css( 'background', '#FCC' );
$( '#footer' ).css( 'background', '#CCF' );
$( '#controls' ).css( 'background', '#BBD' );
$( '#currentSlide' ).css( 'background', '#FFC' );
}
else
{
$( '#header' ).css( 'background', 'transparent' );
$( '#footer' ).css( 'background', 'transparent' );
$( '#controls' ).css( 'background', 'transparent' );
$( '#currentSlide' ).css( 'background', 'transparent' );
}
}
function toggleAutoplay()
{
if( settings.autoplayInterval )
{
clearInterval( settings.autoplayInterval );
settings.autoplayInterval = null;
}
else
{
settings.autoplayInterval = setInterval ( autoplay, 2000 );
}
}
function collectStepsWorker(obj) {
var steps = new Array();
if( !obj )
return steps;
$(obj).children().each( function() {
if( $(this).hasClass( 'step' ) ) {
debug( 'step found for ' + this.tagName );
$(this).removeClass( 'step' );
/* don't add enclosing list; instead add step class to all list items/children */
if( $(this).is( 'ol,ul' ) ) {
debug( ' ol or ul found; adding auto steps' );
$(this).children().addClass( 'step' );
}
else
{
steps.push( this )
}
}
steps = steps.concat( collectStepsWorker(this) );
});
return steps;
}
function collectSteps() {
var steps = new Array();
$slides.each( function(i) {
debug ( 'collectSteps for ' + this.id + ':' );
steps[i] = collectStepsWorker( this );
});
$( steps ).each( function(i) {
debug( 'slide ' + (i+1) + ': found ' + this.length + ' steps' );
});
return steps;
}
function addClicker() {
// if you click on heading of slide -> go to next slide (or next step)
$( settings.titleSelector, $slides ).click( function( ev ) {
if(ev.which != 1) return; // only process left clicks (e.g 1; middle and rightclick use 2 and 3)
if( !settings.isProjection ) // suspend clicker in outline view (just slideshow view)
return;
var csteps = settings.steps[settings.snum-1]; // current slide steps array
if ( !csteps || settings.incpos >= csteps.length )
go(1);
else
subgo(1);
} );
$( settings.titleSelector, $slides ).bind('contextmenu', function() {
if( !settings.isProjection ) // suspend clicker in outline view (just slideshow view)
return;
var csteps = settings.steps[settings.snum-1]; // current slide steps array
if ( !csteps || settings.incpos >= csteps.length )
go(-1);
else
subgo(-1);
return false;
} );
}
function addSlideIds() {
$slides.each( function(i) {
this.id = 'slide'+(i+1);
});
}
// init code here
// store possible slidenumber from hash */
// todo: use regex to extract number
// might be #slide1 or just #1
var gotoSlideNum = parseInt( window.location.hash.substring(1) );
debug( "gotoSlideNum=" + gotoSlideNum );
var $slides = $( '.slide' );
settings.smax = $slides.length;
addSlideIds();
settings.steps = collectSteps();
createControls();
addClicker();
/* opera is the only browser currently supporting css projection mode */
/* if( !$.browser.opera ) */
notOperaFix();
if( !isNaN( gotoSlideNum ))
{
debug( "restoring slide on (re)load #: " + gotoSlideNum );
goTo( gotoSlideNum );
}
if( settings.mode == 'outline' )
toggle();
else if( settings.mode == 'autoplay' )
toggleAutoplay();
if( settings.debug == true )
doDebug();
document.onkeyup = keys;
} // end Slideshow