mirror of
https://github.com/morrisjs/morris.js.git
synced 2024-11-10 21:36:34 +01:00
Getting there... (for line charts, at least).
This commit is contained in:
parent
7ea84dda7f
commit
5a31deda53
@ -40,10 +40,18 @@ class Morris.Grid extends Morris.EventEmitter
|
||||
@setData @options.data
|
||||
|
||||
# hover
|
||||
unless @options.hideHover is 'always'
|
||||
@hover = new Morris.Hover
|
||||
parent: @el
|
||||
@initHover()
|
||||
@el.bind 'mousemove', (evt) =>
|
||||
offset = @el.offset()
|
||||
@fire 'hover', evt.pageX - offset.left, evt.pageY - offset.top
|
||||
|
||||
@el.bind 'mouseout', (evt) =>
|
||||
@fire 'hoverout'
|
||||
|
||||
@el.bind 'touchstart touchmove touchend', (evt) =>
|
||||
touch = evt.originalEvent.touches[0] or evt.originalEvent.changedTouches[0]
|
||||
offset = @el.offset()
|
||||
@fire 'hover', touch.pageX - offset.left, touch.pageY - offset.top
|
||||
touch
|
||||
|
||||
@postInit() if @postInit
|
||||
|
||||
@ -268,29 +276,7 @@ class Morris.Grid extends Morris.EventEmitter
|
||||
yLabelFormat: (label) ->
|
||||
"#{@options.preUnits}#{Morris.commas(label)}#{@options.postUnits}"
|
||||
|
||||
# Hover stuff
|
||||
#
|
||||
#
|
||||
initHover: ->
|
||||
if @hover?
|
||||
@el.bind 'mousemove', (evt) =>
|
||||
@updateHover evt.pageX, evt.pageY
|
||||
|
||||
if @options.hideHover
|
||||
@el.bind 'mouseout', (evt) =>
|
||||
@hover.hide()
|
||||
|
||||
@el.bind 'touchstart touchmove touchend', (evt) =>
|
||||
touch = evt.originalEvent.touches[0] or evt.originalEvent.changedTouches[0]
|
||||
@updateHover touch.pageX, touch.pageY
|
||||
touch
|
||||
|
||||
hitTest: (x, y) -> null
|
||||
|
||||
updateHover: (x, y) ->
|
||||
offset = @el.offset()
|
||||
x -= offset.left
|
||||
y -= offset.top
|
||||
hit = @hitTest(x, y)
|
||||
if hit?
|
||||
@hover.update(hit...)
|
||||
|
@ -9,8 +9,6 @@ class Morris.Hover
|
||||
@el = $ "<div class='#{@options.class}'></div>"
|
||||
@el.hide()
|
||||
@options.parent.append(@el)
|
||||
@el.bind 'mousemove mouseout touchstart touchmove touchend', (evt) ->
|
||||
evt.stopPropagation()
|
||||
|
||||
update: (html, x, y) ->
|
||||
@html(html)
|
||||
|
@ -10,21 +10,10 @@ class Morris.Line extends Morris.Grid
|
||||
@pointGrow = Raphael.animation r: @options.pointSize + 3, 25, 'linear'
|
||||
@pointShrink = Raphael.animation r: @options.pointSize, 25, 'linear'
|
||||
|
||||
# column hilight events
|
||||
if @options.hilight
|
||||
@prevHilight = null
|
||||
@el.mousemove (evt) =>
|
||||
@updateHilight evt.pageX
|
||||
if @options.hilightAutoHide
|
||||
@el.mouseout (evt) =>
|
||||
@hilight null
|
||||
touchHandler = (evt) =>
|
||||
touch = evt.originalEvent.touches[0] or evt.originalEvent.changedTouches[0]
|
||||
@updateHilight touch.pageX
|
||||
return touch
|
||||
@el.bind 'touchstart', touchHandler
|
||||
@el.bind 'touchmove', touchHandler
|
||||
@el.bind 'touchend', touchHandler
|
||||
if @options.hideHover isnt 'always'
|
||||
@hover = new Morris.Hover(parent: @el)
|
||||
@on('hover', @onHover)
|
||||
@on('hoverout', @onHoverOut)
|
||||
|
||||
# Default configuration
|
||||
#
|
||||
@ -44,11 +33,10 @@ class Morris.Line extends Morris.Grid
|
||||
pointStrokeColors: ['#ffffff']
|
||||
pointFillColors: []
|
||||
smooth: true
|
||||
hilight: true
|
||||
hilightAutoHide: false
|
||||
xLabels: 'auto'
|
||||
xLabelFormat: null
|
||||
continuousLine: true
|
||||
hideHover: false
|
||||
|
||||
# Do any size-related calculations
|
||||
#
|
||||
@ -56,7 +44,6 @@ class Morris.Line extends Morris.Grid
|
||||
calc: ->
|
||||
@calcPoints()
|
||||
@generatePaths()
|
||||
@calcHilightMargins()
|
||||
|
||||
# calculate series data point coordinates
|
||||
#
|
||||
@ -68,25 +55,38 @@ class Morris.Line extends Morris.Grid
|
||||
if y? then @transY(y) else y
|
||||
row._ymax = Math.min.apply(null, [@bottom].concat(y for y in row._y when y?))
|
||||
|
||||
# calculate hilight margins
|
||||
# hit test - returns the index of the row beneath the given coordinate
|
||||
#
|
||||
# @private
|
||||
calcHilightMargins: ->
|
||||
@hilightMargins = ((r._x + @data[i]._x) / 2 for r, i in @data.slice(1))
|
||||
|
||||
# hover element hit test
|
||||
#
|
||||
# @private
|
||||
hitTest: (x, y) ->
|
||||
# TODO better search algo
|
||||
for r, i in @data.slice(1)
|
||||
break if x < (r._x + @data[i]._x) / 2
|
||||
@hoverFor(i)
|
||||
for r, index in @data.slice(1)
|
||||
break if x < (r._x + @data[index]._x) / 2
|
||||
index
|
||||
|
||||
# hover event handler
|
||||
#
|
||||
onHover: (x, y) =>
|
||||
index = @hitTest(x, y)
|
||||
if @options.hideHover isnt 'always'
|
||||
@hover.update(@hoverContentForRow(index)...)
|
||||
@hilight(index)
|
||||
|
||||
onHoverOut: =>
|
||||
if @options.hideHover is 'auto'
|
||||
@displayHoverForIndex(null)
|
||||
|
||||
displayHoverForRow: (index) ->
|
||||
if index?
|
||||
@hover.update(@hoverContentForRow(index)...)
|
||||
@hilight(index)
|
||||
else
|
||||
@hover.hide()
|
||||
@hilight()
|
||||
|
||||
# hover content for a point
|
||||
#
|
||||
# @private
|
||||
hoverFor: (index) ->
|
||||
hoverContentForRow: (index) ->
|
||||
row = @data[index]
|
||||
content = "<div class='morris-hover-row-label'>#{row.label}</div>"
|
||||
for y, j in row.y
|
||||
@ -118,7 +118,8 @@ class Morris.Line extends Morris.Grid
|
||||
draw: ->
|
||||
@drawXAxis()
|
||||
@drawSeries()
|
||||
@hilight(if @options.hilightAutoHide then null else @data.length - 1) if @options.hilight
|
||||
if @options.hideHover is false
|
||||
@displayHoverForRow(@data.length - 1)
|
||||
|
||||
# draw the x-axis labels
|
||||
#
|
||||
@ -236,13 +237,6 @@ class Morris.Line extends Morris.Grid
|
||||
@seriesPoints[i][index].animate @pointGrow
|
||||
@prevHilight = index
|
||||
|
||||
# @private
|
||||
updateHilight: (x) =>
|
||||
x -= @el.offset().left
|
||||
for hilightIndex in [0...@hilightMargins.length]
|
||||
break if @hilightMargins[hilightIndex] > x
|
||||
@hilight hilightIndex
|
||||
|
||||
# @private
|
||||
strokeWidthForSeries: (index) ->
|
||||
@options.pointWidths[index % @options.pointWidths.length]
|
||||
|
160
morris.js
160
morris.js
@ -68,6 +68,7 @@
|
||||
__extends(Grid, _super);
|
||||
|
||||
function Grid(options) {
|
||||
var _this = this;
|
||||
if (typeof options.element === 'string') {
|
||||
this.el = $(document.getElementById(options.element));
|
||||
} else {
|
||||
@ -94,12 +95,21 @@
|
||||
this.init();
|
||||
}
|
||||
this.setData(this.options.data);
|
||||
if (this.options.hideHover !== 'always') {
|
||||
this.hover = new Morris.Hover({
|
||||
parent: this.el
|
||||
});
|
||||
this.initHover();
|
||||
}
|
||||
this.el.bind('mousemove', function(evt) {
|
||||
var offset;
|
||||
offset = _this.el.offset();
|
||||
return _this.fire('hover', evt.pageX - offset.left, evt.pageY - offset.top);
|
||||
});
|
||||
this.el.bind('mouseout', function(evt) {
|
||||
return _this.fire('hoverout');
|
||||
});
|
||||
this.el.bind('touchstart touchmove touchend', function(evt) {
|
||||
var offset, touch;
|
||||
touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];
|
||||
offset = _this.el.offset();
|
||||
_this.fire('hover', touch.pageX - offset.left, touch.pageY - offset.top);
|
||||
return touch;
|
||||
});
|
||||
if (this.postInit) {
|
||||
this.postInit();
|
||||
}
|
||||
@ -372,35 +382,8 @@
|
||||
return "" + this.options.preUnits + (Morris.commas(label)) + this.options.postUnits;
|
||||
};
|
||||
|
||||
Grid.prototype.initHover = function() {
|
||||
var _this = this;
|
||||
if (this.hover != null) {
|
||||
this.el.bind('mousemove', function(evt) {
|
||||
return _this.updateHover(evt.pageX, evt.pageY);
|
||||
});
|
||||
if (this.options.hideHover) {
|
||||
this.el.bind('mouseout', function(evt) {
|
||||
return _this.hover.hide();
|
||||
});
|
||||
}
|
||||
return this.el.bind('touchstart touchmove touchend', function(evt) {
|
||||
var touch;
|
||||
touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];
|
||||
_this.updateHover(touch.pageX, touch.pageY);
|
||||
return touch;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Grid.prototype.hitTest = function(x, y) {
|
||||
return null;
|
||||
};
|
||||
|
||||
Grid.prototype.updateHover = function(x, y) {
|
||||
var hit, offset, _ref;
|
||||
offset = this.el.offset();
|
||||
x -= offset.left;
|
||||
y -= offset.top;
|
||||
var hit, _ref;
|
||||
hit = this.hitTest(x, y);
|
||||
if (hit != null) {
|
||||
return (_ref = this.hover).update.apply(_ref, hit);
|
||||
@ -482,9 +465,6 @@
|
||||
this.el = $("<div class='" + this.options["class"] + "'></div>");
|
||||
this.el.hide();
|
||||
this.options.parent.append(this.el);
|
||||
this.el.bind('mousemove mouseout touchstart touchmove touchend', function(evt) {
|
||||
return evt.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
Hover.prototype.update = function(html, x, y) {
|
||||
@ -538,9 +518,11 @@
|
||||
__extends(Line, _super);
|
||||
|
||||
function Line(options) {
|
||||
this.updateHilight = __bind(this.updateHilight, this);
|
||||
|
||||
this.hilight = __bind(this.hilight, this);
|
||||
|
||||
this.onHoverOut = __bind(this.onHoverOut, this);
|
||||
|
||||
this.onHover = __bind(this.onHover, this);
|
||||
if (!(this instanceof Morris.Line)) {
|
||||
return new Morris.Line(options);
|
||||
}
|
||||
@ -548,33 +530,18 @@
|
||||
}
|
||||
|
||||
Line.prototype.init = function() {
|
||||
var touchHandler,
|
||||
_this = this;
|
||||
this.pointGrow = Raphael.animation({
|
||||
r: this.options.pointSize + 3
|
||||
}, 25, 'linear');
|
||||
this.pointShrink = Raphael.animation({
|
||||
r: this.options.pointSize
|
||||
}, 25, 'linear');
|
||||
if (this.options.hilight) {
|
||||
this.prevHilight = null;
|
||||
this.el.mousemove(function(evt) {
|
||||
return _this.updateHilight(evt.pageX);
|
||||
if (this.options.hideHover !== 'always') {
|
||||
this.hover = new Morris.Hover({
|
||||
parent: this.el
|
||||
});
|
||||
if (this.options.hilightAutoHide) {
|
||||
this.el.mouseout(function(evt) {
|
||||
return _this.hilight(null);
|
||||
});
|
||||
}
|
||||
touchHandler = function(evt) {
|
||||
var touch;
|
||||
touch = evt.originalEvent.touches[0] || evt.originalEvent.changedTouches[0];
|
||||
_this.updateHilight(touch.pageX);
|
||||
return touch;
|
||||
};
|
||||
this.el.bind('touchstart', touchHandler);
|
||||
this.el.bind('touchmove', touchHandler);
|
||||
return this.el.bind('touchend', touchHandler);
|
||||
this.on('hover', this.onHover);
|
||||
return this.on('hoverout', this.onHoverOut);
|
||||
}
|
||||
};
|
||||
|
||||
@ -586,17 +553,15 @@
|
||||
pointStrokeColors: ['#ffffff'],
|
||||
pointFillColors: [],
|
||||
smooth: true,
|
||||
hilight: true,
|
||||
hilightAutoHide: false,
|
||||
xLabels: 'auto',
|
||||
xLabelFormat: null,
|
||||
continuousLine: true
|
||||
continuousLine: true,
|
||||
hideHover: false
|
||||
};
|
||||
|
||||
Line.prototype.calc = function() {
|
||||
this.calcPoints();
|
||||
this.generatePaths();
|
||||
return this.calcHilightMargins();
|
||||
return this.generatePaths();
|
||||
};
|
||||
|
||||
Line.prototype.calcPoints = function() {
|
||||
@ -636,33 +601,45 @@
|
||||
return _results;
|
||||
};
|
||||
|
||||
Line.prototype.calcHilightMargins = function() {
|
||||
var i, r;
|
||||
return this.hilightMargins = (function() {
|
||||
var _i, _len, _ref, _results;
|
||||
_ref = this.data.slice(1);
|
||||
_results = [];
|
||||
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
|
||||
r = _ref[i];
|
||||
_results.push((r._x + this.data[i]._x) / 2);
|
||||
}
|
||||
return _results;
|
||||
}).call(this);
|
||||
};
|
||||
|
||||
Line.prototype.hitTest = function(x, y) {
|
||||
var i, r, _i, _len, _ref;
|
||||
var index, r, _i, _len, _ref;
|
||||
_ref = this.data.slice(1);
|
||||
for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) {
|
||||
r = _ref[i];
|
||||
if (x < (r._x + this.data[i]._x) / 2) {
|
||||
for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
|
||||
r = _ref[index];
|
||||
if (x < (r._x + this.data[index]._x) / 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this.hoverFor(i);
|
||||
return index;
|
||||
};
|
||||
|
||||
Line.prototype.hoverFor = function(index) {
|
||||
Line.prototype.onHover = function(x, y) {
|
||||
var index, _ref;
|
||||
index = this.hitTest(x, y);
|
||||
if (this.options.hideHover !== 'always') {
|
||||
(_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index));
|
||||
return this.hilight(index);
|
||||
}
|
||||
};
|
||||
|
||||
Line.prototype.onHoverOut = function() {
|
||||
if (this.options.hideHover === 'auto') {
|
||||
return this.displayHoverForIndex(null);
|
||||
}
|
||||
};
|
||||
|
||||
Line.prototype.displayHoverForRow = function(index) {
|
||||
var _ref;
|
||||
if (index != null) {
|
||||
(_ref = this.hover).update.apply(_ref, this.hoverContentForRow(index));
|
||||
return this.hilight(index);
|
||||
} else {
|
||||
this.hover.hide();
|
||||
return this.hilight();
|
||||
}
|
||||
};
|
||||
|
||||
Line.prototype.hoverContentForRow = function(index) {
|
||||
var content, j, row, y, _i, _len, _ref;
|
||||
row = this.data[index];
|
||||
content = "<div class='morris-hover-row-label'>" + row.label + "</div>";
|
||||
@ -722,8 +699,8 @@
|
||||
Line.prototype.draw = function() {
|
||||
this.drawXAxis();
|
||||
this.drawSeries();
|
||||
if (this.options.hilight) {
|
||||
return this.hilight(this.options.hilightAutoHide ? null : this.data.length - 1);
|
||||
if (this.options.hideHover === false) {
|
||||
return this.displayHoverForRow(this.data.length - 1);
|
||||
}
|
||||
};
|
||||
|
||||
@ -893,17 +870,6 @@
|
||||
return this.prevHilight = index;
|
||||
};
|
||||
|
||||
Line.prototype.updateHilight = function(x) {
|
||||
var hilightIndex, _i, _ref;
|
||||
x -= this.el.offset().left;
|
||||
for (hilightIndex = _i = 0, _ref = this.hilightMargins.length; 0 <= _ref ? _i < _ref : _i > _ref; hilightIndex = 0 <= _ref ? ++_i : --_i) {
|
||||
if (this.hilightMargins[hilightIndex] > x) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this.hilight(hilightIndex);
|
||||
};
|
||||
|
||||
Line.prototype.strokeWidthForSeries = function(index) {
|
||||
return this.options.pointWidths[index % this.options.pointWidths.length];
|
||||
};
|
||||
|
2
morris.min.js
vendored
2
morris.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user