sean@0: <!DOCTYPE html> sean@0: <html> sean@0: <head> sean@0: <title> Issues </title> sean@0: <style type = text/css> sean@1: sean@1: * { sean@1: font-family: "Sans-serif"; sean@1: font-size: 14px; sean@1: } sean@1: sean@0: .svg div{ sean@1: font: 10px; sean@0: text-align: right; sean@0: float: left; sean@0: display: block; sean@0: padding: 10px; sean@0: margin: 10px; sean@0: color: white; sean@0: } sean@0: sean@0: .axis path, sean@0: sean@0: .axis line { sean@0: fill: none; sean@0: stroke: black; sean@0: stroke-width: 1px; sean@0: } sean@0: sean@0: .line { sean@0: fill: none; sean@1: stroke-width: 3px; sean@1: opacity: 1; sean@0: } sean@0: sean@0: .line.critical { sean@0: stroke: red; sean@0: } sean@0: sean@0: .line.critical.legend { sean@0: fill: red; sean@0: } sean@0: sean@0: .line.urgent { sean@0: stroke: orange; sean@0: } sean@0: sean@0: .line.urgent.legend { sean@0: fill: orange; sean@0: } sean@0: sean@0: .line.bug { sean@0: stroke: violet; sean@0: } sean@0: sean@0: .line.bug.legend { sean@0: fill: violet; sean@0: } sean@0: sean@0: .line.feature { sean@1: stroke: chartreuse; sean@1: style: stroke-dasharray; sean@0: } sean@0: sean@0: .line.feature.legend { sean@1: fill: chartreuse; sean@0: } sean@0: sean@0: .line.wish { sean@0: stroke: blue; sean@0: } sean@0: sean@0: .line.wish.legend { sean@0: fill: blue; sean@0: } sean@0: sean@0: .grid .tick { sean@0: stroke: lightgrey; sean@0: opacity: 0.7; sean@0: } sean@0: sean@0: .grid path { sean@0: stroke-width: 0; sean@0: } sean@0: sean@0: </style> sean@0: </head> sean@0: <body> sean@1: <div id="content" style="display: inline-block"></div> sean@0: <script type="text/javascript" src="d3.v3.min.js"></script> sean@0: <script type="text/javascript"> sean@0: sean@1: window.onresize = function(){ sean@1: document.getElementById("content").innerHTML = ""; sean@1: makeChart(); sean@1: }; sean@0: sean@0: var critical=[]; sean@0: var urgent=[]; sean@0: var bug=[]; sean@0: var feature=[]; sean@0: var wish=[]; sean@0: var timestamp=[]; sean@0: sean@1: sean@1: sean@0: function assignIssueToDate(issueArray, dateArray){ sean@0: a = []; sean@0: for (var i = 0; i < issueArray.length; i++) { sean@0: a.push({points: issueArray[i].points, date : dateArray[i].date}); sean@0: } sean@0: sean@0: return a; sean@0: } sean@0: sean@1: function limitDatesOnXAxis(limit){ sean@1: if ( timestamp.length < limit ){ sean@1: return timestamp.length; sean@1: } else { sean@1: return limit; sean@1: } sean@1: } sean@0: sean@0: function maxInObject( array ){ sean@0: var maxVal = 0; sean@0: for (var i = 0; i < array.length; i++) { sean@0: if (maxVal < array[i].points){ sean@0: maxVal = array[i].points; sean@0: } sean@0: } sean@0: return maxVal; sean@0: } sean@0: sean@0: sean@0: function getMaxIssues(){ sean@0: maxIssuesOfAllArrays = []; sean@0: maxIssuesOfAllArrays.push(maxInObject(critical)); sean@0: maxIssuesOfAllArrays.push(maxInObject(urgent)); sean@0: maxIssuesOfAllArrays.push(maxInObject(bug)); sean@0: maxIssuesOfAllArrays.push(maxInObject(feature)); sean@0: maxIssuesOfAllArrays.push(maxInObject(wish)); sean@0: sean@0: return Math.max.apply(Math, maxIssuesOfAllArrays)+1; sean@0: } sean@0: sean@0: sean@0: function dayDifference(first, second) { sean@0: "use strict"; sean@0: var difference = (second - first) / (1000 * 60 * 60 * 24); sean@0: sean@0: // just to avoid the get thousands of lines... would look ugly. sean@0: if (difference > 60){ sean@0: difference = 60; sean@0: } sean@0: sean@0: return difference; sean@0: } sean@0: sean@0: sean@0: // function for the grid lines sean@0: function makeGrid(direction, orientation, ticknumber) { sean@0: return d3.svg.axis() sean@0: .scale(direction) sean@0: .orient(orientation) sean@0: .ticks( ticknumber ); sean@0: } sean@0: sean@0: sean@0: //append a svg_path. pretty generic sean@1: function draw_line(svg, data_array, css_class, line_object, lineShape){ sean@0: svg.append("path") sean@0: .datum(assignIssueToDate(data_array, timestamp)) sean@0: .attr("class", css_class) sean@1: .style("stroke-dasharray", (lineShape)) sean@0: .attr("d", line_object); sean@0: } sean@0: sean@0: sean@1: function makeLegend(svg, width){ sean@0: sean@1: var legend_distance = width+40; sean@1: var top_distance = 20; sean@1: var distance_steps = 50; sean@1: sean@1: sean@1: function set_propper_distance(steps){ sean@1: top_distance += steps; sean@1: return top_distance; sean@1: } sean@1: sean@1: function draw_legend_line(svg, width, Ypos, text, issues){ sean@1: svg.append("svg:text") sean@1: .attr("class", "legend") sean@1: .attr("x", width-30 ) sean@1: .attr("y", Ypos) sean@1: .text(text + ":"); sean@1: sean@1: svg.append("svg:text") sean@1: .attr("class", "legend") sean@1: .attr("x", width+35 ) sean@1: .attr("y", Ypos) sean@1: .text(issues); sean@1: sean@1: svg.append("rect") sean@1: .attr("class", "line " + text.toLowerCase() + " legend") sean@1: .attr("x", width-30) sean@1: .attr("y", Ypos-20) sean@1: .attr("width", 100) sean@1: .attr("height", 2); sean@1: } sean@1: sean@1: draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Critical", critical[critical.length-1].points); sean@1: draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Urgent", urgent[urgent.length-1].points); sean@1: draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Bug", bug[bug.length-1].points); sean@1: draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Feature", feature[feature.length-1].points); sean@1: draw_legend_line(svg, legend_distance, set_propper_distance(distance_steps), "Wish", wish[wish.length-1].points); sean@0: } sean@0: sean@0: sean@1: sean@0: //draw the chart sean@0: function makeChart(){ sean@0: sean@0: //declaration sean@0: var sizeOfSystemBorders = 50; sean@1: var margin = {top: 20, right: 100, bottom: 90, left: 60}, sean@0: width = (document.documentElement.clientWidth-sizeOfSystemBorders) - margin.left - margin.right, sean@1: height = (document.documentElement.clientHeight-sizeOfSystemBorders) - margin.top - margin.bottom; sean@0: sean@0: var x = d3.time.scale() sean@0: .range([0, width]); sean@0: sean@0: var y = d3.scale.linear() sean@0: .range([height, 0]); sean@0: sean@0: var base_line = d3.svg.line() sean@0: .x(function(d) { return x(d.date); }) sean@0: .y(function(d) { return y(d.points); }); sean@0: sean@0: //lines sean@0: var criticalLine = base_line; sean@0: var urgentLine = base_line; sean@0: var bugLine = base_line; sean@0: var featureLine = base_line; sean@0: var wishLine = base_line; sean@0: var timestampLine = base_line; sean@0: sean@0: sean@0: //set domain of y axis sean@0: var yDomain = [ ]; sean@0: yDomain[0] = 0; sean@0: yDomain[1] = getMaxIssues(); sean@0: y.domain(d3.extent(yDomain, function(d){return d; })); sean@0: sean@0: //set domain of y axis sean@0: x.domain(d3.extent(timestamp, function(d){return d.date; })); sean@0: sean@0: sean@0: var xAxis = d3.svg.axis() sean@0: .scale(x) sean@0: .orient("bottom") sean@1: .ticks(limitDatesOnXAxis(10)) sean@1: .tickFormat(d3.time.format("%d.%m:%H:%M")); sean@1: // .tickFormat(d3.time.format("%X")); sean@1: // .tickFormat(d3.time.format.iso); sean@0: sean@0: sean@0: var yAxis = d3.svg.axis() sean@0: .scale(y) sean@0: .orient("left"); sean@0: sean@0: sean@1: var svg = d3.select("#content") sean@0: .append("svg") sean@0: .attr("class", "svg") sean@0: .attr("width", width + margin.left + margin.right) sean@0: .attr("height", height + margin.top + margin.bottom) sean@0: .append("g") sean@0: .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); sean@0: sean@0: sean@0: // creation sean@0: sean@0: sean@0: // Draw the x Grid lines gernot@11: // svg.append("g") gernot@11: // .attr("class", "grid") gernot@11: // .attr("transform", "translate(0," + height + ")") gernot@11: // .call(makeGrid(x, "bottom", timestamp.length) gernot@11: // .tickSize(-height, 0, 0) gernot@11: // .tickFormat("") gernot@11: // ); sean@0: sean@0: sean@0: // Draw the y Grid lines sean@0: svg.append("g") sean@0: .attr("class", "grid") sean@1: .call(makeGrid(y, "left", function(){return Math.min(getMaxIssues(), 50);}()) sean@0: .tickSize(-width, 0, 0) sean@0: .tickFormat("") sean@0: ); sean@0: sean@0: sean@0: // Draw the x-axis sean@0: svg.append("g") sean@0: .attr("class", "x axis") sean@0: .attr("transform", "translate(0," + height + ")") sean@0: .call(xAxis) sean@0: .selectAll("text") sean@0: .style("text-anchor", "end") sean@1: .attr("dx", "-.5em") sean@1: .attr("dy", ".1em") sean@0: .attr("transform", function() { sean@0: return "rotate(-65)"; sean@0: }); sean@0: sean@0: sean@0: // Draw the y-axis sean@0: svg.append("g") sean@0: .attr("class", "y axis") sean@0: .call(yAxis) sean@0: .append("text") sean@0: .attr("transform", "rotate(-90)") sean@0: .attr("y", 6) sean@0: .attr("dy", ".71em") sean@0: .style("text-anchor", "end"); sean@0: sean@0: sean@0: // Text for y-axis sean@0: svg.append("text") sean@0: .attr("transform", "rotate(-90)") sean@0: .attr("y", 10 - margin.left) sean@0: .attr("x", 0 - (height / 2)) sean@0: .attr("dy", "1em") sean@0: .style("text-anchor", "middle") sean@0: .text("Issues"); sean@0: sean@0: sean@0: //Titel und Legende sean@0: sean@0: svg.append("svg:text") sean@1: .attr("class", "text") sean@0: .attr("x", 10) sean@0: .attr("y", -5) sean@0: .text("Issues Nach Zeit"); sean@0: sean@0: sean@1: draw_line(svg, wish, "line wish", wishLine, "0, 0"); sean@1: draw_line(svg, feature, "line feature", featureLine, "3, 3"); sean@1: draw_line(svg, bug, "line bug", bugLine, "7, 7"); sean@1: draw_line(svg, urgent, "line urgent", urgentLine, "13, 13"); sean@1: draw_line(svg, critical, "line critical", criticalLine, "17, 17"); sean@0: sean@0: sean@1: makeLegend(svg, width); sean@1: sean@0: sean@0: } sean@0: sean@0: makeChart(); sean@0: sean@0: sean@0: </script> sean@0: </body> sean@0: </html>