// slideshow-ER.js -- version 2009-02-01 -- by Eugene Reimer 2004-January (rewritten 2009-Jan);
//
// For a slideshow that works in ANY browser!!  (Nicely in any modern browser, degrading to a 
// simple webpage in an old browser.)  Uses dynamic-CSS techniques to scale images and fonts
// according to window size.
//
// Copyright (c) 2004,2009 Eugene Reimer;  can be freely used, modified, copied, distributed, 
// sold, etc, under the terms of either the LGPL or the GPL (your choice);
// see http://www.gnu.org/licenses for the details of these terms.
//=============================================================================================

function screenWidth()  {return screen.width  ? screen.width  : 640;}
function screenHeight() {return screen.height ? screen.height : 480;}
function windowWidth() {	//avoid window.innerWidth even when available, since prefer the clientWidth
  return document.documentElement && document.documentElement.clientWidth ? document.documentElement.clientWidth :
  document.body ? document.body.clientWidth :
  630;
}
function windowHeight() {	//avoid window.innerHeight, since prefer clientHeight
  return document.documentElement && document.documentElement.clientHeight ? document.documentElement.clientHeight :
  document.body ? document.body.clientHeight :
  440;
}
function pageWidth() {
  return document.documentElement && document.documentElement.scrollWidth ? document.documentElement.scrollWidth :
  document.body ? document.body.scrollWidth :
  0;
}
function pageHeight() {		//note kluge to get around Opera sometimes spuriously providing 2147483647 (2^31 -1) as document.documentElement.scrollHeight
  return document.documentElement && document.documentElement.scrollHeight && document.documentElement.scrollHeight<99999999 ? document.documentElement.scrollHeight :
  document.body ? document.body.scrollHeight :
  0;
}
function pagePosition() {
  return window.pageYOffset ? window.pageYOffset :
  document.documentElement && document.documentElement.scrollTop ? document.documentElement.scrollTop :
  document.body ? document.body.scrollTop :
  0;
}
function objPosn(obj) {
  var top=0;  if(obj.offsetParent) do top += obj.offsetTop; while(obj = obj.offsetParent);
  return top;
}
//function objWidth(obj)  {return obj.offsetWidth;}
//function objHeight(obj) {return obj.offsetHeight;}
//function objWidthVARIANT(obj) {  		//sum of descendant img node widths, or object-width when no img nodes
//  var W=0, imgs=obj.getElementsByTagName("img");
//  for(var i=0; i<imgs.length; ++i)  W+=imgs[i].offsetWidth;
//  return  W ? W : obj.offsetWidth;
//}
function objWidth(obj) {			//max of descendant node widths, or object-width when no descendants
  var W=0, w;
  for(var i=0; i<obj.childNodes.length; ++i)  if(w=objWidth(obj.childNodes[i]), w>W) W=w;
  //if(W && obj.offsetWidth && W!=obj.offsetWidth) alert("node:"+obj.nodeName+","+obj.nodeType+" offsetWidth:"+obj.offsetWidth+" W:"+W);
  return  W || obj.offsetWidth || 0;
}
function objHeight(obj) {			//sum of descendant node heights, or object-height when no descendants
  var H=0, h;
  for(var i=0; i<obj.childNodes.length; ++i)  H+=objHeight(obj.childNodes[i]);
  //if(H && obj.offsetHeight && H!=obj.offsetHeight) alert("node:"+obj.nodeName+","+obj.nodeType+" offsetHeight:"+obj.offsetHeight+" H:"+H);
  return  H || obj.offsetHeight || 0;
}
if(typeof FONTDIV == "undefined") FONTDIV=33;	//global var, normally supplied by the slideshow HTML page
var H,W,FS,R,img=[],div=[],divPosn=[];		//global vars, supplied by pickFontAndImageSizes
var divSizeX=[],divSizeY=[];			//global vars, supplied by pickFontAndImageSizes
var divImg=[],divImgX=[],divImgY=[];		//global vars, supplied by pickFontAndImageSizes

