d3_rails 2.8.0 → 2.8.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 (63) hide show
  1. data/.DS_Store +0 -0
  2. data/README.md +27 -5
  3. data/lib/d3_rails/version.rb +1 -1
  4. data/vendor/.DS_Store +0 -0
  5. data/vendor/assets/.DS_Store +0 -0
  6. data/vendor/assets/javascripts/.DS_Store +0 -0
  7. data/vendor/assets/javascripts/d3.v2.js +99 -80
  8. data/vendor/assets/javascripts/morris.js +1 -0
  9. data/vendor/assets/javascripts/morris/.DS_Store +0 -0
  10. data/vendor/assets/javascripts/morris/Makefile +10 -0
  11. data/vendor/assets/javascripts/morris/README.md +87 -0
  12. data/vendor/assets/javascripts/morris/examples/_template.html +18 -0
  13. data/vendor/assets/javascripts/morris/examples/days.html +36 -0
  14. data/vendor/assets/javascripts/morris/examples/decimal.html +31 -0
  15. data/vendor/assets/javascripts/morris/examples/lib/example.css +13 -0
  16. data/vendor/assets/javascripts/morris/examples/lib/example.js +4 -0
  17. data/vendor/assets/javascripts/morris/examples/lib/prettify.css +1 -0
  18. data/vendor/assets/javascripts/morris/examples/lib/prettify.js +28 -0
  19. data/vendor/assets/javascripts/morris/examples/months-no-smooth.html +37 -0
  20. data/vendor/assets/javascripts/morris/examples/negative.html +35 -0
  21. data/vendor/assets/javascripts/morris/examples/non-date.html +36 -0
  22. data/vendor/assets/javascripts/morris/examples/quarters.html +53 -0
  23. data/vendor/assets/javascripts/morris/examples/timestamps.html +37 -0
  24. data/vendor/assets/javascripts/morris/examples/weeks.html +52 -0
  25. data/vendor/assets/javascripts/morris/morris.coffee +444 -0
  26. data/vendor/assets/javascripts/morris/morris.js +493 -0
  27. data/vendor/assets/javascripts/morris/morris.min.js +1 -0
  28. data/vendor/assets/javascripts/tesseract.js +1 -0
  29. data/vendor/assets/javascripts/tesseract/.gitignore +2 -0
  30. data/vendor/assets/javascripts/tesseract/LICENSE +12 -0
  31. data/vendor/assets/javascripts/tesseract/Makefile +48 -0
  32. data/vendor/assets/javascripts/tesseract/README.md +11 -0
  33. data/vendor/assets/javascripts/tesseract/index.js +1 -0
  34. data/vendor/assets/javascripts/tesseract/lib/dart/AUTHORS +9 -0
  35. data/vendor/assets/javascripts/tesseract/lib/dart/LICENSE +25 -0
  36. data/vendor/assets/javascripts/tesseract/lib/dart/dual_pivot_quicksort.dart +342 -0
  37. data/vendor/assets/javascripts/tesseract/package.json +11 -0
  38. data/vendor/assets/javascripts/tesseract/src/array.js +32 -0
  39. data/vendor/assets/javascripts/tesseract/src/bisect.js +44 -0
  40. data/vendor/assets/javascripts/tesseract/src/filter.js +19 -0
  41. data/vendor/assets/javascripts/tesseract/src/heap.js +44 -0
  42. data/vendor/assets/javascripts/tesseract/src/heapselect.js +36 -0
  43. data/vendor/assets/javascripts/tesseract/src/identity.js +3 -0
  44. data/vendor/assets/javascripts/tesseract/src/insertionsort.js +18 -0
  45. data/vendor/assets/javascripts/tesseract/src/null.js +3 -0
  46. data/vendor/assets/javascripts/tesseract/src/package.js +14 -0
  47. data/vendor/assets/javascripts/tesseract/src/permute.js +8 -0
  48. data/vendor/assets/javascripts/tesseract/src/quicksort.js +282 -0
  49. data/vendor/assets/javascripts/tesseract/src/reduce.js +19 -0
  50. data/vendor/assets/javascripts/tesseract/src/tesseract.js +663 -0
  51. data/vendor/assets/javascripts/tesseract/src/version.js +1 -0
  52. data/vendor/assets/javascripts/tesseract/src/zero.js +3 -0
  53. data/vendor/assets/javascripts/tesseract/tesseract.js +1177 -0
  54. data/vendor/assets/javascripts/tesseract/tesseract.min.js +1 -0
  55. data/vendor/assets/javascripts/tesseract/test/benchmark.js +177 -0
  56. data/vendor/assets/javascripts/tesseract/test/bisect-test.js +206 -0
  57. data/vendor/assets/javascripts/tesseract/test/heap-test.js +44 -0
  58. data/vendor/assets/javascripts/tesseract/test/permute-test.js +51 -0
  59. data/vendor/assets/javascripts/tesseract/test/select-test.js +63 -0
  60. data/vendor/assets/javascripts/tesseract/test/sort-test.js +83 -0
  61. data/vendor/assets/javascripts/tesseract/test/tesseract-test.js +655 -0
  62. data/vendor/assets/javascripts/tesseract/test/version-test.js +16 -0
  63. metadata +63 -8
