morris-rails 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/Gemfile +3 -0
  2. data/Gemfile.lock +97 -0
  3. data/LICENSE +20 -0
  4. data/README.md +58 -0
  5. data/Rakefile +8 -0
  6. data/VERSION +1 -0
  7. data/app/assets/javascripts/morris.area.coffee +42 -0
  8. data/app/assets/javascripts/morris.bar.coffee +165 -0
  9. data/app/assets/javascripts/morris.coffee +42 -0
  10. data/app/assets/javascripts/morris.donut.coffee +182 -0
  11. data/app/assets/javascripts/morris.grid.coffee +392 -0
  12. data/app/assets/javascripts/morris.hover.coffee +41 -0
  13. data/app/assets/javascripts/morris.line.coffee +354 -0
  14. data/app/assets/stylesheets/morris.core.less +27 -0
  15. data/lib/morris-rails/rails.rb +1 -0
  16. data/morris-rails.gemspec +30 -0
  17. data/spec/dummy/README.rdoc +261 -0
  18. data/spec/dummy/Rakefile +7 -0
  19. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  20. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  21. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  22. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  23. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  24. data/spec/dummy/config.ru +4 -0
  25. data/spec/dummy/config/application.rb +65 -0
  26. data/spec/dummy/config/boot.rb +10 -0
  27. data/spec/dummy/config/database.yml +25 -0
  28. data/spec/dummy/config/environment.rb +5 -0
  29. data/spec/dummy/config/environments/development.rb +37 -0
  30. data/spec/dummy/config/environments/production.rb +67 -0
  31. data/spec/dummy/config/environments/test.rb +37 -0
  32. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  33. data/spec/dummy/config/initializers/inflections.rb +15 -0
  34. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  35. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  36. data/spec/dummy/config/initializers/session_store.rb +8 -0
  37. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  38. data/spec/dummy/config/locales/en.yml +5 -0
  39. data/spec/dummy/config/routes.rb +58 -0
  40. data/spec/dummy/db/test.sqlite3 +0 -0
  41. data/spec/dummy/log/test.log +6 -0
  42. data/spec/dummy/public/404.html +26 -0
  43. data/spec/dummy/public/422.html +26 -0
  44. data/spec/dummy/public/500.html +25 -0
  45. data/spec/dummy/public/favicon.ico +0 -0
  46. data/spec/dummy/script/rails +6 -0
  47. data/spec/dummy/tmp/cache/assets/C87/360/sprockets%2F7f2a79129bb3445603eb704843de5397 +0 -0
  48. data/spec/dummy/tmp/cache/assets/D5B/040/sprockets%2F5d0b7809f616213c43a3ba43cbcda91d +0 -0
  49. data/spec/dummy/tmp/cache/assets/DAE/5D0/sprockets%2Fae427ff9e5b67de97e2ad285c5b623b6 +0 -0
  50. data/spec/morris-rails_spec.rb +12 -0
  51. data/spec/spec_helper.rb +16 -0
  52. metadata +271 -0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,97 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ morris-rails (0.4.2)
