diff --git a/timeline.js b/timeline.js index f7dea99..fdb0fee 100644 --- a/timeline.js +++ b/timeline.js @@ -13,6 +13,10 @@ * --------------------------------------------------------------------------------- */ +// TODO : +// * X legend +// * Y axis + var SVG = {}; SVG.ns = "http://www.w3.org/2000/svg"; SVG.xlinkns = "http://www.w3.org/1999/xlink"; @@ -122,7 +126,6 @@ SVG.newCoordinate = function(value, min, max, minValue, maxValue) { }; // Compute new X and Y values -// TODO : Partial application ? SVG.getNewXY = function (minX, maxX, minY, maxY) { return function (x, y) { return { @@ -266,7 +269,7 @@ SVG.init = function (arg) { SVG.x_callback = arg.x_callback; SVG.parent_holder.addEventListener('mousemove', function(e) { - // TODO + // TODO : Better over effect ? var evt = e || window.event; var rect = false; @@ -314,7 +317,6 @@ SVG.overEffect = function(x, y) { }; // Get the scale so that graph fits with window -// TODO : refactor SVG.scale = function(data) { var empty = true; for(graph in data) { @@ -329,8 +331,9 @@ SVG.scale = function(data) { var maxX = new Array(), maxY = new Array(); var circle = false, last_point = false, line = false; - var tmp_minX, tmp_minY, tmp_maxX, tmp_maxY + var tmp_minX, tmp_minY, tmp_maxX, tmp_maxY; + // Look for max and min values for both axis for(graph in data) { tmp_minX = false; tmp_minY = 0; @@ -365,32 +368,37 @@ SVG.scale = function(data) { maxX = Math.max.apply(null, maxX); maxY = Math.max.apply(null, maxY); + // Scale the grid, if needed var scale = SVG.getNewXY(minX, maxX, minY, maxY); - var coordinates = 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 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(SVG.grid === 'big' || SVG.grid === 'both') { - SVG.holder.getElementById('grid').setAttribute('width', coordinates.x); - SVG.holder.getElementById('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)))) - SVG.holder.getElementById('grid').setAttribute('y', big_coords.y); - SVG.holder.getElementById('grid').setAttribute('x', big_coords.x); - SVG.holder.getElementById('grid').querySelector('path').setAttribute('d', 'M '+coordinates.x+' 0 L 0 0 0 '+coordinates.y); + var grid = SVG.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(SVG.grid === 'both') { - SVG.holder.getElementById('grid').querySelector('rect').setAttribute('width', coordinates.x); - SVG.holder.getElementById('grid').querySelector('rect').setAttribute('height', coordinates.y); + grid.querySelector('rect').setAttribute('width', coordinates.x); + grid.querySelector('rect').setAttribute('height', coordinates.y); } } if(SVG.grid === 'small' || SVG.grid === 'both') { coordinates.x = coordinates.x / 10; coordinates.y = coordinates.y / 10; - SVG.holder.getElementById('smallGrid').setAttribute('width', coordinates.x); - SVG.holder.getElementById('smallGrid').setAttribute('height', coordinates.y); + var grid = SVG.holder.getElementById('smallGrid'); + grid.setAttribute('width', coordinates.x); + grid.setAttribute('height', coordinates.y); if(SVG.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)))); - SVG.holder.getElementById('smallGrid').setAttribute('y', small_coords.y); - SVG.holder.getElementById('smallGrid').setAttribute('x', small_coords.x); + grid.setAttribute('y', small_coords.y); + grid.setAttribute('x', small_coords.x); } - SVG.holder.getElementById('smallGrid').querySelector('path').setAttribute('d', 'M '+coordinates.x+' 0 L 0 0 0 '+coordinates.y); + grid.querySelector('path').setAttribute('d', 'M '+coordinates.x+' 0 L 0 0 0 '+coordinates.y); } /* Draw axis */ @@ -404,7 +412,6 @@ SVG.scale = function(data) { }; // Draw graphs -// TODO : Finish refactor SVG.draw = function() { var scale = SVG.scale(SVG.raw_points); var x, y, path; diff --git a/timeline.min.js b/timeline.min.js index 8342972..1aece20 100644 --- a/timeline.min.js +++ b/timeline.min.js @@ -1 +1 @@ -var SVG={};SVG.ns="http://www.w3.org/2000/svg";SVG.xlinkns="http://www.w3.org/1999/xlink";SVG.marginBottom=10;SVG.marginTop=15;SVG.marginLeft=10;SVG.marginRight=10;SVG.rounded=false;SVG.x_axis=false;SVG.parent_holder=false;SVG.holder=false;SVG.g=false;SVG.axis=false;SVG.raw_points=[];SVG.labels=[];SVG.click=[];SVG.x_callback=false;SVG.createElement=function(b,a){var c=document.createElementNS(SVG.ns,b);for(attr in a){c.setAttribute(attr,a[attr])}return c};SVG.hasClass=function(b,a){return(" "+b.getAttribute("class")+" ").indexOf(" "+a+" ")>-1};SVG.addGraph=function(b,a){SVG.raw_points[b]={};SVG.raw_points[b].color=a;SVG.raw_points[b].data=new Array();SVG.labels[b]=new Array();SVG.click[b]=new Array()};SVG.hasGraph=function(a){if(SVG.raw_points[a]===undefined){return false}else{return true}};SVG.clearGraphData=function(a){if(typeof(a)==="undefined"){SVG.raw_points=[];SVG.labels=[];SVG.click=[]}else{SVG.raw_points[a].data=new Array();SVG.labels[a]=new Array();SVG.click[a]=new Array()}};SVG.addPoints=function(c,b){b.sort(function(e,d){if(e.x=0;--g){p[g]=(d[g]-j[g]*p[g+1])/k[g]}for(var g=0;gj||j===false){j=x}if(yh||h===false){h=y}}p.push(k);n.push(i);o.push(j);m.push(h)}p=Math.min.apply(null,p);n=Math.min.apply(null,n);o=Math.max.apply(null,o);m=Math.max.apply(null,m);var r=SVG.getNewXY(p,o,n,m);var b=r(Math.pow(10,Math.floor(Math.log(o-p)/Math.log(10))),Math.pow(10,Math.floor(Math.log(m-n)/Math.log(10))));if(SVG.grid==="big"||SVG.grid==="both"){SVG.holder.getElementById("grid").setAttribute("width",b.x);SVG.holder.getElementById("grid").setAttribute("height",b.y);var c=r(Math.floor(p/Math.pow(10,Math.floor(Math.log(o-p)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(o-p)/Math.log(10))),Math.floor(n/Math.pow(10,Math.floor(Math.log(m-n)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(m-n)/Math.log(10))));SVG.holder.getElementById("grid").setAttribute("y",c.y);SVG.holder.getElementById("grid").setAttribute("x",c.x);SVG.holder.getElementById("grid").querySelector("path").setAttribute("d","M "+b.x+" 0 L 0 0 0 "+b.y);if(SVG.grid==="both"){SVG.holder.getElementById("grid").querySelector("rect").setAttribute("width",b.x);SVG.holder.getElementById("grid").querySelector("rect").setAttribute("height",b.y)}}if(SVG.grid==="small"||SVG.grid==="both"){b.x=b.x/10;b.y=b.y/10;SVG.holder.getElementById("smallGrid").setAttribute("width",b.x);SVG.holder.getElementById("smallGrid").setAttribute("height",b.y);if(SVG.grid==="small"){var e=r(Math.floor(p/Math.pow(10,Math.floor(Math.log(o-p)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(o-p)/Math.log(10))),Math.floor(n/Math.pow(10,Math.floor(Math.log(m-n)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(m-n)/Math.log(10))));SVG.holder.getElementById("smallGrid").setAttribute("y",e.y);SVG.holder.getElementById("smallGrid").setAttribute("x",e.x)}SVG.holder.getElementById("smallGrid").querySelector("path").setAttribute("d","M "+b.x+" 0 L 0 0 0 "+b.y)}if(SVG.x_axis===true){y=r(0,0).y;SVG.axis.setAttribute("y1",y);SVG.axis.setAttribute("y2",y)}return r};SVG.draw=function(){var t=SVG.scale(SVG.raw_points);var h,f,m;var l,k;var d;for(var c in SVG.raw_points){h=new Array();f=new Array();m="";for(var n=0;n","").split("");for(var o=0;o]+)>)/ig,"").replace("%y",SVG.raw_points[c].data[n][1]).replace("%x",SVG.raw_points[c].data[n][0]);if(o%2==0){d.appendChild(document.createTextNode(j[o]))}else{var r=SVG.createElement("tspan",{dy:"-5"});r.appendChild(document.createTextNode(j[o]));d.appendChild(r)}}m=SVG.createElement("path",{stroke:"black","stroke-width":2,fill:"white",opacity:0.5});q.appendChild(m);q.appendChild(d);var s=h[n]-d.getBoundingClientRect().width/2;var a=SVG.parent_holder.offsetHeight-f[n]-20;var e=d.getBoundingClientRect().width;var p=d.getBoundingClientRect().height;if(h[n]-d.getBoundingClientRect().width/2<0){s=h[n]+20;a=SVG.parent_holder.offsetHeight-f[n]+5;m.setAttribute("d","M "+(s-5)+" "+(a+5)+" L "+(s-5)+" "+(a-p/2+7.5)+" L "+(s-10)+" "+(a-p/2+5)+" L "+(s-5)+" "+(a-p/2+2.5)+" L "+(s-5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a+5)+" Z")}else{if(f[n]+d.getBoundingClientRect().height+12>SVG.parent_holder.offsetHeight){s=h[n]+20;a=SVG.parent_holder.offsetHeight-f[n]+5;m.setAttribute("d","M "+(s-5)+" "+(a+5)+" L "+(s-5)+" "+(a-p/2+7.5)+" L "+(s-10)+" "+(a-p/2+5)+" L "+(s-5)+" "+(a-p/2+2.5)+" L "+(s-5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a+5)+" Z");if(s+e>SVG.parent_holder.offsetWidth){s=h[n]-e-20;a=SVG.parent_holder.offsetHeight-f[n]+5;m.setAttribute("d","M "+(s-5)+" "+(a+5)+" L "+(s-5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p/2+2.5)+" L "+(s+e+10)+" "+(a-p/2+5)+" L "+(s+e+5)+" "+(a-p/2+7.5)+" L "+(s+e+5)+" "+(a+5)+" Z")}}else{if(h[n]+e/2+12>SVG.parent_holder.offsetWidth){s=h[n]-e-20;a=SVG.parent_holder.offsetHeight-f[n]+5;m.setAttribute("d","M "+(s-5)+" "+(a+5)+" L "+(s-5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p/2+2.5)+" L "+(s+e+10)+" "+(a-p/2+5)+" L "+(s+e+5)+" "+(a-p/2+7.5)+" L "+(s+e+5)+" "+(a+5)+" Z")}else{m.setAttribute("d","M "+(s-5)+" "+(a+5)+" L "+(s-5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a+5)+" L "+(s+e/2+2.5)+" "+(a+5)+" L "+(s+e/2)+" "+(a+10)+" L "+(s+e/2-2.5)+" "+(a+5)+" Z")}}}d.setAttribute("x",s);d.setAttribute("y",a);q.setAttribute("display","none")}}for(var n=0;n=-5&&z<=5&&z>=-5){SVG.holder.getElementById(this.getAttribute("id").replace("over","point")).onclick()}}})(h[n],f[n]);if(SVG.x_callback!==false){d=SVG.createElement("text",{"class":"legend_x",fill:"gray",transform:"translate(0, "+SVG.parent_holder.offsetHeight+") scale(1, -1)"});d.appendChild(document.createTextNode(SVG.x_callback(h[n])));SVG.g.appendChild(d);d.setAttribute("x",h[n]-d.getBoundingClientRect().width/2+2.5);var u=t(0,0).y;d.setAttribute("y",SVG.parent_holder.offsetHeight-SVG.marginBottom-u);d=SVG.createElement("line",{"class":"legend_x",stroke:"gray","stroke-width":2,x1:h[n],x2:h[n],y1:u-5,y2:u+5});SVG.g.appendChild(d)}}}};var old=window.onresize||function(){};window.onresize=function(){old();if(SVG.g!==false){SVG.g.setAttribute("transform","translate(0, "+SVG.parent_holder.offsetHeight+") scale(1, -1)");if(SVG.x_axis===true){SVG.axis.setAttribute("x2",SVG.parent_holder.offsetWidth-13-SVG.marginRight)}[].forEach.call(SVG.holder.querySelectorAll(".label, .over, .point, .line, .graph, .legend_x"),function(a){a.parentNode.removeChild(a)});SVG.draw()}}; \ No newline at end of file +var SVG={};SVG.ns="http://www.w3.org/2000/svg";SVG.xlinkns="http://www.w3.org/1999/xlink";SVG.marginBottom=10;SVG.marginTop=15;SVG.marginLeft=10;SVG.marginRight=10;SVG.rounded=false;SVG.x_axis=false;SVG.parent_holder=false;SVG.holder=false;SVG.g=false;SVG.axis=false;SVG.raw_points=[];SVG.labels=[];SVG.click=[];SVG.x_callback=false;SVG.createElement=function(b,a){var c=document.createElementNS(SVG.ns,b);for(attr in a){c.setAttribute(attr,a[attr])}return c};SVG.hasClass=function(b,a){return(" "+b.getAttribute("class")+" ").indexOf(" "+a+" ")>-1};SVG.addGraph=function(b,a){SVG.raw_points[b]={};SVG.raw_points[b].color=a;SVG.raw_points[b].data=new Array();SVG.labels[b]=new Array();SVG.click[b]=new Array()};SVG.hasGraph=function(a){if(SVG.raw_points[a]===undefined){return false}else{return true}};SVG.clearGraphData=function(a){if(typeof(a)==="undefined"){SVG.raw_points=[];SVG.labels=[];SVG.click=[]}else{SVG.raw_points[a].data=new Array();SVG.labels[a]=new Array();SVG.click[a]=new Array()}};SVG.addPoints=function(c,b){b.sort(function(e,d){if(e.x=0;--g){p[g]=(d[g]-j[g]*p[g+1])/k[g]}for(var g=0;gk||k===false){k=x}if(yi||i===false){i=y}}r.push(l);o.push(j);p.push(k);n.push(i)}r=Math.min.apply(null,r);o=Math.min.apply(null,o);p=Math.max.apply(null,p);n=Math.max.apply(null,n);var u=SVG.getNewXY(r,p,o,n);var q=u(Math.pow(10,Math.floor(Math.log(p-r)/Math.log(10))),Math.pow(10,Math.floor(Math.log(n-o)/Math.log(10))));var s=u(0,0);var c={x:q.x-s.x,y:q.y-s.y};if(SVG.grid==="big"||SVG.grid==="both"){var a=SVG.holder.getElementById("grid");a.setAttribute("width",c.x);a.setAttribute("height",c.y);var d=u(Math.floor(r/Math.pow(10,Math.floor(Math.log(p-r)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(p-r)/Math.log(10))),Math.floor(o/Math.pow(10,Math.floor(Math.log(n-o)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(n-o)/Math.log(10))));a.setAttribute("y",d.y);a.setAttribute("x",d.x);a.querySelector("path").setAttribute("d","M "+c.x+" 0 L 0 0 0 "+c.y);if(SVG.grid==="both"){a.querySelector("rect").setAttribute("width",c.x);a.querySelector("rect").setAttribute("height",c.y)}}if(SVG.grid==="small"||SVG.grid==="both"){c.x=c.x/10;c.y=c.y/10;var a=SVG.holder.getElementById("smallGrid");a.setAttribute("width",c.x);a.setAttribute("height",c.y);if(SVG.grid==="small"){var f=u(Math.floor(r/Math.pow(10,Math.floor(Math.log(p-r)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(p-r)/Math.log(10))),Math.floor(o/Math.pow(10,Math.floor(Math.log(n-o)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(n-o)/Math.log(10))));a.setAttribute("y",f.y);a.setAttribute("x",f.x)}a.querySelector("path").setAttribute("d","M "+c.x+" 0 L 0 0 0 "+c.y)}if(SVG.x_axis===true){y=u(0,0).y;SVG.axis.setAttribute("y1",y);SVG.axis.setAttribute("y2",y)}return u};SVG.draw=function(){var t=SVG.scale(SVG.raw_points);var h,f,m;var l,k;var d;for(var c in SVG.raw_points){h=new Array();f=new Array();m="";for(var n=0;n","").split("");for(var o=0;o]+)>)/ig,"").replace("%y",SVG.raw_points[c].data[n][1]).replace("%x",SVG.raw_points[c].data[n][0]);if(o%2==0){d.appendChild(document.createTextNode(j[o]))}else{var r=SVG.createElement("tspan",{dy:"-5"});r.appendChild(document.createTextNode(j[o]));d.appendChild(r)}}m=SVG.createElement("path",{stroke:"black","stroke-width":2,fill:"white",opacity:0.5});q.appendChild(m);q.appendChild(d);var s=h[n]-d.getBoundingClientRect().width/2;var a=SVG.parent_holder.offsetHeight-f[n]-20;var e=d.getBoundingClientRect().width;var p=d.getBoundingClientRect().height;if(h[n]-d.getBoundingClientRect().width/2<0){s=h[n]+20;a=SVG.parent_holder.offsetHeight-f[n]+5;m.setAttribute("d","M "+(s-5)+" "+(a+5)+" L "+(s-5)+" "+(a-p/2+7.5)+" L "+(s-10)+" "+(a-p/2+5)+" L "+(s-5)+" "+(a-p/2+2.5)+" L "+(s-5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a+5)+" Z")}else{if(f[n]+d.getBoundingClientRect().height+12>SVG.parent_holder.offsetHeight){s=h[n]+20;a=SVG.parent_holder.offsetHeight-f[n]+5;m.setAttribute("d","M "+(s-5)+" "+(a+5)+" L "+(s-5)+" "+(a-p/2+7.5)+" L "+(s-10)+" "+(a-p/2+5)+" L "+(s-5)+" "+(a-p/2+2.5)+" L "+(s-5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a+5)+" Z");if(s+e>SVG.parent_holder.offsetWidth){s=h[n]-e-20;a=SVG.parent_holder.offsetHeight-f[n]+5;m.setAttribute("d","M "+(s-5)+" "+(a+5)+" L "+(s-5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p/2+2.5)+" L "+(s+e+10)+" "+(a-p/2+5)+" L "+(s+e+5)+" "+(a-p/2+7.5)+" L "+(s+e+5)+" "+(a+5)+" Z")}}else{if(h[n]+e/2+12>SVG.parent_holder.offsetWidth){s=h[n]-e-20;a=SVG.parent_holder.offsetHeight-f[n]+5;m.setAttribute("d","M "+(s-5)+" "+(a+5)+" L "+(s-5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p/2+2.5)+" L "+(s+e+10)+" "+(a-p/2+5)+" L "+(s+e+5)+" "+(a-p/2+7.5)+" L "+(s+e+5)+" "+(a+5)+" Z")}else{m.setAttribute("d","M "+(s-5)+" "+(a+5)+" L "+(s-5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a-p+5)+" L "+(s+e+5)+" "+(a+5)+" L "+(s+e/2+2.5)+" "+(a+5)+" L "+(s+e/2)+" "+(a+10)+" L "+(s+e/2-2.5)+" "+(a+5)+" Z")}}}d.setAttribute("x",s);d.setAttribute("y",a);q.setAttribute("display","none")}}for(var n=0;n=-5&&z<=5&&z>=-5){SVG.holder.getElementById(this.getAttribute("id").replace("over","point")).onclick()}}})(h[n],f[n]);if(SVG.x_callback!==false){d=SVG.createElement("text",{"class":"legend_x",fill:"gray",transform:"translate(0, "+SVG.parent_holder.offsetHeight+") scale(1, -1)"});d.appendChild(document.createTextNode(SVG.x_callback(h[n])));SVG.g.appendChild(d);d.setAttribute("x",h[n]-d.getBoundingClientRect().width/2+2.5);var u=t(0,0).y;d.setAttribute("y",SVG.parent_holder.offsetHeight-SVG.marginBottom-u);d=SVG.createElement("line",{"class":"legend_x",stroke:"gray","stroke-width":2,x1:h[n],x2:h[n],y1:u-5,y2:u+5});SVG.g.appendChild(d)}}}};var old=window.onresize||function(){};window.onresize=function(){old();if(SVG.g!==false){SVG.g.setAttribute("transform","translate(0, "+SVG.parent_holder.offsetHeight+") scale(1, -1)");if(SVG.x_axis===true){SVG.axis.setAttribute("x2",SVG.parent_holder.offsetWidth-13-SVG.marginRight)}[].forEach.call(SVG.holder.querySelectorAll(".label, .over, .point, .line, .graph, .legend_x"),function(a){a.parentNode.removeChild(a)});SVG.draw()}}; \ No newline at end of file