view 2015_01_27/slide_template/s6/jquery.slideshow.js @ 0:47676a16ed13

Add Slides
author Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
date Tue, 14 Jul 2015 17:23:04 +0900
parents
children
line wrap: on
line source


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="#">&#216;<\/a>' 
	    + '<a accesskey="z" id="prev" href="#">&laquo;<\/a>' 
	    + '<a accesskey="x" id="next" href="#">&raquo;<\/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