5
+ jquery-rails (~> 2.0)
6
+ railties (>= 3.2.0, < 5.0)
7
+ raphaeljs-rails (~> 1.0)
8
+ version (~> 1.0)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ actionpack (3.2.12)
14
+ activemodel (= 3.2.12)
15
+ activesupport (= 3.2.12)
16
+ builder (~> 3.0.0)
17
+ erubis (~> 2.7.0)
18
+ journey (~> 1.0.4)
19
+ rack (~> 1.4.5)
20
+ rack-cache (~> 1.2)
21
+ rack-test (~> 0.6.1)
22
+ sprockets (~> 2.2.1)
23
+ activemodel (3.2.12)
24
+ activesupport (= 3.2.12)
25
+ builder (~> 3.0.0)
26
+ activesupport (3.2.12)
27
+ i18n (~> 0.6)
28
+ multi_json (~> 1.0)
29
+ builder (3.0.4)
30
+ diff-lcs (1.2.1)
31
+ erubis (2.7.0)
32
+ fancy_logger (0.1.1)
33
+ outline (~> 0.1.5)
34
+ rainbow (~> 1.1.3)
35
+ version (~> 1.0.0)
36
+ fuubar (1.1.0)
37
+ rspec (~> 2.0)
38
+ rspec-instafail (~> 0.2.0)
39
+ ruby-progressbar (~> 1.0.0)
40
+ hike (1.2.1)
41
+ i18n (0.6.4)
42
+ journey (1.0.4)
43
+ jquery-rails (2.2.1)
44
+ railties (>= 3.0, < 5.0)
45
+ thor (>= 0.14, < 2.0)
46
+ json (1.7.7)
47
+ meta_tools (0.2.7)
48
+ multi_json (1.7.1)
49
+ outline (0.1.5)
50
+ meta_tools (~> 0.2.6)
51
+ rack (1.4.5)
52
+ rack-cache (1.2)
53
+ rack (>= 0.4)
54
+ rack-ssl (1.3.3)
55
+ rack
56
+ rack-test (0.6.2)
57
+ rack (>= 1.0)
58
+ railties (3.2.12)
59
+ actionpack (= 3.2.12)
60
+ activesupport (= 3.2.12)
61
+ rack-ssl (~> 1.3.2)
62
+ rake (>= 0.8.7)
63
+ rdoc (~> 3.4)
64
+ thor (>= 0.14.6, < 2.0)
65
+ rainbow (1.1.4)
66
+ rake (10.0.3)
67
+ raphaeljs-rails (1.0.1)
68
+ rdoc (3.12.2)
69
+ json (~> 1.4)
70
+ rspec (2.13.0)
71
+ rspec-core (~> 2.13.0)
72
+ rspec-expectations (~> 2.13.0)
73
+ rspec-mocks (~> 2.13.0)
74
+ rspec-core (2.13.1)
75
+ rspec-expectations (2.13.0)
76
+ diff-lcs (>= 1.1.3, < 2.0)
77
+ rspec-instafail (0.2.4)
78
+ rspec-mocks (2.13.0)
79
+ ruby-progressbar (1.0.2)
80
+ sprockets (2.2.2)
81
+ hike (~> 1.2)
82
+ multi_json (~> 1.0)
83
+ rack (~> 1.0)
84
+ tilt (~> 1.1, != 1.3.0)
85
+ thor (0.17.0)
86
+ tilt (1.3.6)
87
+ version (1.0.0)
88
+
89
+ PLATFORMS
90
+ ruby
91
+
92
+ DEPENDENCIES
93
+ fancy_logger (~> 0.1)
94
+ fuubar (~> 1.1)
95
+ morris-rails!
96
+ rake (~> 10.0)
97
+ rspec (~> 2.13)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Ryan Scott Lewis <ryan@rynet.us>.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,58 @@
1
+ # morris-rails
2
+
3
+ Adds [morris](https://github.com/oesmith/morris.js) to the Rails 3 asset pipeline.
4
+
5
+ ## Install
6
+
7
+ ### Bundler: `gem 'morris-rails'` in `group :assets`
8
+
9
+ ### RubyGems: `gem install morris-rails`
10
+
11
+ ### Setup
12
+
13
+ Add the default morris stylesheet to `app/assets/stylesheets/application.css`:
14
+
15
+ ```css
16
+ //= require morris.core
17
+ ```
18
+
19
+ Or, if using Less, you can use the `import` declaration to import the default morris stylesheet:
20
+
21
+ ```less
22
+ @import 'morris.core';
23
+ ```
24
+
25
+ Now you must add `require` statements to `app/assets/javascripts/application.js` for `morris` and it's dependencies:
26
+
27
+ > Note that `jquery` and `raphael/raphael` must be required before `morris`.
28
+
29
+ ```js
30
+ //= require jquery
31
+ //= require raphael/raphael
32
+ //= require morris
33
+ ```
34
+
35
+ Now, require which graphs you will be using:
36
+
37
+ ```js
38
+ //= require morris.grid
39
+ //= require morris.hover
40
+ //= require morris.area
41
+ //= require morris.line
42
+ //= require morris.bar
43
+ //= require morris.donut
44
+ ```
45
+
46
+ ## Contributing
47
+
48
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
49
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
50
+ * Fork the project
51
+ * Start a feature/bugfix branch
52
+ * Commit and push until you are happy with your contribution
53
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
54
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
55
+
56
+ ## Copyright
57
+
58
+ Copyright (c) 2012 Ryan Scott Lewis. See LICENSE for details.
@@ -0,0 +1,8 @@
1
+ require 'rake/morris_task'
2
+
3
+ Rake::MorrisTask.new do |options|
4
+ options.root = Pathname.new(__FILE__).dirname
5
+ options.log_level = :info
6
+ options.tag_on_update = true
7
+ # options.fake = true
8
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.2
@@ -0,0 +1,42 @@
1
+ class Morris.Area extends Morris.Line
2
+ # Initialise
3
+ #
4
+ constructor: (options) ->
5
+ return new Morris.Area(options) unless (@ instanceof Morris.Area)
6
+ @cumulative = true
7
+ super(options)
8
+
9
+ # calculate series data point coordinates
10
+ #
11
+ # @private
12
+ calcPoints: ->
13
+ for row in @data
14
+ row._x = @transX(row.x)
15
+ total = 0
16
+ row._y = for y in row.y
17
+ total += (y || 0)
18
+ @transY(total)
19
+ row._ymax = row._y[row._y.length - 1]
20
+
21
+ # draw the data series
22
+ #
23
+ # @private
24
+ drawSeries: ->
25
+ for i in [@options.ykeys.length-1..0]
26
+ path = @paths[i]
27
+ if path isnt null
28
+ path = path + "L#{@transX(@xmax)},#{@bottom}L#{@transX(@xmin)},#{@bottom}Z"
29
+ @drawFilledPath(path, @fillForSeries(i))
30
+ super()
31
+
32
+ fillForSeries: (i) ->
33
+ color = Raphael.rgb2hsl @colorFor(@data[i], i, 'line')
34
+ Raphael.hsl(
35
+ color.h,
36
+ Math.min(255, color.s * 0.75),
37
+ Math.min(255, color.l * 1.25))
38
+
39
+ drawFilledPath: (path, fill) ->
40
+ @raphael.path(path)
41
+ .attr('fill', fill)
42
+ .attr('stroke-width', 0)
@@ -0,0 +1,165 @@
1
+ class Morris.Bar extends Morris.Grid
2
+ constructor: (options) ->
3
+ return new Morris.Bar(options) unless (@ instanceof Morris.Bar)
4
+ super($.extend {}, options, parseTime: false)
5
+
6
+ init: ->
7
+ @cumulative = @options.stacked
8
+
9
+ if @options.hideHover isnt 'always'
10
+ @hover = new Morris.Hover(parent: @el)
11
+ @on('hovermove', @onHoverMove)
12
+ @on('hoverout', @onHoverOut)
13
+
14
+ # Default configuration
15
+ #
16
+ defaults:
17
+ barSizeRatio: 0.75
18
+ barGap: 3
19
+ barColors: [
20
+ '#0b62a4'
21
+ '#7a92a3'
22
+ '#4da74d'
23
+ '#afd8f8'
24
+ '#edc240'
25
+ '#cb4b4b'
26
+ '#9440ed'
27
+ ]
28
+ xLabelMargin: 50
29
+
30
+ # Do any size-related calculations
31
+ #
32
+ # @private
33
+ calc: ->
34
+ @calcBars()
35
+ if @options.hideHover is false
36
+ @hover.update(@hoverContentForRow(@data.length - 1)...)
37
+
38
+ # calculate series data bars coordinates and sizes
39
+ #
40
+ # @private
41
+ calcBars: ->
42
+ for row, idx in @data
43
+ row._x = @left + @width * (idx + 0.5) / @data.length
44
+ row._y = for y in row.y
45
+ if y? then @transY(y) else null
46
+
47
+ # Draws the bar chart.
48
+ #
49
+ draw: ->
50
+ @drawXAxis() if @options.axes
51
+ @drawSeries()
52
+
53
+ # draw the x-axis labels
54
+ #
55
+ # @private
56
+ drawXAxis: ->
57
+ # draw x axis labels
58
+ ypos = @bottom + @options.gridTextSize * 1.25
59
+ prevLabelMargin = null
60
+ for i in [0...@data.length]
61
+ row = @data[@data.length - 1 - i]
62
+ label = @drawXAxisLabel(row._x, ypos, row.label)
63
+ labelBox = label.getBBox()
64
+ # ensure a minimum of `xLabelMargin` pixels between labels, and ensure
65
+ # labels don't overflow the container
66
+ if (not prevLabelMargin? or prevLabelMargin >= labelBox.x + labelBox.width) and
67
+ labelBox.x >= 0 and (labelBox.x + labelBox.width) < @el.width()
68
+ prevLabelMargin = labelBox.x - @options.xLabelMargin
69
+ else
70
+ label.remove()
71
+
72
+ # draw the data series
73
+ #
74
+ # @private
75
+ drawSeries: ->
76
+ groupWidth = @width / @options.data.length
77
+ numBars = if @options.stacked? then 1 else @options.ykeys.length
78
+ barWidth = (groupWidth * @options.barSizeRatio - @options.barGap * (numBars - 1)) / numBars
79
+ leftPadding = groupWidth * (1 - @options.barSizeRatio) / 2
80
+ zeroPos = if @ymin <= 0 and @ymax >= 0 then @transY(0) else null
81
+ @bars = for row, idx in @data
82
+ lastTop = 0
83
+ for ypos, sidx in row._y
84
+ if ypos != null
85
+ if zeroPos
86
+ top = Math.min(ypos, zeroPos)
87
+ bottom = Math.max(ypos, zeroPos)
88
+ else
89
+ top = ypos
90
+ bottom = @bottom
91
+
92
+ left = @left + idx * groupWidth + leftPadding
93
+ left += sidx * (barWidth + @options.barGap) unless @options.stacked
94
+ size = bottom - top
95
+
96
+ top -= lastTop if @options.stacked
97
+ @drawBar(left, top, barWidth, size, @colorFor(row, sidx, 'bar'))
98
+
99
+ lastTop += size
100
+ else
101
+ null
102
+
103
+ # @private
104
+ #
105
+ # @param row [Object] row data
106
+ # @param sidx [Number] series index
107
+ # @param type [String] "bar", "hover" or "label"
108
+ colorFor: (row, sidx, type) ->
109
+ if typeof @options.barColors is 'function'
110
+ r = { x: row.x, y: row.y[sidx], label: row.label }
111
+ s = { index: sidx, key: @options.ykeys[sidx], label: @options.labels[sidx] }
112
+ @options.barColors.call(@, r, s, type)
113
+ else
114
+ @options.barColors[sidx % @options.barColors.length]
115
+
116
+ # hit test - returns the index of the row beneath the given coordinate
117
+ #
118
+ hitTest: (x, y) ->
119
+ return null if @data.length == 0
120
+ x = Math.max(Math.min(x, @right), @left)
121
+ Math.min(@data.length - 1,
122
+ Math.floor((x - @left) / (@width / @data.length)))
123
+
124
+ # hover movement event handler
125
+ #
126
+ # @private
127
+ onHoverMove: (x, y) =>
128
+ index = @hitTest(x, y)
129
+ @hover.update(@hoverContentForRow(index)...)
130
+
131
+ # hover out event handler
132
+ #
133
+ # @private
134
+ onHoverOut: =>
135
+ if @options.hideHover is 'auto'
136
+ @hover.hide()
137
+
138
+ # hover content for a point
139
+ #
140
+ # @private
141
+ hoverContentForRow: (index) ->
142
+ if typeof @options.hoverCallback is 'function'
143
+ content = @options.hoverCallback(index, @options)
144
+ else
145
+ row = @data[index]
146
+ content = "<div class='morris-hover-row-label'>#{row.label}</div>"
147
+ for y, j in row.y
148
+ content += """
149
+ <div class='morris-hover-point' style='color: #{@colorFor(row, j, 'label')}'>
150
+ #{@options.labels[j]}:
151
+ #{@yLabelFormat(y)}
152
+ </div>
153
+ """
154
+ x = @left + (index + 0.5) * @width / @data.length
155
+ [content, x]
156
+
157
+ drawXAxisLabel: (xPos, yPos, text) ->
158
+ label = @raphael.text(xPos, yPos, text)
159
+ .attr('font-size', @options.gridTextSize)
160
+ .attr('fill', @options.gridTextColor)
161
+
162
+ drawBar: (xPos, yPos, width, height, barColor) ->
163
+ @raphael.rect(xPos, yPos, width, height)
164
+ .attr('fill', barColor)
165
+ .attr('stroke-width', 0)
@@ -0,0 +1,42 @@
1
+ Morris = window.Morris = {}
2
+
3
+ $ = jQuery
4
+
5
+ # Very simple event-emitter class.
6
+ #
7
+ # @private
8
+ class Morris.EventEmitter
9
+ on: (name, handler) ->
10
+ unless @handlers?
11
+ @handlers = {}
12
+ unless @handlers[name]?
13
+ @handlers[name] = []
14
+ @handlers[name].push(handler)
15
+
16
+ fire: (name, args...) ->
17
+ if @handlers? and @handlers[name]?
18
+ for handler in @handlers[name]
19
+ handler(args...)
20
+
21
+ # Make long numbers prettier by inserting commas.
22
+ #
23
+ # @example
24
+ # Morris.commas(1234567) -> '1,234,567'
25
+ Morris.commas = (num) ->
26
+ if num?
27
+ ret = if num < 0 then "-" else ""
28
+ absnum = Math.abs(num)
29
+ intnum = Math.floor(absnum).toFixed(0)
30
+ ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ',')
31
+ strabsnum = absnum.toString()
32
+ if strabsnum.length > intnum.length
33
+ ret += strabsnum.slice(intnum.length)
34
+ ret
35
+ else
36
+ '-'
37
+
38
+ # Zero-pad numbers to two characters wide.
39
+ #
40
+ # @example
41
+ # Morris.pad2(1) -> '01'
42
+ Morris.pad2 = (number) -> (if number < 10 then '0' else '') + number