Merge branch 'master' of github.com:danvk/dygraphs
authorDan Vanderkam <danvdk@gmail.com>
Wed, 8 May 2013 23:13:05 +0000 (16:13 -0700)
committerDan Vanderkam <danvdk@gmail.com>
Wed, 8 May 2013 23:13:05 +0000 (16:13 -0700)
auto_tests/misc/local.html
auto_tests/tests/grid_per_axis.js [new file with mode: 0644]
dygraph-options-reference.js
dygraph.js
plugins/grid.js
tests/grid_dot.html
tests/two-axes.html

index f34d18b..e168de0 100644 (file)
@@ -30,6 +30,7 @@
   <script type="text/javascript" src="../tests/dygraph-options-tests.js"></script>
   <script type="text/javascript" src="../tests/error_bars.js"></script>
   <script type="text/javascript" src="../tests/formats.js"></script>
+  <script type="text/javascript" src="../tests/grid_per_axis.js"></script>
   <script type="text/javascript" src="../tests/interaction_model.js"></script>
   <script type="text/javascript" src="../tests/missing_points.js"></script>
   <script type="text/javascript" src="../tests/multi_csv.js"></script>
diff --git a/auto_tests/tests/grid_per_axis.js b/auto_tests/tests/grid_per_axis.js
new file mode 100644 (file)
index 0000000..e5c960f
--- /dev/null
@@ -0,0 +1,317 @@
+/**
+ * @fileoverview Test cases for the per-axis grid options, including the new
+ *               option "gridLinePattern".
+ * 
+ * @author david.eberlein@ch.sauter-bc.com (Fr. Sauter AG)
+ */
+var GridPerAxisTestCase = TestCase("grid-per-axis");
+
+GridPerAxisTestCase.prototype.setUp = function() {
+  document.body.innerHTML = "<div id='graph'></div>";
+};
+
+GridPerAxisTestCase.origFunc = Dygraph.getContext;
+
+GridPerAxisTestCase.prototype.setUp = function() {
+  document.body.innerHTML = "<div id='graph'></div>";
+  Dygraph.getContext = function(canvas) {
+    return new Proxy(GridPerAxisTestCase.origFunc(canvas));
+  };
+};
+
+GridPerAxisTestCase.prototype.tearDown = function() {
+  Dygraph.getContext = GridPerAxisTestCase.origFunc;
+};
+
+GridPerAxisTestCase.prototype.testIndependentGrids = function() {
+  var opts = {
+    width : 480,
+    height : 320,
+    errorBars : false,
+    labels : [ "X", "Left", "Right" ],
+    series : {
+      Left : {
+        axis : "y"
+      },
+      Right : {
+        axis : "y2"
+      }
+    },
+    axes : {
+      y2 : {
+        drawGrid : true,
+        independentTicks : true
+      }
+    }
+  };
+
+  var data = [ [ 1, 0, 0 ], [ 2, 12, 88 ], [ 3, 88, 122 ], [ 4, 63, 273 ],
+      [ 5, 110, 333 ] ];
+  var graph = document.getElementById("graph");
+  var g = new Dygraph(graph, data, opts);
+
+  htx = g.hidden_ctx_;
+
+  // The expected gridlines
+  var yGridlines = [ 0, 20, 40, 60, 80, 100, 120 ];
+  var y2Gridlines = [ 0, 50, 100, 150, 200, 250, 300, 350 ];
+  var gridlines = [ yGridlines, y2Gridlines ];
+
+  function halfUp(x) {
+    return Math.round(x) + 0.5;
+  }
+  function halfDown(y) {
+    return Math.round(y) - 0.5;
+  }
+
+  var attrs = {}, x, y;
+  x = halfUp(g.plotter_.area.x);
+  // Step through y(0) and y2(1) axis
+  for ( var axis = 0; axis < 2; axis++) {
+    // Step through all gridlines of the axis
+    for ( var i = 0; i < gridlines[axis].length; i++) {
+      // Check the labels:
+      var labels = Util.getYLabels(axis + 1);
+      assertEquals("Expected label not found.", gridlines[axis][i], labels[i]);
+
+      // Check that the grid was drawn.
+      y = halfDown(g.toDomYCoord(gridlines[axis][i], axis));
+      var p1 = [ x, y ];
+      var p2 = [ x + g.plotter_.area.w, y ];
+      CanvasAssertions.assertLineDrawn(htx, p1, p2, attrs);
+    }
+  }
+};
+
+GridPerAxisTestCase.prototype.testPerAxisGridColors = function() {
+  var opts = {
+    width : 480,
+    height : 320,
+    errorBars : false,
+    labels : [ "X", "Left", "Right" ],
+    series : {
+      Left : {
+        axis : "y"
+      },
+      Right : {
+        axis : "y2"
+      }
+    },
+    axes : {
+      y : {
+        gridLineColor : "#0000ff",
+        gridLineWidth : 2
+      },
+      y2 : {
+        drawGrid : true,
+        independentTicks : true,
+        gridLineColor : "#ff0000",
+        gridLineWidth : 2,
+      }
+    }
+  };
+  var data = [ [ 1, 0, 0 ], [ 2, 12, 88 ], [ 3, 88, 122 ], [ 4, 63, 273 ],
+      [ 5, 110, 333 ] ];
+  var graph = document.getElementById("graph");
+  var g = new Dygraph(graph, data, opts);
+  htx = g.hidden_ctx_;
+
+  // The expected gridlines
+  var yGridlines = [ 20, 40, 60, 80, 100, 120 ];
+  var y2Gridlines = [ 50, 100, 150, 200, 250, 300, 350 ];
+  var gridlines = [ yGridlines, y2Gridlines ];
+  var gridColors = [ [ 0, 0, 255, 255 ], [ 255, 0, 0, 255 ] ];
+
+  function halfUp(x) {
+    return Math.round(x) + 1;
+  }
+  function halfDown(y) {
+    return Math.round(y) - 1;
+  }
+  var x, y;
+  x = halfUp(g.plotter_.area.x);
+  // Step through y(0) and y2(1) axis
+  for ( var axis = 0; axis < 2; axis++) {
+    // Step through all gridlines of the axis
+    for ( var i = 0; i < gridlines[axis].length; i++) {
+      y = halfDown(g.toDomYCoord(gridlines[axis][i], axis));
+      // Check the grid colors.
+      assertEquals("Unexpected grid color found at pixel: x: " + x + "y: " + y,
+          gridColors[axis], Util.samplePixel(g.hidden_, x, y));
+    }
+  }
+};
+GridPerAxisTestCase.prototype.testPerAxisGridWidth = function() {
+  var opts = {
+    width : 480,
+    height : 320,
+    errorBars : false,
+    gridLineColor : "#ff0000",
+    labels : [ "X", "Left", "Right" ],
+    series : {
+      Left : {
+        axis : "y"
+      },
+      Right : {
+        axis : "y2"
+      }
+    },
+    axes : {
+      x : {
+        gridLineWidth : 4
+      },
+      y : {
+        gridLineWidth : 2
+      },
+      y2 : {
+        drawGrid : true,
+        independentTicks : true,
+        gridLineWidth : 1
+      }
+    }
+  };
+  var data = [ [ 1, 0, 0 ], [ 2, 12, 88 ], [ 3, 88, 122 ], [ 4, 63, 273 ],
+      [ 5, 110, 333 ] ];
+  var graph = document.getElementById("graph");
+  var g = new Dygraph(graph, data, opts);
+  htx = g.hidden_ctx_;
+
+  // The expected gridlines
+  var yGridlines = [ 20, 40, 60, 80 ];
+  var y2Gridlines = [ 50, 100, 150, 200, 250, 350 ];
+  var gridlines = [ yGridlines, y2Gridlines ];
+  var xGridlines = [ 2, 3, 4 ];
+  var gridColor = [ 255, 0, 0 ];
+  var emptyColor = [ 0, 0, 0 ];
+
+  function halfUp(x) {
+    return Math.round(x) + 1;
+  }
+  function halfDown(y) {
+    return Math.round(y) - 1;
+  }
+  var x, y;
+  x = halfUp(g.plotter_.area.x + 10);
+  // Step through y(0) and y2(1) axis
+  for ( var axis = 0; axis < 2; axis++) {
+    // Step through all gridlines of the axis
+    for ( var i = 0; i < gridlines[axis].length; i++) {
+      y = halfDown(g.toDomYCoord(gridlines[axis][i], axis));
+      // Ignore the alpha value
+      var drawnPixeldown2 = Util.samplePixel(g.hidden_, x, y - 2).slice(0, 3);
+      var drawnPixeldown1 = Util.samplePixel(g.hidden_, x, y - 1).slice(0, 3);
+      var drawnPixel = Util.samplePixel(g.hidden_, x, y).slice(0, 3);
+      var drawnPixelup1 = Util.samplePixel(g.hidden_, x, y + 1).slice(0, 3);
+      var drawnPixelup2 = Util.samplePixel(g.hidden_, x, y + 2).slice(0, 3);
+      // Check the grid width.
+      switch (axis) {
+      case 0: // y with 2 pixels width
+        assertEquals("Unexpected y-grid color found at pixel: x: " + x + "y: "
+            + y, emptyColor, drawnPixeldown2);
+        assertEquals("Unexpected y-grid color found at pixel: x: " + x + "y: "
+            + y, gridColor, drawnPixeldown1);
+        assertEquals("Unexpected y-grid color found at pixel: x: " + x + "y: "
+            + y, gridColor, drawnPixel);
+        assertEquals("Unexpected y-grid color found at pixel: x: " + x + "y: "
+            + y, gridColor, drawnPixelup1);
+        assertEquals("Unexpected y-grid color found at pixel: x: " + x + "y: "
+            + y, emptyColor, drawnPixelup2);
+        break;
+      case 1: // y2 with 1 pixel width
+        assertEquals("Unexpected y2-grid color found at pixel: x: " + x + "y: "
+            + y, emptyColor, drawnPixeldown1);
+        assertEquals("Unexpected y2-grid color found at pixel: x: " + x + "y: "
+            + y, gridColor, drawnPixel);
+        assertEquals("Unexpected y2-grid color found at pixel: x: " + x + "y: "
+            + y, emptyColor, drawnPixelup1);
+        break;
+      }
+    }
+  }
+
+  // Check the x axis grid
+  y = halfDown(g.plotter_.area.y) + 10;
+  for ( var i = 0; i < xGridlines.length; i++) {
+    x = halfUp(g.toDomXCoord(xGridlines[i]));
+    assertEquals("Unexpected x-grid color found at pixel: x: " + x + "y: " + y,
+        emptyColor, Util.samplePixel(g.hidden_, x - 4, y).slice(0, 3));
+    assertEquals("Unexpected x-grid color found at pixel: x: " + x + "y: " + y,
+        gridColor, Util.samplePixel(g.hidden_, x - 3, y).slice(0, 3));
+    assertEquals("Unexpected x-grid color found at pixel: x: " + x + "y: " + y,
+        gridColor, Util.samplePixel(g.hidden_, x - 2, y).slice(0, 3));
+    assertEquals("Unexpected x-grid color found at pixel: x: " + x + "y: " + y,
+        gridColor, Util.samplePixel(g.hidden_, x - 1, y).slice(0, 3));
+    assertEquals("Unexpected x-grid color found at pixel: x: " + x + "y: " + y,
+        gridColor, Util.samplePixel(g.hidden_, x, y).slice(0, 3));
+    assertEquals("Unexpected x-grid color found at pixel: x: " + x + "y: " + y,
+        gridColor, Util.samplePixel(g.hidden_, x + 1, y).slice(0, 3));
+    assertEquals("Unexpected x-grid color found at pixel: x: " + x + "y: " + y,
+        emptyColor, Util.samplePixel(g.hidden_, x + 2, y).slice(0, 3));
+  }
+};
+GridPerAxisTestCase.prototype.testGridLinePattern = function() {
+  var opts = {
+    width : 480,
+    height : 320,
+    errorBars : false,
+    drawXGrid : false,
+    drawXAxis : false,
+    drawYAxis : false,
+    labels : [ "X", "Left", "Right" ],
+    colors : [ "rgba(0,0,0,0)", "rgba(0,0,0,0)" ],
+    series : {
+      Left : {
+        axis : "y"
+      },
+      Right : {
+        axis : "y2"
+      }
+    },
+    axes : {
+      y : {
+        gridLineColor : "#0000ff",
+        gridLinePattern : [ 10, 10 ]
+      }
+    }
+  };
+  var data = [ [ 1, 0, 0 ], [ 2, 12, 88 ], [ 3, 88, 122 ], [ 4, 63, 273 ],
+      [ 5, 110, 333 ] ];
+  var graph = document.getElementById("graph");
+  var g = new Dygraph(graph, data, opts);
+  htx = g.hidden_ctx_;
+
+  // The expected gridlines
+  var yGridlines = [ 0, 20, 40, 60, 80, 100, 120 ];
+
+  function halfUp(x) {
+    return Math.round(x) + 1;
+  }
+  function halfDown(y) {
+    return Math.round(y) - 1;
+  }
+  var x, y;
+  // Step through all gridlines of the axis
+  for ( var i = 0; i < yGridlines.length; i++) {
+    y = halfDown(g.toDomYCoord(yGridlines[i], 0));
+    // Step through the pixels of the line and test the pattern.
+    for (x = halfUp(g.plotter_.area.x); x < g.plotter_.area.w; x++) {
+      // avoid checking the edge pixels since they differ depending on the OS.
+      var pixelpos = x % 10;
+      if(pixelpos < 1 || pixelpos > 8) continue;
+      
+      // Ignore alpha
+      var drawnPixel = Util.samplePixel(g.hidden_, x, y).slice(0,3);
+      var pattern = (Math.floor((x) / 10)) % 2;
+      switch (pattern) {
+      case 0: // fill
+        assertEquals("Unexpected filled grid-pattern color found at pixel: x: " + x + "y: "
+            + y, [ 0, 0, 255 ], drawnPixel);
+        break;
+      case 1: // no fill
+        assertEquals("Unexpected empty grid-pattern color found at pixel: x: " + x + "y: "
+            + y, [ 0, 0, 0 ], drawnPixel);
+        break;
+      }
+    }
+  }
+};
index 9010385..bd69bfc 100644 (file)
@@ -410,7 +410,7 @@ Dygraph.OPTIONS_REFERENCE =  // <JSON>
     "default": "rgb(128,128,128)",
     "labels": ["Grid"],
     "type": "red, blue",
