From bf0eca699e4f16eee152ff41a8a98ed28c6c7be8 Mon Sep 17 00:00:00 2001 From: jonybang Date: Sun, 12 Apr 2015 01:19:52 -0700 Subject: [PATCH 1/5] refactoring, implementation of the principle DRY, add the the ability to insert text and text wrapping --- gantt-chart-d3.js | 444 ++++++++++++++++++++++++++++++---------------- 1 file changed, 293 insertions(+), 151 deletions(-) diff --git a/gantt-chart-d3.js b/gantt-chart-d3.js index f28dbc0..cddf256 100644 --- a/gantt-chart-d3.js +++ b/gantt-chart-d3.js @@ -1,18 +1,20 @@ /** * @author Dimitry Kudrayvtsev - * @version 2.1 + * @version 2.0 */ d3.gantt = function() { var FIT_TIME_DOMAIN_MODE = "fit"; var FIXED_TIME_DOMAIN_MODE = "fixed"; - + var margin = { - top : 20, - right : 40, - bottom : 20, - left : 150 + top : 20, + right : 0, + bottom : 20, + left : 120 }; + var yAxisPaddingRightLeft = 70; + var containerId = 'svg-gantt'; var timeDomainStart = d3.time.day.offset(new Date(),-3); var timeDomainEnd = d3.time.hour.offset(new Date(),+3); var timeDomainMode = FIT_TIME_DOMAIN_MODE;// fixed or fit @@ -23,148 +25,207 @@ d3.gantt = function() { var tickFormat = "%H:%M"; + window.calcTextWrapWidth = getWidth; + var keyFunction = function(d) { - return d.startDate + d.taskName + d.endDate; + return d.startDate + d.taskName + d.endDate; }; var rectTransform = function(d) { - return "translate(" + x(d.startDate) + "," + y(d.taskName) + ")"; + return "translate(" + x(d.startDate) + "," + y(d.taskName) + ")"; }; - var x = d3.time.scale().domain([ timeDomainStart, timeDomainEnd ]).range([ 0, width ]).clamp(true); - - var y = d3.scale.ordinal().domain(taskTypes).rangeRoundBands([ 0, height - margin.top - margin.bottom ], .1); - - var xAxis = d3.svg.axis().scale(x).orient("bottom").tickFormat(d3.time.format(tickFormat)).tickSubdivide(true) - .tickSize(8).tickPadding(8); - - var yAxis = d3.svg.axis().scale(y).orient("left").tickSize(0); - - var initTimeDomain = function(tasks) { - if (timeDomainMode === FIT_TIME_DOMAIN_MODE) { - if (tasks === undefined || tasks.length < 1) { - timeDomainStart = d3.time.day.offset(new Date(), -3); - timeDomainEnd = d3.time.hour.offset(new Date(), +3); - return; - } - tasks.sort(function(a, b) { - return a.endDate - b.endDate; - }); - timeDomainEnd = tasks[tasks.length - 1].endDate; - tasks.sort(function(a, b) { - return a.startDate - b.startDate; - }); - timeDomainStart = tasks[0].startDate; - } + function getWidth(d){ + return (x(d.endDate) - x(d.startDate)); + } + function getText(d) { + return d.title; + } + + var initTimeDomain = function() { + if (timeDomainMode === FIT_TIME_DOMAIN_MODE) { + if (tasks === undefined || tasks.length < 1) { + timeDomainStart = d3.time.day.offset(new Date(), -3); + timeDomainEnd = d3.time.hour.offset(new Date(), +3); + return; + } + tasks.sort(function(a, b) { + return a.endDate - b.endDate; + }); + timeDomainEnd = tasks[tasks.length - 1].endDate; + tasks.sort(function(a, b) { + return a.startDate - b.startDate; + }); + timeDomainStart = tasks[0].startDate; + } }; + var x, y, xAxis, yAxis; var initAxis = function() { - x = d3.time.scale().domain([ timeDomainStart, timeDomainEnd ]).range([ 0, width ]).clamp(true); - y = d3.scale.ordinal().domain(taskTypes).rangeRoundBands([ 0, height - margin.top - margin.bottom ], .1); - xAxis = d3.svg.axis().scale(x).orient("bottom").tickFormat(d3.time.format(tickFormat)).tickSubdivide(true) - .tickSize(8).tickPadding(8); + x = d3.time + .scale() + .domain([ timeDomainStart, timeDomainEnd ]) + .range([ 0, width ]) + .clamp(true); + + y = d3.scale + .ordinal() + .domain(taskTypes) + .rangeRoundBands([ 0, height - margin.top - margin.bottom ], .1, .3); - yAxis = d3.svg.axis().scale(y).orient("left").tickSize(0); + xAxis = d3.svg + .axis() + .scale(x) + .orient("bottom") + .tickFormat(d3.time.format(tickFormat)) + .tickSubdivide(true) + .tickSize(8) + .tickPadding(8); + + yAxis = d3.svg + .axis() + .scale(y) + .orient("left") + .ticks(8, "%"); }; - + initAxis(); + function gantt(tasks) { - - initTimeDomain(tasks); - initAxis(); - - var svg = d3.select("body") - .append("svg") - .attr("class", "chart") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("class", "gantt-chart") - .attr("width", width + margin.left + margin.right) - .attr("height", height + margin.top + margin.bottom) - .attr("transform", "translate(" + margin.left + ", " + margin.top + ")"); - - svg.selectAll(".chart") - .data(tasks, keyFunction).enter() - .append("rect") - .attr("rx", 5) - .attr("ry", 5) - .attr("class", function(d){ - if(taskStatus[d.status] == null){ return "bar";} - return taskStatus[d.status]; - }) - .attr("y", 0) - .attr("transform", rectTransform) - .attr("height", function(d) { return y.rangeBand(); }) - .attr("width", function(d) { - return (x(d.endDate) - x(d.startDate)); - }); - - - svg.append("g") - .attr("class", "x axis") - .attr("transform", "translate(0, " + (height - margin.top - margin.bottom) + ")") - .transition() - .call(xAxis); - - svg.append("g").attr("class", "y axis").transition().call(yAxis); - - return gantt; + initTimeDomain(); + initAxis(); + + var svg = d3.select("#"+containerId) + .append("svg") + .attr("class", "chart") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .append("g") + .attr("class", "gantt-chart") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .attr("transform", "translate(" + margin.left + ", " + margin.top + ")"); + + svg.append("g") + .attr("class", "x axis") + .attr("transform", "translate(0, " + (height - margin.top - margin.bottom) + ")") + .transition() + .call(xAxis); + + svg.append("g") + .attr("class", "y axis") + .call(yAxis); + + if(tasks && tasks.length){ + gantt.redraw(tasks); + } + + return gantt; + } + + + function confGTasks(task){ + task.attr("transform", rectTransform) + .attr("height", function(d) { return y.rangeBand(); }) + .attr("width", getWidth); + } + function confRect(rect){ + rect.attr("height", function(d) { return y.rangeBand(); }) + .attr("width", getWidth) + .attr("rx", 5) + .attr("ry", 5) + .attr("class", function(d){ + if(taskStatus[d.status] == null){ return "bar";} + return taskStatus[d.status]; + }); + } + + function confText(text){ + text.attr("x", 0) + .attr("y", y.rangeBand() / 4) + .attr("dy", ".35em") + .style("visibility", function(d) { + return x(d.startDate) == 0 ? "hidden" : "visible"; + }); + } - }; - gantt.redraw = function(tasks) { - initTimeDomain(tasks); - initAxis(); - + initTimeDomain(); + initAxis(); + var svg = d3.select("svg"); + var gTasks = svg.select(".gantt-chart") + .selectAll(".task") + .data(tasks, keyFunction); + + svg.select(".gantt-chart") + .selectAll(".task") + .selectAll("*") + .data(tasks, keyFunction) + .exit() + .attr('width', 0).remove(); + + gTasks.exit().remove(); + + gTasks.enter() + .insert("g", ":first-child") + .attr('class', 'task') + .attr("y", 0) + .transition() + .call(confGTasks); + + gTasks.exit().remove(); + + var gRect = gTasks.insert("rect",":first-child") + .transition() + .call(confRect); + + var gText = gTasks.append("text") + .call(confText) + .text(getText) + .call(d3TextWrap, false); + + gTasks.transition() + .call(confGTasks); + + gRect.transition() + .call(confRect); + + gText.transition() + .call(confText); - var ganttChartGroup = svg.select(".gantt-chart"); - var rect = ganttChartGroup.selectAll("rect").data(tasks, keyFunction); - - rect.enter() - .insert("rect",":first-child") - .attr("rx", 5) - .attr("ry", 5) - .attr("class", function(d){ - if(taskStatus[d.status] == null){ return "bar";} - return taskStatus[d.status]; - }) - .transition() - .attr("y", 0) - .attr("transform", rectTransform) - .attr("height", function(d) { return y.rangeBand(); }) - .attr("width", function(d) { - return (x(d.endDate) - x(d.startDate)); - }); - - rect.transition() - .attr("transform", rectTransform) - .attr("height", function(d) { return y.rangeBand(); }) - .attr("width", function(d) { - return (x(d.endDate) - x(d.startDate)); - }); - - rect.exit().remove(); - - svg.select(".x").transition().call(xAxis); - svg.select(".y").transition().call(yAxis); - - return gantt; + gTasks.exit().remove(); + + svg.select(".x") + .transition() + .call(xAxis); + + svg.select(".y") + .transition() + .call(yAxis) + .selectAll(".tick text") + .call(d3TextWrap, margin.left, yAxisPaddingRightLeft); + + return gantt; + }; + + gantt.containerId = function(strId){ + containerId = strId; + return gantt; }; gantt.margin = function(value) { - if (!arguments.length) - return margin; - margin = value; - return gantt; + if (!arguments.length) + return margin; + margin = value; + return gantt; }; gantt.timeDomain = function(value) { - if (!arguments.length) - return [ timeDomainStart, timeDomainEnd ]; - timeDomainStart = +value[0], timeDomainEnd = +value[1]; - return gantt; + if (!arguments.length) + return [ timeDomainStart, timeDomainEnd ]; + timeDomainStart = +value[0], timeDomainEnd = +value[1]; + return gantt; }; /** @@ -173,49 +234,130 @@ d3.gantt = function() { * "fixed" - fixed domain. */ gantt.timeDomainMode = function(value) { - if (!arguments.length) - return timeDomainMode; + if (!arguments.length) + return timeDomainMode; timeDomainMode = value; return gantt; - }; gantt.taskTypes = function(value) { - if (!arguments.length) - return taskTypes; - taskTypes = value; - return gantt; + if (!arguments.length) + return taskTypes; + taskTypes = value; + return gantt; }; - + gantt.taskStatus = function(value) { - if (!arguments.length) - return taskStatus; - taskStatus = value; - return gantt; + if (!arguments.length) + return taskStatus; + taskStatus = value; + return gantt; }; gantt.width = function(value) { - if (!arguments.length) - return width; - width = +value; - return gantt; + if (!arguments.length) + return width; + width = +value; + return gantt; }; gantt.height = function(value) { - if (!arguments.length) - return height; - height = +value; - return gantt; + if (!arguments.length) + return height; + height = +value; + return gantt; }; gantt.tickFormat = function(value) { - if (!arguments.length) - return tickFormat; - tickFormat = value; - return gantt; + if (!arguments.length) + return tickFormat; + tickFormat = value; + return gantt; }; - - return gantt; }; + +function d3TextWrap (allText, inputWidth, paddingRightLeft, paddingTopBottom) { + paddingRightLeft = paddingRightLeft || 5; //Default padding (5px) + paddingTopBottom = (paddingTopBottom || 5) - 2; //Default padding (5px), remove 2 pixels because of the borders + + var arrLineCreatedCount = []; + allText.each(function(object) { + var text = d3.select(this), + objType = typeof object, + words = ((objType == "string") ? object : text.text()).split(/[ \f\n\r\t\v]+/).reverse(), //Don't cut non-breaking space (\xA0), as well as the Unicode characters \u00A0 \u2028 \u2029) + word, + width, + line = [], + lineNumber = 0, + lineHeight = 1.1, //Ems + x, + y = text.attr("y"), + dy = parseFloat(text.attr("dy")), + createdLineCount = 1, //Total line created count + textAlign = text.style('text-anchor') || 'start'; //'start' by default (start, middle, end, inherit) + + if(calcTextWrapWidth && inputWidth == false){ + width = calcTextWrapWidth(object); + } else { + width = inputWidth; + } + + var maxWidth = width; //I store the tooltip max width + width = width - (paddingRightLeft * 2); //Take the padding into account + + //Clean the data in case does not define those values + if (isNaN(dy)) dy = 0; //Default padding (0em) : the 'dy' attribute on the first _must_ be identical to the 'dy' specified on the element, or start at '0em' if undefined + + //Offset the text position based on the text-anchor + var wrapTickLabels = d3.select(text.node().parentNode).classed('tick'); //Don't wrap the 'normal untranslated' element and the translated elements the same way.. + if (wrapTickLabels) { + switch (textAlign) { + case 'start': + x = -width / 2; + break; + case 'middle': + x = 0; + break; + case 'end': + x = width / 2; + break; + default : + } + } + else { //untranslated elements + switch (textAlign) { + case 'start': + x = paddingRightLeft; + break; + case 'middle': + x = maxWidth / 2; + break; + case 'end': + x = maxWidth - paddingRightLeft; + break; + default : + } + } + y = +((null === y) ? paddingTopBottom : y); + + var tspan = text.text(null).append("tspan").attr("x", x).attr("y", y).attr("dy", dy + "em"); + //noinspection JSHint + while (word = words.pop()) { + line.push(word); + tspan.text(line.join(" ")); + var computedTextLength = tspan.node().getComputedTextLength(); + if (computedTextLength > width && line.length > 1) { + line.pop(); + tspan.text(line.join(" ")); + line = [word]; + tspan = text.append("tspan").attr("x", x).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word); + ++createdLineCount; + } + } + + arrLineCreatedCount.push(createdLineCount); //Store the line count in the array + }); + return arrLineCreatedCount; +} From 32603ef87666755be719d70f203885181c7a08b0 Mon Sep 17 00:00:00 2001 From: Jonybang Date: Sun, 12 Apr 2015 19:31:05 +1000 Subject: [PATCH 2/5] adapting examples --- examples/example.html | 1 + examples/example.js | 50 +++++++++---------- examples/example2.html | 1 + examples/example2.js | 109 ++++++++++++++++++++++------------------- examples/example3.html | 1 + examples/example3.js | 71 +++++++++++++++------------ 6 files changed, 126 insertions(+), 107 deletions(-) diff --git a/examples/example.html b/examples/example.html index 7f8cf29..505dbe8 100644 --- a/examples/example.html +++ b/examples/example.html @@ -9,6 +9,7 @@ View on GitHub Share on Twitter +
diff --git a/examples/example.js b/examples/example.js index 5b8ff49..669c5d2 100644 --- a/examples/example.js +++ b/examples/example.js @@ -3,31 +3,31 @@ example(); function example() { var tasks = [ -{"startDate":new Date("Sun Dec 09 01:36:45 EST 2012"),"endDate":new Date("Sun Dec 09 02:36:45 EST 2012"),"taskName":"E Job","status":"RUNNING"}, -{"startDate":new Date("Sun Dec 09 04:56:32 EST 2012"),"endDate":new Date("Sun Dec 09 06:35:47 EST 2012"),"taskName":"A Job","status":"RUNNING"}, -{"startDate":new Date("Sun Dec 09 06:29:53 EST 2012"),"endDate":new Date("Sun Dec 09 06:34:04 EST 2012"),"taskName":"D Job","status":"RUNNING"}, -{"startDate":new Date("Sun Dec 09 05:35:21 EST 2012"),"endDate":new Date("Sun Dec 09 06:21:22 EST 2012"),"taskName":"P Job","status":"RUNNING"}, -{"startDate":new Date("Sun Dec 09 05:00:06 EST 2012"),"endDate":new Date("Sun Dec 09 05:05:07 EST 2012"),"taskName":"D Job","status":"RUNNING"}, -{"startDate":new Date("Sun Dec 09 03:46:59 EST 2012"),"endDate":new Date("Sun Dec 09 04:54:19 EST 2012"),"taskName":"P Job","status":"RUNNING"}, -{"startDate":new Date("Sun Dec 09 04:02:45 EST 2012"),"endDate":new Date("Sun Dec 09 04:48:56 EST 2012"),"taskName":"N Job","status":"RUNNING"}, -{"startDate":new Date("Sun Dec 09 03:27:35 EST 2012"),"endDate":new Date("Sun Dec 09 03:58:43 EST 2012"),"taskName":"E Job","status":"SUCCEEDED"}, -{"startDate":new Date("Sun Dec 09 01:40:11 EST 2012"),"endDate":new Date("Sun Dec 09 03:26:35 EST 2012"),"taskName":"A Job","status":"SUCCEEDED"}, -{"startDate":new Date("Sun Dec 09 03:00:03 EST 2012"),"endDate":new Date("Sun Dec 09 03:09:51 EST 2012"),"taskName":"D Job","status":"SUCCEEDED"}, -{"startDate":new Date("Sun Dec 09 01:21:00 EST 2012"),"endDate":new Date("Sun Dec 09 02:51:42 EST 2012"),"taskName":"P Job","status":"SUCCEEDED"}, -{"startDate":new Date("Sun Dec 09 01:08:42 EST 2012"),"endDate":new Date("Sun Dec 09 01:33:42 EST 2012"),"taskName":"N Job","status":"FAILED"}, -{"startDate":new Date("Sun Dec 09 00:27:15 EST 2012"),"endDate":new Date("Sun Dec 09 00:54:56 EST 2012"),"taskName":"E Job","status":"SUCCEEDED"}, -{"startDate":new Date("Sun Dec 09 00:29:48 EST 2012"),"endDate":new Date("Sun Dec 09 00:44:50 EST 2012"),"taskName":"D Job","status":"SUCCEEDED"}, -{"startDate":new Date("Sun Dec 09 07:39:21 EST 2012"),"endDate":new Date("Sun Dec 09 07:43:22 EST 2012"),"taskName":"P Job","status":"RUNNING"}, -{"startDate":new Date("Sun Dec 09 07:00:06 EST 2012"),"endDate":new Date("Sun Dec 09 07:05:07 EST 2012"),"taskName":"D Job","status":"RUNNING"}, -{"startDate":new Date("Sun Dec 09 08:46:59 EST 2012"),"endDate":new Date("Sun Dec 09 09:54:19 EST 2012"),"taskName":"P Job","status":"RUNNING"}, -{"startDate":new Date("Sun Dec 09 09:02:45 EST 2012"),"endDate":new Date("Sun Dec 09 09:48:56 EST 2012"),"taskName":"N Job","status":"RUNNING"}, -{"startDate":new Date("Sun Dec 09 08:27:35 EST 2012"),"endDate":new Date("Sun Dec 09 08:58:43 EST 2012"),"taskName":"E Job","status":"SUCCEEDED"}, -{"startDate":new Date("Sun Dec 09 08:40:11 EST 2012"),"endDate":new Date("Sun Dec 09 08:46:35 EST 2012"),"taskName":"A Job","status":"SUCCEEDED"}, -{"startDate":new Date("Sun Dec 09 08:00:03 EST 2012"),"endDate":new Date("Sun Dec 09 08:09:51 EST 2012"),"taskName":"D Job","status":"SUCCEEDED"}, -{"startDate":new Date("Sun Dec 09 10:21:00 EST 2012"),"endDate":new Date("Sun Dec 09 10:51:42 EST 2012"),"taskName":"P Job","status":"SUCCEEDED"}, -{"startDate":new Date("Sun Dec 09 11:08:42 EST 2012"),"endDate":new Date("Sun Dec 09 11:33:42 EST 2012"),"taskName":"N Job","status":"FAILED"}, -{"startDate":new Date("Sun Dec 09 12:27:15 EST 2012"),"endDate":new Date("Sun Dec 09 12:54:56 EST 2012"),"taskName":"E Job","status":"SUCCEEDED"}, -{"startDate":new Date("Sat Dec 08 23:12:24 EST 2012"),"endDate":new Date("Sun Dec 09 00:26:13 EST 2012"),"taskName":"A Job","status":"KILLED"}]; +{"startDate":new Date("Sun Dec 09 01:36:45 EST 2012"),"endDate":new Date("Sun Dec 09 02:36:45 EST 2012"),"taskName":"E Job","status":"RUNNING", title: "Text content of task 1"}, +{"startDate":new Date("Sun Dec 09 04:56:32 EST 2012"),"endDate":new Date("Sun Dec 09 06:35:47 EST 2012"),"taskName":"A Job","status":"RUNNING", title: "Text content of task 2"}, +{"startDate":new Date("Sun Dec 09 06:29:53 EST 2012"),"endDate":new Date("Sun Dec 09 06:34:04 EST 2012"),"taskName":"D Job","status":"RUNNING", title: "Text content of task 3"}, +{"startDate":new Date("Sun Dec 09 05:35:21 EST 2012"),"endDate":new Date("Sun Dec 09 06:21:22 EST 2012"),"taskName":"P Job","status":"RUNNING", title: "Text content of task 4"}, +{"startDate":new Date("Sun Dec 09 05:00:06 EST 2012"),"endDate":new Date("Sun Dec 09 05:05:07 EST 2012"),"taskName":"D Job","status":"RUNNING", title: "Text content of task 5"}, +{"startDate":new Date("Sun Dec 09 03:46:59 EST 2012"),"endDate":new Date("Sun Dec 09 04:54:19 EST 2012"),"taskName":"P Job","status":"RUNNING", title: "Text content of task 6"}, +{"startDate":new Date("Sun Dec 09 04:02:45 EST 2012"),"endDate":new Date("Sun Dec 09 04:48:56 EST 2012"),"taskName":"N Job","status":"RUNNING", title: "Text content of task 7"}, +{"startDate":new Date("Sun Dec 09 03:27:35 EST 2012"),"endDate":new Date("Sun Dec 09 03:58:43 EST 2012"),"taskName":"E Job","status":"SUCCEEDED", title: "Text content of task 8"}, +{"startDate":new Date("Sun Dec 09 01:40:11 EST 2012"),"endDate":new Date("Sun Dec 09 03:26:35 EST 2012"),"taskName":"A Job","status":"SUCCEEDED", title: "Text content of task 9"}, +{"startDate":new Date("Sun Dec 09 03:00:03 EST 2012"),"endDate":new Date("Sun Dec 09 03:09:51 EST 2012"),"taskName":"D Job","status":"SUCCEEDED", title: "Text content of task 10"}, +{"startDate":new Date("Sun Dec 09 01:21:00 EST 2012"),"endDate":new Date("Sun Dec 09 02:51:42 EST 2012"),"taskName":"P Job","status":"SUCCEEDED", title: "Text content of task 11"}, +{"startDate":new Date("Sun Dec 09 01:08:42 EST 2012"),"endDate":new Date("Sun Dec 09 01:33:42 EST 2012"),"taskName":"N Job","status":"FAILED", title: "Text content of task 12"}, +{"startDate":new Date("Sun Dec 09 00:27:15 EST 2012"),"endDate":new Date("Sun Dec 09 00:54:56 EST 2012"),"taskName":"E Job","status":"SUCCEEDED", title: "Text content of task 13"}, +{"startDate":new Date("Sun Dec 09 00:29:48 EST 2012"),"endDate":new Date("Sun Dec 09 00:44:50 EST 2012"),"taskName":"D Job","status":"SUCCEEDED", title: "Text content of task 14"}, +{"startDate":new Date("Sun Dec 09 07:39:21 EST 2012"),"endDate":new Date("Sun Dec 09 07:43:22 EST 2012"),"taskName":"P Job","status":"RUNNING", title: "Text content of task 15"}, +{"startDate":new Date("Sun Dec 09 07:00:06 EST 2012"),"endDate":new Date("Sun Dec 09 07:05:07 EST 2012"),"taskName":"D Job","status":"RUNNING", title: "Text content of task 16"}, +{"startDate":new Date("Sun Dec 09 08:46:59 EST 2012"),"endDate":new Date("Sun Dec 09 09:54:19 EST 2012"),"taskName":"P Job","status":"RUNNING", title: "Text content of task 17"}, +{"startDate":new Date("Sun Dec 09 09:02:45 EST 2012"),"endDate":new Date("Sun Dec 09 09:48:56 EST 2012"),"taskName":"N Job","status":"RUNNING", title: "Text content of task 18"}, +{"startDate":new Date("Sun Dec 09 08:27:35 EST 2012"),"endDate":new Date("Sun Dec 09 08:58:43 EST 2012"),"taskName":"E Job","status":"SUCCEEDED", title: "Text content of task 19"}, +{"startDate":new Date("Sun Dec 09 08:40:11 EST 2012"),"endDate":new Date("Sun Dec 09 08:46:35 EST 2012"),"taskName":"A Job","status":"SUCCEEDED", title: "Text content of task 20"}, +{"startDate":new Date("Sun Dec 09 08:00:03 EST 2012"),"endDate":new Date("Sun Dec 09 08:09:51 EST 2012"),"taskName":"D Job","status":"SUCCEEDED", title: "Text content of task 21"}, +{"startDate":new Date("Sun Dec 09 10:21:00 EST 2012"),"endDate":new Date("Sun Dec 09 10:51:42 EST 2012"),"taskName":"P Job","status":"SUCCEEDED", title: "Text content of task 22"}, +{"startDate":new Date("Sun Dec 09 11:08:42 EST 2012"),"endDate":new Date("Sun Dec 09 11:33:42 EST 2012"),"taskName":"N Job","status":"FAILED", title: "Text content of task 23"}, +{"startDate":new Date("Sun Dec 09 12:27:15 EST 2012"),"endDate":new Date("Sun Dec 09 12:54:56 EST 2012"),"taskName":"E Job","status":"SUCCEEDED", title: "Text content of task 24"}, +{"startDate":new Date("Sat Dec 08 23:12:24 EST 2012"),"endDate":new Date("Sun Dec 09 00:26:13 EST 2012"),"taskName":"A Job","status":"KILLED", title: "Text content of task 25"}]; var taskStatus = { "SUCCEEDED" : "bar", diff --git a/examples/example2.html b/examples/example2.html index 0fcd2ec..def7c70 100644 --- a/examples/example2.html +++ b/examples/example2.html @@ -11,6 +11,7 @@ href="https://twitter.com/intent/tweet?hashtags=d3&original_referer=http%3A%2F%2Fdk8996.github.io%2FGantt-Chart%2F&text=D3%20Gantt%20Chart&tw_p=tweetbutton&url=http%3A%2F%2Fdk8996.github.com%2FGantt-Chart&screen_name=dk8996" target="_blank">Share on Twitter +
diff --git a/examples/example2.js b/examples/example2.js index bb0793e..d5c4acd 100644 --- a/examples/example2.js +++ b/examples/example2.js @@ -1,53 +1,62 @@ example(); function example() { -var tasks = [ -{"startDate":new Date("Sun Dec 09 01:36:45 EST 2012"),"endDate":new Date("Sun Dec 09 02:36:45 EST 2012"),"taskName":"E Job","status":"RUNNING"}]; - -var taskStatus = { - "SUCCEEDED" : "bar", - "FAILED" : "bar-failed", - "RUNNING" : "bar-running", - "KILLED" : "bar-killed" -}; - -var taskNames = [ "D Job", "P Job", "E Job", "A Job", "N Job" ]; - -tasks.sort(function(a, b) { - return a.endDate - b.endDate; -}); -var maxDate = tasks[tasks.length - 1].endDate; -tasks.sort(function(a, b) { - return a.startDate - b.startDate; -}); -var minDate = tasks[0].startDate; - -var format = "%H:%M"; - -var gantt = d3.gantt().taskTypes(taskNames).taskStatus(taskStatus).tickFormat(format); -//gantt.timeDomain([new Date("Sun Dec 09 04:54:19 EST 2012"),new Date("Sun Jan 09 04:54:19 EST 2013")]); -//gantt.timeDomainMode("fixed"); -gantt(tasks); - - -example.addTask = function() { - - var lastEndDate = Date.now(); - if (tasks.length > 0) { - lastEndDate = tasks[tasks.length - 1].endDate; - } - - var taskStatusKeys = Object.keys(taskStatus); - var taskStatusName = taskStatusKeys[Math.floor(Math.random()*taskStatusKeys.length)]; - var taskName = taskNames[Math.floor(Math.random()*taskNames.length)]; - - tasks.push({"startDate":d3.time.hour.offset(lastEndDate,Math.ceil(1*Math.random())),"endDate":d3.time.hour.offset(lastEndDate,(Math.ceil(Math.random()*3))+1),"taskName":taskName,"status":taskStatusName}); - gantt.redraw(tasks); -}; - -example.removeTask = function() { - tasks.pop(); - gantt.redraw(tasks); -}; - -}; + var tasks = [ + {"startDate": new Date("Sun Dec 09 01:36:45 EST 2012"), "endDate": new Date("Sun Dec 09 02:36:45 EST 2012"), "taskName": "E Job", "status": "RUNNING", title: "Text content of task"} + ]; + + var taskStatus = { + "SUCCEEDED" : "bar", + "FAILED" : "bar-failed", + "RUNNING" : "bar-running", + "KILLED" : "bar-killed" + }; + + var taskNames = [ "D Job", "P Job", "E Job", "A Job", "N Job" ]; + + var taskTitles = ['Random text content of task 1', 'Random text content of task 2', 'Random text content of task 3', 'Random text content of task 4']; + + tasks.sort(function(a, b) { + return a.endDate - b.endDate; + }); + var maxDate = tasks[tasks.length - 1].endDate; + tasks.sort(function(a, b) { + return a.startDate - b.startDate; + }); + var minDate = tasks[0].startDate; + + var format = "%H:%M"; + + var gantt = d3.gantt().taskTypes(taskNames).taskStatus(taskStatus).tickFormat(format); + //gantt.timeDomain([new Date("Sun Dec 09 04:54:19 EST 2012"),new Date("Sun Jan 09 04:54:19 EST 2013")]); + //gantt.timeDomainMode("fixed"); + gantt(tasks); + + + example.addTask = function() { + + var lastEndDate = Date.now(); + if (tasks.length > 0) { + lastEndDate = tasks[tasks.length - 1].endDate; + } + + var taskStatusKeys = Object.keys(taskStatus); + var taskStatusName = taskStatusKeys[Math.floor(Math.random() * taskStatusKeys.length)]; + var taskName = taskNames[Math.floor(Math.random() * taskNames.length)]; + var taskRandomTitle = taskTitles[Math.floor(Math.random() * taskTitles.length)]; + + tasks.push({ + "startDate":d3.time.hour.offset(lastEndDate,Math.ceil(1*Math.random())), + "endDate":d3.time.hour.offset(lastEndDate,(Math.ceil(Math.random()*3))+1), + "taskName":taskName, + "status":taskStatusName, + "title": taskRandomTitle + }); + gantt.redraw(tasks); + }; + + example.removeTask = function() { + tasks.pop(); + gantt.redraw(tasks); + }; +} diff --git a/examples/example3.html b/examples/example3.html index 4be9dbe..1986f7d 100644 --- a/examples/example3.html +++ b/examples/example3.html @@ -16,6 +16,7 @@ +
diff --git a/examples/example3.js b/examples/example3.js index b75dfce..9727065 100644 --- a/examples/example3.js +++ b/examples/example3.js @@ -1,5 +1,6 @@ var tasks = [ -{"startDate":new Date("Sun Dec 09 01:36:45 EST 2012"),"endDate":new Date("Sun Dec 09 02:36:45 EST 2012"),"taskName":"E Job","status":"RUNNING"}]; + {"startDate": new Date("Sun Dec 09 01:36:45 EST 2012"), "endDate": new Date("Sun Dec 09 02:36:45 EST 2012"), "taskName": "E Job", "status": "RUNNING", title: "Text content of task"} +]; var taskStatus = { "SUCCEEDED" : "bar", @@ -10,6 +11,8 @@ var taskStatus = { var taskNames = [ "D Job", "P Job", "E Job", "A Job", "N Job" ]; +var taskTitles = ['Random text content of task 1', 'Random text content of task 2', 'Random text content of task 3', 'Random text content of task 4']; + tasks.sort(function(a, b) { return a.endDate - b.endDate; }); @@ -39,33 +42,35 @@ gantt(tasks); function changeTimeDomain(timeDomainString) { this.timeDomainString = timeDomainString; + switch (timeDomainString) { - case "1hr": - format = "%H:%M:%S"; - gantt.timeDomain([ d3.time.hour.offset(getEndDate(), -1), getEndDate() ]); - break; - case "3hr": - format = "%H:%M"; - gantt.timeDomain([ d3.time.hour.offset(getEndDate(), -3), getEndDate() ]); - break; - - case "6hr": - format = "%H:%M"; - gantt.timeDomain([ d3.time.hour.offset(getEndDate(), -6), getEndDate() ]); - break; - - case "1day": - format = "%H:%M"; - gantt.timeDomain([ d3.time.day.offset(getEndDate(), -1), getEndDate() ]); - break; - - case "1week": - format = "%a %H:%M"; - gantt.timeDomain([ d3.time.day.offset(getEndDate(), -7), getEndDate() ]); - break; - default: - format = "%H:%M" + case "1hr": + format = "%H:%M:%S"; + gantt.timeDomain([ d3.time.hour.offset(getEndDate(), -1), getEndDate() ]); + break; + + case "3hr": + format = "%H:%M"; + gantt.timeDomain([ d3.time.hour.offset(getEndDate(), -3), getEndDate() ]); + break; + + case "6hr": + format = "%H:%M"; + gantt.timeDomain([ d3.time.hour.offset(getEndDate(), -6), getEndDate() ]); + break; + + case "1day": + format = "%H:%M"; + gantt.timeDomain([ d3.time.day.offset(getEndDate(), -1), getEndDate() ]); + break; + + case "1week": + format = "%a %H:%M"; + gantt.timeDomain([ d3.time.day.offset(getEndDate(), -7), getEndDate() ]); + break; + default: + format = "%H:%M"; } gantt.tickFormat(format); gantt.redraw(tasks); @@ -74,7 +79,7 @@ function changeTimeDomain(timeDomainString) { function getEndDate() { var lastEndDate = Date.now(); if (tasks.length > 0) { - lastEndDate = tasks[tasks.length - 1].endDate; + lastEndDate = tasks[tasks.length - 1].endDate; } return lastEndDate; @@ -86,17 +91,19 @@ function addTask() { var taskStatusKeys = Object.keys(taskStatus); var taskStatusName = taskStatusKeys[Math.floor(Math.random() * taskStatusKeys.length)]; var taskName = taskNames[Math.floor(Math.random() * taskNames.length)]; + var taskRandomTitle = taskTitles[Math.floor(Math.random() * taskTitles.length)]; tasks.push({ - "startDate" : d3.time.hour.offset(lastEndDate, Math.ceil(1 * Math.random())), - "endDate" : d3.time.hour.offset(lastEndDate, (Math.ceil(Math.random() * 3)) + 1), - "taskName" : taskName, - "status" : taskStatusName + "startDate" : d3.time.hour.offset(lastEndDate, Math.ceil(1 * Math.random())), + "endDate" : d3.time.hour.offset(lastEndDate, (Math.ceil(Math.random() * 3)) + 1), + "taskName" : taskName, + "status" : taskStatusName, + "title": taskRandomTitle }); changeTimeDomain(timeDomainString); gantt.redraw(tasks); -}; +} function removeTask() { tasks.pop(); From 14922bf66546f802a9d30a7e06fbb564a474a37d Mon Sep 17 00:00:00 2001 From: Jonybang Date: Sun, 12 Apr 2015 19:35:08 +1000 Subject: [PATCH 3/5] fix stuck blocks --- gantt-chart-d3.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/gantt-chart-d3.js b/gantt-chart-d3.js index cddf256..08b0b14 100644 --- a/gantt-chart-d3.js +++ b/gantt-chart-d3.js @@ -42,7 +42,7 @@ d3.gantt = function() { return d.title; } - var initTimeDomain = function() { + var initTimeDomain = function(tasks) { if (timeDomainMode === FIT_TIME_DOMAIN_MODE) { if (tasks === undefined || tasks.length < 1) { timeDomainStart = d3.time.day.offset(new Date(), -3); @@ -91,7 +91,7 @@ d3.gantt = function() { initAxis(); function gantt(tasks) { - initTimeDomain(); + initTimeDomain(tasks); initAxis(); var svg = d3.select("#"+containerId) @@ -150,7 +150,7 @@ d3.gantt = function() { gantt.redraw = function(tasks) { - initTimeDomain(); + initTimeDomain(tasks); initAxis(); var svg = d3.select("svg"); @@ -180,6 +180,15 @@ d3.gantt = function() { .transition() .call(confRect); + //FIXME, code for redraw stuck blocks + svg.select(".gantt-chart") + .selectAll(".task") + .selectAll("*") + .data(tasks, keyFunction) + .exit() + .transition() + .attr('width', 0).remove(); + var gText = gTasks.append("text") .call(confText) .text(getText) From d275ee1ace44991695e4d588f0b9e875eec4ab5e Mon Sep 17 00:00:00 2001 From: Jonybang Date: Sun, 12 Apr 2015 19:36:44 +1000 Subject: [PATCH 4/5] new screenshots --- examples/screenshot1.png | Bin 14685 -> 20425 bytes examples/screenshot2.png | Bin 9425 -> 16940 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/examples/screenshot1.png b/examples/screenshot1.png index 331264b2d73321a118afd32a0218c9961ce09c67..a257eb6b913a0d031c41c0c6f59ac073968b3b01 100644 GIT binary patch literal 20425 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%0D}|)kfAsW;WtY%EEe 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 diff --git a/examples/screenshot2.png b/examples/screenshot2.png index 30e26bc4ad86fe479b8506d23aaff2163ddf2f99..128595d98454762b2077d9d78746df4b28240ea6 100644 GIT binary patch literal 16940 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 Lf0UlTdG~(-1&yhn literal 9425 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 From e392538d420ee7de7564e4618769ab25d9585b70 Mon Sep 17 00:00:00 2001 From: Jonybang Date: Sun, 12 Apr 2015 19:53:06 +1000 Subject: [PATCH 5/5] edit readme --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index af516be..486fb8a 100644 --- a/README.md +++ b/README.md @@ -12,19 +12,20 @@ Create a array of all your data. ```javascript var tasks = [ - { "startDate": new Date("Sun Dec 09 01:36:45 EST 2012"), "endDate": new Date("Sun Dec 09 02:36:45 EST 2012"), "taskName": "E Job", - "status": "FAILED" + "status": "FAILED", + "title": "Text content of task 1" }, { "startDate": new Date("Sun Dec 09 04:56:32 EST 2012"), "endDate": new Date("Sun Dec 09 06:35:47 EST 2012"), "taskName": "A Job", - "status": "RUNNING" + "status": "RUNNING", + "title": "Text content of task 2" }]; ```