/* slides.js

   Copyright (c) 2005 W3C (MIT, ERCIM, Keio), All Rights Reserved.
   W3C liability, trademark, document use and software licensing
   rules apply, see:

   http://www.w3.org/Consortium/Legal/copyright-documents
   http://www.w3.org/Consortium/Legal/copyright-software
*/

var ns_pos = (typeof window.pageYOffset!='undefined');

window.onload = startup;

var slidenum = 0;     // integer slide count: 0, 1, 2, ...
var slides;           // set to array of slide div's
var slideNumElement;  // element containing slide number
var footer;           // element containing footer

var helpPage = "http://www.w3.org/2005/03/slideshowhelp.html";
var helpText = "Navigate with click, space bar, Pg Up or Pg Dn." + " Use < and > to change font size.";

var sizeIndex = 0;
var sizes = new Array("14pt", "18pt", "22pt", "24pt", "26pt", "30pt", "36pt");
var lastWidth = 0;

/* general initialization */
function startup()
{
   footer = addFooter();
   slides = collectSlides();
   patchAnchors();
   slidenum = findSlideNumber();
   showSlideNumber();

   if (slides.length > 0)
   {
      slide = slides[slidenum];
      showSlide(slide);
   }

   // opera fonts look smaller somehow on Linux
   //if (navigator.userAgent.indexOf("Opera")!=-1)
   //   sizes = new Array("18pt", "22pt", "28pt", "36pt", "40pt");

   document.onclick = nextSlide;
   document.onkeydown = keyDown;
   //window.onfullscreen = resized;
   window.onresize = resized;
}


function resized()
{
   var width = 0;

   if( typeof( window.innerWidth ) == 'number' )
   {
      width = window.innerWidth;  // Non IE browser
   }
   else if (document.documentElement && document.documentElement.clientWidth)
   {
      width = document.documentElement.clientWidth;  // IE6
   }
   else if (document.body && document.body.clientWidth)
   {
      width = document.clientWidth; // IE4
   }

   // IE fires onresize even when only font size is changed!
   // so we do a check to avoid blocking < and > actions
   if (width != lastWidth)
   {
      if (width > 1000)
         sizeIndex = 4;
      else if (width > 800)
         sizeIndex = 1;
      else if (width)
         sizeIndex = 0;

      document.body.style.fontSize = sizes[sizeIndex];
      lastWidth = width;
   }
}

// these don't work well on Opera, for which
// we take advantage on @media projection
function smaller()
{
   if (sizeIndex > 0)
   {
      --sizeIndex;
   }

   document.body.style.fontSize = sizes[sizeIndex];
}

function bigger()
{
   if (sizeIndex < sizes.length - 1)
   {
      ++sizeIndex;
   }
   document.body.style.fontSize = sizes[sizeIndex];
}

function keyDown(event)
{
    var key;

    // kludge around NS/IE differences 
    if (window.event)
       key = window.event.keyCode;
    else if (event.which)
       key = event.which;
    else
       return true; // Yikes! unknown browser

//alert(key);

    if (((key == 34) || (key == 39)) || (key == 40)) // Page Down, right or down cursor
    {
       nextSlide();
    }
    else if (((key == 33) || (key == 37)) || (key == 38)) // Page Up, left or up cursor
    {
       previousSlide();
    }
    else if (key == 32) // space bar
    {
       nextSlide();
    }
    else if (key == 188)  // < for smaller fonts
    {
       smaller();
    }
    else if (key == 190)  // > for larger fonts
    {
       bigger();
    }
    else if (key == 86)  // V for smaller fonts
    {
       smaller();
    }
    else if (key == 66)  // B for larger fonts
    {
       bigger();
    }

    return false;
}

function showSlideNumber()
{
   slideNumElement.innerHTML = "slide " + (slidenum + 1) + "/" + slides.length;
}

function nextSlide()
{
   var slide;

   if (slidenum < slides.length - 1)
   {
      slide = slides[slidenum];
      hideSlide(slide);

      slidenum = slidenum + 1;
      slide = slides[slidenum];
      showSlide(slide);
   }

   showSlideNumber();
}

/*
 oldslidenum is slide number from browser location before click
 by the time we get here, the location will have been updated
 so we can check if it has changed!
*/
function checkSlideNumber(oldslidenum)
{
   var newslidenum = findSlideNumber();

   if (newslidenum != oldslidenum)
   {
       slide = slides[slidenum];
       hideSlide(slide);
       slidenum = newslidenum;
       slide = slides[slidenum];
       showSlide(slide);
   }
}

function previousSlide()
{
   var slide;

   if (slidenum > 0)
   {
      slide = slides[slidenum];
      hideSlide(slide);

      slidenum = slidenum - 1;
      slide = slides[slidenum];
      showSlide(slide);
   }

   showSlideNumber();
}

function showSlide(slide)
{
   slide.style.visibility = "visible";
   slide.style.display = "block";
}

function hideSlide(slide)
{
   slide.style.visibility = "hidden";
   slide.style.display = "none";
}

// return new array of all slides
function collectSlides()
{
   var slides = new Array();
   var divs = document.body.getElementsByTagName("div");

   // IE getAttribute requires "class" to be "className"
   var name = ns_pos ? "class" : "className";

   for (var i = 0; i < divs.length; ++i)
   {
      div = divs.item(i);

      if (div.getAttribute(name) == "slide")
      {
         // add slide to collection
         slides[slides.length] = div;

         // hide each slide as it is found
         div.style.display = "none";
         div.style.visibility = "hidden";
      }
   }

   return slides;
}

/* set click handlers on all anchors */
function patchAnchors()
{
   var anchors = document.body.getElementsByTagName("a");

   for (var i = 0; i < anchors.length; ++i)
   {
      anchors[i].onclick = clickedAnchor;
   }
}

