morris.js 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767
  1. (function() {
  2. var $, Morris, minutesSpecHelper, secondsSpecHelper,
  3. __slice = [].slice,
  4. __hasProp = {}.hasOwnProperty,
  5. __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  6. __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  7. __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
  8. Morris = window.Morris = {};
  9. $ = jQuery;
  10. Morris.EventEmitter = (function() {
  11. function EventEmitter() {}
  12. EventEmitter.prototype.on = function(name, handler) {
  13. if (this.handlers == null) {
  14. this.handlers = {};
  15. }
  16. if (this.handlers[name] == null) {
  17. this.handlers[name] = [];
  18. }
  19. this.handlers[name].push(handler);
  20. return this;
  21. };
  22. EventEmitter.prototype.fire = function() {
  23. var args, handler, name, _i, _len, _ref, _results;
  24. name = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  25. if ((this.handlers != null) && (this.handlers[name] != null)) {
  26. _ref = this.handlers[name];
  27. _results = [];
  28. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  29. handler = _ref[_i];
  30. _results.push(handler.apply(null, args));
  31. }
  32. return _results;
  33. }
  34. };
  35. return EventEmitter;
  36. })();
  37. Morris.commas = function(num) {
  38. var absnum, intnum, ret, strabsnum;
  39. if (num != null) {
  40. ret = num < 0 ? "-" : "";
  41. absnum = Math.abs(num);
  42. intnum = Math.floor(absnum).toFixed(0);
  43. ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ',');
  44. strabsnum = absnum.toString();
  45. if (strabsnum.length > intnum.length) {
  46. ret += strabsnum.slice(intnum.length);
  47. }
  48. return ret;
  49. } else {
  50. return '-';
  51. }
  52. };
  53. Morris.pad2 = function(number) {
  54. return (number < 10 ? '0' : '') + number;
  55. };
  56. Morris.Grid = (function(_super) {
  57. __extends(Grid, _super);
  58. function Grid(options) {
  59. var _this = this;
  60. if (typeof options.element === 'string') {
  61. this.el = $(document.getElementById(options.element));
  62. } else {
  63. this.el = $(options.element);
  64. }
  65. if (!(this.el != null) || this.el.length === 0) {
  66. throw new Error("Graph container element not found");
  67. }
  68. if (this.el.css('position') === 'static') {
  69. this.el.css('position', 'relative');
  70. }
  71. this.options = $.extend({}, this.gridDefaults, this.defaults || {}, options);
  72. if (typeof this.options.units === 'string') {
  73. this.options.postUnits = options.units;
  74. }
  75. this.raphael = new Raphael(this.el[0]);
  76. this.elementWidth = null;
  77. this.elementHeight = null;
  78. this.dirty = false;
  79. if (this.init) {
  80. this.init();
  81. }
  82. this.setData(this.options.data);
  83. this.el.bind('mousemove', function(evt) {
  84. var offset;
  85. offset = _this.el.offset();
  86. return _this.fire('hovermove', evt.pageX - offset.left, evt.pageY - offset.top);
  87. });
  88. this.el.bind('mouseout', function(evt) {
  89. return _this.fire('hoverout');
  90. });
  91. this.el.bind('touchstart touchmove touchend', function(evt) {
  92. var offset, touch;
  93. touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];
  94. offset = _this.el.offset();
  95. _this.fire('hover', touch.pageX - offset.left, touch.pageY - offset.top);
  96. return touch;
  97. });
  98. this.el.bind('click', function(evt) {
  99. var offset;
  100. offset = _this.el.offset();
  101. return _this.fire('gridclick', evt.pageX - offset.left, evt.pageY - offset.top);
  102. });
  103. if (this.postInit) {
  104. this.postInit();
  105. }
  106. }
  107. Grid.prototype.gridDefaults = {
  108. dateFormat: null,
  109. axes: true,
  110. grid: true,
  111. gridLineColor: '#aaa',
  112. gridStrokeWidth: 0.5,
  113. gridTextColor: '#888',
  114. gridTextSize: 12,
  115. gridTextFamily: 'sans-serif',
  116. gridTextWeight: 'normal',
  117. hideHover: false,
  118. yLabelFormat: null,
  119. xLabelAngle: 0,
  120. numLines: 5,
  121. padding: 25,
  122. parseTime: true,
  123. postUnits: '',
  124. preUnits: '',
  125. ymax: 'auto',
  126. ymin: 'auto 0',
  127. goals: [],
  128. goalStrokeWidth: 1.0,
  129. goalLineColors: ['#666633', '#999966', '#cc6666', '#663333'],
  130. events: [],
  131. eventStrokeWidth: 1.0,
  132. eventLineColors: ['#005a04', '#ccffbb', '#3a5f0b', '#005502']
  133. };
  134. Grid.prototype.setData = function(data, redraw) {
  135. var e, idx, index, maxGoal, minGoal, ret, row, step, total, y, ykey, ymax, ymin, yval;
  136. if (redraw == null) {
  137. redraw = true;
  138. }
  139. this.options.data = data;
  140. if (!(data != null) || data.length === 0) {
  141. this.data = [];
  142. this.raphael.clear();
  143. if (this.hover != null) {
  144. this.hover.hide();
  145. }
  146. return;
  147. }
  148. ymax = this.cumulative ? 0 : null;
  149. ymin = this.cumulative ? 0 : null;
  150. if (this.options.goals.length > 0) {
  151. minGoal = Math.min.apply(null, this.options.goals);
  152. maxGoal = Math.max.apply(null, this.options.goals);
  153. ymin = ymin != null ? Math.min(ymin, minGoal) : minGoal;
  154. ymax = ymax != null ? Math.max(ymax, maxGoal) : maxGoal;
  155. }
  156. this.data = (function() {
  157. var _i, _len, _results;
  158. _results = [];
  159. for (index = _i = 0, _len = data.length; _i < _len; index = ++_i) {
  160. row = data[index];
  161. ret = {};
  162. ret.label = row[this.options.xkey];
  163. if (this.options.parseTime) {
  164. ret.x = Morris.parseDate(ret.label);
  165. if (this.options.dateFormat) {
  166. ret.label = this.options.dateFormat(ret.x);
  167. } else if (typeof ret.label === 'number') {
  168. ret.label = new Date(ret.label).toString();
  169. }
  170. } else {
  171. ret.x = index;
  172. if (this.options.xLabelFormat) {
  173. ret.label = this.options.xLabelFormat(ret);
  174. }
  175. }
  176. total = 0;
  177. ret.y = (function() {
  178. var _j, _len1, _ref, _results1;
  179. _ref = this.options.ykeys;
  180. _results1 = [];
  181. for (idx = _j = 0, _len1 = _ref.length; _j < _len1; idx = ++_j) {
  182. ykey = _ref[idx];
  183. yval = row[ykey];
  184. if (typeof yval === 'string') {
  185. yval = parseFloat(yval);
  186. }
  187. if ((yval != null) && typeof yval !== 'number') {
  188. yval = null;
  189. }
  190. if (yval != null) {
  191. if (this.cumulative) {
  192. total += yval;
  193. } else {
  194. if (ymax != null) {
  195. ymax = Math.max(yval, ymax);
  196. ymin = Math.min(yval, ymin);
  197. } else {
  198. ymax = ymin = yval;
  199. }
  200. }
  201. }
  202. if (this.cumulative && (total != null)) {
  203. ymax = Math.max(total, ymax);
  204. ymin = Math.min(total, ymin);
  205. }
  206. _results1.push(yval);
  207. }
  208. return _results1;
  209. }).call(this);
  210. _results.push(ret);
  211. }
  212. return _results;
  213. }).call(this);
  214. if (this.options.parseTime) {
  215. this.data = this.data.sort(function(a, b) {
  216. return (a.x > b.x) - (b.x > a.x);
  217. });
  218. }
  219. this.xmin = this.data[0].x;
  220. this.xmax = this.data[this.data.length - 1].x;
  221. this.events = [];
  222. if (this.options.parseTime && this.options.events.length > 0) {
  223. this.events = (function() {
  224. var _i, _len, _ref, _results;
  225. _ref = this.options.events;
  226. _results = [];
  227. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  228. e = _ref[_i];
  229. _results.push(Morris.parseDate(e));
  230. }
  231. return _results;
  232. }).call(this);
  233. this.xmax = Math.max(this.xmax, Math.max.apply(null, this.events));
  234. this.xmin = Math.min(this.xmin, Math.min.apply(null, this.events));
  235. }
  236. if (this.xmin === this.xmax) {
  237. this.xmin -= 1;
  238. this.xmax += 1;
  239. }
  240. this.ymin = this.yboundary('min', ymin);
  241. this.ymax = this.yboundary('max', ymax);
  242. if (this.ymin === this.ymax) {
  243. if (ymin) {
  244. this.ymin -= 1;
  245. }
  246. this.ymax += 1;
  247. }
  248. if (this.options.axes === true || this.options.grid === true) {
  249. if (this.options.ymax === this.gridDefaults.ymax && this.options.ymin === this.gridDefaults.ymin) {
  250. this.grid = this.autoGridLines(this.ymin, this.ymax, this.options.numLines);
  251. this.ymin = Math.min(this.ymin, this.grid[0]);
  252. this.ymax = Math.max(this.ymax, this.grid[this.grid.length - 1]);
  253. } else {
  254. step = (this.ymax - this.ymin) / (this.options.numLines - 1);
  255. this.grid = (function() {
  256. var _i, _ref, _ref1, _results;
  257. _results = [];
  258. for (y = _i = _ref = this.ymin, _ref1 = this.ymax; _ref <= _ref1 ? _i <= _ref1 : _i >= _ref1; y = _i += step) {
  259. _results.push(y);
  260. }
  261. return _results;
  262. }).call(this);
  263. }
  264. }
  265. this.dirty = true;
  266. if (redraw) {
  267. return this.redraw();
  268. }
  269. };
  270. Grid.prototype.yboundary = function(boundaryType, currentValue) {
  271. var boundaryOption, suggestedValue;
  272. boundaryOption = this.options["y" + boundaryType];
  273. if (typeof boundaryOption === 'string') {
  274. if (boundaryOption.slice(0, 4) === 'auto') {
  275. if (boundaryOption.length > 5) {
  276. suggestedValue = parseInt(boundaryOption.slice(5), 10);
  277. if (currentValue == null) {
  278. return suggestedValue;
  279. }
  280. return Math[boundaryType](currentValue, suggestedValue);
  281. } else {
  282. if (currentValue != null) {
  283. return currentValue;
  284. } else {
  285. return 0;
  286. }
  287. }
  288. } else {
  289. return parseInt(boundaryOption, 10);
  290. }
  291. } else {
  292. return boundaryOption;
  293. }
  294. };
  295. Grid.prototype.autoGridLines = function(ymin, ymax, nlines) {
  296. var gmax, gmin, grid, smag, span, step, unit, y, ymag;
  297. span = ymax - ymin;
  298. ymag = Math.floor(Math.log(span) / Math.log(10));
  299. unit = Math.pow(10, ymag);
  300. gmin = Math.floor(ymin / unit) * unit;
  301. gmax = Math.ceil(ymax / unit) * unit;
  302. step = (gmax - gmin) / (nlines - 1);
  303. if (unit === 1 && step > 1 && Math.ceil(step) !== step) {
  304. step = Math.ceil(step);
  305. gmax = gmin + step * (nlines - 1);
  306. }
  307. if (gmin < 0 && gmax > 0) {
  308. gmin = Math.floor(ymin / step) * step;
  309. gmax = Math.ceil(ymax / step) * step;
  310. }
  311. if (step < 1) {
  312. smag = Math.floor(Math.log(step) / Math.log(10));
  313. grid = (function() {
  314. var _i, _results;
  315. _results = [];
  316. for (y = _i = gmin; gmin <= gmax ? _i <= gmax : _i >= gmax; y = _i += step) {
  317. _results.push(parseFloat(y.toFixed(1 - smag)));
  318. }
  319. return _results;
  320. })();
  321. } else {
  322. grid = (function() {
  323. var _i, _results;
  324. _results = [];
  325. for (y = _i = gmin; gmin <= gmax ? _i <= gmax : _i >= gmax; y = _i += step) {
  326. _results.push(y);
  327. }
  328. return _results;
  329. })();
  330. }
  331. return grid;
  332. };
  333. Grid.prototype._calc = function() {
  334. var bottomOffsets, gridLine, h, i, w, yLabelWidths;
  335. w = this.el.width();
  336. h = this.el.height();
  337. if (this.elementWidth !== w || this.elementHeight !== h || this.dirty) {
  338. this.elementWidth = w;
  339. this.elementHeight = h;
  340. this.dirty = false;
  341. this.left = this.options.padding;
  342. this.right = this.elementWidth - this.options.padding;
  343. this.top = this.options.padding;
  344. this.bottom = this.elementHeight - this.options.padding;
  345. if (this.options.axes) {
  346. yLabelWidths = (function() {
  347. var _i, _len, _ref, _results;
  348. _ref = this.grid;
  349. _results = [];
  350. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  351. gridLine = _ref[_i];
  352. _results.push(this.measureText(this.yAxisFormat(gridLine)).width);
  353. }
  354. return _results;
  355. }).call(this);
  356. this.left += Math.max.apply(Math, yLabelWidths);
  357. bottomOffsets = (function() {
  358. var _i, _ref, _results;
  359. _results = [];
  360. for (i = _i = 0, _ref = this.data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  361. _results.push(this.measureText(this.data[i].text, -this.options.xLabelAngle).height);
  362. }
  363. return _results;
  364. }).call(this);
  365. this.bottom -= Math.max.apply(Math, bottomOffsets);
  366. }
  367. this.width = Math.max(1, this.right - this.left);
  368. this.height = Math.max(1, this.bottom - this.top);
  369. this.dx = this.width / (this.xmax - this.xmin);
  370. this.dy = this.height / (this.ymax - this.ymin);
  371. if (this.calc) {
  372. return this.calc();
  373. }
  374. }
  375. };
  376. Grid.prototype.transY = function(y) {
  377. return this.bottom - (y - this.ymin) * this.dy;
  378. };
  379. Grid.prototype.transX = function(x) {
  380. if (this.data.length === 1) {
  381. return (this.left + this.right) / 2;
  382. } else {
  383. return this.left + (x - this.xmin) * this.dx;
  384. }
  385. };
  386. Grid.prototype.redraw = function() {
  387. this.raphael.clear();
  388. this._calc();
  389. this.drawGrid();
  390. this.drawGoals();
  391. this.drawEvents();
  392. if (this.draw) {
  393. return this.draw();
  394. }
  395. };
  396. Grid.prototype.measureText = function(text, angle) {
  397. var ret, tt;
  398. if (angle == null) {
  399. angle = 0;
  400. }
  401. tt = this.raphael.text(100, 100, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).rotate(angle);
  402. ret = tt.getBBox();
  403. tt.remove();
  404. return ret;
  405. };
  406. Grid.prototype.yAxisFormat = function(label) {
  407. return this.yLabelFormat(label);
  408. };
  409. Grid.prototype.yLabelFormat = function(label) {
  410. if (typeof this.options.yLabelFormat === 'function') {
  411. return this.options.yLabelFormat(label);
  412. } else {
  413. return "" + this.options.preUnits + (Morris.commas(label)) + this.options.postUnits;
  414. }
  415. };
  416. Grid.prototype.updateHover = function(x, y) {
  417. var hit, _ref;
  418. hit = this.hitTest(x, y);
  419. if (hit != null) {
  420. return (_ref = this.hover).update.apply(_ref, hit);
  421. }
  422. };
  423. Grid.prototype.drawGrid = function() {
  424. var lineY, y, _i, _len, _ref, _results;
  425. if (this.options.grid === false && this.options.axes === false) {
  426. return;
  427. }
  428. _ref = this.grid;
  429. _results = [];
  430. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  431. lineY = _ref[_i];
  432. y = this.transY(lineY);
  433. if (this.options.axes) {
  434. this.drawYAxisLabel(this.left - this.options.padding / 2, y, this.yAxisFormat(lineY));
  435. }
  436. if (this.options.grid) {
  437. _results.push(this.drawGridLine("M" + this.left + "," + y + "H" + (this.left + this.width)));
  438. } else {
  439. _results.push(void 0);
  440. }
  441. }
  442. return _results;
  443. };
  444. Grid.prototype.drawGoals = function() {
  445. var color, goal, i, _i, _len, _ref, _results;
  446. _ref = this.options.goals;
  447. _results = [];
  448. for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
  449. goal = _ref[i];
  450. color = this.options.goalLineColors[i % this.options.goalLineColors.length];
  451. _results.push(this.drawGoal(goal, color));
  452. }
  453. return _results;
  454. };
  455. Grid.prototype.drawEvents = function() {
  456. var color, event, i, _i, _len, _ref, _results;
  457. _ref = this.events;
  458. _results = [];
  459. for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
  460. event = _ref[i];
  461. color = this.options.eventLineColors[i % this.options.eventLineColors.length];
  462. _results.push(this.drawEvent(event, color));
  463. }
  464. return _results;
  465. };
  466. Grid.prototype.drawGoal = function(goal, color) {
  467. return this.raphael.path("M" + this.left + "," + (this.transY(goal)) + "H" + this.right).attr('stroke', color).attr('stroke-width', this.options.goalStrokeWidth);
  468. };
  469. Grid.prototype.drawEvent = function(event, color) {
  470. return this.raphael.path("M" + (this.transX(event)) + "," + this.bottom + "V" + this.top).attr('stroke', color).attr('stroke-width', this.options.eventStrokeWidth);
  471. };
  472. Grid.prototype.drawYAxisLabel = function(xPos, yPos, text) {
  473. return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor).attr('text-anchor', 'end');
  474. };
  475. Grid.prototype.drawGridLine = function(path) {
  476. return this.raphael.path(path).attr('stroke', this.options.gridLineColor).attr('stroke-width', this.options.gridStrokeWidth);
  477. };
  478. return Grid;
  479. })(Morris.EventEmitter);
  480. Morris.parseDate = function(date) {
  481. var isecs, m, msecs, n, o, offsetmins, p, q, r, ret, secs;
  482. if (typeof date === 'number') {
  483. return date;
  484. }
  485. m = date.match(/^(\d+) Q(\d)$/);
  486. n = date.match(/^(\d+)-(\d+)$/);
  487. o = date.match(/^(\d+)-(\d+)-(\d+)$/);
  488. p = date.match(/^(\d+) W(\d+)$/);
  489. q = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)(Z|([+-])(\d\d):?(\d\d))?$/);
  490. r = date.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)(Z|([+-])(\d\d):?(\d\d))?$/);
  491. if (m) {
  492. return new Date(parseInt(m[1], 10), parseInt(m[2], 10) * 3 - 1, 1).getTime();
  493. } else if (n) {
  494. return new Date(parseInt(n[1], 10), parseInt(n[2], 10) - 1, 1).getTime();
  495. } else if (o) {
  496. return new Date(parseInt(o[1], 10), parseInt(o[2], 10) - 1, parseInt(o[3], 10)).getTime();
  497. } else if (p) {
  498. ret = new Date(parseInt(p[1], 10), 0, 1);
  499. if (ret.getDay() !== 4) {
  500. ret.setMonth(0, 1 + ((4 - ret.getDay()) + 7) % 7);
  501. }
  502. return ret.getTime() + parseInt(p[2], 10) * 604800000;
  503. } else if (q) {
  504. if (!q[6]) {
  505. return new Date(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10)).getTime();
  506. } else {
  507. offsetmins = 0;
  508. if (q[6] !== 'Z') {
  509. offsetmins = parseInt(q[8], 10) * 60 + parseInt(q[9], 10);
  510. if (q[7] === '+') {
  511. offsetmins = 0 - offsetmins;
  512. }
  513. }
  514. return Date.UTC(parseInt(q[1], 10), parseInt(q[2], 10) - 1, parseInt(q[3], 10), parseInt(q[4], 10), parseInt(q[5], 10) + offsetmins);
  515. }
  516. } else if (r) {
  517. secs = parseFloat(r[6]);
  518. isecs = Math.floor(secs);
  519. msecs = Math.round((secs - isecs) * 1000);
  520. if (!r[8]) {
  521. return new Date(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10), isecs, msecs).getTime();
  522. } else {
  523. offsetmins = 0;
  524. if (r[8] !== 'Z') {
  525. offsetmins = parseInt(r[10], 10) * 60 + parseInt(r[11], 10);
  526. if (r[9] === '+') {
  527. offsetmins = 0 - offsetmins;
  528. }
  529. }
  530. return Date.UTC(parseInt(r[1], 10), parseInt(r[2], 10) - 1, parseInt(r[3], 10), parseInt(r[4], 10), parseInt(r[5], 10) + offsetmins, isecs, msecs);
  531. }
  532. } else {
  533. return new Date(parseInt(date, 10), 0, 1).getTime();
  534. }
  535. };
  536. Morris.Hover = (function() {
  537. Hover.defaults = {
  538. "class": 'morris-hover morris-default-style'
  539. };
  540. function Hover(options) {
  541. if (options == null) {
  542. options = {};
  543. }
  544. this.options = $.extend({}, Morris.Hover.defaults, options);
  545. this.el = $("<div class='" + this.options["class"] + "'></div>");
  546. this.el.hide();
  547. this.options.parent.append(this.el);
  548. }
  549. Hover.prototype.update = function(html, x, y) {
  550. this.html(html);
  551. this.show();
  552. return this.moveTo(x, y);
  553. };
  554. Hover.prototype.html = function(content) {
  555. return this.el.html(content);
  556. };
  557. Hover.prototype.moveTo = function(x, y) {
  558. var hoverHeight, hoverWidth, left, parentHeight, parentWidth, top;
  559. parentWidth = this.options.parent.innerWidth();
  560. parentHeight = this.options.parent.innerHeight();
  561. hoverWidth = this.el.outerWidth();
  562. hoverHeight = this.el.outerHeight();
  563. left = Math.min(Math.max(0, x - hoverWidth / 2), parentWidth - hoverWidth);
  564. if (y != null) {
  565. top = y - hoverHeight - 10;
  566. if (top < 0) {
  567. top = y + 10;
  568. if (top + hoverHeight > parentHeight) {
  569. top = parentHeight / 2 - hoverHeight / 2;
  570. }
  571. }
  572. } else {
  573. top = parentHeight / 2 - hoverHeight / 2;
  574. }
  575. return this.el.css({
  576. left: left + "px",
  577. top: parseInt(top) + "px"
  578. });
  579. };
  580. Hover.prototype.show = function() {
  581. return this.el.show();
  582. };
  583. Hover.prototype.hide = function() {
  584. return this.el.hide();
  585. };
  586. return Hover;
  587. })();
  588. Morris.Line = (function(_super) {
  589. __extends(Line, _super);
  590. function Line(options) {
  591. this.hilight = __bind(this.hilight, this);
  592. this.onHoverOut = __bind(this.onHoverOut, this);
  593. this.onHoverMove = __bind(this.onHoverMove, this);
  594. this.onGridClick = __bind(this.onGridClick, this);
  595. if (!(this instanceof Morris.Line)) {
  596. return new Morris.Line(options);
  597. }
  598. Line.__super__.constructor.call(this, options);
  599. }
  600. Line.prototype.init = function() {
  601. this.pointGrow = Raphael.animation({
  602. r: this.options.pointSize + 3
  603. }, 25, 'linear');
  604. this.pointShrink = Raphael.animation({
  605. r: this.options.pointSize
  606. }, 25, 'linear');
  607. if (this.options.hideHover !== 'always') {
  608. this.hover = new Morris.Hover({
  609. parent: this.el
  610. });
  611. this.on('hovermove', this.onHoverMove);
  612. this.on('hoverout', this.onHoverOut);
  613. return this.on('gridclick', this.onGridClick);
  614. }
  615. };
  616. Line.prototype.defaults = {
  617. lineWidth: 3,
  618. pointSize: 4,
  619. lineColors: ['#0b62a4', '#7A92A3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'],
  620. pointWidths: [1],
  621. pointStrokeColors: ['#ffffff'],
  622. pointFillColors: [],
  623. smooth: true,
  624. xLabels: 'auto',
  625. xLabelFormat: null,
  626. xLabelMargin: 24,
  627. continuousLine: true,
  628. hideHover: false
  629. };
  630. Line.prototype.calc = function() {
  631. this.calcPoints();
  632. return this.generatePaths();
  633. };
  634. Line.prototype.calcPoints = function() {
  635. var row, y, _i, _len, _ref, _results;
  636. _ref = this.data;
  637. _results = [];
  638. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  639. row = _ref[_i];
  640. row._x = this.transX(row.x);
  641. row._y = (function() {
  642. var _j, _len1, _ref1, _results1;
  643. _ref1 = row.y;
  644. _results1 = [];
  645. for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
  646. y = _ref1[_j];
  647. if (y != null) {
  648. _results1.push(this.transY(y));
  649. } else {
  650. _results1.push(y);
  651. }
  652. }
  653. return _results1;
  654. }).call(this);
  655. _results.push(row._ymax = Math.min.apply(null, [this.bottom].concat((function() {
  656. var _j, _len1, _ref1, _results1;
  657. _ref1 = row._y;
  658. _results1 = [];
  659. for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
  660. y = _ref1[_j];
  661. if (y != null) {
  662. _results1.push(y);
  663. }
  664. }
  665. return _results1;
  666. })())));
  667. }
  668. return _results;
  669. };
  670. Line.prototype.hitTest = function(x, y) {
  671. var index, r, _i, _len, _ref;
  672. if (this.data.length === 0) {
  673. return null;
  674. }
  675. _ref = this.data.slice(1);
  676. for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
  677. r = _ref[index];
  678. if (x < (r._x + this.data[index]._x) / 2) {
  679. break;
  680. }
  681. }
  682. return index;
  683. };
  684. Line.prototype.onGridClick = function(x, y) {
  685. var index;
  686. index = this.hitTest(x, y);
  687. return this.fire('click', index, this.options.data[index], x, y);
  688. };
  689. Line.prototype.onHoverMove = function(x, y) {
  690. var index;
  691. index = this.hitTest(x, y);
  692. return this.displayHoverForRow(index);
  693. };
  694. Line.prototype.onHoverOut = function() {
  695. if (this.options.hideHover !== false) {
  696. return this.displayHoverForRow(null);
  697. }
  698. };
  699. Line.prototype.displayHoverForRow = function(index) {
  700. var _ref;
  701. if (index != null) {
  702. (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index));
  703. return this.hilight(index);
  704. } else {
  705. this.hover.hide();
  706. return this.hilight();
  707. }
  708. };
  709. Line.prototype.hoverContentForRow = function(index) {
  710. var content, j, row, y, _i, _len, _ref;
  711. row = this.data[index];
  712. content = "<div class='morris-hover-row-label'>" + row.label + "</div>";
  713. _ref = row.y;
  714. for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) {
  715. y = _ref[j];
  716. content += "<div class='morris-hover-point' style='color: " + (this.colorFor(row, j, 'label')) + "'>\n " + this.options.labels[j] + ":\n " + (this.yLabelFormat(y)) + "\n</div>";
  717. }
  718. if (typeof this.options.hoverCallback === 'function') {
  719. content = this.options.hoverCallback(index, this.options, content);
  720. }
  721. return [content, row._x, row._ymax];
  722. };
  723. Line.prototype.generatePaths = function() {
  724. var c, coords, i, r, smooth;
  725. return this.paths = (function() {
  726. var _i, _ref, _ref1, _results;
  727. _results = [];
  728. for (i = _i = 0, _ref = this.options.ykeys.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  729. smooth = this.options.smooth === true || (_ref1 = this.options.ykeys[i], __indexOf.call(this.options.smooth, _ref1) >= 0);
  730. coords = (function() {
  731. var _j, _len, _ref2, _results1;
  732. _ref2 = this.data;
  733. _results1 = [];
  734. for (_j = 0, _len = _ref2.length; _j < _len; _j++) {
  735. r = _ref2[_j];
  736. if (r._y[i] !== void 0) {
  737. _results1.push({
  738. x: r._x,
  739. y: r._y[i]
  740. });
  741. }
  742. }
  743. return _results1;
  744. }).call(this);
  745. if (this.options.continuousLine) {
  746. coords = (function() {
  747. var _j, _len, _results1;
  748. _results1 = [];
  749. for (_j = 0, _len = coords.length; _j < _len; _j++) {
  750. c = coords[_j];
  751. if (c.y !== null) {
  752. _results1.push(c);
  753. }
  754. }
  755. return _results1;
  756. })();
  757. }
  758. if (coords.length > 1) {
  759. _results.push(Morris.Line.createPath(coords, smooth, this.bottom));
  760. } else {
  761. _results.push(null);
  762. }
  763. }
  764. return _results;
  765. }).call(this);
  766. };
  767. Line.prototype.draw = function() {
  768. if (this.options.axes) {
  769. this.drawXAxis();
  770. }
  771. this.drawSeries();
  772. if (this.options.hideHover === false) {
  773. return this.displayHoverForRow(this.data.length - 1);
  774. }
  775. };
  776. Line.prototype.drawXAxis = function() {
  777. var drawLabel, l, labels, prevAngleMargin, prevLabelMargin, row, ypos, _i, _len, _results,
  778. _this = this;
  779. ypos = this.bottom + this.options.padding / 2;
  780. prevLabelMargin = null;
  781. prevAngleMargin = null;
  782. drawLabel = function(labelText, xpos) {
  783. var label, labelBox, margin, offset, textBox;
  784. label = _this.drawXAxisLabel(_this.transX(xpos), ypos, labelText);
  785. textBox = label.getBBox();
  786. label.transform("r" + (-_this.options.xLabelAngle));
  787. labelBox = label.getBBox();
  788. label.transform("t0," + (labelBox.height / 2) + "...");
  789. if (_this.options.xLabelAngle !== 0) {
  790. offset = -0.5 * textBox.width * Math.cos(_this.options.xLabelAngle * Math.PI / 180.0);
  791. label.transform("t" + offset + ",0...");
  792. }
  793. labelBox = label.getBBox();
  794. if ((!(prevLabelMargin != null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < _this.el.width()) {
  795. if (_this.options.xLabelAngle !== 0) {
  796. margin = 1.25 * _this.options.gridTextSize / Math.sin(_this.options.xLabelAngle * Math.PI / 180.0);
  797. prevAngleMargin = labelBox.x - margin;
  798. }
  799. return prevLabelMargin = labelBox.x - _this.options.xLabelMargin;
  800. } else {
  801. return label.remove();
  802. }
  803. };
  804. if (this.options.parseTime) {
  805. if (this.data.length === 1 && this.options.xLabels === 'auto') {
  806. labels = [[this.data[0].label, this.data[0].x]];
  807. } else {
  808. labels = Morris.labelSeries(this.xmin, this.xmax, this.width, this.options.xLabels, this.options.xLabelFormat);
  809. }
  810. } else {
  811. labels = (function() {
  812. var _i, _len, _ref, _results;
  813. _ref = this.data;
  814. _results = [];
  815. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  816. row = _ref[_i];
  817. _results.push([row.label, row.x]);
  818. }
  819. return _results;
  820. }).call(this);
  821. }
  822. labels.reverse();
  823. _results = [];
  824. for (_i = 0, _len = labels.length; _i < _len; _i++) {
  825. l = labels[_i];
  826. _results.push(drawLabel(l[0], l[1]));
  827. }
  828. return _results;
  829. };
  830. Line.prototype.drawSeries = function() {
  831. var i, _i, _j, _ref, _ref1, _results;
  832. this.seriesPoints = [];
  833. for (i = _i = _ref = this.options.ykeys.length - 1; _ref <= 0 ? _i <= 0 : _i >= 0; i = _ref <= 0 ? ++_i : --_i) {
  834. this._drawLineFor(i);
  835. }
  836. _results = [];
  837. for (i = _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; i = _ref1 <= 0 ? ++_j : --_j) {
  838. _results.push(this._drawPointFor(i));
  839. }
  840. return _results;
  841. };
  842. Line.prototype._drawPointFor = function(index) {
  843. var circle, row, _i, _len, _ref, _results;
  844. this.seriesPoints[index] = [];
  845. _ref = this.data;
  846. _results = [];
  847. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  848. row = _ref[_i];
  849. circle = null;
  850. if (row._y[index] != null) {
  851. circle = this.drawLinePoint(row._x, row._y[index], this.options.pointSize, this.colorFor(row, index, 'point'), index);
  852. }
  853. _results.push(this.seriesPoints[index].push(circle));
  854. }
  855. return _results;
  856. };
  857. Line.prototype._drawLineFor = function(index) {
  858. var path;
  859. path = this.paths[index];
  860. if (path !== null) {
  861. return this.drawLinePath(path, this.colorFor(null, index, 'line'));
  862. }
  863. };
  864. Line.createPath = function(coords, smooth, bottom) {
  865. var coord, g, grads, i, ix, lg, path, prevCoord, x1, x2, y1, y2, _i, _len;
  866. path = "";
  867. if (smooth) {
  868. grads = Morris.Line.gradients(coords);
  869. }
  870. prevCoord = {
  871. y: null
  872. };
  873. for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) {
  874. coord = coords[i];
  875. if (coord.y != null) {
  876. if (prevCoord.y != null) {
  877. if (smooth) {
  878. g = grads[i];
  879. lg = grads[i - 1];
  880. ix = (coord.x - prevCoord.x) / 4;
  881. x1 = prevCoord.x + ix;
  882. y1 = Math.min(bottom, prevCoord.y + ix * lg);
  883. x2 = coord.x - ix;
  884. y2 = Math.min(bottom, coord.y - ix * g);
  885. path += "C" + x1 + "," + y1 + "," + x2 + "," + y2 + "," + coord.x + "," + coord.y;
  886. } else {
  887. path += "L" + coord.x + "," + coord.y;
  888. }
  889. } else {
  890. if (!smooth || (grads[i] != null)) {
  891. path += "M" + coord.x + "," + coord.y;
  892. }
  893. }
  894. }
  895. prevCoord = coord;
  896. }
  897. return path;
  898. };
  899. Line.gradients = function(coords) {
  900. var coord, grad, i, nextCoord, prevCoord, _i, _len, _results;
  901. grad = function(a, b) {
  902. return (a.y - b.y) / (a.x - b.x);
  903. };
  904. _results = [];
  905. for (i = _i = 0, _len = coords.length; _i < _len; i = ++_i) {
  906. coord = coords[i];
  907. if (coord.y != null) {
  908. nextCoord = coords[i + 1] || {
  909. y: null
  910. };
  911. prevCoord = coords[i - 1] || {
  912. y: null
  913. };
  914. if ((prevCoord.y != null) && (nextCoord.y != null)) {
  915. _results.push(grad(prevCoord, nextCoord));
  916. } else if (prevCoord.y != null) {
  917. _results.push(grad(prevCoord, coord));
  918. } else if (nextCoord.y != null) {
  919. _results.push(grad(coord, nextCoord));
  920. } else {
  921. _results.push(null);
  922. }
  923. } else {
  924. _results.push(null);
  925. }
  926. }
  927. return _results;
  928. };
  929. Line.prototype.hilight = function(index) {
  930. var i, _i, _j, _ref, _ref1;
  931. if (this.prevHilight !== null && this.prevHilight !== index) {
  932. for (i = _i = 0, _ref = this.seriesPoints.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {
  933. if (this.seriesPoints[i][this.prevHilight]) {
  934. this.seriesPoints[i][this.prevHilight].animate(this.pointShrink);
  935. }
  936. }
  937. }
  938. if (index !== null && this.prevHilight !== index) {
  939. for (i = _j = 0, _ref1 = this.seriesPoints.length - 1; 0 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
  940. if (this.seriesPoints[i][index]) {
  941. this.seriesPoints[i][index].animate(this.pointGrow);
  942. }
  943. }
  944. }
  945. return this.prevHilight = index;
  946. };
  947. Line.prototype.colorFor = function(row, sidx, type) {
  948. if (typeof this.options.lineColors === 'function') {
  949. return this.options.lineColors.call(this, row, sidx, type);
  950. } else if (type === 'point') {
  951. return this.options.pointFillColors[sidx % this.options.pointFillColors.length] || this.options.lineColors[sidx % this.options.lineColors.length];
  952. } else {
  953. return this.options.lineColors[sidx % this.options.lineColors.length];
  954. }
  955. };
  956. Line.prototype.drawXAxisLabel = function(xPos, yPos, text) {
  957. return this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor);
  958. };
  959. Line.prototype.drawLinePath = function(path, lineColor) {
  960. return this.raphael.path(path).attr('stroke', lineColor).attr('stroke-width', this.options.lineWidth);
  961. };
  962. Line.prototype.drawLinePoint = function(xPos, yPos, size, pointColor, lineIndex) {
  963. return this.raphael.circle(xPos, yPos, size).attr('fill', pointColor).attr('stroke-width', this.strokeWidthForSeries(lineIndex)).attr('stroke', this.strokeForSeries(lineIndex));
  964. };
  965. Line.prototype.strokeWidthForSeries = function(index) {
  966. return this.options.pointWidths[index % this.options.pointWidths.length];
  967. };
  968. Line.prototype.strokeForSeries = function(index) {
  969. return this.options.pointStrokeColors[index % this.options.pointStrokeColors.length];
  970. };
  971. return Line;
  972. })(Morris.Grid);
  973. Morris.labelSeries = function(dmin, dmax, pxwidth, specName, xLabelFormat) {
  974. var d, d0, ddensity, name, ret, s, spec, t, _i, _len, _ref;
  975. ddensity = 200 * (dmax - dmin) / pxwidth;
  976. d0 = new Date(dmin);
  977. spec = Morris.LABEL_SPECS[specName];
  978. if (spec === void 0) {
  979. _ref = Morris.AUTO_LABEL_ORDER;
  980. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  981. name = _ref[_i];
  982. s = Morris.LABEL_SPECS[name];
  983. if (ddensity >= s.span) {
  984. spec = s;
  985. break;
  986. }
  987. }
  988. }
  989. if (spec === void 0) {
  990. spec = Morris.LABEL_SPECS["second"];
  991. }
  992. if (xLabelFormat) {
  993. spec = $.extend({}, spec, {
  994. fmt: xLabelFormat
  995. });
  996. }
  997. d = spec.start(d0);
  998. ret = [];
  999. while ((t = d.getTime()) <= dmax) {
  1000. if (t >= dmin) {
  1001. ret.push([spec.fmt(d), t]);
  1002. }
  1003. spec.incr(d);
  1004. }
  1005. return ret;
  1006. };
  1007. minutesSpecHelper = function(interval) {
  1008. return {
  1009. span: interval * 60 * 1000,
  1010. start: function(d) {
  1011. return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours());
  1012. },
  1013. fmt: function(d) {
  1014. return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes()));
  1015. },
  1016. incr: function(d) {
  1017. return d.setUTCMinutes(d.getUTCMinutes() + interval);
  1018. }
  1019. };
  1020. };
  1021. secondsSpecHelper = function(interval) {
  1022. return {
  1023. span: interval * 1000,
  1024. start: function(d) {
  1025. return new Date(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes());
  1026. },
  1027. fmt: function(d) {
  1028. return "" + (Morris.pad2(d.getHours())) + ":" + (Morris.pad2(d.getMinutes())) + ":" + (Morris.pad2(d.getSeconds()));
  1029. },
  1030. incr: function(d) {
  1031. return d.setUTCSeconds(d.getUTCSeconds() + interval);
  1032. }
  1033. };
  1034. };
  1035. Morris.LABEL_SPECS = {
  1036. "decade": {
  1037. span: 172800000000,
  1038. start: function(d) {
  1039. return new Date(d.getFullYear() - d.getFullYear() % 10, 0, 1);
  1040. },
  1041. fmt: function(d) {
  1042. return "" + (d.getFullYear());
  1043. },
  1044. incr: function(d) {
  1045. return d.setFullYear(d.getFullYear() + 10);
  1046. }
  1047. },
  1048. "year": {
  1049. span: 17280000000,
  1050. start: function(d) {
  1051. return new Date(d.getFullYear(), 0, 1);
  1052. },
  1053. fmt: function(d) {
  1054. return "" + (d.getFullYear());
  1055. },
  1056. incr: function(d) {
  1057. return d.setFullYear(d.getFullYear() + 1);
  1058. }
  1059. },
  1060. "month": {
  1061. span: 2419200000,
  1062. start: function(d) {
  1063. return new Date(d.getFullYear(), d.getMonth(), 1);
  1064. },
  1065. fmt: function(d) {
  1066. return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1));
  1067. },
  1068. incr: function(d) {
  1069. return d.setMonth(d.getMonth() + 1);
  1070. }
  1071. },
  1072. "day": {
  1073. span: 86400000,
  1074. start: function(d) {
  1075. return new Date(d.getFullYear(), d.getMonth(), d.getDate());
  1076. },
  1077. fmt: function(d) {
  1078. return "" + (d.getFullYear()) + "-" + (Morris.pad2(d.getMonth() + 1)) + "-" + (Morris.pad2(d.getDate()));
  1079. },
  1080. incr: function(d) {
  1081. return d.setDate(d.getDate() + 1);
  1082. }
  1083. },
  1084. "hour": minutesSpecHelper(60),
  1085. "30min": minutesSpecHelper(30),
  1086. "15min": minutesSpecHelper(15),
  1087. "10min": minutesSpecHelper(10),
  1088. "5min": minutesSpecHelper(5),
  1089. "minute": minutesSpecHelper(1),
  1090. "30sec": secondsSpecHelper(30),
  1091. "15sec": secondsSpecHelper(15),
  1092. "10sec": secondsSpecHelper(10),
  1093. "5sec": secondsSpecHelper(5),
  1094. "second": secondsSpecHelper(1)
  1095. };
  1096. Morris.AUTO_LABEL_ORDER = ["decade", "year", "month", "day", "hour", "30min", "15min", "10min", "5min", "minute", "30sec", "15sec", "10sec", "5sec", "second"];
  1097. Morris.Area = (function(_super) {
  1098. var areaDefaults;
  1099. __extends(Area, _super);
  1100. areaDefaults = {
  1101. fillOpacity: 'auto',
  1102. behaveLikeLine: false
  1103. };
  1104. function Area(options) {
  1105. var areaOptions;
  1106. if (!(this instanceof Morris.Area)) {
  1107. return new Morris.Area(options);
  1108. }
  1109. areaOptions = $.extend({}, areaDefaults, options);
  1110. this.cumulative = !areaOptions.behaveLikeLine;
  1111. if (areaOptions.fillOpacity === 'auto') {
  1112. areaOptions.fillOpacity = areaOptions.behaveLikeLine ? .8 : 1;
  1113. }
  1114. Area.__super__.constructor.call(this, areaOptions);
  1115. }
  1116. Area.prototype.calcPoints = function() {
  1117. var row, total, y, _i, _len, _ref, _results;
  1118. _ref = this.data;
  1119. _results = [];
  1120. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  1121. row = _ref[_i];
  1122. row._x = this.transX(row.x);
  1123. total = 0;
  1124. row._y = (function() {
  1125. var _j, _len1, _ref1, _results1;
  1126. _ref1 = row.y;
  1127. _results1 = [];
  1128. for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
  1129. y = _ref1[_j];
  1130. if (this.options.behaveLikeLine) {
  1131. _results1.push(this.transY(y));
  1132. } else {
  1133. total += y || 0;
  1134. _results1.push(this.transY(total));
  1135. }
  1136. }
  1137. return _results1;
  1138. }).call(this);
  1139. _results.push(row._ymax = Math.max.apply(Math, row._y));
  1140. }
  1141. return _results;
  1142. };
  1143. Area.prototype.drawSeries = function() {
  1144. var i, range, _i, _j, _k, _len, _ref, _ref1, _results, _results1, _results2;
  1145. this.seriesPoints = [];
  1146. if (this.options.behaveLikeLine) {
  1147. range = (function() {
  1148. _results = [];
  1149. for (var _i = 0, _ref = this.options.ykeys.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); }
  1150. return _results;
  1151. }).apply(this);
  1152. } else {
  1153. range = (function() {
  1154. _results1 = [];
  1155. for (var _j = _ref1 = this.options.ykeys.length - 1; _ref1 <= 0 ? _j <= 0 : _j >= 0; _ref1 <= 0 ? _j++ : _j--){ _results1.push(_j); }
  1156. return _results1;
  1157. }).apply(this);
  1158. }
  1159. _results2 = [];
  1160. for (_k = 0, _len = range.length; _k < _len; _k++) {
  1161. i = range[_k];
  1162. this._drawFillFor(i);
  1163. this._drawLineFor(i);
  1164. _results2.push(this._drawPointFor(i));
  1165. }
  1166. return _results2;
  1167. };
  1168. Area.prototype._drawFillFor = function(index) {
  1169. var path;
  1170. path = this.paths[index];
  1171. if (path !== null) {
  1172. path = path + ("L" + (this.transX(this.xmax)) + "," + this.bottom + "L" + (this.transX(this.xmin)) + "," + this.bottom + "Z");
  1173. return this.drawFilledPath(path, this.fillForSeries(index));
  1174. }
  1175. };
  1176. Area.prototype.fillForSeries = function(i) {
  1177. var color;
  1178. color = Raphael.rgb2hsl(this.colorFor(this.data[i], i, 'line'));
  1179. return Raphael.hsl(color.h, this.options.behaveLikeLine ? color.s * 0.9 : color.s * 0.75, Math.min(0.98, this.options.behaveLikeLine ? color.l * 1.2 : color.l * 1.25));
  1180. };
  1181. Area.prototype.drawFilledPath = function(path, fill) {
  1182. return this.raphael.path(path).attr('fill', fill).attr('fill-opacity', this.options.fillOpacity).attr('stroke-width', 0);
  1183. };
  1184. return Area;
  1185. })(Morris.Line);
  1186. Morris.Bar = (function(_super) {
  1187. __extends(Bar, _super);
  1188. function Bar(options) {
  1189. this.onHoverOut = __bind(this.onHoverOut, this);
  1190. this.onHoverMove = __bind(this.onHoverMove, this);
  1191. this.onGridClick = __bind(this.onGridClick, this);
  1192. if (!(this instanceof Morris.Bar)) {
  1193. return new Morris.Bar(options);
  1194. }
  1195. Bar.__super__.constructor.call(this, $.extend({}, options, {
  1196. parseTime: false
  1197. }));
  1198. }
  1199. Bar.prototype.init = function() {
  1200. this.cumulative = this.options.stacked;
  1201. if (this.options.hideHover !== 'always') {
  1202. this.hover = new Morris.Hover({
  1203. parent: this.el
  1204. });
  1205. this.on('hovermove', this.onHoverMove);
  1206. this.on('hoverout', this.onHoverOut);
  1207. return this.on('gridclick', this.onGridClick);
  1208. }
  1209. };
  1210. Bar.prototype.defaults = {
  1211. barSizeRatio: 0.75,
  1212. barGap: 3,
  1213. barColors: ['#0b62a4', '#7a92a3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'],
  1214. xLabelMargin: 50
  1215. };
  1216. Bar.prototype.calc = function() {
  1217. var _ref;
  1218. this.calcBars();
  1219. if (this.options.hideHover === false) {
  1220. return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(this.data.length - 1));
  1221. }
  1222. };
  1223. Bar.prototype.calcBars = function() {
  1224. var idx, row, y, _i, _len, _ref, _results;
  1225. _ref = this.data;
  1226. _results = [];
  1227. for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
  1228. row = _ref[idx];
  1229. row._x = this.left + this.width * (idx + 0.5) / this.data.length;
  1230. _results.push(row._y = (function() {
  1231. var _j, _len1, _ref1, _results1;
  1232. _ref1 = row.y;
  1233. _results1 = [];
  1234. for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
  1235. y = _ref1[_j];
  1236. if (y != null) {
  1237. _results1.push(this.transY(y));
  1238. } else {
  1239. _results1.push(null);
  1240. }
  1241. }
  1242. return _results1;
  1243. }).call(this));
  1244. }
  1245. return _results;
  1246. };
  1247. Bar.prototype.draw = function() {
  1248. if (this.options.axes) {
  1249. this.drawXAxis();
  1250. }
  1251. return this.drawSeries();
  1252. };
  1253. Bar.prototype.drawXAxis = function() {
  1254. var i, label, labelBox, margin, offset, prevAngleMargin, prevLabelMargin, row, textBox, ypos, _i, _ref, _results;
  1255. ypos = this.bottom + this.options.padding / 2;
  1256. prevLabelMargin = null;
  1257. prevAngleMargin = null;
  1258. _results = [];
  1259. for (i = _i = 0, _ref = this.data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
  1260. row = this.data[this.data.length - 1 - i];
  1261. label = this.drawXAxisLabel(row._x, ypos, row.label);
  1262. textBox = label.getBBox();
  1263. label.transform("r" + (-this.options.xLabelAngle));
  1264. labelBox = label.getBBox();
  1265. label.transform("t0," + (labelBox.height / 2) + "...");
  1266. if (this.options.xLabelAngle !== 0) {
  1267. offset = -0.5 * textBox.width * Math.cos(this.options.xLabelAngle * Math.PI / 180.0);
  1268. label.transform("t" + offset + ",0...");
  1269. }
  1270. if ((!(prevLabelMargin != null) || prevLabelMargin >= labelBox.x + labelBox.width || (prevAngleMargin != null) && prevAngleMargin >= labelBox.x) && labelBox.x >= 0 && (labelBox.x + labelBox.width) < this.el.width()) {
  1271. if (this.options.xLabelAngle !== 0) {
  1272. margin = 1.25 * this.options.gridTextSize / Math.sin(this.options.xLabelAngle * Math.PI / 180.0);
  1273. prevAngleMargin = labelBox.x - margin;
  1274. }
  1275. _results.push(prevLabelMargin = labelBox.x - this.options.xLabelMargin);
  1276. } else {
  1277. _results.push(label.remove());
  1278. }
  1279. }
  1280. return _results;
  1281. };
  1282. Bar.prototype.drawSeries = function() {
  1283. var barWidth, bottom, groupWidth, idx, lastTop, left, leftPadding, numBars, row, sidx, size, top, ypos, zeroPos;
  1284. groupWidth = this.width / this.options.data.length;
  1285. numBars = this.options.stacked != null ? 1 : this.options.ykeys.length;
  1286. barWidth = (groupWidth * this.options.barSizeRatio - this.options.barGap * (numBars - 1)) / numBars;
  1287. leftPadding = groupWidth * (1 - this.options.barSizeRatio) / 2;
  1288. zeroPos = this.ymin <= 0 && this.ymax >= 0 ? this.transY(0) : null;
  1289. return this.bars = (function() {
  1290. var _i, _len, _ref, _results;
  1291. _ref = this.data;
  1292. _results = [];
  1293. for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
  1294. row = _ref[idx];
  1295. lastTop = 0;
  1296. _results.push((function() {
  1297. var _j, _len1, _ref1, _results1;
  1298. _ref1 = row._y;
  1299. _results1 = [];
  1300. for (sidx = _j = 0, _len1 = _ref1.length; _j < _len1; sidx = ++_j) {
  1301. ypos = _ref1[sidx];
  1302. if (ypos !== null) {
  1303. if (zeroPos) {
  1304. top = Math.min(ypos, zeroPos);
  1305. bottom = Math.max(ypos, zeroPos);
  1306. } else {
  1307. top = ypos;
  1308. bottom = this.bottom;
  1309. }
  1310. left = this.left + idx * groupWidth + leftPadding;
  1311. if (!this.options.stacked) {
  1312. left += sidx * (barWidth + this.options.barGap);
  1313. }
  1314. size = bottom - top;
  1315. if (this.options.stacked) {
  1316. top -= lastTop;
  1317. }
  1318. this.drawBar(left, top, barWidth, size, this.colorFor(row, sidx, 'bar'));
  1319. _results1.push(lastTop += size);
  1320. } else {
  1321. _results1.push(null);
  1322. }
  1323. }
  1324. return _results1;
  1325. }).call(this));
  1326. }
  1327. return _results;
  1328. }).call(this);
  1329. };
  1330. Bar.prototype.colorFor = function(row, sidx, type) {
  1331. var r, s;
  1332. if (typeof this.options.barColors === 'function') {
  1333. r = {
  1334. x: row.x,
  1335. y: row.y[sidx],
  1336. label: row.label
  1337. };
  1338. s = {
  1339. index: sidx,
  1340. key: this.options.ykeys[sidx],
  1341. label: this.options.labels[sidx]
  1342. };
  1343. return this.options.barColors.call(this, r, s, type);
  1344. } else {
  1345. return this.options.barColors[sidx % this.options.barColors.length];
  1346. }
  1347. };
  1348. Bar.prototype.hitTest = function(x, y) {
  1349. if (this.data.length === 0) {
  1350. return null;
  1351. }
  1352. x = Math.max(Math.min(x, this.right), this.left);
  1353. return Math.min(this.data.length - 1, Math.floor((x - this.left) / (this.width / this.data.length)));
  1354. };
  1355. Bar.prototype.onGridClick = function(x, y) {
  1356. var index;
  1357. index = this.hitTest(x, y);
  1358. return this.fire('click', index, this.options.data[index], x, y);
  1359. };
  1360. Bar.prototype.onHoverMove = function(x, y) {
  1361. var index, _ref;
  1362. index = this.hitTest(x, y);
  1363. return (_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index));
  1364. };
  1365. Bar.prototype.onHoverOut = function() {
  1366. if (this.options.hideHover !== false) {
  1367. return this.hover.hide();
  1368. }
  1369. };
  1370. Bar.prototype.hoverContentForRow = function(index) {
  1371. var content, j, row, x, y, _i, _len, _ref;
  1372. row = this.data[index];
  1373. content = "<div class='morris-hover-row-label'>" + row.label + "</div>";
  1374. _ref = row.y;
  1375. for (j = _i = 0, _len = _ref.length; _i < _len; j = ++_i) {
  1376. y = _ref[j];
  1377. content += "<div class='morris-hover-point' style='color: " + (this.colorFor(row, j, 'label')) + "'>\n " + this.options.labels[j] + ":\n " + (this.yLabelFormat(y)) + "\n</div>";
  1378. }
  1379. if (typeof this.options.hoverCallback === 'function') {
  1380. content = this.options.hoverCallback(index, this.options, content);
  1381. }
  1382. x = this.left + (index + 0.5) * this.width / this.data.length;
  1383. return [content, x];
  1384. };
  1385. Bar.prototype.drawXAxisLabel = function(xPos, yPos, text) {
  1386. var label;
  1387. return label = this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor);
  1388. };
  1389. Bar.prototype.drawBar = function(xPos, yPos, width, height, barColor) {
  1390. return this.raphael.rect(xPos, yPos, width, height).attr('fill', barColor).attr('stroke-width', 0);
  1391. };
  1392. return Bar;
  1393. })(Morris.Grid);
  1394. Morris.Donut = (function(_super) {
  1395. __extends(Donut, _super);
  1396. Donut.prototype.defaults = {
  1397. colors: ['#0B62A4', '#3980B5', '#679DC6', '#95BBD7', '#B0CCE1', '#095791', '#095085', '#083E67', '#052C48', '#042135'],
  1398. backgroundColor: '#FFFFFF',
  1399. labelColor: '#000000',
  1400. formatter: Morris.commas
  1401. };
  1402. function Donut(options) {
  1403. this.select = __bind(this.select, this);
  1404. this.click = __bind(this.click, this);
  1405. var row;
  1406. if (!(this instanceof Morris.Donut)) {
  1407. return new Morris.Donut(options);
  1408. }
  1409. if (typeof options.element === 'string') {
  1410. this.el = $(document.getElementById(options.element));
  1411. } else {
  1412. this.el = $(options.element);
  1413. }
  1414. this.options = $.extend({}, this.defaults, options);
  1415. if (this.el === null || this.el.length === 0) {
  1416. throw new Error("Graph placeholder not found.");
  1417. }
  1418. if (options.data === void 0 || options.data.length === 0) {
  1419. return;
  1420. }
  1421. this.data = options.data;
  1422. this.values = (function() {
  1423. var _i, _len, _ref, _results;
  1424. _ref = this.data;
  1425. _results = [];
  1426. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  1427. row = _ref[_i];
  1428. _results.push(parseFloat(row.value));
  1429. }
  1430. return _results;
  1431. }).call(this);
  1432. this.redraw();
  1433. }
  1434. Donut.prototype.redraw = function() {
  1435. var C, cx, cy, i, idx, last, max_value, min, next, seg, total, value, w, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
  1436. this.el.empty();
  1437. this.raphael = new Raphael(this.el[0]);
  1438. cx = this.el.width() / 2;
  1439. cy = this.el.height() / 2;
  1440. w = (Math.min(cx, cy) - 10) / 3;
  1441. total = 0;
  1442. _ref = this.values;
  1443. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  1444. value = _ref[_i];
  1445. total += value;
  1446. }
  1447. min = 5 / (2 * w);
  1448. C = 1.9999 * Math.PI - min * this.data.length;
  1449. last = 0;
  1450. idx = 0;
  1451. this.segments = [];
  1452. _ref1 = this.values;
  1453. for (i = _j = 0, _len1 = _ref1.length; _j < _len1; i = ++_j) {
  1454. value = _ref1[i];
  1455. next = last + min + C * (value / total);
  1456. seg = new Morris.DonutSegment(cx, cy, w * 2, w, last, next, this.options.colors[idx % this.options.colors.length], this.options.backgroundColor, idx, this.raphael);
  1457. seg.render();
  1458. this.segments.push(seg);
  1459. seg.on('hover', this.select);
  1460. seg.on('click', this.click);
  1461. last = next;
  1462. idx += 1;
  1463. }
  1464. this.text1 = this.drawEmptyDonutLabel(cx, cy - 10, this.options.labelColor, 15, 800);
  1465. this.text2 = this.drawEmptyDonutLabel(cx, cy + 10, this.options.labelColor, 14);
  1466. max_value = Math.max.apply(null, (function() {
  1467. var _k, _len2, _ref2, _results;
  1468. _ref2 = this.values;
  1469. _results = [];
  1470. for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
  1471. value = _ref2[_k];
  1472. _results.push(value);
  1473. }
  1474. return _results;
  1475. }).call(this));
  1476. idx = 0;
  1477. _ref2 = this.values;
  1478. _results = [];
  1479. for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
  1480. value = _ref2[_k];
  1481. if (value === max_value) {
  1482. this.select(idx);
  1483. break;
  1484. }
  1485. _results.push(idx += 1);
  1486. }
  1487. return _results;
  1488. };
  1489. Donut.prototype.click = function(idx) {
  1490. return this.fire('click', idx, this.data[idx]);
  1491. };
  1492. Donut.prototype.select = function(idx) {
  1493. var row, s, segment, _i, _len, _ref;
  1494. _ref = this.segments;
  1495. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  1496. s = _ref[_i];
  1497. s.deselect();
  1498. }
  1499. segment = this.segments[idx];
  1500. segment.select();
  1501. row = this.data[idx];
  1502. return this.setLabels(row.label, this.options.formatter(row.value, row));
  1503. };
  1504. Donut.prototype.setLabels = function(label1, label2) {
  1505. var inner, maxHeightBottom, maxHeightTop, maxWidth, text1bbox, text1scale, text2bbox, text2scale;
  1506. inner = (Math.min(this.el.width() / 2, this.el.height() / 2) - 10) * 2 / 3;
  1507. maxWidth = 1.8 * inner;
  1508. maxHeightTop = inner / 2;
  1509. maxHeightBottom = inner / 3;
  1510. this.text1.attr({
  1511. text: label1,
  1512. transform: ''
  1513. });
  1514. text1bbox = this.text1.getBBox();
  1515. text1scale = Math.min(maxWidth / text1bbox.width, maxHeightTop / text1bbox.height);
  1516. this.text1.attr({
  1517. transform: "S" + text1scale + "," + text1scale + "," + (text1bbox.x + text1bbox.width / 2) + "," + (text1bbox.y + text1bbox.height)
  1518. });
  1519. this.text2.attr({
  1520. text: label2,
  1521. transform: ''
  1522. });
  1523. text2bbox = this.text2.getBBox();
  1524. text2scale = Math.min(maxWidth / text2bbox.width, maxHeightBottom / text2bbox.height);
  1525. return this.text2.attr({
  1526. transform: "S" + text2scale + "," + text2scale + "," + (text2bbox.x + text2bbox.width / 2) + "," + text2bbox.y
  1527. });
  1528. };
  1529. Donut.prototype.drawEmptyDonutLabel = function(xPos, yPos, color, fontSize, fontWeight) {
  1530. var text;
  1531. text = this.raphael.text(xPos, yPos, '').attr('font-size', fontSize).attr('fill', color);
  1532. if (fontWeight != null) {
  1533. text.attr('font-weight', fontWeight);
  1534. }
  1535. return text;
  1536. };
  1537. return Donut;
  1538. })(Morris.EventEmitter);
  1539. Morris.DonutSegment = (function(_super) {
  1540. __extends(DonutSegment, _super);
  1541. function DonutSegment(cx, cy, inner, outer, p0, p1, color, backgroundColor, index, raphael) {
  1542. this.cx = cx;
  1543. this.cy = cy;
  1544. this.inner = inner;
  1545. this.outer = outer;
  1546. this.color = color;
  1547. this.backgroundColor = backgroundColor;
  1548. this.index = index;
  1549. this.raphael = raphael;
  1550. this.deselect = __bind(this.deselect, this);
  1551. this.select = __bind(this.select, this);
  1552. this.sin_p0 = Math.sin(p0);
  1553. this.cos_p0 = Math.cos(p0);
  1554. this.sin_p1 = Math.sin(p1);
  1555. this.cos_p1 = Math.cos(p1);
  1556. this.is_long = (p1 - p0) > Math.PI ? 1 : 0;
  1557. this.path = this.calcSegment(this.inner + 3, this.inner + this.outer - 5);
  1558. this.selectedPath = this.calcSegment(this.inner + 3, this.inner + this.outer);
  1559. this.hilight = this.calcArc(this.inner);
  1560. }
  1561. DonutSegment.prototype.calcArcPoints = function(r) {
  1562. return [this.cx + r * this.sin_p0, this.cy + r * this.cos_p0, this.cx + r * this.sin_p1, this.cy + r * this.cos_p1];
  1563. };
  1564. DonutSegment.prototype.calcSegment = function(r1, r2) {
  1565. var ix0, ix1, iy0, iy1, ox0, ox1, oy0, oy1, _ref, _ref1;
  1566. _ref = this.calcArcPoints(r1), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3];
  1567. _ref1 = this.calcArcPoints(r2), ox0 = _ref1[0], oy0 = _ref1[1], ox1 = _ref1[2], oy1 = _ref1[3];
  1568. return ("M" + ix0 + "," + iy0) + ("A" + r1 + "," + r1 + ",0," + this.is_long + ",0," + ix1 + "," + iy1) + ("L" + ox1 + "," + oy1) + ("A" + r2 + "," + r2 + ",0," + this.is_long + ",1," + ox0 + "," + oy0) + "Z";
  1569. };
  1570. DonutSegment.prototype.calcArc = function(r) {
  1571. var ix0, ix1, iy0, iy1, _ref;
  1572. _ref = this.calcArcPoints(r), ix0 = _ref[0], iy0 = _ref[1], ix1 = _ref[2], iy1 = _ref[3];
  1573. return ("M" + ix0 + "," + iy0) + ("A" + r + "," + r + ",0," + this.is_long + ",0," + ix1 + "," + iy1);
  1574. };
  1575. DonutSegment.prototype.render = function() {
  1576. var _this = this;
  1577. this.arc = this.drawDonutArc(this.hilight, this.color);
  1578. return this.seg = this.drawDonutSegment(this.path, this.color, this.backgroundColor, function() {
  1579. return _this.fire('hover', _this.index);
  1580. }, function() {
  1581. return _this.fire('click', _this.index);
  1582. });
  1583. };
  1584. DonutSegment.prototype.drawDonutArc = function(path, color) {
  1585. return this.raphael.path(path).attr({
  1586. stroke: color,
  1587. 'stroke-width': 2,
  1588. opacity: 0
  1589. });
  1590. };
  1591. DonutSegment.prototype.drawDonutSegment = function(path, fillColor, strokeColor, hoverFunction, clickFunction) {
  1592. return this.raphael.path(path).attr({
  1593. fill: fillColor,
  1594. stroke: strokeColor,
  1595. 'stroke-width': 3
  1596. }).hover(hoverFunction).click(clickFunction);
  1597. };
  1598. DonutSegment.prototype.select = function() {
  1599. if (!this.selected) {
  1600. this.seg.animate({
  1601. path: this.selectedPath
  1602. }, 150, '<>');
  1603. this.arc.animate({
  1604. opacity: 1
  1605. }, 150, '<>');
  1606. return this.selected = true;
  1607. }
  1608. };
  1609. DonutSegment.prototype.deselect = function() {
  1610. if (this.selected) {
  1611. this.seg.animate({
  1612. path: this.path
  1613. }, 150, '<>');
  1614. this.arc.animate({
  1615. opacity: 0
  1616. }, 150, '<>');
  1617. return this.selected = false;
  1618. }
  1619. };
  1620. return DonutSegment;
  1621. })(Morris.EventEmitter);
  1622. }).call(this);