Merge pull request #674 from danvk/module
[dygraphs.git] / src / extras / synchronizer.js
index 16e4d96..bf5b6f3 100644 (file)
 /* global Dygraph:false */
 'use strict';
 
-Dygraph.synchronize = function(/* dygraphs..., opts */) {
+var Dygraph;
+if (window.Dygraph) {
+  Dygraph = window.Dygraph;
+} else if (typeof(module) !== 'undefined') {
+  Dygraph = require('../dygraph');
+}
+
+var synchronize = function(/* dygraphs..., opts */) {
   if (arguments.length === 0) {
     throw 'Invalid invocation of Dygraph.synchronize(). Need >= 1 argument.';
   }
@@ -47,12 +54,7 @@ Dygraph.synchronize = function(/* dygraphs..., opts */) {
     range: true
   };
   var dygraphs = [];
-
-  var prevCallbacks = {
-    draw: null,
-    highlight: null,
-    unhighlight: null
-  };
+  var prevCallbacks = [];
 
   var parseOpts = function(obj) {
     if (!(obj instanceof Object)) {
@@ -100,12 +102,23 @@ Dygraph.synchronize = function(/* dygraphs..., opts */) {
     throw 'Invalid invocation of Dygraph.synchronize(). ' +
           'Need two or more dygraphs to synchronize.';
   }
-  
+
   var readycount = dygraphs.length;
   for (var i = 0; i < dygraphs.length; i++) {
     var g = dygraphs[i];
     g.ready( function() {
       if (--readycount == 0) {
+        // store original callbacks
+        var callBackTypes = ['drawCallback', 'highlightCallback', 'unhighlightCallback'];
+        for (var j = 0; j < dygraphs.length; j++) {
+          if (!prevCallbacks[j]) {
+            prevCallbacks[j] = {};
+          }
+          for (var k = callBackTypes.length - 1; k >= 0; k--) {
+            prevCallbacks[j][callBackTypes[k]] = dygraphs[j].getFunctionOption(callBackTypes[k]);
+          }
+        }
+
         // Listen for draw, highlight, unhighlight callbacks.
         if (opts.zoom) {
           attachZoomHandlers(dygraphs, opts, prevCallbacks);
@@ -117,18 +130,18 @@ Dygraph.synchronize = function(/* dygraphs..., opts */) {
       }
     });
   }
+
   return {
     detach: function() {
       for (var i = 0; i < dygraphs.length; i++) {
         var g = dygraphs[i];
         if (opts.zoom) {
-          g.updateOptions({drawCallback: prevCallbacks.draw});
+          g.updateOptions({drawCallback: prevCallbacks[i].drawCallback});
         }
         if (opts.selection) {
           g.updateOptions({
-            highlightCallback: prevCallbacks.highlight,
-            unhighlightCallback: prevCallbacks.unhighlight
+            highlightCallback: prevCallbacks[i].highlightCallback,
+            unhighlightCallback: prevCallbacks[i].unhighlightCallback
           });
         }
       }
@@ -144,10 +157,8 @@ function attachZoomHandlers(gs, syncOpts, prevCallbacks) {
   var block = false;
   for (var i = 0; i < gs.length; i++) {
     var g = gs[i];
-    prevCallbacks.draw = g.getFunctionOption('drawCallback');
     g.updateOptions({
       drawCallback: function(me, initial) {
-        if (prevCallbacks.draw) prevCallbacks.draw(me, initial);
         if (block || initial) return;
         block = true;
         var opts = {
@@ -156,12 +167,17 @@ function attachZoomHandlers(gs, syncOpts, prevCallbacks) {
         if (syncOpts.range) opts.valueRange = me.yAxisRange();
 
         for (var j = 0; j < gs.length; j++) {
-          if (gs[j] == me) continue;
+          if (gs[j] == me) {
+            if (prevCallbacks[j] && prevCallbacks[j].drawCallback) {
+              prevCallbacks[j].drawCallback.apply(this, arguments);
+            }
+            continue;
+          }
           gs[j].updateOptions(opts);
         }
         block = false;
       }
-    }, false /* no need to redraw */);
+    }, true /* no need to redraw */);
   }
 }
 
@@ -169,18 +185,19 @@ function attachSelectionHandlers(gs, prevCallbacks) {
   var block = false;
   for (var i = 0; i < gs.length; i++) {
     var g = gs[i];
-    prevCallbacks.highlight = g.getFunctionOption('highlightCallback');
-    prevCallbacks.unhighlight = g.getFunctionOption('unhighlightCallback');
+
     g.updateOptions({
       highlightCallback: function(event, x, points, row, seriesName) {
-        if (prevCallbacks.highlight) {
-            prevCallbacks.highlight(event, x, points, row, seriesName);
-        }
         if (block) return;
         block = true;
         var me = this;
         for (var i = 0; i < gs.length; i++) {
-          if (me == gs[i]) continue;
+          if (me == gs[i]) {
+            if (prevCallbacks[i] && prevCallbacks[i].highlightCallback) {
+              prevCallbacks[i].highlightCallback.apply(this, arguments);
+            }
+            continue;
+          }
           var idx = gs[i].getRowForX(x);
           if (idx !== null) {
             gs[i].setSelection(idx, seriesName);
@@ -189,18 +206,24 @@ function attachSelectionHandlers(gs, prevCallbacks) {
         block = false;
       },
       unhighlightCallback: function(event) {
-        if (prevCallbacks.unhighlight) prevCallbacks.unhighlight(event);
         if (block) return;
         block = true;
         var me = this;
         for (var i = 0; i < gs.length; i++) {
-          if (me == gs[i]) continue;
+          if (me == gs[i]) {
+            if (prevCallbacks[i] && prevCallbacks[i].unhighlightCallback) {
+              prevCallbacks[i].unhighlightCallback.apply(this, arguments);
+            }
+            continue;
+          }
           gs[i].clearSelection();
         }
         block = false;
       }
-    });
+    }, true /* no need to redraw */);
   }
 }
 
+Dygraph.synchronize = synchronize;
+
 })();