Statistician.js 40 KB

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