├── examples ├── lib │ ├── example.js │ └── example.css ├── _template.html ├── donut.html ├── bar-no-axes.html ├── goals.html ├── stacked_bars.html ├── dst.html ├── area-as-line.html ├── bar.html ├── donut-formatter.html ├── area.html ├── donut-colors.html ├── negative.html ├── decimal-custom-hover.html ├── bar-highlight-hover.html ├── non-date.html ├── bar-colors.html ├── updating.html ├── years.html ├── days.html ├── months-no-smooth.html ├── no-grid.html ├── diagonal-xlabels.html ├── diagonal-xlabels-bar.html ├── timestamps.html ├── resize.html ├── non-continuous.html ├── weeks.html ├── quarters.html └── events.html ├── spec ├── viz │ ├── exemplary │ │ ├── area0.png │ │ ├── bar0.png │ │ ├── line0.png │ │ └── stacked_bar0.png │ ├── run.sh │ ├── test.html │ ├── examples.js │ └── visual_specs.js ├── support │ └── placeholder.coffee ├── lib │ ├── grid │ │ ├── y_label_format_spec.coffee │ │ ├── auto_grid_lines_spec.coffee │ │ └── set_data_spec.coffee │ ├── pad_spec.coffee │ ├── commas_spec.coffee │ ├── bar │ │ ├── colours.coffee │ │ └── bar_spec.coffee │ ├── parse_time_spec.coffee │ ├── area │ │ └── area_spec.coffee │ ├── hover_spec.coffee │ ├── donut │ │ └── donut_spec.coffee │ ├── label_series_spec.coffee │ └── line │ │ └── line_spec.coffee └── specs.html ├── .gitignore ├── bower.json ├── morris.css ├── bower.travis.json ├── less └── morris.core.less ├── .travis.yml ├── package.json ├── lib ├── morris.coffee ├── morris.hover.coffee ├── morris.area.coffee ├── morris.donut.coffee ├── morris.bar.coffee ├── morris.line.coffee └── morris.grid.coffee ├── Gruntfile.js ├── README.md └── morris.min.js /examples/lib/example.js: -------------------------------------------------------------------------------- 1 | $(function () { 2 | eval($('#code').text()); 3 | prettyPrint(); 4 | }); -------------------------------------------------------------------------------- /spec/viz/exemplary/area0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arch/morris.js/master/spec/viz/exemplary/area0.png -------------------------------------------------------------------------------- /spec/viz/exemplary/bar0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arch/morris.js/master/spec/viz/exemplary/bar0.png -------------------------------------------------------------------------------- /spec/viz/exemplary/line0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arch/morris.js/master/spec/viz/exemplary/line0.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | node_modules/ 3 | spec/viz/output/ 4 | spec/viz/diff/ 5 | bower_components 6 | .idea 7 | -------------------------------------------------------------------------------- /spec/viz/exemplary/stacked_bar0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arch/morris.js/master/spec/viz/exemplary/stacked_bar0.png -------------------------------------------------------------------------------- /spec/support/placeholder.coffee: -------------------------------------------------------------------------------- 1 | beforeEach -> 2 | placeholder = $('
') 3 | $('#test').append(placeholder) 4 | 5 | afterEach -> 6 | $('#test').empty() 7 | -------------------------------------------------------------------------------- /examples/lib/example.css: -------------------------------------------------------------------------------- 1 | body { 2 | width: 800px; 3 | margin: 0 auto; 4 | } 5 | #graph { 6 | width: 800px; 7 | height: 250px; 8 | margin: 20px auto 0 auto; 9 | } 10 | pre { 11 | height: 250px; 12 | overflow: auto; 13 | } 14 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "morris.js", 3 | "main": [ 4 | "./morris.js", 5 | "./morris.css" 6 | ], 7 | "dependencies": { 8 | "jquery": ">= 1.7.0", 9 | "raphael": ">= 2.0" 10 | }, 11 | "devDependencies": { 12 | "mocha": "~1.17.1", 13 | "chai": "~1.9.0", 14 | "chai-jquery": "~1.2.1", 15 | "sinon": "http://sinonjs.org/releases/sinon-1.8.1.js", 16 | "sinon-chai": "~2.5.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /morris.css: -------------------------------------------------------------------------------- 1 | .morris-hover{position:absolute;z-index:1000}.morris-hover.morris-default-style{border-radius:10px;padding:6px;color:#666;background:rgba(255,255,255,0.8);border:solid 2px rgba(230,230,230,0.8);font-family:sans-serif;font-size:12px;text-align:center}.morris-hover.morris-default-style .morris-hover-row-label{font-weight:bold;margin:0.25em 0} 2 | .morris-hover.morris-default-style .morris-hover-point{white-space:nowrap;margin:0.1em 0} 3 | -------------------------------------------------------------------------------- /bower.travis.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "morris.js", 3 | "version": "0.5.1", 4 | "main": [ 5 | "./morris.js", 6 | "./morris.css" 7 | ], 8 | "dependencies": { 9 | "jquery": "JQUERY", 10 | "raphael": "RAPHAEL" 11 | }, 12 | "devDependencies": { 13 | "mocha": "~1.17.1", 14 | "chai": "~1.9.0", 15 | "chai-jquery": "~1.2.1", 16 | "sinon": "http://sinonjs.org/releases/sinon-1.8.1.js", 17 | "sinon-chai": "~2.5.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /spec/lib/grid/y_label_format_spec.coffee: -------------------------------------------------------------------------------- 1 | describe 'Morris.Grid#yLabelFormat', -> 2 | 3 | it 'should use custom formatter for y labels', -> 4 | formatter = (label) -> 5 | flabel = parseFloat(label) / 1000 6 | "#{flabel.toFixed(1)}k" 7 | line = Morris.Line 8 | element: 'graph' 9 | data: [{x: 1, y: 1500}, {x: 2, y: 2500}] 10 | xkey: 'x' 11 | ykeys: ['y'] 12 | labels: ['dontcare'] 13 | preUnits: "$" 14 | yLabelFormat: formatter 15 | line.yLabelFormat(1500).should.equal "1.5k" 16 | -------------------------------------------------------------------------------- /spec/viz/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # visual_specs.js creates output in output/XXX.png 4 | phantomjs visual_specs.js 5 | 6 | # clear out old diffs 7 | mkdir -p diff 8 | rm -f diff/* 9 | 10 | # generate diffs 11 | PASS=1 12 | for i in exemplary/*.png 13 | do 14 | FN=`basename $i` 15 | perceptualdiff $i output/$FN -output diff/$FN 16 | if [ $? -eq 0 ] 17 | then 18 | echo "OK: $FN" 19 | else 20 | echo "FAIL: $FN" 21 | PASS=0 22 | fi 23 | done 24 | 25 | # pass / fail 26 | if [ $PASS -eq 1 ] 27 | then 28 | echo "Success." 29 | else 30 | echo "Failed." 31 | exit 1 32 | fi 33 | -------------------------------------------------------------------------------- /less/morris.core.less: -------------------------------------------------------------------------------- 1 | .morris-hover { 2 | position: absolute; 3 | z-index: 1000; 4 | 5 | &.morris-default-style { 6 | border-radius: 10px; 7 | padding: 6px; 8 | color: #666; 9 | background: rgba(255, 255, 255, 0.8); 10 | border: solid 2px rgba(230, 230, 230, 0.8); 11 | 12 | font-family: sans-serif; 13 | font-size: 12px; 14 | text-align: center; 15 | 16 | .morris-hover-row-label { 17 | font-weight: bold; 18 | margin: 0.25em 0; 19 | } 20 | 21 | .morris-hover-point { 22 | white-space: nowrap; 23 | margin: 0.1em 0; 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /spec/lib/pad_spec.coffee: -------------------------------------------------------------------------------- 1 | describe '#pad', -> 2 | 3 | it 'should pad numbers', -> 4 | Morris.pad2(0).should.equal("00") 5 | Morris.pad2(1).should.equal("01") 6 | Morris.pad2(2).should.equal("02") 7 | Morris.pad2(3).should.equal("03") 8 | Morris.pad2(4).should.equal("04") 9 | Morris.pad2(5).should.equal("05") 10 | Morris.pad2(6).should.equal("06") 11 | Morris.pad2(7).should.equal("07") 12 | Morris.pad2(8).should.equal("08") 13 | Morris.pad2(9).should.equal("09") 14 | Morris.pad2(10).should.equal("10") 15 | Morris.pad2(12).should.equal("12") 16 | Morris.pad2(34).should.equal("34") 17 | Morris.pad2(123).should.equal("123") -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 0.10 4 | before_script: 5 | - "npm install -g grunt-cli" 6 | - "npm install" 7 | - "cp -f bower.travis.json bower.json" 8 | - 'sed -i -e "s/JQUERY/$JQUERY/" bower.json' 9 | - 'sed -i -e "s/RAPHAEL/$RAPHAEL/" bower.json' 10 | - "bower install" 11 | env: 12 | - JQUERY="~> 1.7.0" RAPHAEL="~> 2.0.0" 13 | - JQUERY="~> 1.8.0" RAPHAEL="~> 2.0.0" 14 | - JQUERY="~> 1.9.0" RAPHAEL="~> 2.0.0" 15 | - JQUERY="~> 2.0.0" RAPHAEL="~> 2.0.0" 16 | - JQUERY="~> 2.1.0" RAPHAEL="~> 2.0.0" 17 | - JQUERY="~> 1.8.0" RAPHAEL="~> 2.1.0" 18 | - JQUERY="~> 1.9.0" RAPHAEL="~> 2.1.0" 19 | - JQUERY="~> 2.0.0" RAPHAEL="~> 2.1.0" 20 | - JQUERY="~> 2.1.0" RAPHAEL="~> 2.1.0" 21 | -------------------------------------------------------------------------------- /examples/_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |15 | // Insert code here: 16 | // it'll get eval()-ed and prettyprinted. 17 |18 | 19 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "morris.js", 3 | "version": "0.5.1", 4 | "homepage": "http://morrisjs.github.com/morris.js", 5 | "license": "BSD-2-Clause", 6 | "description": "Easy, pretty charts", 7 | "author": { 8 | "name": "Olly Smith", 9 | "email": "olly@oesmith.co.uk" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git://github.com/morrisjs/morris.js.git" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/morrisjs/morris.js/issues" 17 | }, 18 | "devDependencies": { 19 | "matchdep": "~0.1.2", 20 | "grunt": "~0.4.1", 21 | "grunt-mocha": "~0.4.10", 22 | "grunt-contrib-concat": "~0.3.0", 23 | "grunt-contrib-coffee": "~0.7.0", 24 | "grunt-contrib-uglify": "~0.2.4", 25 | "grunt-contrib-less": "~0.7.0", 26 | "grunt-contrib-watch": "~0.5.3", 27 | "grunt-shell": "~0.5.0", 28 | "bower": "1.3.8" 29 | }, 30 | "scripts": { 31 | "test": "grunt concat coffee mocha" 32 | }, 33 | "engines": { 34 | "node": ">=0.8 <0.11" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /spec/viz/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 20 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /examples/donut.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
16 | Morris.Donut({
17 | element: 'graph',
18 | data: [
19 | {value: 70, label: 'foo'},
20 | {value: 15, label: 'bar'},
21 | {value: 10, label: 'baz'},
22 | {value: 5, label: 'A really really long label'}
23 | ],
24 | formatter: function (x) { return x + "%"}
25 | }).on('click', function(i, row){
26 | console.log(i, row);
27 | });
28 |
29 |
30 |
--------------------------------------------------------------------------------
/examples/bar-no-axes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 | // Use Morris.Bar
17 | Morris.Bar({
18 | element: 'graph',
19 | axes: false,
20 | data: [
21 | {x: '2011 Q1', y: 3, z: 2, a: 3},
22 | {x: '2011 Q2', y: 2, z: null, a: 1},
23 | {x: '2011 Q3', y: 0, z: 2, a: 4},
24 | {x: '2011 Q4', y: 2, z: 4, a: 3}
25 | ],
26 | xkey: 'x',
27 | ykeys: ['y', 'z', 'a'],
28 | labels: ['Y', 'Z', 'A']
29 | });
30 |
31 |
32 |
--------------------------------------------------------------------------------
/examples/goals.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 | var decimal_data = [];
17 | for (var x = 0; x <= 360; x += 10) {
18 | decimal_data.push({
19 | x: x,
20 | y: Math.sin(Math.PI * x / 180).toFixed(4)
21 | });
22 | }
23 | window.m = Morris.Line({
24 | element: 'graph',
25 | data: decimal_data,
26 | xkey: 'x',
27 | ykeys: ['y'],
28 | labels: ['sin(x)'],
29 | parseTime: false,
30 | goals: [-1, 0, 1]
31 | });
32 |
33 |
34 |
--------------------------------------------------------------------------------
/examples/stacked_bars.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 | // Use Morris.Bar
17 | Morris.Bar({
18 | element: 'graph',
19 | data: [
20 | {x: '2011 Q1', y: 3, z: 2, a: 3},
21 | {x: '2011 Q2', y: 2, z: null, a: 1},
22 | {x: '2011 Q3', y: 0, z: 2, a: 4},
23 | {x: '2011 Q4', y: 2, z: 4, a: 3}
24 | ],
25 | xkey: 'x',
26 | ykeys: ['y', 'z', 'a'],
27 | labels: ['Y', 'Z', 'A'],
28 | stacked: true
29 | });
30 |
31 |
32 |
--------------------------------------------------------------------------------
/examples/dst.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 | // This crosses a DST boundary in the UK.
17 | Morris.Area({
18 | element: 'graph',
19 | data: [
20 | {x: '2013-03-30 22:00:00', y: 3, z: 3},
21 | {x: '2013-03-31 00:00:00', y: 2, z: 0},
22 | {x: '2013-03-31 02:00:00', y: 0, z: 2},
23 | {x: '2013-03-31 04:00:00', y: 4, z: 4}
24 | ],
25 | xkey: 'x',
26 | ykeys: ['y', 'z'],
27 | labels: ['Y', 'Z']
28 | });
29 |
30 |
31 |
--------------------------------------------------------------------------------
/examples/area-as-line.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 | // Use Morris.Area instead of Morris.Line
17 | Morris.Area({
18 | element: 'graph',
19 | behaveLikeLine: true,
20 | data: [
21 | {x: '2011 Q1', y: 3, z: 3},
22 | {x: '2011 Q2', y: 2, z: 1},
23 | {x: '2011 Q3', y: 2, z: 4},
24 | {x: '2011 Q4', y: 3, z: 3}
25 | ],
26 | xkey: 'x',
27 | ykeys: ['y', 'z'],
28 | labels: ['Y', 'Z']
29 | });
30 |
31 |
32 |
--------------------------------------------------------------------------------
/examples/bar.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 | // Use Morris.Bar
17 | Morris.Bar({
18 | element: 'graph',
19 | data: [
20 | {x: '2011 Q1', y: 3, z: 2, a: 3},
21 | {x: '2011 Q2', y: 2, z: null, a: 1},
22 | {x: '2011 Q3', y: 0, z: 2, a: 4},
23 | {x: '2011 Q4', y: 2, z: 4, a: 3}
24 | ],
25 | xkey: 'x',
26 | ykeys: ['y', 'z', 'a'],
27 | labels: ['Y', 'Z', 'A']
28 | }).on('click', function(i, row){
29 | console.log(i, row);
30 | });
31 |
32 |
33 |
--------------------------------------------------------------------------------
/examples/donut-formatter.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 | Morris.Donut({
17 | element: 'graph',
18 | data: [
19 | {value: 70, label: 'foo', formatted: 'at least 70%' },
20 | {value: 15, label: 'bar', formatted: 'approx. 15%' },
21 | {value: 10, label: 'baz', formatted: 'approx. 10%' },
22 | {value: 5, label: 'A really really long label', formatted: 'at most 5%' }
23 | ],
24 | formatter: function (x, data) { return data.formatted; }
25 | });
26 |
27 |
28 |
--------------------------------------------------------------------------------
/lib/morris.coffee:
--------------------------------------------------------------------------------
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 |
17 | fire: (name, args...) ->
18 | if @handlers? and @handlers[name]?
19 | for handler in @handlers[name]
20 | handler(args...)
21 |
22 | # Make long numbers prettier by inserting commas.
23 | #
24 | # @example
25 | # Morris.commas(1234567) -> '1,234,567'
26 | Morris.commas = (num) ->
27 | if num?
28 | ret = if num < 0 then "-" else ""
29 | absnum = Math.abs(num)
30 | intnum = Math.floor(absnum).toFixed(0)
31 | ret += intnum.replace(/(?=(?:\d{3})+$)(?!^)/g, ',')
32 | strabsnum = absnum.toString()
33 | if strabsnum.length > intnum.length
34 | ret += strabsnum.slice(intnum.length)
35 | ret
36 | else
37 | '-'
38 |
39 | # Zero-pad numbers to two characters wide.
40 | #
41 | # @example
42 | # Morris.pad2(1) -> '01'
43 | Morris.pad2 = (number) -> (if number < 10 then '0' else '') + number
44 |
--------------------------------------------------------------------------------
/examples/area.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 | // Use Morris.Area instead of Morris.Line
17 | Morris.Area({
18 | element: 'graph',
19 | data: [
20 | {x: '2010 Q4', y: 3, z: 7},
21 | {x: '2011 Q1', y: 3, z: 4},
22 | {x: '2011 Q2', y: null, z: 1},
23 | {x: '2011 Q3', y: 2, z: 5},
24 | {x: '2011 Q4', y: 8, z: 2},
25 | {x: '2012 Q1', y: 4, z: 4}
26 | ],
27 | xkey: 'x',
28 | ykeys: ['y', 'z'],
29 | labels: ['Y', 'Z']
30 | }).on('click', function(i, row){
31 | console.log(i, row);
32 | });
33 |
34 |
35 |
--------------------------------------------------------------------------------
/spec/lib/grid/auto_grid_lines_spec.coffee:
--------------------------------------------------------------------------------
1 | describe 'Morris.Grid#autoGridLines', ->
2 |
3 | beforeEach ->
4 | @subject = Morris.Grid.prototype.autoGridLines
5 |
6 | it 'should draw at fixed intervals', ->
7 | @subject(0, 4, 5).should.deep.equal [0, 1, 2, 3, 4]
8 | @subject(0, 400, 5).should.deep.equal [0, 100, 200, 300, 400]
9 |
10 | it 'should pick intervals that show significant numbers', ->
11 | @subject(102, 499, 5).should.deep.equal [100, 200, 300, 400, 500]
12 |
13 | it 'should draw zero when it falls within [ymin..ymax]', ->
14 | @subject(-100, 300, 5).should.deep.equal [-100, 0, 100, 200, 300]
15 | @subject(-50, 350, 5).should.deep.equal [-125, 0, 125, 250, 375]
16 | @subject(-400, 400, 5).should.deep.equal [-400, -200, 0, 200, 400]
17 | @subject(100, 500, 5).should.deep.equal [100, 200, 300, 400, 500]
18 | @subject(-500, -100, 5).should.deep.equal [-500, -400, -300, -200, -100]
19 |
20 | it 'should generate decimal labels to 2 significant figures', ->
21 | @subject(0, 1, 5).should.deep.equal [0, 0.25, 0.5, 0.75, 1]
22 | @subject(0.1, 0.5, 5).should.deep.equal [0.1, 0.2, 0.3, 0.4, 0.5]
23 |
24 | it 'should use integer intervals for intervals larger than 1', ->
25 | @subject(0, 9, 5).should.deep.equal [0, 3, 6, 9, 12]
26 |
--------------------------------------------------------------------------------
/examples/donut-colors.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
19 | Morris.Donut({
20 | element: 'graph',
21 | data: [
22 | {value: 70, label: 'foo'},
23 | {value: 15, label: 'bar'},
24 | {value: 10, label: 'baz'},
25 | {value: 5, label: 'A really really long label'}
26 | ],
27 | backgroundColor: '#ccc',
28 | labelColor: '#060',
29 | colors: [
30 | '#0BA462',
31 | '#39B580',
32 | '#67C69D',
33 | '#95D7BB'
34 | ],
35 | formatter: function (x) { return x + "%"}
36 | });
37 |
38 |
39 |
--------------------------------------------------------------------------------
/examples/negative.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 | var neg_data = [
17 | {"period": "2011-08-12", "a": 100},
18 | {"period": "2011-03-03", "a": 75},
19 | {"period": "2010-08-08", "a": 50},
20 | {"period": "2010-05-10", "a": 25},
21 | {"period": "2010-03-14", "a": 0},
22 | {"period": "2010-01-10", "a": -25},
23 | {"period": "2009-12-10", "a": -50},
24 | {"period": "2009-10-07", "a": -75},
25 | {"period": "2009-09-25", "a": -100}
26 | ];
27 | Morris.Line({
28 | element: 'graph',
29 | data: neg_data,
30 | xkey: 'period',
31 | ykeys: ['a'],
32 | labels: ['Series A'],
33 | units: '%'
34 | });
35 |
36 |
37 |
--------------------------------------------------------------------------------
/examples/decimal-custom-hover.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 | var decimal_data = [];
17 | for (var x = 0; x <= 360; x += 10) {
18 | decimal_data.push({
19 | x: x,
20 | y: 1.5 + 1.5 * Math.sin(Math.PI * x / 180).toFixed(4)
21 | });
22 | }
23 | window.m = Morris.Line({
24 | element: 'graph',
25 | data: decimal_data,
26 | xkey: 'x',
27 | ykeys: ['y'],
28 | labels: ['sin(x)'],
29 | parseTime: false,
30 | hoverCallback: function (index, options, default_content, row) {
31 | return default_content.replace("sin(x)", "1.5 + 1.5 sin(" + row.x + ")");
32 | },
33 | xLabelMargin: 10,
34 | integerYLabels: true
35 | });
36 |
37 |
38 |
--------------------------------------------------------------------------------
/examples/bar-highlight-hover.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
17 |
20 | Morris.Bar({
21 | element: 'graph',
22 | data: [
23 | {x: 'One', y: 3, z: 2, a: 1, q: 2},
24 | {x: 'Two', y: 2, z: null, a: 1, q: 2},
25 | {x: 'Three', y: 0, z: 2, a: 1, q: 2},
26 | {x: 'Four', y: 2, z: 4, a: 1, q: 2}
27 | ],
28 | xkey: 'x',
29 | ykeys: ['y', 'z'],
30 | labels: [],
31 | barColors: ['#1fbba6', '#f8aa33', '#4da74d', '#afd8f8', '#edc240', '#cb4b4b', '#9440ed'],
32 | barOpacity: 0.5,
33 | resize: true,
34 | gridTextColor: '#666',
35 | grid: false
36 |
37 | });
38 |
39 |
40 |
--------------------------------------------------------------------------------
/examples/non-date.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 | var day_data = [
17 | {"elapsed": "I", "value": 34},
18 | {"elapsed": "II", "value": 24},
19 | {"elapsed": "III", "value": 3},
20 | {"elapsed": "IV", "value": 12},
21 | {"elapsed": "V", "value": 13},
22 | {"elapsed": "VI", "value": 22},
23 | {"elapsed": "VII", "value": 5},
24 | {"elapsed": "VIII", "value": 26},
25 | {"elapsed": "IX", "value": 12},
26 | {"elapsed": "X", "value": 19}
27 | ];
28 | Morris.Line({
29 | element: 'graph',
30 | data: day_data,
31 | xkey: 'elapsed',
32 | ykeys: ['value'],
33 | labels: ['value'],
34 | parseTime: false
35 | });
36 |
37 |
38 |
--------------------------------------------------------------------------------
/examples/bar-colors.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
16 | // Use Morris.Bar
17 | Morris.Bar({
18 | element: 'graph',
19 | data: [
20 | {x: '2011 Q1', y: 0},
21 | {x: '2011 Q2', y: 1},
22 | {x: '2011 Q3', y: 2},
23 | {x: '2011 Q4', y: 3},
24 | {x: '2012 Q1', y: 4},
25 | {x: '2012 Q2', y: 5},
26 | {x: '2012 Q3', y: 6},
27 | {x: '2012 Q4', y: 7},
28 | {x: '2013 Q1', y: 8}
29 | ],
30 | xkey: 'x',
31 | ykeys: ['y'],
32 | labels: ['Y'],
33 | barColors: function (row, series, type) {
34 | if (type === 'bar') {
35 | var red = Math.ceil(255 * row.y / this.ymax);
36 | return 'rgb(' + red + ',0,0)';
37 | }
38 | else {
39 | return '#000';
40 | }
41 | }
42 | });
43 |
44 |
45 |
--------------------------------------------------------------------------------
/lib/morris.hover.coffee:
--------------------------------------------------------------------------------
1 | class Morris.Hover
2 | # Displays contextual information in a floating HTML div.
3 |
4 | @defaults:
5 | class: 'morris-hover morris-default-style'
6 |
7 | constructor: (options = {}) ->
8 | @options = $.extend {}, Morris.Hover.defaults, options
9 | @el = $ ""
10 | @el.hide()
11 | @options.parent.append(@el)
12 |
13 | update: (html, x, y, centre_y) ->
14 | if not html
15 | @hide()
16 | else
17 | @html(html)
18 | @show()
19 | @moveTo(x, y, centre_y)
20 |
21 | html: (content) ->
22 | @el.html(content)
23 |
24 | moveTo: (x, y, centre_y) ->
25 | parentWidth = @options.parent.innerWidth()
26 | parentHeight = @options.parent.innerHeight()
27 | hoverWidth = @el.outerWidth()
28 | hoverHeight = @el.outerHeight()
29 | left = Math.min(Math.max(0, x - hoverWidth / 2), parentWidth - hoverWidth)
30 | if y?
31 | if centre_y is true
32 | top = y - hoverHeight / 2
33 | if top < 0
34 | top = 0
35 | else
36 | top = y - hoverHeight - 10
37 | if top < 0
38 | top = y + 10
39 | if top + hoverHeight > parentHeight
40 | top = parentHeight / 2 - hoverHeight / 2
41 | else
42 | top = parentHeight / 2 - hoverHeight / 2
43 | @el.css(left: left + "px", top: parseInt(top) + "px")
44 |
45 | show: ->
46 | @el.show()
47 |
48 | hide: ->
49 | @el.hide()
50 |
--------------------------------------------------------------------------------
/spec/lib/commas_spec.coffee:
--------------------------------------------------------------------------------
1 | describe '#commas', ->
2 |
3 | it 'should insert commas into long numbers', ->
4 | # zero
5 | Morris.commas(0).should.equal("0")
6 |
7 | # positive integers
8 | Morris.commas(1).should.equal("1")
9 | Morris.commas(12).should.equal("12")
10 | Morris.commas(123).should.equal("123")
11 | Morris.commas(1234).should.equal("1,234")
12 | Morris.commas(12345).should.equal("12,345")
13 | Morris.commas(123456).should.equal("123,456")
14 | Morris.commas(1234567).should.equal("1,234,567")
15 |
16 | # negative integers
17 | Morris.commas(-1).should.equal("-1")
18 | Morris.commas(-12).should.equal("-12")
19 | Morris.commas(-123).should.equal("-123")
20 | Morris.commas(-1234).should.equal("-1,234")
21 | Morris.commas(-12345).should.equal("-12,345")
22 | Morris.commas(-123456).should.equal("-123,456")
23 | Morris.commas(-1234567).should.equal("-1,234,567")
24 |
25 | # positive decimals
26 | Morris.commas(1.2).should.equal("1.2")
27 | Morris.commas(12.34).should.equal("12.34")
28 | Morris.commas(123.456).should.equal("123.456")
29 | Morris.commas(1234.56).should.equal("1,234.56")
30 |
31 | # negative decimals
32 | Morris.commas(-1.2).should.equal("-1.2")
33 | Morris.commas(-12.34).should.equal("-12.34")
34 | Morris.commas(-123.456).should.equal("-123.456")
35 | Morris.commas(-1234.56).should.equal("-1,234.56")
36 |
37 | # null
38 | Morris.commas(null).should.equal('-')
39 |
--------------------------------------------------------------------------------
/spec/lib/bar/colours.coffee:
--------------------------------------------------------------------------------
1 | describe 'Morris.Bar#colorFor', ->
2 |
3 | defaults =
4 | element: 'graph'
5 | data: [{x: 'foo', y: 2, z: 3}, {x: 'bar', y: 4, z: 6}]
6 | xkey: 'x'
7 | ykeys: ['y', 'z']
8 | labels: ['Y', 'Z']
9 |
10 | it 'should fetch colours from an array', ->
11 | chart = Morris.Bar $.extend {}, defaults, barColors: ['#f00', '#0f0', '#00f']
12 | chart.colorFor(chart.data[0], 0, 'bar').should.equal '#f00'
13 | chart.colorFor(chart.data[0], 0, 'hover').should.equal '#f00'
14 | chart.colorFor(chart.data[0], 1, 'bar').should.equal '#0f0'
15 | chart.colorFor(chart.data[0], 1, 'hover').should.equal '#0f0'
16 | chart.colorFor(chart.data[0], 2, 'bar').should.equal '#00f'
17 | chart.colorFor(chart.data[0], 2, 'hover').should.equal '#00f'
18 | chart.colorFor(chart.data[0], 3, 'bar').should.equal '#f00'
19 | chart.colorFor(chart.data[0], 4, 'hover').should.equal '#0f0'
20 |
21 | it 'should defer to a callback', ->
22 | stub = sinon.stub().returns '#f00'
23 | chart = Morris.Bar $.extend {}, defaults, barColors: stub
24 | stub.reset()
25 |
26 | chart.colorFor(chart.data[0], 0, 'bar')
27 | stub.should.have.been.calledWith(
28 | {x:0, y:2, label:'foo', src: { x: "foo", y: 2, z: 3 }},
29 | {index:0, key:'y', label:'Y'},
30 | 'bar')
31 |
32 | chart.colorFor(chart.data[0], 1, 'hover')
33 | stub.should.have.been.calledWith(
34 | {x:0, y:3, label:'foo', src: { x: "foo", y: 2, z: 3 }},
35 | {index:1, key:'z', label:'Z'},
36 | 'hover')
37 |
--------------------------------------------------------------------------------
/spec/specs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |