var taskStatus = {'Stand':'Stand', 'Table ronde':'Table-ronde', 'Atelier':'Atelier', 'Concert':'Concert', 'Conference':'Conference', 'Repas':'Repas'}; var tickFormat = "%H:%M"; var margin = { top : 15, right : 0, bottom : 0, left : 50 }; var height = 500; var width = 730; var Keys = Array(); var Salles = Array(); var Areas = Array(); var Tasks = Array(); d3.json("le-prog-json", function(error, json) { if (error) return console.warn(error); var Keys = Object.keys(json["all"]) // Build set of data in memory for (var k = 0; k < Keys.length; k++) { Salles[Keys[k]] = Array(); Areas[Keys[k]] = Array(); Tasks[Keys[k]] = json["all"][Keys[k]] // Fix Json to make date objects Tasks[Keys[k]].forEach(function(d) { d.startDate = new Date(d.startDate); d.endDate = new Date(d.endDate); }) // Build the list of Salles and Areas Tasks[Keys[k]].forEach(function(d) { Salles[Keys[k]].push( d.placeName ); Areas[Keys[k]].push( d.status ); } ) Salles[Keys[k]] = d3.set(Salles[Keys[k]]).values(); Areas[Keys[k]] = d3.set(Areas[Keys[k]]).values(); // Create Controls to Handle user selection Areas[Keys[k]].forEach(function(TypeArea) { d3.select("#Schedule_SVG_"+Keys[k]) .append("input") .attr("type", "checkbox") .attr("name", "OptTimetable-"+Keys[k]) .attr("id", TypeArea+"-"+Keys[k]) .attr("area", TypeArea) .style("float", "left") .style("margin-left", "5px") .property("checked",true); d3.select("#Schedule_SVG_"+Keys[k]) .append("label") .attr("for", TypeArea+"-"+Keys[k]) .style("float", "left") .style("margin-left", "5px") .text(TypeArea); }); // Create a dedicated SVG for it svg = d3.select("#Schedule_SVG_"+Keys[k]) .append("svg") .attr("id", "TimeTable-"+Keys[k]) .attr("width", width + margin.right + margin.left) .attr("height", height + margin.top + margin.bottom) //.attr("viewBox", "0 0 " + width + " " + height ) //.attr("preserveAspectRatio", "xMidYMid"); svg.append("g") .attr("class", "xAxis axis"); svg.append("g") .attr("class", "yAxis axis"); var chart = svg.append("g") .attr("class", "timetable"); HandleEvents(Keys[k]) displayit(json["all"][Keys[k]], Salles[Keys[k]], Keys[k]); } }); var keyFunction = function(d) { return d.startDate + d.placeName + d.endDate; }; function HandleEvents(Ctrl) { d3.selectAll("input[name=OptTimetable-"+Ctrl+"]") .data(Areas[Ctrl]) .on("change", function(TypeData) { ArrayChoice = Array() checked = d3.selectAll("input[name=OptTimetable-"+Ctrl+"]")[0] .forEach( function(v) { if (d3.select(v).node().checked) ArrayChoice.push(v.attributes['area'].value) } ) area_select = Array() selection = Tasks[Ctrl].filter(function(v) { return ArrayChoice.indexOf(v.status)>=0; }); if (selection.length) { selection.forEach(function(d) { area_select.push( d.placeName ); } ); area_select = d3.set(area_select).values(); displayit(selection, area_select, Ctrl); d3.select("#TimeTable-"+Ctrl)[0][0].style.opacity = 1; } else { d3.select("#TimeTable-"+Ctrl)[0][0].style.opacity = 0; } }); } function displayit(Set_of_Task, Set_of_Area, key) { // Try to compute time range Set_of_Task.sort(function(a, b) { return a.startDate - b.startDate; }); timeDomainStart = Set_of_Task[0].startDate; Set_of_Task.sort(function(a, b) { return a.endDate - b.endDate; }); timeDomainEnd = Set_of_Task[Set_of_Task.length - 1].endDate; // Prepare scales xScale = d3.scale.ordinal() .domain(Set_of_Area) .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); var svg = d3.select("#TimeTable-"+key); var chart = svg.select(".timetable") var content = chart.selectAll("foreignObject") .data(Set_of_Task, keyFunction); content.enter() .insert("foreignObject",":first-child") .append("xhtml:div") .html(function(d) { return '
' + d.desc + '
' }) .transition() .duration(750); content.transition() .duration(750) .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() .transition() .duration(300) .style("opacity", 1e-6) .remove(); var rect = chart.selectAll("rect") .data(Set_of_Task, keyFunction); rect.enter() .insert("rect",":first-child") .attr("rx", 5) .attr("ry", 5) .attr("filter", "url(/img/shadow.svg#dropshadow)") .attr("style", function(d){ return "fill:url(/img/shadow.svg#BoxGradient-"+ taskStatus[d.status] +")" }) .attr("class", function(d){ if(taskStatus[d.status] == null) { return "bar";} return taskStatus[d.status]; }) .transition() .duration(750) rect.transition() .duration(750) .attr("x", function(d){ return xScale(d.placeName || "unk"); }) .attr("y", function(d){ return yScale( d.startDate )+1; }) .attr("width", function(d) { return xScale.rangeBand(); }) .attr("height", function(d) { return (yScale( d.endDate ) - yScale( d.startDate )-2); }); rect.exit() .transition() .duration(300) .style("opacity", 1e-6) .remove(); svg.select(".yAxis") .attr("transform", "translate("+ margin.left +","+ margin.top +")") .transition() .call(yAxis); svg.select(".xAxis") .attr("transform", "translate("+ margin.left +","+ margin.top +")") .transition() .call(xAxis); chart.attr("transform", "translate("+ margin.left +","+ margin.top +")"); }