/*
//////////////////////////////////////////////////////////////////////////////
// 
// Copyright (c) March 2005
// 
// All rights reserved. This material contains unpublished,
// copyrighted work, which includes confidential and proprietary
// information of HyperTrust NV
// 
// HyperTrust NV, Geldenaaksebaan 329, 3001 Leuven, Brabant, BELGIUM
// 
// $Revision: $
// Last modified by $Author: $ on $Date:  $
// 
///////////////////////////////////////////////////////////////////////////////
*/

//-----------------------------------------------------------------------------
// Constructor
function Slider(i_name, i_default_value, i_slider_button)
{
  // members
  this.leftValue        = 10;
  this.rightValue       = 1; 
  this.defaultValue     = i_default_value;
  this.offsetX          = -4;
  this.offsetY          = -7;
  this.maxSlide         = 100;
  this.buttonWidth      = 8;
  this.buttonHeight     = 16;
  this.buttonImg        = i_slider_button;
  this.buttonHiliteImg  = i_slider_button;
  this.buttonHoverImg   = null;
  this.imgPath          = "";

  // functions
  this.Write            = Slider_Write;
  this.Place            = Slider_Place;
  this.MakeEventHandler = Slider_MakeEventHandler;
  this.getValue         = Slider_GetValue;
  this.setValue         = Slider_SetValue;

  // Events
  this.MouseOver        = Slider_MouseOver;
  this.MouseOut         = Slider_MouseOut;
  this.MouseDown        = Slider_MouseDown;
  this.MouseUp          = Slider_MouseUp;
  this.MouseSlide       = Slider_MouseSlide;

  this.onmouseover = null;
  this.onmouseout = null;
  this.onmousedown = null;
  this.onmouseup = null;
  this.onslide = null;
  this.onchange = null;
  this.onclick = null;

  if (!window.sliders)
    window.sliders = new Array();

  this.name = i_name || "slider" + window.sliders.length;
  window.sliders[window.sliders.length] = this;
  window.sliders[this.name] = this;
  if (!window.sliderDrag)
    window.sliderDrag = new Object();
}

