Automatic resizing.

Fixes #111. It's a costly operation, but it's working.
This commit is contained in:
Olly Smith 2013-11-09 19:33:36 +00:00
parent 6e5d68fc99
commit 88e3fe6211
5 changed files with 137 additions and 34 deletions

42
examples/resize.html Normal file
View file

@ -0,0 +1,42 @@
<!doctype html>
<head>
<script src="../third_party/jquery-1.8.2.min.js"></script>
<script src="../third_party/raphael-2.1.0.min.js"></script>
<script src="../morris.js"></script>
<script src="lib/prettify.js"></script>
<script src="lib/example.js"></script>
<link rel="stylesheet" href="lib/example.css">
<link rel="stylesheet" href="lib/prettify.css">
<link rel="stylesheet" href="../morris.css">
<style>
body { width: 100%; }
#graph { width: 100%; }
</style>
</head>
<body>
<h1>Formatting Dates YYYY-MM-DD</h1>
<div id="graph"></div>
<pre id="code" class="prettyprint linenums">
/* data stolen from http://howmanyleft.co.uk/vehicle/jaguar_'e'_type */
var day_data = [
{"period": "2012-10-01", "licensed": 3407, "sorned": 660},
{"period": "2012-09-30", "licensed": 3351, "sorned": 629},
{"period": "2012-09-29", "licensed": 3269, "sorned": 618},
{"period": "2012-09-20", "licensed": 3246, "sorned": 661},
{"period": "2012-09-19", "licensed": 3257, "sorned": 667},
{"period": "2012-09-18", "licensed": 3248, "sorned": 627},
{"period": "2012-09-17", "licensed": 3171, "sorned": 660},
{"period": "2012-09-16", "licensed": 3171, "sorned": 676},
{"period": "2012-09-15", "licensed": 3201, "sorned": 656},
{"period": "2012-09-10", "licensed": 3215, "sorned": 622}
];
Morris.Line({
element: 'graph',
data: day_data,
xkey: 'period',
ykeys: ['licensed', 'sorned'],
labels: ['Licensed', 'SORN'],
resize: true
});
</pre>
</body>

View file

@ -25,6 +25,7 @@ class Morris.Donut extends Morris.EventEmitter
backgroundColor: '#FFFFFF', backgroundColor: '#FFFFFF',
labelColor: '#000000', labelColor: '#000000',
formatter: Morris.commas formatter: Morris.commas
resize: false
# Create and render a donut chart. # Create and render a donut chart.
# #
@ -46,16 +47,19 @@ class Morris.Donut extends Morris.EventEmitter
@data = options.data @data = options.data
@values = (parseFloat(row.value) for row in @data) @values = (parseFloat(row.value) for row in @data)
@raphael = new Raphael(@el[0])
if @options.resize
$(window).bind 'resize', (evt) =>
if @timeoutId?
window.clearTimeout @timeoutId
@timeoutId = window.setTimeout @resizeHandler, 100
@redraw() @redraw()
# Clear and redraw the chart. # Clear and redraw the chart.
#
# If you need to re-size your charts, call this method after changing the
# size of the container element.
redraw: -> redraw: ->
@el.empty() @raphael.clear()
@raphael = new Raphael(@el[0])
cx = @el.width() / 2 cx = @el.width() / 2
cy = @el.height() / 2 cy = @el.height() / 2
@ -128,6 +132,11 @@ class Morris.Donut extends Morris.EventEmitter
text.attr('font-weight', fontWeight) if fontWeight? text.attr('font-weight', fontWeight) if fontWeight?
return text return text
resizeHandler: =>
@timeoutId = null
@raphael.setSize @el.width(), @el.height()
@redraw()
# A segment within a donut chart. # A segment within a donut chart.
# #

View file