-    "description": "The color of the gridlines."
+    "description": "The color of the gridlines. This may be set on a per-axis basis to define each axis' grid separately."
   },
   "visibility": {
     "default": "[true, true, ...]",
@@ -650,15 +650,27 @@ Dygraph.OPTIONS_REFERENCE =  // <JSON>
   },
   "drawXGrid": {
     "default": "true",
-    "labels": ["Grid"],
+    "labels": ["Grid","Deprecated"],
     "type": "boolean",
-    "description" : "Whether to display vertical gridlines under the chart."
+    "description" : "Use the per-axis option drawGrid instead. Whether to display vertical gridlines under the chart."
   },
   "drawYGrid": {
     "default": "true",
+    "labels": ["Grid","Deprecated"],
+    "type": "boolean",
+    "description" : "Use the per-axis option drawGrid instead. Whether to display horizontal gridlines under the chart."
+  },
+  "drawGrid": {
+    "default": "true for x and y, false for y2",
     "labels": ["Grid"],
     "type": "boolean",
-    "description" : "Whether to display horizontal gridlines under the chart."
+    "description" : "Whether to display gridlines in the chart. This may be set on a per-axis basis to define the visibility of each axis' grid separately."
+  },
+  "independentTicks": {
+    "default": "true for y, false for y2",
+    "labels": ["Axis display", "Grid"],
+    "type": "boolean",
+    "description" : "Only valid for y and y2, has no effect on x: This option defines whether the y axes should align their ticks or if they should be independent. Possible combinations: 1.) y=true, y2=false (default): y is the primary axis and the y2 ticks are aligned to the the ones of y. (only 1 grid) 2.) y=false, y2=true: y2 is the primary axis and the y ticks are aligned to the the ones of y2. (only 1 grid) 3.) y=true, y2=true: Both axis are independent and have their own ticks. (2 grids) 4.) y=false, y2=false: Invalid configuration causes an error."
   },
   "drawXAxis": {
     "default": "true",
@@ -676,7 +688,7 @@ Dygraph.OPTIONS_REFERENCE =  // <JSON>
     "default": "0.3",
     "labels": ["Grid"],
     "type": "float",
-    "description" : "Thickness (in pixels) of the gridlines drawn under the chart. The vertical/horizontal gridlines can be turned off entirely by using the drawXGrid and drawYGrid options."
+    "description" : "Thickness (in pixels) of the gridlines drawn under the chart. The vertical/horizontal gridlines can be turned off entirely by using the drawXGrid and drawYGrid options. This may be set on a per-axis basis to define each axis' grid separately."
   },
   "axisLineWidth": {
     "default": "0.3",
index 44214ad..5e4ba62 100644 (file)
@@ -344,18 +344,24 @@ Dygraph.DEFAULT_ATTRS = {
       pixelsPerLabel: 60,
       axisLabelFormatter: Dygraph.dateAxisFormatter,
       valueFormatter: Dygraph.dateString_,
+      drawGrid: true,
+      independentTicks: true,
       ticker: null  // will be set in dygraph-tickers.js
     },
     y: {
       pixelsPerLabel: 30,
       valueFormatter: Dygraph.numberValueFormatter,
       axisLabelFormatter: Dygraph.numberAxisLabelFormatter,
+      drawGrid: true,
+      independentTicks: true,
       ticker: null  // will be set in dygraph-tickers.js
     },
     y2: {
       pixelsPerLabel: 30,
       valueFormatter: Dygraph.numberValueFormatter,
       axisLabelFormatter: Dygraph.numberAxisLabelFormatter,
+      drawGrid: false,
+      independentTicks: false,
       ticker: null  // will be set in dygraph-tickers.js
     }
   }
