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.
 
 
 
 
 

367 lines
11 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, Keys[k]);
  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, day) {
  84. defs = svg.append("svg:defs");
  85. conf = defs.append("svg:linearGradient")
  86. .attr("id", "BoxGradient-Conference-"+day)
  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-"+day)
  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. tabler = defs.append("svg:linearGradient")
  116. .attr("id", "BoxGradient-Table-ronde-"+day)
  117. .attr("x1", "100%")
  118. .attr("y1", "0%")
  119. .attr("x2", "50%")
  120. .attr("y2", "100%")
  121. .attr("spreadMethod", "pad");
  122. tabler.append("svg:stop")
  123. .attr("offset", "0%")
  124. .attr("stop-color", "#EEE")
  125. .attr("stop-opacity", 0);
  126. tabler.append("svg:stop")
  127. .attr("offset", "15%")
  128. .attr("stop-color", "#B59EFF")
  129. .attr("stop-opacity", .5);
  130. undef = defs.append("svg:linearGradient")
  131. .attr("id", "BoxGradient-undefined-"+day)
  132. .attr("x1", "100%")
  133. .attr("y1", "0%")
  134. .attr("x2", "50%")
  135. .attr("y2", "100%")
  136. .attr("spreadMethod", "pad");
  137. undef.append("svg:stop")
  138. .attr("offset", "0%")
  139. .attr("stop-color", "#EEE")
  140. .attr("stop-opacity", 0);
  141. undef.append("svg:stop")
  142. .attr("offset", "15%")
  143. .attr("stop-color", "#359E35")
  144. .attr("stop-opacity", .5);
  145. // append filter element
  146. var filter = defs.append( 'filter' )
  147. .attr( 'id', 'dropshadow-'+day ); /// !!! important - define id to reference it later
  148. // append gaussian blur to filter
  149. filter.append( 'feGaussianBlur' )
  150. .attr( 'in', 'SourceAlpha' )
  151. .attr( 'stdDeviation', 3 ) // !!! important parameter - blur
  152. .attr( 'result', 'blur' );
  153. // append offset filter to result of gaussion blur filter
  154. filter.append( 'feOffset' )
  155. .attr( 'in', 'blur' )
  156. .attr( 'dx', 2 ) // !!! important parameter - x-offset
  157. .attr( 'dy', 2 ) // !!! important parameter - y-offset
  158. .attr( 'result', 'offsetBlur' );
  159. filter.append( 'feComponentTransfer' )
  160. .append( 'feFuncA' )
  161. .attr( "type", "linear" )
  162. .attr( "slope", "0.4" );
  163. // merge result with original image
  164. var feMerge = filter.append( 'feMerge' );
  165. // first layer result of blur and offset
  166. feMerge.append( 'feMergeNode' )
  167. .attr( 'in", "offsetBlur' );
  168. // original image on top
  169. feMerge.append( 'feMergeNode' )
  170. .attr( 'in', 'SourceGraphic' );
  171. // end filter stuff
  172. }
  173. var keyFunction = function(d) {
  174. return d.startDate + d.placeName + d.endDate;
  175. };
  176. function HandleEvents(Ctrl) {
  177. d3.selectAll("input[name=OptTimetable-"+Ctrl+"]")
  178. .data(Areas[Ctrl])
  179. .on("change", function(TypeData) {
  180. ArrayChoice = Array();
  181. checked = d3.selectAll("input[name=OptTimetable-"+Ctrl+"]")[0]
  182. .forEach( function(v)
  183. {
  184. if (d3.select(v).node().checked)
  185. ArrayChoice.push(v.attributes['area'].value);
  186. }
  187. );
  188. area_select = Array();
  189. selection = Tasks[Ctrl].filter(function(v) {
  190. return ArrayChoice.indexOf(v.status)>=0;
  191. });
  192. if (selection.length) {
  193. selection.forEach(function(d)
  194. { area_select.push( d.placeName ); }
  195. );
  196. area_select = d3.set(area_select).values();
  197. displayit(selection, area_select, Ctrl);
  198. d3.select("#TimeTable-"+Ctrl)[0][0].style.opacity = 1;
  199. } else {
  200. d3.select("#TimeTable-"+Ctrl)[0][0].style.opacity = 0;
  201. }
  202. });
  203. }
  204. function displayit(Set_of_Task, Set_of_Area, key) {
  205. // Try to compute time range
  206. Set_of_Task.sort(function(a, b) {
  207. return a.startDate - b.startDate;
  208. });
  209. timeDomainStart = Set_of_Task[0].startDate;
  210. Set_of_Task.sort(function(a, b) {
  211. return a.endDate - b.endDate;
  212. });
  213. timeDomainEnd = Set_of_Task[Set_of_Task.length - 1].endDate;
  214. // Prepare scales
  215. xScale = d3.scale.ordinal()
  216. .domain(Set_of_Area)
  217. .rangeRoundBands([ 0, width ], .1);
  218. yScale = d3.time.scale()
  219. .domain([ timeDomainStart, timeDomainEnd ])
  220. .range([ 0, height - margin.top - margin.bottom ])
  221. .clamp(true);
  222. xAxis = d3.svg.axis()
  223. .scale(xScale)
  224. .orient("top")
  225. .tickSize(1);
  226. yAxis = d3.svg.axis()
  227. .scale(yScale)
  228. .orient("left")
  229. .tickFormat(d3.time.format(tickFormat))
  230. .tickSubdivide(true)
  231. .tickSize(8)
  232. .tickPadding(8);
  233. var svg = d3.select("#TimeTable-"+key);
  234. var chart = svg.select(".timetable");
  235. var rect = chart.selectAll("rect")
  236. .data(Set_of_Task, keyFunction);
  237. rect.enter()
  238. .insert("rect")
  239. .attr("rx", 5)
  240. .attr("ry", 5)
  241. .attr("filter", "url(#dropshadow-" + key + ")")
  242. .style("fill", function(d){
  243. return "url(#BoxGradient-"+ taskStatus[d.status] + "-" + key + ")";
  244. })
  245. .attr("class", function(d){
  246. if(taskStatus[d.status] == null)
  247. { return "bar";}
  248. return taskStatus[d.status];
  249. })
  250. .transition()
  251. .duration(750);
  252. rect.transition()
  253. .duration(750)
  254. .attr("x", function(d){
  255. return xScale(d.placeName || "unk");
  256. })
  257. .attr("y", function(d){
  258. return yScale( d.startDate )+1;
  259. })
  260. .attr("width", function(d) {
  261. return xScale.rangeBand();
  262. })
  263. .attr("height", function(d) {
  264. return (yScale( d.endDate ) - yScale( d.startDate )-2);
  265. });
  266. rect.exit()
  267. .transition()
  268. .duration(300)
  269. .style("opacity", 1e-6)
  270. .remove();
  271. var content = chart.selectAll("foreignObject")
  272. .data(Set_of_Task, keyFunction);
  273. content.enter()
  274. .insert("foreignObject")
  275. .append("xhtml:div")
  276. .attr("class", "SvgBody")
  277. .html(function(d) {
  278. return '<div class="EvtBox '+ taskStatus[d.status] +'"><a href="/event/'+ d.uid +
  279. '">' + d.desc + '</a></div>';
  280. })
  281. .transition()
  282. .duration(750);
  283. content.transition()
  284. .duration(750)
  285. .attr("x", function(d){
  286. return xScale(d.placeName || "unk");
  287. })
  288. .attr("y", function(d){
  289. return yScale( d.startDate );
  290. })
  291. .attr("width", function(d) {
  292. return xScale.rangeBand();
  293. })
  294. .attr("height", function(d) {
  295. return (yScale( d.endDate ) - yScale( d.startDate ));
  296. });
  297. // .attr("transform" ,"scale(1)");
  298. content.exit()
  299. .transition()
  300. .duration(300)
  301. .style("opacity", 1e-6)
  302. .remove();
  303. svg.select(".yAxis")
  304. .attr("transform", "translate("+ margin.left +","+ margin.top +")")
  305. .transition()
  306. .call(yAxis);
  307. svg.select(".xAxis")
  308. .attr("transform", "translate("+ margin.left +","+ margin.top +")")
  309. .transition()
  310. .call(xAxis);
  311. chart.attr("transform", "translate("+ margin.left +","+ margin.top +")");
  312. }