function pickFontAndImageSizes() {		//onload/onresize function to pick sizes -- this is the interesting part...
  var I;  H=windowHeight(); W=windowWidth(); FS=W/FONTDIV;  R=(H/W<0.75 ? H/W/0.75 : 1);		//R is ratio for current windowsize to replace 80%
  if(!document.getElementsByTagName) return;
  div=document.getElementsByTagName("div");
  img=document.getElementsByTagName("img");	//no longer needed
  if(divSizeX.length==0){										//do this only onload, not onresize
    for(var i=0; i<div.length; ++i) {divSizeX[i]=objWidth(div[i]); divSizeY[i]=objHeight(div[i]);}	//build array of div sizes
    for(var i=0; i<div.length; ++i) {divImg[i]=div[i].getElementsByTagName("img");}			//build array of div->img info
    for(var i=0; i<div.length; ++i) {if(I=divImg[i],I.length){divImgX[i]=objWidth(I[0]); divImgY[i]=objHeight(I[0]);}}	//build array of div.img sizes
    //alert("offsetWidth:"+div[0].offsetWidth + " scrollWidth:"+div[0].scrollWidth + " clientWidth:"+div[0].clientWidth);
  }
  //for(var i=0; i<img.length; ++i)  img[i].style.width = W*R+"px";					//each IMG gets width=windowWidth*R  <--for padded imgs
  for(var i=0; i<div.length; ++i) if(divImg[i].length) {						//each DIV.IMG gets height or width  <--for non-padded imgs
    var dh=divSizeY[i], di=divImg[i][0], iw=divImgX[i], ih=divImgY[i], th=dh-ih;
    var RAT=(768-1.1*th-(th>0?31:0)-(i==0?82:0))/1024;	//want 0.75 for singleton-img div, independent of initial window-size (achieved by moving set-body-fontsize)
    if(ih/iw<RAT)di.style.width=W*R+"px";  else di.style.height=W*R*RAT+"px";				//resize the img
  }
  if(document.body && document.body.style)  document.body.style.fontSize = FS+"px";			//BODY gets font-size=windowWidth/FONTDIV  <--needed?
  for(var i=0; i<div.length; ++i)  div[i].style.height   = H+"px";					//each DIV gets height=windowHeight
  for(var i=0; i<div.length; ++i)  div[i].style.fontSize = FS*R+"px";					//each DIV gets font-size=bodyFontSize*R
  for(var i=0; i<div.length; ++i)  divPosn[i] = objPosn(div[i]);					//build divPosn array of positions
  divPosn[0] = 0;											//workaround for one of Opera's quirks
}
window.onload=   pickFontAndImageSizes;		//install as onload handler
window.onresize= pickFontAndImageSizes;		//install as onresize handler

