// HSlider.js
// Javascript Behaviour for the HSlider Control
// Copyright (c) by Matthias Hertel, http://www.mathertel.de
// This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx
// ----- 
// 17.09.2005 PropHSlider was created by Matthias Hertel
// 25.08.2007 HSlider was created from PropHSlider
// 18.12.2007 Simplifications and documentation.
// 06.01.2008 documentation and simplifications

jcl.HSliderBehavior = {
/// <summary>This control implements is a horizontal moveable rectangle that acts as a slider.
/// It can be attached to an OpenAjax event and acts as a subscriber and publisher.</summary>
/// <example>A page that uses this control ist available at:<br />
/// <a href="http://www.mathertel.de/AjaxEngine/S03_AJAXControls/ConnectionsTestPage.aspx">
/// http://www.mathertel.de/AjaxEngine/S03_AJAXControls/ConnectionsTestPage.aspx</a></example>

_knob: null, /// <summary>Reference to the movable knob obj.</summary>
_lastValue: -1, /// <summary>last published value to avoid doublicate events.</summary>
_x: 0, /// <summary>Offset between mouse and the knob.</summary>
_maxright: 0, /// <summary>rightmost position of the knob.</summary>
_xOffset: 0, /// <summary>x-offset of the region the knob is allowed to be moved.</summary>

minvalue:0, /// <summary>The value that is reached on the leftmost position of the knob.</summary>
maxvalue:100, /// <summary>The value that is reached on the rightmost position of the knob.</summary>
unit:1, /// <summary>The unit of the oublished values. All values can be divided by this value without any reminder
        /// if the value is determined by using the HSlider.</summary>

eventname: "", /// <summary>The local or complete event name that is used for publishing OpenAjax events.</summary>

init: function () {
  /// <summary>Initialze the JavaScript control.</summary>
  this._removeTextNodes(this);
  
  this.eventname = jcl.BuildFullEventname(this);

  if (this.eventname) {
    OpenAjax.hub.subscribe(this.eventname, this._handleEvent, this);
  } // if

  // find the moveable knob
  this._knob = jcl.getElementsByClassName(this, "knob")[0];
  this._removeTextNodes(this._knob.parentNode);

  this._maxright = this.offsetWidth - 32 - this._knob.offsetWidth;

  this.minvalue = parseInt(this.minvalue);
  this.maxvalue = parseInt(this.maxvalue);
  this.unit = parseInt(this.unit);
}, // init


// --- events

onmousedown: function (evt) {
  /// <summary>Handle the event when the mouse button is pressed.</summary>
  evt = evt || window.event;
  var src = evt.srcElement;
  var left = this._lastValue;

  if (src.className == "knob") {
    this.MoveStart(evt);

  } else if (src.className == "minus") {
    left = parseInt(left) - this.unit

  } else if (src.className == "plus") {
    left = parseInt(left) + this.unit
  } // if

  if (left != this._lastValue) {
    if ((this.eventname != null) && (this.eventname != "")) {
      OpenAjax.hub.publish(this.eventname, left);
    } // if
    this._lastValue = left;
  } // if
}, // onmousedown


_onmousemove: function (evt) {
/// <summary>Handle the mouse button move event. This handler will be attached to the document level.</summary>
  evt = evt || window.event;
  jcl.currentMoving.MoveIt(evt);
}, // onmousemove


_onmouseup: function (evt) {
/// <summary>Handle the mouse button up event. This handler will be attached to the document level.</summary>
  evt = evt || window.event;
  jcl.currentMoving.MoveEnd(evt);
}, // onmouseup


// --- methods

MoveStart: function (evt) {
/// <summary>Start sliding the knob.</summary>
  this._xOffset = 0;
  var obj = this._knob.offsetParent;
  while (obj != null) {
    this._xOffset += obj.offsetLeft;
    obj = obj.offsetParent;
  } // while

  // calculate mousepointer-knob delta
  this._x = evt.clientX - (this._knob.offsetLeft + this._xOffset);

  jcl.currentMoving = this; // make it globally evailable when mouse is leaving this object.
  jcl.AttachEvent(document, "onmousemove", this._onmousemove);
  jcl.AttachEvent(document, "onmouseup", this._onmouseup);
  // cancel selecting anything
  evt.cancelBubble = true;
  evt.returnValue = false;
}, // MoveStart


MoveIt: function (evt) {
/// <summary>Move the knob element and eventually publish a new event.</summary>
  var left = evt.clientX - this._x - this._xOffset;
  left = Math.min(this._maxright, Math.max(0, left));
  this._knob.style.left = left + "px";

  left = Math.round(left * (this.maxvalue - this.minvalue) / this._maxright + this.minvalue);
  left = Math.round(left / parseInt(this.unit)) * parseInt(this.unit);

  if (left != this._lastValue) {
    if ((this.eventname != null) && (this.eventname != "")) {
      OpenAjax.hub.publish(this.eventname, left);
    } // if

  } // if

  this._lastValue = left;
  // cancel selecting anything
  evt.cancelBubble = true;
  evt.returnValue = false;
}, // MoveIt


MoveEnd: function () {
/// <summary>Handle the end of a moving gesture.</summary>
  if (this._knob != null) {
    jcl.DetachEvent(document, "onmousemove", this._onmousemove);
    jcl.DetachEvent(document, "onmouseup", this._onmouseup);
    jcl.currentMoving = null;
  } // if
}, // MoveEnd


// --- OpenAjax event handler ---

_handleEvent: function (eventName, eventData) {
/// <summary>Handle OpenAjax events.</summary>
  var knob = this._knob;
  if ((knob != null) && (this._lastValue != eventData)) {
    this._lastValue = eventData;
    eventData = eventData - this.minvalue;
    eventData = Math.round(eventData * this._maxright / (this.maxvalue - this.minvalue));
    eventData = Math.min(this._maxright, Math.max(0, eventData));
    knob.style.left = eventData + "px";
  } // if
}, // _handleEvent


_removeTextNodes: function (n) {
/// <summary>remove all textnodes from the control to avoid unwanted spaces.</summary>
  var obj = n.firstChild;
  while (obj != null) {
    var nextObj = obj.nextSibling;
    if (obj.nodeType == 3)
      obj.parentNode.removeChild(obj);
    obj = nextObj;
  } // while
} // _removeTextNodes

} // jcl.HSliderBehavior
