Le repo des sources pour le site web des JM2L
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

329 lines
10 KiB

  1. var taskStatus = {'Stand':'Stand',
  2. 'Table ronde':'Table-ronde',
  3. 'Atelier':'Atelier',
  4. 'Concert':'Concert',
  5. 'Conference':'Conference',
  6. 'Repas':'Repas'};
  7. var tickFormat = "%H:%M";
  8. var margin = {
  9. top : 15,
  10. right : 0,
  11. bottom : 0,
  12. left : 50
  13. };
  14. var height = 500;
  15. var width = 730;
  16. var Keys = Array();
  17. var Salles = Array();
  18. var Areas = Array();
  19. var Tasks = Array();
  20. d3.json("le-prog-json",
  21. function(error, json) {
  22. if (error) return console.warn(error);
  23. var Keys = Object.keys(json["all"]);
  24. // Build set of data in memory
  25. for (var k = 0; k < Keys.length; k++) {
  26. Salles[Keys[k]] = Array();
  27. Areas[Keys[k]] = Array();
  28. Tasks[Keys[k]] = json["all"][Keys[k]];
  29. // Fix Json to make date objects
  30. Tasks[Keys[k]].forEach(function(d) {
  31. d.startDate = new Date(d.startDate);
  32. d.endDate = new Date(d.endDate);
  33. });
  34. // Build the list of Salles and Areas
  35. Tasks[Keys[k]].forEach(function(d) {
  36. Salles[Keys[k]].push( d.placeName );
  37. Areas[Keys[k]].push( d.status );
  38. } );
  39. Salles[Keys[k]] = d3.set(Salles[Keys[k]]).values();
  40. Areas[Keys[k]] = d3.set(Areas[Keys[k]]).values();
  41. // Create Controls to Handle user selection
  42. Areas[Keys[k]].forEach(function(TypeArea) {
  43. d3.select("#Schedule_SVG_"+Keys[k])
  44. .append("input")
  45. .attr("type", "checkbox")
  46. .attr("name", "OptTimetable-"+Keys[k])
  47. .attr("id", TypeArea+"-"+Keys[k])
  48. .attr("area", TypeArea)
  49. .style("float", "left")
  50. .style("margin-left", "20px")
  51. .style("margin-right", "3px")
  52. .property("checked",true);
  53. d3.select("#Schedule_SVG_"+Keys[k])
  54. .append("label")
  55. .attr("for", TypeArea+"-"+Keys[k])
  56. .style("float", "left")
  57. .style("margin-left", "5px")
  58. .text(TypeArea);
  59. });
  60. d3.select("#Schedule_SVG_"+Keys[k])
  61. .append("br");
  62. // Create a dedicated SVG for it
  63. svg = d3.select("#Schedule_SVG_"+Keys[k])
  64. .append("svg")
  65. .attr("id", "TimeTable-"+Keys[k])
  66. .attr("width", "100%") //width + margin.right + margin.left)
  67. //.attr("height", height + margin.top + margin.bottom)
  68. .attr("viewBox", "0 0 " + (width + margin.right + margin.left) + " " + (height + margin.top + margin.bottom) )
  69. .attr("preserveAspectRatio", "xMidYMid meet");
  70. // Add some gradient
  71. header(svg);
  72. // Create axis
  73. svg.append("g")
  74. .attr("class", "xAxis axis");
  75. svg.append("g")
  76. .attr("class", "yAxis axis");
  77. var chart = svg.append("g")
  78. .attr("class", "timetable");
  79. HandleEvents(Keys[k]);
  80. displayit(json["all"][Keys[k]], Salles[Keys[k]], Keys[k]);
  81. }
  82. });
  83. function header(svg) {
  84. defs = svg.append("svg:defs");
  85. conf = defs.append("svg:linearGradient")
  86. .attr("id", "BoxGradient-Conference")
  87. .attr("x1", "100%")
  88. .attr("y1", "0%")
  89. .attr("x2", "50%")
  90. .attr("y2", "100%")
  91. .attr("spreadMethod", "pad");
  92. conf.append("svg:stop")
  93. .attr("offset", "0%")
  94. .attr("stop-color", "#EEE")
  95. .attr("stop-opacity", 0);
  96. conf.append("svg:stop")
  97. .attr("offset", "15%")
  98. .attr("stop-color", "#BDF86B")
  99. .attr("stop-opacity", .5);
  100. atlier = defs.append("svg:linearGradient")
  101. .attr("id", "BoxGradient-Atelier")
  102. .attr("x1", "100%")
  103. .attr("y1", "0%")
  104. .attr("x2", "50%")
  105. .attr("y2", "100%")
  106. .attr("spreadMethod", "pad");
  107. atlier.append("svg:stop")
  108. .attr("offset", "0%")
  109. .attr("stop-color", "#EEE")
  110. .attr("stop-opacity", 0);
  111. atlier.append("svg:stop")
  112. .attr("offset", "15%")
  113. .attr("stop-color", "#FF856E")
  114. .attr("stop-opacity", .5);
  115. // append filter element
  116. var filter = defs.append( 'filter' )
  117. .attr( 'id', 'dropshadow' ); /// !!! important - define id to reference it later
  118. // append gaussian blur to filter
  119. filter.append( 'feGaussianBlur' )
  120. .attr( 'in', 'SourceAlpha' )
  121. .attr( 'stdDeviation', 3 ) // !!! important parameter - blur
  122. .attr( 'result', 'blur' );
  123. // append offset filter to result of gaussion blur filter
  124. filter.append( 'feOffset' )
  125. .attr( 'in', 'blur' )
  126. .attr( 'dx', 2 ) // !!! important parameter - x-offset
  127. .attr( 'dy', 2 ) // !!! important parameter - y-offset
  128. .attr( 'result', 'offsetBlur' );
  129. filter.append( 'feComponentTransfer' )
  130. .append( 'feFuncA' )
  131. .attr( "type", "linear" )
  132. .attr( "slope", "0.4" );
  133. // merge result with original image
  134. var feMerge = filter.append( 'feMerge' );
  135. // first layer result of blur and offset
  136. feMerge.append( 'feMergeNode' )
  137. .attr( 'in", "offsetBlur' );
  138. // original image on top
  139. feMerge.append( 'feMergeNode' )
  140. .attr( 'in', 'SourceGraphic' );
  141. // end filter stuff
  142. }
  143. var keyFunction = function(d) {
  144. return d.startDate + d.placeName + d.endDate;
  145. };
  146. function HandleEvents(Ctrl) {
  147. d3.selectAll("input[name=OptTimetable-"+Ctrl+"]")
  148. .data(Areas[Ctrl])
  149. .on("change", function(TypeData) {
  150. ArrayChoice = Array();
  151. checked = d3.selectAll("input[name=OptTimetable-"+Ctrl+"]")[0]
  152. .forEach( function(v)
  153. {
  154. if (d3.select(v).node().checked)
  155. ArrayChoice.push(v.attributes['area'].value);
  156. }
  157. );
  158. area_select = Array();
  159. selection = Tasks[Ctrl].filter(function(v) {
  160. return ArrayChoice.indexOf(v.status)>=0;
  161. });
  162. if (selection.length) {
  163. selection.forEach(function(d)
  164. { area_select.push( d.placeName ); }
  165. );
  166. area_select = d3.set(area_select).values();
  167. displayit(selection, area_select, Ctrl);
  168. d3.select("#TimeTable-"+Ctrl)[0][0].style.opacity = 1;
  169. } else {
  170. d3.select("#TimeTable-"+Ctrl)[0][0].style.opacity = 0;
  171. }
  172. });
  173. }
  174. function displayit(Set_of_Task, Set_of_Area, key) {
  175. // Try to compute time range
  176. Set_of_Task.sort(function(a, b) {
  177. return a.startDate - b.startDate;
  178. });
  179. timeDomainStart = Set_of_Task[0].startDate;
  180. Set_of_Task.sort(function(a, b) {
  181. return a.endDate - b.endDate;
  182. });
  183. timeDomainEnd = Set_of_Task[Set_of_Task.length - 1].endDate;
  184. // Prepare scales
  185. xScale = d3.scale.ordinal()
  186. .domain(Set_of_Area)
  187. .rangeRoundBands([ 0, width ], .1);
  188. yScale = d3.time.scale()
  189. .domain([ timeDomainStart, timeDomainEnd ])
  190. .range([ 0, height - margin.top - margin.bottom ])
  191. .clamp(true);
  192. xAxis = d3.svg.axis()
  193. .scale(xScale)
  194. .orient("top")
  195. .tickSize(1);
  196. yAxis = d3.svg.axis()
  197. .scale(yScale)
  198. .orient("left")
  199. .tickFormat(d3.time.format(tickFormat))
  200. .tickSubdivide(true)
  201. .tickSize(8)
  202. .tickPadding(8);
  203. var svg = d3.select("#TimeTable-"+key);
  204. var chart = svg.select(".timetable");
  205. var rect = chart.selectAll("rect")
  206. .data(Set_of_Task, keyFunction);
  207. rect.enter()
  208. .insert("rect")
  209. .attr("rx", 5)
  210. .attr("ry", 5)
  211. .attr("filter", "url(#dropshadow)")
  212. .style("fill", function(d){
  213. return "url(#BoxGradient-"+ taskStatus[d.status] +")";
  214. })
  215. .attr("class", function(d){
  216. if(taskStatus[d.status] == null)
  217. { return "bar";}
  218. return taskStatus[d.status];
  219. })
  220. .transition()
  221. .duration(750);
  222. rect.transition()
  223. .duration(750)
  224. .attr("x", function(d){
  225. return xScale(d.placeName || "unk");
  226. })
  227. .attr("y", function(d){
  228. return yScale( d.startDate )+1;
  229. })
  230. .attr("width", function(d) {
  231. return xScale.rangeBand();
  232. })
  233. .attr("height", function(d) {
  234. return (yScale( d.endDate ) - yScale( d.startDate )-2);
  235. });
  236. rect.exit()
  237. .transition()
  238. .duration(300)
  239. .style("opacity", 1e-6)
  240. .remove();
  241. var content = chart.selectAll("foreignObject")
  242. .data(Set_of_Task, keyFunction);
  243. content.enter()
  244. .insert("foreignObject")
  245. .append("xhtml:div")
  246. .attr("class", "SvgBody")
  247. .html(function(d) {
  248. return '<div class="EvtBox '+ taskStatus[d.status] +'"><a href="/event/'+ d.uid +
  249. '">' + d.desc + '</a></div>';
  250. })
  251. .transition()
  252. .duration(750);
  253. content.transition()
  254. .duration(750)
  255. .attr("x", function(d){
  256. return xScale(d.placeName || "unk");
  257. })
  258. .attr("y", function(d){
  259. return yScale( d.startDate );
  260. })
  261. .attr("width", function(d) {
  262. return xScale.rangeBand();
  263. })
  264. .attr("height", function(d) {
  265. return (yScale( d.endDate ) - yScale( d.startDate ));
  266. });
  267. // .attr("transform" ,"scale(1)");
  268. content.exit()
  269. .transition()
  270. .duration(300)
  271. .style("opacity", 1e-6)
  272. .remove();
  273. svg.select(".yAxis")
  274. .attr("transform", "translate("+ margin.left +","+ margin.top +")")
  275. .transition()
  276. .call(yAxis);
  277. svg.select(".xAxis")
  278. .attr("transform", "translate("+ margin.left +","+ margin.top +")")
  279. .transition()
  280. .call(xAxis);
  281. chart.attr("transform", "translate("+ margin.left +","+ margin.top +")");
  282. }