gricer 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +84 -0
  3. data/Rakefile +49 -0
  4. data/app/assets/images/gricer/fluid/breadcrumb.png +0 -0
  5. data/app/assets/javascripts/gricer.js.coffee +85 -0
  6. data/app/assets/javascripts/gricer_backend_jquery.js.coffee +352 -0
  7. data/app/assets/javascripts/jquery.flot.js +2599 -0
  8. data/app/assets/javascripts/jquery.flot.pie.js +750 -0
  9. data/app/assets/javascripts/jquery.flot.resize.js +60 -0
  10. data/app/assets/javascripts/jquery.flot.symbol.js +70 -0
  11. data/app/assets/javascripts/worldmap.js +146 -0
  12. data/app/assets/stylesheets/gricer/fluid-jquery-ui.css.scss +1298 -0
  13. data/app/assets/stylesheets/gricer/fluid.css.scss +240 -0
  14. data/app/assets/stylesheets/gricer/helpers/css3.css.scss +21 -0
  15. data/app/controllers/gricer/base_controller.rb +141 -0
  16. data/app/controllers/gricer/capture_controller.rb +42 -0
  17. data/app/controllers/gricer/dashboard_controller.rb +18 -0
  18. data/app/controllers/gricer/requests_controller.rb +42 -0
  19. data/app/controllers/gricer/sessions_controller.rb +24 -0
  20. data/app/helpers/gricer/base_helper.rb +22 -0
  21. data/app/models/gricer/agent.rb +789 -0
  22. data/app/models/gricer/request.rb +239 -0
  23. data/app/models/gricer/session.rb +433 -0
  24. data/app/views/gricer/capture/index.html.erb +1 -0
  25. data/app/views/gricer/dashboard/_menu.html.erb +10 -0
  26. data/app/views/gricer/dashboard/_overview.html.erb +33 -0
  27. data/app/views/gricer/dashboard/index.html.erb +19 -0
  28. data/config/routes.rb +51 -0
  29. data/lib/gricer.rb +36 -0
  30. data/lib/gricer/action_controller/base.rb +28 -0
  31. data/lib/gricer/action_controller/track.rb +132 -0
  32. data/lib/gricer/active_model/statistics.rb +167 -0
  33. data/lib/gricer/config.rb +125 -0
  34. data/lib/gricer/engine.rb +9 -0
  35. data/lib/gricer/localization.rb +3 -0
  36. data/lib/tasks/gricer_tasks.rake +92 -0
  37. data/spec/controllers/gricer/base_controller_spec.rb +207 -0
  38. data/spec/controllers/gricer/capture_controller_spec.rb +44 -0
  39. data/spec/controllers/gricer/dashboard_controller_spec.rb +44 -0
  40. data/spec/controllers/gricer/requests_controller_spec.rb +36 -0
  41. data/spec/controllers/gricer/sessions_controller_spec.rb +37 -0
  42. data/spec/dummy/Rakefile +7 -0
  43. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  44. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  45. data/spec/dummy/app/assets/stylesheets/dashboard.css +4 -0
  46. data/spec/dummy/app/assets/stylesheets/scaffold.css +56 -0
  47. data/spec/dummy/app/assets/stylesheets/sessions.css +4 -0
  48. data/spec/dummy/app/controllers/application_controller.rb +23 -0
  49. data/spec/dummy/app/controllers/dashboard_controller.rb +19 -0
  50. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  51. data/spec/dummy/app/helpers/dashboard_helper.rb +2 -0
  52. data/spec/dummy/app/views/dashboard/index.html.erb +236 -0
  53. data/spec/dummy/app/views/layouts/application.html.erb +16 -0
  54. data/spec/dummy/config.ru +4 -0
  55. data/spec/dummy/config/application.rb +48 -0
  56. data/spec/dummy/config/boot.rb +10 -0
  57. data/spec/dummy/config/cucumber.yml +9 -0
  58. data/spec/dummy/config/database.yml +25 -0
  59. data/spec/dummy/config/environment.rb +5 -0
  60. data/spec/dummy/config/environments/development.rb +27 -0
  61. data/spec/dummy/config/environments/production.rb +51 -0
  62. data/spec/dummy/config/environments/test.rb +39 -0
  63. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  64. data/spec/dummy/config/initializers/inflections.rb +10 -0
  65. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  66. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  67. data/spec/dummy/config/initializers/session_store.rb +8 -0
  68. data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
  69. data/spec/dummy/config/locales/en.yml +5 -0
  70. data/spec/dummy/config/routes.rb +11 -0
  71. data/spec/dummy/db/schema.rb +241 -0
  72. data/spec/dummy/log/development.log +0 -0
  73. data/spec/dummy/public/404.html +26 -0
  74. data/spec/dummy/public/422.html +26 -0
  75. data/spec/dummy/public/500.html +26 -0
  76. data/spec/dummy/public/favicon.ico +0 -0
  77. data/spec/dummy/script/rails +6 -0
  78. data/spec/helpers/gricer/base_helper_spec.rb +28 -0
  79. data/spec/lib/gricer/action_controller/track_spec.rb +63 -0
  80. data/spec/models/gricer/agent_spec.rb +829 -0
  81. data/spec/models/gricer/request_spec.rb +145 -0
  82. data/spec/models/gricer/session_spec.rb +209 -0
  83. data/spec/routing/capture_routes_spec.rb +6 -0
  84. data/spec/routing/dashboard_routes_spec.rb +9 -0
  85. data/spec/routing/requests_routes_spec.rb +90 -0
  86. data/spec/routing/sessions_routes_spec.rb +115 -0
  87. data/spec/spec_helper.rb +23 -0
  88. metadata +185 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2011 Sven G. Brönstrup
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.
data/README.rdoc ADDED
@@ -0,0 +1,84 @@
1
+ = Gricer
2
+
3
+ Web Analytics Tool for Rails 3.1
4
+
5
+ == Installation
6
+
7
+ * Add Gricer to your Rails application's Gemfile:
8
+
9
+ gem 'rails', '>=3.1rc5'
10
+ gem 'gricer', git: 'https://github.com/gmah/gricer.git'
11
+
12
+ * Include the Gricer's CSS theme to your Rails 3 asset chain (e.g. your application.css[.scss]):
13
+
14
+ /*
15
+ ...
16
+ *= require gricer/fluid
17
+ ...
18
+ */
19
+
20
+ If you are using jquery you may add the default theme unless you use your own jquery-ui theme:
21
+
22
+ *= require gricer/fluid-jquery-ui
23
+
24
+ At the moment there is only the fluid theme. More will come with the time.
25
+
26
+ * Include the Gricer's JS files to your Rails 3 asset chain (e.g. your application.js):
27
+
28
+ //= require gricer
29
+
30
+ For the backend you need to include jquery JS files (the jquery-ui is optional):
31
+
32
+ //= require jquery
33
+ //= require jquery-ui
34
+ //= require jquery_ujs
35
+
36
+ * Add the Gricer's hook to your controllers (or your ApplicationController if you want to track all controllers):
37
+
38
+ class ApplicationController < ActionController::Base
39
+ ...
40
+ gricer_track_requests
41
+ ...
42
+ end
43
+
44
+ * To track values captured by javascript (Flash, Silverlight, screen resolution, ...) add to the end of your layout file:
45
+
46
+ <%= gricer_track_tag %>
47
+
48
+ * Migrate your DB:
49
+
50
+ bundle exec rake db:migrate
51
+
52
+ == Geocoding your visitors
53
+
54
+ * If you want to geocode your visitors add geoip-c to your Gemfile:
55
+
56
+ gem 'geoip-c'
57
+
58
+ * Configure Gricer to use GeoIP (e.g. in an initializer)
59
+
60
+ require 'geoip'
61
+
62
+ Gricer.configure do |config|
63
+ config.geoip_db = GeoIP::City.new("#{PATH_TO_YOUR_GEOIP_DB}/GeoLiteCity.dat", :index, false)
64
+ end
65
+
66
+ == API Documentation
67
+
68
+ * API Documentation can be created by running
69
+ rake doc:yard
70
+ from the Gricer project directory.
71
+ * There is an auto-generated, up-to-the-hour online_documentation[http://gricer.org/api] of the API Documentation.
72
+
73
+
74
+ == Note on Patches/Pull Requests
75
+
76
+ * Fork the project.
77
+ * Make your feature addition or bug fix.
78
+ * Add tests for it. No discussion. No tests, no game. We use rspec and cucumber with associated addons.
79
+ * Commit, do not mess with rakefile, version, or history. If you want to have your own version, thats fine. But bump your version in a seperate commit that can be ignored when pulling.
80
+ * Send me a pull request. Bonus points for topic branches.
81
+
82
+ == Copyright
83
+
84
+ Copyright (c) 2011 Sven G. Brönstrup. See MIT-LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ require 'rspec/core/rake_task'
16
+ RSpec::Core::RakeTask.new(:spec)
17
+
18
+ require 'cucumber/rake/task'
19
+ Cucumber::Rake::Task.new(:cucumber)
20
+
21
+ namespace :doc do
22
+ RDoc::Task.new(:rdoc) do |rdoc|
23
+ rdoc.rdoc_dir = 'rdoc'
24
+ rdoc.title = 'Gricer'
25
+ rdoc.options << '--line-numbers' << '--inline-source'
26
+ rdoc.rdoc_files.include('README.rdoc')
27
+ rdoc.rdoc_files.include('lib/**/*.rb')
28
+ end
29
+
30
+ begin
31
+ require 'yard'
32
+
33
+ YARD::Rake::YardocTask.new(:yard) do |t|
34
+ t.files = ['lib/**/*.rb', 'app/**/*.rb', '-', 'README.rdoc', 'MIT-LICENSE']
35
+ t.options = ['--title', 'API - Gricer - Web Analytics Tool for Rails 3.1', '--private', '--protected']
36
+ end
37
+ rescue
38
+ end
39
+ end
40
+
41
+
42
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
43
+ load 'rails/tasks/engine.rake'
44
+
45
+
46
+
47
+ desc "Run RSpec and Cucumber tests"
48
+ task :test => [:spec, :cucumber]
49
+ task :default => :test
@@ -0,0 +1,85 @@
1
+ window.Gricer =
2
+ getFlashVersion: ->
3
+ if navigator?.plugins?.length > 0
4
+ for r in navigator.plugins
5
+ if r.name.indexOf("Shockwave Flash") > -1
6
+ return r.description.split("Shockwave Flash ")[1]
7
+ else
8
+ if window.ActiveXObject
9
+ for q in [12..2]
10
+ try
11
+ g = new ActiveXObject "ShockwaveFlash.ShockwaveFlash." + q
12
+ if g
13
+ return q + ".0"
14
+ catch p
15
+ # nop
16
+ return false
17
+
18
+ hasJava: ->
19
+ if !self.screen && self.java
20
+ return java.awt.Toolkit.getDefaultToolkit() ? 1 : 0
21
+ else
22
+ if navigator?.javaEnabled()
23
+ return navigator.javaEnabled() ? 1 : 0
24
+ return undefined
25
+
26
+ getSilverlightVersion: ->
27
+ version = false;
28
+ if plugin = navigator?.plugins?["Silverlight Plug-In"]
29
+ version = plugin.description
30
+ if version == "1.0.30226.2"
31
+ version = "2.0.30226.2";
32
+ else
33
+ if window.ActiveXObject
34
+ try
35
+ control = new ActiveXObject('AgControl.AgControl')
36
+ q = 1;
37
+ while control.IsVersionSupported(q + '.0')
38
+ q++;
39
+
40
+ version = q-1
41
+ q = 0;
42
+
43
+ while control.IsVersionSupported(version +'.' + q)
44
+ q++
45
+
46
+ version += '.' + (q-1) + '.'
47
+
48
+ i = 10000
49
+ while i >= 1
50
+ q=1;
51
+ while control.IsVersionSupported(version + (q*i))
52
+ q++
53
+ version += (q-1)
54
+
55
+ i = i / 10
56
+ control = null
57
+ catch p
58
+ version = false
59
+
60
+ return version
61
+
62
+ getWindowSize: ->
63
+ if typeof( window.innerWidth ) == 'number'
64
+ # Non-IE
65
+ return {width: window.innerWidth, height: window.innerHeight}
66
+ else if _ref = document.documentElement?.clientWidth
67
+ # IE 6+ in 'standards compliant mode'
68
+ return {width: document.documentElement.clientWidth, height: document.documentElement.clientHeight}
69
+ else if _ref = document.body?.clientWidth
70
+ # IE 4 compatible
71
+ return {width: document.body.clientWidth, height: document.body.clientHeight}
72
+
73
+ prepareValues: ->
74
+ windowsize = Gricer.getWindowSize()
75
+
76
+ {
77
+ f: Gricer.getFlashVersion(),
78
+ j: Gricer.hasJava(),
79
+ sl: Gricer.getSilverlightVersion(),
80
+ sx: screen.width,
81
+ sy: screen.height,
82
+ sd: screen.colorDepth,
83
+ wx: windowsize.width,
84
+ wy: windowsize.height
85
+ }
@@ -0,0 +1,352 @@
1
+ #=require jquery.flot
2
+ #=require jquery.flot.resize
3
+ #=require jquery.flot.symbol
4
+ #=require jquery.flot.pie
5
+
6
+ $.gricer =
7
+ month: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
8
+
9
+ colors: [
10
+ "#5a9bd4", "#f9a65b", "#fd8c96", "#ce7058", "#f15961", "#d77eb4",
11
+ "#9e67ac", "#8cd5f4", "#fede8f", "#fede8f", "#9e67ac", "#b6eea2",
12
+ #"#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"
13
+ ]
14
+ others_color: '#cccccc'
15
+ unknown_color: '#999999'
16
+
17
+ last_called: $('a[data-gricer-dashboard]').first()
18
+
19
+ loading: ->
20
+ $('#gricer-dashboard').hide()
21
+ $('#gricer-container').html('<div class="loading">Loading ...</div>').show()
22
+
23
+ formatPercentage: (value) ->
24
+ (value * 100).toFixed(2) + '%'
25
+
26
+ formatDate: (value, options = {}) ->
27
+ return '' if not value
28
+
29
+ if options.tb
30
+ if $.datepicker != null
31
+ return $.datepicker.formatDate('M<br/>dd', value)
32
+ else
33
+ day = value.getDate()
34
+ day = '0' + day if day < 10
35
+ return '' + @month[value.getMonth()] + '<br/>' + day
36
+ else
37
+ if $.datepicker != undefined
38
+ return $.datepicker.formatDate($.datepicker.RFC_1036, value)
39
+ else
40
+ day = value.getDate()
41
+ day = '0' + day if day < 10
42
+ month = value.getMonth() + 1
43
+ month = '0' + month if month < 10
44
+ return '' + value.getFullYear() + '-' + month + '-' + day
45
+
46
+ formatHour: (value) ->
47
+ return '' if not value
48
+
49
+ hour = value.getHours()
50
+ hour = '0' + hour if hour < 10
51
+
52
+ return hour
53
+
54
+ labelFor: (value) ->
55
+ if value == true or value == 'true'
56
+ return 'Yes'
57
+ if value == false or value == 'false'
58
+ return 'No'
59
+ if value == null or value == ''
60
+ return '(Unknown)'
61
+
62
+ return value
63
+
64
+ typeSelector: (alternatives) ->
65
+ container = $('<div class="type-selector">')
66
+
67
+ for alt in alternatives
68
+ do(alt) ->
69
+ if alt.uri
70
+ container.append($('<a>').attr('href', alt.uri).addClass(alt.type).attr('data-gricer-' + alt.type, true).attr('data-label', alt.type).attr('data-type-selector', true).append(alt.type))
71
+ else
72
+ container.append($('<span>').addClass(alt.type).append(alt.type))
73
+
74
+ return container
75
+
76
+
77
+ blowUpProcessFlotData: (data, from, thru, step) ->
78
+ output = []
79
+
80
+ for timestamp in [from..thru+86400000] by step
81
+ do(timestamp) ->
82
+ value = 0
83
+ for item in data
84
+ do(item) ->
85
+ value = item[1] if item[0] == timestamp
86
+ output.push [timestamp, value]
87
+
88
+ return output
89
+
90
+ updateBreadcrumb: (elem) ->
91
+ $.gricer.last_called = $(elem)
92
+
93
+ label = $(elem).text() || $(elem).attr('data-label')
94
+
95
+ if $(elem).parents('#gricer-menu').length > 0
96
+ $('#gricer-header .path').empty()
97
+ else if $(elem).parents('#gricer-header .path').length > 0
98
+ $(elem).nextAll().remove()
99
+ return
100
+ else if $(elem).attr('data-type-selector')
101
+ label = $('#gricer-header .path a:last').attr('data-label')
102
+ $('#gricer-header .path a:last').remove()
103
+
104
+ $('#gricer-header .path').append( $(elem).clone().attr('data-label', label).html(label) )
105
+
106
+ $('a[data-gricer-process]').live 'click', ->
107
+ $.gricer.loading()
108
+ $.gricer.updateBreadcrumb(this)
109
+
110
+ $.getJSON $(this).attr('href'), {
111
+ from: $('#gricer-from-field').val()
112
+ thru: $('#gricer-thru-field').val()
113
+ }, (data) ->
114
+
115
+ table = $('<table class="process">')
116
+ plot_data = []
117
+
118
+ row = $('<tr>')
119
+ if data.thru-data.from == 0
120
+ date = new Date
121
+ date.setTime data.from
122
+
123
+ row.append( $('<th>').append($.gricer.formatDate(date)) )
124
+ else
125
+ row.append( $('<th>') )
126
+
127
+ table_step = data.step
128
+ table_step = 86400000 if table_step < 86400000 and data.thru-data.from > 0
129
+
130
+ # Needs improvement for durations over a month
131
+
132
+ for timestamp in [data.from..data.thru+86399999] by table_step
133
+ do(timestamp) ->
134
+ date = new Date
135
+ date.setTime timestamp
136
+
137
+ if table_step >= 86400000
138
+ date_string = $.gricer.formatDate(date, {tb: (data.thru-data.from > 86400000*6)})
139
+ else
140
+ date_string = $.gricer.formatHour(date)
141
+
142
+ row.append($('<th>').append($('<span>').append date_string))
143
+
144
+ table.append row
145
+
146
+ $('#gricer-container').html($('<div class="data">').append table)
147
+
148
+ chart = $('<div class="flot-chart">').append $('<div id="flot-line-chart">')
149
+
150
+ $('#gricer-container').append(chart).append($.gricer.typeSelector data.alternatives)
151
+
152
+ i = 0
153
+ for key, value of data.data
154
+ do(key, value) ->
155
+ detail_link = null
156
+ graph = $.gricer.colors[i]
157
+
158
+ label = label_row = $('<td>')
159
+ if data.detail_uri
160
+ label = $('<a data-gricer-process="true"></a>').attr('href', data.detail_uri.replace('%25%7Bself%7D', encodeURI(key)))
161
+ label_row.append(label)
162
+
163
+ if graph
164
+ label.append($('<span class="badge" style="background:' + $.gricer.colors[i] + '">'))
165
+ else
166
+ label.append($('<span class="badge">'))
167
+
168
+ lable_text = $.gricer.labelFor key
169
+ label.attr('data-label', lable_text)
170
+ label.append(lable_text)
171
+
172
+ row = $('<tr>').append( label_row )
173
+
174
+ for timestamp in [data.from..data.thru+86399999] by table_step
175
+ do(timestamp) ->
176
+ count = 0
177
+ for item in value
178
+ do(item) ->
179
+ count += item[1] if item[0] >= timestamp and item[0] < timestamp + table_step
180
+ count = '' if count == 0
181
+ row.append($('<td class="number">').append(count))
182
+ table.append(row)
183
+
184
+ if $.gricer.colors[i]
185
+ plot_data.push
186
+ label: $.gricer.labelFor key
187
+ data: $.gricer.blowUpProcessFlotData value, data.from, data.thru, data.step
188
+ color: $.gricer.colors[i]
189
+ lines:
190
+ show: true
191
+ points:
192
+ show: false
193
+ symbol: 'cross'
194
+ i++
195
+
196
+ $.plot $("#flot-line-chart"), plot_data,
197
+ xaxis:
198
+ mode: 'time',
199
+ min: data.from,
200
+ max: data.thru+86400000
201
+ yaxis:
202
+ min: 0
203
+ legend:
204
+ show: false
205
+ grid:
206
+ color: $("#flot-line-chart").css('color')
207
+ borderColor: 'transparent'
208
+ colors: $.gricer.colors
209
+
210
+ return false
211
+
212
+ $('a[data-gricer-spread]').live 'click', ->
213
+ $.gricer.loading()
214
+ $.gricer.updateBreadcrumb(this)
215
+
216
+ $.getJSON $(this).attr('href'), {
217
+ from: $('#gricer-from-field').val()
218
+ thru: $('#gricer-thru-field').val()
219
+ }, (data) ->
220
+ table = $('<table>')
221
+ plot_data = []
222
+
223
+ row = $('<tr>')
224
+ row.append( $('<th>') )
225
+ row.append( $('<th>').append('Count') )
226
+ row.append( $('<th>').append('Percentage') )
227
+ table.append row
228
+
229
+ i = 0
230
+ others = 0
231
+ unknown = 0
232
+
233
+ for line in data.data
234
+ do(line) ->
235
+ if line[0] == null
236
+ unknown += line[1]
237
+ else
238
+ detail_link = null
239
+ graph = data.data.length < 4 or $.gricer.colors[i] and line[1]/data.total > 0.05
240
+ label = label_row = $('<td>')
241
+ if data.detail_uri
242
+ label = $('<a data-gricer-spread="true"></a>').attr('href', data.detail_uri.replace('%25%7Bself%7D', encodeURI(line[0])))
243
+ label_row.append(label)
244
+
245
+ if graph
246
+ label.append($('<span class="badge" style="background:' + $.gricer.colors[i] + '">'))
247
+ else
248
+ label.append($('<span class="badge">'))
249
+
250
+ label_text = $.gricer.labelFor(line[0])
251
+ label.attr('data-label', label_text)
252
+ label.append(label_text)
253
+
254
+ row = $('<tr>')
255
+ .append( label_row )
256
+ .append( $('<td class="number">').append(line[1]) )
257
+ .append( $('<td class="number">').append($.gricer.formatPercentage(line[1]/data.total)) )
258
+
259
+ table.append row
260
+
261
+ if graph
262
+ plot_data.push
263
+ label: $.gricer.labelFor line[0]
264
+ data: line[1]
265
+ color: $.gricer.colors[i]
266
+ i++
267
+ else
268
+ others += line[1]
269
+
270
+ if others > 0
271
+ plot_data.push
272
+ label: 'Others'
273
+ data: others
274
+ color: $.gricer.others_color
275
+
276
+ if unknown > 0
277
+ plot_data.push
278
+ label: $.gricer.labelFor null
279
+ data: unknown
280
+ color: $.gricer.unknown_color
281
+
282
+ row = $('<tr>')
283
+ .append(
284
+ $('<td>')
285
+ .append($('<span class="badge" style="background:' + $.gricer.unknown_color + '">'))
286
+ .append($.gricer.labelFor null)
287
+ )
288
+ .append( $('<td class="number">').append(unknown) )
289
+ .append( $('<td class="number">').append($.gricer.formatPercentage(unknown/data.total)) )
290
+
291
+ table.append row
292
+
293
+
294
+ $('#gricer-container').html($('<div class="data">').append table)
295
+
296
+ chart = $('<div class="flot-chart">').append $('<div id="flot-pie-chart">')
297
+
298
+ $('#gricer-container').append(chart).append($.gricer.typeSelector(data.alternatives))
299
+
300
+ $.plot $("#flot-pie-chart"), plot_data,
301
+ series:
302
+ pie:
303
+ show: true
304
+ stroke:
305
+ color: $("#flot-pie-chart").css('background-color')
306
+ label:
307
+ formatter: (label, slice) ->
308
+ '<div style="font-size:x-small;text-align:center;padding:2px;color:'+slice.color+';">'+label+'</div>'
309
+ legend:
310
+ show: false
311
+ colors: $.gricer.colors
312
+
313
+ return false
314
+
315
+ $('a[data-gricer-dashboard]').live 'click', ->
316
+ $.gricer.loading()
317
+ $.gricer.updateBreadcrumb(this)
318
+
319
+ $('#gricer-container').load $(this).attr('href'),
320
+ from: $('#gricer-from-field').val()
321
+ thru: $('#gricer-thru-field').val()
322
+
323
+ return false
324
+
325
+ $('#gricer-menu a').live 'click', ->
326
+ $('#gricer-menu a.active').removeClass('active')
327
+ $(this).addClass('active')
328
+ return false
329
+
330
+ jQuery ->
331
+ $('#gricer-menu a:first')?.click();
332
+
333
+ if $.datepicker != undefined
334
+ dates = $('#gricer-from-field, #gricer-thru-field').datepicker
335
+ defaultDate: "+1w"
336
+ changeMonth: true
337
+ changeYear: true
338
+ numberOfMonths: 1
339
+ dateFormat: 'yy-mm-dd'
340
+ maxDate: new Date
341
+ onSelect: (selectedDate) ->
342
+ if this.id == "gricer-from-field"
343
+ option = 'minDate'
344
+ else
345
+ option = 'maxDate'
346
+
347
+ instance = $(this).data 'datepicker'
348
+ dateFormat = instance.settings.dateFormat || $.datepicker._defaults.dateFormat
349
+ date = $.datepicker.parseDate dateFormat, selectedDate, instance.settings
350
+ dates.not(this).datepicker 'option', option, date
351
+ onClose: (dateText, inst) ->
352
+ $.gricer.last_called.click()