Merge pull request #548 from blcook223/range_sel_options
authorDan Vanderkam <danvdk@gmail.com>
Sat, 21 Mar 2015 16:41:43 +0000 (12:41 -0400)
committerDan Vanderkam <danvdk@gmail.com>
Sat, 21 Mar 2015 16:41:43 +0000 (12:41 -0400)
A few basic range selector options

auto_tests/tests/range_selector.js
dygraph-options-reference.js
dygraph-utils.js
dygraph.js
gallery/range-selector.js
plugins/range-selector.js
tests/range-selector.html
tests/range-selector/range-selector-background.png [new file with mode: 0644]
tests/range-selector/range-selector-foreground.png [new file with mode: 0644]
tests/range-selector/range-selector-plot.png [new file with mode: 0644]

index a145d7a..3349ab5 100644 (file)
@@ -115,6 +115,37 @@ RangeSelectorTestCase.prototype.testRangeSelectorOptions = function() {
     showRangeSelector: true,
     rangeSelectorHeight: 30,
     rangeSelectorPlotFillColor: 'lightyellow',
+    rangeSelectorPlotFillGradientColor: 'rgba(200, 200, 42, 10)',
+    labels: ['X', 'Y']
+  };
+  var data = [
+               [1, 10],
+               [2, 15],
+               [3, 10],
+               [4, 15],
+               [5, 10],
+               [6, 15],
+               [7, 10],
+               [8, 15],
+               [9, 10]
+             ];
+  var graph = document.getElementById("graph");
+  var g = new Dygraph(graph, data, opts);
+  this.assertGraphExistence(g, graph);
+};
+
+RangeSelectorTestCase.prototype.testAdditionalRangeSelectorOptions = function() {
+  var opts = {
+    width: 480,
+    height: 320,
+    showRangeSelector: true,
+    rangeSelectorHeight: 30,
+    rangeSelectorBackgroundStrokeColor: 'blue',
+    rangeSelectorBackgroundLineWidth: 3,
+    rangeSelectorPlotLineWidth: 0.5,
+    rangeSelectorForegroundStrokeColor: 'red',
+    rangeSelectorForegroundLineWidth: 2,
+    rangeSelectorAlpha: 0.8,
     labels: ['X', 'Y']
   };
   var data = [
@@ -343,7 +374,7 @@ RangeSelectorTestCase.prototype.testRangeSelectorPositionIfXAxisNotDrawn = funct
              ];
   var graph = document.getElementById("graph");
   var g = new Dygraph(graph, data, opts);
-  
+
   //assert, that the range selector is at top position 70 since the 30px of the
   // xAxis shouldn't be reserved since it isn't drawn.
   this.assertGraphExistence(g, graph);
index 596e541..d37251b 100644 (file)
@@ -739,6 +739,48 @@ Dygraph.OPTIONS_REFERENCE =  // <JSON>
     "type": "string",
     "description": "The range selector mini plot fill color. This can be of the form \"#AABBCC\" or \"rgb(255,100,200)\" or \"yellow\". You can also specify null or \"\" to turn off fill."
   },
