Statistician.js 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968
  1. MWF.xApplication.query = MWF.xApplication.query || {};
  2. MWF.xApplication.query.Query = MWF.xApplication.query.Query || {};
  3. MWF.require("MWF.widget.Common", null, false);
  4. MWF.require("MWF.xScript.Macro", null, false);
  5. MWF.xDesktop.requireApp("query.Query", "lp.zh-cn", null, false);
  6. MWF.xApplication.query.Query.Statistician = MWF.QStatistician = new Class({
  7. Implements: [Options, Events],
  8. Extends: MWF.widget.Common,
  9. options: {
  10. "style": "default",
  11. "resizeNode": true
  12. },
  13. initialize: function(app, container, json, options){
  14. this.setOptions(options);
  15. this.path = "/x_component_query_Query/$Statistician/";
  16. this.cssPath = "/x_component_query_Query/$Statistician/"+this.options.style+"/css.wcss";
  17. this._loadCss();
  18. this.lp = MWF.xApplication.query.Query.LP;
  19. this.app = app;
  20. this.container = $(container);
  21. this.json = json;
  22. this.statJson = null;
  23. this.gridJson = null;
  24. this.load();
  25. },
  26. load: function(){
  27. this.loadLayout();
  28. this.loadStatData();
  29. },
  30. loadLayout: function(){
  31. this.node = new Element("div", {"styles": this.css.node}).inject(this.container);
  32. //if (this.json.isChart) this.chartAreaNode = new Element("div", {"styles": this.css.statChartAreaNode}).inject(this.node);
  33. //if (this.json.isTable) this.tableAreaNode = new Element("div", {"styles": this.css.statTableAreaNode}).inject(this.node);
  34. },
  35. createLoadding: function(){
  36. this.node.empty();
  37. this.loadingAreaNode = new Element("div", {"styles": this.css.viewLoadingAreaNode}).inject(this.node);
  38. new Element("div", {"styles": {"height": "5px"}}).inject(this.loadingAreaNode);
  39. var loadingNode = new Element("div", {"styles": this.css.viewLoadingNode}).inject(this.loadingAreaNode);
  40. new Element("div", {"styles": this.css.viewLoadingIconNode}).inject(loadingNode);
  41. var loadingTextNode = new Element("div", {"styles": this.css.viewLoadingTextNode}).inject(loadingNode);
  42. loadingTextNode.set("text", "loading...");
  43. },
  44. loadStatData: function(node){
  45. this.createLoadding();
  46. MWF.Actions.get("x_query_assemble_surface").loadStat(this.json.statName, this.json.application, null, function(json){
  47. if (this.loadingAreaNode){
  48. this.loadingAreaNode.destroy();
  49. this.loadingAreaNode = null;
  50. }
  51. if (json.data.calculate.isGroup){
  52. this.stat = new MWF.xApplication.query.Query.Statistician.GroupStat(this, json.data);
  53. }else{
  54. this.stat = new MWF.xApplication.query.Query.Statistician.Stat(this, json.data);
  55. }
  56. this.fireEvent("loaded");
  57. }.bind(this));
  58. }
  59. });
  60. MWF.xApplication.query.Query.Statistician.Stat = new Class({
  61. initialize: function(statistician, data){
  62. //this.explorer = explorer;
  63. this.statistician = statistician;
  64. this.json = this.statistician.json;
  65. this.data = data;
  66. this.statGridData = Array.clone(this.data.calculateGrid);
  67. this.css = this.statistician.css;
  68. this.lp = this.statistician.lp;
  69. this.node = this.statistician.node;
  70. this.load();
  71. },
  72. load: function(){
  73. if (this.json.isChart) this.chartAreaNode = new Element("div", {"styles": this.css.statChartAreaNode}).inject(this.node);
  74. if (this.json.isTable) this.tableAreaNode = new Element("div#tableAreaNode", {"styles": this.css.statTableAreaNode}).inject(this.node);
  75. this.loadData();
  76. if (this.json.isTable) this.createTable();
  77. if (this.json.isChart) this.createChart();
  78. },
  79. loadData: function(){
  80. var entries = {};
  81. this.data.calculate.calculateList.each(function(entry){entries[entry.column] = entry;}.bind(this));
  82. },
  83. createChart: function(){
  84. this.chartToolbarNode = new Element("div", {"styles": this.css.statChartToolbarNode}).inject(this.chartAreaNode);
  85. this.chartNode = new Element("div", {"styles": this.css.statChartNode}).inject(this.chartAreaNode);
  86. this.loadChartToolbar();
  87. //this.loadChart();
  88. if (this.statistician.app){
  89. this.resizeChartFun = this.reloadChart.bind(this);
  90. this.statistician.app.addEvent("resizeCompleted", this.resizeChartFun);
  91. this.statistician.app.addEvent("postMaxSize", this.resizeChartFun);
  92. this.statistician.app.addEvent("postRestoreSize", this.resizeChartFun);
  93. }
  94. },
  95. loadChartToolbar: function(){
  96. MWF.require("MWF.widget.Toolbar", function(){
  97. this.toolbar = new MWF.widget.Toolbar(this.chartToolbarNode, {"style": "simple"}, this);
  98. var charts = this.data.calculate.chart;
  99. charts = ["bar", "pie", "line"];
  100. if (charts.indexOf("bar")!==-1){
  101. var actionNode = new Element("div", {
  102. "MWFnodeid": "bar",
  103. "MWFnodetype": "MWFToolBarOnOffButton",
  104. "MWFButtonImage": this.statistician.path+""+this.statistician.options.style+"/icon/barChart.png",
  105. "title": this.lp.chart.bar,
  106. "MWFButtonAction": "changeChartBar",
  107. "MWFButtonText": this.lp.chart.bar
  108. }).inject(this.chartToolbarNode);
  109. }
  110. if (charts.indexOf("pie")!==-1){
  111. var actionNode = new Element("div", {
  112. "MWFnodeid": "pie",
  113. "MWFnodetype": "MWFToolBarOnOffButton",
  114. "MWFButtonImage": this.statistician.path+""+this.statistician.options.style+"/icon/pieChart.png",
  115. "title": this.lp.chart.pie,
  116. "MWFButtonAction": "changeChartPie",
  117. "MWFButtonText": this.lp.chart.pie
  118. }).inject(this.chartToolbarNode);
  119. }
  120. if (charts.indexOf("line")!==-1){
  121. var actionNode = new Element("div", {
  122. "MWFnodeid": "line",
  123. "MWFnodetype": "MWFToolBarOnOffButton",
  124. "MWFButtonImage": this.statistician.path+""+this.statistician.options.style+"/icon/lineChart.png",
  125. "title": this.lp.chart.line,
  126. "MWFButtonAction": "changeChartLine",
  127. "MWFButtonText": this.lp.chart.line
  128. }).inject(this.chartToolbarNode);
  129. }
  130. if (this.data.calculate.isGroup){
  131. var actionNode = new Element("div", {
  132. "MWFnodeid": "rowToColumn",
  133. "MWFnodetype": "MWFToolBarButton",
  134. "MWFButtonImage": this.statistician.path+""+this.statistician.options.style+"/icon/rowToColumn.png",
  135. "title": this.lp.chart.rowToColumn,
  136. "MWFButtonAction": "loadRowToColumn",
  137. "MWFButtonText": this.lp.chart.rowToColumn
  138. }).inject(this.chartToolbarNode);
  139. }
  140. this.toolbar.load();
  141. this.changeChartBar("on", this.toolbar.items["bar"]);
  142. //this.reloadChart();
  143. }.bind(this));
  144. },
  145. changeChartBar: function(status, btn){
  146. this.toolbar.items["pie"].off();
  147. this.toolbar.items["line"].off();
  148. btn.on();
  149. this.currentChart = "bar";
  150. this.reloadChart();
  151. },
  152. changeChartPie: function(status, btn){
  153. this.toolbar.items["bar"].off();
  154. this.toolbar.items["line"].off();
  155. btn.on();
  156. this.currentChart = "pie";
  157. this.reloadChart();
  158. },
  159. changeChartLine: function(status, btn){
  160. this.toolbar.items["pie"].off();
  161. this.toolbar.items["bar"].off();
  162. btn.on();
  163. this.currentChart = "line";
  164. this.reloadChart();
  165. },
  166. toFloat: function(value){
  167. if (value.substr(0,1)==="¥") value = value.substr(1, value.length);
  168. value = value.replace(",", "");
  169. value = value.replace(/\s/g, "");
  170. return value.toFloat()
  171. },
  172. loadChartBar: function(){
  173. MWF.require("MWF.widget.chart.Bar", function(){
  174. this.bar = new MWF.widget.chart.Bar(this.chartNode, this.statGridData, "displayName", {"delay": 0, "style": "monthly"});
  175. //this.bar.addBar("value");
  176. this.bar.addBar(function(d){
  177. var value = d.value;
  178. if (value.substr(0,1)==="¥") value = value.substr(1, value.length);
  179. value = value.replace(",", "");
  180. value = value.replace(/\s/g, "");
  181. return value.toFloat()
  182. }, function(d){
  183. return d.value;
  184. });
  185. //bar.addBar("value");
  186. this.bar.addEvents({
  187. "mouseover": function(rects, texts, d, i){
  188. texts.filter(function(data, idx){return (idx==i);}).attr("display", "block");
  189. var rect = rects.filter(function(data, idx){return (idx==i);});
  190. var color = rect.attr("fill");
  191. rect.node().store("color", color);
  192. rect.attr("fill", "brown");
  193. }.bind(this),
  194. "mouseout": function(rects, texts, d, i){
  195. texts.filter(function(data, idx){return (idx==i);}).attr("display", "none");
  196. var rect = rects.filter(function(data, idx){return (idx==i);});
  197. var color = rect.node().retrieve("color");
  198. rect.attr("fill", color);
  199. }.bind(this)
  200. });
  201. this.bar.load();
  202. }.bind(this));
  203. },
  204. loadChartPie: function(){
  205. MWF.require("MWF.widget.chart.Pie", function(){
  206. var data = [];
  207. var total = 0;
  208. // this.data.calculateGrid.each(function(d){
  209. // total += this.toFloat(d.value);
  210. // }.bind(this));
  211. this.data.calculateGrid.each(function(d){
  212. var v = this.toFloat(d.value);
  213. // var percent = ((v/total)*10000).toInt()/100;
  214. // percent = ""+ percent +"%";
  215. data.push({"name": d.displayName, "value": v});
  216. }.bind(this));
  217. this.bar = new MWF.widget.chart.Pie(this.chartNode, data, {"textType": "percent"});
  218. this.bar.load();
  219. }.bind(this));
  220. },
  221. loadChartLine: function(){
  222. MWF.require("MWF.widget.chart.Line", function(){
  223. this.bar = new MWF.widget.chart.Line(this.chartNode, this.statGridData, "displayName", {"delay": 0, "style": "monthly"});
  224. //this.bar.addBar("value");
  225. this.bar.addBar(function(d){
  226. var value = d.value;
  227. if (value.substr(0,1)==="¥") value = value.substr(1, value.length);
  228. value = value.replace(",", "");
  229. value = value.replace(/\s/g, "");
  230. return value.toFloat()
  231. }, function(d){
  232. return d.value;
  233. });
  234. this.bar.load();
  235. }.bind(this));
  236. },
  237. resizeChart: function(){
  238. if (this.bar) this.bar.destroy();
  239. this.bar = null;
  240. if (this.chartNode) this.chartNode.empty();
  241. this.loadChartBar();
  242. },
  243. // loadChart: function(){
  244. //
  245. // },
  246. createTable: function(){
  247. this.createTableHead();
  248. this.createTableData();
  249. },
  250. createTableHead: function(){
  251. this.table = new Element("table", {
  252. "styles": this.css.statTableNode,
  253. "width": "100%",
  254. "border": "0",
  255. "cellPadding": "0",
  256. "cellSpacing": "0"
  257. }).inject(this.tableAreaNode);
  258. this.headTr = new Element("tr").inject(this.table);
  259. this.data.calculate.calculateList.each(function(title){
  260. var th = new Element("th", {
  261. "styles": this.css.statHeadTh,
  262. "text": title.displayName
  263. }).inject(this.headTr);
  264. }.bind(this));
  265. },
  266. createTableData: function(){
  267. if (this.statGridData.length){
  268. var tr = new Element("tr").inject(this.table);
  269. this.statGridData.each(function(d){
  270. var td = new Element("td", {"styles": this.css.statContentTdNode}).inject(tr);
  271. td.set("text", d.value);
  272. }.bind(this));
  273. }
  274. },
  275. destroy: function(){
  276. if (this.bar) this.bar.destroy();
  277. if (this.statistician.app){
  278. if (this.resizeChartFun){
  279. this.resizeChartFun.app.removeEvent("resizeCompleted", this.resizeChartFun);
  280. this.resizeChartFun.app.removeEvent("postMaxSize", this.resizeChartFun);
  281. this.resizeChartFun.app.removeEvent("postRestoreSize", this.resizeChartFun);
  282. }
  283. }
  284. MWF.release(this);
  285. }
  286. });
  287. MWF.xApplication.query.Query.Statistician.GroupStat = new Class({
  288. Extends: MWF.xApplication.query.Query.Statistician.Stat,
  289. loadData: function(){
  290. var entries = {};
  291. var groupColumn = null;
  292. this.data.calculate.calculateList.each(function(entry){
  293. entries[entry.id] = entry;
  294. // if (entry.column === this.data.group.column){
  295. // groupColumn = entry;
  296. // }
  297. }.bind(this));
  298. this.statGridData.each(function(dd){
  299. // if (groupColumn){
  300. // dd.group = (groupColumn.code) ? MWF.Macro.exec(groupColumn.code, {"value": dd.group, "data": this.data}) : dd.group;
  301. // }
  302. dd.list.each(function(c){
  303. c.value = (entries[c.column].code) ? MWF.Macro.exec(entries[c.column].code, {"value": c.value, "data": this.data}) : c.value
  304. }.bind(this));
  305. }.bind(this));
  306. },
  307. createChart: function(){
  308. this.chartToolbarNode = new Element("div", {"styles": this.css.statChartToolbarNode}).inject(this.chartAreaNode);
  309. if (this.json.isLegend) this.chartFlagNode = new Element("div", {"styles": this.css.statChartFlagAreaNode}).inject(this.chartAreaNode);
  310. this.chartNode = new Element("div", {"styles": this.css.statChartNode}).inject(this.chartAreaNode);
  311. this.loadChartToolbar();
  312. //this.loadChartBar();
  313. if (this.statistician.app){
  314. this.resizeChartFun = this.reloadChart.bind(this);
  315. this.statistician.app.addEvent("resizeCompleted", this.resizeChartFun);
  316. this.statistician.app.addEvent("postMaxSize", this.resizeChartFun);
  317. this.statistician.app.addEvent("postRestoreSize", this.resizeChartFun);
  318. }
  319. },
  320. resizeChart: function(){
  321. if (this.bar) this.bar.destroy();
  322. this.bar = null;
  323. if (this.json.isLegend) this.chartFlagNode.empty();
  324. this.chartNode.empty();
  325. this.loadChartBar();
  326. },
  327. toFloat: function(value){
  328. if (value.substr(0,1)==="¥") value = value.substr(1, value.length);
  329. value = value.replace(",", "");
  330. value = value.replace(/\s/g, "");
  331. return value.toFloat()
  332. },
  333. loadChartBar: function(){
  334. if (this.json.isLegend) if (!this.chartFlagNode) this.chartFlagNode = new Element("div", {"styles": this.css.statChartFlagAreaNode}).inject(this.chartNode, "before");
  335. if (!this.selectedData) this.selectedData = this.statGridData;
  336. if (!this.selectedData.length) this.selectedData = this.statGridData;
  337. MWF.require("MWF.widget.chart.Bar", function(){
  338. //this.selectedData.each()
  339. this.flag = [];
  340. this.bar = new MWF.widget.chart.Bar(this.chartNode, this.selectedData, "group", {"delay": 0, "style": "monthly"});
  341. if (this.selectedData.length){
  342. this.selectedData[0].list.each(function(d, i){
  343. this.flag.push({"name":d.displayName, "color": this.bar.colors[i]});
  344. this.bar.addBar(function(v){
  345. return this.toFloat(v.list[i].value);
  346. }.bind(this), function(v){
  347. return v.list[i].value;
  348. });
  349. }.bind(this));
  350. }
  351. this.bar.addEvents({
  352. "mouseover": function(rects, texts, d, i){
  353. texts.filter(function(data, idx){return (idx==i);}).attr("display", "block");
  354. var rect = rects.filter(function(data, idx){return (idx==i);});
  355. var color = rect.attr("fill");
  356. rect.node().store("color", color);
  357. rect.attr("fill", "brown");
  358. }.bind(this),
  359. "mouseout": function(rects, texts, d, i){
  360. texts.filter(function(data, idx){return (idx==i);}).attr("display", "none");
  361. var rect = rects.filter(function(data, idx){return (idx==i);});
  362. var color = rect.node().retrieve("color");
  363. rect.attr("fill", color);
  364. }.bind(this)
  365. });
  366. this.bar.load();
  367. if (this.json.isLegend) this.loadFlags();
  368. }.bind(this));
  369. },
  370. rowToColumn: function(data){
  371. var o = [];
  372. var idxs = {};
  373. data.each(function(d){
  374. var group = d.group;
  375. var column = d.column;
  376. d.list.each(function(l){
  377. if (l.column){
  378. var idx = (l.column) ? idxs[l.column] : idxs[l.displayName];
  379. if (!idx && idx!==0){
  380. o.push({ "column": l.column, "group": l.displayName, "list": [] });
  381. idx = o.length-1;
  382. idxs[l.column] = idx;
  383. }
  384. o[idx].list.push({
  385. "displayName": group,
  386. "name": group,
  387. "value": l.value
  388. });
  389. }else{
  390. var idx = (l.column) ? idxs[l.column] : idxs[l.displayName];
  391. if (!idx && idx!==0){
  392. o.push({ "group": l.displayName, "list": [] });
  393. idx = o.length-1;
  394. idxs[l.displayName] = idx;
  395. }
  396. o[idx].list.push({
  397. "column": column,
  398. "displayName": group,
  399. "name": group,
  400. "value": l.value
  401. });
  402. }
  403. }.bind(this));
  404. }.bind(this));
  405. return o;
  406. },
  407. loadChartPie: function(){
  408. if (!this.selectedData) this.selectedData = this.statGridData;
  409. if (!this.selectedData.length) this.selectedData = this.statGridData;
  410. var pieData = this.rowToColumn(this.selectedData);
  411. MWF.require("MWF.widget.chart.Pie", function(){
  412. var count = pieData.length;
  413. var size = this.chartNode.getSize();
  414. var w = size.x/count;
  415. pieData.each(function(d){
  416. var pieAreaNode = new Element("div", {
  417. "styles": {"overflow": "hidden", "height": ""+size.y+"px", "float": "left", "width": ""+w+"px"}
  418. }).inject(this.chartNode);
  419. var pieTitleNode = new Element("div", {
  420. "styles": {"text-align": "center", "line-height":"30px", "font-size":"16px", "font-weight":"bold", "overflow": "hidden", "height": "30px"},
  421. "text": d.group
  422. }).inject(pieAreaNode);
  423. var h = size.y-30;
  424. var pieNode = new Element("div", {
  425. "styles": {"overflow": "hidden", "height": ""+h+"px"}
  426. }).inject(pieAreaNode);
  427. var data = [];
  428. d.list.each(function(d){
  429. var v = this.toFloat(d.value);
  430. data.push({"name": d.displayName, "value": v, "text": d.value});
  431. }.bind(this));
  432. var pie = new MWF.widget.chart.Pie(pieNode, data, {"textType": "percent"});
  433. pie.load();
  434. }.bind(this));
  435. }.bind(this));
  436. },
  437. loadChartLine: function(){
  438. if (this.json.isLegend) if (!this.chartFlagNode) this.chartFlagNode = new Element("div", {"styles": this.css.statChartFlagAreaNode}).inject(this.chartNode, "before");
  439. if (!this.selectedData) this.selectedData = this.statGridData;
  440. if (!this.selectedData.length) this.selectedData = this.statGridData;
  441. MWF.require("MWF.widget.chart.Line", function(){
  442. //this.selectedData.each()
  443. this.flag = [];
  444. this.bar = new MWF.widget.chart.Line(this.chartNode, this.selectedData, "group", {"delay": 0, "style": "monthly"});
  445. if (this.selectedData.length){
  446. this.selectedData[0].list.each(function(d, i){
  447. this.flag.push({"name":d.displayName, "color": this.bar.colors[i]});
  448. this.bar.addBar(function(v){
  449. return this.toFloat(v.list[i].value);
  450. }.bind(this), function(v){
  451. return v.list[i].value;
  452. });
  453. }.bind(this));
  454. }
  455. this.bar.addEvents({
  456. "mouseover": function(rects, texts, d, i){
  457. texts.filter(function(data, idx){return (idx==i);}).attr("display", "block");
  458. var rect = rects.filter(function(data, idx){return (idx==i);});
  459. var color = rect.attr("fill");
  460. rect.node().store("color", color);
  461. rect.attr("fill", "brown");
  462. }.bind(this),
  463. "mouseout": function(rects, texts, d, i){
  464. texts.filter(function(data, idx){return (idx==i);}).attr("display", "none");
  465. var rect = rects.filter(function(data, idx){return (idx==i);});
  466. var color = rect.node().retrieve("color");
  467. rect.attr("fill", color);
  468. }.bind(this)
  469. });
  470. this.bar.load();
  471. if (this.json.isLegend) this.loadFlags();
  472. }.bind(this));
  473. },
  474. loadRowToColumn: function(){
  475. if (this.selectedRows.length || this.selectedCols.length) this.selectAll();
  476. this.statGridData = this.rowToColumn(this.statGridData);
  477. this.selectedData = [];
  478. this.reloadChart();
  479. this.reloadTable();
  480. },
  481. loadFlags: function(){
  482. this.flag.each(function(f, i){
  483. this.loadFlag(f, i);
  484. }.bind(this));
  485. },
  486. loadFlag: function(f, i){
  487. var flagNode = new Element("div", {"styles": this.css.ststChartFlagNode}).inject(this.chartFlagNode);
  488. var flagColorNode = new Element("div", {"styles": this.css.ststChartFlagColorNode}).inject(flagNode);
  489. flagColorNode.setStyle("background-color", f.color);
  490. var flagNameNode = new Element("div", {"styles": this.css.ststChartFlagNameNode}).inject(flagNode);
  491. flagNameNode.set("text", f.name);
  492. flagNameNode.set("title", f.name);
  493. flagNode.store("idx", i);
  494. flagNode.store("barColor", f.color);
  495. var _self = this;
  496. flagNode.addEvents({
  497. "mouseover": function(){
  498. this.getFirst().setStyles(_self.css.ststChartFlagColorNode_over);
  499. var idx = this.retrieve("idx");
  500. switch (_self.currentChart){
  501. case "bar":
  502. _self.highlightBar(idx);
  503. break;
  504. case "line":
  505. _self.highlightLine(idx);
  506. break;
  507. }
  508. },
  509. "mouseout": function(){
  510. this.getFirst().setStyles(_self.css.ststChartFlagColorNode);
  511. var idx = this.retrieve("idx");
  512. var barColor = this.retrieve("barColor");
  513. switch (_self.currentChart){
  514. case "bar":
  515. _self.unHighlightBar(idx, barColor);
  516. break;
  517. case "line":
  518. _self.unHighlightLine(idx, barColor);
  519. break;
  520. }
  521. }
  522. });
  523. },
  524. createDefs: function(node, data){
  525. var svgNode = node.append(data.tag);
  526. Object.each(data.attrs, function(v,k){svgNode.attr(k,v);});
  527. if (data.subs) {
  528. data.subs.each(function(v){
  529. this.createDefs(svgNode, v);
  530. }.bind(this));
  531. }
  532. },
  533. createHighlightDefs: function(id){
  534. //this.defssvg = this.bar.createDefs;
  535. var node = this.bar.svg.append("defs");
  536. var data = this.bar.css["rect_over_defs"];
  537. this.createDefs(node, data);
  538. node.select(function(){ return this.getFirst(); }).attr("id", id);
  539. node.attr("id", "defs_"+id);
  540. },
  541. unHighlightBar: function(i, barColor){
  542. var id = "rect_over_defs"+i;
  543. var def = d3.select("#defs_"+id);
  544. def.remove();
  545. var rects = this.bar.rectCluster[i];
  546. rects.attr(this.bar.css["rect_over_defs"].urlAttr, null);
  547. var texts = this.bar.textCluster[i];
  548. texts.attr("display", "none");
  549. texts.attr("font-weight", "normal");
  550. },
  551. unHighlightLine: function(i, barColor){
  552. var line = this.bar.lineCluster[i];
  553. var points = this.bar.pointCluster[i];
  554. var texts = this.bar.textCluster[i];
  555. line.attr("stroke-width", "1");
  556. points.attr("r", "5").attr("stroke-width", "1");
  557. texts.attr("display", "none");
  558. texts.attr("font-weight", "normal");
  559. },
  560. highlightBar: function(i){
  561. this.bar.rectCluster[i].remove();
  562. var rects = this.recreateBars(i);
  563. var id = "rect_over_defs"+i;
  564. this.createHighlightDefs(id);
  565. rects.attr(this.bar.css["rect_over_defs"].urlAttr, "url(#"+id+")");
  566. var texts = this.bar.textCluster[i];
  567. texts.attr("display", "block");
  568. texts.attr("font-weight", "bold");
  569. },
  570. highlightLine: function(i){
  571. var line = this.bar.lineCluster[i];
  572. var points = this.bar.pointCluster[i];
  573. var texts = this.bar.textCluster[i];
  574. // debugger;
  575. // this.bar.lineGroup.selectAll("path").sort(function(a,b, i1, i2){
  576. // debugger;
  577. // });
  578. var p = this.bar.lineGroup.select(":last-child");
  579. line._groups[0][0].inject(p._groups[0][0],"after");
  580. line.attr("stroke-width", "3");
  581. points.attr("r", "6").attr("stroke-width", "3");
  582. texts.attr("display", "block");
  583. texts.attr("font-weight", "bold");
  584. },
  585. recreateBars: function(i){
  586. //var data = this.data.calculateGrid.map(function(d, idx) {
  587. var data = this.selectedData.map(function(d, idx) {
  588. return {"name": d["group"], "data": this.toFloat(d.list[i].value)};
  589. }.bind(this));
  590. this.bar.rectClass = Math.round(Math.random()*100);
  591. var barWidth = this.bar.xScale.bandwidth()/this.bar.barsData.length;
  592. var rects = this.bar.group.selectAll(".MWFBar_"+this.bar.rectClass+"_"+i)
  593. .data(data)
  594. .enter().append("rect")
  595. .attr("class", ".MWFBar_"+this.bar.rectClass+"_"+i)
  596. .attr("x", function(d) { return this.xScale(d.name)+(i*barWidth); }.bind(this.bar))
  597. .attr("width", barWidth)
  598. .attr("height", function(d) { return this.size.y - this.yScale(d.data); }.bind(this.bar))
  599. .attr("y", function(d) { return this.yScale(d.data); }.bind(this.bar))
  600. .attr("fill", this.bar.colors[i]);
  601. this.bar.rectCluster[i] = rects;
  602. this.bar.setEvents();
  603. return rects;
  604. },
  605. reloadTable: function(){
  606. this.tableAreaNode.empty();
  607. this.createTable();
  608. },
  609. createTableHead: function(){
  610. this.selectedCols = [];
  611. this.selectedRows = [];
  612. this.table = new Element("table", {
  613. "styles": this.css.statTableNode,
  614. "width": "100%",
  615. "border": "0",
  616. "cellPadding": "0",
  617. "cellSpacing": "0"
  618. }).inject(this.tableAreaNode);
  619. _self = this;
  620. this.headTr = this.table.insertRow();
  621. this.selectAllTd = (this.headTr.insertCell()).setStyles(this.css.statAllSelectTd).set("title", this.lp.selecteAll);
  622. this.selectAllTd.addEvent("click", function(){
  623. _self.selectAll(this);
  624. });
  625. this.selectEntryTd = (this.headTr.insertCell()).setStyles(this.css.statAllColSelectTd).set("title", this.lp.selecteAllCol);
  626. this.selectEntryTd.addEvent("click", function(){
  627. _self.selectAllCol(this);
  628. });
  629. this.statGridData[0].list.each(function(d){
  630. var title = d.displayName;
  631. selectTd = (this.headTr.insertCell()).setStyles(this.css.statColSelectTd);
  632. selectTd.addEvent("click", function(){
  633. _self.selectCol(this);
  634. });
  635. }.bind(this));
  636. this.titleTr = this.table.insertRow();
  637. this.selectGroupTd = (this.titleTr.insertCell()).setStyles(this.css.statAllRowSelectTd).set("title", this.lp.selecteAllRow);
  638. this.categoryTitleTd = new Element("th", {
  639. "styles": this.css.statHeadTh,
  640. "text": this.data.calculate.title || this.lp.category
  641. }).inject(this.titleTr);
  642. this.categoryTitleTd.setStyle("width", "160px");
  643. this.statGridData[0].list.each(function(d){
  644. var title = d.displayName;
  645. var th = new Element("th", {
  646. "styles": this.css.statHeadTh,
  647. "text": title
  648. }).inject(this.titleTr);
  649. }.bind(this));
  650. },
  651. createTableData: function(){
  652. if (this.statGridData.length){
  653. var _self = this;
  654. // var groupColumn = null;
  655. // for (var c = 0; c<this.data.calculate.calculateList.length; c++){
  656. // if (this.data.calculate.calculateList[c].column === this.data.group.column){
  657. // groupColumn = this.data.calculate.calculateList[c];
  658. // break;
  659. // }
  660. // }
  661. this.statGridData.each(function(d){
  662. var tr = this.table.insertRow();
  663. var selectTd = tr.insertCell().setStyles(this.css.statRowSelectTd);
  664. selectTd.addEvent("click", function(){
  665. _self.selectRow(this);
  666. });
  667. var text = d.group;
  668. // if (groupColumn){
  669. // text = (groupColumn.code) ? MWF.Macro.exec(groupColumn.code, {"value": d.group, "data": this.data}) : d.group;
  670. // }
  671. var categoryTh = new Element("th", {"styles": this.css.statHeadTh, "text": text}).inject(tr);
  672. d.list.each(function(l){
  673. var td = new Element("td", {"styles": this.css.statContentTdNode}).inject(tr);
  674. td.set("text", l.value);
  675. this.setDragEvent(td);
  676. }.bind(this));
  677. }.bind(this));
  678. }
  679. },
  680. setDragEvent: function(td){
  681. new Drag(td, {
  682. "onStart": function(dragged, e){
  683. this.cellDragStart(dragged, e);
  684. }.bind(this),
  685. "onDrag": function(dragged, e){
  686. this.cellDrag(dragged, e);
  687. }.bind(this),
  688. "onComplete": function(dragged, e){
  689. this.completeDrag(dragged, e);
  690. }.bind(this)
  691. });
  692. var _self = this;
  693. td.addEvent("click", function(){
  694. var cellIndex = td.cellIndex-2;
  695. var rowIndex = td.getParent("tr").rowIndex-2;
  696. if (_self.checkIsSelected(cellIndex, rowIndex)){
  697. }else{
  698. if (_self.selectedCols.length || _self.selectedRows.length){
  699. _self.selectAll();
  700. }
  701. }
  702. });
  703. },
  704. cellDragStart: function(td, e){
  705. //if (_self.selectedCols.length || _self.selectedRows.length){
  706. // _self.selectAll();
  707. //}
  708. var p = td.getPosition();
  709. var size = td.getSize();
  710. td.store("start", {"x": p.x, "y": p.y});
  711. td.store("start2", {"x": p.x+size.x, "y": p.y+size.y});
  712. },
  713. getSelectedCells: function(td, start, e){
  714. var ox = e.page.x-start.x;
  715. var oy = e.page.y-start.y;
  716. var tdSize = td.getSize();
  717. var cols = (ox/tdSize.x).toInt();
  718. var rows = (oy/tdSize.y).toInt();
  719. return {"cols": cols, "rows": rows};
  720. },
  721. cellDrag: function(td, e){
  722. this.selectedRows = [];
  723. this.selectedCols = [];
  724. this.selectedData = [];
  725. var start = td.retrieve("start");
  726. var start2 = td.retrieve("start2");
  727. var c1 = this.getSelectedCells(td, start, e);
  728. var c2 = this.getSelectedCells(td, start2, e);
  729. var cols = (Math.abs(c1.cols)>Math.abs(c2.cols)) ? c1.cols : c2.cols;
  730. var rows = (Math.abs(c1.rows)>Math.abs(c2.rows)) ? c1.rows : c2.rows;
  731. var cellIndex = td.cellIndex-2;
  732. var rowIndex = td.getParent("tr").rowIndex-2;
  733. if (!cellIndex || cellIndex<0) cellIndex = 0;
  734. if (!rowIndex || rowIndex<0) rowIndex = 0;
  735. var toCellIndex = cellIndex+cols;
  736. var toRowIndex = rowIndex+rows;
  737. if (toRowIndex>rowIndex){
  738. for (var i=rowIndex; i<=toRowIndex; i++) this.selectedRows.push(i);
  739. }else{
  740. for (var i=toRowIndex; i<=rowIndex; i++) this.selectedRows.push(i);
  741. }
  742. if (toCellIndex>cellIndex){
  743. for (var i=cellIndex; i<=toCellIndex; i++) this.selectedCols.push(i);
  744. }else{
  745. for (var i=toCellIndex; i<=cellIndex; i++) this.selectedCols.push(i);
  746. }
  747. this.checkSelectedCells();
  748. },
  749. completeDrag: function(td, e){
  750. var trs = this.table.getElements("tr");
  751. var tds = trs[0].getElements("td");
  752. this.selectedCols.each(function(i){
  753. tds[i+2].setStyles(this.css.statTableSelectedTd);
  754. }.bind(this));
  755. this.selectedRows.each(function(i){
  756. trs[i+2].getElement("td").setStyles(this.css.statTableSelectedTd);
  757. }.bind(this));
  758. this.reloadChart();
  759. },
  760. selectCol: function(td){
  761. var i = td.cellIndex;
  762. var dataIndex = i-2;
  763. if (this.selectedCols.indexOf(dataIndex)!=-1){
  764. td.setStyles(this.css.statTableSelectTd);
  765. this.selectedCols.erase(dataIndex);
  766. }else{
  767. td.setStyles(this.css.statTableSelectedTd);
  768. this.selectedCols.push(dataIndex);
  769. }
  770. this.checkSelectedCells();
  771. this.reloadChart();
  772. },
  773. selectRow: function(td){
  774. var tr = td.getParent("tr");
  775. var i = tr.rowIndex;
  776. var dataIndex = i-2;
  777. if (this.selectedRows.indexOf(dataIndex)!=-1){
  778. td.setStyles(this.css.statTableSelectTd);
  779. this.selectedRows.erase(dataIndex);
  780. }else{
  781. td.setStyles(this.css.statTableSelectedTd);
  782. this.selectedRows.push(dataIndex);
  783. }
  784. this.checkSelectedCells();
  785. this.reloadChart();
  786. },
  787. selectAllCol: function(){
  788. if (this.selectedCols.length){
  789. this.selectedCols = [];
  790. var trs = this.table.getElements("tr");
  791. var tds = trs[0].getElements("td");
  792. for (var i=2; i<tds.length; i++){
  793. tds[i].setStyles(this.css.statTableSelectTd);
  794. }
  795. //for (var n=2; n<trs.length; n++){
  796. // trs[n].getElement("td").setStyles(this.css.statTableSelectTd);
  797. //}
  798. }else{
  799. var seltrs = this.table.getElements("tr");
  800. var seltds = seltrs[0].getElements("td");
  801. for (var n=2; n<seltds.length; n++){
  802. this.selectedCols.push(n-2);
  803. seltds[n].setStyles(this.css.statTableSelectedTd);
  804. }
  805. }
  806. this.checkSelectedCells();
  807. this.reloadChart();
  808. },
  809. selectAll: function(){
  810. if (this.selectedRows.length || this.selectedCols.length){
  811. this.selectedRows = [];
  812. this.selectedCols = [];
  813. var trs = this.table.getElements("tr");
  814. var tds = trs[0].getElements("td");
  815. for (var i=2; i<tds.length; i++){
  816. tds[i].setStyles(this.css.statTableSelectTd);
  817. }
  818. for (var n=2; n<trs.length; n++){
  819. trs[n].getElement("td").setStyles(this.css.statTableSelectTd);
  820. }
  821. }else{
  822. var seltrs = this.table.getElements("tr");
  823. var seltds = seltrs[0].getElements("td");
  824. for (var seli=2; seli<seltds.length; seli++){
  825. this.selectedCols.push(seli-2);
  826. seltds[seli].setStyles(this.css.statTableSelectedTd);
  827. }
  828. for (var seln=2; seln<seltrs.length; seln++){
  829. this.selectedRows.push(seln-2);
  830. seltrs[seln].getElement("td").setStyles(this.css.statTableSelectedTd);
  831. }
  832. }
  833. this.checkSelectedCells();
  834. this.reloadChart();
  835. },
  836. checkIsSelected: function(ci, ri){
  837. if (!this.selectedCols.length && !this.selectedRows.length) return false;
  838. var colSelect = (!this.selectedCols.length) || this.selectedCols.indexOf(ci)!=-1;
  839. var rowSelect = (!this.selectedRows.length) || this.selectedRows.indexOf(ri)!=-1;
  840. return (colSelect && rowSelect);
  841. },
  842. checkSelectedCells: function(){
  843. this.selectedData = [];
  844. var rows = this.table.getElements("tr");
  845. for (var rowIdx = 2; rowIdx<rows.length; rowIdx++){
  846. var o = {
  847. "group": this.statGridData[rowIdx-2].group,
  848. "list": []
  849. };
  850. var cols = rows[rowIdx].getElements("td");
  851. for (var colIdx = 1; colIdx<cols.length; colIdx++){
  852. if (this.checkIsSelected(colIdx-1, rowIdx-2)){
  853. cols[colIdx].setStyles(this.css.statContentTdNode_selected);
  854. o.list.push({
  855. "column": this.statGridData[rowIdx-2].list[colIdx-1].column,
  856. "displayName": this.statGridData[rowIdx-2].list[colIdx-1].displayName,
  857. "value": this.statGridData[rowIdx-2].list[colIdx-1].value
  858. });
  859. }else{
  860. cols[colIdx].setStyles(this.css.statContentTdNode);
  861. }
  862. }
  863. if (o.list.length) this.selectedData.push(o);
  864. }
  865. },
  866. reloadChart: function(){
  867. if (this.json.isChart){
  868. if (this.bar) this.bar.destroy();
  869. this.bar = null;
  870. if (this.chartFlagNode){
  871. this.chartFlagNode.destroy();
  872. this.chartFlagNode = null;
  873. }
  874. if (this.chartNode)this.chartNode.empty();
  875. switch (this.currentChart){
  876. case "bar":
  877. this.loadChartBar();
  878. break;
  879. case "pie":
  880. this.loadChartPie();
  881. break;
  882. case "line":
  883. this.loadChartLine();
  884. break;
  885. default:
  886. this.loadChartBar();
  887. }
  888. }
  889. }
  890. });