//=====================================================================||
//           NOP Design / Cyberitas Dual Slider Class                  ||
//=====================================================================||
function CyberSlider( strContainerId, bRangeSlider, iLowBound, iHighBound, iResolution,
                         iStartLowAt, iStartHighAt, 
                         strBgImage, strActiveBgImage, iBgWidth, iBgHeight, strAdditionalStyleCommands, 
                         strFgLowImage, strFgHighImage, iFgWidth, iFgHeight,
                         iLeftMargin, iRightMargin,
                         onMoveCompleteCb, onMoveCb )
{
   this.pContainer   = document.getElementById(strContainerId);
   if( !this.pContainer ) {
      throw( new TypeError("Container ID must exist, could not create slider object") );
   }

   this.pContainer.style.cssFloat = "left";
   this.pContainer.style.margin = "0";
   this.pContainer.style.width = iBgWidth;
   this.pContainer.style.height = iBgHeight;

   var strLowPointerId = strContainerId+'_lowpointer';
   var strHighPointerId = strContainerId+'_highpointer';
   var strTrackId = strContainerId+'_track';
   var strActiveOverlayId = strContainerId+'_activeoverlay';
   var bActiveOverlay = false;
   if( strActiveBgImage != null && strActiveBgImage != '' ) {
      bActiveOverlay = true;
   }

   var strContents = '<div id="'+strTrackId+'" style="height:'+iBgHeight+'px;width:'+iBgWidth+'px;background:url('+strBgImage+');position:relative;overflow:hidden;'+strAdditionalStyleCommands+'">' +
                     (bActiveOverlay?'   <div id="'+strActiveOverlayId+'" style="background:url('+strActiveBgImage+');width:0px; height:'+iBgHeight+'px;position:absolute;"></div>':'') + 
                     '   <div id="'+strLowPointerId+'" style="background:url('+strFgLowImage+');width:'+iFgWidth+'px; height:'+iFgHeight+'px;position:absolute; cursor: pointer;"></div>' + 
                     (bRangeSlider?'   <div id="'+strHighPointerId+'" style="background:url('+strFgHighImage+');width:'+iFgWidth+'px; height:'+iFgHeight+'px;position:absolute; cursor: pointer;"></div>':'') + 
                     '</div>';

   this.pContainer.innerHTML = strContents;

   this.pTrack = document.getElementById(strTrackId);
   if( !this.pTrack ) {
      throw( new TypeError("Could not create new slider track.") );
   }

   //Before Adjustment
   this.pTrack.iRealLowBound      = iLowBound;
   this.pTrack.iRealHighBound     = iHighBound;

   //Adjust for resolution
   if( iResolution <= 0 ) iResolution = 1;

   iLowBound = Math.round(parseFloat(iLowBound) / parseFloat(iResolution));
   iHighBound = Math.round(parseFloat(iHighBound) / parseFloat(iResolution));
   iStartLowAt = Math.round(parseFloat(iStartLowAt) / parseFloat(iResolution));
   iStartHighAt = Math.round(parseFloat(iStartHighAt) /parseFloat(iResolution));

   this.pTrack.strContainerId = strContainerId;   
   

   this.pTrack.iLowBound      = iLowBound;
   this.pTrack.iHighBound     = iHighBound;
   this.pTrack.iResolution    = iResolution;
   this.pTrack.iStartLowAt    = iStartLowAt;
   this.pTrack.iStartHighAt   = iStartHighAt;
   this.pTrack.strBgImage     = strBgImage;
   this.pTrack.iBgWidth       = iBgWidth - iLeftMargin - iRightMargin;
   this.pTrack.iBgHeight      = iBgHeight;
   this.pTrack.iFgWidth       = iFgWidth;
   this.pTrack.iFgHeight      = iFgHeight;
   this.pTrack.onMoveComplete = onMoveCompleteCb;
   this.pTrack.onMove         = onMoveCb;
   this.pTrack.pMyself        = this;
   this.pTrack.iDistance      = this.pTrack.iBgWidth-iFgWidth;
   this.pTrack.xMax           = 0;
   this.pTrack.yMax           = 0;
   this.pTrack.xMin           = iLeftMargin;
   this.pTrack.yMin           = 0;
   this.pTrack.bInDrag        = false;
   this.pTrack.iNumElements   = iHighBound - iLowBound;
   this.pTrack.fLowValue      = iStartLowAt;
   this.pTrack.fHighValue     = iStartHighAt;
   this.pTrack.iEffectiveBound= 0;
   this.pTrack.bRangeSlider   = bRangeSlider;
   this.pTrack.bActiveOverlay = bActiveOverlay;   
   
   // Slider-display scale [value-change per pixel of movement].
   this.pTrack.scale = ((this.pTrack.iHighBound - this.pTrack.iLowBound) / this.pTrack.iDistance);
   this.pTrack.iEffectiveBound = iLowBound;
   this.pTrack.xMax = this.pTrack.iDistance;
   this.pTrack.yMax = 0;
   

   this.pTrack.pLowPointer = document.getElementById(strLowPointerId);
   if( !this.pTrack.pLowPointer ) {
      throw( new TypeError("Could not create new low slider pointer.") );
   }
   if( this.pTrack.bRangeSlider ) {
      this.pTrack.pHighPointer = document.getElementById(strHighPointerId);
      if( !this.pTrack.pHighPointer ) {
         throw( new TypeError("Could not create new high slider pointer.") );
      }
   }
   if( this.pTrack.bActiveOverlay ) {
      this.pTrack.pActiveOverlayPointer = document.getElementById(strActiveOverlayId);
      if( !this.pTrack.pActiveOverlayPointer ) {
         throw( new TypeError("Could not create new active overlay pointer.") );
      }
      this.pTrack.pActiveOverlayPointer.pTrack = this.pTrack;      
   }

   this.pTrack.pLowPointer.pTrack = this.pTrack;
   if( this.pTrack.bRangeSlider ) {
      this.pTrack.pHighPointer.pTrack = this.pTrack;
   }

   this.pTrack.pLowPointer.startOffsetX = 0;
   this.pTrack.pLowPointer.startOffsetY = 0;
   this.pTrack.pLowPointer.iHiLoInd = 0;

   if( this.pTrack.bRangeSlider ) {
      this.pTrack.pHighPointer.startOffsetX = 0;
      this.pTrack.pHighPointer.startOffsetY = 0;
      this.pTrack.pHighPointer.iHiLoInd = 1;
      this.pTrack.pHighPointer.onmousedown = cyberSliderHandleOnMouseDown;
   }

   this.pTrack.pLowPointer.onmousedown = cyberSliderHandleOnMouseDown;
   //this.pTrack.onclick = cyberSliderHandleTrackOnClick;
   this.pTrack.onmousedown = cyberSliderHandleTrackOnClick;

   if( this.pTrack.bActiveOverlay ) {
      //this.pTrack.pActiveOverlayPointer.onclick = cyberSliderHandleOverlayOnClick;
      this.pTrack.pActiveOverlayPointer.onmousedown = cyberSliderHandleOverlayOnClick;
   }


   //---------------------------------------------------------------------||
   // FUNCTION:    SetValues                                              ||
   // PARAMETERS:  Value to set pointer to                                ||
   // RETURNS:     N/A                                                    ||
   // PURPOSE:     Sets the slider pointer to fLowValue,fHighValue        ||
   //---------------------------------------------------------------------||
   this.SetValues = function(fLowValue, fHighValue, bCallCallback) {
      var iLowVal = Math.round(parseFloat(fLowValue) / parseFloat(iResolution));
      var iHighVal = Math.round(parseFloat(fHighValue) / parseFloat(iResolution));

      this.realSetValues( iLowVal, iHighVal, bCallCallback );
   }

   this.realSetValues = function(fLowValue, fHighValue, bCallCallback) {
      if( this.pTrack.bRangeSlider && fLowValue > fHighValue ) {
         //Whoops, we received them backwards, flip them around.
         var fTemp = fLowValue;
         fLowValue = fHighValue;
         fHighValue = fTemp;
      }
      if( fLowValue > this.pTrack.iHighBound ) fLowValue = this.pTrack.iHighBound;
      if( fLowValue < this.pTrack.iLowBound ) fLowValue = this.pTrack.iLowBound;

      if( this.pTrack.bRangeSlider ) {
         if( fHighValue > this.pTrack.iHighBound ) fHighValue = this.pTrack.iHighBound;
         if( fHighValue < this.pTrack.iLowBound ) fHighValue = this.pTrack.iLowBound;
         this.pTrack.fHighValue = fHighValue;
      }

      this.pTrack.fLowValue = fLowValue;

      var sliderLowPos = (fLowValue - this.pTrack.iEffectiveBound) / this.pTrack.scale;
      if( this.pTrack.bRangeSlider ) {
         var sliderHighPos = (fHighValue - this.pTrack.iEffectiveBound) / this.pTrack.scale;
      }

      this.getSetObjectLeft(this.pTrack.pLowPointer, Math.round(sliderLowPos + this.pTrack.xMin));
      if( this.pTrack.bRangeSlider ) {
         this.getSetObjectLeft(this.pTrack.pHighPointer, Math.round(sliderHighPos + this.pTrack.xMin));
      }

      if( this.pTrack.bActiveOverlay  ) {
         if( this.pTrack.bRangeSlider ) {
            this.pTrack.pActiveOverlayPointer.style.left = this.getSetObjectLeft( this.pTrack.pLowPointer ) + this.pTrack.iFgWidth - 2 + 'px'; 
            this.pTrack.pActiveOverlayPointer.style.width = this.getSetObjectLeft( this.pTrack.pHighPointer ) - this.getSetObjectLeft( this.pTrack.pLowPointer ) + 'px';
         } else {
            this.pTrack.pActiveOverlayPointer.style.left = this.pTrack.xMin;
            this.pTrack.pActiveOverlayPointer.style.width = this.getSetObjectLeft( this.pTrack.pLowPointer ) + 'px';
         }
      }

      if( bCallCallback && this.pTrack.onMoveComplete ) {
         this.pTrack.onMoveComplete( this );
      }
   };

   this.GetLowValue = function() {
      var iLowValue = (this.pTrack.fLowValue * this.pTrack.iResolution);
      if( iLowValue < this.pTrack.iRealLowBound ) {
         iLowValue = this.pTrack.iRealLowBound;
      }
      return iLowValue;
   };

   this.GetHighValue = function() {
      var iHighValue = (this.pTrack.fHighValue * this.pTrack.iResolution);
      if( iHighValue > this.pTrack.iRealHighBound ) {
         iHighValue = this.pTrack.iRealHighBound;
      }
      return iHighValue;
   };

   this.Destroy = function() {
      if (document.removeEventListener) {
         document.removeEventListener('mousemove', cyberSliderHandleOnMouseMove, false);
         document.removeEventListener('mouseup', cyberSliderHandleOnMouseUp, false);
      } else if (document.detachEvent) {
         document.detachEvent('onmousemove', cyberSliderHandleOnMouseMove);
         document.detachEvent('onmouseup', cyberSliderHandleOnMouseUp);
      }
      this.pTrack.pLowPointer.onmousedown = null;
      if( this.pTrack.bRangeSlider ) {
         this.pTrack.pHighPointer.onmousedown = null;
      }
      this.pTrack.onclick = null;
      this.pContainer.innerHTML = '';
   };


   //Private Members
   this.getSetObjectLeft = function(objElement, pos)
   {
      if (objElement.style && (typeof(objElement.style.left) == 'string')) {
         if (typeof(pos) == 'number') {
            objElement.style.left = pos + 'px';
         } else {
            pos = parseInt(objElement.style.left);
            if (isNaN(pos)) pos = 0;
         }
      }
      else if (objElement.style && objElement.style.pixelLeft) {
         if (typeof(pos) == 'number') objElement.style.pixelLeft = pos;
         else pos = objElement.style.pixelLeft;
      }
      return pos;
   }

   this.findPosY = function(obj)
   {
      var curtop = 0;
      if (document.getElementById || document.all) {
         if( !obj.offsetParent ){
            curtop += obj.offsetTop;
         }
         while (obj.offsetParent) {
            curtop += obj.offsetTop;
            obj = obj.offsetParent;
         }
      } else if (document.layers)
         curtop += obj.y;
   
      return curtop;
   }

   this.findPosX = function(obj)
   {
      var curleft = 0;
      if (document.getElementById || document.all) {
         while (obj.offsetParent) {
            curleft += obj.offsetLeft;
            obj = obj.offsetParent;
         }
      } else if (document.layers)
         curleft += obj.x;
   
      return curleft;
   }


   this.getSetObjectTop = function(objElement, pos)
   {
      if (objElement.style && (typeof(objElement.style.top) == 'string')) {
         if (typeof(pos) == 'number') {
            objElement.style.top = pos + 'px';
         } else {
            pos = parseInt(objElement.style.top);
            if (isNaN(pos)) pos = 0;
         }
      } else if (objElement.style && objElement.style.pixelTop) {
         if (typeof(pos) == 'number') objElement.style.pixelTop = pos;
         else pos = objElement.style.pixelTop;
      }
      return pos;
   }

   this.HandleTrackOnClick = function(objEvent) {

      var iPosX = 0;
      if ( objEvent.pageX ) {
         iPosX = objEvent.pageX;
      } else {
         if ( objEvent.clientX ) {
            iPosX = objEvent.clientX + (document.body.scrollLeft?document.body.scrollLeft:0);
         }
      }

      var iRelativeX = iPosX - this.findPosX(this.pTrack) - (this.pTrack.iFgWidth/2) - this.pTrack.xMin;
      var v = Math.round( (iRelativeX * this.pTrack.scale + this.pTrack.iEffectiveBound) );

      var iFinalX = (v - this.pTrack.iEffectiveBound)/(this.pTrack.scale);
      if (iFinalX > this.pTrack.xMax) iFinalX = this.pTrack.xMax;
      if (iFinalX < this.pTrack.xMin) iFinalX = 0; //Yes, 0, not xMin

      //Determin which slider to move if we have 2...
      if( this.pTrack.bRangeSlider ) {
         var iLowAt = this.findPosX(this.pTrack.pLowPointer);
         var iHighAt = this.findPosX(this.pTrack.pHighPointer);
         if( Math.abs(iPosX - iLowAt) > Math.abs(iPosX - iHighAt) ) {
            this.getSetObjectLeft(this.pTrack.pHighPointer, Math.round(iFinalX + this.pTrack.xMin));
            this.pTrack.fHighValue = v;
         } else {
            this.getSetObjectLeft(this.pTrack.pLowPointer, Math.round(iFinalX + this.pTrack.xMin));


            //Uh oh, we guessed wrong.  Don't let this happen
            if( this.getSetObjectLeft(this.pTrack.pLowPointer) > this.getSetObjectLeft(this.pTrack.pHighPointer) ) {
               this.getSetObjectLeft(this.pTrack.pLowPointer, this.getSetObjectLeft(this.pTrack.pHighPointer));
               this.getSetObjectLeft(this.pTrack.pHighPointer, Math.round(iFinalX + this.pTrack.xMin));
               this.pTrack.fHighValue = v;
            } else {
               this.pTrack.fLowValue = v;
            }


         }
      } else {
         this.getSetObjectLeft(this.pTrack.pLowPointer, Math.round(iFinalX + this.pTrack.xMin));
         this.pTrack.fLowValue = v;
      } 

      if( this.pTrack.bActiveOverlay  ) {
         if( this.pTrack.bRangeSlider ) {
            this.pTrack.pActiveOverlayPointer.style.left = this.getSetObjectLeft( this.pTrack.pLowPointer ) + this.pTrack.iFgWidth - 2 + 'px'; 
            this.pTrack.pActiveOverlayPointer.style.width = this.getSetObjectLeft( this.pTrack.pHighPointer ) - this.getSetObjectLeft( this.pTrack.pLowPointer ) + 'px';
         } else {
            this.pTrack.pActiveOverlayPointer.style.left = this.pTrack.xMin;
            this.pTrack.pActiveOverlayPointer.style.width = this.getSetObjectLeft( this.pTrack.pLowPointer ) + 'px';
         }
      }

      if( this.pTrack.onMoveComplete ) {
         this.pTrack.onMoveComplete( this );
      }
   }

   this.HandleOnMouseDown = function(objEvent) {  
      if( g_pCurrentMovingPointer ) {


         g_pCurrentMovingPointer.startOffsetX = this.getSetObjectLeft(g_pCurrentMovingPointer) - objEvent.screenX;
         g_pCurrentMovingPointer.startOffsetY = this.getSetObjectTop(g_pCurrentMovingPointer) - objEvent.screenY;



         if( this.pTrack.pHighPointer ) g_pCurrentMovingPointer.startHiX = this.getSetObjectLeft( this.pTrack.pHighPointer );
         else g_pCurrentMovingPointer.startHiX = this.pTrack.xMax;

         if( this.pTrack.pLowPointer ) g_pCurrentMovingPointer.startLoX = this.getSetObjectLeft( this.pTrack.pLowPointer );
         else g_pCurrentMovingPointer.startHiX = this.pTrack.xMin;

         
         this.pTrack.bInDrag = true;
   
         if( window.addEventListener ) {
            document.addEventListener('mousemove', cyberSliderHandleOnMouseMove, false);
            document.addEventListener('mouseup', cyberSliderHandleOnMouseUp, false);
         } else {
            document.attachEvent('onmouseup', cyberSliderHandleOnMouseUp);
            document.attachEvent('onmousemove', cyberSliderHandleOnMouseMove);
         }
      } 

      return false
   };

   this.HandleOnMouseMove = function(objEvent) {  
      if (this.pTrack.bInDrag && g_pCurrentMovingPointer) {
         var x = g_pCurrentMovingPointer.startOffsetX + objEvent.screenX;
         if (x > this.pTrack.xMax + this.pTrack.xMin) x = this.pTrack.xMax + this.pTrack.xMin;
         if (x < this.pTrack.xMin) x = this.pTrack.xMin;

         var sliderVal = x;
         var sliderPos = (parseFloat(this.pTrack.iDistance) / parseFloat(this.pTrack.iNumElements) ) * Math.round(parseFloat(this.pTrack.iNumElements) * parseFloat(sliderVal) / parseFloat(this.pTrack.iDistance));
         var v = Math.round( (sliderPos * this.pTrack.scale + this.pTrack.iEffectiveBound) );

         if( g_pCurrentMovingPointer.iHiLoInd ) { 
            if( v < this.pTrack.fLowValue ) {
               return;               
            }
            this.pTrack.fHighValue = v;

            if( this.pTrack.bRangeSlider && x < g_pCurrentMovingPointer.startLoX ) {
               x = this.getSetObjectLeft( this.pTrack.pLowPointer )
            }

         } else {
            if( this.pTrack.bRangeSlider && v > this.pTrack.fHighValue ) {
               return;
            }
            this.pTrack.fLowValue = v;

            if( this.pTrack.bRangeSlider && x > g_pCurrentMovingPointer.startHiX ) {
               x = this.getSetObjectLeft( this.pTrack.pHighPointer )
            }
         }

         this.getSetObjectLeft(g_pCurrentMovingPointer, x);

            if( this.pTrack.bActiveOverlay  ) {
               if( this.pTrack.bRangeSlider ) {
                  this.pTrack.pActiveOverlayPointer.style.left = this.getSetObjectLeft( this.pTrack.pLowPointer ) + this.pTrack.iFgWidth - 2 + 'px'; 
                  this.pTrack.pActiveOverlayPointer.style.width = this.getSetObjectLeft( this.pTrack.pHighPointer ) - this.getSetObjectLeft( this.pTrack.pLowPointer ) + 'px';
               } else {
                  this.pTrack.pActiveOverlayPointer.style.left = this.pTrack.xMin;
                  this.pTrack.pActiveOverlayPointer.style.width = this.getSetObjectLeft( this.pTrack.pLowPointer ) + 'px';
               }
            }
   

         if( this.pTrack.onMove ) {
            this.pTrack.onMove( this );
         }
   
         return false;
      }
      return;
   }

   this.HandleOnMouseUp = function(objEvent) {  

      if (this.pTrack.bInDrag && g_pCurrentMovingPointer) {
         var v = null;
         if( g_pCurrentMovingPointer.iHiLoInd ) {
            v = (this.pTrack.fHighValue) ? this.pTrack.fHighValue : 0;
         } else {
            v = (this.pTrack.fLowValue) ? this.pTrack.fLowValue : 0;
         }
         var pos = (v - this.pTrack.iEffectiveBound)/(this.pTrack.scale);

         pos = (pos > this.pTrack.xMax) ? this.pTrack.xMax : pos;
         pos = (pos < this.pTrack.xMin) ? this.pTrack.xMin : pos;

          if( g_pCurrentMovingPointer ) {
               var iMyPos = this.findPosX(g_pCurrentMovingPointer);
               if( !this.pTrack.bRangeSlider || g_pCurrentMovingPointer.iHiLoInd ) {
                  var iLowPos = this.findPosX(this.pTrack.pLowPointer);
//SCOTT                  if( iMyPos <= iLowPos ) {
                  if( iMyPos < iLowPos ) {
                     pos += (this.pTrack.iFgWidth/2);
                  }
               } else {
                  var iHiPos = this.findPosX(this.pTrack.pHighPointer);
//SCOTT                  if( iMyPos >= iHiPos ) {
                  if( iMyPos >= iHiPos ) {
                     pos -= (this.pTrack.iFgWidth/2);
                  }
               }

               this.getSetObjectLeft(g_pCurrentMovingPointer, pos);
            }

         if (document.removeEventListener) {
            document.removeEventListener('mousemove', cyberSliderHandleOnMouseMove, false);
            document.removeEventListener('mouseup', cyberSliderHandleOnMouseUp, false);
         } else if (document.detachEvent) {
            document.detachEvent('onmousemove', cyberSliderHandleOnMouseMove);
            document.detachEvent('onmouseup', cyberSliderHandleOnMouseUp);
         }
      }
      this.pTrack.bInDrag = false;

      this.realSetValues( this.pTrack.fLowValue, this.pTrack.fHighValue, true );

   }

   //Everything is almost done, now set the options
   this.realSetValues( iStartLowAt, iStartHighAt, false );

} //END CyberSlider object