//-----------------------------------------------------------------------------
// method write the button DIV
function Slider_Write()
{
  var proto = this.prototype || this;

  // create images for the prototype, if not already set
  if (!proto.loImg)
  {
    proto.loImg = new Image(proto.buttonWidth,proto.buttonHeight);
    proto.loImg.src = proto.imgPath + proto.buttonImg;
    if (proto.buttonHiliteImg)
    {
      proto.hiImg = new Image(proto.buttonWidth,proto.buttonHeight);
      proto.hiImg.src = proto.imgPath + (proto.buttonHiliteImg || proto.buttonImg);
    }
    if (proto.buttonHoverImg)
    {
      proto.hoImg = new Image(proto.buttonWidth,proto.buttonHeight);
      proto.hoImg.src = proto.imgPath + proto.buttonHoverImg;
    }
  }
  // set the properties according to the prototype
  if (proto != this)
  {
    this.loImg = proto.loImg;
    if (proto.hiImg)
      this.hiImg = proto.hiImg;
    if (proto.hoImg)
      this.hoImg = proto.hoImg;
    this.maxSlide = proto.maxSlide;
  }

  // style for the slider button
  var style = '<STYLE TYPE="text/css"><!--\n' +
      '#'+this.name+'Button {visibility:hidden; position:absolute; width:'+ proto.buttonWidth +'px; height:'+ proto.buttonHeight +'px; z-index:1; }\n' +
      '--></STYLE>';

  // html for the button div
  var content = '<DIV ID="'+this.name+'Button">'+
      '<IMG ID="'+this.name+'ButtonImg" SRC="'+proto.loImg.src+'" WIDTH='+proto.buttonWidth+' HEIGHT='+proto.buttonHeight+'>'+
      '</DIV>';

  // write the button style and content in the document
  if (document.getElementById || document.layers || document.all)
  {
    document.writeln(style);
    document.writeln(content);
  }

  // set button properties and mouse event handlers
  if (document.layers)
  {
    // NS4 code
    this.button = document.layers[this.name+"Button"];
    this.button.img = this.button.document.images[0];
    this.button.clip.width = proto.buttonWidth;
    this.button.clip.height = proto.buttonHeight;
    this.button.captureEvents(Event.MOUSEOVER|Event.MOUSEDOWN|Event.MOUSEOUT);
    this.button.onmousedown = this.MouseDown;
    this.button.onmouseout = this.MouseOut;
    this.button.onmouseover = this.MouseOver;
   }
   else if (document.all)
   { 
    // IE code
    this.button = document.all[this.name+"Button"];
    this.button.img = document.all[this.name+"ButtonImg"];
    this.button.style.pixelWidth = proto.buttonWidth;
    this.button.style.pixelHeight = proto.buttonHeight;
    this.button.onmousedown = this.MouseDown;
    this.button.onmouseout = this.MouseOut;
    this.button.onmouseover = this.MouseOver;
  }
  else if (document.getElementById)
  { 
    // W3DOM code
    this.button = document.getElementById(this.name+"Button");
    this.button.img = document.getElementById(this.name+"ButtonImg");
    this.button.style.width = proto.buttonWidth + 'px';
    this.button.style.height = proto.buttonHeight + 'px';
    this.button.addEventListener("mousedown",this.MouseDown,false);
    this.button.addEventListener("mouseout",this.MouseOut,false);
    this.button.addEventListener("mouseover",this.MouseOver,false);
  }
  // set event handlers as functions
  this.onmouseover = this.MakeEventHandler(this.onmouseover);
  this.onmouseout  = this.MakeEventHandler(this.onmouseout);
  this.onmousedown = this.MakeEventHandler(this.onmousedown);
  this.onmouseup   = this.MakeEventHandler(this.onmouseup);
  this.onslide     = this.MakeEventHandler(this.onslide);
  this.onchange    = this.MakeEventHandler(this.onchange);
  this.onclick     = this.MakeEventHandler(this.onclick);

  // tell button who we are
  this.button.slider = this;

  // from now on button refers to the style object in IE and W3DOM
  if (document.all || document.getElementById)
    this.button = this.button.style;
}

//-----------------------------------------------------------------------------
// method to put the slider button in place
function Slider_Place(imgName, layer)
{
  var proto = this.prototype || this;

  // for NS4 refer to document of layer containing slider rail
  var doc = (document.layers && layer)? ((typeof(layer) == 'string')? document.layers[layer].document : layer.document) : document;

  // set name or default name
  imgName = imgName || this.name+'RailImg';

  // find the rail image
  this.rail = (typeof(imgName) == 'string')? doc.images[imgName] : imgName;

  // offset w.r.t rail
  var x = proto.offsetX;
  var y = proto.offsetY;

  // add global position of rail and parents in global document to the offset
  if (this.rail.offsetParent)
  {
    var parent = this.rail;
    while (parent)
    {
      x += parent.offsetLeft;
      y += parent.offsetTop;
      parent = parent.offsetParent;
    }
    // Fix for IE 5 for Mac
    if (navigator.userAgent.indexOf("MSIE")+1 && navigator.userAgent.indexOf("Mac")+1 && !(navigator.userAgent.indexOf("Opera")+1))
    {
      x += parseInt(document.body.currentStyle.marginLeft);
      y += parseInt(document.body.currentStyle.marginTop);
    }
  }
  else
  {
    x += (typeof(this.rail.pageX) == 'number')? this.rail.pageX : this.rail.x;
    y += (typeof(this.rail.pageY) == 'number')? this.rail.pageY : this.rail.y;
    if (layer && document.layers)
    {
      x += layer.pageX;
      y += layer.pageY;
    }
  }

  // set position of button
  if (document.layers)
  {
    this.button.left = x;
    this.button.top = y;
  }
  else if (document.all || document.getElementById)
  {
    this.button.left = x + 'px';
    this.button.top = y + 'px';
  }

  // offset is remembered for later sliding
  this.offset = x;

  // put button in default position and make visible
  this.setValue(this.defaultValue);
  this.button.visibility = 'inherit';
}