@@ -2621,12 +2627,15 @@ 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.
   for (var i = 0; i < numAxes; i++) {
     var axis = this.axes_[i];
     var logscale = this.attributes_.getForAxis("logscale", i);
     var includeZero = this.attributes_.getForAxis("includeZero", i);
+    var independentTicks = this.attributes_.getForAxis("independentTicks", i);
     series = this.attributes_.seriesForAxis(i);
 
     // Add some padding. This supports two Y padding operation modes:
@@ -2744,20 +2753,33 @@ Dygraph.prototype.computeYAxisRanges_ = function(extremes) {
     } else {
       axis.computedValueRange = axis.extremeRange;
     }
-
-    // Add ticks. By default, all axes inherit the tick positions of the
-    // primary axis. However, if an axis is specifically marked as having
-    // independent ticks, then that is permissible as well.
-    var opts = this.optionsViewForAxis_('y' + (i ? '2' : ''));
-    var ticker = opts('ticker');
-    if (i === 0 || axis.independentTicks) {
+    
+    
+    if(independentTicks) {
+      axis.independentTicks = independentTicks;
+      var opts = this.optionsViewForAxis_('y' + (i ? '2' : ''));
+      var ticker = opts('ticker');
       axis.ticks = ticker(axis.computedValueRange[0],
-                          axis.computedValueRange[1],
-                          this.height_,  // TODO(danvk): should be area.height
-                          opts,
-                          this);
-    } else {
-      var p_axis = this.axes_[0];
+              axis.computedValueRange[1],
+              this.height_,  // TODO(danvk): should be area.height
+              opts,
+              this);
+      // Define the first independent axis as primary axis.
+      if (!p_axis) p_axis = axis;
+    }
+  }
+  if (p_axis === undefined) {
+    throw ("Configuration Error: At least one axis has to have the \"independentTicks\" option activated.");
+  }
+  // Add ticks. By default, all axes inherit the tick positions of the
+  // primary axis. However, if an axis is specifically marked as having
+  // 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');
       var p_ticks = p_axis.ticks;
       var p_scale = p_axis.computedValueRange[1] - p_axis.computedValueRange[0];
       var scale = axis.computedValueRange[1] - axis.computedValueRange[0];