//Global pointer to current moving pointer
var g_pCurrentMovingPointer = null;

//Friend function, do not call directly
function cyberSliderHandleOnMouseDown( objEvent )
{
   if (!objEvent) objEvent = window.event;
   var pPointer = (objEvent.target) ? objEvent.target : objEvent.srcElement;
   
   if( pPointer && pPointer.pTrack ) {
      g_pCurrentMovingPointer = pPointer;
      return pPointer.pTrack.pMyself.HandleOnMouseDown( objEvent );
   }
}

//Friend function, do not call directly
function cyberSliderHandleOnMouseMove( objEvent )
{
   if (!objEvent) objEvent = window.event;
   var pPointer = g_pCurrentMovingPointer;
   if( pPointer && pPointer.pTrack ) {
      return pPointer.pTrack.pMyself.HandleOnMouseMove( objEvent );
   }
}

//Friend function, do not call directly
function cyberSliderHandleOnMouseUp( objEvent )
{
   if (!objEvent) objEvent = window.event;
   var pPointer = g_pCurrentMovingPointer;
   if( pPointer && pPointer.pTrack ) {
      return pPointer.pTrack.pMyself.HandleOnMouseUp( objEvent );
   }
}

//Friend function, do not call directly
function cyberSliderHandleTrackOnClick( objEvent )
{
   if (!objEvent) objEvent = window.event;
   var pTrack = (objEvent.target) ? objEvent.target : objEvent.srcElement;
   if( pTrack && pTrack.pMyself ) {
      return pTrack.pMyself.HandleTrackOnClick( objEvent );
   }
}

//Friend function, do not call directly
function cyberSliderHandleOverlayOnClick( objEvent )
{
   if (!objEvent) objEvent = window.event;
   var pOverlay = (objEvent.target) ? objEvent.target : objEvent.srcElement;
   if( pOverlay && pOverlay.pTrack ) {
      return pOverlay.pTrack.pMyself.HandleTrackOnClick( objEvent );
   }
}

