/****************************************************************************
 * Copyright (c) 1998-2007 Luna Imaging, Inc.  All Rights Reserved.
 *
 * This software is confidential and proprietary information of
 * Luna Imaging, Inc.  ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Luna Imaging, Inc.
 *
 * The software may not be copied, reproduced, translated or reduced to
 * any electronic medium or machine-readable form without
 * the prior written consent of Luna Imaging.
 *
 * You are not allowed to distribute the binary and source code
 * (if released) to third parties, without the prior written consent from
 * Luna Imaging.
 *
 * You are not allowed to reverse engineer, disassemble or decompile
 * code, or make any modifications of the binary or source code, remove
 * or alter any trademark, logo, copyright or other proprietary notices,
 * legends, symbols, or labels in the Software.
 *
 * You are not allowed to sub-license the Software or any derivative
 * work based on or derived from the Software.
 *
 * LUNA IMAGING MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT
 * NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
 * A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, LUNA IMAGING SHALL NOT BE
 * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, 
 * MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 *  
 *  cruiz10020@yahoo.com
 *
 *  Slider.js
 *
 *  Description:
 *    Slider with integer values
 *
 *  Structure:
 *
 *
 *  Requires:
 *    prototype.js - http://www.prototypejs.org/
 *
 *  Development History:
 *    7-26-2007       - created
 *
 *******************************************************************************/


