function Coords(x,y){
  return {x:x,y:y};
}

function hasClass( obj, className ){
  return (' '+obj.className+' ').indexOf(' '+className+' ') >= 0;
}

function addClass( obj, className ){
  if( obj && !hasClass( obj, className ) ){
    obj.className += ' ' + className;
  }
}

function removeClass(obj, className){
  if(obj){
    obj.className = (' '+obj.className+' ').replace( ' ' + className + ' ', ' ');
    obj.className = obj.className.replace(/(^\s+|\s+$)/g,'');
  }
}

var DOM={
  getObj:function(id, el) {
    el = el || document;
    return el.getElementById ? el.getElementById(id) :
      el.all ? el.all[id] :
      el.layers ? el.layers[id] :
      null;
  },
  scrollTo:function( scrollingEl, el, offset ){
    offset = offset || 0;
    if( typeof scrollingEl == 'string' ){
      scrollingEl = DOM.getObj( scrollingEl );
    }

    var sc = DOM.getObjectCoords( scrollingEl ),
        el = DOM.getObjectCoords( el );

    scrollingEl.scrollTop = (el.top - sc.top - offset);
  },  
  findStyle:function( parent, style, depth ){
    if( style.indexOf('.') == 0 ){
      element = '*';
      className = style.substr( 1 );
    } else if( style.indexOf('.') > 0 ) {
      element = style.substr(0, style.indexOf('.') );
      className = style.substr( style.indexOf('.') + 1 );
    } else {
      element = '*';
      className = style;
    }
      
    if( typeof depth == 'undefined' ) depth = 1;

    if( depth > 5 ) return null;
      
    var els = parent.getElementsByTagName( element ),
        foundEl = [];
    for( var x=0; x<els.length; x++ ){
      if( hasClass( els[x], className ) ){
        foundEl[foundEl.length] = els[x];
      }
      // recursively check
      /*tmpFound = findStyle( els[x], element + '.' + className, depth + 1 );
      if( tmpFound && tmpFound.length && tmpFound.length > 0 ){
        for( var i=0; i<tmpFound.length; i++ ){
          foundEl[foundEl.length] = tmpFound[i];
        }
      }*/
    }
    if( foundEl.length == 1 ){
      return foundEl[0];
    } else {
      return foundEl;
    }
  },
  // http://www.quirksmode.org/js/findpos.html
  findPos:function(obj) {
    var curleft = curtop = 0;
    if (obj.offsetParent) {
      curleft = obj.offsetLeft
      curtop = obj.offsetTop
      while (obj = obj.offsetParent) {
        curleft += obj.offsetLeft
        curtop += obj.offsetTop
      }
    }
    return {left:curleft,top:curtop};
  },
  // http://www.howtocreate.co.uk/tutorials/javascript/browserwindow
  getWindowSize:function(){
    if( typeof( window.innerWidth ) == 'number' ) {
      //Non-IE
      return {w:window.innerWidth, h:window.innerHeight};
    } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
      //IE 6+ in 'standards compliant mode'
      return {w:document.documentElement.clientWidth, h:document.documentElement.clientHeight};
    } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
      //IE 4 compatible
      return {w:document.body.clientWidth, h:document.body.clientHeight};
    }
    return null;
  },
  getObjectCoords:function(obj){
    var p=DOM.findPos(obj),
        objCoords={
          left   : p.left,
          top    : p.top,
          width  : obj.offsetWidth,
          height : obj.offsetHeight
        };

    Debug.dbg( objCoords );
    return objCoords;
  },
  create:function(tag, opts, append){
    if( document.createElement ){
      var obj=document.createElement(tag);
      if( append && append == true ){
        document.body.appendChild(obj);
      }

      for( var x in opts ){
        obj[x] = opts[x];
      }
      return obj;
    }
  },
  remove:function( obj ){
    if( document.createElement ){
      obj.parentNode.removeChild( obj );
    }
  }
}

var Debug={
  on:false,
  divId:'debug',
  div:null,
  d:function( obj, options ){
    var workingOptions={
      ignoreFunctions:false,
      regTest:null,
      depth:0
    };
    
    if( options ){
      for( var x in workingOptions ){
        if( options[x] ){
          workingOptions[x] = options[x];
        }
      }
    }

    if( typeof obj == 'string'){
      obj = getObj( obj );
    }
    var c=0,s='';
    for( var x in obj ){
      val = obj[x];
      if( workingOptions.ignoreFunctions && typeof obj[x] == 'function' ) {
        val = 'function()';
      } else if( workingOptions.depth > 0 && typeof obj[x] == 'object' ) {
        var tmpOptions = workingOptions;
        tmpOptions.depth--;
        val = '[' + Debug.d( val, tmpOptions ) + ']<br/>\n';
      }
      if( !workingOptions.regTest || workingOptions.regTest.test( x ) ){
        s += x + '=' + val + ( ++c % 4 == 0 ? "\n" : ' ' );
      }
    }
    return s;
  },
  dbg:function ( o ){
    if( !Debug.on ){
      return true;
    }
    if( !Debug.div ){
      Debug.div = DOM.create('div', {id:Debug.divId}, true);
      if( typeof window.event == 'undefined' ){
        Debug.div.style.position = 'fixed';
      }
    }
    if( typeof o != 'string' ){
      o = Debug.d( o );
    }
    Debug.div.innerHTML += o + "<br/>";
    Debug.div.scrollTop = Debug.div.scrollHeight;
  }
};

// Dynamic Document functions
var zoomSlider=null,
    pls=[];