@ -81,6 +81,12 @@ class Morris.Grid extends Morris.EventEmitter
@endRange evt.pageX - offset.left @endRange evt.pageX - offset.left
@fire 'hovermove', evt.pageX - offset.left, evt.pageY - offset.top @fire 'hovermove', evt.pageX - offset.left, evt.pageY - offset.top
if @options.resize
$(window).bind 'resize', (evt) =>
if @timeoutId?
window.clearTimeout @timeoutId
@timeoutId = window.setTimeout @resizeHandler, 100
@postInit() if @postInit @postInit() if @postInit
# Default options # Default options
@ -123,6 +129,7 @@ class Morris.Grid extends Morris.EventEmitter
] ]
rangeSelect: null rangeSelect: null
rangeSelectColor: '#eef' rangeSelectColor: '#eef'
resize: false
# Update the data series and redraw the chart. # Update the data series and redraw the chart.
# #
@ -396,6 +403,11 @@ class Morris.Grid extends Morris.EventEmitter
end: @data[@hitTest(end)].x end: @data[@hitTest(end)].x
@selectFrom = null @selectFrom = null
resizeHandler: =>
@timeoutId = null
@raphael.setSize @el.width(), @el.height()
@redraw()
# Parse a date into a javascript timestamp # Parse a date into a javascript timestamp
# #
# #

View file

