/*
Copyright (c) 2005 Zuavra.net

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

// check if browser supports everything needed
function SLIDE_general_support() {
  var d = document;
  var b = d.body;
  if (!b) return 1;
  if (!d.getElementById) return 2;
}

// check if named element supports everything needed
function SLIDE_element_support(elementName, checkLevel) {
  var d = document;
  var e = d.getElementById(elementName);
  if (!e) return 1;
  if (checkLevel=='basic') return 0;
  if (typeof(e.offsetTop)!='number') return 2;
  if (typeof(e.offsetHeight)!='number') return 3;
  if (checkLevel=='position') return 0;
  if (!e.style) return 4;
  if (typeof(e.style.top)!='string') return 5;
  if (typeof(e.style.position)!='string') return 6;
  return 0;
}

// how much window has scrolled
// courtesy of www.quirksmode.org
function SLIDE_scrollTop() {
  var d = document;
  if (self.pageYOffset) {
    // all except IE
    return self.pageYOffset;
  }
  else if (d.documentElement && d.documentElement.scrollTop) {
    // Explorer 6 Strict
    return d.documentElement.scrollTop;
  }
  else {
    // all other Explorers
    var b = d.body;
    return b.scrollTop;
  }
}

// viewport height
// courtesy of www.quirksmode.org
function SLIDE_clientHeight() {
  var d = document;
  if (self.innerHeight) {
    // all except Explorer
    return self.innerHeight;
  }
  else if (d.documentElement && d.documentElement.clientHeight) {
    // Explorer 6 Strict Mode
    return d.documentElement.clientHeight;
  }
  else {
    // other Explorers
    var b = d.body;
    return b.clientHeight;
  }
}

// function that updates the slider position
function SLIDE_update(sliderName, containerName, slideSpeed, updateInterval, breakerName, cDelta) {
  // grab elements
  var d = document;
  var slider = d.getElementById(sliderName);
  var container = d.getElementById(containerName);
  if (breakerName) var breaker = d.getElementById(breakerName);
  // init slider position
  var topStopper = container.offsetTop + cDelta;
  var wantedPosition = topStopper;
  // determine would-be position in regard to viewport
  var clientHeight = SLIDE_clientHeight();
  var scrollTop = SLIDE_scrollTop();
  // if element is shorter than or equal with the viewport
  if (slider.offsetHeight <= clientHeight) {
    // align element top margin with viewport top margin
    wantedPosition = scrollTop;
  }
  // if element is bigger than the viewport
  else {
    // if element top margin is lower than the viewport top margin
    if (scrollTop < slider.offsetTop) {
      // align element top margin with top viewport margin
      wantedPosition = scrollTop;
    }
    // if element bottom margin is higher than the bottom viewport margin
    else if (scrollTop + clientHeight > slider.offsetTop + slider.offsetHeight) {
      // align element bottom margin with bottom viewport margin
      wantedPosition = scrollTop + clientHeight - slider.offsetHeight;
    }
    else {
      // we're in the middle, and the element is taller than the viewport, leave as it is
      wantedPosition = slider.offsetTop;
    }
  }
  // next, we have to adjust position in regard to container
  // did the slider go up past the top of the container?
  if (wantedPosition < topStopper) {
    wantedPosition = topStopper;
  }
  else {
    // did the slider go down past the bottom of the container?
    if (wantedPosition + slider.offsetHeight >= topStopper + container.offsetHeight) {
      wantedPosition = topStopper + container.offsetHeight - slider.offsetHeight;
    }
    else {
      // slider is in the visible area with either both margins or none
      // no adjustment needed, let user scroll it normally
    }
  }
  // if there's a breaker, use it
  if (breaker) {
    if (wantedPosition + slider.offsetHeight > breaker.offsetTop) {
      wantedPosition = breaker.offsetTop - slider.offsetHeight;
    }
  }
  // adjust jump according to requested speed
  if (slideSpeed != 0) {
    var delta = Math.ceil(Math.abs(slider.offsetTop - wantedPosition) * slideSpeed);
    wantedPosition = (slider.offsetTop > wantedPosition) ? slider.offsetTop - delta : slider.offsetTop + delta;
  }
  // ** SWITCH FROM ABSOLUTE (PAGE VALUE) TO RELATIVE (INSIDE CONTAINER) VALUE **
  var wPold = wantedPosition;
  relativePosition = wantedPosition - topStopper;
  // sanity checks
  // did it pass over the top margin of the container?
  if (relativePosition < 0)  {
    relativePosition = 0;
  }
  // did it pass over the lower margin of the container?
  if (relativePosition + slider.offsetHeight > container.offsetHeight) {
    relativePosition = container.offsetHeight - slider.offsetHeight;
  }
  // set the new position
  slider.style.top = relativePosition + 'px';
  // detect anomalies; most likely user resized fonts
  if (wantedPosition != slider.offsetTop) {
    // recalculate cDelta
    cDelta = slider.offsetTop - container.offsetTop;
    // force a reset jump
    slider.style.top = '0px'; 
  }
  //debugging
  /*window.status=
  'rP='+relativePosition
  +', wP='+wantedPosition
  +(wantedPosition!=slider.offsetTop?'*':'')
  +', c.oT='+container.offsetTop
  +', s.oT='+slider.offsetTop
  +', s.oH='+slider.offsetHeight
  +', tS='+topStopper
  +', cH='+clientHeight
  +', sT='+scrollTop
  +', cD='+cDelta
  ;*/
  // set hook to call myself again later; this is better than calling myself directly,
  // because the used memory is freed and reallocated, rather than allocated over and over
  setTimeout("SLIDE_update('"+sliderName+"','"+containerName+"',"+slideSpeed+","+updateInterval+",'"+breakerName+"',"+cDelta+")", updateInterval);
}

// function that tests slider data and launches it if it checks out
function SLIDE_launch_slider(sInfo) {
  // init vars
  var d = document;
  var er = 0;
  // test and init slider
  er = SLIDE_element_support(sInfo[0], 'style');
  if (er) return 0;
  s = d.getElementById(sInfo[0]);
  // test and init container
  er = SLIDE_element_support(sInfo[1], 'position');
  if (er) return 0;
  var c = d.getElementById(sInfo[1]);
  // test and init breaker
  if (sInfo[4]) {
    er = SLIDE_element_support(sInfo[4], 'position');
    if (er) return 0;
    var b = d.getElementById(sInfo[4]);
  }
  else {
    var b = false;
  }
  // force relative positioning
  s.style.position = 'relative';
  // launch slider
  SLIDE_update(sInfo[0], sInfo[1], sInfo[2], sInfo[3], sInfo[4], s.offsetTop - c.offsetTop);
}
