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.
 
 
 
 
 

438 lines
13 KiB

  1. /**
  2. * inspired from @author Dimitry Kudrayvtsev
  3. * @author tr4ck3ur
  4. */
  5. d3.sched = function(EventType) {
  6. var FIT_TIME_DOMAIN_MODE = "fit";
  7. var FIXED_TIME_DOMAIN_MODE = "fixed";
  8. var myname = EventType;
  9. var margin = {
  10. top : 15,
  11. right : 10,
  12. bottom : 10,
  13. left : 50
  14. };
  15. var timeDomainStart = d3.time.hour.offset(new Date(),-2);
  16. var timeDomainEnd = d3.time.hour.offset(new Date(),+2);
  17. var timeDomainMode = FIT_TIME_DOMAIN_MODE;// fixed or fit
  18. var taskTypes = [];
  19. var taskStatus = [];
  20. //var height = document.body.clientHeight - margin.top - margin.bottom-5;
  21. height = 700;
  22. //var width = document.body.clientWidth - margin.right - margin.left-5;
  23. var width = 700;// - margin.right - margin.left;
  24. var tickFormat = "%H:%M";
  25. var lastscale = -1;
  26. var xScale = d3.scale.ordinal()
  27. .domain(taskTypes)
  28. .rangeRoundBands([ 0, width - margin.left], .1);
  29. var yScale = d3.time.scale()
  30. .domain([ timeDomainStart, timeDomainEnd ])
  31. .range([ 0, height - margin.top ]) //- margin.bottom ]);
  32. .clamp(true);
  33. var xAxis = d3.svg.axis()
  34. .scale(xScale)
  35. .orient("left")
  36. .tickSize(1);
  37. var yAxis = d3.svg.axis()
  38. .scale(yScale)
  39. .orient("bottom")
  40. .tickFormat(d3.time.format(tickFormat))
  41. .tickSubdivide(true)
  42. .tickSize(8).tickPadding(8);
  43. var keyFunction = function(d) {
  44. return d.startDate + d.placeName + d.endDate;
  45. };
  46. var rectTransform = function(d) {
  47. return "translate(" + xScale(d.placeName) + "," + yScale(d.startDate) + ")";
  48. };
  49. var initTimeDomain = function(tasks) {
  50. if (timeDomainMode === FIT_TIME_DOMAIN_MODE) {
  51. if (tasks === undefined || tasks.length < 1) {
  52. timeDomainStart = d3.time.day.offset(new Date(), -3);
  53. timeDomainEnd = d3.time.hour.offset(new Date(), +3);
  54. return;
  55. }
  56. tasks.sort(function(a, b) {
  57. return a.endDate - b.endDate;
  58. });
  59. timeDomainEnd = tasks[tasks.length - 1].endDate;
  60. tasks.sort(function(a, b) {
  61. return a.startDate - b.startDate;
  62. });
  63. timeDomainStart = tasks[0].startDate;
  64. }
  65. };
  66. var initAxis = function() {
  67. xScale = d3.scale.ordinal()
  68. .domain(taskTypes)
  69. .rangeRoundBands([ 0, width ], .1);
  70. yScale = d3.time.scale()
  71. .domain([ timeDomainStart, timeDomainEnd ])
  72. .range([ 0, height - margin.top - margin.bottom ])
  73. .clamp(true);
  74. xAxis = d3.svg.axis()
  75. .scale(xScale)
  76. .orient("top")
  77. .tickSize(1);
  78. yAxis = d3.svg.axis()
  79. .scale(yScale)
  80. .orient("left")
  81. .tickFormat(d3.time.format(tickFormat))
  82. .tickSubdivide(true)
  83. .tickSize(8)
  84. .tickPadding(8);
  85. };
  86. function sched(tasks) {
  87. initTimeDomain(tasks);
  88. initAxis();
  89. function zoomed() {
  90. var px = d3.event.translate[0];
  91. var py = d3.event.translate[1];
  92. var dx = 0;
  93. timeDomainStart = d3.time.hour.offset( timeDomainStart, 0)
  94. if (py>0) {
  95. dx = timeDomainStart.getTime()-yScale.invert(py).getTime()
  96. } else {
  97. dx = -timeDomainStart.getTime()+yScale.invert(-py).getTime()
  98. }
  99. NewStart = d3.time.hour.offset( timeDomainStart.getTime()+dx, 0)
  100. //NewEnd = d3.time.hour.offset( timeDomainStart.getTime()+dx, 0) //.3*d3.event.scale)
  101. //yScale.domain([ NewStart , NewEnd ])
  102. sched.timeDomainMode("fit")
  103. //sched.timeDomain([ NewStart , NewEnd ]);
  104. //timeDomainStart = NewStart
  105. //timeDomainEnd = NewEnd
  106. var dy = py;
  107. var dz = timeDomainEnd-timeDomainStart
  108. if (py>0)
  109. var dx = timeDomainStart-yScale.invert(py).getTime()
  110. else
  111. var dx = -timeDomainStart+yScale.invert(-py).getTime()
  112. //yScale.domain([ timeDomainStart, d3.time.hour.offset(timeDomainStart, d3.event.scale*4) ])
  113. // .range([ 0, height - margin.top - margin.bottom ])
  114. // .clamp(true);
  115. //yScale2.domain([ NewStart, d3.time.hour.offset(NewStart, d3.event.scale*4) ])
  116. // .range([ 0, height - margin.top - margin.bottom ])
  117. // .clamp(true);
  118. //
  119. if (0 && lastscale!=d3.event.scale) {
  120. lastscale = d3.event.scale;
  121. yScale.domain([ timeDomainStart, d3.time.hour.offset(timeDomainStart, d3.event.scale*4) ])
  122. .range([ 0, height - margin.top - margin.bottom ])
  123. .clamp(true);
  124. //Saved = chart.attr("transform");
  125. //coords = Saved.slice(Saved.search(/([0-9]+)/g),Saved.length-1).split(',');
  126. //chart.attr("transform", "translate(" + px + "," + py + ")");
  127. //zoom.translate((80,120))
  128. //zoom.center([121, 21])
  129. //sched.redraw(this.id, tasks);
  130. //zoom.translate()
  131. //chart.attr("transform", "translate(" + parseInt(coords[0])+px + "," + parseInt(coords[1])+py + ")");
  132. //chart.attr("transform", "translate(" + 121 + "," + 21 + ")");
  133. chart.attr("transform", "translate(" + px + "," + py + ")");
  134. }
  135. // else {
  136. // chart.attr("transform", "translate(" + px + "," + py + ")");
  137. //}
  138. var dxr = d3.time.hour.offset( timeDomainStart+dx, 0)
  139. //ind.text( py +" "+ dz +" => "+ d3.event.scale )
  140. //if ( DragLimit.xmin < (-px) && (-px) < DragLimit.xmax ) {
  141. // } else {
  142. // d3.event.sourceEvent.stopPropagation();
  143. // }
  144. //sched.redraw(tasks);
  145. //sched.timeDomain([ d3.time.hour.offset(mystart,0), d3.time.hour.offset(mystart, d3.event.scale) ]);
  146. if (1) {
  147. svg.select(".yAxis")
  148. .attr("transform", "translate("+ margin.left +","+ margin.top +")")// + py + ")")
  149. .transition()
  150. .call(yAxis);
  151. //svg.select(".yAxis2")
  152. // .attr("transform", "translate(80,0)")
  153. // .call(yAxis2);
  154. svg.select(".xAxis")
  155. .attr("transform", "translate("+ margin.left +","+ margin.top +")")
  156. .transition()
  157. .call(xAxis);
  158. chart.attr("transform", "translate("+ margin.left +","+ margin.top +")");
  159. }
  160. }
  161. var zoom = d3.behavior.zoom()
  162. .scaleExtent([1, 4])
  163. .on("zoom", zoomed);
  164. var svg = d3.select("#Schedule_"+EventType)
  165. .append("svg")
  166. .attr("id", EventType)
  167. .attr("class", "chart")
  168. .attr("width", width + margin.left + margin.right)
  169. .attr("height", height + margin.top + margin.bottom)
  170. .call(zoom);
  171. var chart = svg.append("g")
  172. .attr("class", "sched-chart");
  173. chart.selectAll(".sched-chart")
  174. .data(tasks, keyFunction).enter()
  175. .append("rect")
  176. .attr("class", function(d){
  177. if(taskStatus[d.status] == null)
  178. { return "bar";}
  179. return taskStatus[d.status];
  180. });
  181. if (0) {
  182. chart.selectAll('.foreignObject')
  183. .data(tasks, keyFunction).enter()
  184. .append('foreignObject')
  185. .attr("x", function(d){
  186. return xScale(d.placeName || "unk");
  187. })
  188. .attr("y", function(d){
  189. return yScale(d.startDate);
  190. })
  191. //.attr("y", 0)
  192. //.attr("x", 2)
  193. //.attr("transform", rectTransform)
  194. .attr("width", function(d) {
  195. return xScale.rangeBand();
  196. })
  197. .attr("height", function(d) {
  198. return (yScale(d.endDate) - yScale(d.startDate));
  199. })
  200. .append("xhtml:div")
  201. .html(function(d) {
  202. return '<div style="padding:2px;height:100%"><a href="/event/'+ d.uid +
  203. '">' + d.desc + '</a></div>'
  204. });
  205. }
  206. /* svg.selectAll("text")
  207. .data(tasks, keyFunction).enter()
  208. .append("text")
  209. .text(function(d) { return d.desc; })
  210. .attr("x", 2)
  211. .attr("y", 16)
  212. .attr("transform", rectTransform)
  213. .attr("width", function(d) {
  214. return x.rangeBand();
  215. })
  216. .fill('blue');
  217. */
  218. svg.append("g")
  219. .attr("class", "xAxis axis");
  220. svg.append("g")
  221. .attr("class", "yAxis axis");
  222. //zoomed();
  223. //sched.redraw(tasks);
  224. return sched;
  225. };
  226. sched.redraw = function(who, tasks) {
  227. //initTimeDomain(tasks);
  228. //initAxis();
  229. var svg = d3.select("#"+who);
  230. var schedChartGroup = svg.select(".sched-chart");
  231. var rect = schedChartGroup.selectAll("rect")
  232. .data(tasks, keyFunction);
  233. rect.enter()
  234. .insert("rect",":first-child")
  235. .attr("rx", 5)
  236. .attr("ry", 5)
  237. .attr("class", function(d){
  238. if(taskStatus[d.status] == null)
  239. { return "bar";}
  240. return taskStatus[d.status];
  241. })
  242. //.transition()
  243. .attr("x", function(d){
  244. return xScale(d.placeName || "unk");
  245. })
  246. .attr("y", function(d){
  247. return yScale(d.startDate);
  248. })
  249. //.attr("transform", rectTransform)
  250. .attr("width", function(d) {
  251. return xScale.rangeBand();
  252. })
  253. .attr("height", function(d) {
  254. return (yScale(d.endDate) - yScale(d.startDate));
  255. });
  256. rect.transition()
  257. //.attr("transform", rectTransform)
  258. .attr("x", function(d){
  259. return xScale(d.placeName || "unk");
  260. })
  261. .attr("y", function(d){
  262. return yScale(d.startDate);
  263. })
  264. .attr("width", function(d) {
  265. return xScale.rangeBand();
  266. })
  267. .attr("height", function(d) {
  268. return (yScale(d.endDate) - yScale(d.startDate));
  269. });
  270. rect.exit()
  271. .remove();
  272. var content = schedChartGroup.selectAll("foreignObject")
  273. .data(tasks, keyFunction);
  274. content.enter()
  275. .insert("foreignObject",":first-child")
  276. //.transition()
  277. .attr("x", function(d){
  278. return xScale(d.placeName || "unk");
  279. })
  280. .attr("y", function(d){
  281. return yScale(d.startDate);
  282. })
  283. //.attr("transform", rectTransform)
  284. .attr("width", function(d) {
  285. return xScale.rangeBand();
  286. })
  287. .attr("height", function(d) {
  288. return (yScale(d.endDate) - yScale(d.startDate));
  289. })
  290. .append("xhtml:div")
  291. .html(function(d) {
  292. return '<div style="padding:2px;height:100%"><a href="/event/'+ d.uid +
  293. '">' + d.desc + '</a></div>'
  294. });
  295. content.transition()
  296. //.attr("transform", rectTransform)
  297. .attr("x", function(d){
  298. return xScale(d.placeName || "unk");
  299. })
  300. .attr("y", function(d){
  301. return yScale(d.startDate);
  302. })
  303. .attr("width", function(d) {
  304. return xScale.rangeBand();
  305. })
  306. .attr("height", function(d) {
  307. return (yScale(d.endDate) - yScale(d.startDate));
  308. });
  309. content.exit()
  310. .remove();
  311. return sched;
  312. };
  313. sched.margin = function(value) {
  314. if (!arguments.length)
  315. return margin;
  316. margin = value;
  317. return sched;
  318. };
  319. sched.timeDomain = function(value) {
  320. if (!arguments.length)
  321. return [ timeDomainStart, timeDomainEnd ];
  322. timeDomainStart = +value[0], timeDomainEnd = +value[1];
  323. return sched;
  324. };
  325. /**
  326. * @param {string}
  327. * vale The value can be "fit" - the domain fits the data or
  328. * "fixed" - fixed domain.
  329. */
  330. sched.timeDomainMode = function(value) {
  331. if (!arguments.length)
  332. return timeDomainMode;
  333. timeDomainMode = value;
  334. return sched;
  335. };
  336. sched.taskTypes = function(value) {
  337. if (!arguments.length)
  338. return taskTypes;
  339. taskTypes = value;
  340. return sched;
  341. };
  342. sched.taskStatus = function(value) {
  343. if (!arguments.length)
  344. return taskStatus;
  345. taskStatus = value;
  346. return sched;
  347. };
  348. sched.width = function(value) {
  349. if (!arguments.length)
  350. return width;
  351. width = +value;
  352. return sched;
  353. };
  354. sched.height = function(value) {
  355. if (!arguments.length)
  356. return height;
  357. height = +value;
  358. return sched;
  359. };
  360. sched.tickFormat = function(value) {
  361. if (!arguments.length)
  362. return tickFormat;
  363. tickFormat = value;
  364. return sched;
  365. };
  366. sched.name = function(value) {
  367. if (!arguments.length)
  368. return myname;
  369. myname = value;
  370. return sched;
  371. };
  372. return sched;
  373. };