/*--------------------------------------------------------------------*/
/*   DvtTimeSelector          Time Selector Component                 */
/*--------------------------------------------------------------------*/
/**
  *  Time selector component.
  *  @extends DvtContainer
  *  @class DvtTimeSelector  Graph time slector component.
  *  <p>
  *  Example:<br><br><code>
  *  var ts = new DvtTimeSelector(context) ;<br>
  *  </code>
  *  @constructor  
  */
var   DvtTimeSelector = function(context, x, y, w, h, id)
{
   this.Init(context, x, y, w, h, id) ;
}  

DvtObj.createSubclass(DvtTimeSelector, DvtContainer, "DvtTimeSelector");

DvtTimeSelector.TOK_X         = "__X__";
DvtTimeSelector.TOK_Y         = "__Y__";
DvtTimeSelector.TOK_STARTDATE = "__START_DATE__";
DvtTimeSelector.TOK_ENDDATE   = "__END_DATE__";

 
/*--------------------------------------------------------------------*/
/*  init()                                                            */
/*--------------------------------------------------------------------*/
/**
 *    Implementation of DvtDetObj.init()
 */
DvtTimeSelector.prototype.init = function()
{
    // var chart = this._Dlo._Chart;

    this._pxRatio = (this._timeAxisEndDate - this._timeAxisStartDate) 
                    / (this._timeAxisEndPixel - this._timeAxisStartPixel);

    // make sure the time selector area is withing axis pixel limits
    var pLeft = this.getLPos();
    var pRight = this.getRPos();
    if (pLeft < this._timeAxisStartPixel)
        this._container.setX(this._timeAxisStartPixel);
    if (pRight > this._timeAxisEndPixel)
        this._container.setWidth(this._timeAxisEndPixel - this.getX());

    // make sure at least a line is visible if TS width is zero
    if (this.getWidth() <= 0) 
        this._container.setWidth(1);

    // set up the time axis for labels and tooltips
    this._timeAxis = new DvtTimeAxis(this._timeAxisStartDate, this._timeAxisEndDate,
                            this._timeAxisStartPixel, this._timeAxisEndPixel,
                            300, 10,  // meaningless
                            this._aTimeAxisMonths, this._timeZoneOffset, true);
                            
    if (!DvtAgent.isTouchDevice()) {
        // register mouse event handlers
        this.addEvtListener(DvtMouseEvent.MOUSEOVER, this.mouseOverHandler, false, this);
        this.addEvtListener(DvtMouseEvent.MOUSEOUT, this.mouseOutHandler, false, this);
        this.addEvtListener(DvtMouseEvent.MOUSEDOWN, this.mouseDownHandler, false, this);
    } else {
        this._Dlo._Chart.addEvtListener(DvtTouchEvent.TOUCHSTART, this._touchHandler, false, this);
        this._Dlo._Chart.addEvtListener(DvtTouchEvent.TOUCHMOVE, this._touchHandler, false, this);
        this._Dlo._Chart.addEvtListener(DvtTouchEvent.TOUCHEND, this._touchHandler, false, this);
    }

    this._grabberLeft = this.createGrabber(DvtTSGrabber.LEFT);
    this._grabberRight = this.createGrabber(DvtTSGrabber.RIGHT);

    this._grabberLeft.setStroke(this.getStroke());
    this._grabberRight.setStroke(this.getStroke());
    this._grabberLeft.setVisible(false);
    this._grabberRight.setVisible(false);

    this._grabberLeft.init();
    this._grabberRight.init();

    this._container.addChild(this._grabberLeft);
    this._container.addChild(this._grabberRight);
    this.addChild(this._container);

    if (DvtAgent.isTouchDevice()) {
        this._showSelection();
    }

    this._container.setPixelHinting(true);
    DvtGraphSysUtils.makeDetObject(this._container);
    this._container._Dlo.setTooltip(this.makeTooltipText());
    
    this._standardStroke = this.getStroke();
    this._selectStroke = this._standardStroke.clone();
    this._selectStroke.setWidth(2);
};

