// menu transition $("#leftside-navigation .sub-menu > a").click(function(e) { $("#leftside-navigation ul ul").slideUp(), $(this).next().is(":visible") || $(this).next().slideDown(), e.stopPropagation() }); // generateHeatMap(["../static/data/data_dummy.tsv", "../static/data/data2_dummy.tsv"], "#chart"); function generateHeatMap(datasets, divID){ // heatmap SVG const margin = { top: 50, right: 0, bottom: 100, left: 30 }, width =520 - margin.left - margin.right, height = 320 - margin.top - margin.bottom, gridSize = Math.floor(width / 24), legendElementWidth = gridSize*2, buckets = 9, // blue colors // colors = ["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"], // alternatively colorbrewer.YlGnBu[9] // orange colors // colors = ['#fff5eb','#fee6ce','#fdd0a2','#fdae6b','#fd8d3c','#f16913','#d94801','#a63603','#7f2704'], // yellow colors colors =["#ECE622","#D5CF22","#BEB922","#A7A222","#908C22","#797522","#625F22","#625F22","#4B4822","#343222"], days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], times = ["1a", "2a", "3a", "4a", "5a", "6a", "7a", "8a", "9a", "10a", "11a", "12a", "1p", "2p", "3p", "4p", "5p", "6p", "7p", "8p", "9p", "10p", "11p", "12p"]; // datasets = ["../static/data/data_dummy.tsv", "../static/data/data2_dummy.tsv"]; const svg = d3.select(divID).append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); const dayLabels = svg.selectAll(".dayLabel") .data(days) .enter().append("text") .text(function (d) { return d; }) .attr("x", 0) .attr("y", (d, i) => i * gridSize) .style("text-anchor", "end") .attr("transform", "translate(-6," + gridSize / 1.5 + ")") .attr("class", (d, i) => ((i >= 0 && i <= 4) ? "dayLabel mono axis axis-workweek" : "dayLabel mono axis")); const timeLabels = svg.selectAll(".timeLabel") .data(times) .enter().append("text") .text((d) => d) .attr("x", (d, i) => i * gridSize) .attr("y", 0) .style("text-anchor", "middle") .attr("transform", "translate(" + gridSize / 2 + ", -6)") .attr("class", (d, i) => ((i >= 7 && i <= 16) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis")); const type = (d) => { return { day: +d.day, hour: +d.hour, value: +d.value }; }; const heatmapChart = function(tsvFile) { d3.tsv(tsvFile, type, (error, data) => { var div = d3.select("body").append("div") .attr("class", "tooltip") .style("opacity", 0); const colorScale = d3.scaleQuantile() .domain([0, buckets - 1, d3.max(data, (d) => d.value)]) .range(colors); const cards = svg.selectAll(".hour") .data(data, (d) => d.day+':'+d.hour); cards.append("title"); cards.enter().append("rect") .attr("x", (d) => (d.hour - 1) * gridSize) .attr("y", (d) => (d.day - 1) * gridSize) .attr("rx", 4) .attr("ry", 4) .attr("class", "hour bordered") .attr("width", gridSize) .attr("height", gridSize) .style("fill", colors[0]) .on("mouseover", function(d) { div.transition() .duration(200) .style("opacity", .9); div.html("Day: " +days[d.day-1]+ "
Hour: " +times[d.hour-1]+ "
Commits: " +d.value+ "") .style("left", (d3.event.pageX + 20) + "px") .style("top", (d3.event.pageY - 20) + "px"); }) .on("mouseout", function(d) { div.transition() .duration(500) .style("opacity", 0); }) .merge(cards) .transition() .duration(1000) .style("fill", (d) => colorScale(d.value)); // cards.select("title").text((d) => d.value); cards.exit().remove(); const legend = svg.selectAll(".legend") .data([0].concat(colorScale.quantiles()), (d) => d); const legend_g = legend.enter().append("g") .attr("class", "legend"); legend_g.append("rect") .attr("x", (d, i) => legendElementWidth * i) .attr("y", height) .attr("width", legendElementWidth) .attr("height", gridSize / 2) .style("fill", (d, i) => colors[i]); legend_g.append("text") .attr("class", "mono") .text((d) => "≥ " + Math.round(d)) .attr("x", (d, i) => legendElementWidth * i) .attr("y", height + gridSize); legend.exit().remove(); }); }; // use first dataset by default heatmapChart(datasets[0]); // dataset buttons const datasetpicker = d3.select("#dataset-picker") .selectAll(".btn btn-primary") .data(datasets); // dataset picking button datasetpicker.enter() .append("input") .attr("value", (d) => "Dataset " + d) .attr("type", "button") .attr("class", "btn-sm btn-primary") .on("click", (d) => heatmapChart(d)); } // generateBarChart("../static/data/day_of_week_copy.tsv", "#day_of_week"); function generateBarChart (pathToTSV,divID){ // Bar chart, see function 'main' for main execution wheel function toNum(d){ //cleaner function d.commits= +d.commits return d }; d3.tsv(pathToTSV, toNum, function (error,data){ "use strict" // declare outside for reference later var width=520 var height=380 var chartWidth, chartHeight var svg = d3.select(divID).append("svg") var axisLayer = svg.append("g").classed("axisLayer", true) var chartLayer = svg.append("g").classed("chartLayer", true) var margin = {top:50, right:0, bottom:100, left:30} var xScale = d3.scaleBand() var yScale = d3.scaleLinear() var div = d3.select("body").append("div") .attr("class", "rect_tooltip") .style("opacity", 0); function main(data) { setSize(); drawAxisBarChart(); drawChartBarChart(); } function setSize() { chartWidth = width - margin.left - margin.right, chartHeight = height - margin.top - margin.bottom, svg .attr("width", 520) .attr("height", 320) axisLayer .attr("width", chartWidth) .attr("height", chartHeight) chartLayer .attr("width", chartWidth) .attr("height", chartHeight) .attr("transform", "translate("+[margin.left, margin.top]+")") xScale.domain(data.map(function(d){ return d.day_name })).range([0, chartWidth]) .paddingInner(0.1) .paddingOuter(0.5) yScale.domain([0, d3.max(data, function(d){ return d.commits})]).range([chartHeight, 0]) } function drawChartBarChart() { // monitor the transition var t = d3.transition() .duration(1100) .ease(d3.easeLinear) .on("start", function(d){ console.log("Bar Chart Transiton start") }) .on("end", function(d){ console.log("Bar Chart Transiton end") }) var bar = chartLayer .selectAll(".bar") .data(data) bar.exit().remove() bar .enter() .append("rect") .classed("bar", true) .merge(bar) .attr("fill", "rgb(236, 230, 34)") .attr("width", xScale.bandwidth()) .attr("stroke", "#323232") //setup for cool transition .attr("height", 0) .attr("transform", function(d){ return "translate("+[xScale(d.day_name), chartHeight]+")"}) var labels = chartLayer .selectAll("labels") .data(data) //setup for percentage display var totalCommits=0 data.forEach(function(d){ totalCommits+=d.commits }) labels .enter() .append("text") .text(function(d){ var percentage= (d.commits/totalCommits *100).toFixed(2) return ""+percentage+"%"; }) .attr("transform", function(d){ return "translate("+[xScale(d.day_name)+5, chartHeight-5]+")" }) chartLayer.selectAll(".bar").transition(t) // grows to appropriate amount .attr("height", function(d){ return chartHeight - yScale(d.commits) }) .attr("transform", function(d){ return "translate("+[xScale(d.day_name), yScale(d.commits)]+")"}) } function drawAxisBarChart(){ var yAxis = d3.axisLeft(yScale) .tickSizeInner(-chartWidth) axisLayer.append("g") .attr("transform", "translate("+[margin.left, margin.top]+")") .attr("class", "axis y") .call(yAxis); var xAxis = d3.axisBottom(xScale) axisLayer.append("g") .attr("class", "axis x") .attr("transform", "translate("+[margin.left, (height-margin.bottom)]+")") .call(xAxis); } //kicks of execution of the bar chart main(); }); //end of tsv read in } //end of generateBarChart // generateLineChart("../static/data/commits_by_author_copy.tsv", "#lineChart"); // generateLineChart("../static/data/lines_of_code_by_author_copy.tsv", "#lineChart2"); function generateLineChart(pathToTSV, divID){ function allToNumber(d){ //converts everything to Number type for (var key in d){ d[key] = +d[key] } //fix for Unix timestamps d.date = new Date(d.date * 1000) return d; } d3.tsv(pathToTSV, allToNumber, function (error,data){ if (error) throw error; var authors = data.columns.slice(1).map(function(id) { return { id: id, values: data.map(function(d) { return {date: d.date, commits: d[id]}; }) }; }); var svgWidth=1200, svgHeight=400, chartWidth= 1000; var svg = d3.select(divID).append("svg").attr("height", svgHeight).attr("width", svgWidth), margin = {top: 20, right: 80, bottom: 30, left: 50}, //this is smaller than svgWidth to accomodate Legend width = chartWidth - margin.left - margin.right, height = svgHeight - margin.top - margin.bottom, //dynamically builds grid numberGridLines=30 //main chart container g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var xScale = d3.scaleTime().range([0, width]), yScale = d3.scaleLinear().range([height, 0]), // 10 nice colors colors = d3.scaleOrdinal(d3.schemeCategory10); xScale.domain(d3.extent(data, function(d) { return d.date; })); yScale.domain([ d3.min(authors, function(c) { return d3.min(c.values, function(d) { return d.commits; }); }), d3.max(authors, function(c) { return d3.max(c.values, function(d) { return d.commits; }); }) ]); var line = d3.line() // different types of interpolations here // https://bl.ocks.org/d3noob/ced1b9b18bd8192d2c898884033b5529 .curve(d3.curveBasis) .x(function(d) { return xScale(d.date); }) .y(function(d) { return yScale(d.commits);}); colors.domain(authors.map(function(c) { return c.id; })); function main(){ drawAxisLineChart(); drawChartLineChart(); drawLegend(); } // gridlines in x axis function make_x_gridlines() { return d3.axisBottom(xScale) .ticks(numberGridLines) } // gridlines in y axis function make_y_gridlines() { return d3.axisLeft(yScale) .ticks(numberGridLines) } function drawAxisLineChart(){ g.append("g") .attr("class", "axis axis--x") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(xScale)); g.append("g") .attr("class", "axis axis--y") .call(d3.axisLeft(yScale)) // .append("text") // .attr("transform", "rotate(-90)") // .attr("y", 6) // .attr("dy", "0.71em") // .attr("fill", "#000") // add the X gridlines g.append("g") .attr("class", "grid") .attr("transform", "translate(0," + height + ")") .call(make_x_gridlines() .tickSize(-height) .tickFormat("") ); // add the Y gridlines g.append("g") .attr("class", "grid") .call(make_y_gridlines() .tickSize(-width) .tickFormat("") ); } function drawChartLineChart() { var author = g.selectAll(".author") .data(authors) .enter().append("g") .attr("class", "author"); author.append("path") .attr("class", "line") .attr("d", function(d) { return line(d.values); }) .style("stroke", function(d) { return colors(d.id); }); // Enable to show author at the end of the line // author.append("text") // .datum(function(d) { return {id: d.id, value: d.values[d.values.length - 1]}; }) // .attr("transform", function(d) { return "translate(" + xScale(d.value.date) + "," + yScale(d.value.commits) + ")"; }) // .attr("x", 3) // .attr("dy", "0.35em") // .style("font", "10px sans-serif") // .text(function(d) { return d.id; }); } function drawLegend(){ var legend= svg.selectAll(".legend-item") .data(authors) .enter().append("g") .attr("class","legend"); legend.append("rect") .attr('x', chartWidth - 20) .attr('y', function(d, i) { return (i * 35) + 20; }) .attr('width', 10) .attr('height', 10) .style('fill', function(d) { return colors(d.id); }); legend.append('text') .attr('x', chartWidth - 8) .attr('y', function(d, i) { return (i * 35) + 29; }) .text(function(d) { return d.id; }); } main(); //kicks off main execution wheel }); //end tsv read in }; //end generate line chart