- Stop charts with no visible plots from crashing.
authorNeal Nelson <neal@makalumedia.com>
Thu, 27 Jan 2011 14:48:01 +0000 (15:48 +0100)
committerNeal Nelson <neal@makalumedia.com>
Thu, 27 Jan 2011 14:48:01 +0000 (15:48 +0100)
- Add noZoomFlagChange option to stop the zoom flags being updated when
the dateWindow or valueRange is changed programmatically.

docs/index.html
dygraph.js
tests/no-zoom-change.html [new file with mode: 0644]

index 9d295aa..a2a2b5f 100644 (file)
@@ -1025,6 +1025,17 @@ perl -ne 'BEGIN{print "Month,Nominal,Real\n"} chomp; ($m,$cpi,$low,$close,$high)
           </td>
         </tr>
 
+        <tr>
+          <td><strong>noZoomFlagChange</strong></td>
+          <td><code></code></td>
+          <td><code></code></td>
+          <td>
+            When this flag is passed along with either the <code>dateWindow</code> or <code>valueRange</code> options, the zoom flags are not changed to reflect a zoomed state.
+            This is primarily useful for when the display area of a chart is changed programmatically and also where manual zooming is allowed and use is made of the <code>isZoomed</code> method to determine this.
+            <div class="tests">Tests: <a href="tests/no-zoom-change.html">no-zoom-change</a></div>
+          </td>
+        </tr>
+
       </tbody>
     </table>
 
index 4539382..d28fad3 100644 (file)
@@ -2104,18 +2104,22 @@ Dygraph.prototype.drawGraph_ = function() {
     this.layout_.addDataset(this.attr_("labels")[i], datasets[i]);
   }
 
-  // TODO(danvk): this method doesn't need to return anything.
-  var out = this.computeYAxisRanges_(extremes);
-  var axes = out[0];
-  var seriesToAxisMap = out[1];
-  this.layout_.updateOptions( { yAxes: axes,
-                                seriesToAxisMap: seriesToAxisMap
-                              } );
-
+  if (datasets.length > 0) {
+    // TODO(danvk): this method doesn't need to return anything.
+    var out = this.computeYAxisRanges_(extremes);
+    var axes = out[0];
+    var seriesToAxisMap = out[1];
+    this.layout_.updateOptions( { yAxes: axes,
+                                  seriesToAxisMap: seriesToAxisMap
+                                } );
+  }
   this.addXTicks_();
 
+  // Save the X axis zoomed status as the updateOptions call will tend to set it errorneously
+  var tmp_zoomed_x = this.zoomed_x_;
   // Tell PlotKit to use this new data and render itself
   this.layout_.updateOptions({dateWindow: this.dateWindow_});
+  this.zoomed_x_ = tmp_zoomed_x;
   this.layout_.evaluateWithError();
   this.plotter_.clear();
   this.plotter_.render();