DvtTimeSelector.prototype.createGrabber = function(type)
{
    var grabber = null;
    if (DvtAgent.isTouchDevice()) {
        grabber = new DvtMobileTSGrabber(this, type);
    } else {
        grabber = new DvtTSGrabber(this, type);
    }
    DvtGraphSysUtils.makeDetObject(grabber);
    return grabber;
}

/*--------------------------------------------------------------------*/
/*  Init()                                                            */
/*--------------------------------------------------------------------*/
/**
 *    @private
 */
DvtTimeSelector.prototype.Init = function(context, x, y, w, h, id)
{
   DvtTimeSelector.superclass.Init.call(this, context, "timeselector");
   this._container = new DvtRect(context, x, y, w, h, id) ;
   
   this._timeAxisStartDate   = 0 ;
   this._timeAxisEndDate     = 0 ;
   this._timeAxisStartPixel  = 0 ;
   this._timeAxisEndPixel    = 0 ;
   this._aTimeAxisMonths     = null ;     // month names, am/pm strings
   this._timeZoneOffset      = 0 ;
   this._timeAxisEventJs     = null ;
   this._timeSelectorEventJs = null ;
   this._translatedStart     = null ;
   this._translatedEnd       = null ;

   this._timeAxis            = null;
   
   this._pxRatio             = 0;
   
   this._grabberLeft         = null;
   this._grabberRight        = null;
   this._isMouseOver         = false;
   this._isDragging          = false;
   this._dragX               = -1;
   this._dragY               = -1;
   this._origLPos            = -1;
   this._origRPos            = -1;
   this._dragTarget          = 0;
   this._overTarget          = 0;
   
   this._standardStroke      = null;
   this._selectStroke        = null;
   this._targets = new Object();
   this._dragXMap = new Object();
   this._dragItems = new Array();
};


/*--------------------------------------------------------------------*/
/*  get/setTimeAxisStartDate()                                        */
/*--------------------------------------------------------------------*/

DvtTimeSelector.prototype.getTimeAxisStartDate = function()
{
    return this._timeAxisStartDate ;
};

DvtTimeSelector.prototype.setTimeAxisStartDate = function(sd)
{
    this._timeAxisStartDate = sd ;
};

/*--------------------------------------------------------------------*/
/*  get/setTimeAxisEndDate()                                          */
/*--------------------------------------------------------------------*/

DvtTimeSelector.prototype.getTimeAxisEndDate = function()
{
    return this._timeAxisEndDate ;
};

DvtTimeSelector.prototype.setTimeAxisEndDate = function(ed)
{
    this._timeAxisEndDate = ed ;
};

/*--------------------------------------------------------------------*/
/*  get/setTimeAxisStartPixel()                                       */
/*--------------------------------------------------------------------*/
/**
  *   @type number
  */
DvtTimeSelector.prototype.getTimeAxisStartPixel = function() 
{
    return this._timeAxisStartPixel ;
} ;

/**
  *   @param {number}  sp
  */
DvtTimeSelector.prototype.setTimeAxisStartPixel = function(sp) 
{
    this._timeAxisStartPixel =  sp ;
} ;

/*--------------------------------------------------------------------*/
/*  get/setTimeAxisEndPixel()                                         */
/*--------------------------------------------------------------------*/
/**
  *   @type number
  */
DvtTimeSelector.prototype.getTimeAxisEndPixel = function()
{
    return this._timeAxisEndPixel  ;
};

/**
  *   @param {number}  ep
  */
DvtTimeSelector.prototype.setTimeAxisEndPixel = function(ep)
{
    this._timeAxisEndPixel =  ep ;
};

/*--------------------------------------------------------------------*/
/*  get/setTimeAxisMonths()                                           */
/*--------------------------------------------------------------------*/
/**
  *   @type Array
  */