function clickedAnchor(e)
{
   /* hack for clicking on link to slide on same page */

   var check = "checkSlideNumber(" + slidenum + ")"; 
   setTimeout(check, 300); 
   this.blur();

// we could get the href attribute and move to the corresponding
// slide, but we would then have to parse the URI and stop propagation
// for now we let the browser parse the URI and update the location  
//   stopPropagation(e);
}

// find current slide based upon location
// first find target anchor and then look
// for associated div element enclosing it
// finally map that to slide number
function findSlideNumber()
{
   // first get anchor from page location

   var i = location.href.indexOf("#");

   // check if anchor is entire page

   if (i < 0)
      return 0;  // yes

   var anchor = location.href.substr(i+1);

   // now use anchor as XML ID to find target

   var target = document.getElementById(anchor);

   if (!target)
      return 0;

   // search for enclosing slide

   // IE getAttribute requires "class" to be "className"
   var name = ns_pos ? "class" : "className";

   while (true)
   {
      // browser coerces html elements to uppercase!
      if (target.nodeName.toLowerCase() == "div" &&
          target.getAttribute(name) == "slide")
      {
         // found the slide element
         break;
      }

      // otherwise try parent element if any

      target = target.parentNode;

      if (!target)
      {
         return 0;   // no luck!
      }
   };

   for (i = 0; i < slides.length; ++i)
   {
      if (slides[i] == target)
         return i;  // success
   }

   // oh dear still no luck
   return 0;
}

/* find copyright text from meta element */
function findCopyright()
{
   var name, content;
   var meta = document.getElementsByTagName("meta");

   for (var i = 0; i < meta.length; ++i)
   {
      name = meta[i].getAttribute("name");
      content = meta[i].getAttribute("content");

      if (name == "copyright")
         return content;
   }

   return null;
}

function addFooter()
{
   var slideCounter, page;

   var footer = createElement("div");
   footer.setAttribute("class", "footer");

   if (ns_pos) // a reasonably behaved browser
   {
      var right = document.createElement("div");
      right.setAttribute("style", "float: right; text-align: right");

      slideCounter = document.createElement("div")
      slideCounter.innerHTML = "slide n/m";
      right.appendChild(slideCounter);
      footer.appendChild(right);

      var left = document.createElement("div");
      left.setAttribute("style", "text-align: left");

      var help = document.createElement("a");
      help.setAttribute("href", helpPage);
      help.setAttribute("title", helpText);
      help.innerHTML = "help?";
      left.appendChild(help);

      var gap = document.createTextNode(" ");
      left.appendChild(gap);

      var i = location.href.indexOf("#");

      // check if anchor is entire page

      if (i > 0)
         page = location.href.substr(0, i);
      else
         page = location.href;

      var start = document.createElement("a");
      start.setAttribute("href", page);
      start.setAttribute("title", "restart presentation");
      start.innerHTML = "restart?";
      left.appendChild(start);

      var copyright = findCopyright();

      if (copyright)
      {
         var span = document.createElement("span");
         span.innerHTML = copyright;
         span.style.color = "black";
         span.style.marginLeft = "4em";
         left.appendChild(span);
      }

      footer.appendChild(left);
   }
   else // IE so need to work around its poor CSS support
   {
      footer.style.position = "absolute";
      footer.style.width = "100%";
      footer.style.height = "1.2em";
      footer.style.top = "auto";
      footer.style.bottom = 0;
      footer.style.left = "0";
      footer.style.right = "0";
      footer.style.textAlign = "right";
      footer.style.fontSize = "60%";
      footer.style.color = "red";
      footer.style.background = "rgb(240,240,240)";

      // would like to have help text left aligned
      // and counter text right aligned, but have
      // but have yet to solve this here for IE6

      var help = document.createElement("a");
      help.setAttribute("href", helpPage);
      help.setAttribute("title", helpText);
      help.innerHTML = "help?";
      footer.appendChild(help);

      var gap = document.createTextNode(" ");
      footer.appendChild(gap);

      var i = location.href.indexOf("#");

      // check if anchor is entire page

      if (i > 0)
         page = location.href.substr(0, i);
      else
         page = location.href;

      var start = document.createElement("a");
      start.setAttribute("href", page);
      start.setAttribute("title", "restart presentation");
      start.innerHTML = "restart?";
      footer.appendChild(start);

      var copyright = findCopyright();

      if (copyright)
      {
         var span = document.createElement("span");
         span.innerHTML = copyright;
         span.style.color = "black";
         span.style.marginLeft = "2em";
         footer.appendChild(span);
      }

      slideCounter = document.createElement("span")
      slideCounter.innerHTML = "slide n/m";
      slideCounter.style.marginLeft = "4em";
      footer.appendChild(slideCounter);
   }

   footer.setAttribute("onclick", "stopPropagation");
   document.body.appendChild(footer);
   slideNumElement = slideCounter;
   return footer;
}

function replaceByNonBreakingSpace(str)
{
   for (var i = 0; i < str.length; ++i)
      str[i] = 160;
}

function stopPropagation(e)
{
   if (window.event)
   {
      window.event.cancelBubble = true;
   }
   else
   {
      e.cancelBubble = true;
      e.stopPropagation();
      e.preventDefault();
   }
}

// works with text/html and text/xhtml+xml with thanks to Simon Willison
function createElement(element)
{
   if (typeof document.createElementNS != 'undefined')
   {
      return document.createElementNS('http://www.w3.org/1999/xhtml', element);
   }

   if (typeof document.createElement != 'undefined')
   {
      return document.createElement(element);
   }

   return false;
}
