diff options
Diffstat (limited to 'public/bower_components/morris.js/lib/morris.bar.coffee')
-rw-r--r-- | public/bower_components/morris.js/lib/morris.bar.coffee | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/public/bower_components/morris.js/lib/morris.bar.coffee b/public/bower_components/morris.js/lib/morris.bar.coffee new file mode 100644 index 0000000..86fb32b --- /dev/null +++ b/public/bower_components/morris.js/lib/morris.bar.coffee @@ -0,0 +1,208 @@ +class Morris.Bar extends Morris.Grid + constructor: (options) -> + return new Morris.Bar(options) unless (@ instanceof Morris.Bar) + super($.extend {}, options, parseTime: false) + + init: -> + @cumulative = @options.stacked + + if @options.hideHover isnt 'always' + @hover = new Morris.Hover(parent: @el) + @on('hovermove', @onHoverMove) + @on('hoverout', @onHoverOut) + @on('gridclick', @onGridClick) + + # Default configuration + # + defaults: + barSizeRatio: 0.75 + barGap: 3 + barColors: [ + '#0b62a4' + '#7a92a3' + '#4da74d' + '#afd8f8' + '#edc240' + '#cb4b4b' + '#9440ed' + ], + barOpacity: 1.0 + barRadius: [0, 0, 0, 0] + xLabelMargin: 50 + + # Do any size-related calculations + # + # @private + calc: -> + @calcBars() + if @options.hideHover is false + @hover.update(@hoverContentForRow(@data.length - 1)...) + + # calculate series data bars coordinates and sizes + # + # @private + calcBars: -> + for row, idx in @data + row._x = @left + @width * (idx + 0.5) / @data.length + row._y = for y in row.y + if y? then @transY(y) else null + + # Draws the bar chart. + # + draw: -> + @drawXAxis() if @options.axes in [true, 'both', 'x'] + @drawSeries() + + # draw the x-axis labels + # + # @private + drawXAxis: -> + # draw x axis labels + ypos = @bottom + (@options.xAxisLabelTopPadding || @options.padding / 2) + prevLabelMargin = null + prevAngleMargin = null + for i in [0...@data.length] + row = @data[@data.length - 1 - i] + label = @drawXAxisLabel(row._x, ypos, row.label) + textBox = label.getBBox() + label.transform("r#{-@options.xLabelAngle}") + labelBox = label.getBBox() + label.transform("t0,#{labelBox.height / 2}...") + if @options.xLabelAngle != 0 + offset = -0.5 * textBox.width * + Math.cos(@options.xLabelAngle * Math.PI / 180.0) + label.transform("t#{offset},0...") + # try to avoid overlaps + if (not prevLabelMargin? or + prevLabelMargin >= labelBox.x + labelBox.width or + prevAngleMargin? and prevAngleMargin >= labelBox.x) and + labelBox.x >= 0 and (labelBox.x + labelBox.width) < @el.width() + if @options.xLabelAngle != 0 + margin = 1.25 * @options.gridTextSize / + Math.sin(@options.xLabelAngle * Math.PI / 180.0) + prevAngleMargin = labelBox.x - margin + prevLabelMargin = labelBox.x - @options.xLabelMargin + else + label.remove() + + # draw the data series + # + # @private + drawSeries: -> + groupWidth = @width / @options.data.length + numBars = if @options.stacked then 1 else @options.ykeys.length + barWidth = (groupWidth * @options.barSizeRatio - @options.barGap * (numBars - 1)) / numBars + barWidth = Math.min(barWidth, @options.barSize) if @options.barSize + spaceLeft = groupWidth - barWidth * numBars - @options.barGap * (numBars - 1) + leftPadding = spaceLeft / 2 + zeroPos = if @ymin <= 0 and @ymax >= 0 then @transY(0) else null + @bars = for row, idx in @data + lastTop = 0 + for ypos, sidx in row._y + if ypos != null + if zeroPos + top = Math.min(ypos, zeroPos) + bottom = Math.max(ypos, zeroPos) + else + top = ypos + bottom = @bottom + + left = @left + idx * groupWidth + leftPadding + left += sidx * (barWidth + @options.barGap) unless @options.stacked + size = bottom - top + + if @options.verticalGridCondition and @options.verticalGridCondition(row.x) + @drawBar(@left + idx * groupWidth, @top, groupWidth, Math.abs(@top - @bottom), @options.verticalGridColor, @options.verticalGridOpacity, @options.barRadius) + + top -= lastTop if @options.stacked + @drawBar(left, top, barWidth, size, @colorFor(row, sidx, 'bar'), + @options.barOpacity, @options.barRadius) + + lastTop += size + else + null + + # @private + # + # @param row [Object] row data + # @param sidx [Number] series index + # @param type [String] "bar", "hover" or "label" + colorFor: (row, sidx, type) -> + if typeof @options.barColors is 'function' + r = { x: row.x, y: row.y[sidx], label: row.label } + s = { index: sidx, key: @options.ykeys[sidx], label: @options.labels[sidx] } + @options.barColors.call(@, r, s, type) + else + @options.barColors[sidx % @options.barColors.length] + + # hit test - returns the index of the row at the given x-coordinate + # + hitTest: (x) -> + return null if @data.length == 0 + x = Math.max(Math.min(x, @right), @left) + Math.min(@data.length - 1, + Math.floor((x - @left) / (@width / @data.length))) + + # click on grid event handler + # + # @private + onGridClick: (x, y) => + index = @hitTest(x) + @fire 'click', index, @data[index].src, x, y + + # hover movement event handler + # + # @private + onHoverMove: (x, y) => + index = @hitTest(x) + @hover.update(@hoverContentForRow(index)...) + + # hover out event handler + # + # @private + onHoverOut: => + if @options.hideHover isnt false + @hover.hide() + + # hover content for a point + # + # @private + hoverContentForRow: (index) -> + row = @data[index] + content = "<div class='morris-hover-row-label'>#{row.label}</div>" + for y, j in row.y + content += """ + <div class='morris-hover-point' style='color: #{@colorFor(row, j, 'label')}'> + #{@options.labels[j]}: + #{@yLabelFormat(y)} + </div> + """ + if typeof @options.hoverCallback is 'function' + content = @options.hoverCallback(index, @options, content, row.src) + x = @left + (index + 0.5) * @width / @data.length + [content, x] + + drawXAxisLabel: (xPos, yPos, text) -> + label = @raphael.text(xPos, yPos, text) + .attr('font-size', @options.gridTextSize) + .attr('font-family', @options.gridTextFamily) + .attr('font-weight', @options.gridTextWeight) + .attr('fill', @options.gridTextColor) + + drawBar: (xPos, yPos, width, height, barColor, opacity, radiusArray) -> + maxRadius = Math.max(radiusArray...) + if maxRadius == 0 or maxRadius > height + path = @raphael.rect(xPos, yPos, width, height) + else + path = @raphael.path @roundedRect(xPos, yPos, width, height, radiusArray) + path + .attr('fill', barColor) + .attr('fill-opacity', opacity) + .attr('stroke', 'none') + + roundedRect: (x, y, w, h, r = [0,0,0,0]) -> + [ "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" ] + |