index 9186dd4..425d93f 100644 (file)
@@ -50,29 +50,56 @@ grid.prototype.willDrawChart = function(e) {
 
   var x, y, i, ticks;
   if (g.getOption('drawYGrid')) {
+    var axes = ["y", "y2"];
+    var strokeStyles = [], lineWidths = [], drawGrid = [], stroking = [], strokePattern = [];
+    for (var i = 0; i < axes.length; i++) {
+      drawGrid[i] = g.getOptionForAxis("drawGrid", axes[i]);
+      if (drawGrid[i]) {
+        strokeStyles[i] = g.getOptionForAxis('gridLineColor', axes[i]);
+        lineWidths[i] = g.getOptionForAxis('gridLineWidth', axes[i]);
+        strokePattern[i] = g.getOptionForAxis('gridLinePattern', axes[i]);
+        stroking[i] = strokePattern[i] && (strokePattern[i].length >= 2);
+      }
+    }
     ticks = layout.yticks;
     ctx.save();
-    ctx.strokeStyle = g.getOption('gridLineColor');
-    ctx.lineWidth = g.getOption('gridLineWidth');
+    // draw grids for the different y axes
     for (i = 0; i < ticks.length; i++) {
-      // TODO(danvk): allow secondary axes to draw a grid, too.
-      if (ticks[i][0] !== 0) continue;
-      x = halfUp(area.x);
-      y = halfDown(area.y + ticks[i][1] * area.h);
-      ctx.beginPath();
-      ctx.moveTo(x, y);
-      ctx.lineTo(x + area.w, y);
-      ctx.closePath();
-      ctx.stroke();
+      var axis = ticks[i][0];
+      if(drawGrid[axis]) {
+        if (stroking[axis]) {
+          ctx.installPattern(strokePattern[axis]);
+        }
+        ctx.strokeStyle = strokeStyles[axis];
+        ctx.lineWidth = lineWidths[axis];
+
+        x = halfUp(area.x);
+        y = halfDown(area.y + ticks[i][1] * area.h);
+        ctx.beginPath();
+        ctx.moveTo(x, y);
+        ctx.lineTo(x + area.w, y);
+        ctx.closePath();
+        ctx.stroke();
+
+        if (stroking[axis]) {
+          ctx.uninstallPattern();
+        }
+      }
     }
     ctx.restore();
   }
 
-  if (g.getOption('drawXGrid')) {
+  // draw grid for x axis
+  if (g.getOption('drawXGrid') && g.getOptionForAxis("drawGrid", 'x')) {
     ticks = layout.xticks;
     ctx.save();
-    ctx.strokeStyle = g.getOption('gridLineColor');
-    ctx.lineWidth = g.getOption('gridLineWidth');
+    var strokePattern = g.getOptionForAxis('gridLinePattern', 'x');
+    var stroking = strokePattern && (strokePattern.length >= 2);
+    if (stroking) {
+      ctx.installPattern(strokePattern);
+    }
+    ctx.strokeStyle = g.getOptionForAxis('gridLineColor', 'x');
+    ctx.lineWidth = g.getOptionForAxis('gridLineWidth', 'x');
     for (i = 0; i < ticks.length; i++) {
       x = halfUp(area.x + ticks[i][0] * area.w);
       y = halfDown(area.y + area.h);
@@ -82,6 +109,9 @@ grid.prototype.willDrawChart = function(e) {
       ctx.closePath();
       ctx.stroke();
     }
+    if (stroking) {
+      ctx.uninstallPattern();
+    }
     ctx.restore();
   }
 };
index 4136ee2..77a271b 100644 (file)
             }
           );
     </script>