function debugAlert() {
  var I, B=document.body, H=document.documentElement, HtB=0, HtH=0, HtKluge=0;  if(B)HtB=B.scrollHeight; if(H)HtH=H.scrollHeight; if(B&&H)HtKluge=HtH-HtB;
  var divSz=""; for(var i=0; i<div.length; ++i) {divSz+=divSizeX[i]+"x"+divSizeY[i]; if(I=divImg[i],I.length)divSz+="("+divImgX[i]+"x"+divImgY[i]+")"; divSz+=" ";}
  alert("DOM Info:"+
  "\ncompatMode:  \t"+document.compatMode+
  "\nscreen:      \t"+screenWidth()+"x"+screenHeight()+
  "\nwindow:      \t"+windowWidth()+"x"+windowHeight()+	" ("+window.innerWidth+","+document.documentElement.clientWidth+","+document.body.clientWidth+")"+
  "\npage:        \t"+pageWidth()+"x"+pageHeight()+
  "\nscaleR:      \t"+R+
  "\npageHeight-B:\t"+HtB+
  "\npageHeight-H:\t"+HtH+
  "\npageHtKluge: \t"+HtKluge+
  "\npagePosition:\t"+pagePosition()+
  "\nslideNum:    \t"+curSlide()+" of "+divPosn.length+
  "\nslidePosns:  \t"+divPosn[0]+","+divPosn[1]+","+divPosn[2]+"..."+
  "\ndivSizes-ini:\t"+divSz+
  "\ndivSizes-cur:\t"+div[0].offsetWidth+"x"+div[0].offsetHeight+"..."+div[div.length-1].offsetWidth+"x"+div[div.length-1].offsetHeight+
  "\nchildren:    \t"+div[0].childNodes.length+" "+div[1].childNodes.length+"..."+
  "");
}
function curSlide() {
  return Math.round(pagePosition()/windowHeight());	//==SAFER to use Math.round rather than Math.floor==??==
}
function toSlide(num) {				//replaces both pageDn and pageUp
  var N = (num<0 ?0 : num>divPosn.length-1 ?divPosn.length-1 :num);
  if(window.scrollTo) window.scrollTo(0, divPosn[N]);
}
//function pageDn () {
//  var HtKluge=document.documentElement.scrollHeight - document.body.scrollHeight;
//  if(window.scrollTo) window.scrollTo(0, HtKluge+slideNum*windowHeight());
//  if(windowWidth() < screenWidth()) window.location.hash=ANCH[slideNum];			//non-fullscreen variant using ANCH
//  else if(window.scrollBy) window.scrollBy(0, windowHeight());  				//normal pagedown action
//}
function onMouseEvent(eventParm) {
  var e=(eventParm||window.event);              //window.event for ie
  var rightButton= (e.button==2);               //all browsers use 2 for Right-button  (but either 0 or 1 for Left)
  if(curSlide()==divPosn.length-1) return;	//want standard mouse-click behaviour on TOC page
  //alert("mouse-event e.type:"+e.type+" e.button:"+e.button);
  if(rightButton) toSlide(curSlide()-1);
  else            toSlide(curSlide()+1);
  if(e.preventDefault)  e.preventDefault();     //prevent default action - Opera|ff|ns;  NOT WORKING in Opera|ff;  needed for Right-click
  else                  e.returnValue=false;    //prevent default action - ie;           NOT WORKING in ie
}
function onKeyboardEvent(eventParm) {
  var e=(eventParm||window.event);              //window.event for ie
  var keyCode=(e.charCode||e.keyCode||e.which); //e.keyCode for ie;  e.which for ns4
  var keyChar=String.fromCharCode(keyCode);
  //alert("keystroke e.type:"+e.type+" keyCode:"+keyCode+" keyChar:"+keyChar);
  if     (keyChar=="N"||keyChar=="n"||keyCode==34||keyCode==63277) toSlide(curSlide()+1);	//was pageDn();  could use: keyCode==78||keyCode==110
  else if(keyChar=="P"||keyChar=="p"||keyCode==33||keyCode==63276) toSlide(curSlide()-1);	//was pageUp();
  else if(                            keyCode==35||keyCode==63275) toSlide(99999999);		//the END-key;  needed to get around Opera-Fullscreen quirk
  else if(keyChar=="D"||keyChar=="d"                             ) debugAlert();
  else return;
  if(e.preventDefault)  e.preventDefault();     //prevent default action - Opera|ff|ns;  also available: stopPropagation;  needed for PageUp/Down keys
  else                  e.returnValue=false;    //prevent default action - ie;           also available: cancelBubble
}
function onKeyboardPress(eventParm) {
  var e=(eventParm||window.event);              //window.event for ie
  var keyCode=(e.charCode||e.keyCode||e.which); //e.keyCode for ie;  e.which for ns4
  var keyChar=String.fromCharCode(keyCode);
  //alert("keystroke e.type:"+e.type+" keyCode:"+keyCode+" keyChar:"+keyChar);
  if     (keyChar=="N"||keyChar=="n"||keyCode==34||keyCode==63277) {}
  else if(keyChar=="P"||keyChar=="p"||keyCode==33||keyCode==63276) {}
  else if(                            keyCode==35||keyCode==63275) {}
  else if(keyChar=="D"||keyChar=="d"                             ) {}
  else return;
  if(e.preventDefault)  e.preventDefault();     //prevent default action - Opera|ff|ns;  also available: stopPropagation;  needed for PageUp/Down keys
  else                  e.returnValue=false;    //prevent default action - ie;           also available: cancelBubble
}
if(window.scrollTo){				//==Install Mouse + Keyboard handlers ONLY if browser supports window.scrollTo  (ignore ns4's document.captureEvents)
//cument.onmousedown = onMouseEvent;            //mouse handler; for RIGHT-clicks in Opera: Tools: Preferences: Advanced: Content: JavascriptOptions: Allow...RightClicks
document.onkeydown   = onKeyboardEvent;         //keydown-handler  -- works for PageUp/Down keys in IE (onkeypress does not)
document.onkeypress  = onKeyboardPress;         //keypress-handler -- needed to suppress default in non-IE browsers
}