//-----------------------------------------------------------------------------
// mouseover handler of the button, only calls handler of slider
function Slider_MouseOver(e)
{
  window.sliderDrag.isOver = true;
  if (this.slider.hoImg && !window.sliderDrag.isDown)
    this.img.src = this.slider.hoImg.src;   
  if (this.slider.onmouseover)
    this.slider.onmouseover(e);
}

//-----------------------------------------------------------------------------
// mouseout handler of the button, only calls handler of slider
function Slider_MouseOut(e)
{
  window.sliderDrag.isOver = false;
  if (this.slider.hoImg && !window.sliderDrag.isDown)
    this.img.src = this.slider.loImg.src;   
  if (this.slider.onmouseout)
    this.slider.onmouseout(e);
}

//-----------------------------------------------------------------------------
// mousedown handler of the button
function Slider_MouseDown(e)
{
  var slider = this.slider;

  // remember me
  window.sliderDrag.dragLayer = this;
  window.sliderDrag.dragged = false;
  window.sliderDrag.isDown = true;

  // event position
  var evtX = evtY = 0;
  if (!e) e = window.event;
  if (typeof(e.pageX) == 'number')
  {
    evtX = e.pageX;
    evtY = e.pageY;
  }
  else if (typeof(e.clientX) == 'number')
  {
    evtX = e.clientX + (document.body.scrollLeft || 0);
    evtY = e.clientY + (document.body.scrollTop || 0);
  }

  // ignore right mouse button
  if ((e.which && e.which == 3) || (e.button && e.button == 2))
    return true;

  // set starting offset of event
  if (document.layers)
  {
    // NS4 code
    window.sliderDrag.offX = evtX - this.left + slider.offset;
    window.sliderDrag.offY = evtY - this.top + slider.offset;
  }
  else if (document.all || document.getElementById)
  {
    // IE and W3DOM code
    window.sliderDrag.offX  =  evtX - parseInt(this.style.left) + slider.offset;
    window.sliderDrag.offY  =  evtY - parseInt(this.style.top) + slider.offset;
    if (e.cancelable)
      e.preventDefault();
    if (e.stopPropagation)
      e.stopPropagation();

    e.cancelBubble = true; 
  }

  // document handles move and up events
  document.onmousemove = slider.MouseSlide;
  document.onmouseup = slider.MouseUp;

  // capture events in NS4
  if (document.captureEvents)
    document.captureEvents(Event.MOUSEMOVE|Event.MOUSEUP);

  // show hilite img
  if (slider.hiImg)
    this.img.src = slider.hiImg.src;

  // call event handler of slider
  if (slider.onmousedown)
    slider.onmousedown(e);

  return false;
}

//-----------------------------------------------------------------------------
// mouseup handler of the button
function Slider_MouseUp(e)
{
  // button and slider that was draged
  var l = window.sliderDrag.dragLayer;
  var slider = l.slider;
  window.sliderDrag.isDown = false;

  // cancel move and up event handlers of document
  document.onmousemove = null;
  document.onmouseup = null;

  // release them in NS4
  if (document.releaseEvents)
    document.releaseEvents(Event.MOUSEMOVE|Event.MOUSEUP);
  window.sliderDrag.dragLayer = null;

  // show normal image
  if (slider.hiImg) 
    l.img.src = (window.sliderDrag.isOver && slider.hoImg)? slider.hoImg.src : slider.loImg.src;

  // cal event handlers of slider
  if (slider.onmouseup)
    slider.onmouseup(e);
  if (window.sliderDrag.dragged)
    if (slider.onchange) slider.onchange(e);
  else if (slider.onclick)
    slider.onclick(e);

  return false;
}