DvtTimeSelector.prototype.getTimeAxisMonths = function()
{
    return this._aTimeAxisMonths ;
} ;

/**
  *   @param {Array}  arm  array of months
  */
DvtTimeSelector.prototype.setTimeAxisMonths = function(arm)
{
    this._aTimeAxisMonths = arm ;
} ;

/*--------------------------------------------------------------------*/
/*  get/setTimeZoneOffset()                                           */
/*--------------------------------------------------------------------*/

DvtTimeSelector.prototype.getTimeZoneOffset = function()
{
    return this._timeZoneOffset ;
} ;

DvtTimeSelector.prototype.setTimeZoneOffset = function(tzo)
{
    this._timeZoneOffset = tzo ;
} ;

/*--------------------------------------------------------------------*/
/*  get/setTimeAxisEventJs()                                          */
/*--------------------------------------------------------------------*/
/**
  *   @type String
  */
DvtTimeSelector.prototype.getTimeAxisEventJs = function()
{
    return this._timeAxisEventJs ;
};

/**
  *   @param {String} ejs  Time axis event Javascript.
  */
DvtTimeSelector.prototype.setTimeAxisEventJs = function(ejs)
{
    this._timeAxisEventJs = ejs ;
};

/*--------------------------------------------------------------------*/
/*  get/setTimeSelectorEventJs()                                      */
/*--------------------------------------------------------------------*/
/**
  *   @type String
  */
DvtTimeSelector.prototype.getTimeSelectorEventJs = function()
{
    return this._timeSelectorEventJs ;
} ;

/**
  *   @param {String} evjs  Time selector event Javascript.
  */
DvtTimeSelector.prototype.setTimeSelectorEventJs = function(evjs)
{
    this._timeSelectorEventJs = evjs ;
} ;


/*--------------------------------------------------------------------*/
/*  get/setTranslatedStart()                                          */
/*--------------------------------------------------------------------*/
/**
  *   @type String
  */
DvtTimeSelector.prototype.getTranslatedStart = function()
{
    return this._translatedStart ;
} ;

/**
  *   @param {String}  start
  */
DvtTimeSelector.prototype.setTranslatedStart = function(start)
{
    this._translatedStart = start ;
} ;


/*--------------------------------------------------------------------*/
/*  get/setTranslatedEnd()                                            */
/*--------------------------------------------------------------------*/
/**
  *   @type String
  */
DvtTimeSelector.prototype.getTranslatedEnd = function()
{
    return this._translatedEnd ;
} ;

/**
  *   @param {String}  end
  */
DvtTimeSelector.prototype.setTranslatedEnd = function(end)
{
    this._translatedEnd = end ;
} ;


DvtTimeSelector.prototype.isPointInside = function(x, y) {
    return (x >= this.getX() && x <= (this.getX() + this.getWidth())
            && y >= this.getY() && y <= (this.getY() + this.getHeight()));
}

/*-------------------------------------------------------------------
 *
 * Mouse handling methods
 *
 *-------------------------------------------------------------------*/
 
/**
 * _getMouseTarget(x, y)
 * 
 * returns an integer representing the area under the current position specified
 * by the [x, y] coordinates:
 * 
 *   0 ... area outside of the time selector
 *   1 ... the main time selector rectangle
 *   2 ... left grabber
 *   3 ... right grabber
 * 
 * @private
 */ 
DvtTimeSelector.prototype._getMouseTarget = function(x, y) {
    var target = 0;
    
    if (this._isMouseOver || this._isDragging) {
        if (this._grabberLeft.isPointInside(x, y)) {
            target = 2;     // in left grabber
        }
        else if (this._grabberRight.isPointInside(x, y)) {
            target = 3;     // in right grabber
        }
    }
    if (target == 0 && this.isPointInside(x, y)) {
        target = 1;
    }
    return target;
}


/**
 * mouseOverHandler(event)
 * 
 * "mouseover" DOM event handler. Highlights the TS area when
 * hovered over with mouse.
 * 
 */