function placeLinks(e){
  e = e || event;
  if( pls.length > 0 ){
    for( var i=0; i<pls.length; i++ ){
      Debug.dbg( 'Removing ' + i );
      pls[i].remove();
    }
    pls.length = 0;
  }
  for( var i=0;i<weblinks.length;i++ ){
    pls[pls.length]=new PlacedLinks( baseImage, zoomPercValue, weblinks[i].loc, weblinks[i].url, weblinks[i].title, {parentDiv:DOM.getObj('CurrentPage').parentNode}, weblinks[i].target );
  }

  var win = DOM.getWindowSize(),
      calcWidth = parseInt(pageWidth * zoomPercValue / 100);

  DOM.getObj('hashFixHide').style.display = 'none';
  var o =DOM.getObj('headerfixed');
  if( o ){
    o.style.width = (win.w - (window.event ? 0 : 20) ) + "px";
    DOM.getObj('header').style.width = ( win.w > calcWidth ? '' : calcWidth + 'px' );
    DOM.getObj('headerShadow').style.width = ( win.w > calcWidth ? '' : calcWidth + 'px' );
  }
}

function changePage( num ){
  if( num < 1 || num > lastPage || num == currentPage ){
    return false;
  }
  currentPage = num;
  // change location
  location.href = thisPage.replace( '[Zoom]', zoomValue ).replace( '[Page]', currentPage );
}

function changeSection( section, num ){
  /*if( num == currentPage ){
    location.href = '#' + section;
    toggleTOCmenu();
  } else {*/
    thisPage = thisPage.replace( /(search|keywords|email|print|resultpage)=[^&]+&?/ig, '' );
    location.href = thisPage.replace( '[Zoom]', zoomValue ).replace( '[Page]', num ) + 
      '&Section=' + section + '#' + section;
    
  //}
}

function prevPage(){
  changePage( currentPage - 1 );
}

function nextPage(){
  changePage( currentPage + 1 );
}

function setZoom( zoomAmount ){
  zoomSlider.setValue( parseInt(zoomAmount, 10) + 'x' );
  changeZoom( parseInt(zoomAmount, 10) + 'x' );
}

function toggleSearch(){
  var ns = DOM.getObj('keywordnonsearch'),
      s = DOM.getObj('keywordsearch');
  if( s.style.display == '' ){
    ns.style.display = '';
    s.style.display = 'none';
  } else {
    ns.style.display = 'none';
    s.style.display = '';
  }
}

function changeZoom( zoomAmount ){
  if( !zoomAmount ){
    zoomAmount = zoomSlider.getValue();
  }
  switch( zoomAmount ){
    case '4x':
      zoomValue = zoomAmount;
      zoomPercValue = 200;
      break;
    case '2x':
      zoomValue = zoomAmount;
      zoomPercValue = 150;
      break;
    default:
      zoomValue = '1x';
      zoomPercValue = 100;
  }
  DOM.getObj(baseImage).src = imageLocation.replace('[Page]', currentPage).replace('[Zoom]', zoomPercValue);
  DOM.getObj(baseImage).width = parseInt(pageWidth * zoomPercValue / 100);
  toggleZoom();
}

function findPage(obj){
  var n=obj.value,
      similarPage = -1;

  if( typeof pagesText != 'undefined' && pagesText.length ){
    for( var i=0; i<pagesText.length; i++ ){
      if( pagesText[i].t == n.toLowerCase() ){
        if( pagesText[i].p != currentPage ){
          changePage( pagesText[i].p );
        }
        return true;
      } else if ( similarPage == -1 && pagesText[i].t.indexOf( n.toLowerCase() ) == 0 ){
        similarPage = pagesText[i].p;
      }
    }
    if( similarPage != -1 ){
      changePage( similarPage );
      return true;
    }

    alert('Could not find page "' + n + '"' );
  } else {
    alert('Page file was not loaded.\nNothing to lookup.');
  } 
}

function toggleTOCmenu(){
  tocMenu.toggle();
}

function toggleLinks(){
  linkMenu.toggle();
}

function checkEnter(e){
  e = e || event;
  
  return ( ( e.which && e.which == 13 ) || ( e.keyCode && e.keyCode == 13 ) );
}

function toggleZoom(show){
  var z = DOM.getObj('zoommenu');

  // clearTimeout
  zoomMenuOver()
  z.onmouseover = zoomMenuOver;
  z.onmouseout = zoomMenuOut;
  if( typeof show == 'undefined' ){
    show = (z.style.display!='');
  }
  if( show ){
    ZoomTout = setTimeout("toggleZoom(false)", 3000);
  }
  z.style.display = (show?'':'none');
}

var ZoomTout;
function zoomMenuOver(e){
  if( ZoomTout ){
    ZoomTout = clearTimeout(ZoomTout);
  }
}
function zoomMenuOut(e){
  zoomMenuOver(e);
  ZoomTout = setTimeout("toggleZoom(false)", 1500);
}

function keywordSearch(keywords){
  href = thisPage.replace( '[Zoom]', zoomValue ).replace( '[Page]', currentPage );
  keywords = escape(keywords).replace(/%20/g,'+');
  if( /keywords=/i.test( href ) ){
    href = href.replace(/keywords=[^&]*/i, 'keywords=' + keywords );
  } else {
    href += '&keywords=' + keywords;
  }
  location.href = href;
}

// prototypes ...
if( !Array.prototype.push ){
  Array.prototype.push=function(){
    var l=this.length;
    for( var i=0; i<arguments.length; i++ ){
      this[l++] = arguments[i];
    }
    return true;
  }
}
if( !Array.prototype.push ){
  Array.prototype.pop=function(){
    var l=this.length,
        t = this[l];
    this.length--;
    return t;
  }
}
if( !Array.prototype.indexOf ){
  Array.prototype.indexOf = function( itm ){
    for( var i=0; i<this.length; i++ ){
      if( this[i] == itm ){
        return i;
      }
    }
    return -1;
  }
}