summaryrefslogtreecommitdiffstats
path: root/debian/missing-sources/epoch/tests
diff options
context:
space:
mode:
Diffstat (limited to 'debian/missing-sources/epoch/tests')
-rw-r--r--debian/missing-sources/epoch/tests/render/basic/area.html450
-rw-r--r--debian/missing-sources/epoch/tests/render/basic/bar.html745
-rw-r--r--debian/missing-sources/epoch/tests/render/basic/histogram.html155
-rw-r--r--debian/missing-sources/epoch/tests/render/basic/line.html471
-rw-r--r--debian/missing-sources/epoch/tests/render/basic/model.html94
-rw-r--r--debian/missing-sources/epoch/tests/render/basic/options.html267
-rw-r--r--debian/missing-sources/epoch/tests/render/basic/pie.html346
-rw-r--r--debian/missing-sources/epoch/tests/render/basic/scatter.html398
-rw-r--r--debian/missing-sources/epoch/tests/render/css/tests.css12
-rw-r--r--debian/missing-sources/epoch/tests/render/index.html57
-rw-r--r--debian/missing-sources/epoch/tests/render/js/data.js210
-rw-r--r--debian/missing-sources/epoch/tests/render/real-time/area.html494
-rw-r--r--debian/missing-sources/epoch/tests/render/real-time/bar.html484
-rw-r--r--debian/missing-sources/epoch/tests/render/real-time/gauge.html283
-rw-r--r--debian/missing-sources/epoch/tests/render/real-time/heatmap.html559
-rw-r--r--debian/missing-sources/epoch/tests/render/real-time/line.html596
-rw-r--r--debian/missing-sources/epoch/tests/render/real-time/model.html85
-rw-r--r--debian/missing-sources/epoch/tests/render/real-time/options.html299
-rw-r--r--debian/missing-sources/epoch/tests/render/themes/dark.html211
-rw-r--r--debian/missing-sources/epoch/tests/render/themes/default.html70
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/charts.coffee573
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/copy.coffee47
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/css.coffee85
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/d3.coffee40
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/events.coffee111
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/format.coffee68
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/is.coffee88
-rw-r--r--debian/missing-sources/epoch/tests/unit/core/util.coffee92
-rw-r--r--debian/missing-sources/epoch/tests/unit/data/array_format.coffee106
-rw-r--r--debian/missing-sources/epoch/tests/unit/data/chart.coffee121
-rw-r--r--debian/missing-sources/epoch/tests/unit/data/keyvalue_format.coffee101
-rw-r--r--debian/missing-sources/epoch/tests/unit/data/tuple_format.coffee76
-rw-r--r--debian/missing-sources/epoch/tests/unit/init.coffee55
-rw-r--r--debian/missing-sources/epoch/tests/unit/time.coffee67
-rw-r--r--debian/missing-sources/epoch/tests/unit/time/line.coffee15
35 files changed, 7931 insertions, 0 deletions
diff --git a/debian/missing-sources/epoch/tests/render/basic/area.html b/debian/missing-sources/epoch/tests/render/basic/area.html
new file mode 100644
index 0000000..ea23851
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/basic/area.html
@@ -0,0 +1,450 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <script src="../js/data.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+ </head>
+ <body>
+ <h1>Basic Area Chart Test</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Basic Area</p>
+
+ <ol>
+ <li><a href="#test-1">Single Series</a></li>
+ <li><a href="#test-2">Single Series II</a></li>
+ <li><a href="#test-3">Multi Series</a></li>
+ <li><a href="#test-4">Multi Series II</a></li>
+ <li><a href="#test-5">Single Series Transition</a></li>
+ <li><a href="#test-6">Multi Series Transition</a></li>
+ <li><a href="#test-7">Single Series to Multi Series Transition</a></li>
+ <li><a href="#test-8">Layer Color Override</a></li>
+ <li><a href="#test-9">Categorical Color Switching</a></li>
+ <li><a href="#test-10">Multi Series without Labels</a></li>
+ <li><a href="#test-11">Hide/Show Layers</a></li>
+ <li><a href="#test-12">Data Format</a></li>
+ </ol>
+
+
+ <!-- Test 1 -->
+ <div id="test-1" class="test">
+ <h2>1. Single Series</h2>
+ <p>It should display a plot of <code>y = cos(x) + 1</code> over the range <code>[0, 2&pi;)</code>.</p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 64;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.cos(x) + 1;
+ data[0].values.push({x: x, y: y});
+ }
+
+ $('#test-1 .epoch').epoch({ type: 'area', data: data });
+ });
+ </script>
+
+
+ <!-- Test 2 -->
+ <div id="test-2" class="test">
+ <h2>2. Single Series II</h2>
+ <p>It should display a plot of <code>y = sin(x) + 1</code> over the range <code>[0, 2&pi;)</code>.</p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 64;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.sin(x) + 1;
+ data[0].values.push({x: x, y: y});
+ }
+
+ $('#test-2 .epoch').epoch({ type: 'area', data: data });
+ });
+ </script>
+
+
+ <!-- Test 3 -->
+ <div id="test-3" class="test">
+ <h2>3. Multi-series Plot</h2>
+ <p>
+ It should display a plot of the following functions stacked atop one another:
+ <ul>
+ <li><code>y = x</code></li>
+ <li><code>y = 2x</code></li>
+ <li><code>y = 3x</code></li>
+ </ul>
+ over the range <code>[0, 10)</code>.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function(){
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 32;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 10 / length;
+ data[0].values.push({x: x, y: x});
+ data[1].values.push({x: x, y: 2*x});
+ data[2].values.push({x: x, y: 3*x});
+ }
+
+ $('#test-3 .epoch').epoch({ type: 'area', data: data });
+ });
+ </script>
+
+
+ <!-- Test 4 -->
+ <div id="test-4" class="test">
+ <h2>4. Multi-series Plot II</h2>
+ <p>
+ It should display a plot of the following functions stacked atop one another:
+ <ul>
+ <li><code>y = |x|</code></li>
+ <li><code>y = x<sup>2</sup></code></li>
+ <li><code>y = |x<sup>3</sup>|</code></li>
+ </ul>
+ over the range [-1, 1).
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 64;
+
+ for (var i = 0; i < length; i++) {
+ var x = (i - length / 2) / (length / 2);
+ data[0].values.push({x: x, y: Math.abs(x)});
+ data[1].values.push({x: x, y: Math.pow(x, 2)});
+ data[2].values.push({x: x, y: Math.abs(Math.pow(x, 3))});
+ }
+
+ $('#test-4 .epoch').epoch({ type: 'area', data: data });
+ });
+ </script>
+
+
+ <!-- Test 5 -->
+ <div id="test-5" class="test">
+ <h2>5. Single Series Transition</h2>
+ <p>
+ It should correctly transition between the plots <code>y = |x|</code> over the range [-10, 10) and <code>y = x<sup>2</sup></code> over the range [-20, 20). The transition should be initiated when pressing the buttons below the plot.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">y = x</button>
+ <button data-index="1">y = x^2</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data1 = [{label: 'A', values: []}],
+ data2 = [{label: 'B', values: []}],
+ data = [data1, data2],
+ length = 64;
+
+ for (var i = 0; i < length; i++) {
+ var x1 = (i - length / 2) * 10 / (length / 2),
+ y1 = Math.abs(x1),
+ x2 = (i - length / 2) * 20 / (length / 2),
+ y2 = Math.pow(x2, 2);
+ data1[0].values.push({x: x1, y: y1});
+ data2[0].values.push({x: x2, y: y2});
+ }
+
+ var chart = $('#test-5 .epoch').epoch({
+ type: 'area',
+ data: data1
+ });
+
+ $('#test-5 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+ <!-- Test 6 -->
+ <div id="test-6" class="test">
+ <h2>6. Multi Series Transition</h2>
+ <p>
+ It should correctly render and transition between Set A:
+ <ul>
+ <li><code>y = x</code></li>
+ <li><code>y = 2*x</code></li>
+ <li><code>y = 3*x</code></li>
+ </ul>
+ over the range [1, 100). and Set B:
+ <ul>
+ <li><code>y = ln(x)</code></li>
+ <li><code>y = 2*ln(x)</code></li>
+ <li><code>y = 3*ln(x)</code></li>
+ </ul>
+ over the range [1, 100). The transition should be initiated when pressing the buttons below the plot.
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Set A</button>
+ <button data-index="1">Set B</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data1 = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ];
+
+ var data2 = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ];
+
+ var data = [data1, data2],
+ length = 128;
+
+ for (var i = 0; i < length; i++) {
+ var x = (i * 99 / length) + 1;
+
+ data1[0].values.push({x: x, y: x});
+ data1[1].values.push({x: x, y: 2*x});
+ data1[2].values.push({x: x, y: 3*x});
+
+ data2[0].values.push({x: x, y: Math.log(x)});
+ data2[1].values.push({x: x, y: 2*Math.log(x)});
+ data2[2].values.push({x: x, y: 3*Math.log(x)});
+ }
+
+ var chart = $('#test-6 .epoch').epoch({ type: 'area', data: data1 });
+
+ $('#test-6 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+
+ <!-- Test 7 -->
+ <div id="test-7" class="test">
+ <h2>7. Single Series to Multi Series Transition</h2>
+ <p>
+ It should correctly transition between a single series, plotting the functions:
+ <ul>
+ <li><code>y = x<sup>2</sup> - 0.5*x</code></li>
+ </ul>
+ To a multi series set, plotting the functions:
+ <ul>
+ <li><code>y = ln(x)</code></li>
+ <li><code>y = x</code></li>
+ <li><code>y = x * ln(x)</code></li>
+ </ul>
+ over the range [1, 4) for all plots. The transition should be initiated when pressing the buttons below the plot.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Single</button>
+ <button data-index="1">Multi</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data1 = [{label: 'A', values: []}],
+ data2 = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ data = [data1, data2],
+ length = 64;
+
+ for (var i = 0; i < length; i++) {
+ var x = (3*i/length) + 1;
+ data1[0].values.push({x: x, y: x*x - 0.5*x});
+ data2[0].values.push({x: x, y: Math.log(x)});
+ data2[1].values.push({x: x, y: x});
+ data2[2].values.push({x: x, y: x * Math.log(x)});
+ }
+
+ var chart = $('#test-7 .epoch').epoch({ type: 'area', data: data1 });
+
+ $('#test-7 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+ <!-- Test 8 -->
+ <div id="test-8" class="test">
+ <h2>8. Layer Color Override</h2>
+ <p>
+ It should display the first layer of the plot as pink, the second layer as green, and the third layer as blue.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <style>
+ #test-8 .epoch .a .area { fill: pink; }
+ #test-8 .epoch .b .area { fill: green; }
+ #test-8 .epoch .c .area { fill: blue; }
+ </style>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 128;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 10 / length + 1,
+ y = x * Math.log(x);
+ for (var j = 0; j < data.length; j++) {
+ data[j].values.push({x: x, y: y});
+ }
+ }
+
+ $('#test-8 .epoch').epoch({ type: 'area', data: data });
+ });
+ </script>
+
+ <!-- Test 9 -->
+ <div id="test-9" class="test">
+ <h2>9. Categorical Color Switching</h3>
+ <p>
+ It should change layer colors automatically when switching between the following categorical color classes on the containing element:
+ <ul>
+ <li><code>category10</code></li>
+ <li><code>category20</code></li>
+ <li><code>category20b</code></li>
+ <li><code>category20c</code></li>
+ </ul>
+ The colors should change when pressing the buttons for each categorical type below the chart.
+ </p>
+
+ <div class="epoch category10"></div>
+
+ <p>
+ <button data-class="category10">category10</button>
+ <button data-class="category20">category20</button>
+ <button data-class="category20b">category20b</button>
+ <button data-class="category20c">category20c</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []},
+ {label: 'D', values: []},
+ {label: 'E', values: []},
+ {label: 'F', values: []},
+ {label: 'G', values: []}
+ ],
+ length = 128,
+ className = 'category10';
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 1 / length;
+ for (var j = 0; j < data.length; j++) {
+ data[j].values.push({x: x, y: Math.pow(x, j+1)});
+ }
+ }
+
+ $('#test-9 .epoch').epoch({ type: 'area', data: data });
+
+ $('#test-9 button').on('click', function(e) {
+ $('#test-9 .epoch').removeClass(className);
+ className = $(e.target).attr('data-class');
+ $('#test-9 .epoch').addClass(className);
+ });
+ });
+ </script>
+
+ <!-- Test 10 -->
+ <div id="test-10" class="test">
+ <h2>10. Multi Series without Labels</h2>
+ <p>
+ Correctly render a multi-series plot of:
+ <ul>
+ <li><code>y = sin(x) + 1</code></li>
+ <li><code>y = cos(x) + 1</code></li>
+ </ul>
+ where the layers are given without labels.
+ </p>
+ <div class="epoch"></div>
+ </div>
+ <script>
+ $(function() {
+ var data = [{values: []}, {values: []}],
+ length = 128;
+
+ for (var i = 0; i <= length; i++) {
+ var x = i * 4 * Math.PI / length;
+ data[0].values.push({x: x, y: Math.sin(x) + 1});
+ data[1].values.push({x: x, y: Math.cos(x) + 1});
+ }
+
+ $('#test-10 .epoch').epoch({ type: 'area', data: data });
+ });
+ </script>
+
+ <!-- Test 11 -->
+ <div id="test-11" class="test">
+ <h2>11. Hide/Show Layers</h2>
+ <p>Correctly hide and show multiple layers</p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Toggle A</button>
+ <button data-index="1">Toggle B</button>
+ <button data-index="2">Toggle C</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var chart = $('#test-11 .epoch').epoch({
+ type: 'area',
+ data: data().add(function(x) { return x; })
+ .add(function(x) { return 1.5*x; })
+ .add(function(x) { return 2.0*x; }).get([0, 10], 1)
+ });
+
+ $('#test-11 button').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.toggleLayer(index);
+ });
+ });
+ </script>
+
+ </body>
+</html>
diff --git a/debian/missing-sources/epoch/tests/render/basic/bar.html b/debian/missing-sources/epoch/tests/render/basic/bar.html
new file mode 100644
index 0000000..07b5122
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/basic/bar.html
@@ -0,0 +1,745 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <script src="../js/data.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+ </head>
+ <body>
+ <h1>Basic Bar Chart Test</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Basic Bar</p>
+
+ <ol>
+ <li><a href="#test-1">Single Series</a></li>
+ <li><a href="#test-2">Single Series II</a></li>
+ <li><a href="#test-3">Multi Series</a></li>
+ <li><a href="#test-4">Multi Series II</a></li>
+ <li><a href="#test-5">Single Series Transition</a></li>
+ <li><a href="#test-6">Multi Series Transition</a></li>
+ <li><a href="#test-7">Single Series to Multi Series Transition</a></li>
+ <li><a href="#test-8">Layer Color Override</a></li>
+ <li><a href="#test-9">Categorical Color Switching</a></li>
+ <li><a href="#test-10">Multi Series without Labels</a></li>
+ <li><a href="#test-11">Horizontally Oriented Single Series</a></li>
+ <li><a href="#test-12">Horizontally Oriented Multi Series</a></li>
+ <li><a href="#test-13">Horizontally Oriented Multi Series Transition</a></li>
+ <li><a href="#test-14">Vertical to Horizontal Transition</a></li>
+ <li><a href="#test-15">Padding Changes</a></li>
+ <li><a href="#test-16">Hide/Show Layers</a></li>
+ <li><a href="#test-17">Data Formatting</a></li>
+ <li><a href="#test-18">Many bars</a></li>
+ </ol>
+
+
+ <!-- Test 1 -->
+ <div id="test-1" class="test">
+ <h2>1. Single Series</h2>
+ <p>Display a plot of <code>y = cos(x) + 1</code> over the range <code>[0, 2&pi;)</code>.</p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 32;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.cos(x) + 1;
+ data[0].values.push({x: x, y: y});
+ }
+
+ $('#test-1 .epoch').epoch({
+ type: 'bar',
+ data: data,
+ tickFormats: {
+ bottom: function(d) {
+ return parseFloat(d).toFixed(1);
+ }
+ }
+ });
+ });
+ </script>
+
+
+ <!-- Test 2 -->
+ <div id="test-2" class="test">
+ <h2>2. Single Series II</h2>
+ <p>Display a plot of <code>y = sin(x) + 1</code> over the range <code>[0, 2&pi;)</code>.</p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 32;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.sin(x) + 1;
+ data[0].values.push({x: x, y: y});
+ }
+
+ $('#test-2 .epoch').epoch({
+ type: 'bar',
+ data: data,
+ tickFormats: {
+ bottom: function(d) {
+ return parseFloat(d).toFixed(1);
+ }
+ }
+ });
+ });
+ </script>
+
+
+ <!-- Test 3 -->
+ <div id="test-3" class="test">
+ <h2>3. Multi-series Plot</h2>
+ <p>
+ Display a plot of the following functions stacked atop one another:
+ <ul>
+ <li><code>y = x</code></li>
+ <li><code>y = 2x</code></li>
+ <li><code>y = 3x</code></li>
+ </ul>
+ over the range <code>[0, 10)</code>.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function(){
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 10;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 10 / length;
+ data[0].values.push({x: x, y: x});
+ data[1].values.push({x: x, y: 2*x});
+ data[2].values.push({x: x, y: 3*x});
+ }
+
+ $('#test-3 .epoch').epoch({
+ type: 'bar',
+ data: data
+ });
+ });
+ </script>
+
+
+ <!-- Test 4 -->
+ <div id="test-4" class="test">
+ <h2>4. Multi-series Plot II</h2>
+ <p>
+ Display a plot of the following functions stacked atop one another:
+ <ul>
+ <li><code>y = |x|</code></li>
+ <li><code>y = x<sup>2</sup></code></li>
+ <li><code>y = |x<sup>3</sup>|</code></li>
+ </ul>
+ over the range [-1, 1).
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 20;
+
+ for (var i = 0; i < length; i++) {
+ var x = (i - length / 2) / (length / 2);
+ data[0].values.push({x: x, y: Math.abs(x)});
+ data[1].values.push({x: x, y: Math.pow(x, 2)});
+ data[2].values.push({x: x, y: Math.abs(Math.pow(x, 3))});
+ }
+
+ $('#test-4 .epoch').epoch({ type: 'bar', data: data });
+ });
+ </script>
+
+
+ <!-- Test 5 -->
+ <div id="test-5" class="test">
+ <h2>5. Single Series Transition</h2>
+ <p>
+ Correctly transition between the plots <code>y = |x|</code> over the range [-10, 10) and <code>y = x<sup>2</sup></code> over the range [-20, 20). The transition is initiated by pressing the buttons below the plot.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">y = x</button>
+ <button data-index="1">y = x^2</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data1 = [{label: 'A', values: []}],
+ data2 = [{label: 'B', values: []}],
+ data = [data1, data2],
+ length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x1 = (i - length / 2) * 10 / (length / 2),
+ y1 = Math.abs(x1),
+ x2 = (i - length / 2) * 20 / (length / 2),
+ y2 = Math.pow(x2, 2);
+ data1[0].values.push({x: x1, y: y1});
+ data2[0].values.push({x: x2, y: y2});
+ }
+
+ var chart = $('#test-5 .epoch').epoch({
+ type: 'bar',
+ data: data1
+ });
+
+ $('#test-5 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+ <!-- Test 6 -->
+ <div id="test-6" class="test">
+ <h2>6. Multi Series Transition</h2>
+ <p>
+ Correctly render and transition between Set A:
+ <ul>
+ <li><code>y = x</code></li>
+ <li><code>y = 2*x</code></li>
+ <li><code>y = 3*x</code></li>
+ </ul>
+ over the range [1, 100). and Set B:
+ <ul>
+ <li><code>y = ln(x)</code></li>
+ <li><code>y = 2*ln(x)</code></li>
+ <li><code>y = 3*ln(x)</code></li>
+ </ul>
+ over the range [1, 100). The transition is initiated by pressing the buttons below the plot.
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Set A</button>
+ <button data-index="1">Set B</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data1 = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ];
+
+ var data2 = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ];
+
+ var data = [data1, data2],
+ length = 10;
+
+ for (var i = 0; i < length; i++) {
+ var x = (i * 100 / length) + 1;
+
+ data1[0].values.push({x: x, y: x});
+ data1[1].values.push({x: x, y: 2*x});
+ data1[2].values.push({x: x, y: 3*x});
+
+ data2[0].values.push({x: x, y: Math.log(x)});
+ data2[1].values.push({x: x, y: 2*Math.log(x)});
+ data2[2].values.push({x: x, y: 3*Math.log(x)});
+ }
+
+ var chart = $('#test-6 .epoch').epoch({ type: 'bar', data: data1 });
+
+ $('#test-6 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+
+ <!-- Test 7 -->
+ <div id="test-7" class="test">
+ <h2>7. Single Series to Multi Series Transition</h2>
+ <p>
+ Correctly transition between a single series, plotting the functions:
+ <ul>
+ <li><code>y = x<sup>2</sup> - 0.5*x</code></li>
+ </ul>
+ To a multi series set, plotting the functions:
+ <ul>
+ <li><code>y = ln(x)</code></li>
+ <li><code>y = x</code></li>
+ <li><code>y = x * ln(x)</code></li>
+ </ul>
+ over the range [1, 4) for all plots. The transition is initiated by pressing the buttons below the plot.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Single</button>
+ <button data-index="1">Multi</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data1 = [{label: 'A', values: []}],
+ data2 = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ data = [data1, data2],
+ length = 32;
+
+ for (var i = 0; i < length; i++) {
+ var x = (3*i/length) + 1;
+ data1[0].values.push({x: x, y: x*x - 0.5*x});
+ data2[0].values.push({x: x, y: Math.log(x)});
+ data2[1].values.push({x: x, y: x});
+ data2[2].values.push({x: x, y: x * Math.log(x)});
+ }
+
+ var chart = $('#test-7 .epoch').epoch({
+ type: 'bar',
+ data: data1,
+ tickFormats: {
+ bottom: function(d) { return d.toFixed(1); }
+ }
+ });
+
+ $('#test-7 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+ <!-- Test 8 -->
+ <div id="test-8" class="test">
+ <h2>8. Layer Color Override</h2>
+ <p>
+ Display the first layer of the plot as pink, the second layer as green, and the third layer as blue.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <style>
+ #test-8 .epoch .bar.a { fill: pink; }
+ #test-8 .epoch .bar.b { fill: green; }
+ #test-8 .epoch .bar.c { fill: blue; }
+ </style>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 10;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 10 / length + 1,
+ y = x * Math.log(x);
+ for (var j = 0; j < data.length; j++) {
+ data[j].values.push({x: x, y: y});
+ }
+ }
+
+ $('#test-8 .epoch').epoch({ type: 'bar', data: data });
+ });
+ </script>
+
+ <!-- Test 9 -->
+ <div id="test-9" class="test">
+ <h2>9. Categorical Color Switching</h3>
+ <p>
+ Change layer colors automatically when switching between the following categorical color classes on the containing element:
+ <ul>
+ <li><code>category10</code></li>
+ <li><code>category20</code></li>
+ <li><code>category20b</code></li>
+ <li><code>category20c</code></li>
+ </ul>
+ Change the categorical colors by pressing the buttons below the chart.
+ </p>
+
+ <div class="epoch category10"></div>
+
+ <p>
+ <button data-class="category10">category10</button>
+ <button data-class="category20">category20</button>
+ <button data-class="category20b">category20b</button>
+ <button data-class="category20c">category20c</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []},
+ {label: 'D', values: []},
+ {label: 'E', values: []},
+ {label: 'F', values: []},
+ {label: 'G', values: []}
+ ],
+ length = 4,
+ className = 'category10';
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 1 / length;
+ for (var j = 0; j < data.length; j++) {
+ data[j].values.push({x: x, y: Math.pow(x, j+1)});
+ }
+ }
+
+ $('#test-9 .epoch').epoch({
+ type: 'bar',
+ data: data,
+ tickFormats: {
+ bottom: function(d) { return d.toFixed(1); }
+ }
+ });
+
+ $('#test-9 button').on('click', function(e) {
+ $('#test-9 .epoch').removeClass(className);
+ className = $(e.target).attr('data-class');
+ $('#test-9 .epoch').addClass(className);
+ });
+ });
+ </script>
+
+ <!-- Test 10 -->
+ <div id="test-10" class="test">
+ <h2>10. Multi Series without Labels</h2>
+ <p>
+ Correctly render a multi-series plot of:
+ <ul>
+ <li><code>y = sin(x) + 1</code></li>
+ <li><code>y = cos(x) + 1</code></li>
+ </ul>
+ where the layers are given without labels.
+ </p>
+ <div class="epoch"></div>
+ </div>
+ <script>
+ $(function() {
+ var data = [{values: []}, {values: []}],
+ length = 32;
+
+ for (var i = 0; i <= length; i++) {
+ var x = i * 4 * Math.PI / length;
+ data[0].values.push({x: x, y: Math.sin(x) + 1});
+ data[1].values.push({x: x, y: Math.cos(x) + 1});
+ }
+
+ $('#test-10 .epoch').epoch({
+ type: 'bar',
+ data: data,
+ tickFormats: {
+ bottom: function(d) { return d.toFixed(1); }
+ }
+ });
+ });
+ </script>
+
+ <!-- Test 11 -->
+ <div id="test-11" class="test">
+ <h2>11. Horizontally Oriented Single Series</h2>
+ <p>
+ Correctly render the single series plot of:
+ <ul>
+ <li>A - 20</li>
+ <li>B - 30</li>
+ <li>C - 60</li>
+ </ul>
+ using a horizontal orientation.
+ </p>
+ <div class="epoch"></div>
+ </div>
+ <script>
+ $(function() {
+ var data = [{values: [
+ {x: 'A', y: 20},
+ {x: 'B', y: 30},
+ {x: 'C', y: 60}
+ ]}];
+
+ $('#test-11 .epoch').epoch({
+ type: 'bar',
+ orientation: 'horizontal',
+ data: data
+ });
+ });
+ </script>
+
+ <!-- Test 12 -->
+ <div id="test-12" class="test">
+ <h2>12. Horizontally Oriented Multi Series</h2>
+ <p>
+ Correctly render the multi series plot of:
+ <ul>
+ <li>A - 10, 30</li>
+ <li>B - 20, 50</li>
+ <li>C - 60, 10</li>
+ </ul>
+ using a horizontal orientation.
+ </p>
+ <div class="epoch"></div>
+ </div>
+ <script>
+ $(function() {
+ var data = [
+ { values: [{x: 'A', y: 10}, {x: 'B', y: 20}, {x: 'C', y: 60}] },
+ { values: [{x: 'A', y: 30}, {x: 'B', y: 50}, {x: 'C', y: 10}] }
+ ];
+
+ $('#test-12 .epoch').epoch({
+ type: 'bar',
+ orientation: 'horizontal',
+ data: data
+ });
+ });
+ </script>
+
+ <!-- Test 13 -->
+ <div id="test-13" class="test">
+ <h2>13. Horizontally Oriented Multi Series Transition</h2>
+ <p>
+ Correctly render the Horizontally oriented multi series plot of:
+ <ul>
+ <li>A - 10, 10</li>
+ <li>B - 20, 20</li>
+ <li>C - 30, 30</li>
+ </ul>
+ and transition to the single series plot:
+ <ul>
+ <li>A - 5</li>
+ <li>B - 10</li>
+ <li>C - 40</li>
+ </ul>
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Multi</button>
+ <button data-index="1">Single</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var data1 = [
+ { values: [{x: 'A', y: 10}, {x: 'B', y: 20}, {x: 'C', y: 30}] },
+ { values: [{x: 'A', y: 10}, {x: 'B', y: 20}, {x: 'C', y: 30}] }
+ ],
+ data2 = [
+ { values: [{x: 'A', y: 5}, {x: 'B', y: 10}, {x: 'C', y: 40}] }
+ ],
+ data = [data1, data2];
+
+ var chart = $('#test-13 .epoch').epoch({
+ type: 'bar',
+ orientation: 'horizontal',
+ data: data1
+ });
+
+ $('#test-13 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+ <div id="test-14" class="test">
+ <h2>14. Vertical to Horizontal Transition</h2>
+ <div class="epoch"></div>
+ <p>
+ <button data-orientation="vertical">Vertical</button>
+ <button data-orientation="horizontal">Horizontal</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var data = [
+ { values: [{x: 'A', y: 10}, {x: 'B', y: 20}, {x: 'C', y: 30}] },
+ { values: [{x: 'A', y: 10}, {x: 'B', y: 20}, {x: 'C', y: 30}] }
+ ];
+
+ var chart = $('#test-14 .epoch').epoch({
+ type: 'bar',
+ data: data
+ });
+
+ $('#test-14 button').click(function(e) {
+ var orientation = $(e.target).attr('data-orientation');
+ chart.option('orientation', orientation);
+ });
+ });
+ </script>
+
+ <div id="test-15" class="test">
+ <h2>15. Padding Changes</h2>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Regular Padding</button>
+ <button data-index="1">Fat Padding</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var data = [
+ { values: [{x: 'A', y: 10}, {x: 'B', y: 20}, {x: 'C', y: 30}] },
+ { values: [{x: 'A', y: 10}, {x: 'B', y: 20}, {x: 'C', y: 30}] }
+ ];
+
+ var padding = [
+ {
+ padding: { bar: 0.08, group: 0.1 },
+ outerPadding: { bar: 0.08, group: 0.1 }
+ },
+ {
+ padding: { bar: 0.2, group: 0.3 },
+ outerPadding: { bar: 0.1, group: 0.2 }
+ }
+ ];
+
+ var chart = $('#test-15 .epoch').epoch({ type: 'bar', data: data });
+ $('#test-15 button').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.option('padding', padding[index].padding);
+ chart.option('outerPadding', padding[index].outerPadding);
+ });
+ });
+ </script>
+
+ <div id="test-16" class="test">
+ <h2>16. Hide/Show Layers</h2>
+ <div class="epoch"></div>
+ <p>
+ <button class="toggle" data-index="0">Toggle A</button>
+ <button class="toggle" data-index="1">Toggle B</button>
+ <button class="toggle" data-index="2">Toggle C</button>
+ |
+ <button class="orientation">Orientation</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var chart = $('#test-16 .epoch').epoch({
+ type: 'bar',
+ data: data().add(function(x) { return x; })
+ .add(function(x) { return 1.5*x; })
+ .add(function(x) { return 2.0*x; }).get([0, 10], 1)
+ });
+
+ $('#test-16 button.toggle').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.toggleLayer(index);
+ });
+
+ $('#test-16 button.orientation').click(function(e) {
+ if (chart.option('orientation') == 'vertical')
+ chart.option('orientation', 'horizontal')
+ else
+ chart.option('orientation', 'vertical')
+ })
+ });
+ </script>
+
+ <div id="test-17" class="test">
+ <h2>17. Data Formatting</h2>
+ <p>Ensure the chart works with the array, tuple, and key-value data formats.<p>
+ <div class="epoch array"></div>
+ <div class="epoch tuple"></div>
+ <div class="epoch keyvalue"></div>
+ </div>
+ <script>
+ $(function() {
+ $('#test-17 .array').epoch({
+ type: 'bar',
+ data: [1, 2, 4, 8, 16, 32],
+ dataFormat: 'array'
+ });
+
+ $('#test-17 .tuple').epoch({
+ type: 'bar',
+ dataFormat: 'tuple',
+ data: [
+ [[0, 1], [1, 2], [2, 4], [3, 8]],
+ [[0, 1], [1, 3], [2, 9], [3, 27]]
+ ]
+ });
+
+ $('#test-17 .keyvalue').epoch({
+ type: 'bar',
+ dataFormat: {
+ name: 'keyvalue',
+ arguments: [['a', 'b']],
+ options: {
+ x: function(d, i) { return d.x; }
+ }
+ },
+ data: [
+ {x: 1, a: 1, b: 1 },
+ {x: 2, a: 2, b: 4 },
+ {x: 3, a: 3, b: 6 },
+ {x: 4, a: 4, b: 8 },
+ {x: 5, a: 5, b: 10 }
+ ]
+ });
+ });
+ </script>
+
+ <div id="test-18" class="test">
+ <h2>18. Bar Ticks</h2>
+ <p>Ensure that we can use ticks option with bar charts.<p>
+ <div class="epoch"></div>
+ </div>
+ <script>
+ $(function() {
+ var data = [],
+ size = 100;
+
+ for (var i = 0; i < size; i++) {
+ data.push({
+ x: i + 1,
+ a: 1 + Math.random()*2*i,
+ b: 1 + Math.random()*2*i
+ });
+ }
+
+ var chart = $('#test-18 .epoch').epoch({
+ type: 'bar',
+ data: data,
+ dataFormat: {
+ name: 'keyvalue',
+ arguments: [['a', 'b']],
+ options: {
+ x: function(d, i) { return d.x; }
+ }
+ },
+ });
+
+ console.log(chart.data);
+ });
+ </script>
+ </body>
+</html>
diff --git a/debian/missing-sources/epoch/tests/render/basic/histogram.html b/debian/missing-sources/epoch/tests/render/basic/histogram.html
new file mode 100644
index 0000000..505054e
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/basic/histogram.html
@@ -0,0 +1,155 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <script src="../js/data.js"></script>
+
+ <script>
+ window.beta = function(a, b) {
+ a = a ? a : 2;
+ b = b ? b : 5;
+
+ var histogram = new BetaData(a, b, 1).next()[0].histogram,
+ values = [];
+
+ for(var x in histogram)
+ values.push({x: x, y: histogram[x]})
+
+ return [{values: values}];
+ }
+ </script>
+
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+ </head>
+ <body>
+ <h1>Basic Bar Chart Test</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Basic Bar</p>
+
+ <ol>
+ <li><a href="#test-1">Beta(2, 5)</a></li>
+ <li><a href="#test-2">Beta(2, 5) Horizontal</a></li>
+ <li><a href="#test-3">Option: buckets</a></li>
+ <li><a href="#test-4">Options: bucketRange &amp; cutOutliers</a></li>
+ </ol>
+
+ <!-- Test 1 -->
+ <div id="test-1" class="test">
+ <h2>1. Beta(2, 5)</h2>
+ <p>Plot a random selection of points from the Beta(2, 5) distribution as a histogram.</p>
+ <div class="epoch"></div>
+ <p><button>Refresh</button></p>
+ </div>
+ <script>
+ $(function() {
+ var chart = $('#test-1 .epoch').epoch({
+ type: 'histogram',
+ buckets: 20,
+ data: beta(2, 5)
+ });
+
+ $('#test-1 button').click(function(e) {
+ chart.update( beta(2, 5) );
+ });
+ });
+ </script>
+
+ <!-- Test 2 -->
+ <div id="test-2" class="test">
+ <h2>2. Beta(2, 5) Horizontal</h2>
+ <p>Plot a random selection of points from Beta(2, 5) and display in a horizontal histogram.</p>
+ <div class="epoch"></div>
+ <p><button>Refresh</button></p>
+ </div>
+ <script>
+ $(function() {
+ var chart = $('#test-2 .epoch').epoch({
+ type: 'histogram',
+ buckets: 10,
+ data: beta(2, 5),
+ orientation: 'horizontal'
+ });
+
+ $('#test-2 button').click(function(e) {
+ chart.update( beta(2, 5) );
+ });
+ });
+ </script>
+
+ <!-- Test 3 -->
+ <div id="test-3" class="test">
+ <h2>3. Option: buckets</h2>
+ <p>Plot Beta(2, 2) and change number of buckets on the fly.</p>
+ <div class="epoch"></div>
+ <p>
+ <button data-value="5">5 Buckets</button>
+ <button data-value="10">10 Buckets</button>
+ <button data-value="20">20 Buckets</button>
+ <button data-value="25">25 Buckets</button>
+ <button data-value="50">50 Buckets</button> |
+ <button class="refresh">Refresh</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var chart = $('#test-3 .epoch').epoch({
+ type: 'histogram',
+ buckets: 10,
+ data: beta(2, 2)
+ });
+
+ $('#test-3 button[data-value]').click(function(e) {
+ var buckets = parseInt($(e.target).attr('data-value'));
+ chart.option('buckets', buckets);
+ });
+
+ $('#test-3 button.refresh').click(function(e) {
+ chart.update( beta(2, 2) );
+ });
+ });
+ </script>
+
+ <!-- Test 4 -->
+ <div id="test-4" class="test">
+ <h2>4. Options: bucketRange &amp; cutOutliers</h2>
+ <p>Plot beta(2, 5) and change the bucket range on the fly.</p>
+ <div class="epoch"></div>
+ <p>
+ <button data-range="0,100">Range [0, 100]</button>
+ <button data-range="0,50">Range [0, 50]</button>
+ <button data-range="25,75">Range [25, 75]</button> |
+ <button class="cutOutliers">Cut Outliers</button>
+ <button class="keepOutliers">Keep Outliers</button> |
+ <button class="refresh">Refresh</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var chart = $('#test-4 .epoch').epoch({
+ type: 'histogram',
+ buckets: 25,
+ data: beta(2, 5)
+ });
+
+ $('#test-4 button[data-range]').click(function(e) {
+ var range = $(e.target).attr('data-range').split(',').map(function(d) { return +d; });
+ chart.option('bucketRange', range);
+ });
+
+ $('#test-4 .cutOutliers').click(function(e) {
+ chart.option('cutOutliers', true);
+ });
+
+ $('#test-4 .keepOutliers').click(function(e) {
+ chart.option('cutOutliers', false);
+ });
+
+ $('#test-4 button.refresh').click(function(e) {
+ chart.update( beta(2, 5) );
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/debian/missing-sources/epoch/tests/render/basic/line.html b/debian/missing-sources/epoch/tests/render/basic/line.html
new file mode 100644
index 0000000..37de38d
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/basic/line.html
@@ -0,0 +1,471 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <script src="../js/data.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+ </head>
+ <body>
+ <h1>Basic Line Chart Test</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Basic Line</p>
+
+ <ol>
+ <li><a href="#test-1">Single Series</a></li>
+ <li><a href="#test-2">Single Series II</a></li>
+ <li><a href="#test-3">Multi Series</a></li>
+ <li><a href="#test-4">Single Series Transition</a></li>
+ <li><a href="#test-5">Multi Series Transition</a></li>
+ <li><a href="#test-6">Single to Multi Series Transition</a></li>
+ <li><a href="#test-7">Color Override</a></li>
+ <li><a href="#test-8">Categorical Colors</a></li>
+ <li><a href="#test-9">Multi Series without Labels</a></li>
+ <li><a href="#test-10">Multi Series with Fixed Domain</a></li>
+ <li><a href="#test-11">Show/Hide Layers</a></li>
+ </ol>
+
+ <!-- Test 1 -->
+ <div id="test-1" class="test">
+ <h2>1. Single Series</h2>
+ <p>Display a plot of <code>y = cos(x)</code> over the range <code>[-2&pi;, 2&pi;)</code>.</p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 128;
+ for (var i = 0; i < length; i++) {
+ var x = i * 4 * Math.PI / length - 2 * Math.PI,
+ y = Math.cos(x);
+ data[0].values.push({x: x, y: y});
+ }
+ $('#test-1 .epoch').epoch({ type: 'line', data: data });
+ });
+ </script>
+
+ <!-- Test 2 -->
+ <div id="test-2" class="test">
+ <h2>2. Single Series II</h2>
+ <p>Display a plot of <code>y = e<sup>x</sup>*sin(x)</code> from <code>[0, &pi)</code>.</p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 128;
+ for (var i = 0; i < length; i++) {
+ var x = i * Math.PI / length,
+ y = Math.exp(x) * Math.sin(x);
+ data[0].values.push({x: x, y: y});
+ }
+ $('#test-2 .epoch').epoch({type: 'line', data: data});
+ })
+ </script>
+
+ <!-- Test 3 -->
+ <div id="test-3" class="test">
+ <h2>3. Multi Series</h2>
+ <p>
+ Display a plot of the following functions over the range [0, 2&pi;]:
+ <ul>
+ <li><code>x*sin(x)</code></li>
+ <li><code>x*cos(x)</code></li>
+ </ul>
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ { label: 'A', values: [] },
+ { label: 'B', values: [] }
+ ],
+ length = 128;
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length;
+ data[0].values.push({x: x, y: x*Math.sin(x)});
+ data[1].values.push({x: x, y: x*Math.cos(x)});
+ }
+ $('#test-3 .epoch').epoch({type: 'line', data: data});
+ });
+ </script>
+
+ <!-- Test 4 -->
+ <div id="test-4" class="test">
+ <h2>4. Single Series Transition</h2>
+ <p>
+ Correctly transition between the functions <code>y = 1 / x</code> and <code>y = x<sup>2</sup></code> over the range [1, 2).
+ Use the buttons below the chart to initiate the transitions.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">y = 1 / x</button>
+ <button data-index="1">y = x^2</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data1 = [{label: 'A', values: []}],
+ data2 = [{label: 'B', values: []}],
+ data = [data1, data2],
+ length = 128;
+
+ for (var i = 0; i < length; i++) {
+ var x = i / length + 1;
+ data1[0].values.push({x: x, y: 1/x});
+ data2[0].values.push({x: x, y: x*x});
+ }
+
+ var chart = $('#test-4 .epoch').epoch({ type: 'line', data: data1 });
+
+ $('#test-4 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+ <!-- Test 5 -->
+ <div id="test-5" class="test">
+ <h2>5. Multi Series Transition</h2>
+ <p>
+ Correctly transition between Set A:
+ <ul>
+ <li><code>y = sin(x)</code></li>
+ <li><code>y = x - x<sup>3</sup>/3! + x<sup>5</sup>/5!</code></li>
+ </ul>
+ Set B:
+ <ul>
+ <li><code>y = cos(x)</code></li>
+ <li><code>y = 1 - x<sup>2</sup>/2! + x<sup>4</sup>/4!</code></li>
+ </ul>
+ and Set C:
+ <ul>
+ <li><code>y = sin(x) - (x - x<sup>3</sup>/3! + x<sup>5</sup>/5!)</code></li>
+ <li><code>y = cos(x) - (1 - x<sup>2</sup>/2! + x<sup>4</sup>/4!)</code></li>
+ </ul>
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Set A</button>
+ <button data-index="1">Set B</button>
+ <button data-index="2">Set C</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var fac = function(n) {
+ var result = n;
+ while(--n > 1) {
+ result *= n;
+ }
+ return result;
+ };
+
+ var taylorSin = function(x) {
+ return x - Math.pow(x, 3) / fac(3) + Math.pow(x, 5) / fac(5);
+ };
+
+ var taylorCos = function(x) {
+ return 1 - Math.pow(x, 2) / fac(2) + Math.pow(x, 4) / fac(4);
+ };
+
+ var data1 = [
+ { label: 'A', values: [] },
+ { label: 'B', values: [] }
+ ],
+ data2 = [
+ { label: 'A', values: [] },
+ { label: 'B', values: [] }
+ ],
+ data3 = [
+ { label: 'A', values: [] },
+ { label: 'B', values: [] }
+ ],
+ data = [data1, data2, data3],
+ length = 64;
+
+ for (var i = 0; i <= length; i++) {
+ var x = i * 8 / length - 4;
+ data1[0].values.push({x: x, y: Math.sin(x)});
+ data1[1].values.push({x: x, y: taylorSin(x)});
+ data2[0].values.push({x: x, y: Math.cos(x)});
+ data2[1].values.push({x: x, y: taylorCos(x)});
+ data3[0].values.push({x: x, y: Math.sin(x) - taylorSin(x)});
+ data3[1].values.push({x: x, y: Math.cos(x) - taylorCos(x)});
+ }
+
+ var chart = $('#test-5 .epoch').epoch({ type: 'line', data: data1 });
+
+ $('#test-5 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+ <!-- Test 6 -->
+ <div id="test-6" class="test">
+ <h2>6. Single to Multi Series Transition</h2>
+ <p>
+ Correctly transition between Set A:
+ <ul>
+ <li><code>y = ln(x)</code></li>
+ </ul>
+ Set B:
+ <ul>
+ <li><code>y = ln(x)</code></li>
+ <li><code>y = x * ln(x)</code></li>
+ <li><code>y = x * ln(x)<sup>2</sup></code></li>
+ </ul>
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Single</button>
+ <button data-index="1">Multi</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data1 = [{label: 'A', values: []}],
+ data2 = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ data = [data1, data2],
+ length = 128;
+
+ for (var i = 0; i <= length; i++) {
+ var x = i * 2 / length + 1;
+ data1[0].values.push({x: x, y: Math.log(x)});
+ data2[0].values.push({x: x, y: Math.log(x)});
+ data2[1].values.push({x: x, y: x * Math.log(x)});
+ data2[2].values.push({x: x, y: x * Math.log(x) * Math.log(x)});
+ }
+
+ var chart = $('#test-6 .epoch').epoch({ type: 'line', data: data1 });
+
+ $('#test-6 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+ <!-- Test 7 -->
+ <div id="test-7" class="test">
+ <h2>7. Color Override</h2>
+ <p>
+ Display the first layer of the plot as pink, the second layer as green, and the third layer as blue.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <style>
+ #test-7 .epoch .a .line { stroke: pink; }
+ #test-7 .epoch .b .line { stroke: green; }
+ #test-7 .epoch .c .line { stroke: blue; }
+ </style>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 64;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 1 / length + 0.5;
+ for (var j = 0; j < data.length; j++) {
+ data[j].values.push({x: x, y: Math.pow(x, 2*j) * Math.log(x)});
+ }
+ }
+
+ $('#test-7 .epoch').epoch({ type: 'line', data: data });
+ });
+ </script>
+
+ <!-- Test 8 -->
+ <div id="test-8" class="test">
+ <h2>Categorical Colors</h2>
+ <p>
+ Change layer colors automatically when switching between the following categorical color classes on the containing element:
+ <ul>
+ <li><code>category10</code></li>
+ <li><code>category20</code></li>
+ <li><code>category20b</code></li>
+ <li><code>category20c</code></li>
+ </ul>
+ Change the categorical colors by pressing the buttons below the chart.
+ </p>
+ <div class="epoch category10"></div>
+ <p>
+ <button data-class="category10">category10</button>
+ <button data-class="category20">category20</button>
+ <button data-class="category20b">category20b</button>
+ <button data-class="category20c">category20c</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []},
+ {label: 'D', values: []},
+ {label: 'E', values: []},
+ {label: 'F', values: []},
+ {label: 'G', values: []}
+ ],
+ length = 64,
+ className = 'category10';
+
+ for (var i = 0; i <= length; i++) {
+ var x = i * 1 / length;
+ for (var j = 0; j < data.length; j++) {
+ data[j].values.push({x: x, y: Math.pow(x, j+1)});
+ }
+ }
+
+ $('#test-8 .epoch').epoch({ type: 'line', data: data });
+
+ $('#test-8 button').on('click', function(e) {
+ $('#test-8 .epoch').removeClass(className);
+ className = $(e.target).attr('data-class');
+ $('#test-8 .epoch').addClass(className);
+ });
+ });
+ </script>
+
+
+ <!-- Test 9 -->
+ <div id="test-9" class="test">
+ <h2>9. Multi Series without Labels</h2>
+ <p>
+ Correctly render a multi-series plot of:
+ <ul>
+ <li><code>y = sin(x)</code></li>
+ <li><code>y = cos(x)</code></li>
+ </ul>
+ where the layers are given without labels.
+ </p>
+ <div class="epoch"></div>
+ </div>
+ <script>
+ $(function() {
+ var data = [{values: []}, {values: []}],
+ length = 128;
+
+ for (var i = 0; i <= length; i++) {
+ var x = i * 4 * Math.PI / length;
+ data[0].values.push({x: x, y: Math.sin(x)});
+ data[1].values.push({x: x, y: Math.cos(x)});
+ }
+
+ $('#test-9 .epoch').epoch({ type: 'line', data: data });
+ });
+ </script>
+
+ <!-- Test 10 -->
+ <div id="test-10" class="test">
+ <h2>10. Multi Series with Fixed Domain</h2>
+ <p>
+ Display a plot of the following functions:
+ <ul>
+ <li><code>x*sin(x)</code></li>
+ <li><code>x*cos(x)</code></li>
+ </ul>
+ On the domain <code>[0, 5]</code> and range <code>[0, 4]</code>.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ { label: 'A', values: [] },
+ { label: 'B', values: [] }
+ ],
+ length = 128;
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length;
+ data[0].values.push({x: x, y: x*Math.sin(x)});
+ data[1].values.push({x: x, y: x*Math.cos(x)});
+ }
+ $('#test-10 .epoch').epoch({
+ type: 'line',
+ data: data,
+ domain: [0, 5],
+ range: [0, 4]
+ });
+ });
+ </script>
+
+ <!-- Test 11 -->
+ <div id="test-11" class="test">
+ <h2>11. Show/Hide Layers</h2>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Toggle A</button>
+ <button data-index="1">Toggle B</button>
+ <button data-index="2">Toggle C</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var chart = $('#test-11 .epoch').epoch({
+ type: 'line',
+ data: data().add(function(x) { return x; })
+ .add(function(x) { return 1.5*x; })
+ .add(function(x) { return 2.0*x; }).get([0, 10], 1)
+ });
+
+ $('#test-11 button').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.toggleLayer(index);
+ });
+ });
+ </script>
+
+ <!-- Test 12 -->
+ <div id="test-12" class="test">
+ <h2>12. Multi-axis</h2>
+ <div class="epoch"></div>
+ </div>
+ <script>
+ $(function() {
+ var d = [
+ { range: 'left', values: [] },
+ { range: 'right', values: [] }
+ ];
+
+ for (var i = 0; i < 40; i++) {
+ d[0].values.push({ x: i, y: 10*i });
+ d[1].values.push({ x: i, y: Math.cos(2*Math.PI*i/40.0) });
+ }
+
+ var chart = $('#test-12 .epoch').epoch({
+ type: 'line',
+ data: d,
+ axes: ['left', 'right'],
+ range: {
+ left: 'left',
+ right: 'right'
+ }
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/debian/missing-sources/epoch/tests/render/basic/model.html b/debian/missing-sources/epoch/tests/render/basic/model.html
new file mode 100644
index 0000000..2814fd8
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/basic/model.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <script src="../js/data.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+ <style>
+ body { background: #333; color: #d0d0d0; }
+ a:link, a:visited { color: white; color: white; }
+
+ .epoch {
+ height: 220px;
+ }
+
+ #sparkline { height: 50px; }
+
+ </style>
+ </head>
+ <body class="epoch-theme-dark">
+ <h1>Basic Chart Model / Data Test</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Basic Chart Model / Data Test</p>
+
+ <p>
+ <button class="set" data-index="0">Data A</button>
+ <button class="set" data-index="1">Data B</button>
+ <button class="set" data-index="2">Data C</button>
+ </p>
+
+ <div id="sparkline" class="epoch"></div>
+ <div id="area" class="epoch"></div>
+ <div id="bar" class="epoch"></div>
+
+ <script>
+ $(function() {
+ var dataA = [];
+ for (var j = 0; j < 3; j++) {
+ var layer = [];
+ for (var i = 0; i < 20; i++) {
+ layer.push(50 + Math.random()*20);
+ }
+ dataA.push(layer);
+ }
+
+ var dataB = [];
+ for (var j = 0; j < 2; j++) {
+ var layer = [];
+ for (i = 0; i < 30; i++) {
+ layer.push(10 + Math.random() * 40)
+ }
+ dataB.push(layer);
+ }
+
+ var dataC = [];
+ for (var i = 0; i < 50; i++) {
+ dataC.push(Math.random() * 100);
+ }
+
+ var data = [dataA, dataB, dataC];
+
+ // Setup the model
+ window.model = new Epoch.Model({ dataFormat: 'array' });
+ model.setData(dataA);
+
+ // Make the charts and associate them with the model
+ var sparkline = $('#sparkline').epoch({
+ type: 'line',
+ axes: ['left', 'right'],
+ model: model
+ });
+
+ var area = $('#area').epoch({
+ type: 'area',
+ axes: ['left', 'right', 'bottom'],
+ model: model
+ });
+
+ window.bar = $('#bar').epoch({
+ type: 'bar',
+ axes: ['left', 'right', 'bottom'],
+ model: model
+ });
+
+ // Click listeners for the buttons
+ $('button.set').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ model.setData(data[index]);
+ });
+ })
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/debian/missing-sources/epoch/tests/render/basic/options.html b/debian/missing-sources/epoch/tests/render/basic/options.html
new file mode 100644
index 0000000..5ff2d7e
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/basic/options.html
@@ -0,0 +1,267 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <script src="../js/data.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+ <style>
+ body { background: #333; color: #d0d0d0; }
+ a:link, a:visited { color: white; color: white; }
+ </style>
+ </head>
+ <body class="epoch-theme-dark">
+ <h1>Basic Chart Options and Events</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Basic Chart Options and Events</p>
+ <ol>
+ <li><a href="#test-1">Axes</a></li>
+ <li><a href="#test-2">Margins</a></li>
+ <li><a href="#test-3">Ticks and Tick Formats</a></li>
+ <li><a href="#test-4">Resize</a></li>
+ <li><a href="#test-5">Domain</a></li>
+ <li><a href="#test-6">Range</a></li>
+ </ol>
+
+ <!-- Test 1 -->
+ <div id="test-1" class="test">
+ <h2>1. Axes</h2>
+ <p>
+ Correctly add and remove axes when options are set.
+ </p>
+ <div class="epoch"></div>
+ <div class="controls">
+ <button data-index="0">All</button>
+ <button data-index="1">[left, right]</button>
+ <button data-index="2">[top, bottom]</button>
+ <button data-index="3">[left, bottom]</button>
+ <button data-index="4">[top, right]</button>
+ <button data-index="5">None</button>
+ </div>
+ </div>
+ <script>
+ $(function() {
+ var axes = [
+ ['top', 'left', 'bottom', 'right'],
+ ['left', 'right'],
+ ['top', 'bottom'],
+ ['left', 'bottom'],
+ ['top', 'right'],
+ []
+ ];
+
+ var chart = $('#test-1 .epoch').epoch({
+ type: 'line',
+ data: data().add(function(x) { return Math.cos(x) }).get([0, 2*Math.PI], Math.PI/25)
+ });
+
+ $('#test-1 button').click(function(e) {
+ chart.option('axes', axes[parseInt($(e.target).attr('data-index'))]);
+ });
+ });
+ </script>
+
+
+ <!-- Test 2 -->
+ <div id="test-2" class="test">
+ <h2>2. Margins</h2>
+ <p>
+ Correctly resize margins when options are set.
+ </p>
+ <div class="epoch"></div>
+ <div class="controls">
+ <button data-index="0">No Margins</button>
+ <button data-index="1">Big Margins</button>
+ <button data-index="2">Small Margins</button>
+ </div>
+ </div>
+ <script>
+ $(function() {
+ var sizes = [
+ {margins: {top: null, left: null, bottom: null, right: null }},
+ {margins: {top: 60, left: 60, bottom: 60, right: 60 }},
+ {margins: {top: 20, left: 20, bottom: 20, right: 20 }}
+ ];
+
+ var chart = $('#test-2 .epoch').epoch({
+ type: 'line',
+ data: data().add(function(x) { return Math.sin(x); })
+ .add(function(x) { return Math.cos(x); })
+ .get([0, 2*Math.PI], Math.PI/25),
+ axes: []
+ });
+
+ $('#test-2 button').click(function(e) {
+ var margins = sizes[parseInt($(e.target).attr('data-index'))];
+ console.log(margins);
+ chart.option(margins);
+ });
+ });
+ </script>
+
+ <!-- Test 3 -->
+ <div id="test-3" class="test">
+ <h2>3. Ticks and Tick Formats</h2>
+ <p>
+ Correctly resize margins when options are set.
+ </p>
+ <div class="epoch"></div>
+ <div class="controls">
+ <button class="ticks">Toggle Ticks</button>
+ <button class="tickFormats">Toggle Tick Formats</button>
+ </div>
+ </div>
+ <script>
+ $(function() {
+ var ticksIndex = 0, ticks = [
+ {
+ ticks: {
+ top: 14,
+ bottom: 14,
+ left: 5,
+ right: 5,
+ }
+ },
+ {
+ ticks: {
+ top: 30,
+ left: 2,
+ bottom: 30,
+ right: 2
+ }
+ }
+ ];
+
+ var tickFormatsIndex = 0, tickFormats = [
+ {
+ tickFormats: {
+ top: Epoch.Formats.regular,
+ bottom: Epoch.Formats.regular,
+ left: Epoch.Formats.si,
+ right: Epoch.Formats.si
+ }
+ },
+ {
+ tickFormats: {
+ top: function(d) { return parseInt(100*d)+'%' },
+ bottom: function(d) { return parseInt(100*d)+'%' },
+ left: function(d) { return parseInt(100*d)+'%' },
+ right: function(d) { return parseInt(100*d)+'%' }
+ }
+ }
+ ];
+
+ var chart = $('#test-3 .epoch').epoch({
+ type: 'area',
+ data: data().add(function(x) { return (Math.sin(x)+1) / (x+1); })
+ .add(function(x) { return (Math.cos(x)+1) / (x+2); })
+ .get([0, 2*Math.PI], Math.PI/25),
+ axes: ['top', 'left', 'right', 'bottom']
+ });
+
+ $('#test-3 button.ticks').click(function(e) {
+ ticksIndex = (ticksIndex + 1) % ticks.length;
+ chart.option(ticks[ticksIndex]);
+ });
+
+ $('#test-3 button.tickFormats').click(function(e) {
+ tickFormatsIndex = (tickFormatsIndex + 1) % tickFormats.length;
+ chart.option(tickFormats[tickFormatsIndex]);
+ });
+ });
+ </script>
+
+ <!-- Test 4 -->
+ <div id="test-4" class="test">
+ <h2>4. Resize</h2>
+ <p>
+ Correctly resize the chart when the width and height options are set.
+ </p>
+ <div class="epoch" style="width: 600px; height: 200px"></div>
+ <div class="controls">
+ <button data-index="0">Original</button>
+ <button data-index="1">Bigger</button>
+ </div>
+ </div>
+ <script>
+ $(function() {
+ var sizes = [
+ [600, 200],
+ [800, 320]
+ ];
+
+ var chart = $('#test-4 .epoch').epoch({
+ type: 'line',
+ data: data().add(function(x) { return Math.sin(x) }).get([0, 2*Math.PI], Math.PI/25)
+ });
+
+ $('#test-4 button').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.option('width', sizes[index][0]);
+ chart.option('height', sizes[index][1]);
+ });
+ });
+ </script>
+
+ <!-- Test 5 -->
+ <div id="test-5" class="test">
+ <h2>6. Option: domain</h2>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Domain From Data Extent</button>
+ <button data-index="1">[0, &pi;]</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var domains = [
+ null,
+ [0, Math.PI]
+ ];
+
+ var chart = $('#test-5 .epoch').epoch({
+ type: 'line',
+ data: data().add(function(x) { return 1 - Math.sin(x) }).get([0, 2*Math.PI], Math.PI/25)
+ });
+
+ $('#test-5 button').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.option('domain', domains[index])
+ });
+ });
+ </script>
+
+
+ <!-- Test 6 -->
+ <div id="test-6" class="test">
+ <h2>7. Option: range</h2>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Range From Data Extent</button>
+ <button data-index="1">[0, 1.5]</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var ranges = [
+ null,
+ [0, 1.5]
+ ];
+
+ var chart = $('#test-6 .epoch').epoch({
+ type: 'area',
+ data: data().add(function(x) { return 1 - Math.cos(x) }).get([0, 2*Math.PI], Math.PI/25)
+ });
+
+ $('#test-6 button').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ console.log(ranges[index]);
+ chart.option('range', ranges[index])
+
+ });
+ });
+ </script>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/debian/missing-sources/epoch/tests/render/basic/pie.html b/debian/missing-sources/epoch/tests/render/basic/pie.html
new file mode 100644
index 0000000..fe105e8
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/basic/pie.html
@@ -0,0 +1,346 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+ <style>
+ .test .epoch {
+ width: 350px;
+ height: 350px;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>Basic Pie Chart Test</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Basic Pie</p>
+ <ol>
+ <li><a href="#test-1">Basic Pie Test</a></li>
+ <li><a href="#test-2">Basic Donut Test</a></li>
+ <li><a href="#test-3">Pie Tranisition I</a></li>
+ <li><a href="#test-4">Pie Tranisition II</a></li>
+ <li><a href="#test-5">Color Override</a></li>
+ <li><a href="#test-6">Categorical Colors</a></li>
+ <li><a href="#test-7">Pie Chart Layers without Labels</a></li>
+ <li><a href="#test-8">Margin Changes</a></li>
+ <li><a href="#test-9">Inner Changes</a></li>
+ <li><a href="#test-10">Show/Hide Layers</a></li>
+ </ol>
+
+ <!-- Test 1 -->
+ <div id="test-1" class="test">
+ <h2>Basic Pie Test</h2>
+ <p>
+ Correctly render a pie chart with three categories:
+ <ul>
+ <li>A - 20</li>
+ <li>B - 45</li>
+ <li>C - 35</li>
+ </ul>
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ $('#test-1 .epoch').epoch({
+ type: 'pie',
+ data: [
+ {label: 'A', value: 20},
+ {label: 'B', value: 45},
+ {label: 'C', value: 35}
+ ]
+ });
+ });
+ </script>
+
+ <!-- Test 2 -->
+ <div id="test-2" class="test">
+ <h2>2. Basic Donut Test</h2>
+ <p>
+ Correctly render a donut chart with three categories:
+ <ul>
+ <li>A - 50</li>
+ <li>B - 30</li>
+ <li>C - 20</li>
+ </ul>
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ $('#test-2 .epoch').epoch({
+ type: 'pie',
+ inner: 100,
+ data: [
+ {label: 'A', value: 50},
+ {label: 'B', value: 30},
+ {label: 'C', value: 20}
+ ]
+ });
+ });
+ </script>
+
+ <!-- Test 3 -->
+ <div id="test-3" class="test">
+ <h2>3. Pie Tranisition I</h2>
+ <p>
+ Correctly transition between set A:
+ <ul>
+ <li>A - 20</li>
+ <li>B - 80</li>
+ </ul>
+ and set B:
+ <ul>
+ <li>A - 20</li>
+ <li>B - 30</li>
+ <li>C - 50</li>
+ </ul>
+ Use the buttons below the chart to initiate the transitions.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Set A</button>
+ <button data-index="1">Set B</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data1 = [
+ {label: 'A', value: 20},
+ {label: 'B', value: 80}
+ ],
+ data2 = [
+ {label: 'A', value: 20},
+ {label: 'B', value: 30},
+ {label: 'C', value: 50}
+ ],
+ data = [data1, data2],
+ chart = $('#test-3 .epoch').epoch({ type: 'pie', data: data1 });
+
+ $('#test-3 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+ <!-- Test 4 -->
+ <div id="test-4" class="test">
+ <h2>4. Pie Tranisition II</h2>
+ <p>
+ Correctly transition between set A:
+ <ul>
+ <li>A - 20</li>
+ <li>B - 80</li>
+ </ul>
+ and set B:
+ <ul>
+ <li>A - 50</li>
+ <li>B - 50</li>
+ </ul>
+ Use the buttons below the chart to initiate the transitions.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Set A</button>
+ <button data-index="1">Set B</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data1 = [
+ {label: 'A', value: 20},
+ {label: 'B', value: 80}
+ ],
+ data2 = [
+ {label: 'A', value: 50},
+ {label: 'B', value: 50}
+ ],
+ data = [data1, data2],
+ chart = $('#test-4 .epoch').epoch({ type: 'pie', data: data1 });
+
+ $('#test-4 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+ <!-- Test 5 -->
+ <div id="test-5" class="test">
+ <h2>5. Color Override</h2>
+ <p>
+ Override the colors as such:
+ <ul>
+ <li>A - Pink</li>
+ <li>B - Green</li>
+ <li>C - Blue</li>
+ </ul>
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <style>
+ #test-5 .arc.a path { fill: pink; }
+ #test-5 .arc.b path { fill: green; }
+ #test-5 .arc.c path { fill: blue; }
+ </style>
+
+ <script>
+ $(function() {
+ $('#test-5 .epoch').epoch({
+ type: 'pie',
+ data: [
+ {label: 'A', value: 20},
+ {label: 'B', value: 45},
+ {label: 'C', value: 35}
+ ]
+ });
+ });
+ </script>
+
+ <!-- Test 6 -->
+ <div id="test-6" class="test">
+ <h2>6. Categorical Colors</h2>
+ <p>
+ Correctly transition between different categorical colors sets.
+ </p>
+ <div class="epoch category10"></div>
+ <p>
+ <button data-class="category10">category10</button>
+ <button data-class="category20">category20</button>
+ <button data-class="category20b">category20b</button>
+ <button data-class="category20c">category20c</button>
+ </p>
+ </div>
+
+
+ <script>
+ $(function() {
+ var data = [],
+ className = 'category10';
+
+ for (var j = 0; j < 10; j++) {
+ data.push({label: String.fromCharCode(65+j), value: 10});
+ }
+
+ $('#test-6 .epoch').epoch({
+ type: 'pie',
+ inner: 100,
+ data: data
+ });
+
+ $('#test-6 button').on('click', function(e) {
+ $('#test-6 .epoch').removeClass(className);
+ className = $(e.target).attr('data-class');
+ $('#test-6 .epoch').addClass(className);
+ });
+ });
+ </script>
+
+
+ <!-- Test 7 -->
+ <div id="test-7" class="test">
+ <h2>7. Pie Chart Layers without Labels</h2>
+ <p>
+ Correctly render a pie chart with three categories:
+ <ul>
+ <li>30</li>
+ <li>35</li>
+ <li>35</li>
+ </ul>
+ when the layers are not provided labels.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ $('#test-7 .epoch').epoch({
+ type: 'pie',
+ data: [ {value: 30}, {value: 35}, {value: 35} ]
+ });
+ });
+ </script>
+
+ <!-- Test 8 -->
+ <div id="test-8" class="test">
+ <h2>8. Margin Changes</h2>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Small</button>
+ <button data-index="1">Big</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var margins = [10, 40];
+ var chart = $('#test-8 .epoch').epoch({
+ type: 'pie',
+ data: [ {value: 30}, {value: 35}, {value: 35} ]
+ });
+ $('#test-8 button').click(function(e) {
+ var margin = margins[parseInt($(e.target).attr('data-index'))];
+ chart.option('margin', margin);
+ });
+ });
+ </script>
+
+ <!-- Test 9 -->
+ <div id="test-9" class="test">
+ <h2>9. Inner Changes</h2>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">No Inner</button>
+ <button data-index="1">Small Inner</button>
+ <button data-index="2">Big Inner</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var innerMargins = [0, 50, 100];
+ var chart = $('#test-9 .epoch').epoch({
+ type: 'pie',
+ data: [ {value: 30}, {value: 35}, {value: 35} ]
+ });
+ $('#test-9 button').click(function(e) {
+ var inner = innerMargins[parseInt($(e.target).attr('data-index'))];
+ chart.option('inner', inner);
+ });
+ });
+ </script>
+
+ <!-- Test 10 -->
+ <div id="test-10" class="test">
+ <h2>10. Show/Hide Layers</h2>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Toggle A</button>
+ <button data-index="1">Toggle B</button>
+ <button data-index="2">Toggle C</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var chart = $('#test-10 .epoch').epoch({
+ type: 'pie',
+ data: [
+ {label: 'A', value: 20},
+ {label: 'B', value: 45},
+ {label: 'C', value: 35}
+ ]
+ });
+ $('#test-10 button').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.toggleLayer(index);
+ });
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/debian/missing-sources/epoch/tests/render/basic/scatter.html b/debian/missing-sources/epoch/tests/render/basic/scatter.html
new file mode 100644
index 0000000..31f1e42
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/basic/scatter.html
@@ -0,0 +1,398 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <script src="../js/data.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+ </head>
+ <body>
+ <h1>Basic Scatter Plot Test</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Basic Scatter</p>
+ <ol>
+ <li><a href="#test-1">Single Series</a></li>
+ <li><a href="#test-2">Multi Series</a></li>
+ <li><a href="#test-3">Single Series Transition</a></li>
+ <li><a href="#test-4">Multi Series Transition</a></li>
+ <li><a href="#test-5">Multi Series Transition II</a></li>
+ <li><a href="#test-6">Color Override</a></li>
+ <li><a href="#test-7">Categorical Colors</a></li>
+ <li><a href="#test-8">Multi Series without Labels</a></li>
+ <li><a href="#test-9">Single Series with Radius</a></li>
+ <li><a href="#test-10">Radius Change</a></li>
+ <li><a href="#test-11">Show/Hide Layers</a></li>
+ </ol>
+
+ <!-- Test 1 -->
+ <div id="test-1" class="test">
+ <h2>1. Single Series</h2>
+ <p>Render a single random series scatter plot.</p>
+ <div class="epoch"></div>
+ </div>
+ <script>
+ $(function() {
+ var data = [],
+ length = 128;
+
+ for (var j = 0; j < length; j++) {
+ var x = Math.random() * 100,
+ y = Math.random() * 20;
+ data.push({x: x, y: y});
+ }
+
+ $('#test-1 .epoch').epoch({ type: 'scatter', data: [{label: 'A', values: data}]});
+ });
+ </script>
+
+ <!-- Test 2 -->
+ <div id="test-2" class="test">
+ <h2>2. Multi Series</h2>
+ <p>Render three random scatter series in the same plot.</p>
+ <div class="epoch"></div>
+ </div>
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 64;
+
+ for (var i = 0; i < length; i++) {
+ for (var j = 0; j < data.length; j++) {
+ var x = Math.random() * 100,
+ y = Math.random() * 20;
+ data[j].values.push({x: x, y: y});
+ }
+ }
+
+ $('#test-2 .epoch').epoch({type: 'scatter', data: data});
+ });
+ </script>
+
+ <!-- Test 3 -->
+ <div id="test-3" class="test">
+ <h2>3. Single Series Transition</h2>
+ <p>
+ Transition from one random series to another random series. Use the
+ buttons below the plot to initiate the transition.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Series A</button>
+ <button data-index="1">Series B</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var data = [
+ [
+ {label: 'A', values: []}
+ ],
+ [
+ {label: 'A', values: []}
+ ]
+ ],
+ length = 64;
+
+ for (var i = 0; i < length; i++) {
+ for (var j = 0; j < data.length; j++) {
+ for (var k = 0; k < data[j].length; k++) {
+ var x = Math.random() * 100,
+ y = Math.random() * 20;
+ data[j][k].values.push({x: x, y: y});
+ }
+ }
+ }
+
+ var chart = $('#test-3 .epoch').epoch({type: 'scatter', data: data[0]});
+ $('#test-3 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+ <!-- Test 4 -->
+ <div id="test-4" class="test">
+ <h2>4. Multi Series Transition</h2>
+ <p>
+ Transition from a set of multiple randoms series random series to another of multiple random series. Use the
+ buttons below the plot to initiate the transition.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Series Set A</button>
+ <button data-index="1">Series Set B</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var data = [
+ [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ]
+ ],
+ length = 64;
+
+ for (var i = 0; i < length; i++) {
+ for (var j = 0; j < data.length; j++) {
+ for (var k = 0; k < data[j].length; k++) {
+ var x = Math.random() * 100,
+ y = Math.random() * 20;
+ data[j][k].values.push({x: x, y: y});
+ }
+ }
+ }
+
+ var chart = $('#test-4 .epoch').epoch({type: 'scatter', data: data[0]});
+ $('#test-4 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+ <!-- Test 5 -->
+ <div id="test-5" class="test">
+ <h2>5. Multi Series Transition II</h2>
+ <p>
+ Transition from a multi-series set of random data to a single series set of random data.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Series Set A</button>
+ <button data-index="1">Series Set B</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var data = [
+ [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ [
+ {label: 'A', values: []}
+ ]
+ ],
+ length = 64;
+
+ for (var i = 0; i < length; i++) {
+ for (var j = 0; j < data.length; j++) {
+ for (var k = 0; k < data[j].length; k++) {
+ var x = Math.random() * 100,
+ y = Math.random() * 20;
+ data[j][k].values.push({x: x, y: y});
+ }
+ }
+ }
+
+ var chart = $('#test-5 .epoch').epoch({type: 'scatter', data: data[0]});
+ $('#test-5 button').on('click', function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.update(data[index]);
+ });
+ });
+ </script>
+
+ <!-- Test 6 -->
+ <div id="test-6" class="test">
+ <h2>6. Color Override</h2>
+ <p>The first series should be pink, the second green, and thrid blue.</p>
+ <div class="epoch"></div>
+ </div>
+ <style>
+ #test-6 .a .dot { fill: pink; }
+ #test-6 .b .dot { fill: green; }
+ #test-6 .c .dot { fill: blue; }
+ </style>
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 64;
+
+ for (var i = 0; i < length; i++) {
+ for (var j = 0; j < data.length; j++) {
+ var x = Math.random() * 100,
+ y = Math.random() * 20;
+ data[j].values.push({x: x, y: y});
+ }
+ }
+
+ $('#test-6 .epoch').epoch({type: 'scatter', data: data});
+ });
+ </script>
+
+ <!-- Test 7 -->
+ <div id="test-7" class="test">
+ <h2>7. Categorical Colors</h2>
+ <p>
+ Correctly transition between different categorical color sets.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button data-class="category10">category10</button>
+ <button data-class="category20">category20</button>
+ <button data-class="category20b">category20b</button>
+ <button data-class="category20c">category20c</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []},
+ {label: 'E', values: []},
+ {label: 'F', values: []},
+ {label: 'G', values: []},
+ {label: 'H', values: []},
+ {label: 'I', values: []},
+ {label: 'J', values: []},
+ {label: 'K', values: []}
+ ],
+ className = 'category10';
+
+ for (var i = 0; i < data.length; i++) {
+ var x = i * Math.PI * 2 / data.length,
+ y = Math.sin(x);
+ data[i].values.push({x: x, y: y});
+ }
+
+ $('#test-7 .epoch').epoch({
+ type: 'scatter',
+ radius: 10,
+ data: data
+ });
+
+
+ $('#test-7 button').on('click', function(e) {
+ $('#test-7 .epoch').removeClass(className);
+ className = $(e.target).attr('data-class');
+ $('#test-7 .epoch').addClass(className);
+ });
+ });
+ </script>
+
+ <!-- Test 8 -->
+ <div id="test-8" class="test">
+ <h2>8. Multi Series without Labels</h2>
+ <p>Correctly render two random scatter plots when labels are not specified for the layers.</p>
+ <div class="epoch"></div>
+ </div>
+ <script>
+ $(function() {
+ var data = [{values: []}, {values: []}],
+ length = 64;
+
+ for (var i = 0; i < length; i++) {
+ for (var j = 0; j < data.length; j++) {
+ var x = Math.random() * 100,
+ y = Math.random() * 20;
+ data[j].values.push({x: x, y: y});
+ }
+ }
+
+ $('#test-8 .epoch').epoch({type: 'scatter', data: data});
+ });
+ </script>
+
+ <!-- Test 9 -->
+ <div id="test-9" class="test">
+ <h2>9. Single Series with Radius</h2>
+ <p>Render a single random series scatter plot with different radii.</p>
+ <div class="epoch"></div>
+ <p>
+ <button>Regenerate</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var length = 128;
+
+ var generateData = function(length) {
+ var data = [];
+ for (var j = 0; j < length; j++) {
+ var x = Math.random() * 100,
+ y = Math.random() * 20,
+ r = Math.random() * 6 + 2;
+ data.push({x: x, y: y, r: r});
+ }
+ return [{label: 'A', values: data}];
+ };
+
+ var chart = $('#test-9 .epoch').epoch({ type: 'scatter', data: generateData(length)});
+
+ $("#test-9 p button:eq(0)").click(function() {
+ chart.update(generateData(length));
+ });
+ });
+ </script>
+
+ <!-- Test 10 -->
+ <div id="test-10" class="test">
+ <h2>10. Radius Change</h2>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Small</button>
+ <button data-index="1">Normal</button>
+ <button data-index="2">Large</button>
+ <button data-index="3">Very Large</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var radii = [2.0, 3.5, 7, 14];
+ var chart = $('#test-10 .epoch').epoch({
+ type: 'scatter',
+ data: data().random()
+ });
+ $('#test-10 button').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.option('radius', radii[index]);
+ });
+ });
+ </script>
+
+ <!-- Test 11 -->
+ <div id="test-11" class="test">
+ <h2>11. Show/Hide Layers</h2>
+ <div class="epoch"></div>
+ <p>
+ <button data-index="0">Toggle A</button>
+ <button data-index="1">Toggle B</button>
+ <button data-index="2">Toggle C</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var chart = $('#test-11 .epoch').epoch({
+ type: 'scatter',
+ data: data().multiRandom(3)
+ });
+
+ $('#test-11 button').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.toggleLayer(index);
+ });
+ });
+ </script>
+
+ </body>
+</html>
diff --git a/debian/missing-sources/epoch/tests/render/css/tests.css b/debian/missing-sources/epoch/tests/render/css/tests.css
new file mode 100644
index 0000000..7f4099e
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/css/tests.css
@@ -0,0 +1,12 @@
+body {
+ font-family: helvetica;
+}
+
+/* Default test chart height of 220px. */
+.test .epoch {
+ height: 220px;
+}
+
+.broken {
+ color: red;
+}
diff --git a/debian/missing-sources/epoch/tests/render/index.html b/debian/missing-sources/epoch/tests/render/index.html
new file mode 100644
index 0000000..1ab15c1
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/index.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Epoch - Chart Rendering Tests</title>
+ <link rel="stylesheet" type="text/css" href="css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../dist/js/epoch.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../dist/css/epoch.css">
+ </head>
+ <body>
+ <h1>Epoch Chart Rendering Tests</h1>
+
+ <h2>Basic Charts</h2>
+ <p>
+ <ul>
+ <li><a href="basic/area.html">Area</a></li>
+ <li><a href="basic/bar.html">Bar</a></li>
+ <li>
+ <ul><li><a href="basic/histogram.html">Histogram</a></li></ul>
+ </li>
+ <li><a href="basic/line.html">Line</a></li>
+ <li><a href="basic/pie.html">Pie</a></li>
+ <li><a href="basic/scatter.html">Scatter</a></li>
+ <li><a href="basic/options.html">All Charts - Options and Events</a></li>
+ </ul>
+ </p>
+
+ <h2>Real-time Charts</h2>
+ <p>
+ <ul>
+ <li><a href="real-time/area.html">Area</a></li>
+ <li><a href="real-time/bar.html">Bar</a></li>
+ <li><a href="real-time/gauge.html">Gauge</a></li>
+ <li><a href="real-time/heatmap.html">Heatmap</a></li>
+ <li><a href="real-time/line.html">Line</a></li>
+ <li><a href="real-time/options.html">All Charts - Options and Events</a></li>
+ </ul>
+ </p>
+
+ <h2>Themes</h2>
+ <p>
+ <ul>
+ <li><a href="themes/default.html">Default</a></li>
+ <li><a href="themes/dark.html">Dark</a></li>
+ </ul>
+ </p>
+
+ <h2>Data / Models</h2>
+ <p>
+ <ul>
+ <li><a href="basic/model.html">Basic Model</a></li>
+ <li><a href="real-time/model.html">Real-time Model</a></li>
+ </ul>
+ </p>
+ </body>
+</html>
diff --git a/debian/missing-sources/epoch/tests/render/js/data.js b/debian/missing-sources/epoch/tests/render/js/data.js
new file mode 100644
index 0000000..a49da68
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/js/data.js
@@ -0,0 +1,210 @@
+(function() {
+
+ // Quick data generator
+ Data = function() {
+ this.layers = []
+ };
+
+ Data.prototype.add = function(fn) {
+ fn = fn ? fn : function(x) { return x; };
+ this.layers.push(fn);
+ return this;
+ };
+
+ Data.prototype.get = function(domain, step) {
+ domain = domain ? domain : [0, 10];
+ step = step ? step : 1;
+
+ var data = []
+ for (var i = 0; i < this.layers.length; i++) {
+ layer = { label: String.fromCharCode(i + 65), values: [] };
+ for (var x = domain[0]; x < domain[1]; x += step) {
+ layer.values.push({ x: x, y: this.layers[i](x) });
+ }
+ data.push(layer);
+ }
+ return data;
+ };
+
+ Data.prototype.random = function(entries, domain, range) {
+ entries = entries ? entries : 50;
+ domain = domain ? domain : [0, 100];
+ range = range ? range : [0, 100];
+
+ var values = [];
+ for (var i = 0; i < entries; i++) {
+ var x = (domain[1] - domain[0]) * Math.random() + domain[0],
+ y = (range[1] - range[0]) * Math.random() + range[1];
+ values.push({ x: x, y: y });
+ }
+
+ return [{ label: 'A', values: values }];
+ };
+
+ Data.prototype.multiRandom = function(numSeries, entries, domain, range) {
+ numSeries = numSeries ? numSeries : 3;
+ entries = entries ? entries : 50;
+ domain = domain ? domain : [0, 100];
+ range = range ? range : [0, 100];
+
+ var data = [];
+
+ for (var j = 0; j < numSeries; j++) {
+ var layer = { label: String.fromCharCode(65 + j), values: [] };
+ for (var i = 0; i < entries; i++) {
+ var x = (domain[1] - domain[0]) * Math.random() + domain[0],
+ y = (range[1] - range[0]) * Math.random() + range[1];
+ layer.values.push({ x: x, y: y });
+ }
+ data.push(layer);
+ }
+
+ return data;
+ };
+
+ window.data = function() { return new Data(); };
+
+
+ // Quick real-time data generator
+ Time = function() {
+ Data.call(this);
+ };
+
+ Time.prototype = new Data()
+
+ Time.prototype.get = function(domain, step) {
+ var data = Data.prototype.get.apply(this, arguments),
+ time = parseInt(new Date().getTime() / 1000);
+
+ for (var i = 0; i < data[0].values.length; i++) {
+ for (var j = 0; j < this.layers.length; j++) {
+ delete data[j].values[i].x;
+ data[j].values[i].time = time + i;
+ }
+ }
+
+ this.currentTime = time;
+ this.lastX = domain[1];
+
+ return data;
+ };
+
+ Time.prototype.next = function(step) {
+ this.currentTime++;
+ this.lastX += (step ? step : 1);
+
+ var data = [];
+ for (var j = 0; j < this.layers.length; j++) {
+ data.push({ time: this.currentTime, y: this.layers[j](this.lastX) })
+ }
+
+ return data;
+ }
+
+ window.time = function() { return new Time(); };
+
+
+
+
+ window.nextTime = (function() {
+ var currentTime = parseInt(new Date().getTime() / 1000);
+ return function() { return currentTime++; }
+ })();
+
+
+ /*
+ * Normal distribution random histogram data generator.
+ */
+ var NormalData = function(layers) {
+ this.layers = layers;
+ this.timestamp = ((new Date()).getTime() / 1000)|0;
+ };
+
+ var normal = function() {
+ var U = Math.random(),
+ V = Math.random();
+ return Math.sqrt(-2*Math.log(U)) * Math.cos(2*Math.PI*V);
+ };
+
+ NormalData.prototype.sample = function() {
+ return parseInt(normal() * 12.5 + 50);
+ }
+
+ NormalData.prototype.rand = function() {
+ var histogram = {};
+
+ for (var i = 0; i < 1000; i ++) {
+ var r = this.sample();
+ if (!histogram[r]) {
+ histogram[r] = 1;
+ }
+ else {
+ histogram[r]++;
+ }
+ }
+
+ return histogram;
+ };
+
+ NormalData.prototype.history = function(entries) {
+ if (typeof(entries) != 'number' || !entries) {
+ entries = 60;
+ }
+
+ var history = [];
+ for (var k = 0; k < this.layers; k++) {
+ history.push({ label: String.fromCharCode(65+k), values: [] });
+ }
+
+ for (var i = 0; i < entries; i++) {
+ for (var j = 0; j < this.layers; j++) {
+ history[j].values.push({time: this.timestamp, histogram: this.rand()});
+ }
+ this.timestamp++;
+ }
+
+ return history;
+ };
+
+ NormalData.prototype.next = function() {
+ var entry = [];
+ for (var i = 0; i < this.layers; i++) {
+ entry.push({ time: this.timestamp, histogram: this.rand() });
+ }
+ this.timestamp++;
+ return entry;
+ }
+
+ window.NormalData = NormalData;
+
+
+ /*
+ * Beta distribution histogram data generator.
+ */
+ var BetaData = function(alpha, beta, layers) {
+ this.alpha = alpha;
+ this.beta = beta;
+ this.layers = layers;
+ this.timestamp = ((new Date()).getTime() / 1000)|0;
+ };
+
+ BetaData.prototype = new NormalData();
+
+ BetaData.prototype.sample = function() {
+ var X = 0,
+ Y = 0;
+
+ for (var j = 1; j <= this.alpha; j++)
+ X += -Math.log(1 - Math.random());
+
+ for (var j = 1; j <= this.beta; j++)
+ Y += -Math.log(1 - Math.random());
+
+ return parseInt(100 * X / (X + Y));
+ }
+
+ window.BetaData = BetaData;
+
+})();
+
+
diff --git a/debian/missing-sources/epoch/tests/render/real-time/area.html b/debian/missing-sources/epoch/tests/render/real-time/area.html
new file mode 100644
index 0000000..b66ab7d
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/real-time/area.html
@@ -0,0 +1,494 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+
+ <script>
+ var nextTime = (function() {
+ var currentTime = parseInt(new Date().getTime() / 1000);
+ return function() { return currentTime++; }
+ })();
+ </script>
+ </head>
+ <body>
+ <h1>Real-time Area Plot Test</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Real-time Area</p>
+ <ol>
+ <li><a href="#test-1">Single Series</a></li>
+ <li><a href="#test-2">Single Series Single Transition</a></li>
+ <li><a href="#test-3">Single Seires Stream</a></li>
+ <li><a href="#test-4">Multi Series</a></li>
+ <li><a href="#test-5">Multi Series Single Transition</a></li>
+ <li><a href="#test-6">Multi Seires Stream</a></li>
+ <li><a href="#test-7">Color Override</a></li>
+ <li><a href="#test-8">Categorical Colors</a></li>
+ <li><a href="#test-9">Show/Hide Layers</a></li>
+ </ol>
+
+ <!-- Test 1 -->
+ <div id="test-1" class="test">
+ <h2>1. Single Series</h2>
+ <p>
+ Correctly render a single series plot of <code>y = cos(x) + 1</code> over the range <code>[0, 2&pi;]</code>.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.cos(x) + 1,
+ time = nextTime();
+ data[0].values.push({time: time, y: y});
+ }
+
+ $('#test-1 .epoch').epoch({ type: 'time.area', data: data });
+ });
+ </script>
+
+ <!-- Test 2 -->
+ <div id="test-2" class="test">
+ <h2>2. Single Series Single Transition</h2>
+ <p>
+ Correctly render a single series plot of <code>y = sin(x) + 1</code>. When the button is pressed push a new data point to the chart and correctly animate/render the transiton.
+ </p>
+ <div class="epoch"></div>
+ <p><button>Next</button></p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 40,
+ nextIndex = length;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.sin(x) + 1,
+ time = nextTime();
+ data[0].values.push({time: time, y: y});
+ }
+
+ var chart = $('#test-2 .epoch').epoch({
+ type: 'time.area',
+ data: data
+ });
+
+ $('#test-2 button').on('click', function(e) {
+ var x = nextIndex * 2 * Math.PI / length,
+ y = Math.sin(x) + 1,
+ time = nextTime();
+ nextIndex++;
+ chart.push([{ time: time, y: y }]);
+ });
+ });
+ </script>
+
+
+ <!-- Test 3 -->
+ <div id="test-3" class="test">
+ <h2>3. Single Seires Stream</h2>
+ <p>Correctly play / pause a single series stream of values from the plot <code>y = cos(x) + 1</code>.</p>
+ <div class="epoch"></div>
+ <p><button>Play</button></p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 40,
+ nextIndex = length,
+ playing = false,
+ interval = null;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.cos(x) + 1,
+ time = nextTime();
+ data[0].values.push({time: time, y: y});
+ }
+
+ var chart = $('#test-3 .epoch').epoch({
+ type: 'time.area',
+ data: data
+ });
+
+ var pushPoint = function() {
+ var x = nextIndex * 2 * Math.PI / length,
+ y = Math.cos(x) + 1,
+ time = nextTime();
+ chart.push([{ time: time, y: y}]);
+ nextIndex++;
+ };
+
+ $('#test-3 button').on('click', function(e) {
+ if (playing) {
+ $(e.target).text('Play');
+ clearInterval(interval);
+ }
+ else {
+ $(e.target).text('Pause');
+ pushPoint();
+ interval = setInterval(pushPoint, 1000);
+ }
+ playing = !playing;
+ });
+ });
+ </script>
+
+ <!-- Test 4 -->
+ <div id="test-4" class="test">
+ <h2>4. Multi Series</h2>
+ <p>Correctly render a multi series plot of the following functions:</p>
+ <ul>
+ <li><code>y = log(x+1)</code></li>
+ <li><code>y = 2*log(x+1)</code></li>
+ <li><code>y = 3*log(x+1)</code></li>
+ </ul>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x = i + 1,
+ time = nextTime();
+ for (var j = 0; j < data.length; j++) {
+ data[j].values.push({time: time, y: (j+1) * Math.log(x)});
+ }
+ }
+
+ $('#test-4 .epoch').epoch({
+ type: 'time.area',
+ data: data,
+ axes: ['left', 'right', 'bottom']
+ });
+ });
+ </script>
+
+
+ <!-- Test 5 -->
+ <div id="test-5" class="test">
+ <h2>5. Multi Series Single Transition</h2>
+ <p>
+ Correctly render a multi series plot of the following functions:
+ <ul>
+ <li><code>y = x</code></li>
+ <li><code>y = x<sup>1.25</sup></code></li>
+ <li><code>y = x<sup>1.5</sup></code></li>
+ </ul>
+ and correctly render/animate the transiton after pressing the "Next" button.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button>Next</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40,
+ scale = 0.1,
+ nextIndex = length;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * scale,
+ time = nextTime();
+ data[0].values.push({time: time, y: x});
+ data[1].values.push({time: time, y: Math.pow(x, 1.25)});
+ data[2].values.push({time: time, y: Math.pow(x, 1.5)});
+ }
+
+ var chart = $('#test-5 .epoch').epoch({
+ type: 'time.area',
+ data: data,
+ axes: ['left', 'right', 'bottom']
+ });
+
+ $('#test-5 button').on('click', function(e) {
+ var x = nextIndex * scale,
+ time = nextTime();
+ nextIndex++;
+ chart.push([
+ {time: time, y: x},
+ {time: time, y: Math.pow(x, 1.25)},
+ {time: time, y: Math.pow(x, 1.5)}
+ ]);
+ });
+ });
+ </script>
+
+ <!-- Test 6 -->
+ <div id="test-6" class="test">
+ <h2>6. Multi Seires Stream</h2>
+ <p>
+ Correctly play / pause a multi series stream of values over the following plots:
+ <ul>
+ <li><code>x</code></li>
+ <li><code>x * log(x)</code></li>
+ <li><code>x * log<sup>2</sup>(x)</code></li>
+ </ul>
+ </p>
+ <div class="epoch"></div>
+ <p><button>Play</button></p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40,
+ nextIndex = length,
+ scale = 0.1,
+ playing = false,
+ interval = null;
+
+ for (var i = 0; i < length; i++) {
+ var x = (i+1) * scale,
+ time = nextTime();
+ data[0].values.push({time: time, y: x});
+ data[1].values.push({time: time, y: x * Math.log(x)});
+ data[2].values.push({time: time, y: x * Math.pow(Math.log(x), 2)});
+ }
+
+ var chart = $('#test-6 .epoch').epoch({
+ type: 'time.area',
+ data: data,
+ axes: ['right', 'bottom']
+ });
+
+ var pushPoint = function() {
+ var x = (nextIndex +1) * scale,
+ time = nextTime();
+ chart.push([
+ { time: time, y: x},
+ { time: time, y: x * Math.log(x)},
+ { time: time, y: x * Math.pow(Math.log(x), 2)}
+ ]);
+ nextIndex++;
+ };
+
+ $('#test-6 button').on('click', function(e) {
+ if (playing) {
+ $(e.target).text('Play');
+ clearInterval(interval);
+ }
+ else {
+ $(e.target).text('Pause');
+ interval = setInterval(pushPoint, 1000);
+ pushPoint();
+ }
+ playing = !playing;
+ });
+ });
+ </script>
+
+ <!-- Test 7 -->
+ <div id="test-7" class="test">
+ <h2>7. Color Override</h2>
+ <p>The first layer should pink, the second green, and the third blue.</p>
+ <div id="test-7-plot" class="epoch"></div>
+ </div>
+
+ <style>
+ #test-7-plot .a .area { fill: pink; }
+ #test-7-plot .b .area { fill: green; }
+ #test-7-plot .c .area { fill: blue; }
+ </style>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x = i + 1,
+ time = nextTime();
+ for (var j = 0; j < data.length; j++) {
+ data[j].values.push({time: time, y: (j+1) * Math.log(x)});
+ }
+ }
+
+ $('#test-7 .epoch').epoch({
+ type: 'time.area',
+ data: data
+ });
+ });
+ </script>
+
+ <!-- Test 8 -->
+ <div id="test-8" class="test">
+ <h2>8. Categorical Colors</h2>
+ <p>Correctly render and switch between different categorical colors. Unlike with the basic charts this doesn't occur just by switching the class name on the containing element. The CSS query engine must be purge and the plot must be manually redrawn, like so:<code><pre>
+Epoch.QueryCSS.purge();
+chart.draw();
+</pre></code>
+ </p>
+
+ <div class="epoch category10"></div>
+
+ <p>
+ <button data-class="category10">category10</button>
+ <button data-class="category20">category20</button>
+ <button data-class="category20b">category20b</button>
+ <button data-class="category20c">category20c</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [],
+ length = 41,
+ className = "category10",
+ layers = 8,
+ time = nextTime();
+
+ for (var i = 0; i < layers; i++) {
+ var layer = { label: String.fromCharCode(i+65), values: [] };
+ for (var j = 0; j < length; j++) {
+ var x = j + 1,
+ y = Math.pow(x, 1 + 0.3 * Math.log(Math.log(Math.log(x+1) + 1) + 1));
+ layer.values.push({ time: time + j, y: y });
+ }
+ data.push(layer);
+ }
+
+ var chart = $('#test-8 .epoch').epoch({ type: 'time.area', data: data });
+
+ $('#test-8 button').on('click', function(e) {
+ $('#test-8 .epoch').removeClass(className);
+ className = $(e.target).attr('data-class');
+ $('#test-8 .epoch').addClass(className);
+ Epoch.QueryCSS.purge();
+ chart.draw();
+ });
+ });
+ </script>
+
+ <!-- Test 9 -->
+ <div id="test-9" class="test">
+ <h2>9. Show/Hide Layers</h2>
+ <div class="epoch"></div>
+ <p>
+ <button class="toggle" data-index="0">Toggle A</button>
+ <button class="toggle" data-index="1">Toggle B</button>
+ <button class="toggle" data-index="2">Toggle C</button> |
+ <button class="playback">Play</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40,
+ nextIndex = length,
+ scale = 0.1,
+ playing = false,
+ interval = null;
+
+ for (var i = 0; i < length; i++) {
+ var x = (i+1) * scale,
+ time = nextTime();
+ data[0].values.push({time: time, y: x});
+ data[1].values.push({time: time, y: 1.5*x});
+ data[2].values.push({time: time, y: 2*x});
+ }
+
+ var chart = $('#test-9 .epoch').epoch({
+ type: 'time.area',
+ data: data,
+ axes: ['right', 'bottom']
+ });
+
+ var pushPoint = function() {
+ var x = (nextIndex +1) * scale,
+ time = nextTime();
+ chart.push([
+ { time: time, y: x},
+ { time: time, y: 1.5*x},
+ { time: time, y: 2*x}
+ ]);
+ nextIndex++;
+ };
+
+ $('#test-9 button.toggle').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.toggleLayer(index);
+ });
+
+ $('#test-9 button.playback').on('click', function(e) {
+ if (playing) {
+ $(e.target).text('Play');
+ clearInterval(interval);
+ }
+ else {
+ $(e.target).text('Pause');
+ interval = setInterval(pushPoint, 1000);
+ pushPoint();
+ }
+ playing = !playing;
+ });
+ });
+ </script>
+
+ <!-- Test 10 -->
+ <div id="test-10" class="test">
+ <h2>10. Fixed Range</h2>
+ <p>
+ Render a single series plot of <code>y = cos(x)</code>. Instead of automatically setting the range to <code>[-1, 1]</code>, the range is manually set to <code>[-2, 5]</code>.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.cos(x),
+ time = nextTime();
+ data[0].values.push({time: time, y: y});
+ }
+
+ $('#test-10 .epoch').epoch({
+ type: 'time.area',
+ axes: ['right', 'bottom'],
+ data: data,
+ range: [-2, 5]
+ });
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/debian/missing-sources/epoch/tests/render/real-time/bar.html b/debian/missing-sources/epoch/tests/render/real-time/bar.html
new file mode 100644
index 0000000..952119c
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/real-time/bar.html
@@ -0,0 +1,484 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+
+ <script>
+ var nextTime = (function() {
+ var currentTime = parseInt(new Date().getTime() / 1000);
+ return function() { return currentTime++; }
+ })();
+ </script>
+ </head>
+ <body>
+ <h1>Real-time Bar Test</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Real-time Bar</p>
+ <ol>
+ <li><a href="#test-1">Single Series</a></li>
+ <li><a href="#test-2">Single Series Single Transition</a></li>
+ <li><a href="#test-3">Single Seires Stream</a></li>
+ <li><a href="#test-4">Multi Series</a></li>
+ <li><a href="#test-5">Multi Series Single Transition</a></li>
+ <li><a href="#test-6">Multi Seires Stream</a></li>
+ <li><a href="#test-7">Color Override</a></li>
+ <li><a href="#test-8">Categorical Colors</a></li>
+ <li><a href="#test-9">Show/Hide Layers</a></li>
+ </ol>
+
+ <!-- Test 1 -->
+ <div id="test-1" class="test">
+ <h2>1. Single Series</h2>
+ <p>
+ Correctly render a single series plot of <code>y = cos(x) + 1</code> over the range <code>[0, 2&pi;]</code>.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.cos(x) + 1,
+ time = nextTime();
+ data[0].values.push({time: time, y: y});
+ }
+
+ $('#test-1 .epoch').epoch({ type: 'time.bar', data: data });
+ });
+ </script>
+
+ <!-- Test 2 -->
+ <div id="test-2" class="test">
+ <h2>2. Single Series Single Transition</h2>
+ <p>
+ Correctly render a single series plot of <code>y = sin(x) + 1</code>. When the button is pressed push a new data point to the chart and correctly animate/render the transiton.
+ </p>
+ <div class="epoch"></div>
+ <p><button>Next</button></p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 40,
+ nextIndex = length;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.sin(x) + 1,
+ time = nextTime();
+ data[0].values.push({time: time, y: y});
+ }
+
+ var chart = $('#test-2 .epoch').epoch({
+ type: 'time.bar',
+ data: data
+ });
+
+ $('#test-2 button').on('click', function(e) {
+ var x = nextIndex * 2 * Math.PI / length,
+ y = Math.sin(x) + 1,
+ time = nextTime();
+ nextIndex++;
+ chart.push([{ time: time, y: y }]);
+ });
+ });
+ </script>
+
+
+ <!-- Test 3 -->
+ <div id="test-3" class="test">
+ <h2>3. Single Seires Stream</h2>
+ <p>Correctly play / pause a single series stream of values from the plot <code>y = cos(x) + 1</code>.</p>
+ <div class="epoch"></div>
+ <p><button>Play</button></p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 40,
+ nextIndex = length,
+ playing = false,
+ interval = null;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.cos(x) + 1,
+ time = nextTime();
+ data[0].values.push({time: time, y: y});
+ }
+
+ var chart = $('#test-3 .epoch').epoch({
+ type: 'time.bar',
+ data: data
+ });
+
+ var pushPoint = function() {
+ var x = nextIndex * 2 * Math.PI / length,
+ y = Math.cos(x) + 1,
+ time = nextTime();
+ chart.push([{ time: time, y: y}]);
+ nextIndex++;
+ };
+
+ $('#test-3 button').on('click', function(e) {
+ if (playing) {
+ $(e.target).text('Play');
+ clearInterval(interval);
+ }
+ else {
+ $(e.target).text('Pause');
+ pushPoint();
+ interval = setInterval(pushPoint, 1000);
+ }
+ playing = !playing;
+ });
+ });
+ </script>
+
+ <!-- Test 4 -->
+ <div id="test-4" class="test">
+ <h2>4. Multi Series</h2>
+ <p>Correctly render a multi series plot of the following functions:</p>
+ <ul>
+ <li><code>y = log(x+1)</code></li>
+ <li><code>y = 2*log(x+1)</code></li>
+ <li><code>y = 3*log(x+1)</code></li>
+ </ul>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x = i + 1,
+ time = nextTime();
+ for (var j = 0; j < data.length; j++) {
+ data[j].values.push({time: time, y: (j+1) * Math.log(x)});
+ }
+ }
+
+ $('#test-4 .epoch').epoch({
+ type: 'time.bar',
+ data: data,
+ axes: ['left', 'right', 'bottom']
+ });
+ });
+ </script>
+
+
+ <!-- Test 5 -->
+ <div id="test-5" class="test">
+ <h2>5. Multi Series Single Transition</h2>
+ <p>
+ Correctly render a multi series plot of the following functions:
+ <ul>
+ <li><code>y = x</code></li>
+ <li><code>y = x<sup>1.25</sup></code></li>
+ <li><code>y = x<sup>1.5</sup></code></li>
+ </ul>
+ and correctly render/animate the transiton after pressing the "Next" button.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button>Next</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40,
+ scale = 0.1,
+ nextIndex = length;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * scale,
+ time = nextTime();
+ data[0].values.push({time: time, y: x});
+ data[1].values.push({time: time, y: Math.pow(x, 1.25)});
+ data[2].values.push({time: time, y: Math.pow(x, 1.5)});
+ }
+
+ var chart = $('#test-5 .epoch').epoch({
+ type: 'time.bar',
+ data: data,
+ axes: ['left', 'right', 'bottom']
+ });
+
+ $('#test-5 button').on('click', function(e) {
+ var x = nextIndex * scale,
+ time = nextTime();
+ nextIndex++;
+ chart.push([
+ {time: time, y: x},
+ {time: time, y: Math.pow(x, 1.25)},
+ {time: time, y: Math.pow(x, 1.5)}
+ ]);
+ });
+ });
+ </script>
+
+ <!-- Test 6 -->
+ <div id="test-6" class="test">
+ <h2>6. Multi Seires Stream</h2>
+ <p>
+ Correctly play / pause a multi series stream of values over the following plots:
+ <ul>
+ <li><code>x</code></li>
+ <li><code>x * log(x)</code></li>
+ <li><code>x * log<sup>2</sup>(x)</code></li>
+ </ul>
+ </p>
+ <div class="epoch"></div>
+ <p><button>Play</button></p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40,
+ nextIndex = length,
+ scale = 0.1,
+ playing = false,
+ interval = null;
+
+ for (var i = 0; i < length; i++) {
+ var x = (i+1) * scale,
+ time = nextTime();
+ data[0].values.push({time: time, y: x});
+ data[1].values.push({time: time, y: x * Math.log(x)});
+ data[2].values.push({time: time, y: x * Math.pow(Math.log(x), 2)});
+ }
+
+ var chart = $('#test-6 .epoch').epoch({
+ type: 'time.bar',
+ data: data,
+ axes: ['right', 'bottom']
+ });
+
+ var pushPoint = function() {
+ var x = (nextIndex +1) * scale,
+ time = nextTime();
+ chart.push([
+ { time: time, y: x},
+ { time: time, y: x * Math.log(x)},
+ { time: time, y: x * Math.pow(Math.log(x), 2)}
+ ]);
+ nextIndex++;
+ };
+
+ $('#test-6 button').on('click', function(e) {
+ if (playing) {
+ $(e.target).text('Play');
+ clearInterval(interval);
+ }
+ else {
+ $(e.target).text('Pause');
+ interval = setInterval(pushPoint, 1000);
+ pushPoint();
+ }
+ playing = !playing;
+ });
+ });
+ </script>
+
+ <!-- Test 7 -->
+ <div id="test-7" class="test">
+ <h2>7. Color Override</h2>
+ <p>The first layer should pink, the second green, and the third blue.</p>
+ <div id="test-7-plot" class="epoch"></div>
+ </div>
+
+ <style>
+ #test-7-plot .bar.a { fill: pink; }
+ #test-7-plot .bar.b { fill: green; }
+ #test-7-plot .bar.c { fill: blue; }
+ </style>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x = i + 1,
+ time = nextTime();
+ for (var j = 0; j < data.length; j++) {
+ data[j].values.push({time: time, y: (j+1) * Math.log(x)});
+ }
+ }
+
+ $('#test-7 .epoch').epoch({
+ type: 'time.bar',
+ data: data
+ });
+ });
+ </script>
+
+ <!-- Test 8 -->
+ <div id="test-8" class="test">
+ <h2>8. Categorical Colors</h2>
+ <p>Correctly render and switch between different categorical colors. Unlike with the basic charts this doesn't occur just by switching the class name on the containing element. The CSS query engine must be purge and the plot must be manually redrawn, like so:<code><pre>
+Epoch.QueryCSS.purge();
+chart.draw();
+</pre></code>
+ </p>
+
+ <div class="epoch category10"></div>
+
+ <p>
+ <button data-class="category10">category10</button>
+ <button data-class="category20">category20</button>
+ <button data-class="category20b">category20b</button>
+ <button data-class="category20c">category20c</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [],
+ length = 41,
+ className = "category10",
+ layers = 8,
+ time = nextTime();
+
+ for (var i = 0; i < layers; i++) {
+ var layer = { label: String.fromCharCode(i+65), values: [] };
+ for (var j = 0; j < length; j++) {
+ var x = j + 1,
+ y = Math.pow(x, 1 + 0.3 * Math.log(Math.log(Math.log(x+1) + 1) + 1));
+ layer.values.push({ time: time + j, y: y });
+ }
+ data.push(layer);
+ }
+
+ var chart = $('#test-8 .epoch').epoch({ type: 'time.bar', data: data });
+
+ $('#test-8 button').on('click', function(e) {
+ $('#test-8 .epoch').removeClass(className);
+ className = $(e.target).attr('data-class');
+ $('#test-8 .epoch').addClass(className);
+ Epoch.QueryCSS.purge();
+ chart.draw();
+ });
+ });
+ </script>
+
+ <!-- Test 9 -->
+ <div id="test-9" class="test">
+ <h2>9. Show/Hide Layers</h2>
+ <div class="epoch"></div>
+ <p>
+ <button class="toggle" data-index="0">Toggle A</button>
+ <button class="toggle" data-index="1">Toggle B</button>
+ <button class="toggle" data-index="2">Toggle C</button> |
+ <button class="playback">Play</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var data = [
+ { label: 'A', values: [] },
+ { label: 'B', values: [] },
+ { label: 'C', values: [] }
+ ],
+ time = nextTime(),
+ j = 0,
+ interval = null;
+
+ for (var i = 0; i < data.length; i++) {
+ for (j = 0; j < 60; j++) {
+ data[i].values.push({time: time+j, y: 0.25*(i+4)*j })
+ }
+ }
+
+ function nextPoint() {
+ var entry = []
+ for (var i = 0; i < data.length; i++) {
+ entry.push({time: time+j, y: 0.25*(i+4)*j });
+ }
+ chart.push(entry);
+ j++;
+ }
+
+ var chart = $('#test-9 .epoch').epoch({ type: 'time.bar', data: data });
+
+ $('#test-9 .toggle').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.toggleLayer(index);
+ });
+
+ $('#test-9 .playback').click(function(e) {
+ if (interval == null) {
+ interval = setInterval(nextPoint, 1000);
+ nextPoint();
+ $(e.target).text('Pause');
+ }
+ else {
+ clearInterval(interval);
+ interval = null;
+ $(e.target).text('Play');
+ }
+ });
+ });
+ </script>
+
+ <!-- Test 10 -->
+ <div id="test-10" class="test">
+ <h2>10. Fixed Range</h2>
+ <p>
+ Render a single series plot of <code>y = cos(x) + 1</code>. Instead of automatically setting the range to <code>[0, 2]</code>, the range is manually set to <code>[0, 5]</code>.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.cos(x) + 1,
+ time = nextTime();
+ data[0].values.push({time: time, y: y});
+ }
+
+ $('#test-10 .epoch').epoch({
+ type: 'time.bar',
+ axes: ['right', 'bottom'],
+ data: data,
+ range: [0, 5]
+ });
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/debian/missing-sources/epoch/tests/render/real-time/gauge.html b/debian/missing-sources/epoch/tests/render/real-time/gauge.html
new file mode 100644
index 0000000..614334d
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/real-time/gauge.html
@@ -0,0 +1,283 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+
+ <script>
+ var nextTime = (function() {
+ var currentTime = parseInt(new Date().getTime() / 1000);
+ return function() { return currentTime++; }
+ })();
+ </script>
+ </head>
+ <body>
+ <h1>Real-time Gauge Test</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Real-time Gauge</p>
+ <ol>
+ <li><a href="#test-1">Single Value Display</a></li>
+ <li><a href="#test-2">Single Transition</a></li>
+ <li><a href="#test-3">Stream Transition</a></li>
+ <li><a href="#test-4">Gauge Sizes</a></li>
+ <li><a href="#test-5">Color Override</a></li>
+ <li><a href="test-6">Option: domain</a></li>
+ <li><a href="test-7">Option: ticks</a></li>
+ <li><a href="test-8">Option: tickSize</a></li>
+ <li><a href="test-9">Option: tickOffset</a></li>
+ <li><a href="test-10">Option: format</a></li>
+ </ol>
+
+ <!-- Test 1 -->
+ <div id="test-1" class="test">
+ <h2>1. Single Value Display</h2>
+ <p>Display a single value of 25%</p>
+ <div class="epoch gauge-small"></div>
+ </div>
+ <script>
+ $(function() {
+ $('#test-1 .epoch').epoch({ type: 'time.gauge', value: 0.25 });
+ });
+ </script>
+
+
+ <!-- Test 2 -->
+ <div id="test-2" class="test">
+ <h2>2. Single Transition</h2>
+ <p>Display value of 0% and transition to a random value when the button is pressed.</p>
+ <div class="epoch gauge-small"></div>
+ <p><button>Transition</button></p>
+ </div>
+ <script>
+ $(function() {
+ var chart = $('#test-2 .epoch').epoch({
+ type: 'time.gauge',
+ value: 0.0
+ });
+
+ $('#test-2 button').on('click', function(e) {
+ chart.update(Math.random());
+ });
+ });
+ </script>
+
+
+ <!-- Test 3 -->
+ <div id="test-3" class="test">
+ <h2>3. Stream Transition</h2>
+ <p>Display value of 0% and transition to a random value every second when the button is pressed.</p>
+ <div class="epoch gauge-small"></div>
+ <p><button>Play</button></p>
+ </div>
+ <script>
+ $(function() {
+ var chart = $('#test-3 .epoch').epoch({
+ type: 'time.gauge',
+ value: 0.0
+ }),
+ playing = false,
+ interval = null;
+
+ $('#test-3 button').on('click', function(e) {
+ if (interval === null) {
+ interval = setInterval(function() {
+ chart.update(Math.random());
+ }, 1000);
+ chart.update(Math.random());
+ $(e.target).text('Pause');
+ }
+ else {
+ clearInterval(interval);
+ interval = null;
+ $(e.target).text('Play');
+ }
+ });
+ });
+ </script>
+
+ <!-- Test 4 -->
+ <div id="test-4" class="test">
+ <h2>4. Gauge Sizes</h2>
+ <p>Display the four built-in gauge sizes in this order: tiny, small, medium, large.</p>
+ <div class="epoch gauge-tiny"></div>
+ <div class="epoch gauge-small"></div>
+ <div class="epoch gauge-medium"></div>
+ <div class="epoch gauge-large"></div>
+ </div>
+ <script>
+ $(function() {
+ $('#test-4 .gauge-tiny').epoch({ type: 'time.gauge', value: 0.75 });
+ $('#test-4 .gauge-small').epoch({ type: 'time.gauge', value: 0.75 });
+ $('#test-4 .gauge-medium').epoch({ type: 'time.gauge', value: 0.75 });
+ $('#test-4 .gauge-large').epoch({ type: 'time.gauge', value: 0.75 });
+ });
+ </script>
+
+ <!-- Test 5 -->
+ <div id="test-5" class="test">
+ <h2>5. Color Override</h2>
+ <p>
+ Override the basic gauge styles with the following
+ <ul>
+ <li>Outer arc 8px thickness colored green</li>
+ <li>Inner arc 2px thickness colored orange</li>
+ <li>Ticks should be 3px in width and red</li>
+ <li>Needle colored blue.</li>
+ <li>Needle base colored black</li>
+ </ul>
+ </p>
+ <div id="test-5-plot" class="epoch gauge-medium"></div>
+ </div>
+
+ <style>
+ #test-5-plot .epoch .gauge .arc.outer {
+ stroke-width: 8px;
+ stroke: green;
+ }
+
+ #test-5-plot .epoch .gauge .arc.inner {
+ stroke-width: 2px;
+ stroke: orange;
+ }
+
+ #test-5-plot .epoch .gauge .tick {
+ stroke-width: 3px;
+ stroke: red;
+ }
+
+ #test-5-plot .epoch .gauge .needle {
+ fill: blue;
+ }
+
+ #test-5-plot .epoch .gauge .needle-base {
+ fill: black;
+ }
+ </style>
+
+ <script>
+ $(function() {
+ $('#test-5 .epoch').epoch({ type: 'time.gauge', value: 0.5 });
+ });
+ </script>
+
+ <!--
+ Common Option Event Listener Events
+ -->
+ <script>
+ window.makeOptionTest = function(testNumber, chartOptions, optionName) {
+ chartOptions = chartOptions ? chartOptions : {};
+
+ if (!chartOptions.type)
+ chartOptions.type = 'time.gauge';
+ if (!chartOptions.value)
+ chartOptions.value = 0.5;
+ if (!chartOptions.domain)
+ chartOptions.domain = [0, 1];
+
+ var domain = chartOptions.domain,
+ id = '#test-' + testNumber,
+ chart = $(id + ' .epoch').epoch(chartOptions),
+ interval = null,
+ next = function() { chart.push(Math.random()*(domain[1] - domain[0]) + domain[0]); };
+
+ $(id + ' .playback').click(function(e) {
+ if (!interval) {
+ interval = setInterval(next, 1500);
+ next();
+ $(e.target).text('Pause');
+ }
+ else {
+ clearInterval(interval);
+ interval = null;
+ $(e.target).text('Play');
+ }
+ });
+
+ var formats = [
+ Epoch.Formats.percent,
+ function(d) { return d.toFixed(2); }
+ ];
+
+ $(id + ' .option').click(function(e) {
+ var value = parseInt($(e.target).attr('data-value'));
+
+ console.log(optionName, value);
+
+ if (optionName == 'domain')
+ value = domain = $(e.target).attr('data-value').split(',').map(function(d) { return parseInt(d); });
+ else if (optionName == 'format')
+ value = formats[value];
+ chart.option(optionName, value);
+ });
+ };
+ </script>
+
+
+ <!-- Test 6 -->
+ <div id="test-6" class="test">
+ <h2>6. Option: domain</h2>
+ <div class="epoch gauge-small"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <button class="option" data-value="0,1">[0, 1]</button>
+ <button class="option" data-value="0,2">[0, 2]</button>
+ </p>
+ </div>
+ <script>$(function() { makeOptionTest(6, {}, 'domain'); });</script>
+
+ <!-- Test 7 -->
+ <div id="test-7" class="test">
+ <h2>7. Option: ticks</h2>
+ <div class="epoch gauge-small"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <button class="option" data-value="5">5 Ticks</button>
+ <button class="option" data-value="10">10 Ticks</button>
+ <button class="option" data-value="20">20 Ticks</button>
+ <button class="option" data-value="40">40 Ticks</button>
+ </p>
+ </div>
+ <script>$(function() { makeOptionTest(7, {}, 'ticks'); });</script>
+
+ <!-- Test 8 -->
+ <div id="test-8" class="test">
+ <h2>8. Option: tickSize</h2>
+ <div class="epoch gauge-small"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <button class="option" data-value="2">2px</button>
+ <button class="option" data-value="5">5px</button>
+ <button class="option" data-value="10">10px</button>
+ <button class="option" data-value="20">20px</button>
+ </p>
+ </div>
+ <script>$(function() { makeOptionTest(8, {}, 'tickSize'); });</script>
+
+ <!-- Test 9 -->
+ <div id="test-9" class="test">
+ <h2>9. Option: tickOffset</h2>
+ <div class="epoch gauge-small"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <button class="option" data-value="5">5px</button>
+ <button class="option" data-value="10">10px</button>
+ <button class="option" data-value="20">20px</button>
+ </p>
+ </div>
+ <script>$(function() { makeOptionTest(9, {}, 'tickOffset'); });</script>
+
+ <!-- Test 10 -->
+ <div id="test-10" class="test">
+ <h2>10. Option: format</h2>
+ <div class="epoch gauge-small"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <button class="option" data-value="0">Percent</button>
+ <button class="option" data-value="1">Normal</button>
+ </p>
+ </div>
+ <script>$(function() { makeOptionTest(10, {}, 'format'); });</script>
+ </body>
+</html>
diff --git a/debian/missing-sources/epoch/tests/render/real-time/heatmap.html b/debian/missing-sources/epoch/tests/render/real-time/heatmap.html
new file mode 100644
index 0000000..ddabe2e
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/real-time/heatmap.html
@@ -0,0 +1,559 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <script src="../js/data.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+ </head>
+ <body>
+ <h1>Real-time Heatmap Plot Test</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Real-time Heatmap</p>
+ <ol>
+ <li><a href="#test-1">Single Series - Normal</a></li>
+ <li><a href="#test-2">Single Series - Beta</a></li>
+ <li><a href="#test-3">Single Series - Normal, Single Update</a></li>
+ <li><a href="#test-4">Single Series - Beta, Stream Update</a></li>
+ <li><a href="#test-5">Single Series - Color Override</a></li>
+ <li><a href="#test-6">Multi Series - Normal + Beta</a></li>
+ <li><a href="#test-7">Multi Series Color Override</a></li>
+ <li><a href="#test-8">Range Independent Bucketing</a></li>
+ <li><a href="#test-9">Option: buckets</a></li>
+ <li><a href="#test-10">Option: bucketRange</a></li>
+ <li><a href="#test-11">Option: bucketPadding</a></li>
+ <li><a href="#test-12">Option: cutOutliers</a></li>
+ <li><a href="#test-13">Option: opacity</a></li>
+ <li><a href="#test-14">Show/Hide Layer</a></li>
+ </ol>
+
+ <!-- Test 1 -->
+ <div id="test-1" class="test">
+ <h2>1. Single Series - Normal</h2>
+ <p>Select random values from the normal distribution and display them with the heatmap.</p>
+ <div class="epoch"></div>
+ </div>
+ <script>
+ $(function() {
+ var data = new NormalData(1);
+ $('#test-1 .epoch').epoch({
+ type: 'time.heatmap',
+ data: data.history(120),
+ windowSize: 120,
+ buckets: 20
+ });
+ });
+ </script>
+
+ <!-- Test 2 -->
+ <div id="test-2" class="test">
+ <h2>2. Single Series - Beta </h2>
+ <p>Select random values from the Beta(2, 5) distribution and display them with the heatmap.</p>
+ <div class="epoch"></div>
+ </div>
+ <script>
+ $(function() {
+ var data = new BetaData(2, 5, 1);
+ $('#test-2 .epoch').epoch({
+ type: 'time.heatmap',
+ data: data.history(120),
+ windowSize: 120,
+ buckets: 20
+ });
+ });
+ </script>
+
+ <!-- Test 3 -->
+ <div id="test-3" class="test">
+ <h2>3. Single Sieres - Normal, Single Update</h2>
+ <p>
+ Plot the normal distribution and transition a new element when the button is pressed.
+ </p>
+ <div class="epoch"></div>
+ <p><button>Next</button></p>
+ </div>
+ <script>
+ $(function() {
+ var data = new NormalData(1);
+ var chart = $('#test-3 .epoch').epoch({
+ type: 'time.heatmap',
+ data: data.history(120),
+ windowSize: 120,
+ buckets: 20
+ });
+ $('#test-3 button').on('click', function(e) {
+ chart.push(data.next());
+ });
+ });
+ </script>
+
+ <!-- Test 4 -->
+ <div id="test-4" class="test">
+ <h2>4. Single Series - Beta, Stream Update</h2>
+ <p>
+ Plot the Beta(2, 5) distribution and begin streaming new elements each second once the
+ button is pressed.
+ </p>
+ <div class="epoch"></div>
+ <button>Play</button>
+ </div>
+
+ <script>
+ $(function() {
+ var data = new BetaData(2, 5, 1),
+ interval = null;
+ var chart = $('#test-4 .epoch').epoch({
+ type: 'time.heatmap',
+ data: data.history(120),
+ windowSize: 120,
+ buckets: 20
+ });
+ $('#test-4 button').on('click', function(e) {
+ if (interval === null) {
+ chart.push(data.next());
+ interval = setInterval(function() {
+ chart.push(data.next());
+ }, 1000);
+ $(e.target).text('Pause');
+ }
+ else {
+ clearInterval(interval);
+ interval = null;
+ $(e.target).text('Play');
+ }
+ });
+ });
+ </script>
+
+ <!-- Test 5 -->
+ <div id="test-5" class="test">
+ <h2>5. Single Series - Color Override</h2>
+ <p>Change the bucket base color to orange and plot the Beta(2, 2) distribution.</p>
+ <div id="test-5-plot" class="epoch"></div>
+ </div>
+
+ <style>
+ #test-5-plot .a rect.bucket { fill: darkorange; }
+ </style>
+
+ <script>
+ $(function() {
+ var data = new BetaData(2, 2, 1);
+ $('#test-5 .epoch').epoch({
+ type: 'time.heatmap',
+ data: data.history(120),
+ windowSize: 120,
+ buckets: 20
+ });
+ });
+ </script>
+
+ <!-- Test 6 -->
+ <div id="test-6" class="test">
+ <h2>6. Multi Series - Normal + Beta</h2>
+ <p>
+ Plot the Beta(2,5) and Normal distributions as two layers in a single heatmap. Stream elements to the plot
+ by pressing the button. The normal distribution layer is in blue and the beta in green.
+ </p>
+ <div class="epoch"></div>
+ <button>Play</button>
+ </div>
+ <script>
+ $(function() {
+ var normal = new NormalData(1),
+ normalData = normal.history(120)[0],
+ beta = new BetaData(2, 5, 1),
+ betaData = beta.history(120)[0],
+ data = [normalData, betaData],
+ interval = null;
+
+ var chart = $('#test-6 .epoch').epoch({
+ type: 'time.heatmap',
+ data: data,
+ windowSize: 120,
+ buckets: 20
+ });
+
+ function pushNext() {
+ chart.push([normal.next()[0], beta.next()[0]]);
+ }
+
+ $('#test-6 button').on('click', function(e) {
+ if (interval == null) {
+ pushNext();
+ interval = setInterval(pushNext, 1000);
+ $(e.target).text('Pause');
+ }
+ else {
+ clearInterval(interval);
+ interval = null;
+ $(e.target).text('Play');
+ }
+ });
+ });
+ </script>
+
+ <!-- Test 7 -->
+ <div id="test-7" class="test">
+ <h2>7. Multi Series Color Override</h2>
+ <p>
+ Plot the normal distribution and the Beta(2, 5) distribution overrding normal to be in red, and beta to
+ be in purple.
+ </p>
+ <div id="test-7-plot" class="epoch"></div>
+ </div>
+
+ <style>
+ #test-7-plot .a rect.bucket { fill: red; }
+ #test-7-plot .b rect.bucket { fill: purple; }
+ </style>
+
+ <script>
+ $(function() {
+ var normal = new NormalData(1),
+ normalData = normal.history(120)[0],
+ beta = new BetaData(2, 5, 1),
+ betaData = beta.history(120)[0],
+ interval = null;
+
+ normalData.label = 'A';
+ betaData.label = 'B';
+
+ var chart = $('#test-7 .epoch').epoch({
+ type: 'time.heatmap',
+ data: [normalData, betaData],
+ windowSize: 120,
+ buckets: 20
+ });
+ });
+ </script>
+
+ <!-- Test 8 -->
+ <div id="test-8" class="test">
+ <h2>8. Range Independent Bucketing (<a href="https://github.com/fastly/epoch/issues/41">Issue #41</a>)</h2>
+ <p>
+ Discrete bucketing of sparse histogram values should produce similar looking graphs regardless
+ of numeric relation between the range of the plot and the number of buckets.
+ </p>
+ <h3>Range [0, 100] with 20 buckets</h3>
+ <div class="chart1 epoch"></div>
+
+ <h3>Range [0, 100] with 45 buckets</h3>
+ <div class="chart2 epoch"></div>
+ </div>
+ <script>
+ $(function() {
+ var normal = new NormalData(1),
+ data = normal.history(120);
+
+ console.log(data);
+
+ $('#test-8 .chart1').epoch({
+ type: 'time.heatmap',
+ data: data,
+ windowSize: 120,
+ buckets: 20
+ });
+ $('#test-8 .chart2').epoch({
+ type: 'time.heatmap',
+ data: data,
+ windowSize: 120,
+ buckets: 45
+ });
+ });
+ </script>
+
+ <!-- Test 9 -->
+ <div id="test-9" class="test">
+ <h2>9. Option: buckets</h2>
+ <div class="epoch"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <button class="buckets" data-buckets="10">10 Buckets</button>
+ <button class="buckets" data-buckets="20">20 Buckets</button>
+ <button class="buckets" data-buckets="40">40 Buckets</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var beta = new BetaData(2, 5, 1),
+ data = beta.history(120);
+
+ var chart = $('#test-9 .epoch').epoch({
+ type: 'time.heatmap',
+ data: data,
+ buckets: 10
+ });
+
+ var interval = null,
+ pushPoint = function () { chart.push(beta.next()); };
+
+ $('#test-9 .playback').click(function(e) {
+ if (interval == null) {
+ $(e.target).text('Pause');
+ pushPoint();
+ interval = setInterval(pushPoint, 1000);
+ }
+ else {
+ $(e.target).text('Play');
+ clearInterval(interval);
+ interval = null;
+ }
+ });
+
+ $('#test-9 .buckets').click(function(e) {
+ var buckets = parseInt($(e.target).attr('data-buckets'));
+ chart.option('buckets', buckets);
+ });
+ });
+ </script>
+
+ <!-- Test 10 -->
+ <div id="test-10" class="test">
+ <h2>10. Option: bucketRange</h2>
+ <div class="epoch"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <button class="bucketRange" data-bucket-range="0,100">[0, 100]</button>
+ <button class="bucketRange" data-bucket-range="0,75">[0, 75]</button>
+ <button class="bucketRange" data-bucket-range="0,50">[0, 50]</button>
+ <button class="bucketRange" data-bucket-range="0,25">[0, 25]</button>
+ <button class="bucketRange" data-bucket-range="10,75">[10,75]</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var beta = window.beta = new BetaData(2, 5, 1),
+ data = beta.history(120);
+
+ var chart = $('#test-10 .epoch').epoch({
+ type: 'time.heatmap',
+ data: data,
+ axes: ['left', 'right'],
+ buckets: 20,
+ windowSize: 100,
+ cutOutliers: true
+ });
+
+ var interval = null,
+ pushPoint = function () { chart.push(beta.next()); };
+
+ $('#test-10 .playback').click(function(e) {
+ if (interval == null) {
+ $(e.target).text('Pause');
+ pushPoint();
+ interval = setInterval(pushPoint, 1000);
+ }
+ else {
+ $(e.target).text('Play');
+ clearInterval(interval);
+ interval = null;
+ }
+ });
+
+ $('#test-10 .bucketRange').click(function(e) {
+ var bucketRange = $(e.target).attr('data-bucket-range')
+ .split(',').map(function(d) { return parseInt(d); });
+ chart.option('bucketRange', bucketRange);
+ });
+ });
+ </script>
+
+ <!-- Test 11 -->
+ <div id="test-11" class="test">
+ <h2>11. Option: bucketPadding</h2>
+ <div class="epoch"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <button class="bucketPadding" data-bucket-padding="0">Padding: 0</button>
+ <button class="bucketPadding" data-bucket-padding="2">Padding: 2</button>
+ <button class="bucketPadding" data-bucket-padding="4">Padding: 4</button>
+ <button class="bucketPadding" data-bucket-padding="8">Padding: 8</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var beta = window.beta = new BetaData(2, 5, 1),
+ data = beta.history(120);
+
+ var chart = $('#test-11 .epoch').epoch({
+ type: 'time.heatmap',
+ data: data,
+ axes: [],
+ buckets: 15,
+ windowSize: 100
+ });
+
+ var interval = null,
+ pushPoint = function () { chart.push(beta.next()); };
+
+ $('#test-11 .playback').click(function(e) {
+ if (interval == null) {
+ $(e.target).text('Pause');
+ pushPoint();
+ interval = setInterval(pushPoint, 1000);
+ }
+ else {
+ $(e.target).text('Play');
+ clearInterval(interval);
+ interval = null;
+ }
+ });
+
+ $('#test-11 .bucketPadding').click(function(e) {
+ var bucketPadding = parseInt($(e.target).attr('data-bucket-padding'));
+ console.log(bucketPadding)
+ chart.option('bucketPadding', bucketPadding);
+ });
+ });
+ </script>
+
+ <!-- Test 12 -->
+ <div id="test-12" class="test">
+ <h2>12. Option: cutOutliers</h2>
+ <div class="epoch"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <button class="cutOutliers" data-value="false">Keep Outliers</button>
+ <button class="cutOutliers" data-value="true">Cut Outliers</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var beta = window.beta = new BetaData(2, 5, 1),
+ data = beta.history(120);
+
+ var chart = $('#test-12 .epoch').epoch({
+ type: 'time.heatmap',
+ data: data,
+ axes: ['left', 'right'],
+ bucketRange: [0, 25],
+ buckets: 15,
+ windowSize: 100
+ });
+
+ var interval = null,
+ pushPoint = function () { chart.push(beta.next()); };
+
+ $('#test-12 .playback').click(function(e) {
+ if (interval == null) {
+ $(e.target).text('Pause');
+ pushPoint();
+ interval = setInterval(pushPoint, 1000);
+ }
+ else {
+ $(e.target).text('Play');
+ clearInterval(interval);
+ interval = null;
+ }
+ });
+
+ $('#test-12 .cutOutliers').click(function(e) {
+ var cutOutliers = $(e.target).attr('data-value') == "true" ? true : false;
+ chart.option('cutOutliers', cutOutliers);
+ });
+ });
+ </script>
+
+ <div id="test-13" class="test">
+ <h2>13. Option: opacity</h2>
+ <div class="epoch"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <select class="opacity">
+ <option value="root">&radic;n</option>
+ <option value="linear" selected>n</option>
+ <option value="quadratic">n<sup>2</sup></option>
+ <option value="cubic">n<sup>3</sup></option>
+ <option value="quartic">n<sup>4</sup></option>
+ <option value="quintic">n<sup>5</sup></option>
+ </select>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var beta = window.beta = new BetaData(2, 5, 1),
+ data = beta.history(120);
+
+ var chart = $('#test-13 .epoch').epoch({
+ type: 'time.heatmap',
+ data: data,
+ axes: [],
+ buckets: 20,
+ windowSize: 100
+ });
+
+ var interval = null,
+ pushPoint = function () { chart.push(beta.next()); };
+
+ $('#test-13 .playback').click(function(e) {
+ if (interval == null) {
+ $(e.target).text('Pause');
+ pushPoint();
+ interval = setInterval(pushPoint, 1000);
+ }
+ else {
+ $(e.target).text('Play');
+ clearInterval(interval);
+ interval = null;
+ }
+ });
+
+ $('#test-13 select.opacity').on('change', function(e) {
+ var opacity = $('#test-13 select.opacity').val();
+ chart.option('opacity', opacity);
+ });
+ });
+ </script>
+
+ <div id="test-14" class="test">
+ <h2>14. Show/Hide Layer</h2>
+ <div class="epoch"></div>
+ <p>
+ <button class="toggle" data-index="0">Toggle A</button>
+ <button class="toggle" data-index="1">Toggle B</button> |
+ <button class="playback">Play</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var normal = new NormalData(1),
+ normalData = normal.history(120)[0],
+ beta = new BetaData(2, 5, 1),
+ betaData = beta.history(120)[0],
+ data = [normalData, betaData],
+ interval = null;
+
+ var chart = $('#test-14 .epoch').epoch({
+ type: 'time.heatmap',
+ data: data,
+ windowSize: 120,
+ buckets: 20
+ });
+
+ $('#test-14 .toggle').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.toggleLayer(index);
+ });
+
+ function pushNext() {
+ chart.push([normal.next()[0], beta.next()[0]]);
+ }
+
+ $('#test-14 .playback').on('click', function(e) {
+ if (interval == null) {
+ pushNext();
+ interval = setInterval(pushNext, 1000);
+ $(e.target).text('Pause');
+ }
+ else {
+ clearInterval(interval);
+ interval = null;
+ $(e.target).text('Play');
+ }
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/debian/missing-sources/epoch/tests/render/real-time/line.html b/debian/missing-sources/epoch/tests/render/real-time/line.html
new file mode 100644
index 0000000..3346c98
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/real-time/line.html
@@ -0,0 +1,596 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+
+ <script>
+ var nextTime = (function() {
+ var currentTime = parseInt(new Date().getTime() / 1000);
+ return function() { return currentTime++; }
+ })();
+ </script>
+ </head>
+ <body>
+ <h1>Real-time Line Plot Test</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Real-time Line</p>
+ <ol>
+ <li><a href="#test-1">Single Series</a></li>
+ <li><a href="#test-2">Single Series Single Transition</a></li>
+ <li><a href="#test-3">Single Seires Stream</a></li>
+ <li><a href="#test-4">Multi Series</a></li>
+ <li><a href="#test-5">Multi Series Single Transition</a></li>
+ <li><a href="#test-6">Multi Seires Stream</a></li>
+ <li><a href="#test-7">Color Override</a></li>
+ <li><a href="#test-8">Categorical Colors</a></li>
+ <li><a href="#test-9">Show/Hide Layers</a></li>
+ <li><a href="#test-10">Show/Hide Layers</a></li>
+ <li><a href="#test-11">Multiaxes</a></li>
+ </ol>
+
+ <!-- Test 1 -->
+ <div id="test-1" class="test">
+ <h2>1. Single Series</h2>
+ <p>
+ Correctly render a single series plot of <code>y = cos(x) + 1</code> over the range <code>[0, 2&pi;]</code>.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.cos(x) + 1,
+ time = nextTime();
+ data[0].values.push({time: time, y: y});
+ }
+
+ $('#test-1 .epoch').epoch({ type: 'time.line', data: data });
+ });
+ </script>
+
+ <!-- Test 2 -->
+ <div id="test-2" class="test">
+ <h2>2. Single Series Single Transition</h2>
+ <p>
+ Correctly render a single series plot of <code>y = sin(x) + 1</code>. When the button is pressed push a new data point to the chart and correctly animate/render the transiton.
+ </p>
+ <div class="epoch"></div>
+ <p><button>Next</button></p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 40,
+ nextIndex = length;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.sin(x) + 1,
+ time = nextTime();
+ data[0].values.push({time: time, y: y});
+ }
+
+ var chart = $('#test-2 .epoch').epoch({
+ type: 'time.line',
+ data: data
+ });
+
+ $('#test-2 button').on('click', function(e) {
+ var x = nextIndex * 2 * Math.PI / length,
+ y = Math.sin(x) + 1,
+ time = nextTime();
+ nextIndex++;
+ chart.push([{ time: time, y: y }]);
+ });
+ });
+ </script>
+
+
+ <!-- Test 3 -->
+ <div id="test-3" class="test">
+ <h2>3. Single Seires Stream</h2>
+ <p>Correctly play / pause a single series stream of values from the plot <code>y = cos(x) + 1</code>.</p>
+ <div class="epoch"></div>
+ <p><button>Play</button></p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 40,
+ nextIndex = length,
+ playing = false,
+ interval = null;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.cos(x) + 1,
+ time = nextTime();
+ data[0].values.push({time: time, y: y});
+ }
+
+ var chart = $('#test-3 .epoch').epoch({
+ type: 'time.line',
+ data: data
+ });
+
+ var pushPoint = function() {
+ var x = nextIndex * 2 * Math.PI / length,
+ y = Math.cos(x) + 1,
+ time = nextTime();
+ chart.push([{ time: time, y: y}]);
+ nextIndex++;
+ };
+
+ $('#test-3 button').on('click', function(e) {
+ if (playing) {
+ $(e.target).text('Play');
+ clearInterval(interval);
+ }
+ else {
+ $(e.target).text('Pause');
+ pushPoint();
+ interval = setInterval(pushPoint, 1000);
+ }
+ playing = !playing;
+ });
+ });
+ </script>
+
+ <!-- Test 4 -->
+ <div id="test-4" class="test">
+ <h2>4. Multi Series</h2>
+ <p>Correctly render a multi series plot of the following functions:</p>
+ <ul>
+ <li><code>y = log(x+1)</code></li>
+ <li><code>y = 2*log(x+1)</code></li>
+ <li><code>y = 3*log(x+1)</code></li>
+ </ul>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x = i + 1,
+ time = nextTime();
+ for (var j = 0; j < data.length; j++) {
+ data[j].values.push({time: time, y: (j+1) * Math.log(x)});
+ }
+ }
+
+ $('#test-4 .epoch').epoch({
+ type: 'time.line',
+ data: data,
+ axes: ['left', 'right', 'bottom']
+ });
+ });
+ </script>
+
+
+ <!-- Test 5 -->
+ <div id="test-5" class="test">
+ <h2>5. Multi Series Single Transition</h2>
+ <p>
+ Correctly render a multi series plot of the following functions:
+ <ul>
+ <li><code>y = x</code></li>
+ <li><code>y = x<sup>1.25</sup></code></li>
+ <li><code>y = x<sup>1.5</sup></code></li>
+ </ul>
+ and correctly render/animate the transiton after pressing the "Next" button.
+ </p>
+ <div class="epoch"></div>
+ <p>
+ <button>Next</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40,
+ scale = 0.1,
+ nextIndex = length;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * scale,
+ time = nextTime();
+ data[0].values.push({time: time, y: x});
+ data[1].values.push({time: time, y: Math.pow(x, 1.25)});
+ data[2].values.push({time: time, y: Math.pow(x, 1.5)});
+ }
+
+ var chart = $('#test-5 .epoch').epoch({
+ type: 'time.line',
+ data: data,
+ axes: ['left', 'right', 'bottom']
+ });
+
+ $('#test-5 button').on('click', function(e) {
+ var x = nextIndex * scale,
+ time = nextTime();
+ nextIndex++;
+ chart.push([
+ {time: time, y: x},
+ {time: time, y: Math.pow(x, 1.25)},
+ {time: time, y: Math.pow(x, 1.5)}
+ ]);
+ });
+ });
+ </script>
+
+ <!-- Test 6 -->
+ <div id="test-6" class="test">
+ <h2>6. Multi Seires Stream</h2>
+ <p>
+ Correctly play / pause a multi series stream of values over the following plots:
+ <ul>
+ <li><code>x</code></li>
+ <li><code>x * log(x)</code></li>
+ <li><code>x * log<sup>2</sup>(x)</code></li>
+ </ul>
+ </p>
+ <div class="epoch"></div>
+ <p><button>Play</button></p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40,
+ nextIndex = length,
+ scale = 0.1,
+ playing = false,
+ interval = null;
+
+ for (var i = 0; i < length; i++) {
+ var x = (i+1) * scale,
+ time = nextTime();
+ data[0].values.push({time: time, y: x});
+ data[1].values.push({time: time, y: x * Math.log(x)});
+ data[2].values.push({time: time, y: x * Math.pow(Math.log(x), 2)});
+ }
+
+ var chart = $('#test-6 .epoch').epoch({
+ type: 'time.line',
+ data: data,
+ axes: ['right', 'bottom']
+ });
+
+ var pushPoint = function() {
+ var x = (nextIndex +1) * scale,
+ time = nextTime();
+ chart.push([
+ { time: time, y: x},
+ { time: time, y: x * Math.log(x)},
+ { time: time, y: x * Math.pow(Math.log(x), 2)}
+ ]);
+ nextIndex++;
+ };
+
+ $('#test-6 button').on('click', function(e) {
+ if (playing) {
+ $(e.target).text('Play');
+ clearInterval(interval);
+ }
+ else {
+ $(e.target).text('Pause');
+ interval = setInterval(pushPoint, 1000);
+ pushPoint();
+ }
+ playing = !playing;
+ });
+ });
+ </script>
+
+ <!-- Test 7 -->
+ <div id="test-7" class="test">
+ <h2>7. Color Override</h2>
+ <p>The first layer should pink, the second green, and the third blue.</p>
+ <div id="test-7-plot" class="epoch"></div>
+ </div>
+
+ <style>
+ #test-7-plot .a .line { stroke: pink; }
+ #test-7-plot .b .line { stroke: green; }
+ #test-7-plot .c .line { stroke: blue; }
+ </style>
+
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x = i + 1,
+ time = nextTime();
+ for (var j = 0; j < data.length; j++) {
+ data[j].values.push({time: time, y: (j+1) * Math.log(x)});
+ }
+ }
+
+ $('#test-7 .epoch').epoch({
+ type: 'time.line',
+ data: data
+ });
+ });
+ </script>
+
+ <!-- Test 8 -->
+ <div id="test-8" class="test">
+ <h2>8. Categorical Colors</h2>
+ <p>Correctly render and switch between different categorical colors. Unlike with the basic charts this doesn't occur just by switching the class name on the containing element. The CSS query engine must be purge and the plot must be manually redrawn, like so:<code><pre>
+Epoch.QueryCSS.purge();
+chart.draw();
+</pre></code>
+ </p>
+
+ <div class="epoch category10"></div>
+
+ <p>
+ <button data-class="category10">category10</button>
+ <button data-class="category20">category20</button>
+ <button data-class="category20b">category20b</button>
+ <button data-class="category20c">category20c</button>
+ </p>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [],
+ length = 41,
+ className = "category10",
+ layers = 8,
+ time = nextTime();
+
+ for (var i = 0; i < layers; i++) {
+ var layer = { label: String.fromCharCode(i+65), values: [] };
+ for (var j = 0; j < length; j++) {
+ var x = j + 1,
+ y = Math.pow(x, i * 0.02);
+ layer.values.push({ time: time + j, y: y });
+ }
+ data.push(layer);
+ }
+
+ var chart = $('#test-8 .epoch').epoch({ type: 'time.line', data: data });
+
+ $('#test-8 button').on('click', function(e) {
+ $('#test-8 .epoch').removeClass(className);
+ className = $(e.target).attr('data-class');
+ $('#test-8 .epoch').addClass(className);
+ Epoch.QueryCSS.purge();
+ chart.draw();
+ });
+ });
+ </script>
+
+ <!-- Test 9 -->
+ <div id="test-9" class="test">
+ <h2>9. Show/Hide Layers</h2>
+ <div class="epoch"></div>
+ <p>
+ <button class="toggle" data-index="0">Toggle A</button>
+ <button class="toggle" data-index="1">Toggle B</button>
+ <button class="toggle" data-index="2">Toggle C</button> |
+ <button class="playback">Play</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 40,
+ nextIndex = length,
+ scale = 0.1,
+ playing = false,
+ interval = null;
+
+ for (var i = 0; i < length; i++) {
+ var x = (i+1) * scale,
+ time = nextTime();
+ data[0].values.push({time: time, y: x});
+ data[1].values.push({time: time, y: x * Math.log(x)});
+ data[2].values.push({time: time, y: x * Math.pow(Math.log(x), 2)});
+ }
+
+ var chart = $('#test-9 .epoch').epoch({
+ type: 'time.line',
+ data: data,
+ axes: ['right', 'bottom']
+ });
+
+ $('#test-9 .toggle').click(function(e) {
+ var index = parseInt($(e.target).attr('data-index'));
+ chart.toggleLayer(index);
+ });
+
+ var pushPoint = function() {
+ var x = (nextIndex +1) * scale,
+ time = nextTime();
+ chart.push([
+ { time: time, y: x},
+ { time: time, y: x * Math.log(x)},
+ { time: time, y: x * Math.pow(Math.log(x), 2)}
+ ]);
+ nextIndex++;
+ };
+
+ $('#test-9 .playback').on('click', function(e) {
+ if (playing) {
+ $(e.target).text('Play');
+ clearInterval(interval);
+ }
+ else {
+ $(e.target).text('Pause');
+ interval = setInterval(pushPoint, 1000);
+ pushPoint();
+ }
+ playing = !playing;
+ });
+ });
+ </script>
+
+ <!-- Test 10 -->
+ <div id="test-10" class="test">
+ <h2>10. Fixed Range</h2>
+ <p>
+ Render a single series plot of <code>y = cos(x)</code>. Instead of automatically setting the range to <code>[-1, 1]</code>, the range is manually set to <code>[-2, 5]</code>.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [{ label: 'A', values: [] }],
+ length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.cos(x),
+ time = nextTime();
+ data[0].values.push({time: time, y: y});
+ }
+
+ $('#test-10 .epoch').epoch({
+ type: 'time.line',
+ axes: ['right', 'bottom'],
+ data: data,
+ range: [-2, 5]
+ });
+ });
+ </script>
+
+ <!-- Test 11 -->
+ <div id="test-11" class="test">
+ <h2>11. Multi-axes</h2>
+ <p>
+ Render a plot that uses independent axes ranges for the left and
+ right sides.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {
+ label: 'A',
+ values: [],
+ range: [-5, 5]
+ },
+ {
+ label: 'B',
+ values: [],
+ range: [0, 100]
+ }
+ ];
+ var length = 40;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length,
+ y = Math.cos(x) + x / 4,
+ y2 = i * 100/40,
+ time = nextTime();
+ data[0].values.push({time: time, y: y});
+ data[1].values.push({time: time, y: y2});
+ }
+
+ $('#test-11 .epoch').epoch({
+ type: 'time.line',
+ axes: ['left', 'right'],
+ data: data,
+ range: {
+ right: [-5, 5],
+ left: [0, 100]
+ }
+ });
+ });
+ </script>
+
+ <!-- Test 12 -->
+ <div id="test-12" class="test">
+ <h2>12. Multi-axes with Labeled Ranges</h2>
+ <p>
+ Render a plot that uses independent axes ranges for the left and
+ right sides that are associated to labels in the chart data.
+ </p>
+ <div class="epoch"></div>
+ </div>
+
+ <script>
+ $(function() {
+ var data = [
+ {
+ label: 'A',
+ values: [],
+ range: 'range-one'
+ },
+ {
+ label: 'B',
+ values: [],
+ range: 'range-two'
+ },
+ {
+ label: 'C',
+ values: [],
+ range: 'range-one'
+ }
+ ];
+ var length = 50;
+
+ for (var i = 0; i < length; i++) {
+ var y = Math.random() * 100;
+ var y2 = Math.random() * 2;
+ var y3 = Math.random() * 50 + 75
+ var time = nextTime();
+ data[0].values.push({time: time, y: y});
+ data[1].values.push({time: time, y: y2});
+ data[2].values.push({time: time, y: y3});
+ }
+
+ $('#test-12 .epoch').epoch({
+ type: 'time.line',
+ axes: ['left', 'right'],
+ data: data,
+ range: {
+ right: 'range-one',
+ left: 'range-two'
+ }
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/debian/missing-sources/epoch/tests/render/real-time/model.html b/debian/missing-sources/epoch/tests/render/real-time/model.html
new file mode 100644
index 0000000..6f53963
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/real-time/model.html
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <script src="../js/data.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+ <style>
+ body { background: #333; color: #d0d0d0; }
+ a:link, a:visited { color: white; color: white; }
+
+ .epoch {
+ height: 220px;
+ }
+
+ #sparkline { height: 50px; }
+
+ </style>
+ </head>
+ <body class="epoch-theme-dark">
+ <h1>Real-time Chart Model / Data Test</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Real-time Chart Model / Data Test</p>
+
+ <p><button class="next">Next</button></p>
+
+ <div id="gauge" class="epoch gauge-small"></div>
+ <div id="sparkline" class="epoch"></div>
+ <div id="area" class="epoch"></div>
+ <div id="bar" class="epoch"></div>
+
+ <script>
+ $(function() {
+ var rnd = function() { return Math.random(); };
+
+ var data = [];
+ for (var j = 0; j < 3; j++) {
+ var layer = [];
+ for (var i = 0; i < 80; i++) {
+ layer.push(rnd());
+ }
+ data.push(layer);
+ }
+
+ // Setup the model
+ window.model = new Epoch.Model({
+ dataFormat: {
+ name: 'array',
+ options: { startTime: (new Date().getTime() / 1000)|0 }
+ }
+ });
+ model.setData(data);
+
+ // Make the charts and associate them with the model
+ window.sparkline = $('#sparkline').epoch({
+ type: 'time.line',
+ axes: ['left', 'right'],
+ model: model
+ });
+
+ window.area = $('#area').epoch({
+ type: 'time.area',
+ axes: ['left', 'right', 'bottom'],
+ model: model
+ });
+
+ window.bar = $('#bar').epoch({
+ type: 'time.bar',
+ axes: ['left', 'right', 'bottom'],
+ model: model
+ });
+
+ window.gauge = $('#gauge').epoch({
+ type: 'time.gauge',
+ model: model
+ })
+
+ $('button.next').click(function(e) {
+ model.push([rnd(), rnd(), rnd()]);
+ });
+ })
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/debian/missing-sources/epoch/tests/render/real-time/options.html b/debian/missing-sources/epoch/tests/render/real-time/options.html
new file mode 100644
index 0000000..a2da792
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/real-time/options.html
@@ -0,0 +1,299 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <script src="../js/data.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+ <style>
+ body { background: #333; color: #d0d0d0; }
+ a:link, a:visited { color: white; color: white; }
+ </style>
+ </head>
+ <body class="epoch-theme-dark">
+ <h1>Real-time Chart Options and Events</h1>
+ <p class="breadcrumbs"><a href="../index.html">Epoch Chart Tests</a> &raquo; Real-time Options and Events</p>
+ <ol>
+ <li><a href="#test-1">Resize</a></li>
+ <li><a href="#test-2">Axes</a></li>
+ <li><a href="#test-3">Ticks</a></li>
+ <li><a href="#test-4">Tick Formats</a></li>
+ <li><a href="#test-5">Margins</a></li>
+ </ol>
+
+ <!-- Test 1 -->
+ <div id="test-1" class="test">
+ <h2>1. Resize</h2>
+ <p>Correctly Resize a Real-time Chart.</p>
+ <div class="epoch"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <button class="size" data-index="0">Size: Small</button>
+ <button class="size" data-index="1">Size: Medium</button>
+ <button class="size" data-index="2">Size: Large</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var step = Math.PI / 30,
+ data = time().add(function(x) { return Math.cos(x) + 1; }),
+ interval = null;
+
+ var sizes = [
+ { width: 400, height: 100 },
+ { width: 800, height: 150 },
+ { width: $('#test-1 .epoch').width(), height: $('#test-1 .epoch').height() }
+ ];
+
+ var chart = $('#test-1 .epoch').epoch({
+ type: 'time.line',
+ data: data.get([0, 2*Math.PI], step)
+ })
+
+ function pushPoint() {
+ chart.push(data.next(step));
+ }
+
+ $('#test-1 .playback').click(function(e) {
+ if (!interval) {
+ interval = setInterval(function() { pushPoint() }, 1000);
+ pushPoint();
+ $('#test-1 .playback').text('Pause');
+ }
+ else {
+ clearInterval(interval);
+ interval = null;
+ $('#test-1 .playback').text('Play');
+ }
+ });
+
+ $('#test-1 .size').click(function(e) {
+ var size = sizes[parseInt($(e.target).attr('data-index'))];
+ chart.option('width', size.width);
+ chart.option('height', size.height);
+ });
+ });
+ </script>
+
+ <!-- Test 2 -->
+ <div id="test-2" class="test">
+ <h2>2. Axes</h2>
+ <div class="epoch"></div>
+ <div class="controls">
+ <button class="playback">Play</button> |
+ <button class="axes" data-index="0">All</button>
+ <button class="axes" data-index="1">[left, right]</button>
+ <button class="axes" data-index="2">[top, bottom]</button>
+ <button class="axes" data-index="3">[left, bottom]</button>
+ <button class="axes" data-index="4">[top, right]</button>
+ <button class="axes" data-index="5">None</button>
+ </div>
+ </div>
+ <script>
+ $(function() {
+ var step = Math.PI / 30,
+ data = time().add(function(x) { return Math.sin(x) + 1; }),
+ interval = null;
+
+ var axes = [
+ ['top', 'left', 'bottom', 'right'],
+ ['left', 'right'],
+ ['top', 'bottom'],
+ ['left', 'bottom'],
+ ['top', 'right'],
+ []
+ ];
+
+ var chart = $('#test-2 .epoch').epoch({
+ type: 'time.line',
+ data: data.get([0, 2*Math.PI], step)
+ })
+
+ function pushPoint() {
+ chart.push(data.next(step));
+ }
+
+ $('#test-2 .playback').click(function(e) {
+ if (!interval) {
+ interval = setInterval(function() { pushPoint() }, 1000);
+ pushPoint();
+ $('#test-2 .playback').text('Pause');
+ }
+ else {
+ clearInterval(interval);
+ interval = null;
+ $('#test-2 .playback').text('Play');
+ }
+ });
+
+ $('#test-2 button.axes').click(function(e) {
+ chart.option('axes', axes[parseInt($(e.target).attr('data-index'))]);
+ });
+ });
+ </script>
+
+ <!-- Test 3 -->
+ <div id="test-3" class="test">
+ <h2>3. Ticks</h2>
+ <div class="epoch"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <button class="ticks" data-index="0">Normal</button>
+ <button class="ticks" data-index="1">Many</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var step = Math.PI / 30,
+ data = time().add(function(x) { return Math.sqrt(x) * Math.sin(x) + 1; }),
+ interval = null;
+
+ var ticks = [
+ {time: 15, left: 5, right: 5},
+ {time: 5, left: 15, right: 15}
+ ];
+
+ var chart = $('#test-3 .epoch').epoch({
+ type: 'time.line',
+ data: data.get([0, 2*Math.PI], step),
+ axes: ['top', 'left', 'bottom', 'right']
+ })
+
+ function pushPoint() {
+ chart.push(data.next(step));
+ }
+
+ $('#test-3 .playback').click(function(e) {
+ if (!interval) {
+ interval = setInterval(function() { pushPoint() }, 1000);
+ pushPoint();
+ $('#test-3 .playback').text('Pause');
+ }
+ else {
+ clearInterval(interval);
+ interval = null;
+ $('#test-3 .playback').text('Play');
+ }
+ });
+
+ $('#test-3 .ticks').click(function(e) {
+ chart.option('ticks', ticks[parseInt($(e.target).attr('data-index'))]);
+ });
+ });
+ </script>
+
+ <!-- Test 4 -->
+ <div id="test-4" class="test">
+ <h2>4. Tick Formats</h2>
+ <div class="epoch"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <button class="tickFormats" data-index="0">Normal</button>
+ <button class="tickFormats" data-index="1">Different</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var step = Math.PI / 30,
+ data = time().add(function(x) { return Math.abs(Math.sin(x)); }),
+ interval = null;
+
+ var tickFormats = [
+ {
+ top: Epoch.Formats.seconds,
+ bottom: Epoch.Formats.seconds,
+ left: Epoch.Formats.si,
+ right: Epoch.Formats.si
+ },
+ {
+ top: Epoch.Formats.si,
+ bottom: Epoch.Formats.si,
+ left: Epoch.Formats.percent,
+ right: Epoch.Formats.percent
+ }
+ ];
+
+ var chart = $('#test-4 .epoch').epoch({
+ type: 'time.area',
+ data: data.get([0, 2*Math.PI], step),
+ axes: ['top', 'left', 'bottom', 'right']
+ })
+
+ function pushPoint() {
+ chart.push(data.next(step));
+ }
+
+ $('#test-4 .playback').click(function(e) {
+ if (!interval) {
+ interval = setInterval(function() { pushPoint() }, 1000);
+ pushPoint();
+ $('#test-4 .playback').text('Pause');
+ }
+ else {
+ clearInterval(interval);
+ interval = null;
+ $('#test-4 .playback').text('Play');
+ }
+ });
+
+ $('#test-4 .tickFormats').click(function(e) {
+ chart.option('tickFormats', tickFormats[parseInt($(e.target).attr('data-index'))]);
+ });
+ });
+ </script>
+
+ <!-- Test 5 -->
+ <div id="test-5" class="test">
+ <h2>5. Margins</h2>
+ <div class="epoch"></div>
+ <p>
+ <button class="playback">Play</button> |
+ <button class="margins" data-index="0">None</button>
+ <button class="margins" data-index="1">Small</button>
+ <button class="margins" data-index="2">Big</button>
+ </p>
+ </div>
+ <script>
+ $(function() {
+ var step = Math.PI / 30,
+ data = time().add(function(x) { return 1 - Math.abs(Math.cos(x)); }),
+ interval = null;
+
+ var margins = [
+ { top: 6, bottom: 6, left: 6, right: 6 },
+ { top: 20, bottom: 20, left: 20, right: 20 },
+ { top: 100, bottom: 50, left: 50, right: 50 }
+ ];
+
+ var chart = $('#test-5 .epoch').epoch({
+ type: 'time.area',
+ data: data.get([0, 2*Math.PI], step),
+ axes: []
+ })
+
+ function pushPoint() {
+ chart.push(data.next(step));
+ }
+
+ $('#test-5 .playback').click(function(e) {
+ if (!interval) {
+ interval = setInterval(function() { pushPoint() }, 1000);
+ pushPoint();
+ $('#test-5 .playback').text('Pause');
+ }
+ else {
+ clearInterval(interval);
+ interval = null;
+ $('#test-5 .playback').text('Play');
+ }
+ });
+
+ $('#test-5 .margins').click(function(e) {
+ chart.option('margins', margins[parseInt($(e.target).attr('data-index'))]);
+ });
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/debian/missing-sources/epoch/tests/render/themes/dark.html b/debian/missing-sources/epoch/tests/render/themes/dark.html
new file mode 100644
index 0000000..265ad93
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/themes/dark.html
@@ -0,0 +1,211 @@
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+ <style>
+ body {
+ background: #303030;
+ color: #d0d0d0;
+ }
+
+ .epoch:after {
+ content:"";
+ display:table;
+ clear:both;
+ }
+
+ .ref {
+ width: 120px;
+ height: 120px;
+ float: left;
+ margin: 2px;
+ color: #303030;
+ text-align: center;
+ line-height: 120px;
+ font-size: 31px;
+ }
+ </style>
+
+ <script>
+ var data = [
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] },
+ { values: [] }
+ ];
+ for (var i = 0; i < 60; i++) {
+ for (j = 0; j < data.length; j++) {
+ data[j].values.push({time: i, y: 0.05*i + 0.5})
+ }
+ }
+ </script>
+ </head>
+ <body class="epoch-theme-dark">
+ <h1>Dark Theme</h1>
+
+ <h2>Category 10</h2>
+ <div class="epoch category10" data-refs-range="1,5"></div>
+ <div class="epoch category10" data-refs-range="6,10"></div>
+
+ <br>
+
+ <div id="bar-10" class="epoch category10" style="height: 300px"></div>
+ <script>
+ $(function() {
+ $('#bar-10').epoch({ type: 'time.bar', axes: ['left', 'right'], data: data.slice(0, 10) });
+ });
+ </script>
+
+
+
+ <h2>Category 20</h2>
+ <div class="epoch category20" data-refs-range="1,4"></div>
+ <div class="epoch category20" data-refs-range="5,8"></div>
+ <div class="epoch category20" data-refs-range="9,12"></div>
+ <div class="epoch category20" data-refs-range="13,16"></div>
+ <div class="epoch category20" data-refs-range="17,20"></div>
+
+ <br>
+
+ <div id="bar-20" class="epoch category20" style="height: 300px"></div>
+ <script>
+ $(function() {
+ $('#bar-20').epoch({ type: 'time.bar', axes: ['left', 'right'], data: data });
+ });
+ </script>
+
+
+ <h2>Category 20b</h2>
+ <div class="epoch category20b" data-refs-range="1,4"></div>
+ <div class="epoch category20b" data-refs-range="5,8"></div>
+ <div class="epoch category20b" data-refs-range="9,12"></div>
+ <div class="epoch category20b" data-refs-range="13,16"></div>
+ <div class="epoch category20b" data-refs-range="17,20"></div>
+
+ <br>
+
+ <div id="bar-20b" class="epoch category20b" style="height: 300px"></div>
+ <script>
+ $(function() {
+ $('#bar-20b').epoch({ type: 'time.bar', axes: ['left', 'right'], data: data });
+ });
+ </script>
+
+
+ <h2>Category 20c</h2>
+ <div class="epoch category20c" data-refs-range="1,4"></div>
+ <div class="epoch category20c" data-refs-range="5,8"></div>
+ <div class="epoch category20c" data-refs-range="9,12"></div>
+ <div class="epoch category20c" data-refs-range="13,16"></div>
+ <div class="epoch category20c" data-refs-range="17,20"></div>
+
+ <br>
+
+ <div id="bar-20c" class="epoch category20c" style="height: 300px"></div>
+ <script>
+ $(function() {
+ $('#bar-20c').epoch({ type: 'time.bar', axes: ['left', 'right'], data: data });
+ });
+ </script>
+
+ <h2>Chart Examples</h2>
+
+ <div class="epoch gauge-medium"></div>
+ <script>
+ $(function() {
+ $('.gauge-medium').epoch({ type: 'time.gauge', value: 0.25 });
+ });
+ </script>
+
+ <div id="pie" class="epoch" style="width: 300px; height: 300px;"></div>
+ <script>
+ $(function() {
+ var data = [],
+ className = 'category10';
+
+ for (var j = 0; j < 10; j++) {
+ data.push({label: String.fromCharCode(65+j), value: 10});
+ }
+
+ $('#pie').epoch({
+ type: 'pie',
+ inner: 80,
+ data: data
+ });
+ });
+ </script>
+
+
+ <div id="bar" class="epoch" style="height: 220px"></div>
+ <script>
+ $(function(){
+ var data = [
+ {label: 'A', values: []},
+ {label: 'B', values: []},
+ {label: 'C', values: []}
+ ],
+ length = 10;
+
+ for (var i = 0; i < length; i++) {
+ var x = i * 10 / length;
+ data[0].values.push({x: x, y: x});
+ data[1].values.push({x: x, y: 2*x});
+ data[2].values.push({x: x, y: 3*x});
+ }
+
+ $('#bar').epoch({
+ type: 'bar',
+ data: data
+ });
+ });
+ </script>
+
+ <div id="line" class="epoch" style="height: 220px"></div>
+ <script>
+ $(function() {
+ var data = [
+ { label: 'A', values: [] },
+ { label: 'B', values: [] }
+ ],
+ length = 128;
+ for (var i = 0; i < length; i++) {
+ var x = i * 2 * Math.PI / length;
+ data[0].values.push({x: x, y: x*Math.sin(x)});
+ data[1].values.push({x: x, y: x*Math.cos(x)});
+ }
+ $('#line').epoch({type: 'line', data: data});
+ });
+ </script>
+
+
+ <script>
+ $(function() {
+ $('div[data-refs-range]').each(function(i, el) {
+ var range = $(el).attr('data-refs-range').split(',');
+ for (var i = parseInt(range[0]); i <= parseInt(range[1]); i++) {
+ $(el).append('<div class="ref category'+i+'">'+i+'</div>')
+ }
+ });
+ });
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/debian/missing-sources/epoch/tests/render/themes/default.html b/debian/missing-sources/epoch/tests/render/themes/default.html
new file mode 100644
index 0000000..9e8bd4e
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/render/themes/default.html
@@ -0,0 +1,70 @@
+<html>
+ <head>
+ <link rel="stylesheet" type="text/css" href="../css/tests.css">
+ <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
+ <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
+ <script src="../../../dist/js/epoch.js"></script>
+ <link rel="stylesheet" type="text/css" href="../../../dist/css/epoch.css">
+ <style>
+
+ .epoch:after {
+ content:"";
+ display:table;
+ clear:both;
+ }
+
+ .ref {
+ width: 120px;
+ height: 120px;
+ float: left;
+ margin: 2px;
+ color: white;
+ text-align: center;
+ line-height: 120px;
+ font-size: 31px;
+ }
+ </style>
+
+ <script>
+ $(function() {
+ $('div[data-refs-range]').each(function(i, el) {
+ var range = $(el).attr('data-refs-range').split(',');
+ for (var i = parseInt(range[0]); i <= parseInt(range[1]); i++) {
+ $(el).append('<div class="ref category'+i+'">'+i+'</div>')
+ }
+ });
+ });
+ </script>
+
+ </head>
+ <body>
+ <h1>Default Theme</h1>
+
+ <h2>Category 10</h2>
+ <div class="epoch category10" data-refs-range="1,5"></div>
+ <div class="epoch category10" data-refs-range="6,10"></div>
+
+ <h2>Category 20</h2>
+ <div class="epoch category20" data-refs-range="1,4"></div>
+ <div class="epoch category20" data-refs-range="5,8"></div>
+ <div class="epoch category20" data-refs-range="9,12"></div>
+ <div class="epoch category20" data-refs-range="13,16"></div>
+ <div class="epoch category20" data-refs-range="17,20"></div>
+
+ <h2>Category 20b</h2>
+ <div class="epoch category20b" data-refs-range="1,4"></div>
+ <div class="epoch category20b" data-refs-range="5,8"></div>
+ <div class="epoch category20b" data-refs-range="9,12"></div>
+ <div class="epoch category20b" data-refs-range="13,16"></div>
+ <div class="epoch category20b" data-refs-range="17,20"></div>
+
+ <h2>Category 20c</h2>
+ <div class="epoch category20c" data-refs-range="1,4"></div>
+ <div class="epoch category20c" data-refs-range="5,8"></div>
+ <div class="epoch category20c" data-refs-range="9,12"></div>
+ <div class="epoch category20c" data-refs-range="13,16"></div>
+ <div class="epoch category20c" data-refs-range="17,20"></div>
+
+
+ </body>
+</html> \ No newline at end of file
diff --git a/debian/missing-sources/epoch/tests/unit/core/charts.coffee b/debian/missing-sources/epoch/tests/unit/core/charts.coffee
new file mode 100644
index 0000000..0f0bb9c
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/charts.coffee
@@ -0,0 +1,573 @@
+sinon = require 'sinon'
+
+describe 'Epoch.Chart', ->
+ [defaultWidth, defaultHeight] = [320, 240]
+
+ describe 'Base', ->
+ [testDivWidth, testDivHeight] = [800, 200]
+ [resizeDivWidth, resizeDivHeight] = [200, 200]
+
+ before (done) ->
+ d3.select(doc.body).append('div').attr('id', 'testDiv').style
+ width: "#{testDivWidth}px"
+ height: "#{testDivHeight}px"
+
+ d3.select(doc.body).append('div').attr('id', 'resizeDiv').style
+ width: "#{resizeDivWidth}px"
+ height: "#{resizeDivHeight}px"
+
+ done()
+
+ after (done) ->
+ d3.select('#testDiv').remove()
+ d3.select('#resizeDiv').remove()
+ done()
+
+ describe 'constructor', ->
+ it 'should set default dimensions', ->
+ c = new Epoch.Chart.Base()
+ assert.equal c.width, defaultWidth, 'Did not set default width'
+ assert.equal c.height, defaultHeight, 'Did not set default height'
+
+ it 'should allow dimensions to be set via options', ->
+ [width, height] = [500, 780]
+ c = new Epoch.Chart.Base({ width: width, height: height })
+ assert.equal c.width, width, "Did not set width to #{width}"
+ assert.equal c.height, height, "Did not set height to #{height}"
+
+ it 'should use the dimensions of the given element when applicable', ->
+ c = new Epoch.Chart.Base({ el: '#testDiv' })
+ assert.equal c.width, testDivWidth, "Did not set width to that of the div"
+ assert.equal c.height, testDivHeight, "Did not set height to that of the div"
+
+ it 'should set default data to an empty array', ->
+ c = new Epoch.Chart.Base()
+ assert.isArray c.data
+ assert.equal c.data.length, 0
+
+ it 'should set data when given as an option', ->
+ data = [
+ {label: 'A', values: [{x: 0, y: 0}]},
+ {label: 'B', values: [{x: 1, y: 1}]}
+ ]
+ c = new Epoch.Chart.Base({ data: data })
+ assert.sameMembers(c.data, data)
+
+ describe 'setData', ->
+ data = [
+ {label: 'A', values: [{x: 10, y: 20}]},
+ {label: 'B', values: [{x: 10, y: 20}]},
+ {label: 'C', values: [{x: 10, y: 20}]}
+ ]
+ classNames = [
+ ['layer', 'category1', 'a'],
+ ['layer', 'category2', 'b'],
+ ['layer', 'category3', 'c']
+ ]
+ chart = null
+
+ before (done) ->
+ (chart = new Epoch.Chart.Base()).setData(data)
+ done()
+
+ it 'should set data correctly', ->
+ assert.sameMembers chart.data, data
+ for i in [0...data.length]
+ assert.equal chart.data[i].label, data[i].label
+ assert.equal chart.data[i].values[0], data[i].values[0]
+
+ it 'should add the correct categories and class names', ->
+ for i in [0...data.length]
+ className = chart.data[i].className
+ for name in classNames[i]
+ assert (className.indexOf(name) > -1), "Missing class '#{name}'"
+
+ describe 'draw', ->
+ it "should trigger the 'draw' event", (done) ->
+ errorCallback = ->
+ assert 'false', "The 'draw' event was never triggered"
+ done()
+ timeout = setTimeout(errorCallback, 1000)
+ chart = new Epoch.Chart.Base()
+ chart.on 'draw', ->
+ clearTimeout(timeout)
+ done()
+ chart.draw()
+
+ describe 'update', ->
+ it 'should call draw by default', (done) ->
+ errorCallback = ->
+ assert false, "update did not call draw by default."
+ done()
+ timeout = setTimeout(errorCallback, 1000)
+ chart = new Epoch.Chart.Base()
+ chart.on 'draw', ->
+ clearTimeout(timeout)
+ done()
+ chart.update([])
+
+ it 'should not call draw when instructed', (done) ->
+ chart = new Epoch.Chart.Base()
+ chart.on 'draw', ->
+ assert false, "Update incorrectly called draw."
+ done()
+ chart.update([], false)
+ done()
+
+ describe 'extent', ->
+ data = [
+ {values: [
+ {x: -1, y: 10},
+ {x: 2, y: 20},
+ {x: 4, y: 50},
+ {x: 8, y: 9900}
+ ]},
+ {values: [
+ {x: 1, y: 170},
+ {x: 7, y: -2380},
+ {x: 19, y: 90},
+ {x: 33, y: 17}
+ ]}
+ ]
+
+ [xMin, xMax] = [-1, 33]
+ [yMin, yMax] = [-2380, 9900]
+
+ chart = null
+
+ before (done) ->
+ chart = new Epoch.Chart.Base({ data: data })
+ done()
+
+ it 'should find the correct extent given a y-comparitor', ->
+ [min, max] = chart.extent (d) -> d.y
+ assert.equal min, yMin, "Incorrect minimum y"
+ assert.equal max, yMax, "Incorrect maximum y"
+
+ it 'should find the correct extent give an x-comparitor', ->
+ [min, max] = chart.extent (d) -> d.x
+ assert.equal min, xMin, "Incorrect minimum x"
+ assert.equal max, xMax, "Incorrect maximum x"
+
+ describe 'option', ->
+ it 'should return all options for the chart when called with no arguments', ->
+ options = { a: 20, b: 30, c: { d: 40 } }
+ chart = new Epoch.Chart.Base options
+ assert.isObject chart.option()
+ assert.deepEqual chart.option(), options
+
+ it 'should return a single value when given a key', ->
+ options = { a: 20, b: 30 }
+ chart = new Epoch.Chart.Base options
+ assert.equal chart.option('a'), options.a
+ assert.equal chart.option('b'), options.b
+ assert.isUndefined chart.option('c')
+
+ it 'should return a deep value when given a hierarchical key', ->
+ options =
+ a:
+ b: 20
+ c:
+ d: 30
+ chart = new Epoch.Chart.Base options
+ assert.equal chart.option('a.b'), options.a.b
+ assert.equal chart.option('a.c.d'), options.a.c.d
+
+ it 'should set an option given a string and a value', ->
+ chart = new Epoch.Chart.Base()
+ [key, value] = ['a', 'hello world']
+ chart.option(key, value)
+ assert.equal chart.option(key), value
+
+ it 'should set a deep value when given a hierarchical key', ->
+ chart = new Epoch.Chart.Base()
+
+ map =
+ 'a.b': 'deep'
+ 'a.c.d': 'deeper'
+ 'b': 'shallow'
+
+ for key, value of map
+ chart.option(key, value)
+ assert.equal chart.option(key), value
+
+ it 'should set all options given an object', ->
+ original = { a: 20, b: { c: 30 } }
+ newOptions = { a: 15, d: { e: 10, f: 30 } }
+ chart = new Epoch.Chart.Base()
+ chart.option(newOptions)
+ assert.deepEqual chart.option(), newOptions
+
+ it 'should trigger an event when an option is changed', (done) ->
+ [key, value] = ['a', 20]
+ eventName = "option:#{key}"
+
+ errorCallback = ->
+ assert false, "Setting an option did not trigger the appropriate event: #{eventName}"
+ done()
+ timeout = setTimeout(errorCallback, 1000)
+
+ chart = new Epoch.Chart.Base()
+ chart.on eventName, ->
+ clearTimeout(timeout)
+ done()
+ chart.option(key, value)
+
+ it 'should resize the containing element when the width option is changed', ->
+ newWidth = resizeDivWidth + 20
+ chart = new Epoch.Chart.Base({ el: '#resizeDiv' })
+ chart.option('width', newWidth)
+ assert.equal d3.select('#resizeDiv').width(), newWidth
+
+ it 'should resize the containing element when the height option is changed', ->
+ newHeight = resizeDivHeight + 20
+ chart = new Epoch.Chart.Base({ el: '#resizeDiv' })
+ chart.option('height', newHeight)
+ assert.equal d3.select('#resizeDiv').height(), newHeight
+
+ describe '_getScaleDomain', ->
+ chart = null
+
+ beforeEach ->
+ chart = new Epoch.Chart.Base
+ data: [ layerWithRange(-2030, 5050) ]
+
+ it 'returns a given array', ->
+ assert.deepEqual(chart._getScaleDomain([0,1]), [0,1])
+
+ it 'returns @options.range if it is an array', ->
+ chart.options.range = [-100, 100]
+ assert.equal chart._getScaleDomain(), chart.options.range
+
+ it 'returns @options.range.left if it is an array', ->
+ chart.options.range = {left: [-100, 100]}
+ assert.equal chart._getScaleDomain(), chart.options.range.left
+
+ it 'returns @options.range.right if it is an array', ->
+ chart.options.range = {right: [-100, 100]}
+ assert.equal chart._getScaleDomain(), chart.options.range.right
+
+ it 'returns the extent of the data', ->
+ assert.deepEqual chart._getScaleDomain(), chart.extent((d) -> d.y)
+
+ describe 'with range grouped layers', ->
+ beforeEach ->
+ chart = new Epoch.Chart.Base
+ data: [
+ layerWithRange(0, 10, 'left'),
+ layerWithRange(-5000, 5000, 'right'),
+ layerWithRange(-10, -5, 'left')
+ ]
+
+ it 'returns the extent of the layers with the given range label', ->
+ assert.deepEqual chart._getScaleDomain('left'), [-10, 10]
+
+ it 'returns the extent of the data if the label is invalid', ->
+ assert.deepEqual chart._getScaleDomain('foobar'), chart.extent((d) -> d.y)
+
+ describe 'layers', ->
+ [chart, eventChart] = [null, null]
+ labels = ['A', 'B', 'C']
+ data = [
+ { label: 'A', data: [{x: 0, y: 0}] },
+ { label: 'B', data: [{x: 1, y: 1}] },
+ { label: 'C', data: [{x: 2, y: 2}] }
+ ]
+ data2 = [
+ { label: 'A', data: [{x: 0, y: 0}] }
+ ]
+
+ before (done) ->
+ chart = new Epoch.Chart.Base
+ el: doc.createElement('div')
+ data: data
+ eventChart = new Epoch.Chart.Base
+ el: doc.createElement('div')
+ data: data2
+ done()
+
+ describe '_findLayer', ->
+ it 'should find layers given a label', ->
+ for label in labels
+ layer = chart._findLayer(label)
+ assert.equal label, layer.label, "Could not find layer with label #{label}"
+
+ it 'should find layers given an index', ->
+ for i in [0...data.length]
+ layer = chart._findLayer(i)
+ assert.equal labels[i], layer.label, "Could not find layer with index #{i}"
+
+ it 'should return null if given an invalid label', ->
+ assert.isNull (chart._findLayer 'D')
+ assert.isNull (chart._findLayer 'not a thing')
+
+ it 'should return null if given an index that is out of bounds', ->
+ assert.isNull (chart._findLayer -1)
+ assert.isNull (chart._findLayer 5)
+
+ describe 'hideLayer', ->
+ it 'should hide a visible layer', ->
+ chart.hideLayer('A')
+ assert.isFalse chart._findLayer('A').visible
+
+ it 'should keep a hidden layer hidden', ->
+ assert.isFalse chart._findLayer('A').visible
+ chart.hideLayer('A')
+ assert.isFalse chart._findLayer('A').visible
+
+ it 'should trigger layer:hidden when a layer is hidden', (done) ->
+ errorCallback = ->
+ assert false, "layer:hidden was not triggered"
+ done()
+ timeout = setTimeout errorCallback, 1000
+ eventChart.on 'layer:hidden', ->
+ clearTimeout timeout
+ done()
+ eventChart.hideLayer('A')
+
+ describe 'showLayer', ->
+ it 'should have keep a visible layer visible', ->
+ assert.isTrue chart._findLayer('B').visible
+ chart.showLayer('B')
+ assert.isTrue chart._findLayer('B').visible
+
+ it 'should make a hidden layer visible', ->
+ assert.isFalse chart._findLayer('A').visible
+ chart.showLayer('A')
+ assert.isTrue chart._findLayer('A').visible
+
+ it 'should trigger layer:shown when a layer is shown', (done) ->
+ errorCallback = ->
+ assert false, "layer:shown was not triggered"
+ done()
+ timeout = setTimeout errorCallback, 1000
+ eventChart.on 'layer:shown', ->
+ clearTimeout timeout
+ done()
+ eventChart.showLayer('A')
+
+ describe 'toggleLayer', ->
+ it 'should hide a visible layer', ->
+ chart.hideLayer('A')
+ chart.toggleLayer('A')
+ assert.isTrue chart._findLayer('A').visible
+
+ it 'should show a hidden layer', ->
+ chart.showLayer('B')
+ chart.toggleLayer('B')
+ assert.isFalse chart._findLayer('B').visible
+
+ describe 'isLayerVisible', ->
+ it 'should report true if a layer is visible', ->
+ chart.showLayer('A')
+ assert.isTrue chart.isLayerVisible('A')
+
+ it 'should report false if a layer is not visible', ->
+ chart.hideLayer('A')
+ assert.isFalse chart.isLayerVisible('B')
+
+ describe 'getVisibleLayers', ->
+ it 'should only return visible layers', ->
+ chart.showLayer('A')
+ chart.showLayer('B')
+ chart.hideLayer('C')
+ visible = chart.getVisibleLayers()
+ assert.equal visible.length, 2
+ assert.equal visible[0].label, 'A'
+ assert.equal visible[1].label, 'B'
+
+ describe 'SVG', ->
+ [containerWidth, containerHeight] = [1000, 280]
+ container = null
+
+ before (done) ->
+ container = doc.createElement('DIV')
+ container.id = 'svg-container'
+ doc.body.appendChild(container)
+ d3.select('#svg-container').style
+ 'width': "#{containerWidth}px"
+ 'height': "#{containerHeight}px"
+ done()
+
+ after (done) ->
+ doc.body.removeChild(container)
+ done()
+
+ describe 'constructor', ->
+ it 'should create a new SVG when not given an element', ->
+ chart = new Epoch.Chart.SVG()
+ assert.ok chart.svg, "SVG not created"
+
+ it 'should set the default width and height of the SVG', ->
+ chart = new Epoch.Chart.SVG()
+ assert.equal chart.svg.attr('width'), defaultWidth, "Default width not set"
+ assert.equal chart.svg.attr('height'), defaultHeight, "Default height not set"
+
+ it 'should set custom dimensions for the SVG via options', ->
+ [customWidth, customHeight] = [500, 600]
+ chart = new Epoch.Chart.SVG({ width: customWidth, height: customHeight })
+ assert.equal chart.svg.attr('width'), customWidth, "Custom width not set"
+ assert.equal chart.svg.attr('height'), customHeight, "Custom height not set"
+
+ it 'should set the container dimensions for the SVG', ->
+ chart = new Epoch.Chart.SVG({ el: '#svg-container' })
+ assert.equal chart.svg.attr('width'), containerWidth
+ assert.equal chart.svg.attr('height'), containerHeight
+
+ describe 'dimensionsChanged', ->
+ [width, height, chart] = [200, 100, null]
+
+ before (done) ->
+ d3.select(doc.body).append('div').attr('id', 'svgResize').style
+ width: width + 'px'
+ height: height + 'px'
+ chart = new Epoch.Chart.SVG { el: '#svgResize' }
+ done()
+
+ after (done) ->
+ d3.select('#svgResize').remove()
+ done()
+
+ it 'should resize the SVG element when the width option is changed', ->
+ newWidth = width + 500
+ chart.option 'width', newWidth
+ assert.equal chart.svg.attr('width'), newWidth
+
+ it 'should resize the SVG element when the height option is changed', ->
+ newHeight = height + 500
+ chart.option 'height', newHeight
+ assert.equal chart.svg.attr('height'), newHeight
+
+ describe 'Canvas', ->
+ [containerWidth, containerHeight] = [1000, 280]
+ container = null
+ container_id = 'canvas-container'
+ containedChart = null
+
+ before (done) ->
+ container = doc.createElement('DIV')
+ container.id = container_id
+ doc.body.appendChild(container)
+ d3.select('#' + container_id).style
+ 'width': "#{containerWidth}px"
+ 'height': "#{containerHeight}px"
+
+ containedChart = new Epoch.Chart.Canvas
+ el: '#' + container_id
+ pixelRatio: 1
+
+ done()
+
+ after (done) ->
+ doc.body.removeChild(container)
+ done()
+
+ describe 'constructor', ->
+ it 'should correctly detect the pixelRatio', ->
+ chart = new Epoch.Chart.Canvas()
+ assert.equal chart.pixelRatio, 2
+
+ it 'should allow the pixelRatio to be explicitly overriden', ->
+ customPixelRatio = 4.2
+ chart = new Epoch.Chart.Canvas({ pixelRatio: customPixelRatio })
+ assert.equal chart.pixelRatio, customPixelRatio
+
+ it 'should create a child canvas', ->
+ chart = new Epoch.Chart.Canvas()
+ assert.ok chart.canvas, "Did not create canvas"
+ assert.equal chart.canvas.node().tagName.toLowerCase(), 'canvas', 'Did not create a canvas node'
+
+ it 'should append the child canvas to the containing element', ->
+ assert.equal containedChart.canvas.node().parentNode.id, container_id
+
+ it 'should set the default dimensions for the canvas', ->
+ chart = new Epoch.Chart.Canvas({ pixelRatio: 1 })
+ assert.equal chart.canvas.attr('width'), defaultWidth
+ assert.equal chart.canvas.attr('height'), defaultHeight
+
+ it 'should allow custom dimensions for the canvas', ->
+ [customWidth, customHeight] = [999, 888]
+ chart = new Epoch.Chart.Canvas
+ width: customWidth
+ height: customHeight
+ pixelRatio: 1
+ assert.equal chart.canvas.attr('width'), customWidth
+ assert.equal chart.canvas.attr('height'), customHeight
+
+ it 'should set container dimensions for the canvas', ->
+ assert.equal containedChart.canvas.attr('width'), containerWidth
+ assert.equal containedChart.canvas.attr('height'), containerHeight
+
+ it 'should fetch a graphics context from the canvas', ->
+ assert.ok containedChart.ctx, "Did not fetch graphics context from canvas"
+
+ it 'should take pixel ratio into account when setting canvas dimension attributes', ->
+ pixelRatio = 3
+ chart = new Epoch.Chart.Canvas({ pixelRatio: pixelRatio })
+ assert.equal chart.canvas.attr('width'), defaultWidth * pixelRatio
+ assert.equal chart.canvas.attr('height'), defaultHeight * pixelRatio
+
+ it 'should not take pixel ratio into account when setting canvas dimension styles', ->
+ chart = new Epoch.Chart.Canvas({ pixelRatio: 2 })
+ assert.equal +chart.canvas.style('width').replace('px', ''), defaultWidth
+ assert.equal +chart.canvas.style('height').replace('px', ''), defaultHeight
+
+ describe 'getWidth', ->
+ it 'should take pixel ratio into account', ->
+ pixelRatio = 2
+ chart = new Epoch.Chart.Canvas({ pixelRatio: pixelRatio })
+ assert.equal chart.getWidth(), pixelRatio * defaultWidth
+
+ describe 'getHeight', ->
+ it 'should take pixel ratio into account', ->
+ pixelRatio = 2
+ chart = new Epoch.Chart.Canvas({ pixelRatio: pixelRatio })
+ assert.equal chart.getHeight(), pixelRatio * defaultHeight
+
+ describe 'dimensionsChanged', ->
+ [width, height, chart, pixelRatio] = [200, 100, null, 2]
+
+ before (done) ->
+ d3.select(doc.body).append('div').attr('id', 'canvasResize').style
+ width: width + 'px'
+ height: height + 'px'
+ chart = new Epoch.Chart.Canvas { el: '#canvasResize', pixelRatio: pixelRatio }
+ done()
+
+ after (done) ->
+ d3.select('#canvasResize').remove()
+ done()
+
+ it 'should resize the canvas element when the width option is changed', ->
+ newWidth = width + 500
+ chart.option 'width', newWidth
+ assert.equal chart.canvas.attr('width'), pixelRatio * newWidth
+ assert.equal chart.canvas.width(), newWidth
+
+ it 'should resize the canvas element when the height option is changed', ->
+ newHeight = height + 500
+ chart.option 'height', newHeight
+ assert.equal chart.canvas.attr('height'), pixelRatio * newHeight
+ assert.equal chart.canvas.height(), newHeight
+
+ describe 'redraw', ->
+ chart = null
+ drawSpy = null
+ purgeSpy = null
+
+ before ->
+ chart = new Epoch.Chart.Canvas()
+
+ beforeEach ->
+ drawSpy = sinon.spy chart, 'draw'
+ purgeSpy = sinon.spy Epoch.QueryCSS, 'purge'
+
+ afterEach ->
+ chart.draw.restore()
+ Epoch.QueryCSS.purge.restore()
+
+ it 'should purge QueryCSS cache and redraw the canvas based chart with new styles', ->
+ chart.redraw()
+
+ assert drawSpy.calledOnce
+ assert purgeSpy.calledOnce
diff --git a/debian/missing-sources/epoch/tests/unit/core/copy.coffee b/debian/missing-sources/epoch/tests/unit/core/copy.coffee
new file mode 100644
index 0000000..2043241
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/copy.coffee
@@ -0,0 +1,47 @@
+describe 'Epoch.Util', ->
+ describe 'copy', ->
+ it 'should correctly create a shallow copy', ->
+ object =
+ a: 20
+ b: 'hello'
+
+ copy = Epoch.Util.copy(object)
+
+ assert.equal copy.a, object.a
+ assert.equal copy.b, object.b
+
+ it 'should not recursively copy objects', ->
+ object =
+ a:
+ foo: 'bar'
+
+ copy = Epoch.Util.copy(object)
+ object.a.foo = 'baz'
+ assert.equal object.a.foo, copy.a.foo
+
+ describe 'defaults', ->
+ it 'should set default values when keys are missing', ->
+ options = {a: 'foo', b: 'bar'}
+ defaults = {c: 'baz'}
+ result = Epoch.Util.defaults(options, defaults)
+ assert.equal result.c, defaults.c
+
+ it 'should not set default values when keys are present', ->
+ options = { a: 'foo', b: 'bar' }
+ defaults = { a: 'wow', b: 'neat' }
+ result = Epoch.Util.defaults(options, defaults)
+ assert.equal result.a, options.a
+ assert.equal result.b, options.b
+
+ it 'should recursively set defaults from sub objects', ->
+ options =
+ a:
+ b: 'foo'
+ defaults =
+ a:
+ b: ''
+ c: 'bar'
+ result = Epoch.Util.defaults(options, defaults)
+
+ assert.equal result.a.b, options.a.b
+ assert.equal result.a.c, defaults.a.c
diff --git a/debian/missing-sources/epoch/tests/unit/core/css.coffee b/debian/missing-sources/epoch/tests/unit/core/css.coffee
new file mode 100644
index 0000000..00cce68
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/css.coffee
@@ -0,0 +1,85 @@
+describe 'Epoch.QueryCSS', ->
+ styleMap =
+ '#container rect':
+ 'fill': 'blue'
+ 'stroke': 'red'
+ 'stroke-width': '5px'
+ '#container rect.a':
+ 'fill': 'green'
+ 'stroke': 'yellow'
+ 'stroke-width': '1px'
+ 'rect#byid':
+ 'fill': 'purple'
+ 'stroke': '#94105A'
+ 'stroke-width': '15px'
+ 'body.alt-color rect#byid':
+ 'fill': '#abcdef1'
+ 'stroke': '#48419A'
+ 'stroke-width': '2em'
+
+ [container, svg, styleTag] = [null, null, null]
+
+ makeStyleSheet = ->
+ cssStatements = []
+ for selector, rules of styleMap
+ cssStatements.push (selector + "{" + ("#{k}: #{v}" for k, v of rules).join(';') + "}")
+ css = cssStatements.join('\n')
+ styleTag = addStyleSheet(css)
+
+ makeContainer = ->
+ container = d3.select(doc.body).append('div')
+ .attr('id', 'container')
+ svg = container.append('svg')
+ .attr('width', 10)
+ .attr('height', 10)
+
+ assertStyles = (object, selector) ->
+ unless object?
+ assert(false, "Object contains no styles")
+
+ unless (mapping = styleMap[selector])?
+ assert(false, "Could not find styles with selector: #{selector}")
+
+ for key, value of mapping
+ assert.equal object[key], value, "Style mismatch on rule '#{key}'"
+
+ before (done) ->
+ makeStyleSheet()
+ makeContainer()
+ done()
+
+ after (done) ->
+ doc.head.removeChild(styleTag)
+ doc.body.removeChild(container.node())
+ done()
+
+ describe 'getStyles', ->
+ it 'should find styles for an svg element', ->
+ styles = Epoch.QueryCSS.getStyles('rect', container)
+ assertStyles styles, '#container rect'
+
+ it 'should find styles using a specific class name', ->
+ styles = Epoch.QueryCSS.getStyles('rect.a', container)
+ assertStyles styles, '#container rect.a'
+
+ it 'should find styles using an id', ->
+ styles = Epoch.QueryCSS.getStyles('rect#byid', container)
+ assertStyles styles, 'rect#byid'
+
+ describe 'purge', ->
+ before (done) ->
+ d3.select(doc.body).attr('class', 'alt-color')
+ done()
+
+ after (done) ->
+ d3.select(doc.body).attr('class', null)
+ done()
+
+ it 'should find cached styles before a purge', ->
+ styles = Epoch.QueryCSS.getStyles('rect#byid', container)
+ assertStyles styles, 'rect#byid'
+
+ it 'should find new styles after purging the cache', ->
+ Epoch.QueryCSS.purge()
+ styles = Epoch.QueryCSS.getStyles('rect#byid', container)
+ assertStyles styles, 'body.alt-color rect#byid'
diff --git a/debian/missing-sources/epoch/tests/unit/core/d3.coffee b/debian/missing-sources/epoch/tests/unit/core/d3.coffee
new file mode 100644
index 0000000..1b65c55
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/d3.coffee
@@ -0,0 +1,40 @@
+describe 'd3.selection', ->
+ [width, height] = [345, 543, null]
+ [element, id] = [null, 'd3-element']
+
+ before (done) ->
+ element = doc.createElement('DIV')
+ element.id = id
+ doc.body.appendChild(element)
+ d3.select('#' + id).style
+ 'width': width + "px"
+ 'height': height + "px"
+ done()
+
+ describe 'width', ->
+ it 'should return the width of an element', ->
+ assert.equal d3.select('#' + id).width(), width
+
+ it 'should set the width of an element given a number', ->
+ widthNumber = 50
+ d3.select('#'+id).width(widthNumber)
+ assert.equal d3.select('#'+id).width(), widthNumber
+
+ it 'should set the width of an element given a css pixel length', ->
+ widthString = '500px'
+ d3.select('#'+id).width(widthString)
+ assert.equal d3.select('#'+id).width(), +widthString.replace('px', '')
+
+ describe 'height', ->
+ it 'should return the height of an element', ->
+ assert.equal d3.select('#' + id).height(), height
+
+ it 'should set the height of an element given a number', ->
+ heightNumber = 75
+ d3.select('#'+id).height(heightNumber)
+ assert.equal d3.select('#'+id).height(), heightNumber
+
+ it 'should set the height of an element given a css pixel length', ->
+ heightString = '343px'
+ d3.select('#'+id).height(heightString)
+ assert.equal d3.select('#'+id).height(), +heightString.replace('px', '')
diff --git a/debian/missing-sources/epoch/tests/unit/core/events.coffee b/debian/missing-sources/epoch/tests/unit/core/events.coffee
new file mode 100644
index 0000000..38d9356
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/events.coffee
@@ -0,0 +1,111 @@
+describe 'Epoch.Events', ->
+ eventsObject = null
+
+ before (done) ->
+ eventsObject = new Epoch.Events()
+ done()
+
+ it 'should execute callbacks when events are triggered', (done) ->
+ errorCallback = ->
+ assert false, 'Event callback never executed'
+ done()
+ timeout = setTimeout errorCallback, 1000
+ eventsObject.on 'event', ->
+ clearTimeout(timeout)
+ done()
+ eventsObject.trigger 'event'
+
+ it 'should not execute callbacks that have been removed', (done) ->
+ errorCallback = ->
+ assert false, 'Event callback still executed'
+ done()
+ eventsObject.on 'example', errorCallback
+ eventsObject.off 'example', errorCallback
+ eventsObject.trigger 'example'
+ done()
+
+ it 'should execute all callbacks associated with an event name', (done) ->
+ total = 4
+
+ errorCallback = ->
+ assert false, 'Not all callbacks were executed'
+ done()
+ timeout = setTimeout errorCallback, 1000
+
+ makeCallback = -> ->
+ total--
+ if total == 0
+ clearTimeout(timeout)
+ done()
+ eventsObject.on('multi', makeCallback()) for i in [0...total]
+ eventsObject.trigger 'multi'
+
+ it 'should remove all callbacks when using .off([String])', (done) ->
+ makeCallback = -> ->
+ assert false, "A callback was still executed"
+ done()
+ eventsObject.on('multi2', makeCallback()) for i in [0...4]
+ eventsObject.off('multi2')
+ eventsObject.trigger('multi2')
+ setTimeout (-> done()), 200
+
+ it 'should execute methods on the object when using .on([String], [String])', (done) ->
+ errorCallback = ->
+ assert false, 'Trigger did not call the appropriate method.'
+ done()
+ timeout = setTimeout(errorCallback, 1000)
+
+ eventsObject.method = ->
+ clearTimeout(timeout)
+ done()
+
+ eventsObject.on 'method-event', 'method'
+ eventsObject.trigger 'method-event'
+
+ it 'should register all events when executing .onAll([Object])', (done) ->
+ errorCallback = ->
+ assert false, 'Not all events were triggered.'
+ done()
+ timeout = setTimeout(errorCallback, 1000)
+
+ eventNames = ['multi:a', 'multi:b', 'multi:c', 'multi:d']
+ total = 0
+
+ eventCallback = ->
+ total += 1
+ if total == eventNames.length
+ clearTimeout(timeout)
+ done()
+
+ eventMap = {}
+ eventMap[name] = eventCallback for name in eventNames
+
+ eventsObject.onAll(eventMap)
+ eventsObject.trigger(name) for name in eventNames
+
+
+ it 'should remove all events when executing .offAll([Array])', ->
+ eventCallback = ->
+ assert false, 'A removed callback was still triggered.'
+
+ eventNames = ['multi-off:a', 'multi-off:b', 'multi-off:c', 'multi-off:d']
+ eventMap = {}
+ eventMap[name] = eventCallback for name in eventNames
+
+ eventsObject.onAll(eventMap)
+ eventsObject.offAll(eventNames)
+ eventsObject.trigger(name) for name in eventNames
+
+
+ it 'should remove specific event callbacks when executing .offAll([Object])', (done) ->
+ makeEventCallback = -> ->
+ assert false, 'A removed callback was still triggered.'
+
+ eventNames = ['multi-off:a', 'multi-off:b', 'multi-off:c', 'multi-off:d']
+ eventMap = {}
+ eventMap[name] = makeEventCallback() for name in eventNames
+
+ eventsObject.onAll(eventMap)
+ eventsObject.offAll(eventMap)
+ eventsObject.trigger(name) for name in eventNames
+ setTimeout (-> done()), 200
diff --git a/debian/missing-sources/epoch/tests/unit/core/format.coffee b/debian/missing-sources/epoch/tests/unit/core/format.coffee
new file mode 100644
index 0000000..a645b49
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/format.coffee
@@ -0,0 +1,68 @@
+describe 'Epoch.Util', ->
+ describe 'formatSI', ->
+ it 'should produce the same number for integers < 1000', ->
+ number = 678
+ assert.equal Epoch.Util.formatSI(number), number
+
+ it 'should only set a fixed decimal for integers when instructed', ->
+ number = 20
+ assert.equal Epoch.Util.formatSI(number), number
+ assert.equal Epoch.Util.formatSI(number, 1, true), "#{number}.0"
+
+ it 'should set the appropriate number of fixed digits', ->
+ number = 3.1415
+ for i in [1..5]
+ match = Epoch.Util.formatSI(number, i).split('.')[1]
+ assert.isNotNull match
+ assert.isString match
+ assert.equal match.length, i
+
+ it 'should set the appropriate postfix based on the number\'s order of magnitude', ->
+ for i, postfix of ['K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y']
+ number = Math.pow(10, ((i|0)+1)*3)
+ assert.equal Epoch.Util.formatSI(number), "1 #{postfix}"
+
+
+ describe 'formatBytes', ->
+ it 'should postfix numbers < 1024 with "B"', ->
+ number = 512
+ assert.equal Epoch.Util.formatBytes(number), "#{number} B"
+
+ it 'should only set a fixed decimal for integers when instructed', ->
+ assert.equal Epoch.Util.formatBytes(128), '128 B'
+ assert.equal Epoch.Util.formatBytes(128, 1, true), '128.0 B'
+ assert.equal Epoch.Util.formatBytes(1024), '1 KB'
+ assert.equal Epoch.Util.formatBytes(1024, 1, true), '1.0 KB'
+
+ it 'should set the appropriate number of fixed digits', ->
+ number = 3.1415
+ for i in [1..5]
+ fixed = Epoch.Util.formatBytes(number, i).replace(/\sB$/, '')
+ assert.isString fixed
+ match = fixed.split('.')[1]
+ assert.isNotNull match
+ assert.equal match.length, i
+
+ it 'should set the appropriate postfix based on the number\'s order of magnitude', ->
+ for i, postfix of ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
+ number = Math.pow(1024, (i|0)+1)
+ regexp = new RegExp(" #{postfix}$")
+ assert.isNotNull Epoch.Util.formatBytes(number).match(regexp)
+
+
+describe 'Epoch.Formats', ->
+ describe 'regular', ->
+ it 'should return what it was given', ->
+ assert.equal Epoch.Formats.regular(10), 10
+ assert.equal Epoch.Formats.regular("hello"), "hello"
+
+ describe 'percent', ->
+ it 'should return a percent given a number', ->
+ assert.equal Epoch.Formats.percent(0.1), '10.0%'
+ assert.equal Epoch.Formats.percent(0.5), '50.0%'
+ assert.equal Epoch.Formats.percent(1), '100.0%'
+ assert.equal Epoch.Formats.percent(23.245), '2324.5%'
+
+ describe 'seconds', ->
+ it 'should return a well formatted date given a timestamp', ->
+ assert.match Epoch.Formats.seconds(1404385979), /\d{2}:\d{2}:\d{2} AM|PM/
diff --git a/debian/missing-sources/epoch/tests/unit/core/is.coffee b/debian/missing-sources/epoch/tests/unit/core/is.coffee
new file mode 100644
index 0000000..af08eb2
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/is.coffee
@@ -0,0 +1,88 @@
+describe 'Epoch.Util', ->
+ describe 'isArray', ->
+ it 'should return true if given an array', ->
+ assert.ok Epoch.isArray([])
+ assert.ok Epoch.isArray([1, 2, 3])
+
+ it 'should return false if not given an array', ->
+ assert.notOk Epoch.isArray(2)
+ assert.notOk Epoch.isArray("hello")
+ assert.notOk Epoch.isArray({})
+
+ describe 'isObject', ->
+ it 'should return true if given an flat object', ->
+ assert.ok Epoch.isObject({})
+
+ it 'should return false if given a number object', ->
+ assert.notOk Epoch.isObject(new Number())
+
+ it 'should return false if given a non-object', ->
+ assert.notOk Epoch.isObject([])
+ assert.notOk Epoch.isObject(2)
+ assert.notOk Epoch.isObject("string")
+
+ describe 'isString', ->
+ it 'should return true if given a string', ->
+ assert.ok Epoch.isString("example")
+ assert.ok Epoch.isString(new String())
+
+ it 'should return false if given a non-string', ->
+ assert.notOk Epoch.isString(2)
+ assert.notOk Epoch.isString([])
+ assert.notOk Epoch.isString({})
+
+ describe 'isFunction', ->
+ it 'should return true if given a function', ->
+ assert.ok Epoch.isFunction(->)
+
+ it 'should return false if given a non-function', ->
+ assert.notOk Epoch.isFunction([])
+ assert.notOk Epoch.isFunction({})
+ assert.notOk Epoch.isFunction(42)
+ assert.notOk Epoch.isFunction("cool")
+
+ describe 'isNumber', ->
+ it 'should return true if given a number', ->
+ assert.ok Epoch.isNumber(new Number())
+
+ it 'should return true if given an integer literal', ->
+ assert.ok Epoch.isNumber(1983)
+
+ it 'should return true if given a floating point literal', ->
+ assert.ok Epoch.isNumber(3.1415)
+
+ it 'should return false if given a non-number', ->
+ assert.notOk Epoch.isNumber(->)
+ assert.notOk Epoch.isNumber([])
+ assert.notOk Epoch.isNumber({})
+ assert.notOk Epoch.isNumber("nan")
+
+ describe 'isElement', ->
+ it 'should return true given an html element', ->
+ p = doc.createElement('P')
+ assert.ok Epoch.isElement(p)
+
+ it 'should return false given a non-element', ->
+ assert.notOk Epoch.isElement(1)
+ assert.notOk Epoch.isElement("1")
+ assert.notOk Epoch.isElement({})
+ assert.notOk Epoch.isElement([])
+ assert.notOk Epoch.isElement(->)
+
+ describe 'isNonEmptyArray', ->
+ it 'should return true given a non-empty array', ->
+ assert.ok Epoch.isNonEmptyArray([1])
+ assert.ok Epoch.isNonEmptyArray([1, 3])
+ assert.ok Epoch.isNonEmptyArray(["foo", 4, "bar"])
+
+ it 'should return false given a non-array', ->
+ assert.notOk Epoch.isNonEmptyArray(2)
+ assert.notOk Epoch.isNonEmptyArray("five")
+ assert.notOk Epoch.isNonEmptyArray({})
+ assert.notOk Epoch.isNonEmptyArray(->)
+
+ it 'should return false given a null value', ->
+ assert.notOk Epoch.isNonEmptyArray(null)
+
+ it 'should return false given an empty array', ->
+ assert.notOk Epoch.isNonEmptyArray([])
diff --git a/debian/missing-sources/epoch/tests/unit/core/util.coffee b/debian/missing-sources/epoch/tests/unit/core/util.coffee
new file mode 100644
index 0000000..e02280c
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/core/util.coffee
@@ -0,0 +1,92 @@
+describe 'Epoch.Util', ->
+ describe 'trim', ->
+ it 'should return null unless given a string', ->
+ assert.isNotNull Epoch.Util.trim('test string')
+ assert.isNull Epoch.Util.trim(34)
+
+ it 'should trim leading and trailing whitespace', ->
+ assert.equal Epoch.Util.trim("\t\n\r indeed \n\t\t\r"), 'indeed'
+
+ it 'should leave inner whitespace', ->
+ assert.equal Epoch.Util.trim('Hello world'), 'Hello world'
+
+ describe 'dasherize', ->
+ it 'should dasherize regular strings', ->
+ assert.equal Epoch.Util.dasherize('Hello World'), 'hello-world'
+
+ it 'should trim leading and trailing whitespace before dasherizing', ->
+ assert.equal Epoch.Util.dasherize(' Airieee is KewL '), 'airieee-is-kewl'
+
+ describe 'domain', ->
+ testLayers = [
+ { values: [{x: 'A', y: 10}, {x: 'B', y: 20}, {x: 'C', y: 40}] }
+ ]
+
+ testLayers2 = [
+ { values: [{x: 'A', y: 10}, {x: 'B', y: 20}, {x: 'C', y: 40}] },
+ { values: [{x: 'D', y: 15}, {x: 'E', y: 30}, {x: 'F', y: 90}] }
+ ]
+
+ it 'should find the correct domain of a set of keys and values', ->
+ xDomain = Epoch.Util.domain(testLayers, 'x')
+ assert.sameMembers xDomain, ['A', 'B', 'C']
+ yDomain = Epoch.Util.domain(testLayers, 'y')
+ assert.sameMembers yDomain, [10, 20, 40]
+
+ it 'should find all the values across multiple layers', ->
+ xDomain = Epoch.Util.domain(testLayers2, 'x')
+ assert.sameMembers xDomain, ['A', 'B', 'C', 'D', 'E', 'F']
+ yDomain = Epoch.Util.domain(testLayers2, 'y')
+ assert.sameMembers yDomain, [10, 20, 40, 15, 30, 90]
+
+ describe 'toRGBA', ->
+ it 'should produce the correct rgba style when given an rgba color style', ->
+ assert.equal Epoch.Util.toRGBA('rgba(1, 2, 3, 0.4)', 0.1), 'rgba(1,2,3,0.1)'
+
+ it 'should produce the correct rgba style when given any rgb color style', ->
+ assert.equal Epoch.Util.toRGBA('black', 0.25), 'rgba(0,0,0,0.25)'
+ assert.equal Epoch.Util.toRGBA('#FF0000', 0.9), 'rgba(255,0,0,0.9)'
+ assert.equal Epoch.Util.toRGBA('rgb(10, 20, 40)', 0.99), 'rgba(10,20,40,0.99)'
+
+ describe 'getComputedStyle', ->
+ overrideStyles =
+ 'width': '320px'
+ 'height': '240px'
+ 'background-color': 'blue'
+
+ [style, div] = [null, null]
+
+ before (done) ->
+ style = addStyleSheet('#get-style-div { padding-left: 30px; background: green }')
+ div = doc.createElement('div')
+ div.id = 'get-style-div'
+ doc.body.appendChild(div)
+ d3.select('#get-style-div').style(overrideStyles)
+ done()
+
+ after (done) ->
+ doc.body.removeChild(div)
+ doc.head.removeChild(style)
+ done()
+
+ it 'should find <style> styles', ->
+ styles = Epoch.Util.getComputedStyle(div)
+ assert.equal styles['padding-left'], '30px'
+
+ it 'should find overriden styles', ->
+ styles = Epoch.Util.getComputedStyle(div)
+ for k, v of overrideStyles
+ assert.equal styles[k], v, "ComputedStyles['#{k}'] should be '#{v}'"
+
+ describe 'flatten', ->
+ it 'should flatten a given multi-array', ->
+ multiarray = [[1, 2], 3, [4, 5, 6, [7]]]
+ expected = [1, 2, 3, 4, 5, 6, [7]]
+ assert.deepEqual Epoch.Util.flatten(multiarray), expected
+
+ it 'should throw if given a non-array', ->
+ assert.throws (-> Epoch.Util.flatten null), /only accepts arrays/
+ assert.throws (-> Epoch.Util.flatten 1), /only accepts arrays/
+ assert.throws (-> Epoch.Util.flatten {}), /only accepts arrays/
+ assert.throws (-> Epoch.Util.flatten 'hellooo'), /only accepts arrays/
+ assert.throws (-> Epoch.Util.flatten new Error()), /only accepts arrays/
diff --git a/debian/missing-sources/epoch/tests/unit/data/array_format.coffee b/debian/missing-sources/epoch/tests/unit/data/array_format.coffee
new file mode 100644
index 0000000..a043a1e
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/data/array_format.coffee
@@ -0,0 +1,106 @@
+describe 'Epoch.Data.Format.array', ->
+ startTime = 1000
+
+ it 'should format flat arrays', ->
+ expected = [ {values: [{x: 0, y: 1}, {x: 1, y: 2}, {x: 2, y: 3}]} ]
+ assert.data expected, Epoch.Data.Format.array([1, 2, 3])
+
+ it 'should format multi-dimensional arrays', ->
+ expected = [
+ { values: [{x: 0, y: 1}, {x: 1, y: 2}]},
+ { values: [{x: 0, y: 3}, {x: 1, y: 4}]}
+ ]
+ assert.data expected, Epoch.Data.Format.array([[1, 2], [3, 4]])
+
+ it 'should respect the x option', ->
+ expected = [{values: [{x: 1, y: 1}, {x: 2, y: 2}]}]
+ result = Epoch.Data.Format.array [1, 2], {x: (d, i) -> i+1}
+ assert.data expected, result
+
+ it 'should respect the y option', ->
+ expected = [{values: [{x: 0, y: 2}, {x: 1, y: 4}]}]
+ result = Epoch.Data.Format.array [1, 2], {y: (d) -> d*2}
+ assert.data expected, result
+
+ it 'should format pie chart data with flat arrays', ->
+ input = [20, 30, 40]
+ expected = ({value: v} for v in input)
+ result = Epoch.Data.Format.array input, {type: 'pie'}
+ assert.equal expected.length, result.length, "Result did not have the expected number of layers"
+ for i in [0...expected.length]
+ assert.equal expected[i].value, result[i].value, "Result #{i} did not have the epected value"
+
+ it 'should not format pie chart data with multi-dimensional arrays', ->
+ assert.equal Epoch.Data.Format.array([[1], [2]], {type: 'pie'}).length, 0
+
+ it 'should format real-time plot data with flat arrays', ->
+ input = [1, 2, 3]
+ expected = [{ values: ({time: startTime+parseInt(i), y: v} for i,v of input) }]
+ result = Epoch.Data.Format.array(input, {type: 'time.line', startTime: startTime})
+ assert.timeData expected, result
+
+ it 'should format real-time plot data with multi-dimensional arrays', ->
+ input = [[1, 2], [3, 4]]
+ expected = []
+ for layer in input
+ expected.push {values: ({time: startTime+parseInt(i), y: v} for i, v of layer)}
+ result = Epoch.Data.Format.array(input, {type: 'time.line', startTime: startTime})
+ assert.timeData expected, result
+
+ it 'should format heatmap data with flat arrays', ->
+ input = [{'1': 1, '2': 2}, {'3': 3, '4': 4}]
+ expected = [{values: ({time: startTime+parseInt(i), histogram: h} for i, h of input)}]
+ result = Epoch.Data.Format.array(input, {type: 'time.heatmap', startTime: startTime})
+ assert.data expected, result, ['time', 'heatmap']
+
+ it 'should format heatmap data with multi-dimensional arrays', ->
+ input = [
+ [{'1': 1, '2': 2}, {'3': 3, '4': 4}],
+ [{'5': 5, '6': 6}, {'7': 7, '8': 8}]
+ ]
+ expected = [
+ { values: ({time: startTime+parseInt(i), histogram: h} for i, h of input[0]) },
+ { values: ({time: startTime+parseInt(i), histogram: h} for i, h of input[1]) },
+ ]
+ result = Epoch.Data.Format.array(input, {type: 'time.heatmap', startTime: startTime})
+ assert.data expected, result, ['time', 'heatmap']
+
+ it 'should correctly apply labels if the labels option is present', ->
+ labels = ['alpha', 'beta']
+ result = Epoch.Data.Format.array [[1], [2]], {labels: labels}
+ for i in [0...labels.length]
+ assert.equal labels[i], result[i].label
+
+ it 'should correctly apply labels if the autoLabels option is set', ->
+ labels = ['A', 'B', 'C']
+ result = Epoch.Data.Format.array [[1], [2], [3]], {autoLabels: true}
+ for i in [0...labels.length]
+ assert.equal labels[i], result[i].label
+
+ it 'should prefer the labels option to the autoLabels option if both are set', ->
+ labels = ['alpha', 'beta']
+ result = Epoch.Data.Format.array [[1], [2]], {labels: labels, autoLabels: true}
+ for i in [0...labels.length]
+ assert.equal labels[i], result[i].label
+
+ it 'should produce single series entries correctly', ->
+ result = Epoch.Data.Format.array.entry(2)
+ assert.isArray result
+ assert.equal 1, result.length
+ assert.isObject result[0]
+ assert.equal 0, result[0].x
+ assert.equal 2, result[0].y
+
+ it 'should produce multi-series entries correctly', ->
+ expected = [
+ { x: 0, y: 1 },
+ { x: 0, y: 2 },
+ { x: 0, y: 3 }
+ ]
+ result = Epoch.Data.Format.array.entry([1, 2, 3])
+ assert.isArray result
+ assert.equal 3, result.length
+ for i in [0...expected.length]
+ assert.isObject result[i]
+ assert.equal expected[i].x, result[i].x
+ assert.equal expected[i].y, result[i].y
diff --git a/debian/missing-sources/epoch/tests/unit/data/chart.coffee b/debian/missing-sources/epoch/tests/unit/data/chart.coffee
new file mode 100644
index 0000000..ed115a1
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/data/chart.coffee
@@ -0,0 +1,121 @@
+
+describe 'Epoch.Chart.options', ->
+ it 'should set the type option to "area" for basic area charts', ->
+ assert.equal new Epoch.Chart.Area().options.type, 'area'
+
+ it 'should set the type option to "bar" for basic bar charts', ->
+ assert.equal new Epoch.Chart.Bar().options.type, 'bar'
+
+ it 'should set the type option to "histogram" for basic histogram charts', ->
+ assert.equal new Epoch.Chart.Histogram().options.type, 'histogram'
+
+ it 'should set the type option to "line" for basic line charts', ->
+ assert.equal new Epoch.Chart.Line().options.type, 'line'
+
+ it 'should set the type option to "pie" for basic pie charts', ->
+ assert.equal new Epoch.Chart.Pie().options.type, 'pie'
+
+ it 'should set the type option to "scatter" for basic scatter charts', ->
+ assert.equal new Epoch.Chart.Scatter().options.type, 'scatter'
+
+ it 'should set the type option to "time.area" for real-time area charts', ->
+ assert.equal new Epoch.Time.Area().options.type, 'time.area'
+
+ it 'should set the type option to "time.bar" for real-time bar charts', ->
+ assert.equal new Epoch.Time.Bar().options.type, 'time.bar'
+
+ it 'should set the type option to "time.gauge" for real-time gauge charts', ->
+ assert.equal new Epoch.Time.Gauge().options.type, 'time.gauge'
+
+ it 'should set the type option to "time.heatmap" for real-time heatmap charts', ->
+ assert.equal new Epoch.Time.Heatmap().options.type, 'time.heatmap'
+
+ it 'should set the type option to "time.line" for real-time line charts', ->
+ assert.equal new Epoch.Time.Line().options.type, 'time.line'
+
+describe 'Epoch.Chart._formatData', ->
+ assertBasicData = (klassName, type) ->
+ data = [1, 2, 3, 4]
+ expected = Epoch.data 'array', data, {type: type}
+ chart = new Epoch.Chart[klassName]
+ data: data
+ dataFormat: 'array'
+ assert.data expected, chart.data
+
+ assertTimeData = (klassName, type) ->
+ data = [1, 2, 3, 4]
+ expected = Epoch.data 'array', data, {type: type, time: (d, i) -> parseInt(i)}
+ chart = new Epoch.Time[klassName]
+ data: data
+ dataFormat:
+ name: 'array'
+ options: { time: (d, i) -> parseInt(i) }
+ assert.timeData expected, chart.data
+
+ it 'should correctly detect and format array type data', ->
+ data = [1, 2, 3]
+ expected = Epoch.data 'array', data
+ chart = new Epoch.Chart.Base
+ data: data
+ dataFormat: 'array'
+ assert.data expected, chart.data
+
+ it 'should correctly detect and format tuple type data', ->
+ data = [[1, 1], [2, 4], [3, 78]]
+ expected = Epoch.data 'tuple', data
+ chart = new Epoch.Chart.Base
+ data: data
+ dataFormat: 'tuple'
+ assert.data expected, chart.data
+
+ it 'should correctly detect and format keyvalue type data', ->
+ data = [ {a: 20, b: 30, x: 10}, {a: 40, b: 50, x: 20} ]
+ expected = Epoch.data 'keyvalue', data, ['a', 'b'], { x: (d) -> d.x }
+ chart = new Epoch.Chart.Base
+ data: data
+ dataFormat:
+ name: 'keyvalue'
+ arguments: [['a', 'b']]
+ options: { x: (d, i) -> d.x }
+ assert.data expected, chart.data
+
+ it 'should correctly format area chart data', ->
+ assertBasicData 'Area', 'area'
+
+ it 'should correctly format bar chart data', ->
+ assertBasicData 'Bar', 'bar'
+
+ it 'should correctly format line data', ->
+ assertBasicData 'Line', 'line'
+
+ it 'should correctly format scatter data', ->
+ assertBasicData 'Scatter', 'scatter'
+
+ it 'should correctly format pie data', ->
+ data = [1, 2, 3]
+ expected = data.map (d) -> {value: d}
+ result = (new Epoch.Chart.Pie(data: data, dataFormat: 'array')).data
+ for i in [0...expected.length]
+ assert.equal expected[i].value, result[i].value
+
+ it 'should correctly format histogram data', ->
+ data = (parseInt(Math.random() * 100) for i in [0...100])
+ format = Epoch.data('array', data, { type: 'histogram' })
+ expected = (new Epoch.Chart.Histogram())._prepareData(format)
+ chart = new Epoch.Chart.Histogram({ data: data, dataFormat: 'array' })
+ assert.data expected, chart.data
+
+ it 'should correctly format real-time area data', ->
+ assertTimeData 'Area', 'time.area'
+
+ it 'should correctly format real-time bar data', ->
+ assertTimeData 'Bar', 'time.bar'
+
+ it 'should correctly format real-time heatmap data', ->
+ assertTimeData 'Heatmap', 'time.heatmap'
+
+ it 'should correctly format real-time line data', ->
+ assertTimeData 'Line', 'time.line'
+
+
+
diff --git a/debian/missing-sources/epoch/tests/unit/data/keyvalue_format.coffee b/debian/missing-sources/epoch/tests/unit/data/keyvalue_format.coffee
new file mode 100644
index 0000000..1ac5fcc
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/data/keyvalue_format.coffee
@@ -0,0 +1,101 @@
+describe 'Epoch.Data.Format.keyvalue', ->
+
+ data = [
+ { x: 1, a: 20, b: 30, c: 40, hist: 10, time: 0 },
+ { x: 2, a: 45, b: 83, c: 8, hist: 11, time: 1 },
+ { x: 3, a: 17, b: 72, c: 54, hist: 12, time: 2 },
+ { x: 4, a: 99, b: 19, c: 39, hist: 13, time: 3 }
+ ]
+
+ it 'should format a single series for basic plots', ->
+ expected = [{ values: (data.map (d, i) -> { x: parseInt(i), y: d.a }) }]
+ result = Epoch.Data.Format.keyvalue(data, ['a'])
+ assert.data expected, result
+
+ it 'should format multiple series for basic plots', ->
+ expected = [
+ { values: (data.map (d, i) -> {x: parseInt(i), y: d.a }) },
+ { values: (data.map (d, i) -> {x: parseInt(i), y: d.b }) },
+ { values: (data.map (d, i) -> {x: parseInt(i), y: d.c }) }
+ ]
+ result = Epoch.Data.Format.keyvalue(data, ['a', 'b', 'c'])
+ assert.data expected, result
+
+ it 'should format a single series for real-time plots', ->
+ expected = [
+ { values: (data.map (d, i) -> { time: d.time, y: d.a }) }
+ ]
+ result = Epoch.Data.Format.keyvalue(data, ['a'], { type: 'time.line', time: (d) -> d.time })
+ assert.data expected, result
+
+ it 'should format multiple series for real-time plots', ->
+ expected = [
+ { values: (data.map (d, i) -> { time: d.time, y: d.a }) }
+ { values: (data.map (d, i) -> { time: d.time, y: d.b }) }
+ { values: (data.map (d, i) -> { time: d.time, y: d.c }) }
+ ]
+ result = Epoch.Data.Format.keyvalue(data, ['a', 'b', 'c'], { type: 'time.line', time: (d) -> d.time })
+ assert.data expected, result
+
+ it 'should correctly format heatmap data', ->
+ expected = [
+ { values: (data.map (d, i) -> {time: d.time, histogram: d.hist }) }
+ ]
+ result = Epoch.Data.Format.keyvalue(data, ['hist'], {type: 'time.heatmap', time: ((d) -> d.time) })
+ assert.data expected, result
+
+ it 'should return an empty set for type time.gauge and type pie', ->
+ assert.equal Epoch.Data.Format.keyvalue(data, ['a'], {type: 'pie'}).length, 0
+ assert.equal Epoch.Data.Format.keyvalue(data, ['a'], {type: 'time.gauge'}).length, 0
+
+ it 'should respect the x option', ->
+ expected = [{ values: (data.map (d, i) -> {x: d.x, y: d.a }) }]
+ result = Epoch.Data.Format.keyvalue(data, ['a'], {x: (d) -> d.x})
+ assert.data expected, result
+
+ it 'should respect the y option', ->
+ expected = [{ values: (data.map (d, i) -> {x: parseInt(i), y: d.a + 2 }) }]
+ result = Epoch.Data.Format.keyvalue(data, ['a'], {y: (d) -> d + 2})
+ assert.data expected, result
+
+ it 'should apply key name labels by default', ->
+ labels = ['a', 'b', 'c', 'hist']
+ layers = Epoch.Data.Format.keyvalue(data, ['a', 'b', 'c', 'hist'])
+ for i in [0...labels.length]
+ assert.equal labels[i], layers[i].label
+
+ it 'should override key name labels with given labels', ->
+ labels = ['x', 'y', 'z']
+ layers = Epoch.Data.Format.keyvalue(data, ['a', 'b', 'c'], {labels: labels})
+ for i in [0...labels.length]
+ assert.equal labels[i], layers[i].label
+
+ it 'should apply automatic labels only when labels are not given and key labels are off', ->
+ labels = ['A', 'B']
+ layers = Epoch.Data.Format.keyvalue(data, ['a', 'b'], {keyLabels: false, autoLabels: true})
+ for i in [0...labels.length]
+ assert.equal labels[i], layers[i].label
+
+ it 'should produce single series entries correctly', ->
+ input = data[0]
+ keys = ['a']
+ expected = [{x: 0, y: input.a}]
+ result = Epoch.Data.Format.keyvalue.entry(input, keys)
+ assert.isArray result
+ assert.equal 1, result.length
+ assert.isObject result[0]
+ assert.equal 0, result[0].x
+ assert.equal input.a, result[0].y
+
+ it 'should produce multi-series entries correctly', ->
+ input = data[1]
+ keys = ['a', 'b', 'c']
+ options = {x: 'x'}
+ expected = ({x: input.x, y: input[key]} for key in keys)
+ result = Epoch.Data.Format.keyvalue.entry(input, keys, options)
+ assert.isArray result
+ assert.equal expected.length, result.length
+ for i in [0...expected.length]
+ assert.isObject result[i]
+ assert.equal expected[i].x, result[i].x
+ assert.equal expected[i].y, result[i].y
diff --git a/debian/missing-sources/epoch/tests/unit/data/tuple_format.coffee b/debian/missing-sources/epoch/tests/unit/data/tuple_format.coffee
new file mode 100644
index 0000000..a55f559
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/data/tuple_format.coffee
@@ -0,0 +1,76 @@
+describe 'Epoch.Data.Format.tuple', ->
+ it 'should format flat tuple arrays', ->
+ input = [[1, 2], [3, 4], [5, 6]]
+ expected = [{values: input.map((d) -> {x: d[0], y: d[1]})}]
+ result = Epoch.Data.Format.tuple(input)
+ assert.data expected, result
+
+ it 'should format nested layers of tuple arrays', ->
+ input = [
+ [ [1, 2], [3, 4] ],
+ [ [5, 6], [7, 8] ]
+ ]
+ expected = input.map (series) ->
+ {values: series.map((d) -> {x: d[0], y: d[1]})}
+ result = Epoch.Data.Format.tuple(input)
+ assert.data expected, result
+
+ it 'should respect the x option', ->
+ input = [[1, 2], [3, 4], [5, 6]]
+ expected = [{values: input.map((d, i) -> {x: i, y: d[1]})}]
+ result = Epoch.Data.Format.tuple(input, {x: (d, i) -> i})
+ assert.data expected, result
+
+ it 'should respect the y option', ->
+ input = [[1, 2], [3, 4], [5, 6]]
+ expected = [{values: input.map((d, i) -> {x: d[0], y: i})}]
+ result = Epoch.Data.Format.tuple(input, {y: (d, i) -> i})
+ assert.data expected, result
+
+ it 'should format flat tuples of real-time data', ->
+ input = [[1, 2], [3, 4], [5, 6]]
+ expected = [{values: input.map((d) -> {time: d[0], y: d[1]})}]
+ result = Epoch.Data.Format.tuple(input, {type: 'time.line'})
+ assert.data expected, result
+
+ it 'should format nested layers of real-time tuple data', ->
+ input = [
+ [ [1, 2], [3, 4] ],
+ [ [5, 6], [7, 8] ]
+ ]
+ expected = input.map (series) ->
+ {values: series.map((d) -> {time: d[0], y: d[1]})}
+ result = Epoch.Data.Format.tuple(input, {type: 'time.line'})
+ assert.data expected, result
+
+ it 'should respect the time option', ->
+ input = [[1, 2], [3, 4], [5, 6]]
+ expected = [{values: input.map((d, i) -> {time: i, y: d[1]})}]
+ result = Epoch.Data.Format.tuple(input, {type: 'time.line', time: (d, i) -> i})
+ assert.data expected, result
+
+ it 'should ignore heatmap, pie, and gauge charts', ->
+ input = [[1, 2], [3, 4], [5, 6]]
+ assert.equal 0, Epoch.Data.Format.tuple(input, {type: 'time.heatmap'}).length
+ assert.equal 0, Epoch.Data.Format.tuple(input, {type: 'time.gauge'}).length
+ assert.equal 0, Epoch.Data.Format.tuple(input, {type: 'pie'}).length
+
+ it 'should produce single series entries correctly', ->
+ input = [5, 6]
+ result = Epoch.Data.Format.tuple.entry(input)
+ assert.isArray result
+ assert.equal 1, result.length
+ assert.isObject result[0]
+ assert.equal input[0], result[0].x
+ assert.equal input[1], result[0].y
+
+ it 'should produce multi-series entries correctly', ->
+ input = [[5, -10], [4, 8], [2, 3]]
+ expected = ({x: d[0], y: d[1]} for d in input)
+ result = Epoch.Data.Format.tuple.entry(input)
+ assert.isArray result
+ assert.equal expected.length, result.length
+ for i in [0...expected.length]
+ assert.isObject result[i]
+ assert.equal expected[i].x, result[i].x
+ assert.equal expected[i].y, result[i].y
diff --git a/debian/missing-sources/epoch/tests/unit/init.coffee b/debian/missing-sources/epoch/tests/unit/init.coffee
new file mode 100644
index 0000000..aa8edd2
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/init.coffee
@@ -0,0 +1,55 @@
+process.env.TZ = "America/Los_Angeles"
+
+jsdom = require('jsdom')
+global.assert = require('chai').assert
+url = require('url')
+
+html = "<html><head></head><body></body></html>"
+
+exec = require('child_process').exec
+exec 'pwd', (err, out) -> console.log out
+
+before (done) ->
+ jsdom.env
+ html: html
+ scripts: ["http://d3js.org/d3.v3.min.js", "./dist/js/epoch.js"]
+ done: (errors, window) ->
+ global.Epoch = window.Epoch
+ # Override get context to use a test context by default
+ global.Epoch.Util.getContext = -> new window.Epoch.TestContext()
+ global.d3 = window.d3
+ global.doc = window.document
+ # Set this to "retina" so we can test canvas based charts
+ window.devicePixelRatio = 2
+ done()
+
+global.addStyleSheet = (css) ->
+ head = doc.head
+ style = doc.createElement('style')
+ style.type = 'text/css'
+ style.appendChild(doc.createTextNode(css))
+ head.appendChild(style)
+ style
+
+global.layerWithRange = (min, max, range) ->
+ layer = { values: [{time: 0, y: min}, {time: 1, y: max}] }
+ layer.range = range if range?
+ layer
+
+#
+# Helper assertion methods for data format testing
+#
+assert.data = (expected, result, checkAttributes) ->
+ checkAttributes ?= ['x', 'y']
+ assert.equal expected.length, result.length
+ for i, layer of expected
+ resultLayer = result[i]
+ msg = "Result layer #{i} does not have expected number of values."
+ assert.equal layer.values.length, resultLayer.values.length, msg
+ for j in [0...layer.values.length]
+ for k in checkAttributes
+ msg = "Layer #{i} data point #{j} does not have the expected value for key #{k}"
+ assert.equal layer.values[j][k], resultLayer.values[j][k], msg
+
+assert.timeData = (expected, result) ->
+ assert.data(expected, result, ['time', 'y'])
diff --git a/debian/missing-sources/epoch/tests/unit/time.coffee b/debian/missing-sources/epoch/tests/unit/time.coffee
new file mode 100644
index 0000000..48593a2
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/time.coffee
@@ -0,0 +1,67 @@
+sinon = require 'sinon'
+
+describe 'Epoch.Time.Plot', ->
+ chart = null
+
+ beforeEach ->
+ chart = new Epoch.Time.Plot(data: [layerWithRange(0, 100)])
+
+ describe 'y', ->
+ scaleDomain = [-524, 2324]
+ beforeEach -> sinon.stub(chart, '_getScaleDomain').returns(scaleDomain)
+ afterEach -> chart._getScaleDomain.restore()
+
+ it 'should get the scale domain from the given domain', ->
+ y = chart.y('a')
+ assert.ok chart._getScaleDomain.calledWith('a')
+ assert.deepEqual y.domain(), scaleDomain
+
+ describe 'ySvg', ->
+ scaleDomain = [3004, 10000000]
+ beforeEach -> sinon.stub(chart, '_getScaleDomain').returns(scaleDomain)
+ afterEach -> chart._getScaleDomain.restore()
+
+ it 'should get the scale domain from the given domain', ->
+ y = chart.ySvg('a')
+ assert.ok chart._getScaleDomain.calledWith('a')
+ assert.deepEqual y.domain(), scaleDomain
+
+ describe 'ySvgLeft', ->
+ beforeEach -> sinon.spy(chart, 'ySvg')
+ afterEach -> chart.ySvg.restore()
+
+ it 'should use the left range when present', ->
+ chart.options.range = { left: 'apples' }
+ chart.ySvgLeft()
+ assert.ok chart.ySvg.calledWith('apples')
+
+ it 'should not use the left range when missing', ->
+ chart.ySvgLeft()
+ assert.ok chart.ySvg.calledOnce
+
+ describe 'ySvgRight', ->
+ beforeEach -> sinon.spy(chart, 'ySvg')
+ afterEach -> chart.ySvg.restore()
+
+ it 'should use the right range when present', ->
+ chart.options.range = { right: 'oranges' }
+ chart.ySvgRight()
+ assert.ok chart.ySvg.calledWith('oranges')
+
+ it 'should not use the right range when missing', ->
+ chart.ySvgRight()
+ assert.ok chart.ySvg.calledOnce
+
+ describe 'leftAxis', ->
+ beforeEach -> sinon.spy chart, 'ySvgLeft'
+ afterEach -> chart.ySvgLeft.restore()
+ it 'uses the left svg scale', ->
+ chart.leftAxis()
+ assert.ok chart.ySvgLeft.calledOnce
+
+ describe 'rightAxis', ->
+ beforeEach -> sinon.spy chart, 'ySvgRight'
+ afterEach -> chart.ySvgRight.restore()
+ it 'uses the right svg scale', ->
+ chart.rightAxis()
+ assert.ok chart.ySvgRight.calledOnce
diff --git a/debian/missing-sources/epoch/tests/unit/time/line.coffee b/debian/missing-sources/epoch/tests/unit/time/line.coffee
new file mode 100644
index 0000000..fa6c205
--- /dev/null
+++ b/debian/missing-sources/epoch/tests/unit/time/line.coffee
@@ -0,0 +1,15 @@
+sinon = require 'sinon'
+
+describe 'Epoch.Time.Line', ->
+ chart = null
+ beforeEach ->
+ chart = new Epoch.Time.Line
+ data: [{ range: 'foo', values: [{time: 0, y: 10}, {time: 1, y: 30}] }]
+
+ describe 'draw', ->
+ beforeEach -> sinon.spy chart, 'y'
+ afterEach -> chart.y.restore()
+
+ it 'should provide the layer\'s range to the y scale', ->
+ chart.draw()
+ assert.ok chart.y.calledWith('foo')