DvtTimeSelector.prototype.mouseOverHandler = function(event) {
    var pos = this.getCtx().getRelativePosition(event.pageX, event.pageY);
    var x = pos.x;
    var y = pos.y;
    
    var target = this._getMouseTarget(x, y);    

    // if already dragging, return, just set the 'over' flag
    if (this._isDragging) {
        if (target > 0) {
            this._isMouseOver = true;
        }
        return;
    }
    
    // if not over TimeSelector, do nothing
    if (target == 0)
        return;
        
    // also if already over, do nothing    
    if (this._isMouseOver && this._overTarget == target)
        return;
        
    this._isMouseOver = true;
    this._overTarget = target;

    // set mouse cursor
    if (target == 1)
        this._container.setCursor("move");

    // highlight the TS area
    this._showSelection(target);
}


/**
 * mouseOutHandler(event)
 * 
 * "mouseout" DOM event handler. Unselects the TS area when
 * the mouse is outside (unless in dragging mode).
 * 
 */
DvtTimeSelector.prototype.mouseOutHandler = function(event) {
    var pos = this.getCtx().getRelativePosition(event.pageX, event.pageY);
    var x = pos.x;
    var y = pos.y;

    var target = this._getMouseTarget(x, y);    

    // if dragging, keep tracking mouse actions, just reset the _isOver flag
    if (this._isDragging) {
        if (target == 0)
            this._isMouseOver =false;
            this._overTarget = 0;
        return;
    }
    
    if (target == 0) {
        if (this._isMouseOver == false)
            return;
    
        this._isMouseOver = false;
    
        // reset mouse cursor to default
        this._container.setCursor("default");
/*
        this._grabberLeft.removeEvtListener(DvtMouseEvent.MOUSEOVER, this.mouseOverHandler, false, this);
        this._grabberLeft.removeEvtListener(DvtMouseEvent.MOUSEOUT, this.mouseOutHandler, false, this);
        this._grabberLeft.removeEvtListener(DvtMouseEvent.MOUSEOVER, this.mouseOverHandler, false, this);
        this._grabberLeft.removeEvtListener(DvtMouseEvent.MOUSEOUT, this.mouseOutHandler, false, this);
*/
        this._hideSelection();
    }
}

/**
 * Handler for the touch event
 * @param {DvtTouchEvent} event Touch event
 * @private
 */
DvtTimeSelector.prototype._touchHandler = function(event) {
    this._isMouseOver = true;
    this.getTouchManager().processAssociatedTouchDefault(event, this);
}

/**
 * Processes "touchstart" event
 * @param {DvtTouchEvent} event Touch event
 * @param {DvtTouch} touch Touch object
 */
DvtTimeSelector.prototype.immediateTouchAttempted = function(event, touch) {
    var pos = this.getCtx().getRelativePosition(touch.pageX, touch.pageY);
    var x = pos.x;
    var y = pos.y;
    var target = this._getMouseTarget(x, y);   
    var allowTouch = true;
    if (target == 0) {
        return;
    }

    for (var i=0;i<this._dragItems.length; i++) {
        var dragItemId = this._dragItems[i];
        var targetId = this._targets[dragItemId];
        // Gripper only allows grippers
        if (targetId == 1) {
            allowTouch = false;
        } else if (targetId > 1) {
            if (target == 1) {
                allowTouch = false;
            }
        }
        if (targetId == target) {
            allowTouch = false;
        }
    }

    if (allowTouch) {
        this._dragItems.push(touch.identifier);
        this._targets[touch.identifier] = target;
        this._dragXMap[touch.identifier] = x;
        this._dragStart(target, x, y); 
        
        this.getTouchManager().saveProcessedTouchDefault(touch.identifier, this, this._container, "timeselector", "timeselector"+target, this);
        event.blockTouchHold();

    }
}