function Slider( functionNotifyOfChange )
{
  // html elemnts
  this.mContainer;
  this.mBody;
  this.mSegments;
  this.mSlider;
  this.mIncrementButton;
  this.mDecrementButton;
  this.mGlassPlate;
  
  // attributes
  this.mSegmentRange = null;
  this.mValue = null;
  this.mFunctionNotifyOfChange = functionNotifyOfChange;
  
  // flags
  this.mSlideInProgress = null;
  this.mReverseScale = true;
  this.mAnimate = true;
  
  this.SEGMENT_CLASSNAME = 'sliderSegment';
  this.INCREMENT_CLASSNAME = 'sliderIncrement';
  this.DECREMENT_CLASSNAME = 'sliderDecrement';
  this.SLIDER_CLASSNAME = 'slider';
  
  this.SLIDER_OPACITY = .75;
  
  this.SEGMENT_DIMENSIONS = $( [ 20, 17 ] );
  
  
  this.init = function()
  {
    this.mBody = $( document.createElement( 'div' ) );
    this.mSegments = $( document.createElement( 'div' ) );
    this.mSlider = $( document.createElement( 'div' ) );
    this.mIncrementButton = $( document.createElement( 'div' ) );
    this.mDecrementButton = $( document.createElement( 'div' ) );
    
    // set up references to aide events
    this.mBody.slider = this;
    this.mSegments.slider = this;
    this.mSlider.slider = this;
    this.mIncrementButton.slider = this;
    this.mDecrementButton.slider = this;
    
    // add classnames
    this.mSlider.addClassName( this.SLIDER_CLASSNAME );
    this.mIncrementButton.addClassName( this.INCREMENT_CLASSNAME );
    this.mDecrementButton.addClassName( this.DECREMENT_CLASSNAME );    
    
    // put it all together
    this.mBody.appendChild( this.mSlider );
    this.mBody.appendChild( this.mDecrementButton );
    this.mBody.appendChild( this.mSegments );
    this.mBody.appendChild( this.mIncrementButton );
    jshSetOpacity( this.mBody, this.SLIDER_OPACITY );
    
    // add it to the container
    this.mContainer.appendChild( this.mBody );
    
    // events
    this.mSlider.onmousedown = Static_Slider_StartDrag;
    this.mSlider.onmousemove = Static_Slider_Drag;
    this.mSlider.onmouseup = Static_Slider_EndDrag;
    
    this.mDecrementButton.onclick = Static_Slider_PreviousValue;
    this.mIncrementButton.onclick = Static_Slider_NextValue;

    // stylings
    this.mSlider.style.position = 'absolute'; 
    this.mSlider.style.left = 0 + 'px';
    this.mSlider.style.top = 0 + 'px';
    this.mSlider.style.zIndex = '10000';
    this.mSlider.style.height = this.SEGMENT_DIMENSIONS[1] + 'px';
    
    
    this.mDecrementButton.style.position = 'absolute';
    this.mDecrementButton.style.left = 0 + 'px';
    this.mDecrementButton.style.top = 0 + 'px';
    this.mDecrementButton.style.height = this.SEGMENT_DIMENSIONS[1] + 'px';
    
    this.mSegments.style.position = 'absolute';
    this.mSegments.style.left = this.mDecrementButton.getWidth() + 'px';
    this.mSegments.style.top = 0 + 'px';
    this.mSegments.style.height = this.SEGMENT_DIMENSIONS[1] + 'px';
    
    this.mIncrementButton.style.position = 'absolute';
    this.mIncrementButton.style.right = 0 + 'px';
    this.mIncrementButton.style.top = 0 + 'px';
    this.mIncrementButton.style.height = this.SEGMENT_DIMENSIONS[1] + 'px';
    
    this.constructSegments();
    
    this.mBody.style.position = 'absolute';
    this.mBody.style.width = ( this.mDecrementButton.getWidth() + this.mSegments.getWidth() + this.mIncrementButton.getWidth() ) + 'px';
    this.mBody.style.height = this.SEGMENT_DIMENSIONS[1] + 'px';
    this.mBody.style.overflow = 'hidden';
    
    // move it to the default location
    this.reposition();
    this.setValue( this.mValue );
  };
  
  /**
   * Constrcuts a segment on the slider
   */
  this.constructSegments = function()
  {
    if( this.mSegmentRange )
    {
      var index = 0;
      var segment;
      var positionX;
      for( var i = this.mSegmentRange[0]; i <= this.mSegmentRange[1]; i++ )
      {
        segment = $( document.createElement( 'div' ) );
        segment.addClassName( this.SEGMENT_CLASSNAME );
        segment.slider = this;
       
        this.mSegments.appendChild( segment );
        positionX = ( index * this.SEGMENT_DIMENSIONS[ 0 ] );
        
        segment.style.position = 'absolute';
        segment.style.left = positionX + 'px';
        segment.style.top = 0 + 'px';
        segment.style.width = this.SEGMENT_DIMENSIONS[0] + 'px';
        segment.style.height = this.SEGMENT_DIMENSIONS[1] + 'px';
        
        if( this.mReverseScale == true )
        {
          segment.mSegmentValue = this.mSegmentRange[1] - index;
        }
        else
        {
          segment.mSegmentValue = i;
        }
        
        segment.onclick = Static_Slider_JumptTo;
        
        //segment.title = 'segment: ' + segment.mSegmentValue;        
        index++;
      }
      
      // resize it to display all segements
      this.mSegments.style.width = ( this.SEGMENT_DIMENSIONS[0] * index ) + 'px';
    }
  };
  
  this.render = function( element, glassPlate, segmentRange, startStringValue )
  {
    if( element && segmentRange )
    {
      this.setSegmentRange( segmentRange );
      this.mValue = startStringValue;
      this.mGlassPlate = glassPlate;
      this.mContainer = element;
      this.init();
    }
  };
  
  /**
   * If true the panel will animate certain actions like close and open
   */
  this.setAnimate = function( animate )
  {
    this.mAnimate = animate;
  }
  
  this.setSegmentRange = function( segmentRange )
  {
    this.mSegmentRange = segmentRange
  };
  
  this.setValue = function( newValue, notify )
  {
    // make sure its in bounds
    newValue = Math.max( newValue, this.mSegmentRange[0] );
    newValue = Math.min( newValue, this.mSegmentRange[1] );
    
    // set the value
    this.mValue = newValue;
    
    this.moveSliderTo( this.mValue );
    
    if( this.mFunctionNotifyOfChange && ( notify != false ) )
    {
      this.mFunctionNotifyOfChange( this.mValue );
    }
  };
  
  this.nextValue = function()
  {
    if( this.mReverseScale )
    {
      this.setValue( this.mValue - 1 );
    }
    else
    {
      this.setValue( this.mValue + 1 );
    }
  }
  
  this.previousValue = function()
  {
    if( this.mReverseScale )
    {
      this.setValue( this.mValue + 1 );
    }
    else
    {
      this.setValue( this.mValue - 1 );
    }
  }
  
  this.moveSliderTo = function( value )
  {
    if( ( value >= this.mSegmentRange[0] ) && 
        ( value <= this.mSegmentRange[1] ) )
    {
      var segment = null;
      var children = this.mSegments.childNodes;
      for( var i = 0; i < children.length; i++ )
      {
        if( children[i] && ( children[i].mSegmentValue == value ) )
        {
          segment = children[i];
          break;
        }
      }
      
      if( segment )
      {        
        // calc the left offset, make sure its centered on the segment
        var offset = parseInt( segment.style.left );
        var x = offset + this.mDecrementButton.getWidth(); 
        x += ( this.SEGMENT_DIMENSIONS[0] / 2 );
        x -= ( this.mSlider.getWidth() / 2 );
        
        //this.mSlider.title = value;
        
        this.mSlider.style.left = Math.round( x ) + 'px';
        this.mSlider.style.top = 0 + 'px';
      }
    }
  };
  
  
  this.moveTo = function( location )
  {
    var x = Math.max( location[0], 0 );
    var y = Math.max( location[1], 0 );
    
    this.mBody.style.left = x + 'px';
    this.mBody.style.top = y + 'px';
  };
  
  this.reposition = function()
  {
    if( this.mContainer )
    {
      var x = Math.round( ( this.mContainer.getWidth() / 2 ) - ( this.mBody.getWidth() / 2 ) );
      var y = Math.round( ( 2.3 * this.mContainer.getHeight() / 3 ) - ( this.mBody.getHeight() / 2 ) );
      
      this.moveTo( [ x, y ] );
    }
  };
  
  this.showControls = function()
  {
    if( this.mSegments && this.mSegments.childNodes && this.mSegments.childNodes.length > 0 )
    {
      if( this.mAnimate == true )
      {
        jshFadeElement( this.mBody, 100, 30, true, this.SLIDER_OPACITY );
      }
      else
      {
        this.mBody.show();
      }
    }
  };
  
  this.hideControls = function()
  {
    if( this.mAnimate == true )
    {
      jshFadeElement( this.mBody, 100, 30, false );
    }
    else
    {
      this.mBody.hide()
    }
  };
    
}