+    
+    <p>Use axis specific grid options. (independentTicks, gridLinePattern, ...)</p>
+    <div id="div_g15" style="width:600px; height:300px;"></div>
+
+    <script type="text/javascript">
+      var data = [];
+      for (var i = 1; i <= 100; i++) {
+        var m = "01", d = i;
+        if (d > 31) { m = "02"; d -= 31; }
+        if (m == "02" && d > 28) { m = "03"; d -= 28; }
+        if (m == "03" && d > 31) { m = "04"; d -= 31; }
+        if (d < 10) d = "0" + d;
+        // two series, one with range 1-100, one with range 1-2M
+        data.push([new Date("2010/" + m + "/" + d),
+                   i,
+                   100 - i,
+                   1e6 * (1 + i * (100 - i) / (50 * 50)),
+                   1e6 * (2 - i * (100 - i) / (50 * 50))]);
+      }
+      g15 = new Dygraph(
+            document.getElementById("div_g15"),
+            data,
+            {
+              labels: [ 'Date', 'Y1', 'Y2', 'Y3', 'Y4' ],
+              series : {
+                'Y3': {
+                  axis: 'y2'
+                },
+                'Y4': {
+                  axis: 'y2'
+                }
+              },
+              axes: {
+                x: {
+                  gridLineWidth: 2,
+                  drawGrid: true,
+                  independentTicks: true
+                },
+                y: {
+                  valueRange: [40, 80],
+                  drawGrid: true,
+                  independentTicks: true
+                },
+                y2: {
+                  // set axis-related properties here
+                  labelsKMB: true,
+                  ticker: Dygraph.numericLinearTicks,
+                  drawGrid: true,
+                  independentTicks: true,
+                  gridLineColor: "#ff0000",
+                  gridLinePattern: [4,4]
+                }
+              }
+            }
+          );
+    </script>
   </body>