DvtTimeSelector.prototype.immediateTouchMoved = function(event, touch) {
    var pos = this.getCtx().getRelativePosition(touch.pageX, touch.pageY);
    var x = pos.x;
    var y = pos.y;
    var target = this._getMouseTarget(x, y);   
    event.preventDefault();

    if (this._isDragging == false)          // if not dragging, ignore
        return;

    var target = this._targets[touch.identifier];
    if (target != null && target > 0) {

        var xPos = 0;
        var yPos = 0;
        var targetTouches = event.touches;
        for (var i=0;i<this._dragItems.length; i++) {
            var dragItemId = this._dragItems[i];
            for (var j=0; j<targetTouches.length; j++) {
                var targetTouch = targetTouches[j];
                if (targetTouch.identifier == dragItemId) {
                    xPos += targetTouch.pageX;
                    yPos += targetTouch.pageY;
                }
            }
        }
        
        var dragX = this._dragXMap[touch.identifier];

        this._dragTarget = target;
        this._dragX = dragX;

        this._dragMove(x, y);
    }
}

/**
 * Processes "touchend" event
 * @param {DvtTouchEvent} event Touch event
 * @param {DvtTouch} touch Touch object
 */
DvtTimeSelector.prototype.immediateTouchEnded = function(event, touch) {
    var pos = this.getCtx().getRelativePosition(touch.pageX, touch.pageY);
    var x = pos.x;
    var y = pos.y;
    var target = this._getMouseTarget(x, y);   
    
    if (this._isDragging == false)
        return;
    // finish drag  
    var touchIndex = DvtArrayUtils.getIndex(this._dragItems, touch.identifier);
    if (touchIndex != -1) {
       this._dragItems.splice(touchIndex, 1);
       this._targets[touch.identifier] = null;
       this._dragXMap[touch.identifier] = null;
       this.getTouchManager().removeTooltipInfo(touch.identifier);
    }
    if (this._dragItems.length == 0) {
        this._dragItems = new Array();
        this._dragEnd(x, y);
        this._targets = new Object();
        this._dragXMap = new Object();
    }
}

/**
 * mouseDownHandler(event)
 * 
 * "mousedown" DOM event handler. Used to start the dragging when
 * the mouse pointer is above the active TS area.
 * 
 */
DvtTimeSelector.prototype.mouseDownHandler = function(event) {

    // remove 'mouseover' and 'mouseout' listeners while dragging
    // this.removeEvtListener(DvtMouseEvent.MOUSEOVER, this.mouseOverHandler, false, this);
    // this.removeEvtListener(DvtMouseEvent.MOUSEOUT, this.mouseOutHandler, false, this);

    var pos = this.getCtx().getRelativePosition(event.pageX, event.pageY);
    var x = pos.x;
    var y = pos.y;

    var target = this._getMouseTarget(x, y);

    // start dragging 
    this._dragStart(target, x, y);

    if (event)
        event.preventDefault();

    // add drag tracking listeners, listen everywhere
    this._Dlo._Chart.addEvtListener(DvtMouseEvent.MOUSEMOVE, this.mouseMoveHandler, false, this);
    this._Dlo._Chart.addEvtListener(DvtMouseEvent.MOUSEUP, this.mouseUpHandler, false, this);
}
 

/**
 * mouseUpHandler(event)
 * 
 * "mouseup" DOM event handler. Used to finish the drag operation.
 * 
 */
DvtTimeSelector.prototype.mouseUpHandler = function(event) {

    // remove drag tracking listeners
    this._Dlo._Chart.removeEvtListener(DvtMouseEvent.MOUSEMOVE, this.mouseMoveHandler, false, this);
    this._Dlo._Chart.removeEvtListener(DvtMouseEvent.MOUSEUP, this.mouseUpHandler, false, this);

    // restore 'mouseover' and 'mouseout' listeners
    //this.addEvtListener(DvtMouseEvent.MOUSEOVER, this.mouseOverHandler, false, this);
    //this.addEvtListener(DvtMouseEvent.MOUSEOUT, this.mouseOutHandler, false, this);

    var pos = this.getCtx().getRelativePosition(event.pageX, event.pageY);
    var x = pos.x;
    var y = pos.y;
        
    // finish drag    
    this._dragEnd(x, y);

    if (this._isMouseOver == false) {
        this._hideSelection();
    }

    if (event)
        event.preventDefault();

}

 
/**
 * mouseMoveHandler(event)
 * 
 * "mousemove" DOM event handler. Used to provide visual feedback
 * during dragging.
 * 
 */