//-----------------------------------------------------------------------------
// mousemove handler of the button for sliding
function Slider_MouseSlide(e)
{
  // button and slider to be draged
  var l = window.sliderDrag.dragLayer;
  var slider = l.slider;

  // we have dragged the slider; for click
  window.sliderDrag.dragged = true;

  // event position
  var evtX = evtY = 0;
  if (!e) e = window.event;
  if (typeof(e.pageX) == 'number')
  {
    evtX = e.pageX;
    evtY = e.pageY;
  }
  else if (typeof(e.clientX) == 'number')
  {
    evtX = e.clientX + (document.body.scrollLeft || 0);
    evtY = e.clientY + (document.body.scrollTop || 0);
  }
  var pos = Math.max(Math.min(evtX - window.sliderDrag.offX,slider.maxSlide),0) + slider.offset;

  // move slider. 
  if (document.layers)
    // NS4 code 
    l.left = pos;

  else if (document.all || document.getElementById)
  {
    // IE and W3DOM code
    l.style.left = pos + 'px';

    if (e.cancelable)
      e.preventDefault();
    if (e.stopPropagation)
      e.stopPropagation();
    e.cancelBubble = true;
  }

  // call slider event handlers
  if (slider.onchange)
    slider.onchange(e);
  if (slider.onslide)
    slider.onslide(e);

  return false;
}

//-----------------------------------------------------------------------------
// calculate the value of the slider from position
function Slider_GetValue(n)
{
  var pos = parseInt(this.button.left);
  var val = this.leftValue + (this.rightValue - this.leftValue) * (pos-this.offset) / this.maxSlide;
  return (typeof(n) == 'number') ? _ToDecimals(val,n) :  val;
}

//-----------------------------------------------------------------------------
// set the position of the slider from a value
function Slider_SetValue(value, i_ignore)
{
  if (typeof(value) == 'string')
    value = parseFloat(value);
  if (isNaN(value))
    value = this.defaultValue;

  // set within min/max bounds
  var rangeValue = (this.rightValue >= this.leftValue)? 
      Math.min(Math.max(value,this.leftValue),this.rightValue) - this.leftValue : 
      Math.max(Math.min(value,this.leftValue),this.rightValue) - this.leftValue;
  var pos = this.maxSlide * rangeValue / (this.rightValue-this.leftValue) + this.offset;

  // move button to calculated position
  if (document.layers)
    // NS4 code
    this.button.left = pos;
  else if (document.all || document.getElementById)
    // IE and W3DOM code
    this.button.left = pos;

  // call slider event handler, unless ignore is true
  if (this.onchange && (!i_ignore))
    this.onchange(null);
}

//-----------------------------------------------------------------------------
// make an event handler, ensuring that it is a function
function Slider_MakeEventHandler(i_function)
{
  return (typeof(i_function) == 'string') ? new Function('e', i_function) : ((typeof(i_function) == 'function')? i_function : null);
}

//-----------------------------------------------------------------------------
// return a value as a string with a fixed number of decimals
function _ToDecimals(i_val, i_number_decimals)
{
  if (isNaN(i_number_decimals))
    return i_val;

  for (var i=0; i<i_number_decimals; i++)
    i_val *= 10;
  for (var i=0; i>i_number_decimals; i--)
    i_val *= 0.1;

  i_val = Math.round(i_val);
  if (i_val < 0)
  {
    i_val = -i_val;
    var sgn = "-";
  }
  else
  {
    var sgn = "";
  }

  var valstr = i_val.toString();
  if (i_number_decimals > 0)
  {
    while (valstr.length <= i_number_decimals)
      valstr = "0" + valstr;
    var len = valstr.length;
    valstr = valstr.substring(0, len - i_number_decimals) + "." + valstr.substring(len - i_number_decimals, len);
  }
  else if (i_number_decimals < 0)
  {
    for (i=0; i>i_number_decimals; i--)
      valstr = valstr + "0";
  }

  return sgn + valstr;
}
