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