function Static_Slider_EndDrag( e, cancelAction )
{
  e = jshGetEvent( e );
  var sourceElement = jshGetSourceElement( e );

  if( sourceElement && sourceElement.slider )
  {
    var slider = sourceElement.slider;
    if( slider.mSlideInProgress == true )
    {
      slider.mSlideInProgress = null;
      
      slider.mBody.onmousemove = null;
      slider.mBody.onmouseup = null;
      
      if( slider.mGlassPlate )
      {
        slider.mGlassPlate.hide();
        slider.mGlassPlate.slider = null;
        slider.mGlassPlate.onmousemove = null;
        slider.mGlassPlate.onmouseup = null;
        slider.mGlassPlate.onmouseout = null;
      }
      
      if( cancelAction != true )
      {
        // set the slider value 
        slider.setValue( slider.newValue );
      }
      
      // do any clean up
      slider.newValue = null;      
    }
  }
}

function Static_Slider_StartDrag( e )
{
  e = jshGetEvent( e );
  var sourceElement = jshGetSourceElement( e );

  if( sourceElement && sourceElement.slider )
  {
    var slider = sourceElement.slider;    
    if( slider.mSlideInProgress != true )
    {
      slider.mSlideInProgress = true;
      slider.mDragingX = Event.pointerX( e );
      
      slider.mBody.onmousemove = Static_Slider_Drag;
      slider.mBody.onmouseup = Static_Slider_EndDrag;
      
      slider.mLastCurrentX = parseInt( slider.mSlider.style.left );
      slider.newValue = slider.mValue;
      
      if( slider.mGlassPlate )
      {
        slider.mGlassPlate.slider = slider;
        slider.mGlassPlate.show();
        slider.mGlassPlate.onmousemove = Static_Slider_Drag;
        slider.mGlassPlate.onmouseup = Static_Slider_EndDrag;
        slider.mGlassPlate.onmouseout = Static_Slider_EndDrag;
      }
      
      slider.slidingValue = slider.mValue;
    }
  }
}

function Static_Slider_Drag( e )
{
  e = jshGetEvent( e );
  var sourceElement = jshGetSourceElement( e );
  
  if( sourceElement && sourceElement.slider )
  {
    var slider = sourceElement.slider;
    if( slider.mSlideInProgress == true )
    {
      // current mouse position      
      var x = Event.pointerX( e );
      var y = Event.pointerY( e );
      
      var children = slider.mSegments.childNodes;
      for( var i = 0; i < children.length; i++ )
      {
        if( children[i] )
        {
          if( Position.within( children[i], x, y ) )
          {
            slider.moveSliderTo( children[i].mSegmentValue )
            slider.newValue = children[i].mSegmentValue;
          }
        }
      }
    }
  }
}

function Static_Slider_NextValue( e )
{
  e = jshGetEvent( e );
  var sourceElement = jshGetSourceElement( e );
  
  if( sourceElement && sourceElement.slider )
  {
    var slider = sourceElement.slider;
    if( slider.mSlideInProgress != true )
    { 
      slider.nextValue();
    }
  }
}

function Static_Slider_PreviousValue( e )
{
  e = jshGetEvent( e );
  var sourceElement = jshGetSourceElement( e );
  
  if( sourceElement && sourceElement.slider )
  {
    var slider = sourceElement.slider;
    if( slider.mSlideInProgress != true )
    { 
      slider.previousValue();
    }
  }
}

function Static_Slider_JumptTo( e )
{
  e = jshGetEvent( e );
  var sourceElement = jshGetSourceElement( e );
  
  if( sourceElement && sourceElement.slider )
  {
    var slider = sourceElement.slider;
    if( slider.mSlideInProgress != true )
    { 
      slider.setValue( sourceElement.mSegmentValue, true );
    }
  }
}
















