Fix bug 153, findPosX and findPosY don't take borders into account. This also fixes...
[dygraphs.git] / plugins / range-selector.js
index fd5d791..70b8065 100644 (file)
@@ -1,8 +1,9 @@
 /**
  * @license
- * Copyright 2013 Paul Felix (paul.eric.felix@gmail.com)
+ * Copyright 2011 Paul Felix (paul.eric.felix@gmail.com)
  * MIT-licensed (http://opensource.org/licenses/MIT)
  */
+/*global Dygraph:false,TouchEvent:false */
 
 /**
  * @fileoverview This file contains the RangeSelector plugin used to provide
@@ -15,15 +16,11 @@ Dygraph.Plugins.RangeSelector = (function() {
 /*global Dygraph:false */
 "use strict";
 
-var NOT_CREATED = 0;
-var CREATED = 1<<0;
-var ADDED_TO_GRAPH = 1<<1;
-
 var rangeSelector = function() {
   this.isIE_ = /MSIE/.test(navigator.userAgent) && !window.opera;
   this.hasTouchInterface_ = typeof(TouchEvent) != 'undefined';
   this.isMobileDevice_ = /mobile|android/gi.test(navigator.appVersion);
-  this.status_ = NOT_CREATED;
+  this.interfaceCreated_ = false;
 };
 
 rangeSelector.prototype.toString = function() {
@@ -32,9 +29,8 @@ rangeSelector.prototype.toString = function() {
 
 rangeSelector.prototype.activate = function(dygraph) {
   this.dygraph_ = dygraph;
-  this.layout_ = this.dygraph_.layout_;
   this.isUsingExcanvas_ = dygraph.isUsingExcanvas_;
-  if (this.attr_('showRangeSelector')) {
+  if (this.getOption_('showRangeSelector')) {
     this.createInterface_();
   }
   return {
@@ -56,8 +52,12 @@ rangeSelector.prototype.destroy = function() {
 // Private methods
 //------------------------------------------------------------------
 
-rangeSelector.prototype.attr_ = function(name) {
-  return this.dygraph_.attr_(name);
+rangeSelector.prototype.getOption_ = function(name) {
+  return this.dygraph_.getOption(name);
+};
+
+rangeSelector.prototype.setDefaultOption_ = function(name, value) {
+  return this.dygraph_.attrs_[name] = value;
 };
 
 /**
@@ -73,13 +73,13 @@ rangeSelector.prototype.createInterface_ = function() {
   this.initInteraction_();
 
   // Range selector and animatedZooms have a bad interaction. See issue 359.
-  if (this.attr_('animatedZooms')) {
-    this.dygraph_.warn('You should not set animatedZooms=true when using the range selector.');
-    this.dygraph_.attrs_.animatedZooms = false;
+  if (this.getOption_('animatedZooms')) {
+    this.dygraph_.warn('Animated zooms and range selector are not compatible; disabling animatedZooms.');
+    this.dygraph_.updateOptions({animatedZooms: false}, true);
   }
 
+  this.interfaceCreated_ = true;
   this.addToGraph_();
-  this.status_ = CREATED;
 };
 
 /**
@@ -87,12 +87,11 @@ rangeSelector.prototype.createInterface_ = function() {
  * Adds the range selector to the graph.
  */
 rangeSelector.prototype.addToGraph_ = function() {
-  var graphDiv = this.dygraph_.graphDiv;
+  var graphDiv = this.graphDiv_ = this.dygraph_.graphDiv;
   graphDiv.appendChild(this.bgcanvas_);
   graphDiv.appendChild(this.fgcanvas_);
   graphDiv.appendChild(this.leftZoomHandle_);
   graphDiv.appendChild(this.rightZoomHandle_);
-  this.status_ |= ADDED_TO_GRAPH;
 };
 
 /**
@@ -100,12 +99,12 @@ rangeSelector.prototype.addToGraph_ = function() {
  * Removes the range selector from the graph.
  */
 rangeSelector.prototype.removeFromGraph_ = function() {
-  var graphDiv = this.dygraph_.graphDiv;
+  var graphDiv = this.graphDiv_;
   graphDiv.removeChild(this.bgcanvas_);
   graphDiv.removeChild(this.fgcanvas_);
   graphDiv.removeChild(this.leftZoomHandle_);
   graphDiv.removeChild(this.rightZoomHandle_);
-  this.status_ ^= ADDED_TO_GRAPH;
+  this.graphDiv_ = null;
 };
 
 /**
@@ -113,8 +112,8 @@ rangeSelector.prototype.removeFromGraph_ = function() {
  * Called by Layout to allow range selector to reserve its space.
  */
 rangeSelector.prototype.reserveSpace_ = function(e) {
-  if (this.attr_('showRangeSelector')) {
-    e.reserveSpaceBottom(this.attr_('rangeSelectorHeight') + 4);
+  if (this.getOption_('showRangeSelector')) {
+    e.reserveSpaceBottom(this.getOption_('rangeSelectorHeight') + 4);
   }
 };
 
@@ -123,7 +122,7 @@ rangeSelector.prototype.reserveSpace_ = function(e) {
  * Renders the static portion of the range selector at the predraw stage.
  */
 rangeSelector.prototype.renderStaticLayer_ = function() {
-  if (!this.isEnabled_()) {
+  if (!this.updateVisibility_()) {
     return;
   }
   this.resize_();
@@ -135,7 +134,7 @@ rangeSelector.prototype.renderStaticLayer_ = function() {
  * Renders the interactive portion of the range selector after the chart has been drawn.
  */
 rangeSelector.prototype.renderInteractiveLayer_ = function() {
-  if (!this.isEnabled_() || this.isChangingRange_) {
+  if (!this.updateVisibility_() || this.isChangingRange_) {
     return;
   }
   this.placeZoomHandles_();
@@ -144,23 +143,23 @@ rangeSelector.prototype.renderInteractiveLayer_ = function() {
 
 /**
  * @private
- * Check to see if the range selector is enabled and needs to be created or added to graph.
+ * Check to see if the range selector is enabled/disabled and update visibility accordingly.
  */
-rangeSelector.prototype.isEnabled_ = function() {
-  var enabled = this.attr_('showRangeSelector');
+rangeSelector.prototype.updateVisibility_ = function() {
+  var enabled = this.getOption_('showRangeSelector');
   if (enabled) {
-    if (!(this.status_ & CREATED)) {
+    if (!this.interfaceCreated_) {
       this.createInterface_();
-    } else if (!(this.status_ & ADDED_TO_GRAPH)) {
+    } else if (!this.graphDiv_ || !this.graphDiv_.parentNode) {
       this.addToGraph_();
     }
-  } else if (this.status_ & ADDED_TO_GRAPH) {
+  } else if (this.graphDiv_) {
     this.removeFromGraph_();
     var dygraph = this.dygraph_;
     setTimeout(function() { dygraph.width_ = 0; dygraph.resize(); }, 1);
   }
   return enabled;
-}
+};
 
 /**
  * @private
@@ -176,13 +175,13 @@ rangeSelector.prototype.resize_ = function() {
     canvas.style.height = canvas.height + 'px';  // for IE
   }
 
-  var plotArea = this.layout_.getPlotArea();
-  var xAxisLabelHeight = this.attr_('xAxisHeight') || (this.attr_('axisLabelFontSize') + 2 * this.attr_('axisTickSize'));
+  var plotArea = this.dygraph_.layout_.getPlotArea();
+  var xAxisLabelHeight = this.getOption_('xAxisHeight') || (this.getOption_('axisLabelFontSize') + 2 * this.getOption_('axisTickSize'));
   this.canvasRect_ = {
     x: plotArea.x,
     y: plotArea.y + plotArea.h + xAxisLabelHeight + 4,
     w: plotArea.w,
-    h: this.attr_('rangeSelectorHeight')
+    h: this.getOption_('rangeSelectorHeight')
   };
 
   setElementRect(this.bgcanvas_, this.canvasRect_);
@@ -514,9 +513,8 @@ rangeSelector.prototype.initInteraction_ = function() {
     }
   };
 
-  this.dygraph_.attrs_.interactionModel =
-      Dygraph.Interaction.dragIsPanInteractionModel;
-  this.dygraph_.attrs_.panEdgeFraction = 0.0001;
+  this.setDefaultOption_('interactionModel', Dygraph.Interaction.dragIsPanInteractionModel);
+  this.setDefaultOption_('panEdgeFraction', 0.0001);
 
   var dragStartEvent = window.opera ? 'mousedown' : 'dragstart';
   this.dygraph_.addEvent(this.leftZoomHandle_, dragStartEvent, onZoomStart);
@@ -567,13 +565,13 @@ rangeSelector.prototype.drawStaticLayer_ = function() {
  * Draws the mini plot in the background canvas.
  */
 rangeSelector.prototype.drawMiniPlot_ = function() {
-  var fillStyle = this.attr_('rangeSelectorPlotFillColor');
-  var strokeStyle = this.attr_('rangeSelectorPlotStrokeColor');
+  var fillStyle = this.getOption_('rangeSelectorPlotFillColor');
+  var strokeStyle = this.getOption_('rangeSelectorPlotStrokeColor');
   if (!fillStyle && !strokeStyle) {
     return;
   }
 
-  var stepPlot = this.attr_('stepPlot');
+  var stepPlot = this.getOption_('stepPlot');
 
   var combinedSeriesData = this.computeCombinedSeriesAndLimits_();
   var yRange = combinedSeriesData.yMax - combinedSeriesData.yMin;
@@ -646,7 +644,7 @@ rangeSelector.prototype.drawMiniPlot_ = function() {
  */
 rangeSelector.prototype.computeCombinedSeriesAndLimits_ = function() {
   var data = this.dygraph_.rawData_;
-  var logscale = this.attr_('logscale');
+  var logscale = this.getOption_('logscale');
 
   // Create a combined series (average of all series values).
   var combinedSeries = [];
@@ -841,8 +839,8 @@ rangeSelector.prototype.drawInteractiveLayer_ = function() {
  */
 rangeSelector.prototype.getZoomHandleStatus_ = function() {
   var halfHandleWidth = this.leftZoomHandle_.width/2;
-  var leftHandlePos = parseInt(this.leftZoomHandle_.style.left, 10) + halfHandleWidth;
-  var rightHandlePos = parseInt(this.rightZoomHandle_.style.left, 10) + halfHandleWidth;
+  var leftHandlePos = parseFloat(this.leftZoomHandle_.style.left) + halfHandleWidth;
+  var rightHandlePos = parseFloat(this.rightZoomHandle_.style.left) + halfHandleWidth;
   return {
       leftHandlePos: leftHandlePos,
       rightHandlePos: rightHandlePos,