/** * inspired from @author Dimitry Kudrayvtsev * @author tr4ck3ur */ d3.sched = function(EventType) { var FIT_TIME_DOMAIN_MODE = "fit"; var FIXED_TIME_DOMAIN_MODE = "fixed"; var myname = EventType; var margin = { top : 15, right : 10, bottom : 10, left : 50 }; var timeDomainStart = d3.time.hour.offset(new Date(),-2); var timeDomainEnd = d3.time.hour.offset(new Date(),+2); var timeDomainMode = FIT_TIME_DOMAIN_MODE;// fixed or fit var taskTypes = []; var taskStatus = []; //var height = document.body.clientHeight - margin.top - margin.bottom-5; height = 700; //var width = document.body.clientWidth - margin.right - margin.left-5; var width = 700;// - margin.right - margin.left; var tickFormat = "%H:%M"; var lastscale = -1; var xScale = d3.scale.ordinal() .domain(taskTypes) .rangeRoundBands([ 0, width - margin.left], .1); var yScale = d3.time.scale() .domain([ timeDomainStart, timeDomainEnd ]) .range([ 0, height - margin.top ]) //- margin.bottom ]); .clamp(true); var xAxis = d3.svg.axis() .scale(xScale) .orient("left") .tickSize(1); var yAxis = d3.svg.axis() .scale(yScale) .orient("bottom") .tickFormat(d3.time.format(tickFormat)) .tickSubdivide(true) .tickSize(8).tickPadding(8); var keyFunction = function(d) { return d.startDate + d.placeName + d.endDate; }; var rectTransform = function(d) { return "translate(" + xScale(d.placeName) + "," + yScale(d.startDate) + ")"; }; 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; } }; var initAxis = function() { xScale = d3.scale.ordinal() .domain(taskTypes) .rangeRoundBands([ 0, width ], .1); yScale = d3.time.scale() .domain([ timeDomainStart, timeDomainEnd ]) .range([ 0, height - margin.top - margin.bottom ]) .clamp(true); xAxis = d3.svg.axis() .scale(xScale) .orient("top") .tickSize(1); yAxis = d3.svg.axis() .scale(yScale) .orient("left") .tickFormat(d3.time.format(tickFormat)) .tickSubdivide(true) .tickSize(8) .tickPadding(8); }; function sched(tasks) { initTimeDomain(tasks); initAxis(); function zoomed() { var px = d3.event.translate[0]; var py = d3.event.translate[1]; var dx = 0; timeDomainStart = d3.time.hour.offset( timeDomainStart, 0) if (py>0) { dx = timeDomainStart.getTime()-yScale.invert(py).getTime() } else { dx = -timeDomainStart.getTime()+yScale.invert(-py).getTime() } NewStart = d3.time.hour.offset( timeDomainStart.getTime()+dx, 0) //NewEnd = d3.time.hour.offset( timeDomainStart.getTime()+dx, 0) //.3*d3.event.scale) //yScale.domain([ NewStart , NewEnd ]) sched.timeDomainMode("fit") //sched.timeDomain([ NewStart , NewEnd ]); //timeDomainStart = NewStart //timeDomainEnd = NewEnd var dy = py; var dz = timeDomainEnd-timeDomainStart if (py>0) var dx = timeDomainStart-yScale.invert(py).getTime() else var dx = -timeDomainStart+yScale.invert(-py).getTime() //yScale.domain([ timeDomainStart, d3.time.hour.offset(timeDomainStart, d3.event.scale*4) ]) // .range([ 0, height - margin.top - margin.bottom ]) // .clamp(true); //yScale2.domain([ NewStart, d3.time.hour.offset(NewStart, d3.event.scale*4) ]) // .range([ 0, height - margin.top - margin.bottom ]) // .clamp(true); // if (0 && lastscale!=d3.event.scale) { lastscale = d3.event.scale; yScale.domain([ timeDomainStart, d3.time.hour.offset(timeDomainStart, d3.event.scale*4) ]) .range([ 0, height - margin.top - margin.bottom ]) .clamp(true); //Saved = chart.attr("transform"); //coords = Saved.slice(Saved.search(/([0-9]+)/g),Saved.length-1).split(','); //chart.attr("transform", "translate(" + px + "," + py + ")"); //zoom.translate((80,120)) //zoom.center([121, 21]) //sched.redraw(this.id, tasks); //zoom.translate() //chart.attr("transform", "translate(" + parseInt(coords[0])+px + "," + parseInt(coords[1])+py + ")"); //chart.attr("transform", "translate(" + 121 + "," + 21 + ")"); chart.attr("transform", "translate(" + px + "," + py + ")"); } // else { // chart.attr("transform", "translate(" + px + "," + py + ")"); //} var dxr = d3.time.hour.offset( timeDomainStart+dx, 0) //ind.text( py +" "+ dz +" => "+ d3.event.scale ) //if ( DragLimit.xmin < (-px) && (-px) < DragLimit.xmax ) { // } else { // d3.event.sourceEvent.stopPropagation(); // } //sched.redraw(tasks); //sched.timeDomain([ d3.time.hour.offset(mystart,0), d3.time.hour.offset(mystart, d3.event.scale) ]); if (1) { svg.select(".yAxis") .attr("transform", "translate("+ margin.left +","+ margin.top +")")// + py + ")") .transition() .call(yAxis); //svg.select(".yAxis2") // .attr("transform", "translate(80,0)") // .call(yAxis2); svg.select(".xAxis") .attr("transform", "translate("+ margin.left +","+ margin.top +")") .transition() .call(xAxis); chart.attr("transform", "translate("+ margin.left +","+ margin.top +")"); } } var zoom = d3.behavior.zoom() .scaleExtent([1, 4]) .on("zoom", zoomed); var svg = d3.select("#Schedule_"+EventType) .append("svg") .attr("id", EventType) .attr("class", "chart") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .call(zoom); var chart = svg.append("g") .attr("class", "sched-chart"); chart.selectAll(".sched-chart") .data(tasks, keyFunction).enter() .append("rect") .attr("class", function(d){ if(taskStatus[d.status] == null) { return "bar";} return taskStatus[d.status]; }); if (0) { chart.selectAll('.foreignObject') .data(tasks, keyFunction).enter() .append('foreignObject') .attr("x", function(d){ return xScale(d.placeName || "unk"); }) .attr("y", function(d){ return yScale(d.startDate); }) //.attr("y", 0) //.attr("x", 2) //.attr("transform", rectTransform) .attr("width", function(d) { return xScale.rangeBand(); }) .attr("height", function(d) { return (yScale(d.endDate) - yScale(d.startDate)); }) .append("xhtml:div") .html(function(d) { return '
' + d.desc + '
' }); } /* svg.selectAll("text") .data(tasks, keyFunction).enter() .append("text") .text(function(d) { return d.desc; }) .attr("x", 2) .attr("y", 16) .attr("transform", rectTransform) .attr("width", function(d) { return x.rangeBand(); }) .fill('blue'); */ svg.append("g") .attr("class", "xAxis axis"); svg.append("g") .attr("class", "yAxis axis"); //zoomed(); //sched.redraw(tasks); return sched; }; sched.redraw = function(who, tasks) { //initTimeDomain(tasks); //initAxis(); var svg = d3.select("#"+who); var schedChartGroup = svg.select(".sched-chart"); var rect = schedChartGroup.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("x", function(d){ return xScale(d.placeName || "unk"); }) .attr("y", function(d){ return yScale(d.startDate); }) //.attr("transform", rectTransform) .attr("width", function(d) { return xScale.rangeBand(); }) .attr("height", function(d) { return (yScale(d.endDate) - yScale(d.startDate)); }); rect.transition() //.attr("transform", rectTransform) .attr("x", function(d){ return xScale(d.placeName || "unk"); }) .attr("y", function(d){ return yScale(d.startDate); }) .attr("width", function(d) { return xScale.rangeBand(); }) .attr("height", function(d) { return (yScale(d.endDate) - yScale(d.startDate)); }); rect.exit() .remove(); var content = schedChartGroup.selectAll("foreignObject") .data(tasks, keyFunction); content.enter() .insert("foreignObject",":first-child") //.transition() .attr("x", function(d){ return xScale(d.placeName || "unk"); }) .attr("y", function(d){ return yScale(d.startDate); }) //.attr("transform", rectTransform) .attr("width", function(d) { return xScale.rangeBand(); }) .attr("height", function(d) { return (yScale(d.endDate) - yScale(d.startDate)); }) .append("xhtml:div") .html(function(d) { return '
' + d.desc + '
' }); content.transition() //.attr("transform", rectTransform) .attr("x", function(d){ return xScale(d.placeName || "unk"); }) .attr("y", function(d){ return yScale(d.startDate); }) .attr("width", function(d) { return xScale.rangeBand(); }) .attr("height", function(d) { return (yScale(d.endDate) - yScale(d.startDate)); }); content.exit() .remove(); return sched; }; sched.margin = function(value) { if (!arguments.length) return margin; margin = value; return sched; }; sched.timeDomain = function(value) { if (!arguments.length) return [ timeDomainStart, timeDomainEnd ]; timeDomainStart = +value[0], timeDomainEnd = +value[1]; return sched; }; /** * @param {string} * vale The value can be "fit" - the domain fits the data or * "fixed" - fixed domain. */ sched.timeDomainMode = function(value) { if (!arguments.length) return timeDomainMode; timeDomainMode = value; return sched; }; sched.taskTypes = function(value) { if (!arguments.length) return taskTypes; taskTypes = value; return sched; }; sched.taskStatus = function(value) { if (!arguments.length) return taskStatus; taskStatus = value; return sched; }; sched.width = function(value) { if (!arguments.length) return width; width = +value; return sched; }; sched.height = function(value) { if (!arguments.length) return height; height = +value; return sched; }; sched.tickFormat = function(value) { if (!arguments.length) return tickFormat; tickFormat = value; return sched; }; sched.name = function(value) { if (!arguments.length) return myname; myname = value; return sched; }; return sched; };