@@ -0,0 +1,52 @@
1
+ <!doctype html>
2
+ <head>
3
+ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
4
+ <script src="https://raw.github.com/DmitryBaranovskiy/raphael/300aa589f5a0ba7fce667cd62c7cdda0bd5ad904/raphael-min.js"></script>
5
+ <script src="../morris.js"></script>
6
+ <script src="lib/prettify.js"></script>
7
+ <script src="lib/example.js"></script>
8
+ <link rel="stylesheet" href="lib/example.css">
9
+ <link rel="stylesheet" href="lib/prettify.css">
10
+ </head>
11
+ <body>
12
+ <h1>Formatting Dates With Weeks</h1>
13
+ <div id="graph"></div>
14
+ <pre id="code" class="prettyprint linenums">
15
+ var week_data = [
16
+ {"period": "2011 W27", "licensed": 3407, "sorned": 660},
17
+ {"period": "2011 W26", "licensed": 3351, "sorned": 629},
18
+ {"period": "2011 W25", "licensed": 3269, "sorned": 618},
19
+ {"period": "2011 W24", "licensed": 3246, "sorned": 661},
20
+ {"period": "2011 W23", "licensed": 3257, "sorned": 667},
21
+ {"period": "2011 W22", "licensed": 3248, "sorned": 627},
22
+ {"period": "2011 W21", "licensed": 3171, "sorned": 660},
23
+ {"period": "2011 W20", "licensed": 3171, "sorned": 676},
24
+ {"period": "2011 W19", "licensed": 3201, "sorned": 656},
25
+ {"period": "2011 W18", "licensed": 3215, "sorned": 622},
26
+ {"period": "2011 W17", "licensed": 3148, "sorned": 632},
27
+ {"period": "2011 W16", "licensed": 3155, "sorned": 681},
28
+ {"period": "2011 W15", "licensed": 3190, "sorned": 667},
29
+ {"period": "2011 W14", "licensed": 3226, "sorned": 620},
30
+ {"period": "2011 W13", "licensed": 3245, "sorned": null},
31
+ {"period": "2011 W12", "licensed": 3289, "sorned": null},
32
+ {"period": "2011 W11", "licensed": 3263, "sorned": null},
33
+ {"period": "2011 W10", "licensed": 3189, "sorned": null},
34
+ {"period": "2011 W09", "licensed": 3079, "sorned": null},
35
+ {"period": "2011 W08", "licensed": 3085, "sorned": null},
36
+ {"period": "2011 W07", "licensed": 3055, "sorned": null},
37
+ {"period": "2011 W06", "licensed": 3063, "sorned": null},
38
+ {"period": "2011 W05", "licensed": 2943, "sorned": null},
39
+ {"period": "2011 W04", "licensed": 2806, "sorned": null},
40
+ {"period": "2011 W03", "licensed": 2674, "sorned": null},
41
+ {"period": "2011 W02", "licensed": 1702, "sorned": null},
42
+ {"period": "2011 W01", "licensed": 1732, "sorned": null}
43
+ ];
44
+ Morris.Line({
45
+ element: 'graph',
46
+ data: week_data,
47
+ xkey: 'period',
48
+ ykeys: ['licensed', 'sorned'],
49
+ labels: ['Licensed', 'SORN']
50
+ });
51
+ </pre>
52
+ </body>
@@ -0,0 +1,444 @@
1
+ # The original line graph.
2
+ #
3
+ $ = jQuery
4
+
5
+ Morris = {}
6
+ class Morris.Line
7
+ # Initialise the graph.
8
+ #
9
+ # @param {Object} options
10
+ constructor: (options) ->
11
+ if not (this instanceof Morris.Line)
12
+ return new Morris.Line(options)
13
+ if typeof options.element is 'string'
14
+ @el = $ document.getElementById(options.element)
15
+ else
16
+ @el = $ options.element
17
+ @options = $.extend {}, @defaults, options
18
+ # bail if there's no data
19
+ if @options.data is undefined or @options.data.length is 0
20
+ return
21
+ @el.addClass 'graph-initialised'
22
+ @precalc()
23
+ @redraw()
24
+
25
+ # Default configuration
26
+ #
27
+ defaults:
28
+ lineWidth: 3
29
+ pointSize: 4
30
+ lineColors: [
31
+ '#0b62a4'
32
+ '#7A92A3'
33
+ '#4da74d'
34
+ '#afd8f8'
35
+ '#edc240'
36
+ '#cb4b4b'
37
+ '#9440ed'
38
+ ]
39
+ ymax: 'auto'
40
+ ymin: 'auto 0'
41
+ marginTop: 25
42
+ marginRight: 25
43
+ marginBottom: 30
44
+ marginLeft: 25
45
+ numLines: 5
46
+ gridLineColor: '#aaa'
47
+ gridTextColor: '#888'
48
+ gridTextSize: 12
49
+ gridStrokeWidth: 0.5
50
+ hoverPaddingX: 10
51
+ hoverPaddingY: 5
52
+ hoverMargin: 10
53
+ hoverFillColor: '#fff'
54
+ hoverBorderColor: '#ccc'
55
+ hoverBorderWidth: 2
56
+ hoverOpacity: 0.95
57
+ hoverLabelColor: '#444'
58
+ hoverFontSize: 12
59
+ smooth: true
60
+ hideHover: false
61
+ parseTime: true
62
+ units: ''
63
+ dateFormat: (x) -> new Date(x).toString()
64
+
65
+ # Do any necessary pre-processing for a new dataset
66
+ #
67
+ precalc: ->
68
+ # sort data
69
+ @options.data.sort (a, b) => (a[@options.xkey] < b[@options.xkey]) - (b[@options.xkey] < a[@options.xkey])
70
+ # extract labels
71
+ @columnLabels = $.map @options.data, (d) => d[@options.xkey]
72
+ @seriesLabels = @options.labels
73
+
74
+ # extract series data
75
+ @series = []
76
+ for ykey in @options.ykeys
77
+ series_data = []
78
+ for d in @options.data
79
+ series_data.push(d[ykey])
80
+ @series.push(series_data)
81
+
82
+ # translate x labels into nominal dates
83
+ # note: currently using decimal years to specify dates
84
+ if @options.parseTime
85
+ @xvals = $.map @columnLabels, (x) => @parseYear x
86
+ else
87
+ @xvals = [(@columnLabels.length-1)..0]
88
+ # translate column labels, if they're timestamps
89
+ if @options.parseTime
90
+ @columnLabels = $.map @columnLabels, (d) =>
91
+ if typeof d is 'number'
92
+ @options.dateFormat(d)
93
+ else
94
+ d
95
+ @xmin = Math.min.apply null, @xvals
96
+ @xmax = Math.max.apply null, @xvals
97
+ if @xmin is @xmax
98
+ @xmin -= 1
99
+ @xmax += 1
100
+
101
+ # Compute the vertical range of the graph if desired
102
+ if typeof @options.ymax is 'string' and @options.ymax[0..3] is 'auto'
103
+ # use Array.concat to flatten arrays and find the max y value
104
+ ymax = Math.max.apply null, Array.prototype.concat.apply([], @series)
105
+ if @options.ymax.length > 5
106
+ @options.ymax = Math.max parseInt(@options.ymax[5..], 10), ymax
107
+ else
108
+ @options.ymax = ymax
109
+ if typeof @options.ymin is 'string' and @options.ymin[0..3] is 'auto'
110
+ ymin = Math.min.apply null, Array.prototype.concat.apply([], @series)
111
+ if @options.ymin.length > 5
112
+ @options.ymin = Math.min parseInt(@options.ymin[5..], 10), ymin
113
+ else
114
+ @options.ymin = ymin
115
+
116
+ # Some instance variables for later
117
+ @pointGrow = Raphael.animation r: @options.pointSize + 3, 25, 'linear'
118
+ @pointShrink = Raphael.animation r: @options.pointSize, 25, 'linear'
119
+ @elementWidth = null
120
+ @elementHeight = null
121
+ # column hilight events
122
+ @prevHilight = null
123
+ @el.mousemove (evt) =>
124
+ @updateHilight evt.pageX
125
+ if @options.hideHover
126
+ @el.mouseout (evt) =>
127
+ @hilight null
128
+ touchHandler = (evt) =>
129
+ touch = evt.originalEvent.touches[0] or evt.originalEvent.changedTouches[0]
130
+ @updateHilight touch.pageX
131
+ return touch
132
+ @el.bind 'touchstart', touchHandler
133
+ @el.bind 'touchmove', touchHandler
134
+ @el.bind 'touchend', touchHandler
135
+
136
+ # Do any size-related calculations
137
+ #
138
+ calc: ->
139
+ w = @el.width()
140
+ h = @el.height()
141
+ if @elementWidth != w or @elementHeight != h
142
+ # calculate grid dimensions
143
+ @maxYLabelWidth = Math.max(
144
+ @measureText(@options.ymin + @options.units, @options.gridTextSize).width,
145
+ @measureText(@options.ymax + @options.units, @options.gridTextSize).width)
146
+ @left = @maxYLabelWidth + @options.marginLeft
147
+ @width = @el.width() - @left - @options.marginRight
148
+ @height = @el.height() - @options.marginTop - @options.marginBottom
149
+ @dx = @width / (@xmax - @xmin)
150
+ @dy = @height / (@options.ymax - @options.ymin)
151
+ # calculate series data point coordinates
152
+ @columns = (@transX(x) for x in @xvals)
153
+ @seriesCoords = []
154
+ for s in @series
155
+ scoords = []
156
+ $.each s, (i, y) =>
157
+ if y == null
158
+ scoords.push(null)
159
+ else
160
+ scoords.push(x: @columns[i], y: @transY(y))
161
+ @seriesCoords.push(scoords)
162
+ # calculate hover margins
163
+ @hoverMargins = $.map @columns.slice(1), (x, i) => (x + @columns[i]) / 2
164
+
165
+ # quick translation helpers
166
+ #
167
+ transX: (x) =>
168
+ if @xvals.length is 1
169
+ @left + @width / 2
170
+ else
171
+ @left + (x - @xmin) * @dx
172
+
173
+ transY: (y) =>
174
+ return @options.marginTop + @height - (y - @options.ymin) * @dy
175
+
176
+ # Clear and redraw the graph
177
+ #
178
+ redraw: ->
179
+ # remove child elements (get rid of old drawings)
180
+ @el.empty()
181
+
182
+ # the raphael drawing instance
183
+ @r = new Raphael(@el[0])
184
+
185
+ @calc()
186
+ @drawGrid()
187
+ @drawSeries()
188
+ @drawHover()
189
+ @hilight(if @options.hideHover then null else 0)
190
+
191
+ # draw the grid, and axes labels
192
+ #
193
+ drawGrid: ->
194
+ # draw y axis labels, horizontal lines
195
+ yInterval = (@options.ymax - @options.ymin) / (@options.numLines - 1)
196
+ firstY = Math.ceil(@options.ymin / yInterval) * yInterval
197
+ lastY = Math.floor(@options.ymax / yInterval) * yInterval
198
+ for lineY in [firstY..lastY] by yInterval
199
+ v = Math.floor(lineY)
200
+ y = @transY(v)
201
+ @r.text(@left - @options.marginLeft/2, y, @commas(v) + @options.units)
202
+ .attr('font-size', @options.gridTextSize)
203
+ .attr('fill', @options.gridTextColor)
204
+ .attr('text-anchor', 'end')
205
+ @r.path("M#{@left},#{y}H#{@left + @width}")
206
+ .attr('stroke', @options.gridLineColor)
207
+ .attr('stroke-width', @options.gridStrokeWidth)
208
+
209
+ ## draw x axis labels
210
+ prevLabelMargin = null
211
+ xLabelMargin = 50 # make this an option?
212
+ if @options.parseTime
213
+ x1 = new Date(@xmin).getFullYear()
214
+ x2 = new Date(@xmax).getFullYear()
215
+ else
216
+ x1 = @xmin
217
+ x2 = @xmax
218
+ for i in [x1..x2]
219
+ if @options.parseTime
220
+ xpos = new Date(i, 0, 1).getTime()
221
+ if xpos < @xmin
222
+ continue
223
+ else
224
+ xpos = i
225
+ labelText = if @options.parseTime then i else @columnLabels[@columnLabels.length-i-1]
226
+ label = @r.text(@transX(xpos), @options.marginTop + @height + @options.marginBottom / 2, labelText)
227
+ .attr('font-size', @options.gridTextSize)
228
+ .attr('fill', @options.gridTextColor)
229
+ labelBox = label.getBBox()
230
+ # ensure a minimum of `xLabelMargin` pixels between labels
231
+ if prevLabelMargin is null or prevLabelMargin <= labelBox.x
232
+ prevLabelMargin = labelBox.x + labelBox.width + xLabelMargin
233
+ else
234
+ label.remove()
235
+
236
+ # draw the data series
237
+ #
238
+ drawSeries: ->
239
+ for i in [@seriesCoords.length-1..0]
240
+ coords = @seriesCoords[i]
241
+ if coords.length > 1
242
+ path = @createPath coords, @options.marginTop, @left, @options.marginTop + @height, @left + @width
243
+ @r.path(path)
244
+ .attr('stroke', @options.lineColors[i])
245
+ .attr('stroke-width', @options.lineWidth)
246
+ @seriesPoints = ([] for i in [0..@seriesCoords.length-1])
247
+ for i in [@seriesCoords.length-1..0]
248
+ for c in @seriesCoords[i]
249
+ if c == null
250
+ circle = null
251
+ else
252
+ circle = @r.circle(c.x, c.y, @options.pointSize)
253
+ .attr('fill', @options.lineColors[i])
254
+ .attr('stroke-width', 1)
255
+ .attr('stroke', '#ffffff')
256
+ @seriesPoints[i].push(circle)
257
+
258
+ # create a path for a data series
259
+ #
260
+ createPath: (all_coords, top, left, bottom, right) ->
261
+ path = ""
262
+ coords = $.map(all_coords, (c) -> c)
263
+ if @options.smooth
264
+ grads = @gradients coords
265
+ for i in [0..coords.length-1]
266
+ c = coords[i]
267
+ if i is 0
268
+ path += "M#{c.x},#{c.y}"
269
+ else
270
+ g = grads[i]
271
+ lc = coords[i - 1]
272
+ lg = grads[i - 1]
273
+ ix = (c.x - lc.x) / 4
274
+ x1 = lc.x + ix
275
+ y1 = Math.min(bottom, lc.y + ix * lg)
276
+ x2 = c.x - ix
277
+ y2 = Math.min(bottom, c.y - ix * g)
278
+ path += "C#{x1},#{y1},#{x2},#{y2},#{c.x},#{c.y}"
279
+ else
280
+ path = "M" + $.map(coords, (c) -> "#{c.x},#{c.y}").join("L")
281
+ return path
282
+
283
+ # calculate a gradient at each point for a series of points
284
+ #
285
+ gradients: (coords) ->
286
+ $.map coords, (c, i) ->
287
+ if i is 0
288
+ (coords[1].y - c.y) / (coords[1].x - c.x)
289
+ else if i is (coords.length - 1)
290
+ (c.y - coords[i - 1].y) / (c.x - coords[i - 1].x)
291
+ else
292
+ (coords[i + 1].y - coords[i - 1].y) / (coords[i + 1].x - coords[i - 1].x)
293
+
294
+ # draw the hover tooltip
295
+ #
296
+ drawHover: ->
297
+ # hover labels
298
+ @hoverHeight = @options.hoverFontSize * 1.5 * (@series.length + 1)
299
+ @hover = @r.rect(-10, -@hoverHeight / 2 - @options.hoverPaddingY, 20, @hoverHeight + @options.hoverPaddingY * 2, 10)
300
+ .attr('fill', @options.hoverFillColor)
301
+ .attr('stroke', @options.hoverBorderColor)
302
+ .attr('stroke-width', @options.hoverBorderWidth)
303
+ .attr('opacity', @options.hoverOpacity)
304
+ @xLabel = @r.text(0, (@options.hoverFontSize * 0.75) - @hoverHeight / 2, '')
305
+ .attr('fill', @options.hoverLabelColor)
306
+ .attr('font-weight', 'bold')
307
+ .attr('font-size', @options.hoverFontSize)
308
+ @hoverSet = @r.set()
309
+ @hoverSet.push(@hover)
310
+ @hoverSet.push(@xLabel)
311
+ @yLabels = []
312
+ for i in [0..@series.length-1]
313
+ yLabel = @r.text(0, @options.hoverFontSize * 1.5 * (i + 1.5) - @hoverHeight / 2, '')
314
+ .attr('fill', @options.lineColors[i])
315
+ .attr('font-size', @options.hoverFontSize)
316
+ @yLabels.push(yLabel)
317
+ @hoverSet.push(yLabel)
318
+
319
+ updateHover: (index) =>
320
+ @hoverSet.show()
321
+ @xLabel.attr('text', @columnLabels[index])
322
+ for i in [0..@series.length-1]
323
+ @yLabels[i].attr('text', "#{@seriesLabels[i]}: #{@commas(@series[i][index])}#{@options.units}")
324
+ # recalculate hover box width
325
+ maxLabelWidth = Math.max.apply null, $.map @yLabels, (l) ->
326
+ l.getBBox().width
327
+ maxLabelWidth = Math.max maxLabelWidth, @xLabel.getBBox().width
328
+ @hover.attr 'width', maxLabelWidth + @options.hoverPaddingX * 2
329
+ @hover.attr 'x', -@options.hoverPaddingX - maxLabelWidth / 2
330
+ # move to y pos
331
+ yloc = Math.min.apply null, $.map @series, (s) =>
332
+ @transY s[index]
333
+ if yloc > @hoverHeight + @options.hoverPaddingY * 2 + @options.hoverMargin + @options.marginTop
334
+ yloc = yloc - @hoverHeight / 2 - @options.hoverPaddingY - @options.hoverMargin
335
+ else
336
+ yloc = yloc + @hoverHeight / 2 + @options.hoverPaddingY + @options.hoverMargin
337
+ yloc = Math.max @options.marginTop + @hoverHeight / 2 + @options.hoverPaddingY, yloc
338
+ yloc = Math.min @options.marginTop + @height - @hoverHeight / 2 - @options.hoverPaddingY, yloc
339
+ xloc = Math.min @left + @width - maxLabelWidth / 2 - @options.hoverPaddingX, @columns[index]
340
+ xloc = Math.max @left + maxLabelWidth / 2 + @options.hoverPaddingX, xloc
341
+ @hoverSet.attr 'transform', "t#{xloc},#{yloc}"
342
+
343
+ hideHover: ->
344
+ @hoverSet.hide()
345
+
346
+ hilight: (index) =>
347
+ if @prevHilight isnt null and @prevHilight isnt index
348
+ for i in [0..@seriesPoints.length-1]
349
+ if @seriesPoints[i][@prevHilight]
350
+ @seriesPoints[i][@prevHilight].animate @pointShrink
351
+ if index isnt null and @prevHilight isnt index
352
+ for i in [0..@seriesPoints.length-1]
353
+ if @seriesPoints[i][index]
354
+ @seriesPoints[i][index].animate @pointGrow
355
+ @updateHover index
356
+ @prevHilight = index
357
+ if index is null
358
+ @hideHover()
359
+
360
+ updateHilight: (x) =>
361
+ x -= @el.offset().left
362
+ for hoverIndex in [@hoverMargins.length..0]
363
+ if hoverIndex == 0 || @hoverMargins[hoverIndex - 1] > x
364
+ @hilight hoverIndex
365
+ break
366
+
367
+ measureText: (text, fontSize = 12) ->
368
+ tt = @r.text(100, 100, text).attr('font-size', fontSize)
369
+ ret = tt.getBBox()
370
+ tt.remove()
371
+ return ret
372
+
373
+ parseYear: (date) ->
374
+ if typeof date is 'number'
375
+ return date
376
+ m = date.match /^(\d+) Q(\d)$/
377
+ n = date.match /^(\d+)-(\d+)$/
378
+ o = date.match /^(\d+)-(\d+)-(\d+)$/
379
+ p = date.match /^(\d+) W(\d+)$/
380
+ q = date.match /^(\d+)-(\d+)-(\d+) (\d+):(\d+)$/
381
+ r = date.match /^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+(\.\d+)?)$/
382
+ if m
383
+ new Date(
384
+ parseInt(m[1], 10),
385
+ parseInt(m[2], 10) * 3 - 1,
386
+ 1).getTime()
387
+ else if n
388
+ new Date(
389
+ parseInt(n[1], 10),
390
+ parseInt(n[2], 10) - 1,
391
+ 1).getTime()
392
+ else if o
393
+ new Date(
394
+ parseInt(o[1], 10),
395
+ parseInt(o[2], 10) - 1,
396
+ parseInt(o[3], 10)).getTime()
397
+ else if p
398
+ # calculate number of weeks in year given
399
+ ret = new Date(parseInt(p[1], 10), 0, 1);
400
+ # first thursday in year (ISO 8601 standard)
401
+ if ret.getDay() isnt 4
402
+ ret.setMonth(0, 1 + ((4 - ret.getDay()) + 7) % 7);
403
+ # add weeks
404
+ ret.getTime() + parseInt(p[2], 10) * 604800000
405
+ else if q
406
+ new Date(
407
+ parseInt(q[1], 10),
408
+ parseInt(q[2], 10) - 1,
409
+ parseInt(q[3], 10),
410
+ parseInt(q[4], 10),
411
+ parseInt(q[5], 10)).getTime()
412
+ else if r
413
+ secs = parseFloat(r[6])
414
+ isecs = Math.floor(secs)
415
+ msecs = Math.floor((secs - isecs) * 1000)
416
+ new Date(
417
+ parseInt(r[1], 10),
418
+ parseInt(r[2], 10) - 1,
419
+ parseInt(r[3], 10),
420
+ parseInt(r[4], 10),
421
+ parseInt(r[5], 10),
422
+ isecs,
423
+ msecs).getTime()
424
+ else
425
+ new Date(parseInt(date, 10), 0, 1)
426
+
427
+ # make long numbers prettier by inserting commas
428
+ # eg: commas(1234567) -> '1,234,567'
429
+ #
430
+ commas: (num) ->
431
+ if num is null
432
+ "n/a"
433
+ else
434
+ ret = if num < 0 then "-" else ""
435
+ absnum = Math.abs(num)
436
+ intnum = Math.floor(absnum).toFixed(0)
437
+ ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ',')
438
+ strabsnum = absnum.toString()
439
+ if strabsnum.length > intnum.length
440
+ ret += strabsnum.slice(intnum.length)
441
+ ret
442
+
443
+ window.Morris = Morris
444
+ # vim: set et ts=2 sw=2 sts=2