@ -1,9 +1,9 @@
(function() { (function() {
var $, Morris, minutesSpecHelper, secondsSpecHelper, var $, Morris, minutesSpecHelper, secondsSpecHelper,
__slice = [].slice, __slice = [].slice,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty, __hasProp = {}.hasOwnProperty,
__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; }, __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; },
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__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; }; __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; };
Morris = window.Morris = {}; Morris = window.Morris = {};
@ -67,6 +67,7 @@
__extends(Grid, _super); __extends(Grid, _super);
function Grid(options) { function Grid(options) {
this.resizeHandler = __bind(this.resizeHandler, this);
var _this = this; var _this = this;
if (typeof options.element === 'string') { if (typeof options.element === 'string') {
this.el = $(document.getElementById(options.element)); this.el = $(document.getElementById(options.element));
@ -144,6 +145,14 @@
return _this.fire('hovermove', evt.pageX - offset.left, evt.pageY - offset.top); return _this.fire('hovermove', evt.pageX - offset.left, evt.pageY - offset.top);
}); });
} }
if (this.options.resize) {
$(window).bind('resize', function(evt) {
if (_this.timeoutId != null) {
window.clearTimeout(_this.timeoutId);
}
return _this.timeoutId = window.setTimeout(_this.resizeHandler, 100);
});
}
if (this.postInit) { if (this.postInit) {
this.postInit(); this.postInit();
} }
@ -176,7 +185,8 @@
eventStrokeWidth: 1.0, eventStrokeWidth: 1.0,
eventLineColors: ['#005a04', '#ccffbb', '#3a5f0b', '#005502'], eventLineColors: ['#005a04', '#ccffbb', '#3a5f0b', '#005502'],
rangeSelect: null, rangeSelect: null,
rangeSelectColor: '#eef' rangeSelectColor: '#eef',
resize: false
}; };
Grid.prototype.setData = function(data, redraw) { Grid.prototype.setData = function(data, redraw) {
@ -196,8 +206,8 @@
ymax = this.cumulative ? 0 : null; ymax = this.cumulative ? 0 : null;
ymin = this.cumulative ? 0 : null; ymin = this.cumulative ? 0 : null;
if (this.options.goals.length > 0) { if (this.options.goals.length > 0) {
minGoal = Math.min.apply(null, this.options.goals); minGoal = Math.min.apply(Math, this.options.goals);
maxGoal = Math.max.apply(null, this.options.goals); maxGoal = Math.max.apply(Math, this.options.goals);
ymin = ymin != null ? Math.min(ymin, minGoal) : minGoal; ymin = ymin != null ? Math.min(ymin, minGoal) : minGoal;
ymax = ymax != null ? Math.max(ymax, maxGoal) : maxGoal; ymax = ymax != null ? Math.max(ymax, maxGoal) : maxGoal;
} }
@ -282,8 +292,8 @@
} else { } else {
this.events = this.options.events; this.events = this.options.events;
} }
this.xmax = Math.max(this.xmax, Math.max.apply(null, this.events)); this.xmax = Math.max(this.xmax, Math.max.apply(Math, this.events));
this.xmin = Math.min(this.xmin, Math.min.apply(null, this.events)); this.xmin = Math.min(this.xmin, Math.min.apply(Math, this.events));
} }
if (this.xmin === this.xmax) { if (this.xmin === this.xmax) {
this.xmin -= 1; this.xmin -= 1;
@ -561,6 +571,12 @@
} }
}; };
Grid.prototype.resizeHandler = function() {
this.timeoutId = null;
this.raphael.setSize(this.el.width(), this.el.height());
return this.redraw();
};
return Grid; return Grid;
})(Morris.EventEmitter); })(Morris.EventEmitter);
@ -749,7 +765,7 @@
} }
return _results1; return _results1;
}).call(this); }).call(this);
_results.push(row._ymax = Math.min.apply(null, [this.bottom].concat((function() { _results.push(row._ymax = Math.min.apply(Math, [this.bottom].concat((function() {
var _j, _len1, _ref1, _results1; var _j, _len1, _ref1, _results1;
_ref1 = row._y; _ref1 = row._y;
_results1 = []; _results1 = [];
@ -1392,6 +1408,8 @@
barSizeRatio: 0.75, barSizeRatio: 0.75,
barGap: 3, barGap: 3,
barColors: ['#0b62a4', '#7a92a3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'], barColors: ['#0b62a4', '#7a92a3', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'],
barOpacity: 1.0,
barRadius: [0, 0, 0, 0],
xLabelMargin: 50 xLabelMargin: 50
}; };
@ -1438,7 +1456,7 @@
Bar.prototype.drawXAxis = function() { Bar.prototype.drawXAxis = function() {
var i, label, labelBox, margin, offset, prevAngleMargin, prevLabelMargin, row, textBox, ypos, _i, _ref, _results; var i, label, labelBox, margin, offset, prevAngleMargin, prevLabelMargin, row, textBox, ypos, _i, _ref, _results;
ypos = this.bottom + this.options.padding / 2; ypos = this.bottom + (this.options.xAxisLabelTopPadding || this.options.padding / 2);
prevLabelMargin = null; prevLabelMargin = null;
prevAngleMargin = null; prevAngleMargin = null;
_results = []; _results = [];
@ -1502,7 +1520,7 @@
if (this.options.stacked) { if (this.options.stacked) {
top -= lastTop; top -= lastTop;
} }
this.drawBar(left, top, barWidth, size, this.colorFor(row, sidx, 'bar')); this.drawBar(left, top, barWidth, size, this.colorFor(row, sidx, 'bar'), this.options.barOpacity, this.options.barRadius);
_results1.push(lastTop += size); _results1.push(lastTop += size);
} else { } else {
_results1.push(null); _results1.push(null);
@ -1581,8 +1599,22 @@
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); 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);
}; };
Bar.prototype.drawBar = function(xPos, yPos, width, height, barColor) { Bar.prototype.drawBar = function(xPos, yPos, width, height, barColor, opacity, radiusArray) {
return this.raphael.rect(xPos, yPos, width, height).attr('fill', barColor).attr('stroke-width', 0); var maxRadius, path;
maxRadius = Math.max.apply(Math, radiusArray);
if (maxRadius === 0 || maxRadius > height) {
path = this.raphael.rect(xPos, yPos, width, height);
} else {
path = this.raphael.path(this.roundedRect(xPos, yPos, width, height, radiusArray));
}
return path.attr('fill', barColor).attr('stroke-width', 0).attr('fill-opacity', opacity);
};
Bar.prototype.roundedRect = function(x, y, w, h, r) {
if (r == null) {
r = [0, 0, 0, 0];
}
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"];
}; };
return Bar; return Bar;
@ -1596,22 +1628,25 @@
colors: ['#0B62A4', '#3980B5', '#679DC6', '#95BBD7', '#B0CCE1', '#095791', '#095085', '#083E67', '#052C48', '#042135'], colors: ['#0B62A4', '#3980B5', '#679DC6', '#95BBD7', '#B0CCE1', '#095791', '#095085', '#083E67', '#052C48', '#042135'],
backgroundColor: '#FFFFFF', backgroundColor: '#FFFFFF',
labelColor: '#000000', labelColor: '#000000',
formatter: Morris.commas formatter: Morris.commas,
resize: false
}; };
function Donut(options) { function Donut(options) {
this.resizeHandler = __bind(this.resizeHandler, this);
this.select = __bind(this.select, this); this.select = __bind(this.select, this);
this.click = __bind(this.click, this); this.click = __bind(this.click, this);
var row; var row,
_this = this;
if (!(this instanceof Morris.Donut)) { if (!(this instanceof Morris.Donut)) {
return new Morris.Donut(options); return new Morris.Donut(options);
} }
this.options = $.extend({}, this.defaults, options);
if (typeof options.element === 'string') { if (typeof options.element === 'string') {
this.el = $(document.getElementById(options.element)); this.el = $(document.getElementById(options.element));
} else { } else {
this.el = $(options.element); this.el = $(options.element);
} }
this.options = $.extend({}, this.defaults, options);
if (this.el === null || this.el.length === 0) { if (this.el === null || this.el.length === 0) {
throw new Error("Graph placeholder not found."); throw new Error("Graph placeholder not found.");
} }
@ -1629,13 +1664,21 @@
} }
return _results; return _results;
}).call(this); }).call(this);
this.raphael = new Raphael(this.el[0]);
if (this.options.resize) {
$(window).bind('resize', function(evt) {
if (_this.timeoutId != null) {
window.clearTimeout(_this.timeoutId);
}
return _this.timeoutId = window.setTimeout(_this.resizeHandler, 100);
});
}
this.redraw(); this.redraw();
} }
Donut.prototype.redraw = function() { Donut.prototype.redraw = function() {
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; 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;
this.el.empty(); this.raphael.clear();
this.raphael = new Raphael(this.el[0]);
cx = this.el.width() / 2; cx = this.el.width() / 2;
cy = this.el.height() / 2; cy = this.el.height() / 2;
w = (Math.min(cx, cy) - 10) / 3; w = (Math.min(cx, cy) - 10) / 3;
@ -1664,16 +1707,7 @@
} }
this.text1 = this.drawEmptyDonutLabel(cx, cy - 10, this.options.labelColor, 15, 800); this.text1 = this.drawEmptyDonutLabel(cx, cy - 10, this.options.labelColor, 15, 800);
this.text2 = this.drawEmptyDonutLabel(cx, cy + 10, this.options.labelColor, 14); this.text2 = this.drawEmptyDonutLabel(cx, cy + 10, this.options.labelColor, 14);
max_value = Math.max.apply(null, (function() { max_value = Math.max.apply(Math, this.values);
var _k, _len2, _ref2, _results;
_ref2 = this.values;
_results = [];
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
value = _ref2[_k];
_results.push(value);
}
return _results;
}).call(this));
idx = 0; idx = 0;
_ref2 = this.values; _ref2 = this.values;
_results = []; _results = [];
@ -1740,6 +1774,12 @@
return text; return text;
}; };
Donut.prototype.resizeHandler = function() {
this.timeoutId = null;
this.raphael.setSize(this.el.width(), this.el.height());
return this.redraw();
};
return Donut; return Donut;
})(Morris.EventEmitter); })(Morris.EventEmitter);

4
morris.min.js vendored

File diff suppressed because one or more lines are too long