-</html>
+</html>
\ No newline at end of file
index cfc36a5..e3e29ff 100644 (file)
   <body>
     <h2>Multiple y-axes</h2>
     <p>The same data with both one and two y-axes. Two y-axes:</p>
+    <p>Two y-axes with y as primary axis (default):</p>
     <div id="demodiv" style="width: 640; height: 350; border: 1px solid black"></div>
-    <p>A single y-axis:</p>
+    <p>Two y-axes with y2 as primary axis:</p>
+    <div id="demodiv_y2_primary" style="width: 640; height: 350; border: 1px solid black"></div>
+    <p>Two y-axes using different grids:</p>
+    <div id="demodiv_two_grids" style="width: 640; height: 350; border: 1px solid black"></div>
+    <p>A single y-axis (left):</p>
     <div id="demodiv_one" style="width: 640; height: 350; border: 1px solid black"></div>
+    <p>A single y-axis (right):</p>
+    <div id="demodiv_one_right" style="width: 640; height: 350; border: 1px solid black"></div>
 
     <script type="text/javascript">
       var data = [];
             yAxisLabelWidth: 60
           }
       );
-
+      
       g2 = new Dygraph(
-          document.getElementById("demodiv_one"),
+          document.getElementById("demodiv_y2_primary"),
           data,
           {
             labels: [ 'Date', 'Y1', 'Y2', 'Y3', 'Y4' ],
-            labelsKMB: true,
             ylabel: 'Primary y-axis',
-            y2label: 'Secondary y-axis'
+            y2label: 'Secondary y-axis',
+            series : {
+              'Y3': {
+                axis: 'y2'
+              },
+              'Y4': {
+                axis: 'y2'
+              }
+            },
+            axes: {
+              y: {
+                // set axis-related properties here
+                drawGrid: false,
+                independentTicks: false
+              },
+              y2: {
+                // set axis-related properties here
+                labelsKMB: true,
+                drawGrid: true,
+                independentTicks: true
+              }
+            }
+          }
+      );
+      
+      g3 = new Dygraph(
+          document.getElementById("demodiv_two_grids"),
+          data,
+          {
+            labels: [ 'Date', 'Y1', 'Y2', 'Y3', 'Y4' ],
+            ylabel: 'Primary y-axis',
+            y2label: 'Secondary y-axis',
+            series : {
+              'Y3': {
+                axis: 'y2'
+              },
+              'Y4': {
+                axis: 'y2'
+              }
+            },
+            axes: {
+              y2: {
+                // set axis-related properties here
+                labelsKMB: true,
+                drawGrid: true,
+                independentTicks: true,
+                gridLinePattern: [2,2]
+              }
+            }
           }
       );
 