+  "rangeSelectorPlotFillGradientColor": {
+    "default": "white",
+    "labels": ["Interactive Elements"],
+    "type": "string",
+    "description": "The top color for the range selector mini plot fill color gradient. This can be of the form \"#AABBCC\" or \"rgb(255,100,200)\" or \"rgba(255,100,200,42)\" or \"yellow\". You can also specify null or \"\" to disable the gradient and fill with one single color."
+  },
+  "rangeSelectorBackgroundStrokeColor": {
+    "default": "gray",
+    "labels": ["Interactive Elements"],
+    "type": "string",
+    "description": "The color of the lines below and on both sides of the range selector mini plot. This can be of the form \"#AABBCC\" or \"rgb(255,100,200)\" or \"yellow\"."
+  },
+  "rangeSelectorBackgroundLineWidth": {
+    "default": "1",
+    "labels": ["Interactive Elements"],
+    "type": "float",
+    "description": "The width of the lines below and on both sides of the range selector mini plot."
+  },
+  "rangeSelectorPlotLineWidth": {
+    "default": "1.5",
+    "labels": ["Interactive Elements"],
+    "type": "float",
+    "description": "The width of the range selector mini plot line."
+  },
+  "rangeSelectorForegroundStrokeColor": {
+    "default": "black",
+    "labels": ["Interactive Elements"],
+    "type": "string",
+    "description": "The color of the lines in the interactive layer of the range selector. This can be of the form \"#AABBCC\" or \"rgb(255,100,200)\" or \"yellow\"."
+  },
+  "rangeSelectorForegroundLineWidth": {
+    "default": "1",
+    "labels": ["Interactive Elements"],
+    "type": "float",
+    "description": "The width the lines in the interactive layer of the range selector."
+  },
+  "rangeSelectorAlpha": {
+    "default": "0.6",
+    "labels": ["Interactive Elements"],
+    "type": "float (0.0 - 1.0)",
+    "description": "The transparency of the veil that is drawn over the unselected portions of the range selector mini plot. A value of 0 represents full transparency and the unselected portions of the mini plot will appear as normal. A value of 1 represents full opacity and the unselected portions of the mini plot will be hidden."
+  },
   "showInRangeSelector": {
     "default": "null",
     "labels": ["Interactive Elements"],
index 992242d..eb08fef 100644 (file)
@@ -355,7 +355,7 @@ Dygraph.zeropad = function(x) {
 };
 
 /**
- * Date accessors to get the parts of a calendar date (year, month, 
+ * Date accessors to get the parts of a calendar date (year, month,
  * day, hour, minute, second and millisecond) according to local time,
  * and factory method to call the Date constructor with an array of arguments.
  */
@@ -374,7 +374,7 @@ Dygraph.DateAccessorsLocal = {
 };
 
 /**
- * Date accessors to get the parts of a calendar date (year, month, 
+ * Date accessors to get the parts of a calendar date (year, month,
  * day of month, hour, minute, second and millisecond) according to UTC time,
  * and factory method to call the Date constructor with an array of arguments.
  */
@@ -902,7 +902,14 @@ var pixelSafeOptions = {
   'pointClickCallback': true,
   'pointSize': true,
   'rangeSelectorPlotFillColor': true,
+  'rangeSelectorPlotFillGradientColor': true,
   'rangeSelectorPlotStrokeColor': true,
+  'rangeSelectorBackgroundStrokeColor': true,
+  'rangeSelectorBackgroundLineWidth': true,
+  'rangeSelectorPlotLineWidth': true,
+  'rangeSelectorForegroundStrokeColor': true,
+  'rangeSelectorForegroundLineWidth': true,
+  'rangeSelectorAlpha': true,
   'showLabelsOnHighlight': true,
   'showRoller': true,
   'strokeWidth': true,
index f82285b..aaf4b39 100644 (file)
@@ -203,7 +203,7 @@ Dygraph.SHORT_MONTH_NAMES_ = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', '
 
 /**
  * Convert a JS date to a string appropriate to display on an axis that
- * is displaying values at the stated granularity. This respects the 
+ * is displaying values at the stated granularity. This respects the
  * labelsUTC option.
  * @param {Date} date The date to format
  * @param {number} granularity One of the Dygraph granularity constants
@@ -241,7 +241,7 @@ Dygraph.dateAxisLabelFormatter = function(date, granularity, opts) {
 Dygraph.dateAxisFormatter = Dygraph.dateAxisLabelFormatter;
 
 /**
- * Return a string version of a JS date for a value label. This respects the 
+ * Return a string version of a JS date for a value label. This respects the
  * labelsUTC option.
  * @param {Date} date The date to be formatted
  * @param {Dygraph} opts An options view
@@ -336,7 +336,14 @@ Dygraph.DEFAULT_ATTRS = {
   showRangeSelector: false,
   rangeSelectorHeight: 40,
   rangeSelectorPlotStrokeColor: "#808FAB",
+  rangeSelectorPlotFillGradientColor: "white",
   rangeSelectorPlotFillColor: "#A7B1C4",
+  rangeSelectorBackgroundStrokeColor: "gray",
+  rangeSelectorBackgroundLineWidth: 1,
+  rangeSelectorPlotLineWidth:1.5,
+  rangeSelectorForegroundStrokeColor: "black",
+  rangeSelectorForegroundLineWidth: 1,
+  rangeSelectorAlpha: 0.6,
   showInRangeSelector: null,
 
   // The ordering here ensures that central lines always appear above any
@@ -1986,7 +1993,7 @@ Dygraph.prototype.mouseMove_ = function(event) {
 };
 
 /**
- * Fetch left offset from the specified set index or if not passed, the 
+ * Fetch left offset from the specified set index or if not passed, the
  * first defined boundaryIds record (see bug #236).
  * @private
  */
@@ -2331,7 +2338,7 @@ Dygraph.prototype.getHandlerClass_ = function() {
  */
 Dygraph.prototype.predraw_ = function() {
   var start = new Date();
-  
+
   // Create the correct dataHandler
   this.dataHandler_ = new (this.getHandlerClass_())();
 
@@ -2369,7 +2376,7 @@ Dygraph.prototype.predraw_ = function() {
     if (this.rollPeriod_ > 1) {
       series = this.dataHandler_.rollingAverage(series, this.rollPeriod_, this.attributes_);
     }
-    
+
     this.rolledSeries_.push(series);
   }
 
@@ -2528,7 +2535,7 @@ Dygraph.prototype.gatherDatasets_ = function(rolledSeries, dateWindow) {
   var seriesIdx, sampleIdx;
   var firstIdx, lastIdx;
   var axisIdx;
-  
+
   // Loop over the fields (series).  Go from the last to the first,
   // because if they're stacked that's how we accumulate the values.
   var num_series = rolledSeries.length - 1;
@@ -2546,7 +2553,7 @@ Dygraph.prototype.gatherDatasets_ = function(rolledSeries, dateWindow) {
 
       // TODO(danvk): do binary search instead of linear search.
       // TODO(danvk): pass firstIdx and lastIdx directly to the renderer.
-      firstIdx = null; 
+      firstIdx = null;
       lastIdx = null;
       for (sampleIdx = 0; sampleIdx < series.length; sampleIdx++) {
         if (series[sampleIdx][0] >= low && firstIdx === null) {
@@ -2580,9 +2587,9 @@ Dygraph.prototype.gatherDatasets_ = function(rolledSeries, dateWindow) {
       if (correctedLastIdx !== lastIdx) {
         lastIdx = correctedLastIdx;
       }
-      
+
       boundaryIds[seriesIdx-1] = [firstIdx, lastIdx];
-      
+
       // .slice's end is exclusive, we want to include lastIdx.
       series = series.slice(firstIdx, lastIdx + 1);
     } else {
@@ -2591,10 +2598,10 @@ Dygraph.prototype.gatherDatasets_ = function(rolledSeries, dateWindow) {
     }
 
     var seriesName = this.attr_("labels")[seriesIdx];
-    var seriesExtremes = this.dataHandler_.getExtremeYValues(series, 
+    var seriesExtremes = this.dataHandler_.getExtremeYValues(series,
         dateWindow, this.getBooleanOption("stepPlot",seriesName));
 
-    var seriesPoints = this.dataHandler_.seriesToPoints(series, 
+    var seriesPoints = this.dataHandler_.seriesToPoints(series,
         seriesName, boundaryIds[seriesIdx-1][0]);
 
     if (this.getBooleanOption("stackedGraph")) {
@@ -2809,7 +2816,7 @@ Dygraph.prototype.computeYAxisRanges_ = function(extremes) {
   };
   var numAxes = this.attributes_.numAxes();
   var ypadCompat, span, series, ypad;
-  
+
   var p_axis;
 
   // Compute extreme values, a span and tick marks for each axis.
@@ -2935,8 +2942,8 @@ Dygraph.prototype.computeYAxisRanges_ = function(extremes) {
     } else {
       axis.computedValueRange = axis.extremeRange;
     }
-    
-    
+
+
     if (independentTicks) {
       axis.independentTicks = independentTicks;
       var opts = this.optionsViewForAxis_('y' + (i ? '2' : ''));
@@ -2958,7 +2965,7 @@ Dygraph.prototype.computeYAxisRanges_ = function(extremes) {
   // independent ticks, then that is permissible as well.
   for (var i = 0; i < numAxes; i++) {
     var axis = this.axes_[i];
-    
+
     if (!axis.independentTicks) {
       var opts = this.optionsViewForAxis_('y' + (i ? '2' : ''));
       var ticker = opts('ticker');
index 3b13ebb..09bfd49 100644 (file)
@@ -11,7 +11,12 @@ Gallery.register(
           "<div id='noroll' style='width:600px; height:300px;'></div>",
           "",
           "<p>Roll period of 14 timesteps, custom range selector height and plot color.</p>",
-          "<div id='roll14' style='width:600px; height:300px;'></div>"].join("\n");
+          "<div id='roll14' style='width:600px; height:300px;'></div>",
+          "",
+          "<div style='background-color: #101015; color: white'>",
+          "<p>Dark background, custom range selector gradient color.</p>",
+          "<div id='darkbg' style='width:600px; height:300px;'></div>",
+          "</div>"].join("\n");
     },
     run: function() {
       new Dygraph(
@@ -41,6 +46,26 @@ Gallery.register(
             rangeSelectorHeight: 30,
             rangeSelectorPlotStrokeColor: 'yellow',
             rangeSelectorPlotFillColor: 'lightyellow'
-          });
+          }
+        );
+      new Dygraph(
+          document.getElementById("darkbg"),
+          data_temp,
+          {
+              rollPeriod: 14,
+              showRoller: true,
+              customBars: true,
+              title: 'Nightly Temperatures in New York vs. San Francisco',
+              ylabel: 'Temperature (F)',
+              legend: 'always',
+              labelsDivStyles: { 'textAlign': 'right', 'backgroundColor': '#101015' },
+              showRangeSelector: true,
+              rangeSelectorPlotFillColor: 'MediumSlateBlue',
+              rangeSelectorPlotFillGradientColor: 'rgba(123, 104, 238, 0)',
+              axisLabelColor: 'white',
+              colorValue: 0.9,
+              fillAlpha: 0.4
+          }
+      );
     }
   });
index 0f72f95..4c1e938 100644 (file)
@@ -176,7 +176,7 @@ rangeSelector.prototype.resize_ = function() {
   }
 
   var plotArea = this.dygraph_.layout_.getPlotArea();
-  
+
   var xAxisLabelHeight = 0;
   if (this.dygraph_.getOptionForAxis('drawAxis', 'x')) {
     xAxisLabelHeight = this.getOption_('xAxisHeight') || (this.getOption_('axisLabelFontSize') + 2 * this.getOption_('axisTickSize'));
@@ -222,7 +222,7 @@ rangeSelector.prototype.createZoomHandles_ = function() {
   img.style.zIndex = 10;
   img.style.visibility = 'hidden'; // Initially hidden so they don't show up in the wrong place.
   img.style.cursor = 'col-resize';
-
+//TODO: change image to more options
   if (/MSIE 7/.test(navigator.userAgent)) { // IE7 doesn't support embedded src data.
     img.width = 7;
     img.height = 14;
@@ -526,8 +526,8 @@ rangeSelector.prototype.drawStaticLayer_ = function() {
   }
 
   var margin = 0.5;
-  this.bgcanvas_ctx_.lineWidth = 1;
-  ctx.strokeStyle = 'gray';
+  this.bgcanvas_ctx_.lineWidth = this.getOption_('rangeSelectorBackgroundLineWidth');
+  ctx.strokeStyle = this.getOption_('rangeSelectorBackgroundStrokeColor');
   ctx.beginPath();
   ctx.moveTo(margin, margin);
   ctx.lineTo(margin, this.canvasRect_.h-margin);
@@ -543,6 +543,7 @@ rangeSelector.prototype.drawStaticLayer_ = function() {
  */
 rangeSelector.prototype.drawMiniPlot_ = function() {
   var fillStyle = this.getOption_('rangeSelectorPlotFillColor');
+  var fillGradientStyle = this.getOption_('rangeSelectorPlotFillGradientColor');
   var strokeStyle = this.getOption_('rangeSelectorPlotStrokeColor');
   if (!fillStyle && !strokeStyle) {
     return;
@@ -608,7 +609,9 @@ rangeSelector.prototype.drawMiniPlot_ = function() {
 
   if (fillStyle) {
     var lingrad = this.bgcanvas_ctx_.createLinearGradient(0, 0, 0, canvasHeight);
-    lingrad.addColorStop(0, 'white');
+    if (fillGradientStyle) {
+      lingrad.addColorStop(0, fillGradientStyle);
+    }
     lingrad.addColorStop(1, fillStyle);
     this.bgcanvas_ctx_.fillStyle = lingrad;
     ctx.fill();
@@ -616,7 +619,7 @@ rangeSelector.prototype.drawMiniPlot_ = function() {
 
   if (strokeStyle) {
     this.bgcanvas_ctx_.strokeStyle = strokeStyle;
-    this.bgcanvas_ctx_.lineWidth = 1.5;
+    this.bgcanvas_ctx_.lineWidth = this.getOption_('rangeSelectorPlotLineWidth');
     ctx.stroke();
   }
 };
@@ -658,7 +661,7 @@ rangeSelector.prototype.computeCombinedSeriesAndLimits_ = function() {
     if (g.rollPeriod() > 1) {
       series = dataHandler.rollingAverage(series, g.rollPeriod(), options);
     }
-    
+
     rolledSeries.push(series);
   }
 
@@ -746,7 +749,8 @@ rangeSelector.prototype.drawInteractiveLayer_ = function() {
   var height = this.canvasRect_.h - margin;
   var zoomHandleStatus = this.getZoomHandleStatus_();
 
-  ctx.strokeStyle = 'black';
+  ctx.strokeStyle = this.getOption_('rangeSelectorForegroundStrokeColor');
+  ctx.lineWidth = this.getOption_('rangeSelectorForegroundLineWidth');
   if (!zoomHandleStatus.isZoomed) {
     ctx.beginPath();
     ctx.moveTo(margin, margin);
@@ -758,7 +762,7 @@ rangeSelector.prototype.drawInteractiveLayer_ = function() {
     var leftHandleCanvasPos = Math.max(margin, zoomHandleStatus.leftHandlePos - this.canvasRect_.x);
     var rightHandleCanvasPos = Math.min(width, zoomHandleStatus.rightHandlePos - this.canvasRect_.x);
 
-    ctx.fillStyle = 'rgba(240, 240, 240, 0.6)';
+    ctx.fillStyle = 'rgba(240, 240, 240, ' + this.getOption_('rangeSelectorAlpha').toString() + ')';
     ctx.fillRect(0, 0, leftHandleCanvasPos, this.canvasRect_.h);
     ctx.fillRect(rightHandleCanvasPos, 0, this.canvasRect_.w - rightHandleCanvasPos, this.canvasRect_.h);
 
index 24a7acf..a7d0c99 100644 (file)
     #bordered {
       border: 1px solid red;
     }
+    #dark-background {
+      background-color: #101015;
+      color: white;
+    }
     </style>
   </head>
   <body>
@@ -22,7 +26,7 @@
     </p>
     <div id="noroll" style="width:800px; height:320px;"></div>
     <p>
-      Roll period of 14 timesteps, custom range selector height and plot color.
+      Roll period of 14 timesteps, various custom range selector options.
     </p>
     <div id="roll14" style="width:800px; height:320px;"></div>
     <p>
       The default behaviour is to compute the average of <em>all</em> series.
     </p>
     <div id="selectcombined" style="width:800px; height:320px;"></div>
+    <h2>Range selector options</h2>
+    <h3>Range selector background</h3>
+    <ul>
+      <li>rangeSelectorBackgroundStrokeColor</li>
+      <li>rangeSelectorBackgroundLineWidth</li>
+    </ul>
+    <img src="range-selector/range-selector-background.png">
+    <h3>Range selector foreground</h3>
+    <ul>
+      <li>rangeSelectorForegroundStrokeColor</li>
+      <li>rangeSelectorForegroundLineWidth</li>
+    </ul>
+    <img src="range-selector/range-selector-foreground.png">
+    <h3>Range selector plot</h3>
+    <ul>
+      <li>rangeSelectorAlpha</li>
+      <li>rangeSelectorPlotFillGradientColor</li>
+      <li>rangeSelectorPlotFillColor</li>
+      <li>rangeSelectorPlotStrokeColor</li>
+    </ul>
+    <img src="range-selector/range-selector-plot.png">
     <p>
       Demo of range selecor without the chart. (interesting if multiple charts should be synced with one range selector).
     </p>
     <div id="nochart" style="width:800px; height:30px;"></div>
+    <div id="dark-background">
+      <p>Demo of range selector on dark background, with (left) and without (right) custom range selector gradient color.</p>
+      <div id="darkbg1" style="width:400px; height:300px;display:inline-block;"></div>
+      <div id="darkbg2" style="width:400px; height:300px;display:inline-block;"></div>
+    </div>
     <p>Demo of range selector with stepPlot</p>
     <div id="stepplot" style="width:800px; height:320px;"></div>
 
             showRangeSelector: true,
             rangeSelectorHeight: 30,
             rangeSelectorPlotStrokeColor: 'yellow',
-            rangeSelectorPlotFillColor: 'lightyellow'
+            rangeSelectorPlotFillColor: 'black',
+            rangeSelectorBackgroundStrokeColor: 'lightyellow',
+            rangeSelectorBackgroundLineWidth: 4,
+            rangeSelectorPlotLineWidth: 1.5,
+            rangeSelectorForegroundStrokeColor: 'brown',
+            rangeSelectorForegroundLineWidth: 2,
+            rangeSelectorAlpha: 1,
+            rangeSelectorPlotFillGradientColor: 'yellow'
           }
       );
       g3 = new Dygraph(
             rangeSelectorHeight: 30
           }
       );
-      g5 = new Dygraph(document.getElementById("stepplot"),
+      g5 = new Dygraph(
+          document.getElementById("darkbg1"),
+          data_temp,
+          {
+              rollPeriod: 14,
+              showRoller: true,
+              customBars: true,
+              title: 'Nightly Temperatures in NY vs. SF',
+              ylabel: 'Temperature (F)',
+              legend: 'always',
+              labelsDivStyles: { 'textAlign': 'right', 'backgroundColor': '#101015' },
+              showRangeSelector: true,
+              rangeSelectorPlotFillColor: 'MediumSlateBlue',
+              rangeSelectorPlotFillGradientColor: 'rgba(123, 104, 238, 0)',
+              axisLabelColor: 'white',
+              colorValue: 0.9,
+              fillAlpha: 0.4
+          }
+      );
+      g6 = new Dygraph(
+          document.getElementById("darkbg2"),
+          data_temp,
+          {
+              rollPeriod: 14,
+              showRoller: true,
+              customBars: true,
+              title: 'Nightly Temperatures in NY vs. SF',
+              ylabel: 'Temperature (F)',
+              legend: 'always',
+              labelsDivStyles: { 'textAlign': 'right', 'backgroundColor': '#101015' },
+              showRangeSelector: true,
+              rangeSelectorPlotFillColor: 'MediumSlateBlue',
+              axisLabelColor: 'white',
+              colorValue: 0.9,
+              fillAlpha: 0.4
+          }
+      );
+      g7 = new Dygraph(document.getElementById("stepplot"),
                       "Date,Idle,Used\n" +
                       "2008-05-07,70,30\n" +
                       "2008-05-08,42,88\n" +
diff --git a/tests/range-selector/range-selector-background.png b/tests/range-selector/range-selector-background.png
new file mode 100644 (file)
index 0000000..02cee89
Binary files /dev/null and b/tests/range-selector/range-selector-background.png differ
diff --git a/tests/range-selector/range-selector-foreground.png b/tests/range-selector/range-selector-foreground.png
new file mode 100644 (file)
index 0000000..2d03078
Binary files /dev/null and b/tests/range-selector/range-selector-foreground.png differ
diff --git a/tests/range-selector/range-selector-plot.png b/tests/range-selector/range-selector-plot.png
new file mode 100644 (file)
index 0000000..5ef4f11
Binary files /dev/null and b/tests/range-selector/range-selector-plot.png differ