DvtTimeSelector.prototype.mouseMoveHandler = function(event) {

    if (this._isDragging == false)          // if not dragging, ignore
        return;
    
    var pos = this.getCtx().getRelativePosition(event.pageX, event.pageY);
    var x = pos.x;
    var y = pos.y;
    
    this._dragMove(x, y);

    if (event)
        event.preventDefault();

}


/**
 * Grabber drag start handler
 */
/*
DvtTimeSelector.prototype.handleGrabberDragStart = function(grabber, event) {

    var chart = this._Dlo._Chart;
    var pos = DvtGraphEventUtils.getRelativePosition(chart, event.pageX, event.pageY);
    var x = pos.x;
    var y = pos.y;

    var target = 0;

    switch (grabber.getSide()) {
        case DvtTSGrabber.LEFT:
            target = 2;
            break;
        case DvtTSGrabber.RIGHT:
            target = 3;
            break;
    }

    // start dragging
    if (target)
        this._dragStart(target, x, y);

    // add drag tracking listeners, listen everywhere
    this._Dlo._Chart.addEvtListener(DvtMouseEvent.MOUSEMOVE, this.mouseMoveHandler, false, this);
    this._Dlo._Chart.addEvtListener(DvtMouseEvent.MOUSEUP, this.mouseUpHandler, false, this);

}
*/


/* -------------------------------------------------------------------
 * 
 * Generic interaction methods. Useful for updating TS active area
 * params in response to mouse, touch, or keyboard actions.
 * 
 * -------------------------------------------------------------------*/

/** 
 * _showSelection()
 * 
 * Updates the TS appearance to higlight the active area and show points
 * that can be dragged.
 * 
 * Called when the mouse pointer is over the active area, or when the area
 * is selected using a touch gesture.
 * 
 * @private
 */
DvtTimeSelector.prototype._showSelection = function(target) {
    
    // highlight the area and add grabbers
    if (target == 1) {
        this.setStroke(this._selectStroke);
        this._grabberLeft.setStroke(this._standardStroke);
        this._grabberRight.setStroke(this._standardStroke);
    }
    else if (target == 2) {
        this.setStroke(this._standardStroke);
        this._grabberLeft.setStroke(this._selectStroke);
        this._grabberRight.setStroke(this._standardStroke);
    }
    else if (target == 3) {
        this.setStroke(this._standardStroke);
        this._grabberLeft.setStroke(this._standardStroke);
        this._grabberRight.setStroke(this._selectStroke);
    }
    this._grabberLeft.setVisible(true);
    this._grabberRight.setVisible(true);
}


/** 
 * _hideSelection()
 * 
 * Updates the TS appearance to un-higlight the active area and hide 
 * the drag grabers.
 * 
 * Called when the mouse pointer is outside the active area, or when
 * the dragging is finished, or when unselected using a touch gesture.
 * 
 * @private
 */
DvtTimeSelector.prototype._hideSelection = function() {

    // reset the stroke and remove grabbers
    this.setStroke(this._standardStroke);
    this._grabberLeft.setStroke(this._standardStroke);
    this._grabberRight.setStroke(this._standardStroke);
    this._grabberLeft.setVisible(false);
    this._grabberRight.setVisible(false);
}


/**
 * _dragStart(target, x, y)
 * 
 * Called when the mouse (or touch) drag is started.
 * 
 * @param  target  time selector area selected for dragging
 * @param  x  current x-coordinate of the pointing device
 * @param  y  current y-coordinate of the pointing device
 *
 * @private
 */