+      g4 = new Dygraph(
+        document.getElementById("demodiv_one"),
+        data,
+        {
+          labels: [ 'Date', 'Y1', 'Y2', 'Y3', 'Y4' ],
+          labelsKMB: true,
+          ylabel: 'Primary y-axis',
+          y2label: 'Secondary y-axis',
+        }
+      );
+      
+      g5 = new Dygraph(
+       document.getElementById("demodiv_one_right"),
+       data,
+       {
+         labels: [ 'Date', 'Y1', 'Y2', 'Y3', 'Y4' ],
+         ylabel: 'Primary y-axis',
+         y2label: 'Secondary y-axis',
+          series : {
+            'Y1': {
+               axis: 'y2'
+            },
+            'Y2': {
+              axis: 'y2'
+            },
+            'Y3': {
+              axis: 'y2'
+            },
+            'Y4': {
+              axis: 'y2'
+            }
+          },
+          axes: {
+            y: {
+              // set axis-related properties here
+              drawGrid: false,
+              independentTicks: false
+            },
+            y2: {
+              // set axis-related properties here
+              labelsKMB: true,
+              drawGrid: true,
+              independentTicks: true
+            }
+          }
+        }
+      );
+      
       function update(el) {
         g.updateOptions( { fillGraph: el.checked } );
         g2.updateOptions( { fillGraph: el.checked } );
+        g3.updateOptions( { fillGraph: el.checked } );
+        g4.updateOptions( { fillGraph: el.checked } );
+        g5.updateOptions( { fillGraph: el.checked } );
       }
     </script>