@@ -2138,12 +2142,12 @@ Dygraph.prototype.drawGraph_ = function() {
  *   indices are into the axes_ array.
  */
 Dygraph.prototype.computeYAxes_ = function() {
-  var valueWindow;
+  var valueWindows;
   if (this.axes_ != undefined) {
     // Preserve valueWindow settings.
-    valueWindow = [];
+    valueWindows = [];
     for (var index = 0; index < this.axes_.length; index++) {
-      valueWindow.push(this.axes_[index].valueWindow);
+      valueWindows.push(this.axes_[index].valueWindow);
     }
   }
 
@@ -2220,10 +2224,10 @@ Dygraph.prototype.computeYAxes_ = function() {
   }
   this.seriesToAxisMap_ = seriesToAxisFiltered;
 
-  if (valueWindow != undefined) {
+  if (valueWindows != undefined) {
     // Restore valueWindow settings.
-    for (var index = 0; index < valueWindow.length; index++) {
-      this.axes_[index].valueWindow = valueWindow[index];
+    for (var index = 0; index < valueWindows.length; index++) {
+      this.axes_[index].valueWindow = valueWindows[index];
     }
   }
 };
@@ -2921,9 +2925,11 @@ Dygraph.prototype.updateOptions = function(attrs) {
   }
   if ('dateWindow' in attrs) {
     this.dateWindow_ = attrs.dateWindow;
-    this.zoomed_x_ = attrs.dateWindow != null;
+    if (!('noZoomFlagChange' in attrs)) {
+      this.zoomed_x_ = attrs.dateWindow != null;
+    }
   }
-  if ('valueRange' in attrs) {
+  if ('valueRange' in attrs && !('noZoomFlagChange' in attrs)) {
     this.zoomed_y_ = attrs.valueRange != null;
   }
 
diff --git a/tests/no-zoom-change.html b/tests/no-zoom-change.html
new file mode 100644 (file)
index 0000000..e1b93d0
--- /dev/null
@@ -0,0 +1,132 @@
+<html>
+    <head>
+        <title>zoom</title>
+        <!--[if IE]>
+        <script type="text/javascript" src="../excanvas.js"></script>
+        <![endif]-->
+        <script type="text/javascript" src="../strftime/strftime-min.js"></script>
+        <script type="text/javascript" src="../rgbcolor/rgbcolor.js"></script>
+        <script type="text/javascript" src="../dygraph-canvas.js"></script>
+        <script type="text/javascript" src="../dygraph.js"></script>
+        <script type="text/javascript" src="data.js"></script>
+    </head>
+    <body>
+        <h3>Click the buttons to change the date and value windows of the chart.</h3>
+        <h4>Window coordinates (in dates and values):</h4>
+        <div id="xdimensions"></div> <div id="ydimensions"></div>
+        <br />
+        <div>
+            <p>
+                Toggle the check box below to determine the difference in operation of the zoom flags
+                when the date and value windows of the chart are changed using the arrows underneath.
+            </p>
+            <input id="noZoomFlagChange" type="checkbox" checked=true>Do not change zoom
+        </div>
+
+        <div style="float: right">
+            <p>Zoomed: <span id="zoomed">False</span><p/>
+            <p>Zoomed X: <span id="zoomedX">False</span><p/>
+            <p>Zoomed Y: <span id="zoomedY">False</span><p/>
+        </div>
+        <div style="float: left">
+            <p><input type="button" value="&uarr;" onclick="adjustTop(+1)"></p>
+            <p><input type="button" value="&darr;" onclick="adjustTop(-1)"></p>
+            <p>
+                <input type="button" value="&larr;" onclick="adjustFirst(-100000000)">
+                    <input type="button" value="&rarr;" onclick="adjustFirst(+100000000)">
+            </p>
+            <p><input type="button" value="&uarr;" onclick="adjustBottom(+1)"></p>
+            <p><input type="button" value="&darr;" onclick="adjustBottom(-1)"></p>
+        </div>
+        <div id="div_g" style="width: 600px; height: 300px; float: left"></div>
+        <div style="float: left">
+            <p>
+                <input type="button" value="&larr;" onclick="adjustLast(-100000000)">
+                <input type="button" value="&rarr;" onclick="adjustLast(+100000000)">
+            </p>
+        </div>
+        <script type="text/javascript">
+            g = new Dygraph(
+                document.getElementById("div_g"),
+                NoisyData,
+                {
+                    errorBars: true,
+                    zoomCallback : function(minDate, maxDate, yRange) {
+                        showDimensions(minDate, maxDate, yRange);
+                    },
+                    drawCallback: function(me, initial) {
+                        document.getElementById("zoomed").innerHTML = "" + me.isZoomed();
+                        document.getElementById("zoomedX").innerHTML = "" + me.isZoomed("x");
+                        document.getElementById("zoomedY").innerHTML = "" + me.isZoomed("y");
+                        var x_range = me.xAxisRange()
+                        var elem = document.getElementById("xdimensions")
+                        elem.innerHTML = "dateWindow : [" + x_range[0] + ", "+ x_range[1] + "]"
+                    }
+                }
+            )
+
+            // Pull an initial value for logging.
+            var minDate = g.xAxisRange()[0];
+            var maxDate = g.xAxisRange()[1];
+            var minValue = g.yAxisRange()[0];
+            var maxValue = g.yAxisRange()[1];
+            showDimensions(minDate, maxDate, [minValue, maxValue]);
+
+            function showDimensions(minDate, maxDate, yRanges) {
+              showXDimensions(minDate, maxDate);
+              showYDimensions(yRanges);
+            }
+
+            function getNoChange() {
+                var options = {}
+                var elem = document.getElementById("noZoomFlagChange")
+                if (elem.checked) {
+                    options.noZoomFlagChange = true
+                }
+                return options
+            }
+
+            function adjustTop(value) {
+                options = getNoChange()
+                maxValue += value
+                options.valueRange = [minValue, maxValue]
+                console.log(options)
+                g.updateOptions(options)
+            }
+
+            function adjustBottom(value) {
+                options = getNoChange()
+                minValue += value
+                options.valueRange = [minValue, maxValue]
+                console.log(options)
+                g.updateOptions(options)
+            }
+
+            function adjustFirst(value) {
+                options = getNoChange()
+                minDate += value
+                options.dateWindow = [minDate, maxDate]
+                console.log(options)
+                g.updateOptions(options)
+            }
+
+            function adjustLast(value) {
+                options = getNoChange()
+                maxDate += value
+                options.dateWindow = [minDate, maxDate]
+                g.updateOptions(options)
+            }
+
+            function showXDimensions(first, second) {
+              var elem = document.getElementById("xdimensions");
+              elem.innerHTML = "dateWindow : [" + first + ", "+ second + "]";
+            }
+
+            function showYDimensions(ranges) {
+              var elem = document.getElementById("ydimensions");
+              elem.innerHTML = "valueRange : [" + ranges + "]";
+            }
+
+        </script>
+    </body>
+</html>