Initial OpenECOMP Portal commit
[portal.git] / ecomp-portal-BE / war / static / fusion / d3 / js / horizon.js
diff --git a/ecomp-portal-BE/war/static/fusion/d3/js/horizon.js b/ecomp-portal-BE/war/static/fusion/d3/js/horizon.js
new file mode 100644 (file)
index 0000000..d84c656
--- /dev/null
@@ -0,0 +1,192 @@
+(function() {
+  d3.horizon = function() {
+    var bands = 1, // between 1 and 5, typically
+        mode = "offset", // or mirror
+        interpolate = "linear", // or basis, monotone, step-before, etc.
+        x = d3_horizonX,
+        y = d3_horizonY,
+        w = 960,
+        h = 40,
+        duration = 0;
+
+    var color = d3.scale.linear()
+        .domain([-1, 0, 1])
+        .range(["#d62728", "#fff", "#1f77b4"]);
+
+    // For each small multiple…
+    function horizon(g) {
+      g.each(function(d, i) {
+        var g = d3.select(this),
+            n = 2 * bands + 1,
+            xMin = Infinity,
+            xMax = -Infinity,
+            yMax = -Infinity,
+            x0, // old x-scale
+            y0, // old y-scale
+            id; // unique id for paths
+
+        // Compute x- and y-values along with extents.
+        var data = d.map(function(d, i) {
+          var xv = x.call(this, d, i),
+              yv = y.call(this, d, i);
+          if (xv < xMin) xMin = xv;
+          if (xv > xMax) xMax = xv;
+          if (-yv > yMax) yMax = -yv;
+          if (yv > yMax) yMax = yv;
+          return [xv, yv];
+        });
+
+        // Compute the new x- and y-scales, and transform.
+        var x1 = d3.scale.linear().domain([xMin, xMax]).range([0, w]),
+            y1 = d3.scale.linear().domain([0, yMax]).range([0, h * bands]),
+            t1 = d3_horizonTransform(bands, h, mode);
+
+        // Retrieve the old scales, if this is an update.
+        if (this.__chart__) {
+          x0 = this.__chart__.x;
+          y0 = this.__chart__.y;
+          t0 = this.__chart__.t;
+          id = this.__chart__.id;
+        } else {
+          x0 = x1.copy();
+          y0 = y1.copy();
+          t0 = t1;
+          id = ++d3_horizonId;
+        }
+
+        // We'll use a defs to store the area path and the clip path.
+        var defs = g.selectAll("defs")
+            .data([null]);
+
+        // The clip path is a simple rect.
+        defs.enter().append("defs").append("clipPath")
+            .attr("id", "d3_horizon_clip" + id)
+          .append("rect")
+            .attr("width", w)
+            .attr("height", h);
+
+        defs.select("rect").transition()
+            .duration(duration)
+            .attr("width", w)
+            .attr("height", h);
+
+        // We'll use a container to clip all horizon layers at once.
+        g.selectAll("g")
+            .data([null])
+          .enter().append("g")
+            .attr("clip-path", "url(#d3_horizon_clip" + id + ")");
+
+        // Instantiate each copy of the path with different transforms.
+        var path = g.select("g").selectAll("path")
+            .data(d3.range(-1, -bands - 1, -1).concat(d3.range(1, bands + 1)), Number);
+
+        var d0 = d3_horizonArea
+            .interpolate(interpolate)
+            .x(function(d) { return x0(d[0]); })
+            .y0(h * bands)
+            .y1(function(d) { return h * bands - y0(d[1]); })
+            (data);
+
+        var d1 = d3_horizonArea
+            .x(function(d) { return x1(d[0]); })
+            .y1(function(d) { return h * bands - y1(d[1]); })
+            (data);
+
+        path.enter().append("path")
+            .style("fill", color)
+            .attr("transform", t0)
+            .attr("d", d0);
+
+        path.transition()
+            .duration(duration)
+            .style("fill", color)
+            .attr("transform", t1)
+            .attr("d", d1);
+
+        path.exit().transition()
+            .duration(duration)
+            .attr("transform", t1)
+            .attr("d", d1)
+            .remove();
+
+        // Stash the new scales.
+        this.__chart__ = {x: x1, y: y1, t: t1, id: id};
+      });
+      d3.timer.flush();
+    }
+
+    horizon.duration = function(x) {
+      if (!arguments.length) return duration;
+      duration = +x;
+      return horizon;
+    };
+
+    horizon.bands = function(x) {
+      if (!arguments.length) return bands;
+      bands = +x;
+      color.domain([-bands, 0, bands]);
+      return horizon;
+    };
+
+    horizon.mode = function(x) {
+      if (!arguments.length) return mode;
+      mode = x + "";
+      return horizon;
+    };
+
+    horizon.colors = function(x) {
+      if (!arguments.length) return color.range();
+      color.range(x);
+      return horizon;
+    };
+
+    horizon.interpolate = function(x) {
+      if (!arguments.length) return interpolate;
+      interpolate = x + "";
+      return horizon;
+    };
+
+    horizon.x = function(z) {
+      if (!arguments.length) return x;
+      x = z;
+      return horizon;
+    };
+
+    horizon.y = function(z) {
+      if (!arguments.length) return y;
+      y = z;
+      return horizon;
+    };
+
+    horizon.width = function(x) {
+      if (!arguments.length) return w;
+      w = +x;
+      return horizon;
+    };
+
+    horizon.height = function(x) {
+      if (!arguments.length) return h;
+      h = +x;
+      return horizon;
+    };
+
+    return horizon;
+  };
+
+  var d3_horizonArea = d3.svg.area(),
+      d3_horizonId = 0;
+
+  function d3_horizonX(d) {
+    return d[0];
+  }
+
+  function d3_horizonY(d) {
+    return d[1];
+  }
+
+  function d3_horizonTransform(bands, h, mode) {
+    return mode == "offset"
+        ? function(d) { return "translate(0," + (d + (d < 0) - bands) * h + ")"; }
+        : function(d) { return (d < 0 ? "scale(1,-1)" : "") + "translate(0," + (d - bands) * h + ")"; };
+  }
+})();