From 7d46e6e90329c02125aaca22ab668388b2175267 Mon Sep 17 00:00:00 2001 From: Omar Khan Date: Mon, 17 Jun 2013 18:46:40 +0100 Subject: [PATCH] Add range selection to Morris.Grid --- lib/morris.bar.coffee | 8 +++---- lib/morris.grid.coffee | 48 +++++++++++++++++++++++++++++++++++++++++- lib/morris.line.coffee | 8 +++---- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/lib/morris.bar.coffee b/lib/morris.bar.coffee index e6a7e18..210c62b 100644 --- a/lib/morris.bar.coffee +++ b/lib/morris.bar.coffee @@ -127,9 +127,9 @@ class Morris.Bar extends Morris.Grid else @options.barColors[sidx % @options.barColors.length] - # hit test - returns the index of the row beneath the given coordinate + # hit test - returns the index of the row at the given x-coordinate # - hitTest: (x, y) -> + hitTest: (x) -> return null if @data.length == 0 x = Math.max(Math.min(x, @right), @left) Math.min(@data.length - 1, @@ -139,14 +139,14 @@ class Morris.Bar extends Morris.Grid # # @private onGridClick: (x, y) => - index = @hitTest(x, y) + index = @hitTest(x) @fire 'click', index, @options.data[index], x, y # hover movement event handler # # @private onHoverMove: (x, y) => - index = @hitTest(x, y) + index = @hitTest(x) @hover.update(@hoverContentForRow(index)...) # hover out event handler diff --git a/lib/morris.grid.coffee b/lib/morris.grid.coffee index 4765cff..e4fef92 100644 --- a/lib/morris.grid.coffee +++ b/lib/morris.grid.coffee @@ -29,6 +29,9 @@ class Morris.Grid extends Morris.EventEmitter @elementHeight = null @dirty = false + # range selection + @selectFrom = null + # more stuff @init() if @init @@ -38,9 +41,19 @@ class Morris.Grid extends Morris.EventEmitter # hover @el.bind 'mousemove', (evt) => offset = @el.offset() - @fire 'hovermove', evt.pageX - offset.left, evt.pageY - offset.top + x = evt.pageX - offset.left + if @selectFrom + left = @data[@hitTest(Math.min(x, @selectFrom))]._x + right = @data[@hitTest(Math.max(x, @selectFrom))]._x + width = right - left + @selectionRect.attr({ x: left, width: width }) + else + @fire 'hovermove', x, evt.pageY - offset.top @el.bind 'mouseleave', (evt) => + if @selectFrom + @selectionRect.hide() + @selectFrom = null @fire 'hoverout' @el.bind 'touchstart touchmove touchend', (evt) => @@ -53,6 +66,21 @@ class Morris.Grid extends Morris.EventEmitter offset = @el.offset() @fire 'gridclick', evt.pageX - offset.left, evt.pageY - offset.top + if @options.rangeSelect + @selectionRect = @raphael.rect(0, 0, 0, @el.innerHeight()) + .attr({ fill: @options.rangeSelectColor, stroke: false }) + .toBack() + .hide() + + @el.bind 'mousedown', (evt) => + offset = @el.offset() + @startRange evt.pageX - offset.left + + @el.bind 'mouseup', (evt) => + offset = @el.offset() + @endRange evt.pageX - offset.left + @fire 'hovermove', evt.pageX - offset.left, evt.pageY - offset.top + @postInit() if @postInit # Default options @@ -93,6 +121,8 @@ class Morris.Grid extends Morris.EventEmitter '#3a5f0b' '#005502' ] + rangeSelect: null + rangeSelectColor: '#eef' # Update the data series and redraw the chart. # @@ -346,6 +376,22 @@ class Morris.Grid extends Morris.EventEmitter .attr('stroke', @options.gridLineColor) .attr('stroke-width', @options.gridStrokeWidth) + # Range selection + # + startRange: (x) -> + @hover.hide() + @selectFrom = x + @selectionRect.attr({ x: x, width: 0 }).show() + + endRange: (x) -> + if @selectFrom + start = Math.min(@selectFrom, x) + end = Math.max(@selectFrom, x) + @options.rangeSelect.call @el, + start: @data[@hitTest(start)].x + end: @data[@hitTest(end)].x + @selectFrom = null + # Parse a date into a javascript timestamp # # diff --git a/lib/morris.line.coffee b/lib/morris.line.coffee index 36ef457..133d009 100644 --- a/lib/morris.line.coffee +++ b/lib/morris.line.coffee @@ -57,9 +57,9 @@ 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?)) - # hit test - returns the index of the row beneath the given coordinate + # hit test - returns the index of the row at the given x-coordinate # - hitTest: (x, y) -> + hitTest: (x) -> return null if @data.length == 0 # TODO better search algo for r, index in @data.slice(1) @@ -70,14 +70,14 @@ class Morris.Line extends Morris.Grid # # @private onGridClick: (x, y) => - index = @hitTest(x, y) + index = @hitTest(x) @fire 'click', index, @options.data[index], x, y # hover movement event handler # # @private onHoverMove: (x, y) => - index = @hitTest(x, y) + index = @hitTest(x) @displayHoverForRow(index) # hover out event handler