diff --git a/timeline.js b/timeline.js index 9baac54..f56d9e7 100644 --- a/timeline.js +++ b/timeline.js @@ -13,32 +13,114 @@ * --------------------------------------------------------------------------------- */ -var Timeline = {}; -Timeline.ns = "http://www.w3.org/2000/svg"; -Timeline.xlinkns = "http://www.w3.org/1999/xlink"; -Timeline.marginBottom = 10; -Timeline.marginTop = 15; -Timeline.marginLeft = 10; -Timeline.marginRight = 10; -Timeline.rounded = false; -Timeline.x_axis = false; -Timeline.fill = true; -Timeline.line = 'line'; -Timeline.dashed_style = '5, 5'; +/* 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"; -Timeline.parent_holder = false; -Timeline.holder = false; -Timeline.g = false; -Timeline.axis = false; -Timeline.graphs = []; -Timeline.raw_points = []; -Timeline.x_callback = false; + 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; + + 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); + + var svg = this.createElement('svg:svg', { 'width': arg.width, 'height': arg.height }); + 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; +} // Create an element "element" with the attributes "attrs" -Timeline.createElement = function (element, attrs) { - var el = document.createElementNS(Timeline.ns, element); +Timeline.prototype.createElement = function (element, attrs) { + var el = document.createElementNS(this.ns, element); for(attr in attrs) { el.setAttribute(attr, attrs[attr]); } @@ -47,18 +129,18 @@ Timeline.createElement = function (element, attrs) { }; // Check wether the element "element" has class "class" -Timeline.hasClass = function (element, cls) { +Timeline.prototype.hasClass = function (element, cls) { return (' ' + element.getAttribute('class') + ' ').indexOf(' ' + cls + ' ') > -1; }; // Add a new graph to the Timeline -Timeline.addGraph = function (graph, color) { - Timeline.graphs[graph] = color; +Timeline.prototype.addGraph = function (graph, color) { + this.graphs[graph] = color; }; // Test wether a graph of name "graph" already exists -Timeline.hasGraph = function (graph) { - if(typeof(Timeline.graphs[graph]) === 'undefined') { +Timeline.prototype.hasGraph = function (graph) { + if(typeof(this.graphs[graph]) === 'undefined') { return false; } else { @@ -67,22 +149,22 @@ Timeline.hasGraph = function (graph) { }; // Clear the specified graph data, or completely clear all the graph data -Timeline.clearGraph = function (graph) { +Timeline.prototype.clearGraph = function (graph) { if(typeof(graph) === 'undefined') { - Timeline.raw_points = []; - Timeline.graphs = []; + this.raw_points = []; + this.graphs = []; } else { - for(var i = 0; i < Timeline.raw_points.length; i++) { - if(Timeline.raw_points[i].graph === graph) { - Timeline.raw_points[i] = undefined; + 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.addPoints = function (graph, data) { +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') { @@ -97,10 +179,10 @@ Timeline.addPoints = function (graph, data) { else { insert.click = false; } - Timeline.raw_points.push(insert); + this.raw_points.push(insert); } - Timeline.raw_points.sort(function (a, b) { + this.raw_points.sort(function (a, b) { if(a.x < b.x) { return -1; } @@ -114,23 +196,24 @@ Timeline.addPoints = function (graph, data) { }; // Compute new coordinates, knowing the min and max value to fit the graph in the container -Timeline.newCoordinate = function(value, min, max, minValue, maxValue) { +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.getNewXY = function (minX, maxX, minY, maxY) { +Timeline.prototype.getNewXY = function (minX, maxX, minY, maxY) { + var obj = this; return function (x, y) { return { - 'x': Timeline.newCoordinate(x, minX, maxX, Timeline.marginLeft, Timeline.parent_holder.offsetWidth - Timeline.marginRight), - 'y': Timeline.newCoordinate(y, minY, maxY, 2*Timeline.marginBottom, Timeline.parent_holder.offsetHeight - Timeline.marginTop) + '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.getControlPoints = function (data) { +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(); @@ -185,90 +268,9 @@ Timeline.getControlPoints = function (data) { return {p1:p1, p2:p2}; }; -/* 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 - */ -Timeline.init = function (arg) { - if(!document.implementation.hasFeature("http://www.w3.org/TR/Timeline11/feature#Image", "1.1")) { - alert("ERROR : Your browser does not support embedded Timeline."); - } - Timeline.parent_holder = document.getElementById(arg.id); - - var svg = Timeline.createElement('svg:svg', { 'width': arg.width, 'height': arg.height }); - svg.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', Timeline.xlinkns); - Timeline.parent_holder.appendChild(svg); - - Timeline.holder = Timeline.parent_holder.querySelector('svg'); - - defs = Timeline.createElement('defs', {}); - Timeline.holder.appendChild(defs); - - if(arg.grid === 'small' || arg.grid === 'both') { - var small_grid_pattern = Timeline.createElement('pattern', { 'id': 'smallGrid', 'width': 8, 'height': 8, 'patternUnits': 'userSpaceOnUse' }); - - var small_grid_path = Timeline.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 = Timeline.createElement('pattern', { 'id': 'grid', 'width': 80, 'height': 80, 'patternUnits': 'userSpaceOnUse' }); - - if(arg.grid === 'both') { - var grid_rect = Timeline.createElement('rect', {'width': 80, 'height': 80, 'fill': 'url(#smallGrid)' }); - grid_pattern.appendChild(grid_rect); - } - - var grid_path = Timeline.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); - } - Timeline.grid = arg.grid; - - - var marker = Timeline.createElement('marker', {'id': 'markerArrow', 'markerWidth': 13, 'markerHeight': 13, 'refX': 2, 'refY': 6, 'orient': 'auto' }); - var marker_path = Timeline.createElement('path', {'d': 'M2,2 L2,11 L10,6 L2,2', 'fill': 'gray' }); - marker.appendChild(marker_path); - defs.appendChild(marker); - - Timeline.g = Timeline.createElement('g', {'transform': 'translate(0, ' + Timeline.parent_holder.offsetHeight + ') scale(1, -1)'}); - Timeline.holder.appendChild(Timeline.g); - - if(arg.x_axis === true) { - Timeline.axis = Timeline.createElement('line', {'x1': Timeline.marginLeft, 'y1': Timeline.parent_holder.offsetHeight / 2 + 1.5, 'x2': Timeline.parent_holder.offsetWidth - 13 - Timeline.marginRight, 'y2': Timeline.parent_holder.offsetHeight / 2 + 1.5, 'stroke': 'gray', 'stroke-width': 3, 'marker-end': 'url("#markerArrow")'}); - Timeline.g.appendChild(Timeline.axis); - } - - if(Timeline.grid !== "none") { - var grid = Timeline.createElement('rect', {'width': '100%', 'height': '100%'}); - if(Timeline.grid === 'big' || Timeline.grid === 'both') { - grid.setAttribute('fill', 'url(#grid)'); - } - else { - grid.setAttribute('fill', 'url(#smallGrid)'); - } - Timeline.g.appendChild(grid); - } - - Timeline.rounded = arg.rounded; - Timeline.x_axis = arg.x_axis; - Timeline.line = arg.line; - Timeline.fill = arg.fill; - - Timeline.x_callback = arg.x_callback; -}; // Get the scale so that graph fits with window -Timeline.scale = function(data) { +Timeline.prototype.scale = function(data) { var empty = true; for(graph in data) { empty = false; @@ -299,12 +301,12 @@ Timeline.scale = function(data) { } // Scale the grid, if needed - var scale = Timeline.getNewXY(minX, maxX, minY, maxY); + 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(Timeline.grid === 'big' || Timeline.grid === 'both') { - var grid = Timeline.holder.getElementById('grid'); + 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)))); @@ -312,18 +314,18 @@ Timeline.scale = function(data) { grid.setAttribute('x', big_coords.x); grid.querySelector('path').setAttribute('d', 'M '+coordinates.x+' 0 L 0 0 0 '+coordinates.y); - if(Timeline.grid === 'both') { + if(this.grid === 'both') { grid.querySelector('rect').setAttribute('width', coordinates.x); grid.querySelector('rect').setAttribute('height', coordinates.y); } } - if(Timeline.grid === 'small' || Timeline.grid === 'both') { + if(this.grid === 'small' || this.grid === 'both') { coordinates.x = coordinates.x / 10; coordinates.y = coordinates.y / 10; - var grid = Timeline.holder.getElementById('smallGrid'); + var grid = this.holder.getElementById('smallGrid'); grid.setAttribute('width', coordinates.x); grid.setAttribute('height', coordinates.y); - if(Timeline.grid === 'small') { + 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); @@ -332,41 +334,42 @@ Timeline.scale = function(data) { } /* Draw axis */ - if(Timeline.x_axis === true) { + if(this.x_axis === true) { y = scale(0, 0).y; - Timeline.axis.setAttribute('y1', y); - Timeline.axis.setAttribute('y2', y); + this.axis.setAttribute('y1', y); + this.axis.setAttribute('y2', y); } return scale; }; // Draw graphs -Timeline.draw = function() { - var scale = Timeline.scale(Timeline.raw_points); +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 < Timeline.raw_points.length; point++) { - var tmp = scale(Timeline.raw_points[point].x, Timeline.raw_points[point].y); - points.push({'id': point, 'x': tmp.x, 'y': tmp.y, 'graph': Timeline.raw_points[point].graph, 'click': Timeline.raw_points[point].click, 'label': Timeline.raw_points[point].label}); + 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 Timeline.graphs) { + for(var graph in this.graphs) { var filtered_points = points.filter(function(el) { return el.graph == graph; }); path = ''; // Draw line - if(Timeline.rounded === true) { + 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 = Timeline.getControlPoints(x); - py = Timeline.getControlPoints(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+' '; } @@ -377,25 +380,25 @@ Timeline.draw = function() { } } - if(Timeline.line !== 'none') { - element = Timeline.createElement('path', {'class': 'line', 'stroke': Timeline.graphs[graph], 'stroke-width': 2, 'fill': 'none', 'd': 'M '+filtered_points[0].x+' '+filtered_points[0].y+' '+path}); - if(Timeline.line === 'dashed') { - element.setAttribute('style', 'stroke-dasharray: '+Timeline.dashed_style); + if(this.line !== 'none') { + 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); } - Timeline.g.appendChild(element); + this.g.appendChild(element); } // Draw fill - if(Timeline.fill) { - element = Timeline.createElement('path', {'class': 'graph', 'fill': Timeline.graphs[graph], 'opacity': '0.25', 'stroke': 'none', 'd': 'M '+filtered_points[0].x+' '+2*Timeline.marginBottom+' L '+filtered_points[0].x+' '+filtered_points[0].y+' '+ path + ' L '+filtered_points[filtered_points.length - 1].x+' '+2*Timeline.marginBottom+' Z' }); - Timeline.g.insertBefore(element, Timeline.g.querySelectorAll('.over')[0]); + 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 = Timeline.createElement('rect', {'class': 'over', 'id': 'over_'+point, 'y': 0, 'fill': 'white', 'opacity': 0, 'height': '100%'}); + 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; @@ -420,47 +423,47 @@ Timeline.draw = function() { } if(point == points.length - 1) { - rect.setAttribute('width', Timeline.parent_holder.offsetWidth - (points[point].x + points[point - 1].x)/2 + 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 + Timeline.marginLeft + 1); + 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); } - Timeline.g.appendChild(rect); + this.g.appendChild(rect); rect.addEventListener('mouseover', (function(arg) { return function() { for(var i = 0; i < arg.length; i++) { - Timeline.holder.getElementById('point_'+arg[i]).setAttribute('r', '6'); - Timeline.holder.getElementById('label_'+arg[i]).setAttribute('display', 'block'); + 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(Timeline.holder.querySelectorAll('.point'), function(el) { + [].forEach.call(obj.holder.querySelectorAll('.point'), function(el) { el.setAttribute('r', '4'); }); - [].forEach.call(Timeline.holder.querySelectorAll('.label'), function(el) { + [].forEach.call(obj.holder.querySelectorAll('.label'), function(el) { el.setAttribute('display', 'none'); }); }); - if(Timeline.x_callback !== false && points[point].x + 2.5 < Timeline.parent_holder.offsetWidth - Timeline.marginRight) { - element = Timeline.createElement('text', {'class': 'legend_x', 'fill': 'gray', 'transform': 'translate(0, ' + Timeline.parent_holder.offsetHeight + ') scale(1, -1)'}); - element.appendChild(document.createTextNode(Timeline.x_callback(Timeline.raw_points[point].x))); - Timeline.g.appendChild(element); + 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', Timeline.parent_holder.offsetHeight - Timeline.marginBottom - y_zero); + element.setAttribute('y', this.parent_holder.offsetHeight - this.marginBottom - y_zero); - element = Timeline.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}); - Timeline.g.appendChild(element); + 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; @@ -468,12 +471,12 @@ Timeline.draw = function() { } // Draw points and labels - for(var graph in Timeline.graphs) { + 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 = Timeline.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': Timeline.graphs[graph], 'stroke-width': 2}); - Timeline.g.insertBefore(element, Timeline.g.querySelectorAll('.label')[0]); + 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; @@ -481,63 +484,63 @@ Timeline.draw = function() { element.addEventListener('mouseover', function() { this.setAttribute('r', '6'); - Timeline.holder.getElementById(this.getAttribute('id').replace('point', 'label')).setAttribute('display', 'block'); + obj.holder.getElementById(this.getAttribute('id').replace('point', 'label')).setAttribute('display', 'block'); }); if(filtered_points[point].label !== '') { - var g = Timeline.createElement('g', { 'class': 'label', 'id': 'label_'+filtered_points[point].id, 'transform': 'translate(0, ' + Timeline.parent_holder.offsetHeight + ') scale(1, -1)'}); - Timeline.g.appendChild(g); + 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() { - Timeline.holder.getElementById(this.getAttribute('id').replace('label', 'point')).setAttribute('r', '6'); + obj.holder.getElementById(this.getAttribute('id').replace('label', 'point')).setAttribute('r', '6'); this.setAttribute('display', 'block'); }); - element = Timeline.createElement('text', {}); + element = this.createElement('text', {}); var text = filtered_points[point].label.replace('', '').split(''); for(var i = 0; i < text.length; i++) { - text[i] = text[i].replace(/(<([^>]+)>)/ig,"").replace('%y', Timeline.raw_points[filtered_points[point].id].y).replace('%x', Timeline.raw_points[filtered_points[point].id].x); + 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 = Timeline.createElement('tspan', {'dy': '-5'}); + var tmp = this.createElement('tspan', {'dy': '-5'}); tmp.appendChild(document.createTextNode(text[i])); element.appendChild(tmp); } } - path = Timeline.createElement('path', {'stroke': 'black', 'stroke-width': 2, 'fill': 'white', 'opacity': 0.5}); + 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 = Timeline.parent_holder.offsetHeight - filtered_points[point].y - 20; + var y_text = this.parent_holder.offsetHeight - filtered_points[point].y - 20; 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 + 20; - y_text = Timeline.parent_holder.offsetHeight - filtered_points[point].y + 5; + 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 + 12 > Timeline.parent_holder.offsetHeight) { + else if(filtered_points[point].y + element.getBoundingClientRect().height + 12 > this.parent_holder.offsetHeight) { x_text = filtered_points[point].x + 20; - y_text = Timeline.parent_holder.offsetHeight - filtered_points[point].y + 5; + 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'); - if(x_text + element_width > Timeline.parent_holder.offsetWidth) { + if(x_text + element_width > this.parent_holder.offsetWidth) { x_text = filtered_points[point].y - element_width - 20; - y_text = Timeline.parent_holder.offsetHeight - filtered_points[point].y + 5; + 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 + 12 > Timeline.parent_holder.offsetWidth) { + else if(filtered_points[point].x + element_width / 2 + 12 > this.parent_holder.offsetWidth) { x_text = filtered_points[point].x - element_width - 20; - y_text = Timeline.parent_holder.offsetHeight - filtered_points[point].y + 5; + 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 { @@ -553,6 +556,7 @@ Timeline.draw = function() { } }; +// TODO var old = window.onresize || function () {}; window.onresize = function() { old(); diff --git a/timeline.min.js b/timeline.min.js index beec710..f0af5be 100644 --- a/timeline.min.js +++ b/timeline.min.js @@ -1 +1 @@ -var Timeline={};Timeline.ns="http://www.w3.org/2000/svg";Timeline.xlinkns="http://www.w3.org/1999/xlink";Timeline.marginBottom=10;Timeline.marginTop=15;Timeline.marginLeft=10;Timeline.marginRight=10;Timeline.rounded=false;Timeline.x_axis=false;Timeline.fill=true;Timeline.line="line";Timeline.dashed_style="5, 5";Timeline.parent_holder=false;Timeline.holder=false;Timeline.g=false;Timeline.axis=false;Timeline.graphs=[];Timeline.raw_points=[];Timeline.x_callback=false;Timeline.createElement=function(b,a){var c=document.createElementNS(Timeline.ns,b);for(attr in a){c.setAttribute(attr,a[attr])}return c};Timeline.hasClass=function(b,a){return(" "+b.getAttribute("class")+" ").indexOf(" "+a+" ")>-1};Timeline.addGraph=function(b,a){Timeline.graphs[b]=a};Timeline.hasGraph=function(a){if(typeof(Timeline.graphs[a])==="undefined"){return false}else{return true}};Timeline.clearGraph=function(b){if(typeof(b)==="undefined"){Timeline.raw_points=[];Timeline.graphs=[]}else{for(var a=0;a=0;--g){p[g]=(d[g]-j[g]*p[g+1])/k[g]}for(var g=0;gc||c===false){c=j[p].x}if(j[p].yb||b===false){b=j[p].y}}var f=Timeline.getNewXY(g,c,e,b);var i=f(Math.pow(10,Math.floor(Math.log(c-g)/Math.log(10))),Math.pow(10,Math.floor(Math.log(b-e)/Math.log(10))));var o=f(0,0);var n={x:i.x-o.x,y:i.y-o.y};if(Timeline.grid==="big"||Timeline.grid==="both"){var a=Timeline.holder.getElementById("grid");a.setAttribute("width",n.x);a.setAttribute("height",n.y);var h=f(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))),Math.floor(e/Math.pow(10,Math.floor(Math.log(b-e)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(b-e)/Math.log(10))));a.setAttribute("y",h.y);a.setAttribute("x",h.x);a.querySelector("path").setAttribute("d","M "+n.x+" 0 L 0 0 0 "+n.y);if(Timeline.grid==="both"){a.querySelector("rect").setAttribute("width",n.x);a.querySelector("rect").setAttribute("height",n.y)}}if(Timeline.grid==="small"||Timeline.grid==="both"){n.x=n.x/10;n.y=n.y/10;var a=Timeline.holder.getElementById("smallGrid");a.setAttribute("width",n.x);a.setAttribute("height",n.y);if(Timeline.grid==="small"){var m=f(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))),Math.floor(e/Math.pow(10,Math.floor(Math.log(b-e)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(b-e)/Math.log(10))));a.setAttribute("y",m.y);a.setAttribute("x",m.x)}a.querySelector("path").setAttribute("d","M "+n.x+" 0 L 0 0 0 "+n.y)}if(Timeline.x_axis===true){y=f(0,0).y;Timeline.axis.setAttribute("y1",y);Timeline.axis.setAttribute("y2",y)}return f};Timeline.draw=function(){var A=Timeline.scale(Timeline.raw_points);var t=[],o;var n,m;var d;for(var r=0;rt.length){break}q++}}for(var u=p+1;u","").split("");for(var u=0;u]+)>)/ig,"").replace("%y",Timeline.raw_points[j[r].id].y).replace("%x",Timeline.raw_points[j[r].id].x);if(u%2==0){d.appendChild(document.createTextNode(l[u]))}else{var w=Timeline.createElement("tspan",{dy:"-5"});w.appendChild(document.createTextNode(l[u]));d.appendChild(w)}}o=Timeline.createElement("path",{stroke:"black","stroke-width":2,fill:"white",opacity:0.5});v.appendChild(o);v.appendChild(d);var z=j[r].x-d.getBoundingClientRect().width/2;var a=Timeline.parent_holder.offsetHeight-j[r].y-20;var f=d.getBoundingClientRect().width;var s=d.getBoundingClientRect().height;if(j[r].x-d.getBoundingClientRect().width/2<0){z=j[r].x+20;a=Timeline.parent_holder.offsetHeight-j[r].y+5;o.setAttribute("d","M "+(z-5)+" "+(a+5)+" L "+(z-5)+" "+(a-s/2+7.5)+" L "+(z-10)+" "+(a-s/2+5)+" L "+(z-5)+" "+(a-s/2+2.5)+" L "+(z-5)+" "+(a-s+5)+" L "+(z+f+5)+" "+(a-s+5)+" L "+(z+f+5)+" "+(a+5)+" Z")}else{if(j[r].y+d.getBoundingClientRect().height+12>Timeline.parent_holder.offsetHeight){z=j[r].x+20;a=Timeline.parent_holder.offsetHeight-j[r].y+5;o.setAttribute("d","M "+(z-5)+" "+(a+5)+" L "+(z-5)+" "+(a-s/2+7.5)+" L "+(z-10)+" "+(a-s/2+5)+" L "+(z-5)+" "+(a-s/2+2.5)+" L "+(z-5)+" "+(a-s+5)+" L "+(z+f+5)+" "+(a-s+5)+" L "+(z+f+5)+" "+(a+5)+" Z");if(z+f>Timeline.parent_holder.offsetWidth){z=j[r].y-f-20;a=Timeline.parent_holder.offsetHeight-j[r].y+5;o.setAttribute("d","M "+(z-5)+" "+(a+5)+" L "+(z-5)+" "+(a-s+5)+" L "+(z+f+5)+" "+(a-s+5)+" L "+(z+f+5)+" "+(a-s/2+2.5)+" L "+(z+f+10)+" "+(a-s/2+5)+" L "+(z+f+5)+" "+(a-s/2+7.5)+" L "+(z+f+5)+" "+(a+5)+" Z")}}else{if(j[r].x+f/2+12>Timeline.parent_holder.offsetWidth){z=j[r].x-f-20;a=Timeline.parent_holder.offsetHeight-j[r].y+5;o.setAttribute("d","M "+(z-5)+" "+(a+5)+" L "+(z-5)+" "+(a-s+5)+" L "+(z+f+5)+" "+(a-s+5)+" L "+(z+f+5)+" "+(a-s/2+2.5)+" L "+(z+f+10)+" "+(a-s/2+5)+" L "+(z+f+5)+" "+(a-s/2+7.5)+" L "+(z+f+5)+" "+(a+5)+" Z")}else{o.setAttribute("d","M "+(z-5)+" "+(a+5)+" L "+(z-5)+" "+(a-s+5)+" L "+(z+f+5)+" "+(a-s+5)+" L "+(z+f+5)+" "+(a+5)+" L "+(z+f/2+2.5)+" "+(a+5)+" L "+(z+f/2)+" "+(a+10)+" L "+(z+f/2-2.5)+" "+(a+5)+" Z")}}}d.setAttribute("x",z);d.setAttribute("y",a);v.setAttribute("display","none")}}}};var old=window.onresize||function(){};window.onresize=function(){old();if(Timeline.g!==false){Timeline.g.setAttribute("transform","translate(0, "+Timeline.parent_holder.offsetHeight+") scale(1, -1)");if(Timeline.x_axis===true){Timeline.axis.setAttribute("x2",Timeline.parent_holder.offsetWidth-13-Timeline.marginRight)}[].forEach.call(Timeline.holder.querySelectorAll(".label, .over, .point, .line, .graph, .legend_x"),function(a){a.parentNode.removeChild(a)});Timeline.draw()}}; \ No newline at end of file +function Timeline(j){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;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(j.id);var h=this.createElement("svg:svg",{width:j.width,height:j.height});h.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink",this.xlinkns);this.parent_holder.appendChild(h);this.holder=this.parent_holder.querySelector("svg");defs=this.createElement("defs",{});this.holder.appendChild(defs);if(j.grid==="small"||j.grid==="both"){var i=this.createElement("pattern",{id:"smallGrid",width:8,height:8,patternUnits:"userSpaceOnUse"});var e=this.createElement("path",{d:"M 8 0 L 0 0 0 8",fill:"none",stroke:"gray","stroke-width":"0.5"});i.appendChild(e);defs.appendChild(i)}if(j.grid==="big"||j.grid==="both"){var d=this.createElement("pattern",{id:"grid",width:80,height:80,patternUnits:"userSpaceOnUse"});if(j.grid==="both"){var c=this.createElement("rect",{width:80,height:80,fill:"url(#smallGrid)"});d.appendChild(c)}var f=this.createElement("path",{d:"M 80 0 L 0 0 0 80",fill:"none",stroke:"gray","stroke-width":"1"});d.appendChild(f);defs.appendChild(d)}this.grid=j.grid;var g=this.createElement("marker",{id:"markerArrow",markerWidth:13,markerHeight:13,refX:2,refY:6,orient:"auto"});var b=this.createElement("path",{d:"M2,2 L2,11 L10,6 L2,2",fill:"gray"});g.appendChild(b);defs.appendChild(g);this.g=this.createElement("g",{transform:"translate(0, "+this.parent_holder.offsetHeight+") scale(1, -1)"});this.holder.appendChild(this.g);if(j.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 a=this.createElement("rect",{width:"100%",height:"100%"});if(this.grid==="big"||this.grid==="both"){a.setAttribute("fill","url(#grid)")}else{a.setAttribute("fill","url(#smallGrid)")}this.g.appendChild(a)}this.rounded=j.rounded;this.x_axis=j.x_axis;this.line=j.line;this.fill=j.fill;this.x_callback=j.x_callback}Timeline.prototype.createElement=function(b,a){var c=document.createElementNS(this.ns,b);for(attr in a){c.setAttribute(attr,a[attr])}return c};Timeline.prototype.hasClass=function(b,a){return(" "+b.getAttribute("class")+" ").indexOf(" "+a+" ")>-1};Timeline.prototype.addGraph=function(b,a){this.graphs[b]=a};Timeline.prototype.hasGraph=function(a){if(typeof(this.graphs[a])==="undefined"){return false}else{return true}};Timeline.prototype.clearGraph=function(b){if(typeof(b)==="undefined"){this.raw_points=[];this.graphs=[]}else{for(var a=0;a=0;--g){p[g]=(d[g]-j[g]*p[g+1])/k[g]}for(var g=0;gc||c===false){c=j[p].x}if(j[p].yb||b===false){b=j[p].y}}var f=this.getNewXY(g,c,e,b);var i=f(Math.pow(10,Math.floor(Math.log(c-g)/Math.log(10))),Math.pow(10,Math.floor(Math.log(b-e)/Math.log(10))));var o=f(0,0);var n={x:i.x-o.x,y:i.y-o.y};if(this.grid==="big"||this.grid==="both"){var a=this.holder.getElementById("grid");a.setAttribute("width",n.x);a.setAttribute("height",n.y);var h=f(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))),Math.floor(e/Math.pow(10,Math.floor(Math.log(b-e)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(b-e)/Math.log(10))));a.setAttribute("y",h.y);a.setAttribute("x",h.x);a.querySelector("path").setAttribute("d","M "+n.x+" 0 L 0 0 0 "+n.y);if(this.grid==="both"){a.querySelector("rect").setAttribute("width",n.x);a.querySelector("rect").setAttribute("height",n.y)}}if(this.grid==="small"||this.grid==="both"){n.x=n.x/10;n.y=n.y/10;var a=this.holder.getElementById("smallGrid");a.setAttribute("width",n.x);a.setAttribute("height",n.y);if(this.grid==="small"){var m=f(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))),Math.floor(e/Math.pow(10,Math.floor(Math.log(b-e)/Math.log(10))))*Math.pow(10,Math.floor(Math.log(b-e)/Math.log(10))));a.setAttribute("y",m.y);a.setAttribute("x",m.x)}a.querySelector("path").setAttribute("d","M "+n.x+" 0 L 0 0 0 "+n.y)}if(this.x_axis===true){y=f(0,0).y;this.axis.setAttribute("y1",y);this.axis.setAttribute("y2",y)}return f};Timeline.prototype.draw=function(){var B=this.scale(this.raw_points);var v=[],p;var o,n;var d;var l=this;for(var s=0;sv.length){break}r++}}for(var u=q+1;u","").split("");for(var u=0;u]+)>)/ig,"").replace("%y",this.raw_points[j[s].id].y).replace("%x",this.raw_points[j[s].id].x);if(u%2==0){d.appendChild(document.createTextNode(m[u]))}else{var z=this.createElement("tspan",{dy:"-5"});z.appendChild(document.createTextNode(m[u]));d.appendChild(z)}}p=this.createElement("path",{stroke:"black","stroke-width":2,fill:"white",opacity:0.5});w.appendChild(p);w.appendChild(d);var A=j[s].x-d.getBoundingClientRect().width/2;var a=this.parent_holder.offsetHeight-j[s].y-20;var f=d.getBoundingClientRect().width;var t=d.getBoundingClientRect().height;if(j[s].x-d.getBoundingClientRect().width/2<0){A=j[s].x+20;a=this.parent_holder.offsetHeight-j[s].y+5;p.setAttribute("d","M "+(A-5)+" "+(a+5)+" L "+(A-5)+" "+(a-t/2+7.5)+" L "+(A-10)+" "+(a-t/2+5)+" L "+(A-5)+" "+(a-t/2+2.5)+" L "+(A-5)+" "+(a-t+5)+" L "+(A+f+5)+" "+(a-t+5)+" L "+(A+f+5)+" "+(a+5)+" Z")}else{if(j[s].y+d.getBoundingClientRect().height+12>this.parent_holder.offsetHeight){A=j[s].x+20;a=this.parent_holder.offsetHeight-j[s].y+5;p.setAttribute("d","M "+(A-5)+" "+(a+5)+" L "+(A-5)+" "+(a-t/2+7.5)+" L "+(A-10)+" "+(a-t/2+5)+" L "+(A-5)+" "+(a-t/2+2.5)+" L "+(A-5)+" "+(a-t+5)+" L "+(A+f+5)+" "+(a-t+5)+" L "+(A+f+5)+" "+(a+5)+" Z");if(A+f>this.parent_holder.offsetWidth){A=j[s].y-f-20;a=this.parent_holder.offsetHeight-j[s].y+5;p.setAttribute("d","M "+(A-5)+" "+(a+5)+" L "+(A-5)+" "+(a-t+5)+" L "+(A+f+5)+" "+(a-t+5)+" L "+(A+f+5)+" "+(a-t/2+2.5)+" L "+(A+f+10)+" "+(a-t/2+5)+" L "+(A+f+5)+" "+(a-t/2+7.5)+" L "+(A+f+5)+" "+(a+5)+" Z")}}else{if(j[s].x+f/2+12>this.parent_holder.offsetWidth){A=j[s].x-f-20;a=this.parent_holder.offsetHeight-j[s].y+5;p.setAttribute("d","M "+(A-5)+" "+(a+5)+" L "+(A-5)+" "+(a-t+5)+" L "+(A+f+5)+" "+(a-t+5)+" L "+(A+f+5)+" "+(a-t/2+2.5)+" L "+(A+f+10)+" "+(a-t/2+5)+" L "+(A+f+5)+" "+(a-t/2+7.5)+" L "+(A+f+5)+" "+(a+5)+" Z")}else{p.setAttribute("d","M "+(A-5)+" "+(a+5)+" L "+(A-5)+" "+(a-t+5)+" L "+(A+f+5)+" "+(a-t+5)+" L "+(A+f+5)+" "+(a+5)+" L "+(A+f/2+2.5)+" "+(a+5)+" L "+(A+f/2)+" "+(a+10)+" L "+(A+f/2-2.5)+" "+(a+5)+" Z")}}}d.setAttribute("x",A);d.setAttribute("y",a);w.setAttribute("display","none")}}}};var old=window.onresize||function(){};window.onresize=function(){old();if(Timeline.g!==false){Timeline.g.setAttribute("transform","translate(0, "+Timeline.parent_holder.offsetHeight+") scale(1, -1)");if(Timeline.x_axis===true){Timeline.axis.setAttribute("x2",Timeline.parent_holder.offsetWidth-13-Timeline.marginRight)}[].forEach.call(Timeline.holder.querySelectorAll(".label, .over, .point, .line, .graph, .legend_x"),function(a){a.parentNode.removeChild(a)});Timeline.draw()}}; \ No newline at end of file