Le repo des sources pour le site web des JM2L
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 

367 Zeilen
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. }