// my original workaround for one of Opera's Fullscreen-mode quirks was to avoid having the last (menu) slide be a DIV;
// but that became inconvenient (with dynamic-CSS) so I went to handling the End-keystroke instead;
//
// Opera will sometimes refuse to reload modified images -- when viewing an unmodified page whose images have been modified;
//	 when nothing else works one can restart the browser;  "touch"ing the HTML page might be another solution?
//
// NOTES on the pickFontAndImageSizes routine:
// Misleading size info:  eg a div containing nothing but one img,  its width is totally bogus;  height ok in ie, approx 5..9 more than img-height in op|ff--??--
//	my objWidth & objHeight routines have solved this -- now getting sensible values, as divSizeX/Y!!
// The R=(H/W<0.75 ? H/W/0.75 : 1) and img-width=W*R -- was for Padded-to-1024x768 images;
//	for unpadded but sized to max-width:1024 max-height:768, use:
//	(a) the smaller, by ratio, of: width:W; height:H  <-- looks hideous in tall narrow window because of annotation-text size-changes on portrait<-->landscape
//	(b) for same size as before, compute the 4:3 dimensions, limit to width:W*R or height:W*R*0.75...
// Added data-structures:  to get from div to img within it;  from div to its img's INITIAL-size (the H:W ratio is preserved but only approximately...)
//	in order to do scaling based on div-height including any text;  to handle captions;  and to scrap special-case for titlepage...
//	my "RAT" calculation to do this is crude, but works reasonably well;  quirks for some extreme window-sizes are due my having set a minimum-fontsz in browser...
//	note: may want to support multiple imgs on one slide, side-by-side??  presently only handling zero or one image per div;
//
// In Firefox, windowWidth was out by width of vertical-scrollbar, leading to unwanted horizontal-scrollbar (in a tall narrow window):  
//	not sure when this became a problem, but am thinking it didn't use to be;  but since it only happens in a tall narrow window, I may have failed to notice;
//	using overflow:hidden avoids this, although means losing rightmost 15-pixels of wide images  -- the better method:
//	-- in ff,op: window.innerWidth gives width of entire window;  both kinds of clientWidth give what's wanted: width less scrollbar-width;
//	-- in ie6, window.innerWidth not available;  both kinds of clientWidth give what's wanted;
//	ergo, modifying windowWidth to never return window.innerWidth solves the problem (w/o needing overflow:hidden);
//
// Mouse-Handling:
// the mouse-click-handling is less than satisfactory;  left-click is fine in most browsers;  right-click less so;
// Only needed when using a mouse-emulating-remote to control an Operashow-Presentation, where that support has been tolerable, just barely...
// Could improve by treating mouse-clicks as page-down/up ONLY when the mouse-pointer is at or past an edge of the window??  (So can also get standard behaviour...)
// Could improve by ensuring that the document part of window has keyboard-focus;
// NOTE: For website use, mouse-click handling is not needed, and best left disabled;
//
// FIXME: caption-text & text-slides not working in ns4, so at present the degrading to simple webpage is not as good as I thought??
//
// Doris reported that Page-Down not working in Windows-XP with ie7 -- Erroneously as it turns out -- PageDown is fine!!
// my testing with ie7 shows PageDown working just fine;  however "D" keystroke is ignored??  whereas N/P keys work just fine;
// AHA, ies4linux limitations on ie7 mean javascript-alert does nothing -- and that's why "D" key does nothing!!
//
// for ie in 800x600 window, revising the RAT-computation-contants (768,1024):  GOT WORSE with 600,800,  MUCH IMPROVED by 1200,1600 -- to my surprise??
//	==RAT=(1200-1.1*th-(th>0?31:0)-(i==0?160:0))/1600;	<--works nicely in ie6 in 800x600 window;
//	==needs further testing...
//
// 2009-Mar: sometimes in Opera in a tall narrow window, the initial size calculations go slightly wrong;  ==need to fix this, 
//	but am playing safe wrt getting stuck in such cases by using Round rather Floor in curSlide  <--consider less drastic rounding-rule, eg: floor(X+0.25);
//	curiously, the problem always goes away on resizing the window??
