├── .gitignore ├── LICENSE ├── README.md ├── doc └── screenshot.png ├── lib └── jutsu.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Joel Auterson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jutsu 2 | 3 | Jutsu is a very simple graphing library for the web, with support for [Smolder](https://github.com/JoelOtter/smolder) built-in. 4 | 5 | This means it can attempt to handle any data that's thrown at it, regardless of structure, and produce a graph. 6 | 7 | To see examples, and read the documentation, check out [this notebook](http://www.joelotter.com/jutsu). 8 | 9 |  10 | 11 | ## Installation 12 | 13 | `npm install jutsu` 14 | 15 | Jutsu works fine on its own, but to get the automatic data reshaping, you'll need Smolder too. 16 | 17 | `npm install smolder` 18 | 19 | ## Usage 20 | 21 | ```javascript 22 | var Smolder = require('smolder'); 23 | var Jutsu = require('jutsu'); 24 | 25 | // graphElement is the DOM element where we want to put the graphs. 26 | var graphs = Smolder(Jutsu(graphElement)); 27 | 28 | // We can then create a graph using, e.g.: 29 | graphs.pieChart(data); 30 | ``` 31 | 32 | ## Graphs 33 | 34 | The optional parameter **[hints]** is a string, or array of strings, which tells Jutsu which part of the data we are interested in. 35 | 36 | ### `pieChart(data, [hints])` 37 | 38 | ### `barChart(data, xLabel, yLabel, [hints])` 39 | 40 | ### `lineChart(data, xLabel, yLabel, [hints])` 41 | 42 | ### `scatterPlot(data, xLabel, yLabel, [hints])` 43 | 44 | Each function will return the reshaped data. 45 | 46 | ## Questions/feedback? 47 | 48 | If you have any issues, please file an issue. If your problem is with the way the data is reshaped, please file your issue over at [Reshaper](http://github.com/JoelOtter/reshaper), the library that does all the heavy lifting. 49 | 50 | Jutsu is a part of my Master's project at Imperial College London, and as part of my evaluation I'd really love to hear any feedback you might have. Feel free to [shoot me an email](mailto:joel.auterson@gmail.com). 51 | -------------------------------------------------------------------------------- /doc/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JoelOtter/jutsu/1c17ed518470a6c8b944ac4ca382e207a2da08b9/doc/screenshot.png -------------------------------------------------------------------------------- /lib/jutsu.js: -------------------------------------------------------------------------------- 1 | var nv = require('nvd3'); 2 | 3 | var svgCounter = 0; 4 | 5 | function _createSvg (domElement) { 6 | var id = 'jutsu-graph-' + svgCounter++; 7 | d3.select(domElement).append('svg') 8 | .attr('id', id) 9 | .attr('width', '100%') 10 | .attr('height', '600'); 11 | return id; 12 | } 13 | 14 | function _pieChart (domElement, data) { 15 | var id = _createSvg(domElement); 16 | 17 | nv.addGraph(function() { 18 | var chart = nv.models.pieChart() 19 | .x(function(d) { return d.label }) 20 | .y(function(d) { return d.value }) 21 | .showLabels(false); 22 | 23 | d3.select('#' + id) 24 | .datum(data) 25 | .transition().duration(500) 26 | .call(chart); 27 | 28 | nv.utils.windowResize(chart.update); 29 | 30 | return chart; 31 | }); 32 | return data; 33 | } 34 | 35 | function _barChart (domElement, data, xLabel, yLabel) { 36 | var id = _createSvg(domElement); 37 | 38 | nv.addGraph(function() { 39 | var chart = nv.models.discreteBarChart() 40 | .margin({bottom: 65}) 41 | .x(function(d) { return d.label }) 42 | .y(function(d) { return d.value }) 43 | .staggerLabels(true); 44 | 45 | chart.xAxis.axisLabel(xLabel); 46 | chart.yAxis.axisLabel(yLabel); 47 | chart.yAxis.tickFormat(d3.format('')); 48 | 49 | d3.select('#' + id) 50 | .datum([{values: data}]) 51 | .transition().duration(500) 52 | .call(chart); 53 | 54 | nv.utils.windowResize(chart.update); 55 | 56 | return chart; 57 | }); 58 | 59 | return data; 60 | } 61 | 62 | function _scatterPlot (domElement, data, xLabel, yLabel) { 63 | var id = _createSvg(domElement); 64 | 65 | nv.addGraph(function() { 66 | var chart = nv.models.scatterChart() 67 | .showDistX(true) 68 | .showDistY(true) 69 | .showLegend(false) 70 | .color(d3.scale.category10().range()); 71 | 72 | chart.xAxis.axisLabel(xLabel); 73 | chart.yAxis.axisLabel(yLabel); 74 | 75 | chart.tooltip.contentGenerator(function(graph) { 76 | return '
' + xLabel + ': ' + graph.point.x + '
' + 78 | '' + yLabel + ': ' + graph.point.y + '
'; 79 | }); 80 | 81 | d3.select('#' + id) 82 | .datum([{key: '', values: data}]) 83 | .transition().duration(500) 84 | .call(chart); 85 | 86 | nv.utils.windowResize(chart.update); 87 | return chart; 88 | }); 89 | 90 | return data; 91 | } 92 | 93 | function _lineChart (domElement, data, xLabel, yLabel) { 94 | data.sort(function(a, b) { return a.x - b.x; }); 95 | var id = _createSvg(domElement); 96 | 97 | nv.addGraph(function() { 98 | var chart = nv.models.lineChart() 99 | .useInteractiveGuideline(true) 100 | .showLegend(false); 101 | 102 | chart.xAxis.axisLabel(xLabel); 103 | chart.yAxis.axisLabel(yLabel); 104 | 105 | chart.interactiveLayer.tooltip.contentGenerator(function(graph) { 106 | var data = graph.series[0].data; 107 | return '' + xLabel + ': ' + data.x + '
' + 109 | '' + yLabel + ': ' + data.y + '
'; 110 | }); 111 | 112 | d3.select('#' + id) 113 | .datum([{key: '', values: data}]) 114 | .transition().duration(500) 115 | .call(chart); 116 | 117 | return chart; 118 | }); 119 | 120 | return data; 121 | } 122 | 123 | var schema = { 124 | pieChart: { 125 | data: [ 126 | { 127 | label: 'String', 128 | value: 'Number' 129 | } 130 | ] 131 | }, 132 | barChart: { 133 | data: [ 134 | { 135 | label: 'String', 136 | value: 'Number' 137 | } 138 | ] 139 | }, 140 | scatterPlot: { 141 | data: [ 142 | { 143 | x: 'Number', 144 | y: 'Number', 145 | label: 'String' 146 | } 147 | ] 148 | }, 149 | lineChart: { 150 | data: [ 151 | { 152 | x: 'Number', 153 | y: 'Number', 154 | label: 'String' 155 | } 156 | ] 157 | } 158 | 159 | } 160 | 161 | function Jutsu (domElement) { 162 | if (domElement) { 163 | d3.select(domElement).selectAll('*').remove(); 164 | } 165 | return { 166 | __SMOLDER_SCHEMA: schema, 167 | pieChart: function (data) { 168 | return _pieChart(domElement, data); 169 | }, 170 | barChart: function (data, xLabel, yLabel) { 171 | return _barChart(domElement, data, xLabel, yLabel); 172 | }, 173 | scatterPlot: function (data, xLabel, yLabel) { 174 | return _scatterPlot(domElement, data, xLabel, yLabel); 175 | }, 176 | lineChart: function (data, xLabel, yLabel) { 177 | return _lineChart(domElement, data, xLabel, yLabel); 178 | } 179 | }; 180 | } 181 | 182 | module.exports = Jutsu; 183 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jutsu", 3 | "version": "0.1.1", 4 | "description": "One-line graphs with Smolder support", 5 | "main": "./lib/jutsu.js", 6 | "scripts": { 7 | "test": "npm test" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/JoelOtter/jutsu" 12 | }, 13 | "keywords": [ 14 | "graphs", 15 | "d3", 16 | "nvd3", 17 | "smolder", 18 | "reshaper" 19 | ], 20 | "author": "Joel Auterson