├── template.html ├── .versions ├── package.js ├── template.js ├── README.md └── c3 └── c3.css /template.html: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /.versions: -------------------------------------------------------------------------------- 1 | babel-compiler@6.24.7 2 | babel-runtime@1.1.1 3 | base64@1.0.10 4 | blaze@2.1.2 5 | blaze-tools@1.0.3 6 | d3js:d3@3.5.8 7 | deps@1.0.12 8 | diff-sequence@1.0.7 9 | ecmascript@0.9.0 10 | ecmascript-runtime@0.5.0 11 | ecmascript-runtime-client@0.5.0 12 | ecmascript-runtime-server@0.5.0 13 | ejson@1.1.0 14 | html-tools@1.0.4 15 | htmljs@1.0.4 16 | id-map@1.0.9 17 | jquery@1.11.10 18 | meteor@1.8.0 19 | minifiers@1.1.5 20 | modules@0.11.2 21 | modules-runtime@0.9.1 22 | mongo-id@1.0.6 23 | observe-sequence@1.0.16 24 | perak:c3@1.0.9 25 | promise@0.10.0 26 | random@1.0.10 27 | reactive-var@1.0.11 28 | spacebars-compiler@1.0.6 29 | templating@1.1.1 30 | tracker@1.1.3 31 | underscore@1.0.10 32 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: 'perak:c3', 3 | summary: "Reactive C3 charting library based on D3", 4 | version: "1.1.0", 5 | git: "https://github.com/perak/meteor-c3.git" 6 | }); 7 | 8 | // Before Meteor 0.9? 9 | if(!Package.onUse) Package.onUse = Package.on_use; 10 | 11 | Package.onUse(function (api) { 12 | if(api.versionsFrom) { 13 | api.versionsFrom('METEOR@0.9.0'); 14 | } 15 | 16 | api.use("d3js:d3@3.5.8", 'client'); 17 | api.use('templating'); 18 | 19 | api.add_files('c3/c3.js', "client"); 20 | api.add_files('c3/c3.css', "client"); 21 | api.add_files('template.html', "client"); 22 | api.add_files('template.js', "client"); 23 | 24 | api.export('c3charts', "client"); 25 | }); 26 | -------------------------------------------------------------------------------- /template.js: -------------------------------------------------------------------------------- 1 | c3charts = {}; 2 | 3 | Template.c3.rendered = function() { 4 | var getData = function() { 5 | // this.data.data.data can only exist if template has been passed a data attribute 6 | // https://github.com/perak/meteor-c3/issues/1 7 | var thisData = UI.getData(); 8 | var data; 9 | if (thisData && thisData.data && thisData.data.data) { 10 | data = thisData.data 11 | data.bindto = thisData.id ? "#"+thisData.id : "#chart" 12 | } else { 13 | data = thisData || { data: { columns: [] }} 14 | } 15 | return data; 16 | }; 17 | 18 | var data = getData() || { columns: [] }; 19 | var chart = c3.generate(data); 20 | 21 | var id = this.data.id || "chart"; 22 | c3charts[id] = chart; 23 | 24 | this.autorun(function (tracker) { 25 | if(UI.getData()) { 26 | chart.load(getData().data || { columns: [] }); 27 | } 28 | }); 29 | }; 30 | 31 | Template.c3.destroyed = function() { 32 | var id = this.data.id || "chart"; 33 | delete c3charts[id]; 34 | }; 35 | 36 | Template.c3.helpers({ 37 | chartId: function() { 38 | return this.id || "chart" 39 | } 40 | }); 41 | 42 | Template.c3.events({ 43 | 44 | }); 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | C3 chart 2 | ======== 3 | 4 | Reactive C3 charting library based on D3 5 | 6 | 7 | Usage 8 | ===== 9 | 10 | Somewhere in your template, add this: 11 | 12 | ```Handlebars 13 | 18 | ``` 19 | 20 | And in .js define helper that returns chart data object as described in c3 docs: 21 | 22 | ```JavaScript 23 | Template.someTemplate.helpers({ 24 | "myChartData": function() { 25 | return { 26 | data: { 27 | columns: [ 28 | ['data1', 30, 200, 100, 400, 150, 250], 29 | ['data2', 130, 100, 140, 200, 150, 50] 30 | ], 31 | type: 'spline' 32 | } 33 | }; 34 | } 35 | }); 36 | ``` 37 | 38 | Of course, instead providing static data, you can reactively show data from collection: 39 | 40 | ```JavaScript 41 | Template.someTemplate.helpers({ 42 | "myChartData": function() { 43 | 44 | theReport = SomeCollection.find().fetch(); 45 | 46 | var theData = ["myData"]; 47 | theData.concat(_.pluck(theReport, "expenses")); 48 | 49 | return { 50 | data: { 51 | columns: [ 52 | theData 53 | ], 54 | type: 'line' 55 | } 56 | }; 57 | } 58 | }); 59 | ``` 60 | In this example, `SomeCollection` contains key `expenses` that will be shown in the graph. 61 | 62 | JSON objects can also be given as data: 63 | 64 | ```JavaScript 65 | // ... 66 | return { 67 | data: { 68 | json: { 69 | data1: [4, 3, 5, 2], 70 | data2: [6, 4, 3, 6] 71 | } 72 | } 73 | } 74 | ``` 75 | 76 | If you want to use **multiple charts on one page** you must specify a unique id, thus the syntax is a bit different: 77 | 78 | ```Handlebars 79 | 84 | ``` 85 | 86 | Access C3 API 87 | ============= 88 | 89 | You can access your chart's c3 variable via global `c3charts` object by referencing your chart's id attribute (please keep id unique). 90 | 91 | ``` 92 | var myChart = c3charts["chart4"]; 93 | ``` 94 | 95 | 96 | Live example 97 | ============ 98 | 99 | You can see live example built with Meteor Kitchen showing radiation level from geiger counter here. 100 | 101 | 102 | Credits 103 | ======= 104 | 105 | - Thanks to @KristerV and @tripflex for fixes and improvements 106 | 107 | 108 | --- 109 | 110 | That's all folks. 111 | 112 | Enjoy! :) 113 | -------------------------------------------------------------------------------- /c3/c3.css: -------------------------------------------------------------------------------- 1 | /*-- Chart --*/ 2 | .c3 svg { 3 | font: 10px sans-serif; 4 | -webkit-tap-highlight-color: transparent; } 5 | 6 | .c3 path, .c3 line { 7 | fill: none; 8 | stroke: #000; } 9 | 10 | .c3 text { 11 | -webkit-user-select: none; 12 | -moz-user-select: none; 13 | user-select: none; } 14 | 15 | .c3-legend-item-tile, 16 | .c3-xgrid-focus, 17 | .c3-ygrid, 18 | .c3-event-rect, 19 | .c3-bars path { 20 | shape-rendering: crispEdges; } 21 | 22 | .c3-chart-arc path { 23 | stroke: #fff; } 24 | 25 | .c3-chart-arc text { 26 | fill: #fff; 27 | font-size: 13px; } 28 | 29 | /*-- Axis --*/ 30 | /*-- Grid --*/ 31 | .c3-grid line { 32 | stroke: #aaa; } 33 | 34 | .c3-grid text { 35 | fill: #aaa; } 36 | 37 | .c3-xgrid, .c3-ygrid { 38 | stroke-dasharray: 3 3; } 39 | 40 | /*-- Text on Chart --*/ 41 | .c3-text.c3-empty { 42 | fill: #808080; 43 | font-size: 2em; } 44 | 45 | /*-- Line --*/ 46 | .c3-line { 47 | stroke-width: 1px; } 48 | 49 | /*-- Point --*/ 50 | .c3-circle._expanded_ { 51 | stroke-width: 1px; 52 | stroke: white; } 53 | 54 | .c3-selected-circle { 55 | fill: white; 56 | stroke-width: 2px; } 57 | 58 | /*-- Bar --*/ 59 | .c3-bar { 60 | stroke-width: 0; } 61 | 62 | .c3-bar._expanded_ { 63 | fill-opacity: 1; 64 | fill-opacity: 0.75; } 65 | 66 | /*-- Focus --*/ 67 | .c3-target.c3-focused { 68 | opacity: 1; } 69 | 70 | .c3-target.c3-focused path.c3-line, .c3-target.c3-focused path.c3-step { 71 | stroke-width: 2px; } 72 | 73 | .c3-target.c3-defocused { 74 | opacity: 0.3 !important; } 75 | 76 | /*-- Region --*/ 77 | .c3-region { 78 | fill: steelblue; 79 | fill-opacity: .1; } 80 | 81 | /*-- Brush --*/ 82 | .c3-brush .extent { 83 | fill-opacity: .1; } 84 | 85 | /*-- Select - Drag --*/ 86 | /*-- Legend --*/ 87 | .c3-legend-item { 88 | font-size: 12px; } 89 | 90 | .c3-legend-item-hidden { 91 | opacity: 0.15; } 92 | 93 | .c3-legend-background { 94 | opacity: 0.75; 95 | fill: white; 96 | stroke: lightgray; 97 | stroke-width: 1; } 98 | 99 | /*-- Title --*/ 100 | .c3-title { 101 | font: 14px sans-serif; } 102 | 103 | /*-- Tooltip --*/ 104 | .c3-tooltip-container { 105 | z-index: 10; } 106 | 107 | .c3-tooltip { 108 | border-collapse: collapse; 109 | border-spacing: 0; 110 | background-color: #fff; 111 | empty-cells: show; 112 | -webkit-box-shadow: 7px 7px 12px -9px #777777; 113 | -moz-box-shadow: 7px 7px 12px -9px #777777; 114 | box-shadow: 7px 7px 12px -9px #777777; 115 | opacity: 0.9; } 116 | 117 | .c3-tooltip tr { 118 | border: 1px solid #CCC; } 119 | 120 | .c3-tooltip th { 121 | background-color: #aaa; 122 | font-size: 14px; 123 | padding: 2px 5px; 124 | text-align: left; 125 | color: #FFF; } 126 | 127 | .c3-tooltip td { 128 | font-size: 13px; 129 | padding: 3px 6px; 130 | background-color: #fff; 131 | border-left: 1px dotted #999; } 132 | 133 | .c3-tooltip td > span { 134 | display: inline-block; 135 | width: 10px; 136 | height: 10px; 137 | margin-right: 6px; } 138 | 139 | .c3-tooltip td.value { 140 | text-align: right; } 141 | 142 | /*-- Area --*/ 143 | .c3-area { 144 | stroke-width: 0; 145 | opacity: 0.2; } 146 | 147 | /*-- Arc --*/ 148 | .c3-chart-arcs-title { 149 | dominant-baseline: middle; 150 | font-size: 1.3em; } 151 | 152 | .c3-chart-arcs .c3-chart-arcs-background { 153 | fill: #e0e0e0; 154 | stroke: none; } 155 | 156 | .c3-chart-arcs .c3-chart-arcs-gauge-unit { 157 | fill: #000; 158 | font-size: 16px; } 159 | 160 | .c3-chart-arcs .c3-chart-arcs-gauge-max { 161 | fill: #777; } 162 | 163 | .c3-chart-arcs .c3-chart-arcs-gauge-min { 164 | fill: #777; } 165 | 166 | .c3-chart-arc .c3-gauge-value { 167 | fill: #000; 168 | /* font-size: 28px !important;*/ } 169 | 170 | .c3-chart-arc.c3-target g path { 171 | opacity: 1; } 172 | 173 | .c3-chart-arc.c3-target.c3-focused g path { 174 | opacity: 1; } 175 | --------------------------------------------------------------------------------