Compare commits
No commits in common. "gh-pages" and "master" have entirely different histories.
69
README.md
Normal file
69
README.md
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
Timeline.js
|
||||||
|
===========
|
||||||
|
|
||||||
|
|
||||||
|
Timeline.js is a lightweight JS library to plot graphs using Timeline. As it uses Timeline, you can add event listeners on the plotted graph very easily.
|
||||||
|
|
||||||
|
I coded it because I couldn't find any basic JS library to do this, without any external dependencies and extra features. Timeline.js is only 13k once minified, and can be reduced under 10k with obfuscation. Better results may be obtained with a little refactor, but that's enough for me. Plus it can be very easily customised to fit your needs.
|
||||||
|
|
||||||
|
## Live demos
|
||||||
|
|
||||||
|
* [Single graph example](http://phyks.github.io/timeline.js/examples/index.html)
|
||||||
|
* [Multi graph example](http://phyks.github.io/timeline.js/examples/index2.html)
|
||||||
|
* [Rounded graph example](http://phyks.github.io/timeline.js/examples/index3.html)
|
||||||
|
* [Dashed graph example](http://phyks.github.io/timeline.js/examples/index4.html)
|
||||||
|
* [Line only graph example](http://phyks.github.io/timeline.js/examples/index5.html)
|
||||||
|
* [Graph with legend example](http://phyks.github.io/timeline.js/examples/index6.html)
|
||||||
|
* [Interactivity with points example](http://phyks.github.io/timeline.js/examples/index7.html)
|
||||||
|
* [Multiple holders example](http://phyks.github.io/timeline.js/examples/index8.html)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
(See examples for more info. For live examples, see http://phyks.github.io/timeline.js/)
|
||||||
|
|
||||||
|
|
||||||
|
First, you must include the `timeline.js` or `timeline.min.js` script.
|
||||||
|
|
||||||
|
Then, you need to init a Timeline object, using something like `var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'rounded': false, 'x_callback': false});`. The arguments are all optional and are:
|
||||||
|
* `id` : the id of the parent element that will contain the Timeline
|
||||||
|
* `width` / `height` : width and height of the created Timeline
|
||||||
|
* `grid` : none / small / big / both to choose which type of grid you want
|
||||||
|
* `x_axis` : true / false to show / hide the x axis
|
||||||
|
* `line` : none / line / dashed to choose line type. You can edit the dasharray by replacing `Timeline.dash_style` value
|
||||||
|
* `fill` : true / false to fill the area below the graph or not
|
||||||
|
* `rounded` : true / false to use splines to smoothen the graph or not
|
||||||
|
* `x_callback` : callback function to call to get texts for the x legend. Not yet implemented
|
||||||
|
|
||||||
|
_Note :_ One Timeline object corresponds to one holder.
|
||||||
|
|
||||||
|
Then, you can add as many graphs as you want, with `tl.addGraph(NAME, COLOR);` where COLOR must be a valid CSS color.
|
||||||
|
And you can add points using `tl.addPoints(GRAPH_NAME, POINTS);`. Points is an array of point objects, which are of the type `{'x': ABSCISSA, 'y': ORDINATE, 'label': LABEL}`. LABEL is the text to display in the infobox when the mouse is over the point. You can use '%x' and '%y' in labels and they will be automatically replaced by the coordinates. You can also use `<sup>` and `<sub>` HTML tags. You can add another (optional) element `click` which must be a ffunction to bind to onclick event on this point.
|
||||||
|
|
||||||
|
_Note_ : You don't have to sort the points inside a same list of points in a tl.addGraph call. They will be sorted for you. But, if you call tl.addPoints multiple times, you must sort the points yourself between each call. The script won't do it for you and it will result in weird graphs if you don't do it.
|
||||||
|
|
||||||
|
Finally, you can draw the timeline with `tl.draw();`.
|
||||||
|
|
||||||
|
## Other functions
|
||||||
|
|
||||||
|
* `tl.clearGraph(GRAPH);` to delete the data for the graph GRAPH, or for all graphs + the graphs definition if GRAPH is not specified.
|
||||||
|
* `tl.hasGraph(GRAPH);` to check if a graph with name GRAPH has already been defined or not.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
```
|
||||||
|
* --------------------------------------------------------------------------------
|
||||||
|
* "THE NO-ALCOHOL BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* Phyks (webmaster@phyks.me) wrote this file. As long as you retain this notice you
|
||||||
|
* can do whatever you want with this stuff (and you can also do whatever you want
|
||||||
|
* with this stuff without retaining it, but that's not cool...). If we meet some
|
||||||
|
* day, and you think this stuff is worth it, you can buy me a <del>beer</del> soda
|
||||||
|
* in return.
|
||||||
|
* Phyks
|
||||||
|
* ---------------------------------------------------------------------------------
|
||||||
|
```
|
||||||
|
|
||||||
|
## Known bugs / TODO
|
||||||
|
|
||||||
|
Feel free to contribute !
|
||||||
|
|
||||||
|
* Y axis is not implemented, but could be implemented easily
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body onload="">
|
<body onload="">
|
||||||
<div id="holder"></div>
|
<div id="holder"></div>
|
||||||
<script type="text/javascript" src="../javascripts/timeline.min.js"></script>
|
<script type="text/javascript" src="../timeline.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'line', 'rounded': false, 'fill': true, 'x_callback': false});
|
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'line', 'rounded': false, 'fill': true, 'x_callback': false});
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body onload="">
|
<body onload="">
|
||||||
<div id="holder"></div>
|
<div id="holder"></div>
|
||||||
<script type="text/javascript" src="../javascripts/timeline.min.js"></script>
|
<script type="text/javascript" src="../timeline.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'line', 'rounded': false, 'fill': true, 'x_callback': false});
|
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'line', 'rounded': false, 'fill': true, 'x_callback': false});
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body onload="">
|
<body onload="">
|
||||||
<div id="holder"></div>
|
<div id="holder"></div>
|
||||||
<script type="text/javascript" src="../javascripts/timeline.min.js"></script>
|
<script type="text/javascript" src="../timeline.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'line', 'rounded': true, 'fill': true, 'x_callback': false});
|
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'line', 'rounded': true, 'fill': true, 'x_callback': false});
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body onload="">
|
<body onload="">
|
||||||
<div id="holder"></div>
|
<div id="holder"></div>
|
||||||
<script type="text/javascript" src="../javascripts/timeline.min.js"></script>
|
<script type="text/javascript" src="../timeline.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'dashed', 'rounded': false, 'fill': true, 'x_callback': false});
|
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'dashed', 'rounded': false, 'fill': true, 'x_callback': false});
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body onload="">
|
<body onload="">
|
||||||
<div id="holder"></div>
|
<div id="holder"></div>
|
||||||
<script type="text/javascript" src="../javascripts/timeline.min.js"></script>
|
<script type="text/javascript" src="../timeline.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'none', 'rounded': false, 'fill': false, 'x_callback': false});
|
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'none', 'rounded': false, 'fill': false, 'x_callback': false});
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body onload="">
|
<body onload="">
|
||||||
<div id="holder"></div>
|
<div id="holder"></div>
|
||||||
<script type="text/javascript" src="../javascripts/timeline.min.js"></script>
|
<script type="text/javascript" src="../timeline.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'none', 'rounded': false, 'fill': false, 'x_callback': function(x) { return x;}});
|
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'none', 'rounded': false, 'fill': false, 'x_callback': function(x) { return x;}});
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body onload="">
|
<body onload="">
|
||||||
<div id="holder"></div>
|
<div id="holder"></div>
|
||||||
<script type="text/javascript" src="../javascripts/timeline.min.js"></script>
|
<script type="text/javascript" src="../timeline.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'none', 'rounded': false, 'fill': false, 'x_callback': false});
|
var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'none', 'rounded': false, 'fill': false, 'x_callback': false});
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
<body onload="">
|
<body onload="">
|
||||||
<div id="holder1"></div>
|
<div id="holder1"></div>
|
||||||
<div id="holder2"></div>
|
<div id="holder2"></div>
|
||||||
<script type="text/javascript" src="../javascripts/timeline.min.js"></script>
|
<script type="text/javascript" src="../timeline.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
t1 = new Timeline({'id': 'holder1', 'height': '40%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'line', 'rounded': false, 'fill': true, 'x_callback': false});
|
t1 = new Timeline({'id': 'holder1', 'height': '40%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'line': 'line', 'rounded': false, 'fill': true, 'x_callback': false});
|
||||||
|
|
||||||
|
124
index.html
124
index.html
@ -1,124 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="chrome=1">
|
|
||||||
<title>Timeline.js by Phyks</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="stylesheets/styles.css">
|
|
||||||
<link rel="stylesheet" href="stylesheets/pygment_trac.css">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
|
||||||
<!--[if lt IE 9]>
|
|
||||||
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
||||||
<![endif]-->
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="wrapper">
|
|
||||||
<header>
|
|
||||||
<h1>Timeline.js</h1>
|
|
||||||
<p>A lightweight javascript library to plot simple graphs.</p>
|
|
||||||
|
|
||||||
<p class="view"><a href="https://github.com/Phyks/timeline.js">View the Project on GitHub <small>Phyks/timeline.js</small></a></p>
|
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://github.com/Phyks/timeline.js/zipball/master">Download <strong>ZIP File</strong></a></li>
|
|
||||||
<li><a href="https://github.com/Phyks/timeline.js/tarball/master">Download <strong>TAR Ball</strong></a></li>
|
|
||||||
<li><a href="https://github.com/Phyks/timeline.js">View On <strong>GitHub</strong></a></li>
|
|
||||||
</ul>
|
|
||||||
</header>
|
|
||||||
<section>
|
|
||||||
<h1>
|
|
||||||
<a name="timelinejs" class="anchor" href="#timelinejs"><span class="octicon octicon-link"></span></a>Timeline.js</h1>
|
|
||||||
|
|
||||||
<p>Timeline.js is a lightweight JS library to plot graphs using Timeline. As it uses Timeline, you can add event listeners on the plotted graph very easily.</p>
|
|
||||||
|
|
||||||
<p>I coded it because I couldn't find any basic JS library to do this, without any external dependencies and extra features. Timeline.js is only 13k once minified, and can be reduced under 10k with obfuscation. Better results may be obtained with a little refactor, but that's enough for me. Plus it can be very easily customised to fit your needs.</p>
|
|
||||||
|
|
||||||
<h2>
|
|
||||||
<a name="live-demos" class="anchor" href="#live-demos"><span class="octicon octicon-link"></span></a>Live demos</h2>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li><a href="http://phyks.github.io/timeline.js/examples/index.html">Single graph example</a></li>
|
|
||||||
<li><a href="http://phyks.github.io/timeline.js/examples/index2.html">Multi graph example</a></li>
|
|
||||||
<li><a href="http://phyks.github.io/timeline.js/examples/index3.html">Rounded graph example</a></li>
|
|
||||||
<li><a href="http://phyks.github.io/timeline.js/examples/index4.html">Dashed graph example</a></li>
|
|
||||||
<li><a href="http://phyks.github.io/timeline.js/examples/index5.html">Line only graph example</a></li>
|
|
||||||
<li><a href="http://phyks.github.io/timeline.js/examples/index6.html">Graph with legend example</a></li>
|
|
||||||
<li><a href="http://phyks.github.io/timeline.js/examples/index7.html">Interactivity with points example</a></li>
|
|
||||||
<li><a href="http://phyks.github.io/timeline.js/examples/index8.html">Multiple holders example</a></li>
|
|
||||||
</ul><h2>
|
|
||||||
<a name="usage" class="anchor" href="#usage"><span class="octicon octicon-link"></span></a>Usage</h2>
|
|
||||||
|
|
||||||
<p>(See examples for more info. For live examples, see <a href="http://phyks.github.io/timeline.js/">http://phyks.github.io/timeline.js/</a>)</p>
|
|
||||||
|
|
||||||
<p>First, you must include the <code>timeline.js</code> or <code>timeline.min.js</code> script.</p>
|
|
||||||
|
|
||||||
<p>Then, you need to init a Timeline object, using something like <code>var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'rounded': false, 'x_callback': false});</code>. The arguments are all optional and are:</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<code>id</code> : the id of the parent element that will contain the Timeline</li>
|
|
||||||
<li>
|
|
||||||
<code>width</code> / <code>height</code> : width and height of the created Timeline</li>
|
|
||||||
<li>
|
|
||||||
<code>grid</code> : none / small / big / both to choose which type of grid you want</li>
|
|
||||||
<li>
|
|
||||||
<code>x_axis</code> : true / false to show / hide the x axis</li>
|
|
||||||
<li>
|
|
||||||
<code>line</code> : none / line / dashed to choose line type. You can edit the dasharray by replacing <code>Timeline.dash_style</code> value</li>
|
|
||||||
<li>
|
|
||||||
<code>fill</code> : true / false to fill the area below the graph or not</li>
|
|
||||||
<li>
|
|
||||||
<code>rounded</code> : true / false to use splines to smoothen the graph or not</li>
|
|
||||||
<li>
|
|
||||||
<code>x_callback</code> : callback function to call to get texts for the x legend. Not yet implemented</li>
|
|
||||||
</ul><p><em>Note :</em> One Timeline object corresponds to one holder.</p>
|
|
||||||
|
|
||||||
<p>Then, you can add as many graphs as you want, with <code>tl.addGraph(NAME, COLOR);</code> where COLOR must be a valid CSS color.
|
|
||||||
And you can add points using <code>tl.addPoints(GRAPH_NAME, POINTS);</code>. Points is an array of point objects, which are of the type <code>{'x': ABSCISSA, 'y': ORDINATE, 'label': LABEL}</code>. LABEL is the text to display in the infobox when the mouse is over the point. You can use '%x' and '%y' in labels and they will be automatically replaced by the coordinates. You can also use <code><sup></code> and <code><sub></code> HTML tags. You can add another (optional) element <code>click</code> which must be a ffunction to bind to onclick event on this point.</p>
|
|
||||||
|
|
||||||
<p><em>Note</em> : You don't have to sort the points inside a same list of points in a tl.addGraph call. They will be sorted for you. But, if you call tl.addPoints multiple times, you must sort the points yourself between each call. The script won't do it for you and it will result in weird graphs if you don't do it.</p>
|
|
||||||
|
|
||||||
<p>Finally, you can draw the timeline with <code>tl.draw();</code>.</p>
|
|
||||||
|
|
||||||
<h2>
|
|
||||||
<a name="other-functions" class="anchor" href="#other-functions"><span class="octicon octicon-link"></span></a>Other functions</h2>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<code>tl.clearGraph(GRAPH);</code> to delete the data for the graph GRAPH, or for all graphs + the graphs definition if GRAPH is not specified.</li>
|
|
||||||
<li>
|
|
||||||
<code>tl.hasGraph(GRAPH);</code> to check if a graph with name GRAPH has already been defined or not.</li>
|
|
||||||
</ul><h2>
|
|
||||||
<a name="license" class="anchor" href="#license"><span class="octicon octicon-link"></span></a>License</h2>
|
|
||||||
|
|
||||||
<pre><code>* --------------------------------------------------------------------------------
|
|
||||||
* "THE NO-ALCOHOL BEER-WARE LICENSE" (Revision 42):
|
|
||||||
* Phyks (webmaster@phyks.me) wrote this file. As long as you retain this notice you
|
|
||||||
* can do whatever you want with this stuff (and you can also do whatever you want
|
|
||||||
* with this stuff without retaining it, but that's not cool...). If we meet some
|
|
||||||
* day, and you think this stuff is worth it, you can buy me a <del>beer</del> soda
|
|
||||||
* in return.
|
|
||||||
* Phyks
|
|
||||||
* ---------------------------------------------------------------------------------
|
|
||||||
</code></pre>
|
|
||||||
|
|
||||||
<h2>
|
|
||||||
<a name="known-bugs--todo" class="anchor" href="#known-bugs--todo"><span class="octicon octicon-link"></span></a>Known bugs / TODO</h2>
|
|
||||||
|
|
||||||
<p>Feel free to contribute !</p>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
<li>Y axis is not implemented, but could be implemented easily</li>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
<footer>
|
|
||||||
<p>This project is maintained by <a href="https://github.com/Phyks">Phyks</a></p>
|
|
||||||
<p><small>Hosted on GitHub Pages — Theme by <a href="https://github.com/orderedlist">orderedlist</a></small></p>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
<script src="javascripts/scale.fix.js"></script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,17 +0,0 @@
|
|||||||
var metas = document.getElementsByTagName('meta');
|
|
||||||
var i;
|
|
||||||
if (navigator.userAgent.match(/iPhone/i)) {
|
|
||||||
for (i=0; i<metas.length; i++) {
|
|
||||||
if (metas[i].name == "viewport") {
|
|
||||||
metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
document.addEventListener("gesturestart", gestureStart, false);
|
|
||||||
}
|
|
||||||
function gestureStart() {
|
|
||||||
for (i=0; i<metas.length; i++) {
|
|
||||||
if (metas[i].name == "viewport") {
|
|
||||||
metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
29
javascripts/timeline.min.js
vendored
29
javascripts/timeline.min.js
vendored
@ -1,29 +0,0 @@
|
|||||||
function Timeline(g){this.ns="http://www.w3.org/2000/svg";this.xlinkns="http://www.w3.org/1999/xlink";this.marginBottom=10;this.marginTop=15;this.marginRight=this.marginLeft=10;this.x_axis=this.rounded=!1;this.fill=!0;this.line="line";this.dashed_style="5, 5";this.axis=this.g=this.holder=this.parent_holder=!1;this.graphs=[];this.raw_points=[];this.x_callback=!1;var e=window.onresize||function(){},f=this;window.onresize=function(){e();!1!==f.g&&(f.g.setAttribute("transform","translate(0, "+f.parent_holder.offsetHeight+
|
|
||||||
") scale(1, -1)"),!0===f.x_axis&&f.axis.setAttribute("x2",f.parent_holder.offsetWidth-f.marginLeft-3-f.marginRight),[].forEach.call(f.holder.querySelectorAll(".label, .over, .point, .line, .graph, .legend_x"),function(a){a.parentNode.removeChild(a)}),f.draw())};document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1")||alert("ERROR : Your browser does not support embedded SVG.");this.parent_holder=document.getElementById(g.id);this.parent_holder.style.width=g.width;this.parent_holder.style.height=
|
|
||||||
g.height;var a=this.createElement("svg:svg",{width:"100%",height:"100%"});a.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink",this.xlinkns);this.parent_holder.appendChild(a);this.holder=this.parent_holder.querySelector("svg");defs=this.createElement("defs",{});this.holder.appendChild(defs);if("small"===g.grid||"both"===g.grid){var a=this.createElement("pattern",{id:"smallGrid",width:8,height:8,patternUnits:"userSpaceOnUse"}),c=this.createElement("path",{d:"M 8 0 L 0 0 0 8",fill:"none",
|
|
||||||
stroke:"gray","stroke-width":"0.5"});a.appendChild(c);defs.appendChild(a)}if("big"===g.grid||"both"===g.grid)a=this.createElement("pattern",{id:"grid",width:80,height:80,patternUnits:"userSpaceOnUse"}),"both"===g.grid&&(c=this.createElement("rect",{width:80,height:80,fill:"url(#smallGrid)"}),a.appendChild(c)),c=this.createElement("path",{d:"M 80 0 L 0 0 0 80",fill:"none",stroke:"gray","stroke-width":"1"}),a.appendChild(c),defs.appendChild(a);this.grid=g.grid;a=this.createElement("marker",{id:"markerArrow",
|
|
||||||
markerWidth:13,markerHeight:13,refX:2,refY:6,orient:"auto"});c=this.createElement("path",{d:"M2,2 L2,11 L10,6 L2,2",fill:"gray"});a.appendChild(c);defs.appendChild(a);this.g=this.createElement("g",{transform:"translate(0, "+this.parent_holder.offsetHeight+") scale(1, -1)"});this.holder.appendChild(this.g);!0===g.x_axis&&(this.axis=this.createElement("line",{x1:this.marginLeft,y1:this.parent_holder.offsetHeight/2+1.5,x2:this.parent_holder.offsetWidth-13-this.marginRight,y2:this.parent_holder.offsetHeight/
|
|
||||||
2+1.5,stroke:"gray","stroke-width":3,"marker-end":'url("#markerArrow")'}),this.g.appendChild(this.axis));"none"!==this.grid&&(a=this.createElement("rect",{width:"100%",height:"100%"}),"big"===this.grid||"both"===this.grid?a.setAttribute("fill","url(#grid)"):a.setAttribute("fill","url(#smallGrid)"),this.g.appendChild(a));this.rounded=g.rounded;this.x_axis=g.x_axis;this.line=g.line;this.fill=g.fill;this.x_callback=g.x_callback}
|
|
||||||
Timeline.prototype.createElement=function(g,e){var f=document.createElementNS(this.ns,g);for(attr in e)f.setAttribute(attr,e[attr]);return f};Timeline.prototype.hasClass=function(g,e){return-1<(" "+g.getAttribute("class")+" ").indexOf(" "+e+" ")};Timeline.prototype.addGraph=function(g,e){this.graphs[g]=e};Timeline.prototype.hasGraph=function(g){return"undefined"===typeof this.graphs[g]?!1:!0};
|
|
||||||
Timeline.prototype.clearGraph=function(g){if("undefined"===typeof g)this.raw_points=[],this.graphs=[];else for(var e=0;e<this.raw_points.length;e++)this.raw_points[e].graph===g&&(this.raw_points[e]=void 0)};
|
|
||||||
Timeline.prototype.addPoints=function(g,e){for(var f=0;f<e.length;f++){var a={graph:g,x:e[f].x,y:e[f].y};a.label="undefined"!==typeof e[f].label?e[f].label:"";a.click="undefined"!==typeof e[f].click?e[f].click:!1;this.raw_points.push(a)}this.raw_points.sort(function(a,e){return a.x<e.x?-1:a.x==e.x?0:1})};Timeline.prototype.newCoordinate=function(g,e,f,a,c){return(c-a)/(f-e)*(g-e)+a};
|
|
||||||
Timeline.prototype.getNewXY=function(g,e,f,a){var c=this;return function(k,b){return{x:c.newCoordinate(k,g,e,c.marginLeft,c.parent_holder.offsetWidth-c.marginRight),y:c.newCoordinate(b,f,a,2*c.marginBottom,c.parent_holder.offsetHeight-c.marginTop)}}};
|
|
||||||
Timeline.prototype.getControlPoints=function(g){var e=[],f=[],a=g.length-1,c=[],k=[],b=[],l=[];c[0]=0;k[0]=2;b[0]=1;l[0]=g[0]+2*g[1];for(var d=1;d<a-1;d++)c[d]=1,k[d]=4,b[d]=1,l[d]=4*g[d]+2*g[d+1];c[a-1]=2;k[a-1]=7;b[a-1]=0;l[a-1]=8*g[a-1]+g[a];for(var h,d=1;d<a;d++)h=c[d]/k[d-1],k[d]-=h*b[d-1],l[d]-=h*l[d-1];e[a-1]=l[a-1]/k[a-1];for(d=a-2;0<=d;--d)e[d]=(l[d]-b[d]*e[d+1])/k[d];for(d=0;d<a-1;d++)f[d]=2*g[d+1]-e[d+1];f[a-1]=0.5*(g[a]+e[a-1]);return{p1:e,p2:f}};
|
|
||||||
Timeline.prototype.scale=function(g){var e=!0;for(graph in g){e=!1;break}if(e)return!1;for(var e=!1,f=0,a=!1,c=!1,k=0;k<g.length;k++){if(g[k].x<e||!1===e)e=g[k].x;if(g[k].x>a||!1===a)a=g[k].x;g[k].y<f&&(f=g[k].y);if(g[k].y>c||!1===c)c=g[k].y}g=this.getNewXY(e,a,f,c);var b=g(Math.pow(10,Math.floor(Math.log(a-e)/Math.log(10))),Math.pow(10,Math.floor(Math.log(c-f)/Math.log(10)))),l=g(0,0),k=b.x-l.x,b=b.y-l.y;if("big"===this.grid||"both"===this.grid){l=this.holder.getElementById("grid");l.setAttribute("width",
|
|
||||||
k);l.setAttribute("height",b);var d=g(Math.floor(e/Math.pow(10,Math.floor(Math.log(a-e)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(a-e)/Math.log(10))),Math.floor(f/Math.pow(10,Math.floor(Math.log(c-f)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(c-f)/Math.log(10))));l.setAttribute("y",d.y);l.setAttribute("x",d.x);l.querySelector("path").setAttribute("d","M "+k+" 0 L 0 0 0 "+b);"both"===this.grid&&(l.querySelector("rect").setAttribute("width",k),l.querySelector("rect").setAttribute("height",
|
|
||||||
b))}if("small"===this.grid||"both"===this.grid)k/=10,b/=10,l=this.holder.getElementById("smallGrid"),l.setAttribute("width",k),l.setAttribute("height",b),"small"===this.grid&&(e=g(Math.floor(e/Math.pow(10,Math.floor(Math.log(a-e)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(a-e)/Math.log(10))),Math.floor(f/Math.pow(10,Math.floor(Math.log(c-f)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(c-f)/Math.log(10)))),l.setAttribute("y",e.y),l.setAttribute("x",e.x)),l.querySelector("path").setAttribute("d",
|
|
||||||
"M "+k+" 0 L 0 0 0 "+b);!0===this.x_axis&&(y=g(0,0).y,this.axis.setAttribute("y1",y),this.axis.setAttribute("y2",y));return g};
|
|
||||||
Timeline.prototype.draw=function(){for(var g=this.scale(this.raw_points),e=[],f,a,c,k=this,b=0;b<this.raw_points.length;b++)f=g(this.raw_points[b].x,this.raw_points[b].y),e.push({id:b,x:f.x,y:f.y,graph:this.raw_points[b].graph,click:this.raw_points[b].click,label:this.raw_points[b].label});for(var l in this.graphs){var d=e.filter(function(a){return a.graph==l});f="";if(!0===this.rounded){a=[];c=[];for(b=0;b<d.length;b++)a.push(d[b].x),c.push(d[b].y);a=this.getControlPoints(a);c=this.getControlPoints(c);
|
|
||||||
for(b=0;b<d.length-1;b++)f+="C "+a.p1[b]+" "+c.p1[b]+" "+a.p2[b]+" "+c.p2[b]+" "+d[b+1].x+" "+d[b+1].y+" "}else for(b=1;b<d.length;b++)f+="L "+d[b].x+" "+d[b].y+" ";"none"!==this.line&&0!==d.length&&(a=this.createElement("path",{"class":"line",stroke:this.graphs[l],"stroke-width":2,fill:"none",d:"M "+d[0].x+" "+d[0].y+" "+f}),"dashed"===this.line&&a.setAttribute("style","stroke-dasharray: "+this.dashed_style),this.g.appendChild(a));this.fill&&(a=this.createElement("path",{"class":"graph",fill:this.graphs[l],
|
|
||||||
opacity:"0.25",stroke:"none",d:"M "+d[0].x+" "+2*this.marginBottom+" L "+d[0].x+" "+d[0].y+" "+f+" L "+d[d.length-1].x+" "+2*this.marginBottom+" Z"}),this.g.insertBefore(a,this.g.querySelectorAll(".over")[0]))}for(b=f=0;b<e.length;){a=this.createElement("rect",{"class":"over",id:"over_"+b,y:0,fill:"white",opacity:0,height:"100%"});c=[b];d=b+1;if(b<e.length-1)for(;e[d].x==e[b].x&&!(h>e.length);)d++;for(var h=f+1;h<d;h++)c.push(h);0==b?a.setAttribute("x",0):a.setAttribute("x",(e[b].x+e[f].x)/2);b==
|
|
||||||
e.length-1?a.setAttribute("width",this.parent_holder.offsetWidth-(e[b].x+e[b-1].x)/2+1):0==b?a.setAttribute("width",(e[1].x+e[0].x)/2+this.marginLeft+1):a.setAttribute("width",(e[d].x-e[f].x)/2+1);this.g.appendChild(a);a.addEventListener("mouseover",function(a){return function(){for(var b=0;b<a.length;b++)k.holder.getElementById("point_"+a[b]).setAttribute("r","6"),k.holder.getElementById("label_"+a[b]).setAttribute("display","block")}}(c));a.addEventListener("mouseout",function(){[].forEach.call(k.holder.querySelectorAll(".point"),
|
|
||||||
function(a){a.setAttribute("r","4")});[].forEach.call(k.holder.querySelectorAll(".label"),function(a){a.setAttribute("display","none")})});this.holder.addEventListener("mouseout",function(){[].forEach.call(k.holder.querySelectorAll(".point"),function(a){a.setAttribute("r","4")});[].forEach.call(k.holder.querySelectorAll(".label"),function(a){a.setAttribute("display","none")})});!1!==this.x_callback&&e[b].x+2.5<this.parent_holder.offsetWidth-this.marginRight&&(a=this.createElement("text",{"class":"legend_x",
|
|
||||||
fill:"gray",transform:"translate(0, "+this.parent_holder.offsetHeight+") scale(1, -1)"}),a.appendChild(document.createTextNode(this.x_callback(this.raw_points[b].x))),this.g.appendChild(a),a.setAttribute("x",e[b].x-a.getBoundingClientRect().width/2+2.5),f=g(0,0).y,a.setAttribute("y",this.parent_holder.offsetHeight-this.marginBottom-f),a=this.createElement("line",{"class":"legend_x",stroke:"gray","stroke-width":2,x1:e[b].x,x2:e[b].x,y1:f-5,y2:f+5}),this.g.appendChild(a));f=d-1;b=d}for(l in this.graphs)for(d=
|
|
||||||
e.filter(function(a){return a.graph==l}),b=0;b<d.length;b++)if(a=this.createElement("circle",{"class":"point",id:"point_"+d[b].id,cx:d[b].x,cy:d[b].y,r:4,fill:"#333",stroke:this.graphs[l],"stroke-width":2}),this.g.insertBefore(a,this.g.querySelectorAll(".label")[0]),!1!==d[b].click&&(a.onclick=d[b].click),a.addEventListener("mouseover",function(){this.setAttribute("r","6");k.holder.getElementById(this.getAttribute("id").replace("point","label")).setAttribute("display","block")}),""!==d[b].label){g=
|
|
||||||
this.createElement("g",{"class":"label",id:"label_"+d[b].id,transform:"translate(0, "+this.parent_holder.offsetHeight+") scale(1, -1)"});this.g.appendChild(g);g.addEventListener("mouseover",function(){k.holder.getElementById(this.getAttribute("id").replace("label","point")).setAttribute("r","6");this.setAttribute("display","block")});a=this.createElement("text",{});c=d[b].label.replace("</sup>","<sup>").split("<sup>");for(h=0;h<c.length;h++)c[h]=c[h].replace(/(<([^>]+)>)/ig,"").replace("%y",this.raw_points[d[b].id].y).replace("%x",
|
|
||||||
this.raw_points[d[b].id].x),0==h%2?a.appendChild(document.createTextNode(c[h])):(f=this.createElement("tspan",{dy:"-5"}),f.appendChild(document.createTextNode(c[h])),a.appendChild(f));f=this.createElement("path",{stroke:"black","stroke-width":2,fill:"white",opacity:0.5});g.appendChild(f);g.appendChild(a);h=d[b].x-a.getBoundingClientRect().width/2;c=this.parent_holder.offsetHeight-d[b].y-this.marginTop-this.marginBottom;var m=a.getBoundingClientRect().width,n=a.getBoundingClientRect().height;0>d[b].x-
|
|
||||||
a.getBoundingClientRect().width/2?(h=d[b].x+this.marginLeft+this.marginRight,c=this.parent_holder.offsetHeight-d[b].y+5,f.setAttribute("d","M "+(h-5)+" "+(c+5)+" L "+(h-5)+" "+(c-n/2+7.5)+" L "+(h-10)+" "+(c-n/2+5)+" L "+(h-5)+" "+(c-n/2+2.5)+" L "+(h-5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c+5)+" Z")):d[b].y+a.getBoundingClientRect().height+this.marginBottom+2>this.parent_holder.offsetHeight?(h=d[b].x+this.marginLeft+this.marginRight,c=this.parent_holder.offsetHeight-d[b].y+5,
|
|
||||||
f.setAttribute("d","M "+(h-5)+" "+(c+5)+" L "+(h-5)+" "+(c-n/2+7.5)+" L "+(h-this.marginBottom)+" "+(c-n/2+5)+" L "+(h-5)+" "+(c-n/2+2.5)+" L "+(h-5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c+5)+" Z"),h+m>this.parent_holder.offsetWidth&&(h=d[b].x-m-this.marginLeft-this.marginRight,c=this.parent_holder.offsetHeight-d[b].y+5,f.setAttribute("d","M "+(h-5)+" "+(c+5)+" L "+(h-5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n/2+2.5)+" L "+(h+m+10)+" "+(c-n/2+5)+" L "+(h+m+
|
|
||||||
5)+" "+(c-n/2+7.5)+" L "+(h+m+5)+" "+(c+5)+" Z"))):d[b].x+m/2+this.marginLeft+2>this.parent_holder.offsetWidth?(h=d[b].x-m-this.marginLeft-this.marginRight,c=this.parent_holder.offsetHeight-d[b].y+5,f.setAttribute("d","M "+(h-5)+" "+(c+5)+" L "+(h-5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n/2+2.5)+" L "+(h+m+10)+" "+(c-n/2+5)+" L "+(h+m+5)+" "+(c-n/2+7.5)+" L "+(h+m+5)+" "+(c+5)+" Z")):f.setAttribute("d","M "+(h-5)+" "+(c+5)+" L "+(h-5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n+5)+" L "+
|
|
||||||
(h+m+5)+" "+(c+5)+" L "+(h+m/2+2.5)+" "+(c+5)+" L "+(h+m/2)+" "+(c+10)+" L "+(h+m/2-2.5)+" "+(c+5)+" Z");a.setAttribute("x",h);a.setAttribute("y",c);g.setAttribute("display","none")}};
|
|
||||||
//# sourceMappingURL=timeline.min.js.map
|
|
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
|||||||
{"name":"Timeline.js","tagline":"A lightweight javascript library to plot simple graphs.","body":"Timeline.js\r\n===========\r\n\r\n\r\nTimeline.js is a lightweight JS library to plot graphs using Timeline. As it uses Timeline, you can add event listeners on the plotted graph very easily.\r\n\r\nI coded it because I couldn't find any basic JS library to do this, without any external dependencies and extra features. Timeline.js is only 13k once minified, and can be reduced under 10k with obfuscation. Better results may be obtained with a little refactor, but that's enough for me. Plus it can be very easily customised to fit your needs.\r\n\r\n## Live demos\r\n\r\n* [Single graph example](http://phyks.github.io/timeline.js/examples/index.html)\r\n* [Multi graph example](http://phyks.github.io/timeline.js/examples/index2.html)\r\n* [Rounded graph example](http://phyks.github.io/timeline.js/examples/index3.html)\r\n* [Dashed graph example](http://phyks.github.io/timeline.js/examples/index4.html)\r\n* [Line only graph example](http://phyks.github.io/timeline.js/examples/index5.html)\r\n* [Graph with legend example](http://phyks.github.io/timeline.js/examples/index6.html)\r\n* [Interactivity with points example](http://phyks.github.io/timeline.js/examples/index7.html)\r\n* [Multiple holders example](http://phyks.github.io/timeline.js/examples/index8.html)\r\n\r\n## Usage\r\n\r\n(See examples for more info. For live examples, see http://phyks.github.io/timeline.js/)\r\n\r\n\r\nFirst, you must include the `timeline.js` or `timeline.min.js` script.\r\n\r\nThen, you need to init a Timeline object, using something like `var tl = new Timeline({'id': 'holder', 'height': '100%', 'width': '100%', 'grid': 'both', 'x_axis': true, 'rounded': false, 'x_callback': false});`. The arguments are all optional and are:\r\n* `id` : the id of the parent element that will contain the Timeline\r\n* `width` / `height` : width and height of the created Timeline\r\n* `grid` : none / small / big / both to choose which type of grid you want\r\n* `x_axis` : true / false to show / hide the x axis\r\n* `line` : none / line / dashed to choose line type. You can edit the dasharray by replacing `Timeline.dash_style` value\r\n* `fill` : true / false to fill the area below the graph or not\r\n* `rounded` : true / false to use splines to smoothen the graph or not\r\n* `x_callback` : callback function to call to get texts for the x legend. Not yet implemented\r\n\r\n_Note :_ One Timeline object corresponds to one holder.\r\n\r\nThen, you can add as many graphs as you want, with `tl.addGraph(NAME, COLOR);` where COLOR must be a valid CSS color.\r\nAnd you can add points using `tl.addPoints(GRAPH_NAME, POINTS);`. Points is an array of point objects, which are of the type `{'x': ABSCISSA, 'y': ORDINATE, 'label': LABEL}`. LABEL is the text to display in the infobox when the mouse is over the point. You can use '%x' and '%y' in labels and they will be automatically replaced by the coordinates. You can also use `<sup>` and `<sub>` HTML tags. You can add another (optional) element `click` which must be a ffunction to bind to onclick event on this point.\r\n\r\n_Note_ : You don't have to sort the points inside a same list of points in a tl.addGraph call. They will be sorted for you. But, if you call tl.addPoints multiple times, you must sort the points yourself between each call. The script won't do it for you and it will result in weird graphs if you don't do it.\r\n\r\nFinally, you can draw the timeline with `tl.draw();`.\r\n\r\n## Other functions\r\n\r\n* `tl.clearGraph(GRAPH);` to delete the data for the graph GRAPH, or for all graphs + the graphs definition if GRAPH is not specified.\r\n* `tl.hasGraph(GRAPH);` to check if a graph with name GRAPH has already been defined or not.\r\n\r\n## License\r\n\r\n```\r\n* --------------------------------------------------------------------------------\r\n* \"THE NO-ALCOHOL BEER-WARE LICENSE\" (Revision 42):\r\n* Phyks (webmaster@phyks.me) wrote this file. As long as you retain this notice you\r\n* can do whatever you want with this stuff (and you can also do whatever you want\r\n* with this stuff without retaining it, but that's not cool...). If we meet some \r\n* day, and you think this stuff is worth it, you can buy me a <del>beer</del> soda \r\n* in return.\r\n*\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPhyks\r\n* ---------------------------------------------------------------------------------\r\n```\r\n\r\n## Known bugs / TODO\r\n\r\nFeel free to contribute !\r\n\r\n* Y axis is not implemented, but could be implemented easily\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."}
|
|
@ -1,69 +0,0 @@
|
|||||||
.highlight { background: #ffffff; }
|
|
||||||
.highlight .c { color: #999988; font-style: italic } /* Comment */
|
|
||||||
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
|
|
||||||
.highlight .k { font-weight: bold } /* Keyword */
|
|
||||||
.highlight .o { font-weight: bold } /* Operator */
|
|
||||||
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
|
||||||
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
|
|
||||||
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
|
|
||||||
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
|
|
||||||
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
|
||||||
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
|
|
||||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
|
||||||
.highlight .gr { color: #aa0000 } /* Generic.Error */
|
|
||||||
.highlight .gh { color: #999999 } /* Generic.Heading */
|
|
||||||
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
|
||||||
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
|
|
||||||
.highlight .go { color: #888888 } /* Generic.Output */
|
|
||||||
.highlight .gp { color: #555555 } /* Generic.Prompt */
|
|
||||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
|
||||||
.highlight .gu { color: #800080; font-weight: bold; } /* Generic.Subheading */
|
|
||||||
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
|
|
||||||
.highlight .kc { font-weight: bold } /* Keyword.Constant */
|
|
||||||
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
|
|
||||||
.highlight .kn { font-weight: bold } /* Keyword.Namespace */
|
|
||||||
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
|
|
||||||
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
|
|
||||||
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
|
||||||
.highlight .m { color: #009999 } /* Literal.Number */
|
|
||||||
.highlight .s { color: #d14 } /* Literal.String */
|
|
||||||
.highlight .na { color: #008080 } /* Name.Attribute */
|
|
||||||
.highlight .nb { color: #0086B3 } /* Name.Builtin */
|
|
||||||
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
|
|
||||||
.highlight .no { color: #008080 } /* Name.Constant */
|
|
||||||
.highlight .ni { color: #800080 } /* Name.Entity */
|
|
||||||
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
|
|
||||||
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
|
|
||||||
.highlight .nn { color: #555555 } /* Name.Namespace */
|
|
||||||
.highlight .nt { color: #000080 } /* Name.Tag */
|
|
||||||
.highlight .nv { color: #008080 } /* Name.Variable */
|
|
||||||
.highlight .ow { font-weight: bold } /* Operator.Word */
|
|
||||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
|
||||||
.highlight .mf { color: #009999 } /* Literal.Number.Float */
|
|
||||||
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
|
|
||||||
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
|
|
||||||
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
|
|
||||||
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
|
|
||||||
.highlight .sc { color: #d14 } /* Literal.String.Char */
|
|
||||||
.highlight .sd { color: #d14 } /* Literal.String.Doc */
|
|
||||||
.highlight .s2 { color: #d14 } /* Literal.String.Double */
|
|
||||||
.highlight .se { color: #d14 } /* Literal.String.Escape */
|
|
||||||
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
|
|
||||||
.highlight .si { color: #d14 } /* Literal.String.Interpol */
|
|
||||||
.highlight .sx { color: #d14 } /* Literal.String.Other */
|
|
||||||
.highlight .sr { color: #009926 } /* Literal.String.Regex */
|
|
||||||
.highlight .s1 { color: #d14 } /* Literal.String.Single */
|
|
||||||
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
|
|
||||||
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
|
|
||||||
.highlight .vc { color: #008080 } /* Name.Variable.Class */
|
|
||||||
.highlight .vg { color: #008080 } /* Name.Variable.Global */
|
|
||||||
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
|
|
||||||
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
|
|
||||||
|
|
||||||
.type-csharp .highlight .k { color: #0000FF }
|
|
||||||
.type-csharp .highlight .kt { color: #0000FF }
|
|
||||||
.type-csharp .highlight .nf { color: #000000; font-weight: normal }
|
|
||||||
.type-csharp .highlight .nc { color: #2B91AF }
|
|
||||||
.type-csharp .highlight .nn { color: #000000 }
|
|
||||||
.type-csharp .highlight .s { color: #A31515 }
|
|
||||||
.type-csharp .highlight .sc { color: #A31515 }
|
|
@ -1,255 +0,0 @@
|
|||||||
@import url(https://fonts.googleapis.com/css?family=Lato:300italic,700italic,300,700);
|
|
||||||
|
|
||||||
body {
|
|
||||||
padding:50px;
|
|
||||||
font:14px/1.5 Lato, "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
color:#777;
|
|
||||||
font-weight:300;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1, h2, h3, h4, h5, h6 {
|
|
||||||
color:#222;
|
|
||||||
margin:0 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
p, ul, ol, table, pre, dl {
|
|
||||||
margin:0 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1, h2, h3 {
|
|
||||||
line-height:1.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size:28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
color:#393939;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3, h4, h5, h6 {
|
|
||||||
color:#494949;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color:#39c;
|
|
||||||
font-weight:400;
|
|
||||||
text-decoration:none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a small {
|
|
||||||
font-size:11px;
|
|
||||||
color:#777;
|
|
||||||
margin-top:-0.6em;
|
|
||||||
display:block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.wrapper {
|
|
||||||
width:860px;
|
|
||||||
margin:0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
|
||||||
border-left:1px solid #e5e5e5;
|
|
||||||
margin:0;
|
|
||||||
padding:0 0 0 20px;
|
|
||||||
font-style:italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
code, pre {
|
|
||||||
font-family:Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal;
|
|
||||||
color:#333;
|
|
||||||
font-size:12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
padding:8px 15px;
|
|
||||||
background: #f8f8f8;
|
|
||||||
border-radius:5px;
|
|
||||||
border:1px solid #e5e5e5;
|
|
||||||
overflow-x: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
width:100%;
|
|
||||||
border-collapse:collapse;
|
|
||||||
}
|
|
||||||
|
|
||||||
th, td {
|
|
||||||
text-align:left;
|
|
||||||
padding:5px 10px;
|
|
||||||
border-bottom:1px solid #e5e5e5;
|
|
||||||
}
|
|
||||||
|
|
||||||
dt {
|
|
||||||
color:#444;
|
|
||||||
font-weight:700;
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
color:#444;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
max-width:100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
width:270px;
|
|
||||||
float:left;
|
|
||||||
position:fixed;
|
|
||||||
}
|
|
||||||
|
|
||||||
header ul {
|
|
||||||
list-style:none;
|
|
||||||
height:40px;
|
|
||||||
|
|
||||||
padding:0;
|
|
||||||
|
|
||||||
background: #eee;
|
|
||||||
background: -moz-linear-gradient(top, #f8f8f8 0%, #dddddd 100%);
|
|
||||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd));
|
|
||||||
background: -webkit-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
|
|
||||||
background: -o-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
|
|
||||||
background: -ms-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
|
|
||||||
background: linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
|
|
||||||
|
|
||||||
border-radius:5px;
|
|
||||||
border:1px solid #d2d2d2;
|
|
||||||
box-shadow:inset #fff 0 1px 0, inset rgba(0,0,0,0.03) 0 -1px 0;
|
|
||||||
width:270px;
|
|
||||||
}
|
|
||||||
|
|
||||||
header li {
|
|
||||||
width:89px;
|
|
||||||
float:left;
|
|
||||||
border-right:1px solid #d2d2d2;
|
|
||||||
height:40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
header ul a {
|
|
||||||
line-height:1;
|
|
||||||
font-size:11px;
|
|
||||||
color:#999;
|
|
||||||
display:block;
|
|
||||||
text-align:center;
|
|
||||||
padding-top:6px;
|
|
||||||
height:40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
strong {
|
|
||||||
color:#222;
|
|
||||||
font-weight:700;
|
|
||||||
}
|
|
||||||
|
|
||||||
header ul li + li {
|
|
||||||
width:88px;
|
|
||||||
border-left:1px solid #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
header ul li + li + li {
|
|
||||||
border-right:none;
|
|
||||||
width:89px;
|
|
||||||
}
|
|
||||||
|
|
||||||
header ul a strong {
|
|
||||||
font-size:14px;
|
|
||||||
display:block;
|
|
||||||
color:#222;
|
|
||||||
}
|
|
||||||
|
|
||||||
section {
|
|
||||||
width:500px;
|
|
||||||
float:right;
|
|
||||||
padding-bottom:50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
small {
|
|
||||||
font-size:11px;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
border:0;
|
|
||||||
background:#e5e5e5;
|
|
||||||
height:1px;
|
|
||||||
margin:0 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
width:270px;
|
|
||||||
float:left;
|
|
||||||
position:fixed;
|
|
||||||
bottom:50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media print, screen and (max-width: 960px) {
|
|
||||||
|
|
||||||
div.wrapper {
|
|
||||||
width:auto;
|
|
||||||
margin:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
header, section, footer {
|
|
||||||
float:none;
|
|
||||||
position:static;
|
|
||||||
width:auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
padding-right:320px;
|
|
||||||
}
|
|
||||||
|
|
||||||
section {
|
|
||||||
border:1px solid #e5e5e5;
|
|
||||||
border-width:1px 0;
|
|
||||||
padding:20px 0;
|
|
||||||
margin:0 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
header a small {
|
|
||||||
display:inline;
|
|
||||||
}
|
|
||||||
|
|
||||||
header ul {
|
|
||||||
position:absolute;
|
|
||||||
right:50px;
|
|
||||||
top:52px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media print, screen and (max-width: 720px) {
|
|
||||||
body {
|
|
||||||
word-wrap:break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
padding:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
header ul, header p.view {
|
|
||||||
position:static;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre, code {
|
|
||||||
word-wrap:normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media print, screen and (max-width: 480px) {
|
|
||||||
body {
|
|
||||||
padding:15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
header ul {
|
|
||||||
display:none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
body {
|
|
||||||
padding:0.4in;
|
|
||||||
font-size:12pt;
|
|
||||||
color:#444;
|
|
||||||
}
|
|
||||||
}
|
|
591
timeline.js
Normal file
591
timeline.js
Normal file
@ -0,0 +1,591 @@
|
|||||||
|
/* Timeline.js
|
||||||
|
* Author : Phyks (http://phyks.me)
|
||||||
|
* http://phyks.github.io/timeline.js
|
||||||
|
|
||||||
|
* --------------------------------------------------------------------------------
|
||||||
|
* "THE NO-ALCOHOL BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* Phyks (webmaster@phyks.me) wrote this file. As long as you retain this notice you
|
||||||
|
* can do whatever you want with this stuff (and you can also do whatever you want
|
||||||
|
* with this stuff without retaining it, but that's not cool...). If we meet some
|
||||||
|
* day, and you think this stuff is worth it, you can buy me a <del>beer</del> soda
|
||||||
|
* in return.
|
||||||
|
* Phyks
|
||||||
|
* ---------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialization :
|
||||||
|
* arg is an object with :
|
||||||
|
* id = id of the parent block
|
||||||
|
* height / width = size of the svg
|
||||||
|
* grid = small / big / both
|
||||||
|
* x_axis = true / false to show or hide x axis
|
||||||
|
* line = none / line / dashed to choose line type
|
||||||
|
* rounded = true / false to use splines to smoothen the graph
|
||||||
|
* x_callback = function(args) { } or false is called to display the legend on the x axis
|
||||||
|
* fill = true / false to fill below the graph or not
|
||||||
|
*/
|
||||||
|
function Timeline(arg) {
|
||||||
|
this.ns = "http://www.w3.org/2000/svg";
|
||||||
|
this.xlinkns = "http://www.w3.org/1999/xlink";
|
||||||
|
|
||||||
|
this.marginBottom = 10;
|
||||||
|
this.marginTop = 15;
|
||||||
|
this.marginLeft = 10;
|
||||||
|
this.marginRight = 10;
|
||||||
|
this.rounded = false;
|
||||||
|
this.x_axis = false;
|
||||||
|
this.fill = true;
|
||||||
|
this.line = 'line';
|
||||||
|
this.dashed_style = '5, 5';
|
||||||
|
|
||||||
|
this.parent_holder = false;
|
||||||
|
this.holder = false;
|
||||||
|
this.g = false;
|
||||||
|
this.axis = false;
|
||||||
|
this.graphs = [];
|
||||||
|
this.raw_points = [];
|
||||||
|
this.x_callback = false;
|
||||||
|
|
||||||
|
var old = window.onresize || function () {};
|
||||||
|
var obj = this;
|
||||||
|
window.onresize = function() {
|
||||||
|
old();
|
||||||
|
obj.resize(obj.parent_holder.offsetWidth, obj.parent_holder.offsetHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image", "1.1")) {
|
||||||
|
alert("ERROR : Your browser does not support embedded SVG.");
|
||||||
|
}
|
||||||
|
this.parent_holder = document.getElementById(arg.id);
|
||||||
|
|
||||||
|
this.parent_holder.style.width = arg.width;
|
||||||
|
this.parent_holder.style.height = arg.height;
|
||||||
|
var svg = this.createElement('svg:svg', { 'width': '100%', 'height': '100%' });
|
||||||
|
svg.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', this.xlinkns);
|
||||||
|
this.parent_holder.appendChild(svg);
|
||||||
|
|
||||||
|
this.holder = this.parent_holder.querySelector('svg');
|
||||||
|
|
||||||
|
defs = this.createElement('defs', {});
|
||||||
|
this.holder.appendChild(defs);
|
||||||
|
|
||||||
|
if(arg.grid === 'small' || arg.grid === 'both') {
|
||||||
|
var small_grid_pattern = this.createElement('pattern', { 'id': 'smallGrid', 'width': 8, 'height': 8, 'patternUnits': 'userSpaceOnUse' });
|
||||||
|
|
||||||
|
var small_grid_path = this.createElement('path', { 'd': 'M 8 0 L 0 0 0 8', 'fill': 'none', 'stroke': 'gray', 'stroke-width': '0.5' });
|
||||||
|
small_grid_pattern.appendChild(small_grid_path);
|
||||||
|
|
||||||
|
defs.appendChild(small_grid_pattern);
|
||||||
|
}
|
||||||
|
if(arg.grid === 'big' || arg.grid === 'both') {
|
||||||
|
var grid_pattern = this.createElement('pattern', { 'id': 'grid', 'width': 80, 'height': 80, 'patternUnits': 'userSpaceOnUse' });
|
||||||
|
|
||||||
|
if(arg.grid === 'both') {
|
||||||
|
var grid_rect = this.createElement('rect', {'width': 80, 'height': 80, 'fill': 'url(#smallGrid)' });
|
||||||
|
grid_pattern.appendChild(grid_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
var grid_path = this.createElement('path', {'d': 'M 80 0 L 0 0 0 80', 'fill': 'none', 'stroke': 'gray', 'stroke-width': '1'});
|
||||||
|
grid_pattern.appendChild(grid_path);
|
||||||
|
|
||||||
|
defs.appendChild(grid_pattern);
|
||||||
|
}
|
||||||
|
this.grid = arg.grid;
|
||||||
|
|
||||||
|
|
||||||
|
var marker = this.createElement('marker', {'id': 'markerArrow', 'markerWidth': 13, 'markerHeight': 13, 'refX': 2, 'refY': 6, 'orient': 'auto' });
|
||||||
|
var marker_path = this.createElement('path', {'d': 'M2,2 L2,11 L10,6 L2,2', 'fill': 'gray' });
|
||||||
|
marker.appendChild(marker_path);
|
||||||
|
defs.appendChild(marker);
|
||||||
|
|
||||||
|
this.g = this.createElement('g', {'transform': 'translate(0, ' + this.parent_holder.offsetHeight + ') scale(1, -1)'});
|
||||||
|
this.holder.appendChild(this.g);
|
||||||
|
|
||||||
|
if(arg.x_axis === true) {
|
||||||
|
this.axis = this.createElement('line', {'x1': this.marginLeft, 'y1': this.parent_holder.offsetHeight / 2 + 1.5, 'x2': this.parent_holder.offsetWidth - 13 - this.marginRight, 'y2': this.parent_holder.offsetHeight / 2 + 1.5, 'stroke': 'gray', 'stroke-width': 3, 'marker-end': 'url("#markerArrow")'});
|
||||||
|
this.g.appendChild(this.axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.grid !== "none") {
|
||||||
|
var grid = this.createElement('rect', {'width': '100%', 'height': '100%'});
|
||||||
|
if(this.grid === 'big' || this.grid === 'both') {
|
||||||
|
grid.setAttribute('fill', 'url(#grid)');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
grid.setAttribute('fill', 'url(#smallGrid)');
|
||||||
|
}
|
||||||
|
this.g.appendChild(grid);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.rounded = arg.rounded;
|
||||||
|
this.x_axis = arg.x_axis;
|
||||||
|
this.line = arg.line;
|
||||||
|
this.fill = arg.fill;
|
||||||
|
|
||||||
|
this.x_callback = arg.x_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resize the SVG
|
||||||
|
Timeline.prototype.resize = function(new_width, new_height) {
|
||||||
|
if(this.g !== false) {
|
||||||
|
this.g.setAttribute('transform', 'translate(0, ' + new_height + ') scale(1, -1)');
|
||||||
|
if(this.x_axis === true) {
|
||||||
|
this.axis.setAttribute('x2', new_width - this.marginLeft - 3 - this.marginRight);
|
||||||
|
}
|
||||||
|
[].forEach.call(this.holder.querySelectorAll('.label, .over, .point, .line, .graph, .legend_x'), function(el) {
|
||||||
|
el.parentNode.removeChild(el);
|
||||||
|
});
|
||||||
|
this.draw();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create an element "element" with the attributes "attrs"
|
||||||
|
Timeline.prototype.createElement = function (element, attrs) {
|
||||||
|
var el = document.createElementNS(this.ns, element);
|
||||||
|
for(attr in attrs) {
|
||||||
|
el.setAttribute(attr, attrs[attr]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check wether the element "element" has class "class"
|
||||||
|
Timeline.prototype.hasClass = function (element, cls) {
|
||||||
|
return (' ' + element.getAttribute('class') + ' ').indexOf(' ' + cls + ' ') > -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add a new graph to the Timeline
|
||||||
|
Timeline.prototype.addGraph = function (graph, color) {
|
||||||
|
this.graphs[graph] = color;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test wether a graph of name "graph" already exists
|
||||||
|
Timeline.prototype.hasGraph = function (graph) {
|
||||||
|
if(typeof(this.graphs[graph]) === 'undefined') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Clear the specified graph data, or completely clear all the graph data
|
||||||
|
Timeline.prototype.clearGraph = function (graph) {
|
||||||
|
if(typeof(graph) === 'undefined') {
|
||||||
|
this.raw_points = [];
|
||||||
|
this.graphs = [];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(var i = 0; i < this.raw_points.length; i++) {
|
||||||
|
if(this.raw_points[i].graph === graph) {
|
||||||
|
this.raw_points[i] = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add points to the specified graph
|
||||||
|
Timeline.prototype.addPoints = function (graph, data) {
|
||||||
|
for(var point = 0; point < data.length; point++) {
|
||||||
|
var insert = {'graph': graph, 'x': data[point].x, 'y': data[point].y};
|
||||||
|
if(typeof(data[point].label) !== 'undefined') {
|
||||||
|
insert.label = data[point].label;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
insert.label = '';
|
||||||
|
}
|
||||||
|
if(typeof(data[point].click) !== 'undefined') {
|
||||||
|
insert.click = data[point].click;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
insert.click = false;
|
||||||
|
}
|
||||||
|
this.raw_points.push(insert);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.raw_points.sort(function (a, b) {
|
||||||
|
if(a.x < b.x) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if(a.x == b.x) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compute new coordinates, knowing the min and max value to fit the graph in the container
|
||||||
|
Timeline.prototype.newCoordinate = function(value, min, max, minValue, maxValue) {
|
||||||
|
var a = (maxValue - minValue) / (max - min);
|
||||||
|
return a *(value - min) + minValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compute new X and Y values
|
||||||
|
Timeline.prototype.getNewXY = function (minX, maxX, minY, maxY) {
|
||||||
|
var obj = this;
|
||||||
|
return function (x, y) {
|
||||||
|
return {
|
||||||
|
'x': obj.newCoordinate(x, minX, maxX, obj.marginLeft, obj.parent_holder.offsetWidth - obj.marginRight),
|
||||||
|
'y': obj.newCoordinate(y, minY, maxY, 2*obj.marginBottom, obj.parent_holder.offsetHeight - obj.marginTop)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the necessary control points to smoothen the graph, is rounded is true
|
||||||
|
Timeline.prototype.getControlPoints = function (data) {
|
||||||
|
// From http://www.particleincell.com/wp-content/uploads/2012/06/bezier-spline.js
|
||||||
|
var p1 = new Array();
|
||||||
|
var p2 = new Array();
|
||||||
|
var n = data.length - 1;
|
||||||
|
|
||||||
|
/*rhs vector*/
|
||||||
|
var a = new Array();
|
||||||
|
var b = new Array();
|
||||||
|
var c = new Array();
|
||||||
|
var r = new Array();
|
||||||
|
|
||||||
|
/*left most segment*/
|
||||||
|
a[0] = 0;
|
||||||
|
b[0] = 2;
|
||||||
|
c[0] = 1;
|
||||||
|
r[0] = data[0] + 2*data[1];
|
||||||
|
|
||||||
|
/*internal segments*/
|
||||||
|
for (var i = 1; i < n - 1; i++) {
|
||||||
|
a[i] = 1;
|
||||||
|
b[i] = 4;
|
||||||
|
c[i] = 1;
|
||||||
|
r[i] = 4 * data[i] + 2 * data[i+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*right segment*/
|
||||||
|
a[n-1] = 2;
|
||||||
|
b[n-1] = 7;
|
||||||
|
c[n-1] = 0;
|
||||||
|
r[n-1] = 8*data[n-1] + data[n];
|
||||||
|
|
||||||
|
/*solves Ax=b with the Thomas algorithm (from Wikipedia)*/
|
||||||
|
var m;
|
||||||
|
for (var i = 1; i < n; i++) {
|
||||||
|
m = a[i]/b[i-1];
|
||||||
|
b[i] = b[i] - m * c[i - 1];
|
||||||
|
r[i] = r[i] - m*r[i-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
p1[n-1] = r[n-1]/b[n-1];
|
||||||
|
for (var i = n - 2; i >= 0; --i) {
|
||||||
|
p1[i] = (r[i] - c[i] * p1[i+1]) / b[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*we have p1, now compute p2*/
|
||||||
|
for (var i=0;i<n-1;i++) {
|
||||||
|
p2[i] = 2*data[i+1] - p1[i+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
p2[n-1] = 0.5*(data[n] + p1[n-1]);
|
||||||
|
|
||||||
|
return {p1:p1, p2:p2};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Get the scale so that graph fits with window
|
||||||
|
Timeline.prototype.scale = function(data) {
|
||||||
|
var empty = true;
|
||||||
|
for(graph in data) {
|
||||||
|
empty = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(empty) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var minX = false, minY = 0;
|
||||||
|
var maxX = false, maxY = false;
|
||||||
|
var circle = false, last_point = false, line = false;
|
||||||
|
|
||||||
|
// Look for max and min values for both axis
|
||||||
|
for(var point = 0; point < data.length; point++) {
|
||||||
|
if(data[point].x < minX || minX === false) {
|
||||||
|
minX = data[point].x;
|
||||||
|
}
|
||||||
|
if(data[point].x > maxX || maxX === false) {
|
||||||
|
maxX = data[point].x;
|
||||||
|
}
|
||||||
|
if(data[point].y < minY) {
|
||||||
|
minY = data[point].y;
|
||||||
|
}
|
||||||
|
if(data[point].y > maxY || maxY === false) {
|
||||||
|
maxY = data[point].y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale the grid, if needed
|
||||||
|
var scale = this.getNewXY(minX, maxX, minY, maxY);
|
||||||
|
var tmp = scale(Math.pow(10, Math.floor(Math.log(maxX - minX) / Math.log(10))), Math.pow(10, Math.floor(Math.log(maxY - minY) / Math.log(10))));
|
||||||
|
var origin = scale(0, 0);
|
||||||
|
var coordinates = {'x': tmp.x - origin.x, 'y': tmp.y - origin.y };
|
||||||
|
if(this.grid === 'big' || this.grid === 'both') {
|
||||||
|
var grid = this.holder.getElementById('grid');
|
||||||
|
grid.setAttribute('width', coordinates.x);
|
||||||
|
grid.setAttribute('height', coordinates.y);
|
||||||
|
var big_coords = scale(Math.floor(minX / Math.pow(10, Math.floor(Math.log(maxX - minX) / Math.log(10)))) * Math.pow(10, Math.floor(Math.log(maxX - minX) / Math.log(10))), Math.floor(minY / Math.pow(10, Math.floor(Math.log(maxY - minY) / Math.log(10)))) * Math.pow(10, Math.floor(Math.log(maxY - minY) / Math.log(10))));
|
||||||
|
grid.setAttribute('y', big_coords.y);
|
||||||
|
grid.setAttribute('x', big_coords.x);
|
||||||
|
grid.querySelector('path').setAttribute('d', 'M '+coordinates.x+' 0 L 0 0 0 '+coordinates.y);
|
||||||
|
|
||||||
|
if(this.grid === 'both') {
|
||||||
|
grid.querySelector('rect').setAttribute('width', coordinates.x);
|
||||||
|
grid.querySelector('rect').setAttribute('height', coordinates.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(this.grid === 'small' || this.grid === 'both') {
|
||||||
|
coordinates.x = coordinates.x / 10;
|
||||||
|
coordinates.y = coordinates.y / 10;
|
||||||
|
var grid = this.holder.getElementById('smallGrid');
|
||||||
|
grid.setAttribute('width', coordinates.x);
|
||||||
|
grid.setAttribute('height', coordinates.y);
|
||||||
|
if(this.grid === 'small') {
|
||||||
|
var small_coords = scale(Math.floor(minX / Math.pow(10, Math.floor(Math.log(maxX - minX) / Math.log(10)))) * Math.pow(10, Math.floor(Math.log(maxX - minX) / Math.log(10))), Math.floor(minY / Math.pow(10, Math.floor(Math.log(maxY - minY) / Math.log(10)))) * Math.pow(10, Math.floor(Math.log(maxY - minY) / Math.log(10))));
|
||||||
|
grid.setAttribute('y', small_coords.y);
|
||||||
|
grid.setAttribute('x', small_coords.x);
|
||||||
|
}
|
||||||
|
grid.querySelector('path').setAttribute('d', 'M '+coordinates.x+' 0 L 0 0 0 '+coordinates.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Draw axis */
|
||||||
|
if(this.x_axis === true) {
|
||||||
|
y = scale(0, 0).y;
|
||||||
|
this.axis.setAttribute('y1', y);
|
||||||
|
this.axis.setAttribute('y2', y);
|
||||||
|
}
|
||||||
|
|
||||||
|
return scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Draw graphs
|
||||||
|
Timeline.prototype.draw = function() {
|
||||||
|
var scale = this.scale(this.raw_points);
|
||||||
|
var points = [], path;
|
||||||
|
var px, py;
|
||||||
|
var element;
|
||||||
|
var obj = this;
|
||||||
|
|
||||||
|
for(var point = 0; point < this.raw_points.length; point++) {
|
||||||
|
var tmp = scale(this.raw_points[point].x, this.raw_points[point].y);
|
||||||
|
points.push({'id': point, 'x': tmp.x, 'y': tmp.y, 'graph': this.raw_points[point].graph, 'click': this.raw_points[point].click, 'label': this.raw_points[point].label});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw each graph
|
||||||
|
for(var graph in this.graphs) {
|
||||||
|
var filtered_points = points.filter(function(el) { return el.graph == graph; });
|
||||||
|
path = '';
|
||||||
|
|
||||||
|
// Draw line
|
||||||
|
if(this.rounded === true) {
|
||||||
|
var x = new Array(), y = new Array();
|
||||||
|
for(var point = 0; point < filtered_points.length; point++) {
|
||||||
|
x.push(filtered_points[point].x);
|
||||||
|
y.push(filtered_points[point].y);
|
||||||
|
}
|
||||||
|
px = this.getControlPoints(x);
|
||||||
|
py = this.getControlPoints(y);
|
||||||
|
for(var point = 0; point < filtered_points.length - 1; point++) {
|
||||||
|
path += 'C '+px.p1[point]+' '+py.p1[point]+' '+px.p2[point]+' '+py.p2[point]+' '+filtered_points[point+1].x+' '+filtered_points[point+1].y+' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(var point = 1; point < filtered_points.length; point++) {
|
||||||
|
path += 'L '+filtered_points[point].x+' '+filtered_points[point].y+' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.line !== 'none' && filtered_points.length !== 0) {
|
||||||
|
element = this.createElement('path', {'class': 'line', 'stroke': this.graphs[graph], 'stroke-width': 2, 'fill': 'none', 'd': 'M '+filtered_points[0].x+' '+filtered_points[0].y+' '+path});
|
||||||
|
if(this.line === 'dashed') {
|
||||||
|
element.setAttribute('style', 'stroke-dasharray: '+this.dashed_style);
|
||||||
|
}
|
||||||
|
this.g.appendChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw fill
|
||||||
|
if(this.fill) {
|
||||||
|
element = this.createElement('path', {'class': 'graph', 'fill': this.graphs[graph], 'opacity': '0.25', 'stroke': 'none', 'd': 'M '+filtered_points[0].x+' '+2*this.marginBottom+' L '+filtered_points[0].x+' '+filtered_points[0].y+' '+ path + ' L '+filtered_points[filtered_points.length - 1].x+' '+2*this.marginBottom+' Z' });
|
||||||
|
this.g.insertBefore(element, this.g.querySelectorAll('.over')[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hover effect
|
||||||
|
var prev = 0;
|
||||||
|
for(var point = 0; point < points.length;) {
|
||||||
|
var rect = this.createElement('rect', {'class': 'over', 'id': 'over_'+point, 'y': 0, 'fill': 'white', 'opacity': 0, 'height': '100%'});
|
||||||
|
var currents = [point];
|
||||||
|
|
||||||
|
var next = point + 1;
|
||||||
|
if(point < points.length - 1) {
|
||||||
|
while(points[next].x == points[point].x) {
|
||||||
|
if(i > points.length) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var i = prev + 1; i < next; i++) {
|
||||||
|
currents.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(point == 0) {
|
||||||
|
rect.setAttribute('x', 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rect.setAttribute('x', (points[point].x + points[prev].x) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(point == points.length - 1) {
|
||||||
|
rect.setAttribute('width', this.parent_holder.offsetWidth - (points[point].x + points[point - 1].x)/2 + 1);
|
||||||
|
}
|
||||||
|
else if(point == 0) {
|
||||||
|
rect.setAttribute('width', (points[1].x + points[0].x)/2 + this.marginLeft + 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rect.setAttribute('width', (points[next].x - points[prev].x)/2 + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.g.appendChild(rect);
|
||||||
|
|
||||||
|
rect.addEventListener('mouseover', (function(arg) {
|
||||||
|
return function() {
|
||||||
|
for(var i = 0; i < arg.length; i++) {
|
||||||
|
obj.holder.getElementById('point_'+arg[i]).setAttribute('r', '6');
|
||||||
|
obj.holder.getElementById('label_'+arg[i]).setAttribute('display', 'block');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})(currents));
|
||||||
|
|
||||||
|
rect.addEventListener('mouseout', function() {
|
||||||
|
// Reinitialize all states
|
||||||
|
[].forEach.call(obj.holder.querySelectorAll('.point'), function(el) {
|
||||||
|
el.setAttribute('r', '4');
|
||||||
|
});
|
||||||
|
|
||||||
|
[].forEach.call(obj.holder.querySelectorAll('.label'), function(el) {
|
||||||
|
el.setAttribute('display', 'none');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear also the labels when moving outside the SVG element
|
||||||
|
this.holder.addEventListener('mouseout', function() {
|
||||||
|
// Reinitialize all states
|
||||||
|
[].forEach.call(obj.holder.querySelectorAll('.point'), function(el) {
|
||||||
|
el.setAttribute('r', '4');
|
||||||
|
});
|
||||||
|
|
||||||
|
[].forEach.call(obj.holder.querySelectorAll('.label'), function(el) {
|
||||||
|
el.setAttribute('display', 'none');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if(this.x_callback !== false && points[point].x + 2.5 < this.parent_holder.offsetWidth - this.marginRight) {
|
||||||
|
element = this.createElement('text', {'class': 'legend_x', 'fill': 'gray', 'transform': 'translate(0, ' + this.parent_holder.offsetHeight + ') scale(1, -1)'});
|
||||||
|
element.appendChild(document.createTextNode(this.x_callback(this.raw_points[point].x)));
|
||||||
|
this.g.appendChild(element);
|
||||||
|
element.setAttribute('x', points[point].x - element.getBoundingClientRect().width / 2 + 2.5);
|
||||||
|
var y_zero = scale(0, 0).y;
|
||||||
|
element.setAttribute('y', this.parent_holder.offsetHeight - this.marginBottom - y_zero);
|
||||||
|
|
||||||
|
element = this.createElement('line', {'class': 'legend_x', 'stroke': 'gray', 'stroke-width': 2, 'x1': points[point].x, 'x2': points[point].x, 'y1': y_zero - 5, 'y2': y_zero + 5});
|
||||||
|
this.g.appendChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
prev = next - 1;
|
||||||
|
point = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw points and labels
|
||||||
|
for(var graph in this.graphs) {
|
||||||
|
var filtered_points = points.filter(function(el) { return el.graph == graph; });
|
||||||
|
|
||||||
|
for(var point = 0; point < filtered_points.length; point++) {
|
||||||
|
element = this.createElement('circle', {'class': 'point', 'id': 'point_'+filtered_points[point].id, 'cx': filtered_points[point].x, 'cy': filtered_points[point].y, 'r': 4, 'fill': '#333', 'stroke': this.graphs[graph], 'stroke-width': 2});
|
||||||
|
this.g.insertBefore(element, this.g.querySelectorAll('.label')[0]);
|
||||||
|
|
||||||
|
if(filtered_points[point].click !== false) {
|
||||||
|
element.onclick = filtered_points[point].click;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.addEventListener('mouseover', function() {
|
||||||
|
this.setAttribute('r', '6');
|
||||||
|
obj.holder.getElementById(this.getAttribute('id').replace('point', 'label')).setAttribute('display', 'block');
|
||||||
|
});
|
||||||
|
|
||||||
|
if(filtered_points[point].label !== '') {
|
||||||
|
var g = this.createElement('g', { 'class': 'label', 'id': 'label_'+filtered_points[point].id, 'transform': 'translate(0, ' + this.parent_holder.offsetHeight + ') scale(1, -1)'});
|
||||||
|
this.g.appendChild(g);
|
||||||
|
|
||||||
|
g.addEventListener('mouseover', function() {
|
||||||
|
obj.holder.getElementById(this.getAttribute('id').replace('label', 'point')).setAttribute('r', '6');
|
||||||
|
this.setAttribute('display', 'block');
|
||||||
|
});
|
||||||
|
|
||||||
|
element = this.createElement('text', {});
|
||||||
|
var text = filtered_points[point].label.replace('</sup>', '<sup>').split('<sup>');
|
||||||
|
for(var i = 0; i < text.length; i++) {
|
||||||
|
text[i] = text[i].replace(/(<([^>]+)>)/ig,"").replace('%y', this.raw_points[filtered_points[point].id].y).replace('%x', this.raw_points[filtered_points[point].id].x);
|
||||||
|
if(i % 2 == 0) {
|
||||||
|
element.appendChild(document.createTextNode(text[i]));
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var tmp = this.createElement('tspan', {'dy': '-5'});
|
||||||
|
tmp.appendChild(document.createTextNode(text[i]));
|
||||||
|
element.appendChild(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
path = this.createElement('path', {'stroke': 'black', 'stroke-width': 2, 'fill': 'white', 'opacity': 0.5});
|
||||||
|
|
||||||
|
// Append here to have them with the good z-index, update their attributes later
|
||||||
|
g.appendChild(path);
|
||||||
|
g.appendChild(element);
|
||||||
|
|
||||||
|
var x_text = filtered_points[point].x - element.getBoundingClientRect().width / 2;
|
||||||
|
var y_text = this.parent_holder.offsetHeight - filtered_points[point].y - this.marginTop - this.marginBottom;
|
||||||
|
var element_width = element.getBoundingClientRect().width;
|
||||||
|
var element_height = element.getBoundingClientRect().height;
|
||||||
|
|
||||||
|
if(filtered_points[point].x - element.getBoundingClientRect().width / 2 < 0) {
|
||||||
|
x_text = filtered_points[point].x + this.marginLeft + this.marginRight;
|
||||||
|
y_text = this.parent_holder.offsetHeight - filtered_points[point].y + 5;
|
||||||
|
path.setAttribute('d', 'M '+(x_text - 5)+' '+(y_text + 5)+' L '+(x_text - 5)+' '+(y_text - element_height/2 + 7.5)+' L '+(x_text - 10)+' '+(y_text - element_height/2 + 5)+' L '+(x_text - 5)+' '+(y_text - element_height/2 + 2.5)+' L '+(x_text - 5)+' '+(y_text - element_height + 5)+' L '+(x_text + element_width + 5)+' '+(y_text - element_height + 5)+' L '+(x_text + element_width + 5)+' '+(y_text + 5)+' Z');
|
||||||
|
}
|
||||||
|
else if(filtered_points[point].y + element.getBoundingClientRect().height + this.marginBottom + 2 > this.parent_holder.offsetHeight) {
|
||||||
|
x_text = filtered_points[point].x + this.marginLeft + this.marginRight;
|
||||||
|
y_text = this.parent_holder.offsetHeight - filtered_points[point].y + 5;
|
||||||
|
path.setAttribute('d', 'M '+(x_text - 5)+' '+(y_text + 5)+' L '+(x_text - 5)+' '+(y_text - element_height/2 + 7.5)+' L '+(x_text - this.marginBottom)+' '+(y_text - element_height/2 + 5)+' L '+(x_text - 5)+' '+(y_text - element_height/2 + 2.5)+' L '+(x_text - 5)+' '+(y_text - element_height + 5)+' L '+(x_text + element_width + 5)+' '+(y_text - element_height + 5)+' L '+(x_text + element_width + 5)+' '+(y_text + 5)+' Z');
|
||||||
|
|
||||||
|
if(x_text + element_width > this.parent_holder.offsetWidth) {
|
||||||
|
x_text = filtered_points[point].x - element_width - this.marginLeft - this.marginRight;
|
||||||
|
y_text = this.parent_holder.offsetHeight - filtered_points[point].y + 5;
|
||||||
|
path.setAttribute('d', 'M '+(x_text - 5)+' '+(y_text + 5)+' L '+(x_text - 5)+' '+(y_text - element_height + 5)+' L '+(x_text + element_width + 5)+' '+(y_text - element_height + 5)+' L '+(x_text + element_width + 5)+' '+(y_text - element_height/2 + 2.5)+' L '+(x_text + element_width + 10)+' '+(y_text - element_height/2 + 5)+' L '+(x_text + element_width + 5)+' '+(y_text - element_height/2 + 7.5)+' L '+(x_text + element_width + 5)+' '+(y_text + 5)+' Z');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(filtered_points[point].x + element_width / 2 + this.marginLeft + 2 > this.parent_holder.offsetWidth) {
|
||||||
|
x_text = filtered_points[point].x - element_width - this.marginLeft - this.marginRight;
|
||||||
|
y_text = this.parent_holder.offsetHeight - filtered_points[point].y + 5;
|
||||||
|
path.setAttribute('d', 'M '+(x_text - 5)+' '+(y_text + 5)+' L '+(x_text - 5)+' '+(y_text - element_height + 5)+' L '+(x_text + element_width + 5)+' '+(y_text - element_height + 5)+' L '+(x_text + element_width + 5)+' '+(y_text - element_height/2 + 2.5)+' L '+(x_text + element_width + 10)+' '+(y_text - element_height/2 + 5)+' L '+(x_text + element_width + 5)+' '+(y_text - element_height/2 + 7.5)+' L '+(x_text + element_width + 5)+' '+(y_text + 5)+' Z');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
path.setAttribute('d', 'M '+(x_text - 5)+' '+(y_text + 5)+' L '+(x_text - 5)+' '+(y_text - element_height + 5)+' L '+(x_text + element_width + 5)+' '+(y_text - element_height + 5)+' L '+(x_text + element_width + 5)+' '+(y_text + 5)+' L '+(x_text + element_width/2 + 2.5)+' '+(y_text + 5)+' L '+(x_text + element_width/2)+' '+(y_text + 10)+' L '+(x_text + element_width/2 - 2.5)+' '+(y_text + 5)+' Z');
|
||||||
|
}
|
||||||
|
element.setAttribute('x', x_text);
|
||||||
|
element.setAttribute('y', y_text);
|
||||||
|
|
||||||
|
|
||||||
|
g.setAttribute('display', 'none');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
29
timeline.min.js
vendored
Normal file
29
timeline.min.js
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
function Timeline(f){this.ns="http://www.w3.org/2000/svg";this.xlinkns="http://www.w3.org/1999/xlink";this.marginBottom=10;this.marginTop=15;this.marginRight=this.marginLeft=10;this.x_axis=this.rounded=!1;this.fill=!0;this.line="line";this.dashed_style="5, 5";this.axis=this.g=this.holder=this.parent_holder=!1;this.graphs=[];this.raw_points=[];this.x_callback=!1;var e=window.onresize||function(){},g=this;window.onresize=function(){e();g.resize(g.parent_holder.offsetWidth,g.parent_holder.offsetHeight)};
|
||||||
|
document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1")||alert("ERROR : Your browser does not support embedded SVG.");this.parent_holder=document.getElementById(f.id);this.parent_holder.style.width=f.width;this.parent_holder.style.height=f.height;var a=this.createElement("svg:svg",{width:"100%",height:"100%"});a.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink",this.xlinkns);this.parent_holder.appendChild(a);this.holder=this.parent_holder.querySelector("svg");
|
||||||
|
defs=this.createElement("defs",{});this.holder.appendChild(defs);if("small"===f.grid||"both"===f.grid){var a=this.createElement("pattern",{id:"smallGrid",width:8,height:8,patternUnits:"userSpaceOnUse"}),c=this.createElement("path",{d:"M 8 0 L 0 0 0 8",fill:"none",stroke:"gray","stroke-width":"0.5"});a.appendChild(c);defs.appendChild(a)}if("big"===f.grid||"both"===f.grid)a=this.createElement("pattern",{id:"grid",width:80,height:80,patternUnits:"userSpaceOnUse"}),"both"===f.grid&&(c=this.createElement("rect",
|
||||||
|
{width:80,height:80,fill:"url(#smallGrid)"}),a.appendChild(c)),c=this.createElement("path",{d:"M 80 0 L 0 0 0 80",fill:"none",stroke:"gray","stroke-width":"1"}),a.appendChild(c),defs.appendChild(a);this.grid=f.grid;a=this.createElement("marker",{id:"markerArrow",markerWidth:13,markerHeight:13,refX:2,refY:6,orient:"auto"});c=this.createElement("path",{d:"M2,2 L2,11 L10,6 L2,2",fill:"gray"});a.appendChild(c);defs.appendChild(a);this.g=this.createElement("g",{transform:"translate(0, "+this.parent_holder.offsetHeight+
|
||||||
|
") scale(1, -1)"});this.holder.appendChild(this.g);!0===f.x_axis&&(this.axis=this.createElement("line",{x1:this.marginLeft,y1:this.parent_holder.offsetHeight/2+1.5,x2:this.parent_holder.offsetWidth-13-this.marginRight,y2:this.parent_holder.offsetHeight/2+1.5,stroke:"gray","stroke-width":3,"marker-end":'url("#markerArrow")'}),this.g.appendChild(this.axis));"none"!==this.grid&&(a=this.createElement("rect",{width:"100%",height:"100%"}),"big"===this.grid||"both"===this.grid?a.setAttribute("fill","url(#grid)"):
|
||||||
|
a.setAttribute("fill","url(#smallGrid)"),this.g.appendChild(a));this.rounded=f.rounded;this.x_axis=f.x_axis;this.line=f.line;this.fill=f.fill;this.x_callback=f.x_callback}
|
||||||
|
Timeline.prototype.resize=function(f,e){!1!==this.g&&(this.g.setAttribute("transform","translate(0, "+e+") scale(1, -1)"),!0===this.x_axis&&this.axis.setAttribute("x2",f-this.marginLeft-3-this.marginRight),[].forEach.call(this.holder.querySelectorAll(".label, .over, .point, .line, .graph, .legend_x"),function(e){e.parentNode.removeChild(e)}),this.draw())};Timeline.prototype.createElement=function(f,e){var g=document.createElementNS(this.ns,f);for(attr in e)g.setAttribute(attr,e[attr]);return g};
|
||||||
|
Timeline.prototype.hasClass=function(f,e){return-1<(" "+f.getAttribute("class")+" ").indexOf(" "+e+" ")};Timeline.prototype.addGraph=function(f,e){this.graphs[f]=e};Timeline.prototype.hasGraph=function(f){return"undefined"===typeof this.graphs[f]?!1:!0};Timeline.prototype.clearGraph=function(f){if("undefined"===typeof f)this.raw_points=[],this.graphs=[];else for(var e=0;e<this.raw_points.length;e++)this.raw_points[e].graph===f&&(this.raw_points[e]=void 0)};
|
||||||
|
Timeline.prototype.addPoints=function(f,e){for(var g=0;g<e.length;g++){var a={graph:f,x:e[g].x,y:e[g].y};a.label="undefined"!==typeof e[g].label?e[g].label:"";a.click="undefined"!==typeof e[g].click?e[g].click:!1;this.raw_points.push(a)}this.raw_points.sort(function(a,e){return a.x<e.x?-1:a.x==e.x?0:1})};Timeline.prototype.newCoordinate=function(f,e,g,a,c){return(c-a)/(g-e)*(f-e)+a};
|
||||||
|
Timeline.prototype.getNewXY=function(f,e,g,a){var c=this;return function(k,b){return{x:c.newCoordinate(k,f,e,c.marginLeft,c.parent_holder.offsetWidth-c.marginRight),y:c.newCoordinate(b,g,a,2*c.marginBottom,c.parent_holder.offsetHeight-c.marginTop)}}};
|
||||||
|
Timeline.prototype.getControlPoints=function(f){var e=[],g=[],a=f.length-1,c=[],k=[],b=[],l=[];c[0]=0;k[0]=2;b[0]=1;l[0]=f[0]+2*f[1];for(var d=1;d<a-1;d++)c[d]=1,k[d]=4,b[d]=1,l[d]=4*f[d]+2*f[d+1];c[a-1]=2;k[a-1]=7;b[a-1]=0;l[a-1]=8*f[a-1]+f[a];for(var h,d=1;d<a;d++)h=c[d]/k[d-1],k[d]-=h*b[d-1],l[d]-=h*l[d-1];e[a-1]=l[a-1]/k[a-1];for(d=a-2;0<=d;--d)e[d]=(l[d]-b[d]*e[d+1])/k[d];for(d=0;d<a-1;d++)g[d]=2*f[d+1]-e[d+1];g[a-1]=0.5*(f[a]+e[a-1]);return{p1:e,p2:g}};
|
||||||
|
Timeline.prototype.scale=function(f){var e=!0;for(graph in f){e=!1;break}if(e)return!1;for(var e=!1,g=0,a=!1,c=!1,k=0;k<f.length;k++){if(f[k].x<e||!1===e)e=f[k].x;if(f[k].x>a||!1===a)a=f[k].x;f[k].y<g&&(g=f[k].y);if(f[k].y>c||!1===c)c=f[k].y}f=this.getNewXY(e,a,g,c);var b=f(Math.pow(10,Math.floor(Math.log(a-e)/Math.log(10))),Math.pow(10,Math.floor(Math.log(c-g)/Math.log(10)))),l=f(0,0),k=b.x-l.x,b=b.y-l.y;if("big"===this.grid||"both"===this.grid){l=this.holder.getElementById("grid");l.setAttribute("width",
|
||||||
|
k);l.setAttribute("height",b);var d=f(Math.floor(e/Math.pow(10,Math.floor(Math.log(a-e)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(a-e)/Math.log(10))),Math.floor(g/Math.pow(10,Math.floor(Math.log(c-g)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(c-g)/Math.log(10))));l.setAttribute("y",d.y);l.setAttribute("x",d.x);l.querySelector("path").setAttribute("d","M "+k+" 0 L 0 0 0 "+b);"both"===this.grid&&(l.querySelector("rect").setAttribute("width",k),l.querySelector("rect").setAttribute("height",
|
||||||
|
b))}if("small"===this.grid||"both"===this.grid)k/=10,b/=10,l=this.holder.getElementById("smallGrid"),l.setAttribute("width",k),l.setAttribute("height",b),"small"===this.grid&&(e=f(Math.floor(e/Math.pow(10,Math.floor(Math.log(a-e)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(a-e)/Math.log(10))),Math.floor(g/Math.pow(10,Math.floor(Math.log(c-g)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(c-g)/Math.log(10)))),l.setAttribute("y",e.y),l.setAttribute("x",e.x)),l.querySelector("path").setAttribute("d",
|
||||||
|
"M "+k+" 0 L 0 0 0 "+b);!0===this.x_axis&&(y=f(0,0).y,this.axis.setAttribute("y1",y),this.axis.setAttribute("y2",y));return f};
|
||||||
|
Timeline.prototype.draw=function(){for(var f=this.scale(this.raw_points),e=[],g,a,c,k=this,b=0;b<this.raw_points.length;b++)g=f(this.raw_points[b].x,this.raw_points[b].y),e.push({id:b,x:g.x,y:g.y,graph:this.raw_points[b].graph,click:this.raw_points[b].click,label:this.raw_points[b].label});for(var l in this.graphs){var d=e.filter(function(a){return a.graph==l});g="";if(!0===this.rounded){a=[];c=[];for(b=0;b<d.length;b++)a.push(d[b].x),c.push(d[b].y);a=this.getControlPoints(a);c=this.getControlPoints(c);
|
||||||
|
for(b=0;b<d.length-1;b++)g+="C "+a.p1[b]+" "+c.p1[b]+" "+a.p2[b]+" "+c.p2[b]+" "+d[b+1].x+" "+d[b+1].y+" "}else for(b=1;b<d.length;b++)g+="L "+d[b].x+" "+d[b].y+" ";"none"!==this.line&&0!==d.length&&(a=this.createElement("path",{"class":"line",stroke:this.graphs[l],"stroke-width":2,fill:"none",d:"M "+d[0].x+" "+d[0].y+" "+g}),"dashed"===this.line&&a.setAttribute("style","stroke-dasharray: "+this.dashed_style),this.g.appendChild(a));this.fill&&(a=this.createElement("path",{"class":"graph",fill:this.graphs[l],
|
||||||
|
opacity:"0.25",stroke:"none",d:"M "+d[0].x+" "+2*this.marginBottom+" L "+d[0].x+" "+d[0].y+" "+g+" L "+d[d.length-1].x+" "+2*this.marginBottom+" Z"}),this.g.insertBefore(a,this.g.querySelectorAll(".over")[0]))}for(b=g=0;b<e.length;){a=this.createElement("rect",{"class":"over",id:"over_"+b,y:0,fill:"white",opacity:0,height:"100%"});c=[b];d=b+1;if(b<e.length-1)for(;e[d].x==e[b].x&&!(h>e.length);)d++;for(var h=g+1;h<d;h++)c.push(h);0==b?a.setAttribute("x",0):a.setAttribute("x",(e[b].x+e[g].x)/2);b==
|
||||||
|
e.length-1?a.setAttribute("width",this.parent_holder.offsetWidth-(e[b].x+e[b-1].x)/2+1):0==b?a.setAttribute("width",(e[1].x+e[0].x)/2+this.marginLeft+1):a.setAttribute("width",(e[d].x-e[g].x)/2+1);this.g.appendChild(a);a.addEventListener("mouseover",function(a){return function(){for(var b=0;b<a.length;b++)k.holder.getElementById("point_"+a[b]).setAttribute("r","6"),k.holder.getElementById("label_"+a[b]).setAttribute("display","block")}}(c));a.addEventListener("mouseout",function(){[].forEach.call(k.holder.querySelectorAll(".point"),
|
||||||
|
function(a){a.setAttribute("r","4")});[].forEach.call(k.holder.querySelectorAll(".label"),function(a){a.setAttribute("display","none")})});this.holder.addEventListener("mouseout",function(){[].forEach.call(k.holder.querySelectorAll(".point"),function(a){a.setAttribute("r","4")});[].forEach.call(k.holder.querySelectorAll(".label"),function(a){a.setAttribute("display","none")})});!1!==this.x_callback&&e[b].x+2.5<this.parent_holder.offsetWidth-this.marginRight&&(a=this.createElement("text",{"class":"legend_x",
|
||||||
|
fill:"gray",transform:"translate(0, "+this.parent_holder.offsetHeight+") scale(1, -1)"}),a.appendChild(document.createTextNode(this.x_callback(this.raw_points[b].x))),this.g.appendChild(a),a.setAttribute("x",e[b].x-a.getBoundingClientRect().width/2+2.5),g=f(0,0).y,a.setAttribute("y",this.parent_holder.offsetHeight-this.marginBottom-g),a=this.createElement("line",{"class":"legend_x",stroke:"gray","stroke-width":2,x1:e[b].x,x2:e[b].x,y1:g-5,y2:g+5}),this.g.appendChild(a));g=d-1;b=d}for(l in this.graphs)for(d=
|
||||||
|
e.filter(function(a){return a.graph==l}),b=0;b<d.length;b++)if(a=this.createElement("circle",{"class":"point",id:"point_"+d[b].id,cx:d[b].x,cy:d[b].y,r:4,fill:"#333",stroke:this.graphs[l],"stroke-width":2}),this.g.insertBefore(a,this.g.querySelectorAll(".label")[0]),!1!==d[b].click&&(a.onclick=d[b].click),a.addEventListener("mouseover",function(){this.setAttribute("r","6");k.holder.getElementById(this.getAttribute("id").replace("point","label")).setAttribute("display","block")}),""!==d[b].label){f=
|
||||||
|
this.createElement("g",{"class":"label",id:"label_"+d[b].id,transform:"translate(0, "+this.parent_holder.offsetHeight+") scale(1, -1)"});this.g.appendChild(f);f.addEventListener("mouseover",function(){k.holder.getElementById(this.getAttribute("id").replace("label","point")).setAttribute("r","6");this.setAttribute("display","block")});a=this.createElement("text",{});c=d[b].label.replace("</sup>","<sup>").split("<sup>");for(h=0;h<c.length;h++)c[h]=c[h].replace(/(<([^>]+)>)/ig,"").replace("%y",this.raw_points[d[b].id].y).replace("%x",
|
||||||
|
this.raw_points[d[b].id].x),0==h%2?a.appendChild(document.createTextNode(c[h])):(g=this.createElement("tspan",{dy:"-5"}),g.appendChild(document.createTextNode(c[h])),a.appendChild(g));g=this.createElement("path",{stroke:"black","stroke-width":2,fill:"white",opacity:0.5});f.appendChild(g);f.appendChild(a);h=d[b].x-a.getBoundingClientRect().width/2;c=this.parent_holder.offsetHeight-d[b].y-this.marginTop-this.marginBottom;var m=a.getBoundingClientRect().width,n=a.getBoundingClientRect().height;0>d[b].x-
|
||||||
|
a.getBoundingClientRect().width/2?(h=d[b].x+this.marginLeft+this.marginRight,c=this.parent_holder.offsetHeight-d[b].y+5,g.setAttribute("d","M "+(h-5)+" "+(c+5)+" L "+(h-5)+" "+(c-n/2+7.5)+" L "+(h-10)+" "+(c-n/2+5)+" L "+(h-5)+" "+(c-n/2+2.5)+" L "+(h-5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c+5)+" Z")):d[b].y+a.getBoundingClientRect().height+this.marginBottom+2>this.parent_holder.offsetHeight?(h=d[b].x+this.marginLeft+this.marginRight,c=this.parent_holder.offsetHeight-d[b].y+5,
|
||||||
|
g.setAttribute("d","M "+(h-5)+" "+(c+5)+" L "+(h-5)+" "+(c-n/2+7.5)+" L "+(h-this.marginBottom)+" "+(c-n/2+5)+" L "+(h-5)+" "+(c-n/2+2.5)+" L "+(h-5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c+5)+" Z"),h+m>this.parent_holder.offsetWidth&&(h=d[b].x-m-this.marginLeft-this.marginRight,c=this.parent_holder.offsetHeight-d[b].y+5,g.setAttribute("d","M "+(h-5)+" "+(c+5)+" L "+(h-5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n/2+2.5)+" L "+(h+m+10)+" "+(c-n/2+5)+" L "+(h+m+
|
||||||
|
5)+" "+(c-n/2+7.5)+" L "+(h+m+5)+" "+(c+5)+" Z"))):d[b].x+m/2+this.marginLeft+2>this.parent_holder.offsetWidth?(h=d[b].x-m-this.marginLeft-this.marginRight,c=this.parent_holder.offsetHeight-d[b].y+5,g.setAttribute("d","M "+(h-5)+" "+(c+5)+" L "+(h-5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n/2+2.5)+" L "+(h+m+10)+" "+(c-n/2+5)+" L "+(h+m+5)+" "+(c-n/2+7.5)+" L "+(h+m+5)+" "+(c+5)+" Z")):g.setAttribute("d","M "+(h-5)+" "+(c+5)+" L "+(h-5)+" "+(c-n+5)+" L "+(h+m+5)+" "+(c-n+5)+" L "+
|
||||||
|
(h+m+5)+" "+(c+5)+" L "+(h+m/2+2.5)+" "+(c+5)+" L "+(h+m/2)+" "+(c+10)+" L "+(h+m/2-2.5)+" "+(c+5)+" Z");a.setAttribute("x",h);a.setAttribute("y",c);f.setAttribute("display","none")}};
|
||||||
|
//# sourceMappingURL=timeline.min.js.map
|
8
timeline.min.js.map
Normal file
8
timeline.min.js.map
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user