DvtTimeSelector.prototype._dragStart = function(target, x, y) {

    if (this._isDragging)   // do nothing, if already dragging
        return;
        
    this._isDragging = true;
    this._dragX = x;                    // start drag x-coordinate
    this._origLPos = this.getLPos();    // original left edge in pixels
    this._origRPos = this.getRPos();    // original right edge in pixels

    this._dragTarget = target;          // the TS area being dragged
}


/**
 * _dragEnd(x, y)
 * 
 * Called when the mouse (or touch) drag is finished.
 *
 * @param  x  current x-coordinate of the pointing device
 * @param  y  current y-coordinate of the pointing device
 *
 * @private
 */
DvtTimeSelector.prototype._dragEnd = function(x, y) {

    // TODO: do we need x, y here? Should use the last _dragMove position.
    if (this._isDragging == false)
        return;

    this._isDragging = false;
    this._dragX = -1;
    this._dragTarget = 0;
    
    // Do not send any event if the bounds did not change
    if(this._origLPos == this.getLPos() && this._origRPos == this.getRPos())
      return;

    // execute the time selector event javascript
    if (this._timeSelectorEventJs && this._timeSelectorEventJs.length > 0) {
        var startTS = this._timeAxisStartDate + ((this.getLPos() - this._timeAxisStartPixel) * this._pxRatio);
        var endTS   = this._timeAxisEndDate - (this._timeAxisEndPixel - this.getRPos()) * this._pxRatio;

        var startD = new Date();
        var endD = new Date();

        startD.setTime(startTS);
        endD.setTime(endTS);

        // TODO: need to convert x, y to global coordinates ???

        // TODO: should use StrUtils token replace and EventTokens constants when available
        var sJS = this._timeSelectorEventJs;
        var sJS1 = sJS.replace(DvtTimeSelector.TOK_X, x);
        var sJS2 = sJS1.replace(DvtTimeSelector.TOK_Y, y);
        var sJS3 = sJS2.replace(DvtTimeSelector.TOK_STARTDATE, startD.getTime());
        var finalJS = sJS3.replace(DvtTimeSelector.TOK_ENDDATE, endD.getTime());

        // execute the JS code 
        //BUG 34184877 - MAKE DVT COMPATIBLE WITH CSP STANDARDS
        var src = finalJS.match(/'(.*?)'/g)[0].replace(/\'/g, "")
        AdfPage.PAGE.findComponent(src).getPeer().sendToServerPPR3({source:src,event:'bi_gtse',bi_gtsS:startD.getTime(),bi_gtsE:endD.getTime()});
    }
}
 
 
/**
 * _dragMove(x, y)
 * 
 * Handles dragging either by mouse or touch. Time selector must be in 'dragging' mode.
 * 
 * @param  x  current x-coordinate of the pointing device
 * @param  y  current y-coordinate of the pointing device
 * 
 * @private
 */
DvtTimeSelector.prototype._dragMove = function(x, y) {
    if (this._isDragging == false)          // if not dragging, nothing to do
        return;

    var offsetX = x - this._dragX;
    var newX = this.getLPos();
    var newWidth = Math.floor(this.getWidth());
    var grabberWidth = this._grabberLeft.getGrabberWidth();
    var minWidth = 0;   // minimum TS area width is 0
    if (this._dragTarget == 1) {            // main TS area
        newX = this._origLPos + offsetX;
        if (newX < this._timeAxisStartPixel) {
            newX = this._timeAxisStartPixel;
        }
        if ((newX + Math.floor(this.getWidth())) > this._timeAxisEndPixel) {
            newX = this._timeAxisEndPixel - Math.floor(this.getWidth());
        }
    }
    else if (this._dragTarget == 2) {       // left grabber
        newX = this._origLPos + offsetX;
        if (newX < this._timeAxisStartPixel) {
            newX = this._timeAxisStartPixel;
        }
        if (newX > this.getRPos() - minWidth) {
            newX = this.getRPos() - minWidth;
        }
        newWidth = this.getRPos() - newX;
    }
    else if (this._dragTarget == 3) {       // right grabber
        var newRPos = this._origRPos + offsetX;
        if (newRPos < this.getLPos() + minWidth) {
            newRPos = this.getLPos() + minWidth;
        }
        if (newRPos > this._timeAxisEndPixel) {
            newRPos = this._timeAxisEndPixel;
        }
        newWidth = newRPos - this.getLPos();
    }

    if (newWidth == 0)
        newWidth = 1;         // must ensure non zero width

    // set new Time Selector coordinates        
    this._container.setX(newX);
    this._container.setWidth(newWidth);
    
    var leftX = newX - grabberWidth / 2;
    var rightX = newX + Math.floor(this.getWidth()) - grabberWidth / 2;

    this._grabberLeft.setX(leftX);
    this._grabberRight.setX(rightX);
  
    //this._grabberLeft.update();
    //this._grabberRight.update();
    
    // update tooltip
    var tooltipText = this.makeTooltipText();

    // tooltip range is the same for grippers / time selector
    this._container._Dlo.setTooltip(tooltipText);
    this._grabberLeft.getContainer()._Dlo.setTooltip(tooltipText);
    this._grabberRight.getContainer()._Dlo.setTooltip(tooltipText);
}


 /**
  * getLPos()
  * 
  * returns position of TimeSelector's left edge in pixels
  * 
  * @private
  */
DvtTimeSelector.prototype.getLPos = function() {
    return this.getX();
}
 
/**
* getRPos()
*
* returns position of TimeSelector's right edge in pixels
*
* @private
*/
DvtTimeSelector.prototype.getRPos = function() {
    return this.getX() + Math.floor(this.getWidth());
}



/**
 * makeTootipText()
 *
 * Returns the text to be displayed in tooltip.
 *
 * @private
 */
DvtTimeSelector.prototype.makeTooltipText = function () {
//diff var inorder to determine what label to use
    var diff = this.getRPos() - this.getLPos();
    if (DvtAgent.isRightToLeft())
        diff = this.getLPos() - this.getRPos();
    var startLabel = this._timeAxis.getLabelAt(this.getLPos(), diff);
    var endLabel = this._timeAxis.getLabelAt(this.getRPos(),  - diff);

    if (DvtAgent.isRightToLeft())
        return endLabel + " - " + startLabel;
    return startLabel + " - " + endLabel;
}
DvtTimeSelector.prototype.getStroke = function() {
    return this._container.getStroke();
} 

DvtTimeSelector.prototype.setStroke = function(stroke) {
    this._container.setStroke(stroke);
}

DvtTimeSelector.prototype.setSolidStroke = function(color, alpha, strokeWidth) {
    this._container.setSolidStroke(color, alpha, strokeWidth);
}

DvtTimeSelector.prototype.setFill = function(fill) {
    this._container.setFill(fill);
}

DvtTimeSelector.prototype.setSolidFill = function(color, alpha) {
    this._container.setSolidFill(color, alpha);
}

DvtTimeSelector.prototype.getX = function() {
    return this._container.getX();
}

DvtTimeSelector.prototype.getY = function() {
    return this._container.getY();
}

DvtTimeSelector.prototype.getWidth = function() {
    return this._container.getWidth();
}

DvtTimeSelector.prototype.getHeight = function() {
    return this._container.getHeight();
}

/**
 * Gets a touch manager object
 * @return {DvtTouchManager} touch manager object
 */
DvtTimeSelector.prototype.getTouchManager = function () {
  return this._touchManager;  
}

/**
 * Sets a touch manager object
 * @param {DvtTouchManager} touch manager object
 */
DvtTimeSelector.prototype.setTouchManager = function (touchManager) {
  this._touchManager = touchManager;  
}
