├── .gitignore ├── .jshintrc ├── GruntFile.js ├── LICENSE.md ├── README.md ├── build ├── jubilee.js └── jubilee.min.js ├── package.json ├── src ├── end.js ├── index.js ├── modules │ ├── builder.js │ ├── chart │ │ ├── bar.js │ │ ├── boxplot.js │ │ ├── dendrogram.js │ │ ├── heatmap.js │ │ ├── histogram.js │ │ ├── horizon.js │ │ ├── pie.js │ │ ├── series.js │ │ ├── spider.js │ │ ├── sunburst.js │ │ └── treemap.js │ ├── component │ │ ├── axis │ │ │ ├── axis.js │ │ │ ├── rotate.js │ │ │ └── truncate.js │ │ ├── boxplot.js │ │ ├── clippath.js │ │ ├── events │ │ │ ├── brush.js │ │ │ └── events.js │ │ ├── legend.js │ │ ├── scale.js │ │ └── series │ │ │ ├── area.js │ │ │ ├── bars.js │ │ │ ├── line.js │ │ │ └── points.js │ ├── element │ │ ├── canvas │ │ │ └── rect.js │ │ └── svg │ │ │ ├── circle.js │ │ │ ├── ellipse.js │ │ │ ├── image.js │ │ │ ├── line.js │ │ │ ├── path.js │ │ │ ├── rect.js │ │ │ └── text.js │ ├── functor.js │ ├── helpers │ │ ├── add_event_listener.js │ │ ├── remove_event_listener.js │ │ ├── scaletor.js │ │ ├── target_index.js │ │ └── timeparser.js │ ├── layout │ │ ├── base.js │ │ ├── box.js │ │ └── grid.js │ └── valuator.js ├── require.config.js └── start.js └── test ├── .jshintrc └── unit ├── fixtures ├── data_generator.js ├── fixture.js ├── path_generator.js ├── remove.js └── remove_children.js ├── index.html └── specs └── modules ├── component ├── axis.js ├── brush.js ├── clippath.js └── events.js ├── element ├── circle.js ├── ellipse.js ├── image.js ├── line.js ├── path.js ├── rect.js └── text.js ├── functor.js ├── helpers ├── add_event_listener.js ├── remove_event_listener.js ├── scaletor.js └── timeparser.js ├── layout ├── base.js └── grid.js └── valuator.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | examples/ -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "define": true, 4 | "require": true 5 | }, 6 | "bitwise": true, 7 | "camelcase": true, 8 | "curly": true, 9 | "eqeqeq": true, 10 | "es3": false, 11 | "forin": true, 12 | "freeze": true, 13 | "immed": true, 14 | "indent": 2, 15 | "latedef": false, 16 | "newcap": true, 17 | "noarg": true, 18 | "noempty": true, 19 | "nonbsp": true, 20 | "nonew": true, 21 | "plusplus": false, 22 | "quotmark": "double", 23 | "undef": true, 24 | "unused": "vars", 25 | "strict": false, 26 | "maxerr": 10, 27 | "maxlen": 120, 28 | "boss": true, 29 | "debug": true, 30 | "eqnull": true 31 | } 32 | -------------------------------------------------------------------------------- /GruntFile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | //Project configuration. 4 | grunt.initConfig({ 5 | pkg: grunt.file.readJSON("package.json"), 6 | mocha: { 7 | all: { 8 | src: ["test/unit/index.html"] 9 | }, 10 | options: { 11 | run: true 12 | } 13 | }, 14 | connect: { 15 | server: { 16 | options: { 17 | port: 8080, 18 | protocol: "http", 19 | hostname: "127.0.0.1", 20 | base: ".", 21 | livereload: true 22 | } 23 | } 24 | }, 25 | requirejs: { 26 | compile: { 27 | options: { 28 | baseUrl: ".", 29 | mainConfigFile: "src/require.config.js", 30 | name: "node_modules/almond/almond", 31 | include: ["src/require.config", "jubilee"], 32 | optimize: "none", 33 | out: "build/jubilee.js", 34 | wrap: { 35 | startFile: "src/start.js", 36 | endFile: "src/end.js" 37 | } 38 | } 39 | } 40 | }, 41 | uglify: { 42 | options: { 43 | banner: "/*! <%= pkg.name %> - v<%= pkg.version %> - " + 44 | "<%= grunt.template.today('yyyy-mm-dd') %> */" 45 | }, 46 | js: { 47 | files: { 48 | "build/jubilee.min.js": ["build/jubilee.js"] 49 | } 50 | } 51 | }, 52 | jshint: { 53 | foo: { 54 | src: "src/**/*.js" 55 | }, 56 | options: { 57 | jshintrc: ".jshintrc" 58 | } 59 | }, 60 | watch: { 61 | js: { 62 | files: ["src/**/*.js"], 63 | tasks: [] 64 | } 65 | }, 66 | copy: { 67 | css: { 68 | files: [ 69 | { src: "src/style/jubilee.css", dest: "build/jubilee.css" } 70 | ] 71 | } 72 | }, 73 | cssmin: { 74 | dist: { 75 | files: { 76 | "build/jubilee.min.css" : ["build/jubilee.css"] 77 | } 78 | } 79 | } 80 | }); 81 | 82 | grunt.loadNpmTasks("grunt-contrib-watch"); 83 | grunt.loadNpmTasks("grunt-contrib-concat"); 84 | grunt.loadNpmTasks("grunt-contrib-jshint"); 85 | grunt.loadNpmTasks("grunt-contrib-uglify"); 86 | grunt.loadNpmTasks("grunt-contrib-copy"); 87 | grunt.loadNpmTasks("grunt-contrib-cssmin"); 88 | grunt.loadNpmTasks("grunt-contrib-requirejs"); 89 | grunt.loadNpmTasks("grunt-contrib-connect"); 90 | grunt.loadNpmTasks("grunt-mocha"); 91 | 92 | grunt.registerTask("default", ["requirejs", "copy", "connect", "watch"]); 93 | grunt.registerTask("production", ["requirejs", "uglify", "copy", "cssmin"]); 94 | grunt.registerTask("release", ["production"]); 95 | grunt.registerTask("lint", ["jshint"]); 96 | grunt.registerTask("test", ["mocha"]); 97 | grunt.registerTask("build", ["requirejs", "copy"]); 98 | }; 99 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jubilee (a.k.a the Ultimate sidekick) 2 | D3 Reusable Components Library 3 | 4 | ## Disclosure 5 | This repository is still in its early stage, so things may not work properly. 6 | 7 | ## Environment Setup 8 | Fork the repository. You will need node, npm, and grunt. Change into the project's root directory. 9 | 10 | ```bash 11 | npm install 12 | ``` 13 | 14 | Run Grunt with `grunt`. That's it! 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jubilee", 3 | "version": "0.0.3", 4 | "description": "D3 Reusable Components Library", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "test": "node_modules/.bin/mocha -w" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/stormpython/jubilee.git" 12 | }, 13 | "keywords": [ 14 | "d3", 15 | "reusable components", 16 | "data visualization" 17 | ], 18 | "authors": [ 19 | "Shelby Sturgis" 20 | ], 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/stormpython/jubilee/issues" 24 | }, 25 | "homepage": "https://github.com/stormpython/jubilee", 26 | "devDependencies": { 27 | "almond": "^0.3.1", 28 | "chai": "^2.1.1", 29 | "grunt": "^0.4.5", 30 | "grunt-cli": "0.1.13", 31 | "grunt-contrib-concat": "^0.5.1", 32 | "grunt-contrib-connect": "^0.9.0", 33 | "grunt-contrib-copy": "^0.8.0", 34 | "grunt-contrib-cssmin": "^0.12.2", 35 | "grunt-contrib-jshint": "^0.11.0", 36 | "grunt-contrib-nodeunit": "~0.3.0", 37 | "grunt-contrib-requirejs": "^0.4.4", 38 | "grunt-contrib-uglify": "^0.8.0", 39 | "grunt-contrib-watch": "^0.6.1", 40 | "grunt-mocha": "^0.4.12", 41 | "mocha": "^2.1.0", 42 | "requirejs": "^2.1.16" 43 | }, 44 | "dependencies": { 45 | "d3": "3.5.6" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/end.js: -------------------------------------------------------------------------------- 1 | return require('jubilee'); 2 | })); 3 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | return { 3 | chart: { 4 | boxplot: require("src/modules/chart/boxplot"), 5 | dendrogram: require("src/modules/chart/dendrogram"), 6 | heatmap: require("src/modules/chart/heatmap"), 7 | pie: require("src/modules/chart/pie"), 8 | series: require("src/modules/chart/series"), 9 | sunburst: require("src/modules/chart/sunburst"), 10 | treemap: require("src/modules/chart/treemap") 11 | }, 12 | layout: { 13 | base: require("src/modules/layout/base"), 14 | box: require("src/modules/layout/box"), 15 | grid: require("src/modules/layout/grid") 16 | }, 17 | axis: { 18 | rotate: require("src/modules/component/axis/rotate"), 19 | truncate: require("src/modules/component/axis/truncate") 20 | }, 21 | component: { 22 | area: require("src/modules/component/series/area"), 23 | axis: require("src/modules/component/axis/axis"), 24 | bars: require("src/modules/component/series/bars"), 25 | boxplot: require("src/modules/component/boxplot"), 26 | brush: require("src/modules/component/events/brush"), 27 | clipPath: require("src/modules/component/clippath"), 28 | events: require("src/modules/component/events/events"), 29 | line: require("src/modules/component/series/line"), 30 | points: require("src/modules/component/series/points") 31 | }, 32 | svg: { 33 | circle: require("src/modules/element/svg/circle"), 34 | ellipse: require("src/modules/element/svg/ellipse"), 35 | image: require("src/modules/element/svg/image"), 36 | line: require("src/modules/element/svg/line"), 37 | path: require("src/modules/element/svg/path"), 38 | rect: require("src/modules/element/svg/rect"), 39 | text: require("src/modules/element/svg/text") 40 | }, 41 | canvas: { 42 | rect: require("src/modules/element/canvas/rect") 43 | }, 44 | builder: require("builder"), 45 | functor: require("functor"), 46 | valuator: require("valuator") 47 | }; 48 | }); 49 | -------------------------------------------------------------------------------- /src/modules/builder.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function builder(attrs, func) { 5 | if (typeof attrs !== "object") { 6 | throw new Error("builder expects an object as its first argument"); 7 | } 8 | 9 | if (typeof func !== "function") { 10 | throw new Error("builder expects a function as its second argument"); 11 | } 12 | 13 | d3.entries(attrs).forEach(function (d) { 14 | if (typeof func[d.key] === "function") { 15 | func[d.key](d.value); 16 | } 17 | }); 18 | 19 | return func; 20 | }; 21 | }); -------------------------------------------------------------------------------- /src/modules/chart/boxplot.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | var box = require("src/modules/layout/box"); 4 | var boxPlot = require("src/modules/component/boxplot"); 5 | var axis = require("src/modules/component/axis/axis"); 6 | 7 | return function boxplot() { 8 | var margin = { top:20, right: 20, bottom: 50, left: 50 }; 9 | var width = 760; 10 | var height = 400; 11 | var xValue = function (d) { return d.x; }; 12 | var values = function (d) { return d.values; }; 13 | var accessor = function (d) { return d; }; 14 | var xScale = null; 15 | var yScale = null; 16 | var transform = null; 17 | var dispatch = d3.dispatch("hover", "mouseover", "mouseout"); 18 | 19 | // X Axis 20 | var xAxis = { 21 | show: true, 22 | xAxisClass: "x axis", 23 | textX: function () { return width / 2; }, 24 | textY: 30, 25 | textDY: ".71em", 26 | textAnchor: "middle", 27 | title: "" 28 | }; 29 | 30 | // Y Axis 31 | var yAxis = { 32 | show: true, 33 | yAxisClass: "y axis", 34 | textX: -height / 2, 35 | textY: -60, 36 | textDY: ".71em", 37 | textAnchor: "middle", 38 | title: "" 39 | }; 40 | 41 | // Box Options 42 | var boxWidth = 20; 43 | 44 | function chart(selection) { 45 | selection.each(function (data) { 46 | var boxData = box().values(values).accessor(accessor); 47 | 48 | var svg = d3.select(this).append("svg") 49 | .datum(boxData(data)) 50 | .attr("width", width + margin.left + margin.right) 51 | .attr("height", height + margin.top + margin.bottom); 52 | 53 | var g = svg.append("g") 54 | .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 55 | 56 | xScale = xScale ? xScale : d3.time.scale() 57 | .domain(d3.extent(data, xValue)) 58 | .range([0, width]); 59 | 60 | yScale = yScale ? yScale : d3.scale.linear() 61 | .domain([ 62 | Math.min(0, d3.min(d3.merge(data))), 63 | Math.max(0, d3.max(d3.merge(data))) 64 | ]) 65 | .range([height, 0]); 66 | 67 | var boxPlotFunc = boxPlot() 68 | .transform(transform ? transform : gTransform) 69 | .box({ width: boxWidth, height: boxHeight, y: boxY }) 70 | .range({ y1: Y1, y2: Y2 }) 71 | .max({ y1: Y1, y2: Y1 }) 72 | .min({ y1: Y2, y2: Y2}); 73 | 74 | g.call(boxPlotFunc); 75 | 76 | if (xAxis.show) { 77 | var axisX = axis() 78 | .scale(xScale) 79 | .gClass(xAxis.xAxisClass) 80 | .transform("translate(0," + yScale.range()[0] + ")") 81 | .titleX(xAxis.textX) 82 | .titleY(xAxis.textY) 83 | .titleDY(xAxis.textDY) 84 | .titleAnchor(xAxis.textAnchor) 85 | .title(xAxis.title); 86 | 87 | g.call(axisX); 88 | } 89 | 90 | if (yAxis.show) { 91 | var axisY = axis() 92 | .scale(yScale) 93 | .orient("left") 94 | .gClass(yAxis.yAxisClass) 95 | .titleX(yAxis.textX) 96 | .titleY(yAxis.textY) 97 | .titleDY(yAxis.textDY) 98 | .titleAnchor(yAxis.textAnchor) 99 | .title(yAxis.title); 100 | 101 | g.call(axisY); 102 | } 103 | }); 104 | } 105 | 106 | function boxHeight(d) { 107 | return yScale(d.q1) - yScale(d.q3); 108 | } 109 | 110 | function boxY(d) { 111 | return yScale(d.q3) - yScale(d.median); 112 | } 113 | 114 | function Y1(d) { 115 | return yScale(d.max) - yScale(d.median); 116 | } 117 | 118 | function Y2(d) { 119 | return yScale(d.min) - yScale(d.median); 120 | } 121 | 122 | function gTransform(d, i) { 123 | return "translate(" + xScale(xValue.call(this, d, i)) + "," + yScale(d.median) + ")"; 124 | } 125 | 126 | chart.margin = function (_) { 127 | if (!arguments.length) { return margin; } 128 | margin.top = typeof _.top !== "undefined" ? _.top : margin.top; 129 | margin.right = typeof _.right !== "undefined" ? _.right : margin.right; 130 | margin.bottom = typeof _.bottom !== "undefined" ? _.bottom : margin.bottom; 131 | margin.left = typeof _.left !== "undefined" ? _.left : margin.left; 132 | return chart; 133 | }; 134 | 135 | chart.width = function (_) { 136 | if (!arguments.length) { return width; } 137 | width = _; 138 | return chart; 139 | }; 140 | 141 | chart.height = function (_) { 142 | if (!arguments.length) { return height; } 143 | height = _; 144 | return chart; 145 | }; 146 | 147 | chart.x = function (_) { 148 | if (!arguments.length) { return xValue; } 149 | xValue = _; 150 | return chart; 151 | }; 152 | 153 | chart.values = function (_) { 154 | if (!arguments.length) { return values; } 155 | values = _; 156 | return chart; 157 | }; 158 | 159 | chart.accessor = function (_) { 160 | if (!arguments.length) { return accessor; } 161 | accessor = _; 162 | return chart; 163 | }; 164 | 165 | chart.xScale = function (_) { 166 | if (!arguments.length) { return xScale; } 167 | xScale = _; 168 | return chart; 169 | }; 170 | 171 | chart.yScale = function (_) { 172 | if (!arguments.length) { return yScale; } 173 | yScale = _; 174 | return chart; 175 | }; 176 | 177 | chart.transform = function (_) { 178 | if (!arguments.length) { return transform; } 179 | transform = _; 180 | return chart; 181 | }; 182 | 183 | chart.dispatch = function (_) { 184 | if (!arguments.length) { return dispatch; } 185 | dispatch = _; 186 | return chart; 187 | }; 188 | 189 | chart.xAxis = function (_) { 190 | if (!arguments.length) { return xAxis; } 191 | xAxis.show = typeof _.show !== "undefined" ? _.show: xAxis.show; 192 | xAxis.xAxisClass = typeof _.xAxisClass !== "undefined" ? _.xAxisClass : xAxis.xAxisClass; 193 | xAxis.textX = typeof _.textX !== "undefined" ? _.textX : xAxis.textX; 194 | xAxis.textY = typeof _.textY !== "undefined" ? _.textY : xAxis.textY; 195 | xAxis.textDY = typeof _.textDY !== "undefined" ? _.textDY : xAxis.textDY; 196 | xAxis.textAnchor = typeof _.textAnchor !== "undefined" ? _.textAnchor : xAxis.textAnchor; 197 | xAxis.title = typeof _.title !== "undefined" ? _.title : xAxis.title; 198 | return chart; 199 | }; 200 | 201 | chart.yAxis = function (_) { 202 | if (!arguments.length) { return yAxis; } 203 | yAxis.show = typeof _.show !== "undefined" ? _.show: yAxis.show; 204 | yAxis.yAxisClass = typeof _.yAxisClass !== "undefined" ? _.yAxisClass : yAxis.yAxisClass; 205 | yAxis.textX = typeof _.textX !== "undefined" ? _.textX : yAxis.textX; 206 | yAxis.textY = typeof _.textY !== "undefined" ? _.textY : yAxis.textY; 207 | yAxis.textDY = typeof _.textDY !== "undefined" ? _.textDY : yAxis.textDY; 208 | yAxis.textAnchor = typeof _.textAnchor !== "undefined" ? _.textAnchor : yAxis.textAnchor; 209 | yAxis.title = typeof _.title !== "undefined" ? _.title : yAxis.title; 210 | return chart; 211 | }; 212 | 213 | chart.boxWidth = function (_) { 214 | if (!arguments.length) { return boxWidth; } 215 | boxWidth = _; 216 | return chart; 217 | }; 218 | 219 | d3.rebind(chart, dispatch, "on"); 220 | return chart; 221 | }; 222 | }); -------------------------------------------------------------------------------- /src/modules/chart/dendrogram.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function dendrogram() { 5 | var marginFactor = 0.5; 6 | var width = 300; 7 | var height = 800; 8 | var color = d3.scale.category20b(); 9 | var value = function (d) { return d.size; }; 10 | var projection = function (d) { return [d.y, d.x]; }; 11 | var transform = "translate(20,0)"; 12 | var dispatch = d3.dispatch("hover", "mouseover", "mouseout"); 13 | 14 | // Node options 15 | var nodeRadius = 4.5; 16 | var nodeTransform = function (d) { return "translate(" + d.y + "," + d.x + ")"; }; 17 | var nodeFill = function (d, i) { return color(i); }; 18 | var nodeStroke = function (d, i) { return color(i); }; 19 | var nodeClass = "node"; 20 | 21 | // Link options 22 | var linkClass = "link"; 23 | 24 | // Text options 25 | var label = function (d) { return d.children ? d.name : d.name + ": " + d.size; }; 26 | var textDX = function (d) { return d.children ? -8 : 8; }; 27 | var textDY = 3; 28 | var textAnchor = function (d) { return d.children ? "end" : "start"; }; 29 | 30 | function chart(selection) { 31 | selection.each(function (data) { 32 | var cluster = d3.layout.cluster() 33 | .size([height, width - (width * marginFactor)]) 34 | .value(value); 35 | 36 | var diagonal = d3.svg.diagonal().projection(projection); 37 | var nodes = cluster.nodes(data); 38 | var links = cluster.links(nodes); 39 | 40 | var svg = d3.select(this).append("svg") 41 | .attr("width", width) 42 | .attr("height", height) 43 | .append("g") 44 | .attr("transform", transform); 45 | 46 | 47 | var link = svg.selectAll(".link") 48 | .data(links) 49 | .enter().append("path") 50 | .attr("class", linkClass) 51 | .attr("d", diagonal); 52 | 53 | var node = svg.selectAll(".node") 54 | .data(nodes) 55 | .enter().append("g") 56 | .attr("class", nodeClass) 57 | .attr("transform", nodeTransform); 58 | 59 | node.append("circle") 60 | .attr("r", nodeRadius) 61 | .style("fill", nodeFill) 62 | .style("stroke", nodeStroke); 63 | 64 | node.append("text") 65 | .attr("dx", textDX) 66 | .attr("dy", textDY) 67 | .style("text-anchor", textAnchor) 68 | .text(label); 69 | 70 | d3.select(this.frameElement).style("height", height + "px"); 71 | }); 72 | } 73 | 74 | chart.marginFactor = function (_) { 75 | if (!arguments.length) { return marginFactor; } 76 | marginFactor = _; 77 | return chart; 78 | }; 79 | 80 | chart.width = function (_) { 81 | if (!arguments.length) { return width; } 82 | width = _; 83 | return chart; 84 | }; 85 | 86 | chart.height = function (_) { 87 | if (!arguments.length) { return height; } 88 | height = _; 89 | return chart; 90 | }; 91 | 92 | chart.color = function (_) { 93 | if (!arguments.length) { return color; } 94 | color = _; 95 | return chart; 96 | }; 97 | 98 | chart.value = function (_) { 99 | if (!arguments.length) { return value; } 100 | value = _; 101 | return chart; 102 | }; 103 | 104 | chart.projection = function (_) { 105 | if (!arguments.length) { return projection; } 106 | projection = _; 107 | return chart; 108 | }; 109 | 110 | chart.transform = function (_) { 111 | if (!arguments.length) { return transform; } 112 | transform = _; 113 | return chart; 114 | }; 115 | 116 | chart.dispatch = function (_) { 117 | if (!arguments.length) { return dispatch;} 118 | dispatch = _; 119 | return chart; 120 | }; 121 | 122 | chart.nodeRadius = function (_) { 123 | if (!arguments.length) { return nodeRadius; } 124 | nodeRadius = _; 125 | return chart; 126 | }; 127 | 128 | chart.nodeFill = function (_) { 129 | if (!arguments.length) { return nodeFill; } 130 | nodeFill = _; 131 | return chart; 132 | }; 133 | 134 | chart.nodeStroke = function (_) { 135 | if (!arguments.length) { return nodeStroke; } 136 | nodeStroke = _; 137 | return chart; 138 | }; 139 | 140 | chart.nodeClass = function (_) { 141 | if (!arguments.length) { return nodeClass; } 142 | nodeClass = _; 143 | return chart; 144 | }; 145 | 146 | chart.linkClass = function (_) { 147 | if (!arguments.length) { return linkClass; } 148 | linkClass = _; 149 | return chart; 150 | }; 151 | 152 | chart.label = function (_) { 153 | if (!arguments.length) { return label; } 154 | label = _; 155 | return chart; 156 | }; 157 | 158 | chart.textDX = function (_) { 159 | if (!arguments.length) { return textDX; } 160 | textDX = _; 161 | return chart; 162 | }; 163 | 164 | chart.textDY = function (_) { 165 | if (!arguments.length) { return textDY; } 166 | textDY = _; 167 | return chart; 168 | }; 169 | 170 | chart.textAnchor = function (_) { 171 | if (!arguments.length) { return textAnchor; } 172 | textAnchor = _; 173 | return chart; 174 | }; 175 | 176 | d3.rebind(chart, dispatch, "on"); 177 | return chart; 178 | }; 179 | }); 180 | -------------------------------------------------------------------------------- /src/modules/chart/histogram.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | var valuator = require("valuator"); 4 | 5 | return function histogram() { 6 | // Private variables 7 | var margin = { top: 20, right: 20, bottom: 20, left: 50 }; 8 | var width = 900; 9 | var height = 500; 10 | var bins = null; 11 | var range = null; 12 | var frequency = "frequency"; 13 | var value = function (d) { return d.y; }; 14 | 15 | var bars = { 16 | class: "rect", 17 | fill: "blue", 18 | stroke: "white", 19 | strokeWidth: 1, 20 | opacity: 1 21 | }; 22 | 23 | var text = { 24 | class: "text", 25 | dy: "0.71em", 26 | textAnchor: "middle", 27 | fill: "black" 28 | }; 29 | 30 | function chart(selection) { 31 | selection.each(function (data, index) { 32 | width = width - margin.left - margin.right; 33 | height = height - margin.top - margin.bottom; 34 | 35 | var histogram = d3.layout.histogram() 36 | .bins(bins) 37 | .value(value) 38 | .frequency(frequency) 39 | .range(range || d3.extent(data, value)); 40 | 41 | data = histogram(data); 42 | 43 | var xScale = d3.scale.linear() 44 | .domain(d3.extent(bins)) 45 | .range([0, width]); 46 | 47 | var yScale = d3.scale.linear() 48 | .domain([0, d3.max(data, yValue)]) 49 | .range([height, 0]); 50 | 51 | var svg = d3.select(this).append("svg") 52 | .attr("width", width + margin.left + margin.right) 53 | .attr("height", height + margin.top + margin.bottom) 54 | .append("g") 55 | .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 56 | 57 | var xAxis = d3.svg.axis().scale(xScale).orient("bottom"); 58 | var yAxis = d3.svg.axis().scale(yScale).orient("left"); 59 | 60 | svg.append("g") 61 | .attr("class", "x axis") 62 | .attr("transform", "translate(0," + yScale.range()[0] + ")") 63 | .call(xAxis); 64 | 65 | var group = svg.selectAll("groups") 66 | .data(data); 67 | 68 | // Exit 69 | group.exit().remove(); 70 | 71 | // Enter 72 | group.enter().append("g"); 73 | 74 | // Update 75 | group.append("rect") 76 | .attr("class", bars.class) 77 | .attr("fill", bars.fill) 78 | .attr("stroke", bars.stroke) 79 | .attr("stroke-width", bars.strokeWidth) 80 | .attr("x", function (d) { return xScale(d.x); }) 81 | .attr("y", function (d) { return yScale(d.y); }) 82 | .attr("width", function (d) { return xScale(d.dx); }) 83 | .attr("height", function (d) { return yScale.range()[0] - yScale(d.y); }); 84 | 85 | group.append("text") 86 | .attr("class", text.class) 87 | .attr("dy", text.dy) 88 | .attr("y", function (d) { return yScale(d.y - 0.1); }) 89 | .attr("x", function (d) { return xScale(d.x) + (xScale(d.dx) / 2); }) 90 | .attr("text-anchor", text.textAnchor) 91 | .attr("fill", text.fill) 92 | .text(function (d) { return !d.y ? "" : d.y; }); 93 | }); 94 | } 95 | 96 | // Public API 97 | chart.margin = function (_) { 98 | if (!arguments.length) { return margin; } 99 | margin.top = typeof _.top !== "undefined" ? _.top : margin.top; 100 | margin.right = typeof _.right !== "undefined" ? _.right : margin.right; 101 | margin.bottom = typeof _.bottom !== "undefined" ? _.bottom : margin.bottom; 102 | margin.left = typeof _.left !== "undefined" ? _.left : margin.left; 103 | return chart; 104 | }; 105 | 106 | chart.width = function (_) { 107 | if (!arguments.length) { return width; } 108 | width = typeof _ !== "number" ? width : _; 109 | return chart; 110 | }; 111 | 112 | chart.height = function (_) { 113 | if (!arguments.length) { return height; } 114 | height = typeof _ !== "number" ? height : _; 115 | return chart; 116 | }; 117 | 118 | chart.value = function (_) { 119 | if (!arguments.length) { return value; } 120 | value = valuator(_); 121 | return chart; 122 | }; 123 | 124 | chart.bins = function (_) { 125 | if (!arguments.length) { return bins; } 126 | bins = _; 127 | return chart; 128 | }; 129 | 130 | chart.frequency = function (_) { 131 | if (!arguments.length) { return frequency; } 132 | frequency = typeof _ !== "string" ? frequency : _; 133 | return chart; 134 | }; 135 | 136 | chart.range = function (_) { 137 | if (!arguments.length) return range; 138 | range = d3.functor(_); 139 | return chart; 140 | }; 141 | 142 | chart.bars = function (_) { 143 | if (!arguments.length) { return bars; } 144 | bars.class = typeof _.class !== "undefined" ? _.class : bars.class; 145 | bars.fill = typeof _.fill !== "undefined" ? _.fill : bars.fill; 146 | bars.stroke = typeof _.stroke !== "undefined" ? _.stroke : bars.stroke; 147 | bars.strokeWidth = typeof _.strokeWidth !== "undefined" ? _.strokeWidth : bars.strokeWidth; 148 | return chart; 149 | }; 150 | 151 | chart.text = function (_) { 152 | if (!arguments.length) { return text; } 153 | text.class = typeof _.class !== "undefined" ? _.class : text.class; 154 | text.fill = typeof _.fill !== "undefined" ? _.fill : text.fill; 155 | text.dy = typeof _.dy !== "undefined" ? _.dy : text.dy; 156 | text.textAnchor = typeof _.textAnchor !== "undefined" ? _.textAnchor : text.textAnchor; 157 | return chart; 158 | }; 159 | 160 | return chart; 161 | }; 162 | }); -------------------------------------------------------------------------------- /src/modules/chart/horizon.js: -------------------------------------------------------------------------------- 1 | define(function (require) {}); 2 | -------------------------------------------------------------------------------- /src/modules/chart/pie.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | var path = require("src/modules/element/svg/path"); 4 | var textElement = require("src/modules/element/svg/text"); 5 | var events = require("src/modules/component/events/events"); 6 | var valuator = require("valuator"); 7 | var addEventListener = require("src/modules/helpers/add_event_listener"); 8 | var removeEventListener = require("src/modules/helpers/remove_event_listener"); 9 | 10 | return function pieChart() { 11 | // Private variables 12 | var width = 300; 13 | var height = 300; 14 | var color = d3.scale.category10(); 15 | var outerRadius = null; 16 | var innerRadius = 0; 17 | var sort = null; 18 | var value = function (d) { return d.x; }; 19 | var label = function (d) { return d.name; }; 20 | 21 | var pieClass = "pie"; 22 | var fill = function (d, i) { 23 | return color(label.call(this, d.data, i)); 24 | }; 25 | var stroke = "#ffffff"; 26 | 27 | // Text options 28 | var text = { 29 | fill: "#ffffff", 30 | dy: ".35em", 31 | anchor: "middle", 32 | transform: null 33 | }; 34 | 35 | var listeners = {}; 36 | 37 | function chart (selection) { 38 | selection.each(function (data, index) { 39 | var pie = d3.layout.pie() 40 | .sort(sort) 41 | .value(value); 42 | 43 | data = pie(data).map(function (d) { 44 | return [d]; 45 | }); 46 | 47 | var radius = Math.min(width, height) / 2; 48 | 49 | var svgEvents = events().listeners(listeners); 50 | 51 | var svg = d3.select(this).append("svg") 52 | .attr("width", width) 53 | .attr("height", height) 54 | .call(svgEvents); 55 | 56 | var g = svg.append("g") 57 | .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); 58 | 59 | var arc = d3.svg.arc() 60 | .outerRadius(outerRadius || radius) 61 | .innerRadius(innerRadius); 62 | 63 | var piePath = path() 64 | .pathGenerator(arc) 65 | .class(pieClass) 66 | .fill(fill) 67 | .stroke(stroke); 68 | 69 | var pieText = textElement() 70 | .transform(text.transform || function (d) { 71 | return "translate(" + arc.centroid(d) + ")"; 72 | }) 73 | .dy(text.dy) 74 | .anchor(text.anchor) 75 | .fill(text.fill) 76 | .text(function (d, i) { 77 | return label.call(this, d.data, i); 78 | }); 79 | 80 | g.selectAll("groups") 81 | .data(data) 82 | .enter().append("g") 83 | .call(piePath) 84 | .call(pieText); 85 | }); 86 | } 87 | 88 | // Public API 89 | chart.width = function (_) { 90 | if (!arguments.length) { return width; } 91 | width = _; 92 | return chart; 93 | }; 94 | 95 | chart.height = function (_) { 96 | if (!arguments.length) { return height; } 97 | height = _; 98 | return chart; 99 | }; 100 | 101 | chart.color = function (_) { 102 | if (!arguments.length) { return color; } 103 | color = _; 104 | return chart; 105 | }; 106 | 107 | chart.outerRadius = function (_) { 108 | if (!arguments.length) { return outerRadius; } 109 | outerRadius = _; 110 | return chart; 111 | }; 112 | 113 | chart.innerRadius = function (_) { 114 | if (!arguments.length) { return innerRadius; } 115 | innerRadius = _; 116 | return chart; 117 | }; 118 | 119 | chart.sort = function (_) { 120 | if (!arguments.length) { return sort; } 121 | sort = _; 122 | return chart; 123 | }; 124 | 125 | chart.value = function (_) { 126 | if (!arguments.length) { return value; } 127 | value = valuator(_); 128 | return chart; 129 | }; 130 | 131 | chart.label = function (_) { 132 | if (!arguments.length) { return label; } 133 | label = valuator(_); 134 | return chart; 135 | }; 136 | 137 | chart.class = function (_) { 138 | if (!arguments.length) { return pieClass; } 139 | pieClass = _; 140 | return chart; 141 | }; 142 | 143 | chart.fill = function (_) { 144 | if (!arguments.length) { return fill; } 145 | fill = _; 146 | return chart; 147 | }; 148 | 149 | chart.stroke = function (_) { 150 | if (!arguments.length) { return stroke; } 151 | stroke = _; 152 | return chart; 153 | }; 154 | 155 | chart.text = function (_) { 156 | if (!arguments.length) { return text; } 157 | text.fill = typeof _.fill !== "undefined" ? _.fill : text.fill; 158 | text.anchor = typeof _.anchor !== "undefined" ? _.anchor: text.anchor; 159 | text.dy = typeof _.dy !== "undefined" ? _.dy : text.dy; 160 | text.transform = typeof _.transform !== "undefined" ? _.transform : text.transform; 161 | return chart; 162 | }; 163 | 164 | chart.listeners = function (_) { 165 | if (!arguments.length) { return listeners; } 166 | listeners = typeof _ !== "object" ? listeners : _; 167 | return chart; 168 | }; 169 | 170 | chart.on = addEventListener(chart); 171 | 172 | chart.off = removeEventListener(chart); 173 | 174 | return chart; 175 | }; 176 | }); -------------------------------------------------------------------------------- /src/modules/chart/spider.js: -------------------------------------------------------------------------------- 1 | define(function (require) {}); 2 | -------------------------------------------------------------------------------- /src/modules/chart/sunburst.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | var path = require("src/modules/element/svg/path"); 4 | var events = require("src/modules/component/events/events"); 5 | var valuator = require("valuator"); 6 | var addEventListener = require("src/modules/helpers/add_event_listener"); 7 | var removeEventListener = require("src/modules/helpers/remove_event_listener"); 8 | 9 | return function sunburst() { 10 | // Private variables 11 | var width = 500; 12 | var height = 500; 13 | var color = d3.scale.category10(); 14 | var sort = null; 15 | var value = function (d) { return d.size; }; 16 | var xScale = d3.scale.linear().range([0, 2 * Math.PI]); 17 | var yScale = d3.scale.sqrt(); 18 | var startAngle = function (d) { 19 | return Math.max(0, Math.min(2 * Math.PI, xScale(d.x))); 20 | }; 21 | var endAngle = function (d) { 22 | return Math.max(0, Math.min(2 * Math.PI, xScale(d.x + d.dx))); 23 | }; 24 | var innerRadius = function (d) { 25 | return Math.max(0, yScale(d.y)); 26 | }; 27 | var outerRadius = function (d) { 28 | return Math.max(0, yScale(d.y + d.dy)); 29 | }; 30 | 31 | // Pie options 32 | var pieClass = "slice"; 33 | var stroke = "#ffffff"; 34 | var fill = function (d, i) { 35 | if (d.depth === 0) { return "none"; } 36 | return color(i); 37 | }; 38 | 39 | var listeners = {}; 40 | 41 | function chart (selection) { 42 | selection.each(function (data) { 43 | var radius = Math.min(width, height) / 2; 44 | 45 | var partition = d3.layout.partition() 46 | .sort(sort) 47 | .value(value); 48 | 49 | var svgEvents = events().listeners(listeners); 50 | 51 | var svg = d3.select(this).append("svg") 52 | .attr("width", width) 53 | .attr("height", height) 54 | .append("g") 55 | .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")") 56 | .call(svgEvents); 57 | 58 | yScale.range([0, radius]); 59 | 60 | var arc = d3.svg.arc() 61 | .startAngle(startAngle) 62 | .endAngle(endAngle) 63 | .innerRadius(innerRadius) 64 | .outerRadius(outerRadius); 65 | 66 | var arcPath = path() 67 | .pathGenerator(arc) 68 | .accessor(partition.nodes) 69 | .class(pieClass) 70 | .stroke(stroke) 71 | .fill(fill); 72 | 73 | svg.datum(data).call(arcPath); 74 | }); 75 | } 76 | 77 | // Public API 78 | chart.width = function (_) { 79 | if (!arguments.length) { return width; } 80 | width = _; 81 | return chart; 82 | }; 83 | 84 | chart.height = function (_) { 85 | if (!arguments.length) { return height; } 86 | height = _; 87 | return chart; 88 | }; 89 | 90 | chart.color = function (_) { 91 | if (!arguments.length) { return color; } 92 | color = typeof _ !== "function" ? color : _; 93 | return chart; 94 | }; 95 | 96 | chart.sort = function (_) { 97 | if (!arguments.length) { return sort; } 98 | sort = _; 99 | return chart; 100 | }; 101 | 102 | chart.value = function (_) { 103 | if (!arguments.length) { return value; } 104 | value = valuator(_); 105 | return chart; 106 | }; 107 | 108 | chart.xScale = function (_) { 109 | if (!arguments.length) { return xScale; } 110 | xScale = _; 111 | return chart; 112 | }; 113 | 114 | chart.yScale = function (_) { 115 | if (!arguments.length) { return yScale; } 116 | yScale = _; 117 | return chart; 118 | }; 119 | 120 | chart.startAngle = function (_) { 121 | if (!arguments.length) { return startAngle; } 122 | startAngle = d3.functor(_); 123 | return chart; 124 | }; 125 | 126 | chart.endAngle = function (_) { 127 | if (!arguments.length) { return endAngle; } 128 | endAngle = d3.functor(_); 129 | return chart; 130 | }; 131 | 132 | chart.innerRadius = function (_) { 133 | if (!arguments.length) { return innerRadius; } 134 | innerRadius = d3.functor(_); 135 | return chart; 136 | }; 137 | 138 | chart.outerRadius = function (_) { 139 | if (!arguments.length) { return outerRadius; } 140 | outerRadius = d3.functor(_); 141 | return chart; 142 | }; 143 | 144 | chart.class = function (_) { 145 | if (!arguments.length) { return pieClass; } 146 | pieClass = typeof _ !== "string" ? pieClass : _; 147 | return chart; 148 | }; 149 | 150 | chart.stroke = function (_) { 151 | if (!arguments.length) { return stroke; } 152 | stroke = _; 153 | return chart; 154 | }; 155 | 156 | chart.fill = function (_) { 157 | if (!arguments.length) { return fill; } 158 | fill= _; 159 | return chart; 160 | }; 161 | 162 | chart.listeners = function (_) { 163 | if (!arguments.length) { return listeners; } 164 | listeners = typeof _ !== "object" ? listeners : _; 165 | return chart; 166 | }; 167 | 168 | chart.on = addEventListener(chart); 169 | 170 | chart.off = removeEventListener(chart); 171 | 172 | return chart; 173 | }; 174 | }); 175 | -------------------------------------------------------------------------------- /src/modules/chart/treemap.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function treemap() { 5 | var margin = {top: 40, right: 10, bottom: 10, left: 10}; 6 | var width = 960 - margin.left - margin.right; 7 | var height = 500 - margin.top - margin.bottom; 8 | var color = d3.scale.category20c(); 9 | var sticky = true; 10 | var value = function (d) { return d.size; }; 11 | var children = function (d) { return d.children; }; 12 | var dispatch = d3.dispatch("hover", "mouseover", "mouseout"); 13 | 14 | var nodeClass = "node"; 15 | var nodeColor = function (d, i) { return d.children ? color(i) : null; }; 16 | var label = function (d) { return d.children ? null : d.name; }; 17 | 18 | function chart(selection) { 19 | selection.each(function (data) { 20 | var treemap = d3.layout.treemap() 21 | .size([width, height]) 22 | .sticky(sticky) 23 | .children(children) 24 | .value(value); 25 | 26 | var div = d3.select(this).append("div") 27 | .style("position", "relative") 28 | .style("width", (width + margin.left + margin.right) + "px") 29 | .style("height", (height + margin.top + margin.bottom) + "px") 30 | .style("left", margin.left + "px") 31 | .style("top", margin.top + "px"); 32 | 33 | div.datum(data).selectAll(".node") 34 | .data(treemap.nodes) 35 | .enter().append("div") 36 | .attr("class", nodeClass) 37 | .call(position) 38 | .style("background", nodeColor) 39 | .text(label); 40 | }); 41 | } 42 | 43 | function position() { 44 | this.style("left", function(d) { return d.x + "px"; }) 45 | .style("top", function(d) { return d.y + "px"; }) 46 | .style("width", function(d) { return Math.max(0, d.dx - 1) + "px"; }) 47 | .style("height", function(d) { return Math.max(0, d.dy - 1) + "px"; }); 48 | } 49 | 50 | chart.margin = function (_) { 51 | if (!arguments.length) { return margin; } 52 | margin.top = typeof _.top !== "undefined" ? _.top : margin.top; 53 | margin.right = typeof _.right !== "undefined" ? _.right : margin.right; 54 | margin.bottom = typeof _.bottom !== "undefined" ? _.bottom : margin.bottom; 55 | margin.left = typeof _.left !== "undefined" ? _.left : margin.left; 56 | return chart; 57 | }; 58 | 59 | chart.width = function (_) { 60 | if (!arguments.length) { return width; } 61 | width = _; 62 | return chart; 63 | }; 64 | 65 | chart.height = function (_) { 66 | if (!arguments.length) { return height; } 67 | height = _; 68 | return chart; 69 | }; 70 | 71 | chart.color = function (_) { 72 | if (!arguments.length) { return color; } 73 | color = _; 74 | return chart; 75 | }; 76 | 77 | return chart; 78 | }; 79 | }); 80 | -------------------------------------------------------------------------------- /src/modules/component/axis/axis.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | var builder = require("builder"); 4 | var rotate = require("./rotate"); 5 | 6 | return function axes() { 7 | // Private variables 8 | var scale = d3.scale.linear(); 9 | var orient = "bottom"; 10 | var tick = { 11 | number: 10, 12 | values: null, 13 | size: 6, 14 | innerTickSize: 6, 15 | outerTickSize: 6, 16 | padding: 3, 17 | format: null 18 | }; 19 | var tickText = { 20 | transform: null, 21 | anchor: "middle", 22 | x: 0, 23 | y: 9, 24 | dx: "", 25 | dy: ".71em" 26 | }; 27 | var rotateLabels = { allow: false }; 28 | var transform = "translate(0,0)"; 29 | var gClass = "axis"; 30 | var title = { 31 | class: "axis title", 32 | x: 6, 33 | y: 6, 34 | dx: "", 35 | dy: ".71em", 36 | anchor: "end", 37 | transform: "translate(0,0)", 38 | text: "" 39 | }; 40 | 41 | function component(selection) { 42 | selection.each(function () { 43 | var axis = d3.svg.axis() 44 | .scale(scale) 45 | .orient(orient) 46 | .ticks(tick.number) 47 | .tickValues(tick.values) 48 | .tickSize(tick.size) 49 | .innerTickSize(tick.innerTickSize) 50 | .outerTickSize(tick.outerTickSize) 51 | .tickPadding(tick.padding) 52 | .tickFormat(tick.format); 53 | 54 | var g = d3.select(this); 55 | 56 | // Remove previous axis 57 | g.select("g." + gClass).remove(); 58 | 59 | // Attach axis 60 | g.append("g") 61 | .attr("class", gClass) 62 | .attr("transform", transform) 63 | .call(axis); 64 | 65 | if (rotateLabels.allow) { 66 | var axisLength = Math.abs(scale.range()[1] - scale.range()[0]); 67 | var rotation = rotate() 68 | .axisLength(axisLength); 69 | 70 | g.call(builder(rotateLabels, rotation)); 71 | } 72 | 73 | g.append("text") 74 | .attr("class", title.class) 75 | .attr("x", title.x) 76 | .attr("y", title.y) 77 | .attr("dx", title.dx) 78 | .attr("dy", title.dy) 79 | .attr("transform", title.transform) 80 | .style("title-anchor", title.anchor) 81 | .text(title.text); 82 | }); 83 | } 84 | 85 | // Public API 86 | component.class = function (_) { 87 | if (!arguments.length) { return gClass; } 88 | gClass = _; 89 | return component; 90 | }; 91 | 92 | component.transform = function (_) { 93 | if (!arguments.length) { return transform; } 94 | transform = _; 95 | return component; 96 | }; 97 | 98 | component.scale = function (_) { 99 | if (!arguments.length) { return scale; } 100 | scale = _; 101 | return component; 102 | }; 103 | 104 | component.orient = function (_) { 105 | if (!arguments.length) { return orient; } 106 | orient = _; 107 | return component; 108 | }; 109 | 110 | component.tick = function (_) { 111 | if (!arguments.length) { return tick; } 112 | tick.number = typeof _.number !== "undefined" ? _.number : tick.number; 113 | tick.values = typeof _.values !== "undefined" ? _.values : tick.values; 114 | tick.size = typeof _.size !== "undefined" ? _.size : tick.size; 115 | tick.padding = typeof _.padding !== "undefined" ? _.padding : tick.padding; 116 | tick.format = typeof _.format !== "undefined" ? _.format : tick.format; 117 | tick.innerTickSize = typeof _.innerTickSize !== "undefined" ? _.innerTickSize : tick.innerTickSize; 118 | tick.outerTickSize = typeof _.outerTickSize !== "undefined" ? _.outerTickSize : tick.outerTickSize; 119 | return component; 120 | }; 121 | 122 | component.tickText = function (_) { 123 | if (!arguments.length) { return tickText; } 124 | tickText.transform = typeof _.transform !== "undefined" ? _.transform : tickText.transform; 125 | tickText.anchor = typeof _.anchor !== "undefined" ? _.anchor : tickText.anchor; 126 | tickText.x = typeof _.x !== "undefined" ? _.x : tickText.x; 127 | tickText.y = typeof _.y !== "undefined" ? _.y : tickText.y; 128 | tickText.dx = typeof _.dx !== "undefined" ? _.dx : tickText.dx; 129 | tickText.dy = typeof _.dy !== "undefined" ? _.dy : tickText.dy; 130 | return component; 131 | }; 132 | 133 | component.rotateLabels = function (_) { 134 | if (!arguments.length) { return rotateLabels; } 135 | rotateLabels = typeof _ !== "object" ? rotateLabels : _; 136 | return component; 137 | }; 138 | 139 | component.title = function (_) { 140 | if (!arguments.length) { return title; } 141 | title.class = typeof _.class !== "undefined" ? _.class : title.class; 142 | title.x = typeof _.x !== "undefined" ? _.x : title.x; 143 | title.y = typeof _.y !== "undefined" ? _.y : title.y; 144 | title.dx = typeof _.dx !== "undefined" ? _.dx : title.dx; 145 | title.dy = typeof _.dy !== "undefined" ? _.dy : title.dy; 146 | title.transform = typeof _.transform !== "undefined" ? _.transform : title.transform; 147 | title.anchor = typeof _.anchor !== "undefined" ? _.anchor : title.anchor; 148 | title.text = typeof _.text !== "undefined" ? _.text : title.text; 149 | return component; 150 | }; 151 | 152 | return component; 153 | }; 154 | }); 155 | -------------------------------------------------------------------------------- /src/modules/component/axis/rotate.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | var truncate = require("./truncate"); 4 | 5 | return function rotate() { 6 | // Private variables 7 | var axisLength = 100; 8 | var measure = "width"; 9 | var labelPadding = 5; 10 | var truncateLength = 10; 11 | var text = { 12 | transform: "translate(0,0)rotate(-45)", 13 | x: 0, 14 | y: 6, 15 | dx: "", 16 | dy: ".71em", 17 | anchor: "end" 18 | }; 19 | 20 | function component(g) { 21 | g.each(function () { 22 | var ticks = d3.select(this).selectAll(".tick text"); 23 | var numOfTicks = ticks[0].length; 24 | var maxTickLabelLength = (axisLength / numOfTicks) - labelPadding; 25 | var isRotated; 26 | 27 | ticks.each(function () { 28 | var labelLength = this.getBBox()[measure]; 29 | if (labelLength >= maxTickLabelLength) { isRotated = true; } 30 | }); 31 | 32 | // Rotate and truncate 33 | if (isRotated) { 34 | ticks 35 | .attr("transform", text.transform) 36 | .attr("x", text.x) 37 | .attr("y", text.y) 38 | .attr("dx", text.dx) 39 | .attr("dy", text.dy) 40 | .style("text-anchor", text.anchor); 41 | 42 | // Truncation logic goes here 43 | ticks.each(function () { 44 | d3.select(this) 45 | .call(truncate().maxCharLength(truncateLength)); 46 | }); 47 | } 48 | }); 49 | } 50 | 51 | // Public API 52 | component.axisLength = function (_) { 53 | if (!arguments.length) { return axisLength; } 54 | axisLength = typeof _ !== "number" ? axisLength : _; 55 | return component; 56 | }; 57 | 58 | component.measure = function (_) { 59 | if (!arguments.length) { return measure; } 60 | measure = typeof _ !== "string" ? measure : _; 61 | return component; 62 | }; 63 | 64 | component.labelPadding = function (_) { 65 | if (!arguments.length) { return labelPadding; } 66 | labelPadding = typeof _ !== "number" ? labelPadding : _; 67 | return component; 68 | }; 69 | 70 | component.truncateLength = function (_) { 71 | if (!arguments.length) { return truncateLength; } 72 | truncateLength = typeof _ !== "number" ? truncateLength : _; 73 | return component; 74 | }; 75 | 76 | component.text = function (_) { 77 | if (!arguments.length) { return text; } 78 | text.transform = typeof _.transform !== "undefined" ? _.transform : text.transform; 79 | text.x = typeof _.x !== "undefined" ? _.x : text.x; 80 | text.y = typeof _.y !== "undefined" ? _.y : text.y; 81 | text.dx = typeof _.dx !== "undefined" ? _.dx : text.dx; 82 | text.dy = typeof _.dy !== "undefined" ? _.dy : text.dy; 83 | text.anchor = typeof _.anchor !== "undefined" ? _.anchor : text.anchor; 84 | return component; 85 | }; 86 | 87 | return component; 88 | }; 89 | }); 90 | -------------------------------------------------------------------------------- /src/modules/component/axis/truncate.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function truncate() { 5 | // Private variables 6 | var maxCharLength = 10; 7 | 8 | function component(text) { 9 | text.each(function () { 10 | var txt = d3.select(this); 11 | var labelCharLength = txt.text().length; 12 | 13 | // Shorten label and append .. 14 | if (labelCharLength > maxCharLength) { 15 | var truncatedLabel = txt.text().slice(0, maxCharLength) + ".."; 16 | txt.text(truncatedLabel); 17 | } 18 | }); 19 | } 20 | 21 | // Public API 22 | component.maxCharLength = function (_) { 23 | if (!arguments.length) { return maxCharLength; } 24 | maxCharLength = typeof _ !== "number" ? maxCharLength : _; 25 | return component; 26 | }; 27 | 28 | return component; 29 | }; 30 | }); 31 | -------------------------------------------------------------------------------- /src/modules/component/boxplot.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function boxplot() { 5 | var gClass = "box"; 6 | var transform = null; 7 | 8 | // Box 9 | var box = { 10 | width: 20, 11 | height: null, 12 | y: null, 13 | class: "range", 14 | fill: "white", 15 | stroke: "black", 16 | strokeWidth: "2px" 17 | }; 18 | 19 | // Range 20 | var range = { 21 | x1: 0, 22 | x2: 0, 23 | y1: null, 24 | y2: null, 25 | class: "range", 26 | stroke: "black", 27 | strokeWidth: "4px" 28 | }; 29 | 30 | // Max 31 | var max = { 32 | y1: null, 33 | y2: null, 34 | class: "max", 35 | stroke: "black", 36 | strokeWidth: "4px" 37 | }; 38 | 39 | // Min 40 | var min = { 41 | y1: null, 42 | y2: null, 43 | class: "min", 44 | stroke: "black", 45 | strokeWidth: "4px" 46 | }; 47 | 48 | // Median 49 | var median = { 50 | y1: 0, 51 | y2: 0, 52 | class: "median", 53 | stroke: "darkgrey", 54 | strokeWidth: "4px" 55 | }; 56 | 57 | function component(selection) { 58 | selection.each(function () { 59 | var boxX = - (box.width / 2); 60 | var maxX1 = - (box.width / 2); 61 | var maxX2 = box.width / 2; 62 | var minX1 = - (box.width / 2); 63 | var minX2 = box.width / 2; 64 | var medianX1 = - (box.width / 2); 65 | var medianX2 = box.width / 2; 66 | 67 | var g = d3.select(this).selectAll("g.box") 68 | .data(function (d) { return d; }) 69 | .enter().append("g") 70 | .attr("class", gClass); 71 | 72 | g.attr("transform", transform) 73 | .each(function (d, i) { 74 | var g = d3.select(this); 75 | 76 | g.append("line") 77 | .attr("class", range.class) 78 | .attr("x1", range.x1) 79 | .attr("x2", range.x2) 80 | .attr("y1", range.y1) 81 | .attr("y2", range.y2) 82 | .style("stroke", range.stroke) 83 | .style("stroke-boxWidth", range.strokeWidth); 84 | 85 | g.append("line") 86 | .attr("class", max.class) 87 | .attr("x1", maxX1) 88 | .attr("x2", maxX2) 89 | .attr("y1", max.y1) 90 | .attr("y2", max.y2) 91 | .style("stroke", max.stroke) 92 | .style("stroke-boxWidth", max.strokeWidth); 93 | 94 | g.append("line") 95 | .attr("class", min.class) 96 | .attr("x1", minX1) 97 | .attr("x2", minX2) 98 | .attr("y1", min.y1) 99 | .attr("y2", min.y2) 100 | .style("stroke", min.stroke) 101 | .style("stroke-boxWidth", min.strokeWidth); 102 | 103 | g.append("rect") 104 | .attr("class", box.class) 105 | .attr("x", boxX) 106 | .attr("y", box.y) 107 | .attr("width", box.width) 108 | .attr("height", box.height) 109 | .style("fill", box.fill) 110 | .style("stroke", box.stroke) 111 | .style("stroke-boxWidth", box.strokeWidth); 112 | 113 | g.append("line") 114 | .attr("class", median.class) 115 | .attr("x1", medianX1) 116 | .attr("x2", medianX2) 117 | .attr("y1", median.y1) 118 | .attr("y2", median.y2) 119 | .style("stroke", median.stroke) 120 | .style("stroke-boxWidth", median.strokeWidth); 121 | }); 122 | }); 123 | } 124 | 125 | component.gClass = function (_) { 126 | if (!arguments.length) { return gClass; } 127 | gClass = _; 128 | return component; 129 | }; 130 | 131 | component.transform = function (_) { 132 | if (!arguments.length) { return transform; } 133 | transform = _; 134 | return component; 135 | }; 136 | 137 | component.box = function (_) { 138 | if (!arguments.length) { return box; } 139 | box.width = typeof _.width !== "undefined" ? _.width : box.width; 140 | box.height = typeof _.height !== "undefined" ? _.height : box.height; 141 | box.y = typeof _.y !== "undefined" ? _.y : box.y; 142 | box.class = typeof _.class !== "undefined" ? _.class : box.class; 143 | box.fill = typeof _.fill !== "undefined" ? _.fill : box.fill; 144 | box.stroke = typeof _.stroke !== "undefined" ? _.stroke : box.stroke; 145 | box.strokeWidth = typeof _.strokeWidth !== "undefined" ? _.strokeWidth : box.strokeWidth; 146 | return component; 147 | }; 148 | 149 | component.range = function (_) { 150 | if (!arguments.length) { return range; } 151 | range.x1 = typeof _.x1!== "undefined" ? _.x1: range.x1; 152 | range.x2 = typeof _.x2!== "undefined" ? _.x2 : range.x2; 153 | range.y1 = typeof _.y1 !== "undefined" ? _.y1 : range.y1; 154 | range.y2 = typeof _.y2 !== "undefined" ? _.y2 : range.y2; 155 | range.class = typeof _.class !== "undefined" ? _.class : range.class; 156 | range.stroke = typeof _.stroke !== "undefined" ? _.stroke : range.stroke; 157 | range.strokeWidth = typeof _.strokeWidth !== "undefined" ? _.strokeWidth : range.strokeWidth; 158 | return component; 159 | }; 160 | 161 | component.max = function (_) { 162 | if (!arguments.length) { return max; } 163 | max.y1 = typeof _.y1 !== "undefined" ? _.y1 : max.y1; 164 | max.y2 = typeof _.y2 !== "undefined" ? _.y2 : max.y2; 165 | max.class = typeof _.class !== "undefined" ? _.class : max.class; 166 | max.stroke = typeof _.stroke !== "undefined" ? _.stroke : max.stroke; 167 | max.strokeWidth = typeof _.strokeWidth !== "undefined" ? _.strokeWidth : max.strokeWidth; 168 | return component; 169 | }; 170 | 171 | component.min = function (_) { 172 | if (!arguments.length) { return min; } 173 | min.y1 = typeof _.y1 !== "undefined" ? _.y1 : min.y1; 174 | min.y2 = typeof _.y2 !== "undefined" ? _.y2 : min.y2; 175 | min.class = typeof _.class !== "undefined" ? _.class : min.class; 176 | min.stroke = typeof _.stroke !== "undefined" ? _.stroke : min.stroke; 177 | min.strokeWidth = typeof _.strokeWidth !== "undefined" ? _.strokeWidth : min.strokeWidth; 178 | return component; 179 | }; 180 | 181 | component.median = function (_) { 182 | if (!arguments.length) { return median; } 183 | median.y1 = typeof _.y1 !== "undefined" ? _.y1 : median.y1; 184 | median.y2 = typeof _.y2 !== "undefined" ? _.y2 : median.y2; 185 | median.class = typeof _.class !== "undefined" ? _.class : median.class; 186 | median.stroke = typeof _.stroke !== "undefined" ? _.stroke : median.stroke; 187 | median.strokeWidth = typeof _.strokeWidth !== "undefined" ? _.strokeWidth : median.strokeWidth; 188 | return component; 189 | }; 190 | 191 | return component; 192 | }; 193 | }); -------------------------------------------------------------------------------- /src/modules/component/clippath.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function clipPath() { 5 | var id = uniqueID(); 6 | var transform = "translate(0,0)"; 7 | var x = 0; 8 | var y = 0; 9 | var width = 0; 10 | var height = 0; 11 | 12 | function element(selection) { 13 | selection.each(function () { 14 | var g = d3.select(this); 15 | 16 | // Remove previous clip-path 17 | g.select("clipPath").remove(); 18 | 19 | g.append("clipPath") 20 | .attr("id", id) 21 | .attr("transform", transform) 22 | .append("rect") 23 | .attr("x", x) 24 | .attr("y", y) 25 | .attr("width", width) 26 | .attr("height", height); 27 | }); 28 | } 29 | 30 | function uniqueID() { 31 | var randomNumber = Math.floor(Math.random() * 100); 32 | return "uniqueId_" + randomNumber; 33 | } 34 | 35 | element.id = function (_) { 36 | if (!arguments.length) { return id; } 37 | id = _; 38 | return element; 39 | }; 40 | 41 | element.transform = function (_) { 42 | if (!arguments.length) { return transform; } 43 | transform = _; 44 | return element; 45 | }; 46 | 47 | element.x = function (_) { 48 | if (!arguments.length) { return x; } 49 | x = _; 50 | return element; 51 | }; 52 | 53 | element.y = function (_) { 54 | if (!arguments.length) { return y; } 55 | y = _; 56 | return element; 57 | }; 58 | 59 | element.width = function (_) { 60 | if (!arguments.length) { return width; } 61 | width = _; 62 | return element; 63 | }; 64 | 65 | element.height = function (_) { 66 | if (!arguments.length) { return height; } 67 | height = _; 68 | return element; 69 | }; 70 | 71 | return element; 72 | }; 73 | }); 74 | -------------------------------------------------------------------------------- /src/modules/component/events/brush.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | /** 5 | * Creates a brush component and binds it to an . 6 | */ 7 | return function brush() { 8 | // Private variables 9 | var margin = { top: 0, right: 0, bottom: 0, left: 0 }; 10 | var cssClass = "brush"; 11 | var opacity = 0.2; 12 | var width = null; 13 | var height = null; 14 | var xScale = null; 15 | var yScale = null; 16 | var extent = null; 17 | var clamp = false; 18 | var brushStartCallback = []; 19 | var brushCallback = []; 20 | var brushEndCallback = []; 21 | 22 | function component(selection) { 23 | selection.each(function (data, index) { 24 | width = width - margin.left - margin.right; 25 | height = height - margin.top - margin.bottom; 26 | 27 | var brush = d3.svg.brush() 28 | .on("brushstart", function () { 29 | brushStartCallback.forEach(function (listener) { 30 | listener.call(this, brush, data, index); 31 | }); 32 | }) 33 | .on("brush", function () { 34 | brushCallback.forEach(function (listener) { 35 | listener.call(this, brush, data, index); 36 | }); 37 | }) 38 | .on("brushend", function () { 39 | brushEndCallback.forEach(function (listener) { 40 | listener.call(this, brush, data, index); 41 | 42 | // Clear brush 43 | d3.selectAll("g." + cssClass) 44 | .call(brush.clear()); 45 | }); 46 | }); 47 | 48 | if (xScale) { brush.x(xScale); } 49 | if (yScale) { brush.y(yScale); } 50 | if (extent) { brush.extent(extent); } 51 | if (clamp) { brush.clamp(clamp); } 52 | 53 | var brushG = d3.select(this); 54 | 55 | // Remove previous brush 56 | brushG.select("g." + cssClass).remove(); 57 | 58 | // Attach new brush 59 | brushG.append("g") 60 | .attr("class", cssClass) 61 | .attr("opacity", opacity) 62 | .call(brush) 63 | .selectAll("rect"); 64 | 65 | if (width) { brushG.attr("width", width); } 66 | if (height) { brushG.attr("height", height); } 67 | }); 68 | } 69 | 70 | // Public API 71 | component.margin = function (_) { 72 | if (!arguments.length) { return margin; } 73 | margin.top = typeof _.top !== "undefined" ? _.top : margin.top; 74 | margin.right = typeof _.right !== "undefined" ? _.right : margin.right; 75 | margin.bottom = typeof _.bottom !== "undefined" ? _.bottom : margin.bottom; 76 | margin.left = typeof _.left !== "undefined" ? _.left : margin.left; 77 | return component; 78 | }; 79 | 80 | component.width = function (_) { 81 | if (!arguments.length) { return width; } 82 | width = _; 83 | return component; 84 | }; 85 | 86 | component.height = function (_) { 87 | if (!arguments.length) { return height; } 88 | height = _; 89 | return component; 90 | }; 91 | 92 | component.opacity = function (_) { 93 | if (!arguments.length) { return opacity; } 94 | opacity = _; 95 | return component; 96 | }; 97 | 98 | component.class = function (_) { 99 | if (!arguments.length) { return cssClass; } 100 | cssClass = _; 101 | return component; 102 | }; 103 | 104 | component.xScale = function (_) { 105 | if (!arguments.length) { return xScale; } 106 | xScale = _; 107 | return component; 108 | }; 109 | 110 | component.yScale = function (_) { 111 | if (!arguments.length) { return yScale; } 112 | yScale = _; 113 | return component; 114 | }; 115 | 116 | component.extent = function (_) { 117 | if (!arguments.length) { return extent; } 118 | extent = _; 119 | return component; 120 | }; 121 | 122 | component.clamp = function (_) { 123 | if (!arguments.length) { return clamp; } 124 | clamp = _; 125 | return component; 126 | }; 127 | 128 | component.brushstart = function (_) { 129 | if (!arguments.length) { return brushStartCallback; } 130 | if (typeof _ === "function") { brushStartCallback.push(_); } 131 | else if (Array.isArray(_)) { brushStartCallback = _; } 132 | return component; 133 | }; 134 | 135 | component.brush = function (_) { 136 | if (!arguments.length) { return brushCallback; } 137 | if (typeof _ === "function") { brushCallback.push(_); } 138 | else if (Array.isArray(_)) { brushCallback = _; } 139 | return component; 140 | }; 141 | 142 | component.brushend = function (_) { 143 | if (!arguments.length) { return brushEndCallback; } 144 | if (typeof _ === "function") { brushEndCallback.push(_); } 145 | else if (Array.isArray(_)) { brushEndCallback = _; } 146 | return component; 147 | }; 148 | 149 | return component; 150 | }; 151 | }); -------------------------------------------------------------------------------- /src/modules/component/events/events.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Adds event listeners to DOM elements 3 | */ 4 | define(function (require) { 5 | var d3 = require("d3"); 6 | var targetIndex = require("src/modules/helpers/target_index"); 7 | 8 | return function events() { 9 | // Private variables 10 | var listeners = {}; 11 | 12 | function component(selection) { 13 | selection.each(function () { 14 | var element = d3.select(this); 15 | 16 | d3.entries(listeners).forEach(function (e) { 17 | // Stop listening for event types that have 18 | // an empty listeners array or that is set to null 19 | if (!e.value || !e.value.length) { 20 | return element.on(e.key, null); 21 | } 22 | 23 | element.on(e.key, function () { 24 | d3.event.stopPropagation(); // => event.stopPropagation() 25 | 26 | e.value.forEach(function (listener) { 27 | // References the data point to calculate the correct index value 28 | var svg = d3.event.target.farthestViewportElement; 29 | var target = d3.select(d3.event.target); 30 | var parent = !svg ? d3.select(d3.event.target) : d3.select(svg); 31 | var datum = target.datum(); 32 | var index = targetIndex(parent, target) || 0; 33 | 34 | listener.call(this, d3.event, datum, index); 35 | }); 36 | }); 37 | }); 38 | }); 39 | } 40 | 41 | // Public API 42 | component.listeners = function (_) { 43 | if (!arguments.length) { return listeners; } 44 | listeners = typeof _ === "object" ? _ : listeners; 45 | return component; 46 | }; 47 | 48 | return component; 49 | }; 50 | }); -------------------------------------------------------------------------------- /src/modules/component/legend.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function legend() { 5 | // Private variables 6 | var color = d3.scale.category10(); 7 | var symbol = { type: "circle", size: 3 }; 8 | var cell = { width: 50, padding: 5 }; 9 | var values = []; 10 | var orientation = "horizontal"; 11 | var position = "nw"; 12 | var fill = function (d) { return color(d); }; 13 | var stroke = "#000000"; 14 | var strokeWidth = 1; 15 | var text = ""; 16 | 17 | function component(g) { 18 | g.each(function () { 19 | var shape = d3.svg.symbol() 20 | .type(symbol.type) 21 | .size(symbol.size); 22 | 23 | g.selectAll("g.legend-cells") 24 | .data(values) 25 | .enter().append("g") 26 | .attr("class", "legend-cells") 27 | .attr("transform", function (d, i) { 28 | return "translate(" + (i * (cell.width + cell.padding)) + ",0)"; 29 | }); 30 | 31 | g.selectAll("g.legend-cells") 32 | .append("path") 33 | .attr("d", shape) 34 | .style("fill", fill) 35 | .style("stroke", stroke) 36 | .style("stroke-width", strokeWidth); 37 | 38 | g.selectAll("g.legend-cells") 39 | .append("text") 40 | .attr("class", "legend-labels") 41 | .attr("y", -7) 42 | .style("pointer-events", "none") 43 | .text(text); 44 | }); 45 | } 46 | 47 | return component; 48 | }; 49 | }); -------------------------------------------------------------------------------- /src/modules/component/scale.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | var builder = require("builder"); 4 | var scalator = require("src/modules/helpers/scaletor"); 5 | 6 | return function scale() { 7 | // Private variables 8 | var type = d3.scale.linear(); 9 | var domain = null; 10 | var rangeType = "range"; 11 | var rangeValue = null; 12 | var padding = 0; 13 | var innerPadding = 0; 14 | var outerPadding = 0; 15 | var opts = {}; 16 | 17 | function component(data) { 18 | if (domain) { type.domain(domain.call(null, data)); } 19 | 20 | if (typeof type[rangeType] === "function" && rangeValue) { 21 | if (rangeType === "rangePoints" || rangeType === "rangeRoundPoints") { 22 | type[rangeType](rangeValue, padding); 23 | } else if (rangeType === "rangeBands" || rangeType === "rangeRoundBands") { 24 | type[rangeType](rangeValue, innerPadding, outerPadding); 25 | } else { 26 | type[rangeType](rangeValue); 27 | } 28 | } 29 | 30 | return builder(opts, type); 31 | } 32 | 33 | // Public API 34 | component.type = function (_) { 35 | if (!arguments.length) { return type; } 36 | type = scalator(_); 37 | return component; 38 | }; 39 | 40 | component.domain = function (_) { 41 | if (!arguments.length) { return domain; } 42 | domain = d3.functor(_); 43 | return component; 44 | }; 45 | 46 | component.rangeType = function (_) { 47 | if (!arguments.length) { return rangeType; } 48 | rangeType = typeof _ === "string" ? _ : rangeType; 49 | return component; 50 | }; 51 | 52 | component.rangeValue = function (_) { 53 | if (!arguments.length) { return rangeValue; } 54 | rangeValue = Array.isArray(_) ? _ : rangeValue; 55 | return component; 56 | }; 57 | 58 | component.padding = function (_) { 59 | if (!arguments.length) { return padding; } 60 | padding = typeof _ === "number" ? _ : padding; 61 | return component; 62 | }; 63 | 64 | component.innerPadding = function (_) { 65 | if (!arguments.length) { return innerPadding; } 66 | innerPadding = typeof _ === "number" ? _ : innerPadding; 67 | return component; 68 | }; 69 | 70 | component.outerPadding = function (_) { 71 | if (!arguments.length) { return outerPadding; } 72 | outerPadding = typeof _ === "number" ? _ : outerPadding; 73 | return component; 74 | }; 75 | 76 | component.options = function (_) { 77 | if (!arguments.length) { return opts; } 78 | if (arguments.length === 1 && typeof _ === "string") { return opts[_]; } 79 | opts = typeof _ === "object" ? _ : opts; 80 | return component; 81 | }; 82 | 83 | return component; 84 | }; 85 | }); 86 | -------------------------------------------------------------------------------- /src/modules/component/series/area.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | var path = require("src/modules/element/svg/path"); 4 | var builder = require("builder"); 5 | var valuator = require("valuator"); 6 | 7 | return function area() { 8 | // Private variables 9 | var x = function (d) { return d.x; }; 10 | var y = function (d) { return d.y; }; 11 | var xScale = d3.time.scale.utc(); 12 | var yScale = d3.scale.linear(); 13 | var offset = "zero"; 14 | var interpolate = "linear"; 15 | var tension = 0.7; 16 | var defined = function (d) { return d.y !== null; }; 17 | var properties = { 18 | class: "area", 19 | fill: function (d, i) { return d3.scale.category10()(i); }, 20 | stroke: function (d, i) { return d3.scale.category10()(i); }, 21 | strokeWidth: 0, 22 | opacity: 1 23 | }; 24 | 25 | function component(selection) { 26 | selection.each(function () { 27 | var areas = d3.svg.area().x(X).y0(Y0).y1(Y1) 28 | .interpolate(interpolate) 29 | .tension(tension) 30 | .defined(defined); 31 | 32 | var areaPath = path().pathGenerator(areas); 33 | 34 | d3.select(this) 35 | .append("g") 36 | .call(builder(properties, areaPath)); 37 | }); 38 | } 39 | 40 | function X(d, i) { 41 | return xScale(x.call(this, d, i)); 42 | } 43 | 44 | function Y0(d) { 45 | var min = Math.max(0, yScale.domain()[0]); 46 | if (offset === "overlap") { 47 | return yScale(min); 48 | } 49 | return yScale(d.y0); 50 | } 51 | 52 | function Y1(d, i) { 53 | if (offset === "overlap") { 54 | return yScale(y.call(this, d, i)); 55 | } 56 | return yScale(d.y0 + y.call(this, d, i)); 57 | } 58 | 59 | // Public API 60 | component.x = function (_) { 61 | if (!arguments.length) { return x; } 62 | x = valuator(_); 63 | return component; 64 | }; 65 | 66 | component.y = function (_) { 67 | if (!arguments.length) { return y; } 68 | y = valuator(_); 69 | return component; 70 | }; 71 | 72 | component.xScale = function (_) { 73 | if (!arguments.length) { return xScale; } 74 | xScale = _; 75 | return component; 76 | }; 77 | 78 | component.yScale = function (_) { 79 | if (!arguments.length) { return yScale; } 80 | yScale = _; 81 | return component; 82 | }; 83 | 84 | component.offset = function (_) { 85 | if (!arguments.length) { return offset; } 86 | offset = _; 87 | return component; 88 | }; 89 | 90 | component.interpolate = function (_) { 91 | if (!arguments.length) { return interpolate; } 92 | interpolate = _; 93 | return component; 94 | }; 95 | 96 | component.tension = function (_) { 97 | if (!arguments.length) { return tension; } 98 | tension = _; 99 | return component; 100 | }; 101 | 102 | component.defined = function (_) { 103 | if (!arguments.length) { return defined; } 104 | defined = _; 105 | return component; 106 | }; 107 | 108 | component.properties = function (_) { 109 | if (!arguments.length) { return properties; } 110 | properties.class = typeof _.class !== "undefined" ? _.class : properties.class; 111 | properties.fill = typeof _.fill !== "undefined" ? _.fill : properties.fill; 112 | properties.stroke = typeof _.stroke !== "undefined" ? _.stroke : properties.stroke; 113 | properties.strokeWidth = typeof _.strokeWidth !== "undefined" ? _.strokeWidth : properties.strokeWidth; 114 | properties.opacity = typeof _.opacity !== "undefined" ? _.opacity : properties.opacity; 115 | return component; 116 | }; 117 | 118 | return component; 119 | }; 120 | }); -------------------------------------------------------------------------------- /src/modules/component/series/bars.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | var rect = require("src/modules/element/svg/rect"); 4 | var builder = require("builder"); 5 | var valuator = require("valuator"); 6 | var parseTime = require("src/modules/helpers/timeparser"); 7 | 8 | return function points() { 9 | // Private variables 10 | var x = function (d) { return d.x; }; 11 | var y = function (d) { return d.y0 + d.y; }; 12 | var xScale = d3.time.scale.utc(); 13 | var yScale = d3.scale.linear(); 14 | var rx = 0; 15 | var ry = 0; 16 | var group = false; 17 | var interval = "30s"; 18 | var padding = 0.1; 19 | var groupPadding = 0; 20 | var properties = { 21 | class: "point", 22 | fill: function (d, i) { return d3.scale.category10()(i); }, 23 | stroke: function (d, i) { return d3.scale.category10()(i); }, 24 | strokeWidth: 0, 25 | opacity: 1 26 | }; 27 | 28 | function component(selection) { 29 | selection.each(function (data) { 30 | var timeNotation = parseTime(interval); 31 | var extent = d3.extent(d3.merge(data), x); 32 | var step = parseFloat(interval); 33 | var start = extent[0]; 34 | var stop = d3.time[timeNotation].offset(extent[1], step); 35 | 36 | // Used only to determine the width of bars for time scales 37 | var timeScale = d3.scale.ordinal() 38 | .domain(d3.time[timeNotation].range(start, stop, step)) 39 | .rangeBands(xScale.range(), padding, 0); 40 | 41 | var groupScale = d3.scale.ordinal() 42 | .domain(d3.range(data.length)) 43 | .rangeRoundBands([0, timeScale.rangeBand()], groupPadding, 0); 44 | 45 | var j = -1; 46 | 47 | var rects = rect() 48 | .x(function (d, i) { 49 | if (group) { 50 | if (i === 0) { j++; } 51 | return xScale(x.call(this, d, i)) + groupScale(j); 52 | } 53 | return xScale(x.call(this, d, i)); 54 | }) 55 | .y(function (d, i) { 56 | if (group) { 57 | return yScale(y.call(this, d, i)); 58 | } 59 | return yScale(d.y0 + Math.abs(y.call(this, d, i))); 60 | }) 61 | .width(function () { 62 | if (group) { 63 | return groupScale.rangeBand(); 64 | } 65 | return timeScale.rangeBand(); 66 | }) 67 | .height(function (d, i) { 68 | return yScale(d.y0) - yScale(d.y0 + Math.abs(y.call(this, d, i))); 69 | }) 70 | .rx(rx) 71 | .ry(ry); 72 | 73 | d3.select(this).append("g") 74 | .selectAll("g") 75 | .data(data) 76 | .enter().append("g") 77 | .call(builder(properties, rects)); 78 | }); 79 | } 80 | 81 | // Public API 82 | component.x = function (_) { 83 | if (!arguments.length) { return x; } 84 | x = valuator(_); 85 | return component; 86 | }; 87 | 88 | component.y = function (_) { 89 | if (!arguments.length) { return y; } 90 | y = valuator(_); 91 | return component; 92 | }; 93 | 94 | component.rx = function (_) { 95 | if (!arguments.length) { return rx; } 96 | rx = _; 97 | return component; 98 | }; 99 | 100 | component.ry = function (_) { 101 | if (!arguments.length) { return ry; } 102 | ry = _; 103 | return component; 104 | }; 105 | 106 | component.interval = function (_) { 107 | if (!arguments.length) { return interval; } 108 | interval = _; 109 | return component; 110 | }; 111 | 112 | component.group = function (_) { 113 | if (!arguments.length) { return group; } 114 | group = _; 115 | return component; 116 | }; 117 | 118 | component.padding = function (_) { 119 | if (!arguments.length) { return padding; } 120 | padding = _; 121 | return component; 122 | }; 123 | 124 | component.groupPadding = function (_) { 125 | if (!arguments.length) { return groupPadding; } 126 | groupPadding = _; 127 | return component; 128 | }; 129 | 130 | component.xScale = function (_) { 131 | if (!arguments.length) { return xScale; } 132 | xScale = _; 133 | return component; 134 | }; 135 | 136 | component.yScale = function (_) { 137 | if (!arguments.length) { return yScale; } 138 | yScale = _; 139 | return component; 140 | }; 141 | 142 | component.properties = function (_) { 143 | if (!arguments.length) { return properties; } 144 | properties.class = typeof _.class !== "undefined" ? _.class : properties.class; 145 | properties.fill = typeof _.fill !== "undefined" ? _.fill : properties.fill; 146 | properties.stroke = typeof _.stroke !== "undefined" ? _.stroke : properties.stroke; 147 | properties.strokeWidth = typeof _.strokeWidth !== "undefined" ? _.strokeWidth : properties.strokeWidth; 148 | properties.opacity = typeof _.opacity !== "undefined" ? _.opacity : properties.opacity; 149 | return component; 150 | }; 151 | 152 | return component; 153 | }; 154 | }); -------------------------------------------------------------------------------- /src/modules/component/series/line.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | var path = require("src/modules/element/svg/path"); 4 | var builder = require("builder"); 5 | var valuator = require("valuator"); 6 | 7 | return function line() { 8 | // Private variables 9 | var x = function (d) { return d.x; }; 10 | var y = function (d) { return d.y; }; 11 | var xScale = d3.time.scale.utc(); 12 | var yScale = d3.scale.linear(); 13 | var interpolate = "linear"; 14 | var tension = 0.7; 15 | var defined = function (d) { return d.y !== null; }; 16 | var properties = { 17 | class: "line", 18 | fill: "none", 19 | stroke: function (d, i) { return d3.scale.category10()(i); }, 20 | strokeWidth: 3, 21 | opacity: 1 22 | }; 23 | 24 | function component(selection) { 25 | selection.each(function () { 26 | var lines = d3.svg.line().x(X).y(Y) 27 | .interpolate(interpolate) 28 | .tension(tension) 29 | .defined(defined); 30 | 31 | var linePath = path().pathGenerator(lines); 32 | 33 | d3.select(this) 34 | .append("g") 35 | .call(builder(properties, linePath)); 36 | }); 37 | } 38 | 39 | function X(d, i) { 40 | return xScale(x.call(this, d, i)); 41 | } 42 | 43 | function Y(d, i) { 44 | return yScale(y.call(this, d, i)); 45 | } 46 | 47 | // Public API 48 | component.x = function (_) { 49 | if (!arguments.length) { return x; } 50 | x = valuator(_); 51 | return component; 52 | }; 53 | 54 | component.y = function (_) { 55 | if (!arguments.length) { return y; } 56 | y = valuator(_); 57 | return component; 58 | }; 59 | 60 | component.xScale = function (_) { 61 | if (!arguments.length) { return xScale; } 62 | xScale = _; 63 | return component; 64 | }; 65 | 66 | component.yScale = function (_) { 67 | if (!arguments.length) { return yScale; } 68 | yScale = _; 69 | return component; 70 | }; 71 | 72 | component.interpolate = function (_) { 73 | if (!arguments.length) { return interpolate; } 74 | interpolate = _; 75 | return component; 76 | }; 77 | 78 | component.tension = function (_) { 79 | if (!arguments.length) { return tension; } 80 | tension = _; 81 | return component; 82 | }; 83 | 84 | component.defined = function (_) { 85 | if (!arguments.length) { return defined; } 86 | defined = _; 87 | return component; 88 | }; 89 | 90 | component.properties = function (_) { 91 | if (!arguments.length) { return properties; } 92 | properties.class = typeof _.class !== "undefined" ? _.class : properties.class; 93 | properties.fill = typeof _.fill !== "undefined" ? _.fill : properties.fill; 94 | properties.stroke = typeof _.stroke !== "undefined" ? _.stroke : properties.stroke; 95 | properties.strokeWidth = typeof _.strokeWidth !== "undefined" ? _.strokeWidth : properties.strokeWidth; 96 | properties.opacity = typeof _.opacity !== "undefined" ? _.opacity : properties.opacity; 97 | return component; 98 | }; 99 | 100 | return component; 101 | }; 102 | }); 103 | -------------------------------------------------------------------------------- /src/modules/component/series/points.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | var circle = require("src/modules/element/svg/circle"); 4 | var builder = require("builder"); 5 | var valuator = require("valuator"); 6 | 7 | return function points() { 8 | // Private variables 9 | var x = function (d) { return d.x; }; 10 | var y = function (d) { return d.y; }; 11 | var xScale = d3.time.scale.utc(); 12 | var yScale = d3.scale.linear(); 13 | var radius = 5; 14 | var properties = { 15 | class: "point", 16 | fill: function (d, i) { return d3.scale.category10()(i); }, 17 | stroke: function (d, i) { return d3.scale.category10()(i); }, 18 | strokeWidth: 0, 19 | opacity: 1 20 | }; 21 | 22 | function component(selection) { 23 | selection.each(function (data) { 24 | var circles = circle() 25 | .cx(X) 26 | .cy(Y) 27 | .radius(radius); 28 | 29 | d3.select(this).append("g") 30 | .datum(data.reduce(function (a, b) { 31 | return a.concat(b); 32 | },[]).filter(y)) 33 | .call(builder(properties, circles)); 34 | }); 35 | } 36 | 37 | function X(d, i) { 38 | return xScale(x.call(this, d, i)); 39 | } 40 | 41 | function Y(d, i) { 42 | return yScale(y.call(this, d, i)); 43 | } 44 | 45 | // Public API 46 | component.x = function (_) { 47 | if (!arguments.length) { return x; } 48 | x = valuator(_); 49 | return component; 50 | }; 51 | 52 | component.y = function (_) { 53 | if (!arguments.length) { return y; } 54 | y = valuator(_); 55 | return component; 56 | }; 57 | 58 | component.radius = function (_) { 59 | if (!arguments.length) { return radius; } 60 | radius = _; 61 | return component; 62 | }; 63 | 64 | component.xScale = function (_) { 65 | if (!arguments.length) { return xScale; } 66 | xScale = _; 67 | return component; 68 | }; 69 | 70 | component.yScale = function (_) { 71 | if (!arguments.length) { return yScale; } 72 | yScale = _; 73 | return component; 74 | }; 75 | 76 | component.properties = function (_) { 77 | if (!arguments.length) { return properties; } 78 | properties.class = typeof _.class !== "undefined" ? _.class : properties.class; 79 | properties.fill = typeof _.fill !== "undefined" ? _.fill : properties.fill; 80 | properties.stroke = typeof _.stroke !== "undefined" ? _.stroke : properties.stroke; 81 | properties.strokeWidth = typeof _.strokeWidth !== "undefined" ? _.strokeWidth : properties.strokeWidth; 82 | properties.opacity = typeof _.opacity !== "undefined" ? _.opacity : properties.opacity; 83 | return component; 84 | }; 85 | 86 | return component; 87 | }; 88 | }); 89 | -------------------------------------------------------------------------------- /src/modules/element/canvas/rect.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function rect() { 5 | // Private variables 6 | var x = function (d) { return d.x; }; 7 | var y = function (d) { return d.y; }; 8 | var width = 10; 9 | var height = 10; 10 | 11 | var cssClass = "rect"; 12 | var fillStyle = "blue"; 13 | var lineWidth = 3; 14 | var strokeStyle = "black"; 15 | var globalAlpha = 1; 16 | 17 | function element(selection) { 18 | selection.each(function (data, index) { 19 | var canvas = d3.select(this); 20 | var context = canvas.node().getContext("2d"); 21 | // var container = canvas.append("custom"); 22 | 23 | canvas.node().addEventListener("click", function (event) { 24 | console.log(event); 25 | }); 26 | 27 | // Clear Canvas 28 | context.fillStyle = "#fff"; 29 | context.rect(0, 0, canvas.attr("width"), canvas.attr("height")); 30 | context.fill(); 31 | 32 | data.forEach(function (d, i) { 33 | d.fillStyle = (typeof fillStyle === "function") ? fillStyle.call(data, d, i) : fillStyle; 34 | d.strokeStyle = (typeof strokeStyle === "function") ? strokeStyle.call(data, d, i) : strokeStyle; 35 | d.globalAlpha = (typeof globalAlpha === "function") ? globalAlpha.call(data, d, i) : globalAlpha; 36 | d.lineWidth = (typeof lineWidth === "function") ? lineWidth.call(data, d, i) : lineWidth; 37 | d.width = (typeof width === "function") ? width.call(data, d, i) : width; 38 | d.height = (typeof height === "function") ? height.call(data, d, i) : height; 39 | 40 | context.beginPath(); 41 | context.fillStyle = d.fillStyle; 42 | context.strokeStyle = d.strokeStyle; 43 | context.lineWidth = d.lineWidth; 44 | context.globalAlpha = d.globalAlpha; 45 | context.rect(x.call(data, d, i), y.call(data, d, i), d.width, d.height); 46 | context.fill(); 47 | context.closePath(); 48 | }); 49 | 50 | // var rects = container.selectAll("custom.rect") 51 | // .data(data); 52 | 53 | // // Exit 54 | // rects.exit().remove(); 55 | 56 | // // Enter 57 | // rects.enter().append("custom"); 58 | 59 | // // Update 60 | // rects 61 | // .attr("class", cssClass) 62 | // .attr("x", x) 63 | // .attr("y", y) 64 | // .attr("width", width) 65 | // .attr("height", height) 66 | // .attr("fillStyle", fillStyle) 67 | // .attr("lineWidth", lineWidth) 68 | // .attr("globalAlpha", globalAlpha) 69 | // .attr("strokeStyle", strokeStyle); 70 | 71 | // // Clear Canvas 72 | // context.fillStyle = "#fff"; 73 | // context.rect(0, 0, canvas.attr("width"), canvas.attr("height")); 74 | // context.fill(); 75 | 76 | // var elements = container.selectAll("custom.rect"); 77 | 78 | // elements.each(function (d, i) { 79 | // var node = d3.select(this); 80 | 81 | // context.beginPath(); 82 | // context.fillStyle = node.attr("fillstyle"); 83 | // context.globalAlpha = node.attr("globalAlpha"); 84 | // context.rect(node.attr("x"), node.attr("y"), node.attr("width"), node.attr("height")); 85 | // context.fill(); 86 | // context.closePath(); 87 | // }); 88 | }); 89 | } 90 | 91 | // Public API 92 | element.class = function (_) { 93 | if (!arguments.length) { return cssClass; } 94 | cssClass = _; 95 | return element; 96 | }; 97 | 98 | element.x = function (_) { 99 | if (!arguments.length) { return x; } 100 | x = _; 101 | return element; 102 | }; 103 | 104 | element.y = function (_) { 105 | if (!arguments.length) { return y; } 106 | y = _; 107 | return element; 108 | }; 109 | 110 | element.width = function (_) { 111 | if (!arguments.length) { return width; } 112 | width = _; 113 | return element; 114 | }; 115 | 116 | element.height = function (_) { 117 | if (!arguments.length) { return height; } 118 | height = _; 119 | return element; 120 | }; 121 | 122 | element.fillStyle = function (_) { 123 | if (!arguments.length) { return fillStyle; } 124 | fillStyle = _; 125 | return element; 126 | }; 127 | 128 | element.opacity = function (_) { 129 | if (!arguments.length) { return globalAlpha; } 130 | globalAlpha = _; 131 | return element; 132 | }; 133 | 134 | element.lineWidth = function (_) { 135 | if (!arguments.length) { return lineWidth; } 136 | lineWidth = _; 137 | return element; 138 | }; 139 | 140 | element.strokeStyle = function (_) { 141 | if (!arguments.length) { return strokeStyle; } 142 | strokeStyle = _; 143 | return element; 144 | }; 145 | 146 | return element; 147 | }; 148 | }); 149 | -------------------------------------------------------------------------------- /src/modules/element/svg/circle.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function circle() { 5 | var accessor = function (d) { return d; }; 6 | var cx = function (d) { return d.x; }; 7 | var cy = function (d) { return d.y; }; 8 | var radius = 5; 9 | 10 | // Options 11 | var cssClass = "circles"; 12 | var fill = colorFill; 13 | var stroke = colorFill; 14 | var strokeWidth = 0; 15 | var opacity = null; 16 | 17 | function element(selection) { 18 | selection.each(function (data, index) { 19 | data = accessor.call(this, data, index); 20 | 21 | var circles = d3.select(this) 22 | .selectAll("." + cssClass) 23 | .data(data); 24 | 25 | // Exit 26 | circles.exit().remove(); 27 | 28 | // Enter 29 | circles 30 | .enter().append("circle"); 31 | 32 | // Update 33 | circles 34 | .attr("class", cssClass) 35 | .attr("fill", fill) 36 | .attr("stroke", stroke) 37 | .attr("stroke-width", strokeWidth) 38 | .attr("r", radius) 39 | .attr("cx", cx) 40 | .attr("cy", cy) 41 | .style("opacity", opacity); 42 | }); 43 | } 44 | 45 | function colorFill (d, i) { 46 | return d3.scale.category10()(i); 47 | } 48 | 49 | // Public API 50 | element.accessor = function (_) { 51 | if (!arguments.length) { return accessor; } 52 | accessor = _; 53 | return element; 54 | }; 55 | 56 | element.cx = function (_) { 57 | if (!arguments.length) { return cx; } 58 | cx = _; 59 | return element; 60 | }; 61 | 62 | element.cy = function (_) { 63 | if (!arguments.length) { return cy; } 64 | cy = _; 65 | return element; 66 | }; 67 | 68 | element.radius = function (_) { 69 | if (!arguments.length) { return radius; } 70 | radius = _; 71 | return element; 72 | }; 73 | 74 | element.class = function (_) { 75 | if (!arguments.length) { return cssClass; } 76 | cssClass = _; 77 | return element; 78 | }; 79 | 80 | element.fill = function (_) { 81 | if (!arguments.length) { return fill; } 82 | fill = _; 83 | return element; 84 | }; 85 | 86 | element.opacity = function (_) { 87 | if (!arguments.length) { return opacity; } 88 | opacity = _; 89 | return element; 90 | }; 91 | 92 | element.stroke = function (_) { 93 | if (!arguments.length) { return stroke; } 94 | stroke = _; 95 | return element; 96 | }; 97 | 98 | element.strokeWidth = function (_) { 99 | if (!arguments.length) { return strokeWidth; } 100 | strokeWidth = _; 101 | return element; 102 | }; 103 | 104 | return element; 105 | }; 106 | }); 107 | -------------------------------------------------------------------------------- /src/modules/element/svg/ellipse.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function ellipse() { 5 | var accessor = function (d) { return d; }; 6 | var cx = function (d) { return d.x; }; 7 | var cy = function (d) { return d.y; }; 8 | var rx = 20; 9 | var ry = 20; 10 | 11 | // Options 12 | var cssClass = "ellipses"; 13 | var fill = colorFill; 14 | var stroke = colorFill; 15 | var strokeWidth = 0; 16 | var opacity = null; 17 | 18 | function element(selection) { 19 | selection.each(function (data, index) { 20 | data = accessor.call(this, data, index); 21 | 22 | var ellipses = d3.select(this) 23 | .selectAll("." + cssClass) 24 | .data(data); 25 | 26 | // Exit 27 | ellipses.exit().remove(); 28 | 29 | // Enter 30 | ellipses.enter().append("ellipse"); 31 | 32 | // Update 33 | ellipses 34 | .attr("class", cssClass) 35 | .attr("fill", fill) 36 | .attr("stroke", stroke) 37 | .attr("stroke-width", strokeWidth) 38 | .attr("cx", cx) 39 | .attr("cy", cy) 40 | .attr("rx", rx) 41 | .attr("ry", ry) 42 | .style("opacity", opacity); 43 | }); 44 | } 45 | 46 | function colorFill(d, i) { 47 | return d3.scale.category10()(i); 48 | } 49 | 50 | // Public API 51 | element.accessor = function (_) { 52 | if (!arguments.length) { return accessor; } 53 | accessor = _; 54 | return element; 55 | }; 56 | 57 | element.cx = function (_) { 58 | if (!arguments.length) { return cx; } 59 | cx = _; 60 | return element; 61 | }; 62 | 63 | element.cy = function (_) { 64 | if (!arguments.length) { return cy; } 65 | cy = _; 66 | return element; 67 | }; 68 | 69 | element.rx = function (_) { 70 | if (!arguments.length) { return rx; } 71 | rx = _; 72 | return element; 73 | }; 74 | 75 | element.ry = function (_) { 76 | if (!arguments.length) { return ry; } 77 | ry = _; 78 | return element; 79 | }; 80 | 81 | element.class = function (_) { 82 | if (!arguments.length) { return cssClass; } 83 | cssClass = _; 84 | return element; 85 | }; 86 | 87 | element.fill = function (_) { 88 | if (!arguments.length) { return fill; } 89 | fill = _; 90 | return element; 91 | }; 92 | 93 | element.opacity = function (_) { 94 | if (!arguments.length) { return opacity; } 95 | opacity = _; 96 | return element; 97 | }; 98 | 99 | element.stroke = function (_) { 100 | if (!arguments.length) { return stroke; } 101 | stroke = _; 102 | return element; 103 | }; 104 | 105 | element.strokeWidth = function (_) { 106 | if (!arguments.length) { return strokeWidth; } 107 | strokeWidth = _; 108 | return element; 109 | }; 110 | 111 | return element; 112 | }; 113 | }); 114 | -------------------------------------------------------------------------------- /src/modules/element/svg/image.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function image() { 5 | var accessor = function (d) { return d; }; 6 | var x = function (d) { return d.x; }; 7 | var y = function (d) { return d.y; }; 8 | var width = 10; 9 | var height = 10; 10 | var xlink = null; 11 | var preserveAspectRatio = null; 12 | 13 | // Options 14 | var cssClass = "image"; 15 | 16 | function element(selection) { 17 | selection.each(function (data, index) { 18 | data = accessor.call(this, data, index); 19 | 20 | var images = d3.select(this) 21 | .selectAll("." + cssClass) 22 | .data(data); 23 | 24 | // Exit 25 | images.exit().remove(); 26 | 27 | // Enter 28 | images.enter().append("image"); 29 | 30 | // Update 31 | images 32 | .attr("class", cssClass) 33 | .attr("x", x) 34 | .attr("y", y) 35 | .attr("width", width) 36 | .attr("height", height) 37 | .attr("xlink:href", xlink) 38 | .attr("preserveAspectRatio", preserveAspectRatio); 39 | }); 40 | } 41 | 42 | // Public API 43 | element.accessor = function (_) { 44 | if (!arguments.length) { return accessor; } 45 | accessor = _; 46 | return element; 47 | }; 48 | 49 | element.x = function (_) { 50 | if (!arguments.length) { return x; } 51 | x = _; 52 | return element; 53 | }; 54 | 55 | element.y = function (_) { 56 | if (!arguments.length) { return y; } 57 | y = _; 58 | return element; 59 | }; 60 | 61 | element.width = function (_) { 62 | if (!arguments.length) { return width; } 63 | width = _; 64 | return element; 65 | }; 66 | 67 | element.height = function (_) { 68 | if (!arguments.length) { return height; } 69 | height = _; 70 | return element; 71 | }; 72 | 73 | element.xlink = function (_) { 74 | if (!arguments.length) { return xlink; } 75 | xlink = _; 76 | return element; 77 | }; 78 | 79 | element.preserveAspectRatio = function (_) { 80 | if (!arguments.length) { return preserveAspectRatio; } 81 | preserveAspectRatio = _; 82 | return element; 83 | }; 84 | 85 | element.class = function (_) { 86 | if (!arguments.length) { return cssClass; } 87 | cssClass = _; 88 | return element; 89 | }; 90 | 91 | return element; 92 | }; 93 | }); 94 | -------------------------------------------------------------------------------- /src/modules/element/svg/line.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function line() { 5 | var accessor = function (d) { return d; }; 6 | var x1 = 0; 7 | var x2 = 0; 8 | var y1 = 0; 9 | var y2 = 0; 10 | 11 | var cssClass = "line"; 12 | var stroke = colorFill; 13 | var strokeWidth = 2; 14 | var opacity = 1; 15 | 16 | function element(selection) { 17 | selection.each(function (data, index) { 18 | data = accessor.call(this, data, index); 19 | 20 | var lines = d3.select(this) 21 | .selectAll("." + cssClass) 22 | .data(data); 23 | 24 | // Exit 25 | lines.exit().remove(); 26 | 27 | // Enter 28 | lines.enter().append("line"); 29 | 30 | // Update 31 | lines 32 | .attr("class", cssClass) 33 | .attr("x1", x1) 34 | .attr("x2", x2) 35 | .attr("y1", y1) 36 | .attr("y2", y2) 37 | .attr("stroke", stroke) 38 | .attr("stroke-width", strokeWidth) 39 | .style("opacity", opacity); 40 | }); 41 | } 42 | 43 | function colorFill(d, i) { 44 | return d3.scale.category10()(i); 45 | } 46 | 47 | // Public API 48 | element.accessor = function (_) { 49 | if (!arguments.length) { return accessor; } 50 | accessor = _; 51 | return element; 52 | }; 53 | 54 | element.x1 = function (_) { 55 | if (!arguments.length) { return x1; } 56 | x1 = _; 57 | return element; 58 | }; 59 | 60 | element.x2 = function (_) { 61 | if (!arguments.length) { return x2; } 62 | x2 = _; 63 | return element; 64 | }; 65 | 66 | element.y1 = function (_) { 67 | if (!arguments.length) { return y1; } 68 | y1 = _; 69 | return element; 70 | }; 71 | 72 | element.y2 = function (_) { 73 | if (!arguments.length) { return y2; } 74 | y2 = _; 75 | return element; 76 | }; 77 | 78 | element.class = function (_) { 79 | if (!arguments.length) { return cssClass; } 80 | cssClass = _; 81 | return element; 82 | }; 83 | 84 | element.opacity = function (_) { 85 | if (!arguments.length) { return opacity; } 86 | opacity = _; 87 | return element; 88 | }; 89 | 90 | element.stroke = function (_) { 91 | if (!arguments.length) { return stroke; } 92 | stroke = _; 93 | return element; 94 | }; 95 | 96 | element.strokeWidth = function (_) { 97 | if (!arguments.length) { return strokeWidth; } 98 | strokeWidth = _; 99 | return element; 100 | }; 101 | 102 | return element; 103 | }; 104 | }); -------------------------------------------------------------------------------- /src/modules/element/svg/path.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function path() { 5 | var accessor = function (d) { return d; }; 6 | var pathGenerator = null; 7 | 8 | // Options 9 | var cssClass = "path"; 10 | var transform = "translate(0,0)"; 11 | var fill = "none"; 12 | var stroke = function (d, i) { return d3.scale.category10()(i); }; 13 | var strokeWidth = 1; 14 | var opacity = 1; 15 | 16 | function element(selection) { 17 | selection.each(function (data, index) { 18 | data = accessor.call(this, data, index); 19 | 20 | var path = d3.select(this) 21 | .selectAll("." + cssClass) 22 | .data(data); 23 | 24 | path.exit().remove(); 25 | 26 | path.enter().append("path"); 27 | 28 | path 29 | .attr("transform", transform) 30 | .attr("class", cssClass) 31 | .attr("fill", fill) 32 | .attr("stroke", stroke) 33 | .attr("stroke-width", strokeWidth) 34 | .attr("d", pathGenerator) 35 | .style("opacity", opacity); 36 | }); 37 | } 38 | 39 | // Public API 40 | element.accessor = function (_) { 41 | if (!arguments.length) { return accessor; } 42 | accessor = _; 43 | return element; 44 | }; 45 | 46 | element.pathGenerator = function (_) { 47 | if (!arguments.length) { return pathGenerator; } 48 | pathGenerator = _; 49 | return element; 50 | }; 51 | 52 | element.class = function (_) { 53 | if (!arguments.length) { return cssClass; } 54 | cssClass = _; 55 | return element; 56 | }; 57 | 58 | element.transform = function (_) { 59 | if (!arguments.length) { return transform; } 60 | transform = _; 61 | return element; 62 | }; 63 | 64 | element.fill = function (_) { 65 | if (!arguments.length) { return fill; } 66 | fill = _; 67 | return element; 68 | }; 69 | 70 | element.opacity = function (_) { 71 | if (!arguments.length) { return opacity; } 72 | opacity = _; 73 | return element; 74 | }; 75 | 76 | element.stroke = function (_) { 77 | if (!arguments.length) { return stroke; } 78 | stroke = d3.functor(_); 79 | return element; 80 | }; 81 | 82 | element.strokeWidth = function (_) { 83 | if (!arguments.length) { return strokeWidth; } 84 | strokeWidth = _; 85 | return element; 86 | }; 87 | 88 | return element; 89 | }; 90 | }); 91 | -------------------------------------------------------------------------------- /src/modules/element/svg/rect.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function rect() { 5 | var accessor = function (d) { return d; }; 6 | var x = function (d) { return d.x; }; 7 | var y = function (d) { return d.y; }; 8 | var rx = 0; 9 | var ry = 0; 10 | var width = null; 11 | var height = null; 12 | 13 | // Options 14 | var cssClass = "bar"; 15 | var fill = colorFill; 16 | var stroke = colorFill; 17 | var strokeWidth = 0; 18 | var opacity = 1; 19 | 20 | function element(selection) { 21 | selection.each(function (data, index) { 22 | data = accessor.call(this, data, index); 23 | 24 | var bars = d3.select(this) 25 | .selectAll("." + cssClass) 26 | .data(data); 27 | 28 | bars.exit().remove(); 29 | 30 | bars.enter().append("rect"); 31 | 32 | bars 33 | .attr("class", cssClass) 34 | .attr("fill", fill) 35 | .attr("stroke", stroke) 36 | .attr("stroke-width", strokeWidth) 37 | .attr("x", x) 38 | .attr("y", y) 39 | .attr("rx", rx) 40 | .attr("ry", ry) 41 | .attr("width", width) 42 | .attr("height", height) 43 | .style("opacity", opacity); 44 | }); 45 | } 46 | 47 | function colorFill(d, i) { 48 | return d3.scale.category10()(i); 49 | } 50 | 51 | // Public API 52 | element.accessor = function (_) { 53 | if (!arguments.length) { return accessor; } 54 | accessor = _; 55 | return element; 56 | }; 57 | 58 | element.x = function (_) { 59 | if (!arguments.length) { return x; } 60 | x = _; 61 | return element; 62 | }; 63 | 64 | element.y = function (_) { 65 | if (!arguments.length) { return y; } 66 | y = _; 67 | return element; 68 | }; 69 | 70 | element.rx = function (_) { 71 | if (!arguments.length) { return rx; } 72 | rx = _; 73 | return element; 74 | }; 75 | 76 | element.ry = function (_) { 77 | if (!arguments.length) { return ry; } 78 | ry = _; 79 | return element; 80 | }; 81 | 82 | element.width = function (_) { 83 | if (!arguments.length) { return width; } 84 | width = _; 85 | return element; 86 | }; 87 | 88 | element.height = function (_) { 89 | if (!arguments.length) { return height; } 90 | height = _; 91 | return element; 92 | }; 93 | 94 | element.class= function (_) { 95 | if (!arguments.length) { return cssClass; } 96 | cssClass = _; 97 | return element; 98 | }; 99 | 100 | element.fill = function (_) { 101 | if (!arguments.length) { return fill; } 102 | fill = _; 103 | return element; 104 | }; 105 | 106 | element.opacity = function (_) { 107 | if (!arguments.length) { return opacity; } 108 | opacity = _; 109 | return element; 110 | }; 111 | 112 | element.stroke = function (_) { 113 | if (!arguments.length) { return stroke; } 114 | stroke = _; 115 | return element; 116 | }; 117 | 118 | element.strokeWidth = function (_) { 119 | if (!arguments.length) { return strokeWidth; } 120 | strokeWidth = _; 121 | return element; 122 | }; 123 | 124 | return element; 125 | }; 126 | }); 127 | -------------------------------------------------------------------------------- /src/modules/element/svg/text.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function text() { 5 | var accessor = function (d) { return d; }; 6 | var x = function (d) { return d.x; }; 7 | var y = function (d) { return d.y; }; 8 | var dx = 0; 9 | var dy = 0; 10 | var transform = null; 11 | 12 | // Options 13 | var cssClass = "text"; 14 | var fill = "#ffffff"; 15 | var anchor = "middle"; 16 | var texts = ""; 17 | 18 | function element(selection) { 19 | selection.each(function (data, index) { 20 | data = accessor.call(this, data, index); 21 | 22 | var text = d3.select(this) 23 | .selectAll("." + cssClass) 24 | .data(data); 25 | 26 | text.exit().remove(); 27 | 28 | text.enter().append("text"); 29 | 30 | text 31 | .attr("class", cssClass) 32 | .attr("transform", transform) 33 | .attr("x", x) 34 | .attr("y", y) 35 | .attr("dx", dx) 36 | .attr("dy", dy) 37 | .attr("fill", fill) 38 | .style("text-anchor", anchor) 39 | .text(texts); 40 | }); 41 | } 42 | 43 | // Public API 44 | element.accessor = function (_) { 45 | if (!arguments.length) { return accessor; } 46 | accessor = _; 47 | return element; 48 | }; 49 | 50 | element.x = function (_) { 51 | if (!arguments.length) { return x; } 52 | x = _; 53 | return element; 54 | }; 55 | 56 | element.y = function (_) { 57 | if (!arguments.length) { return y; } 58 | y = _; 59 | return element; 60 | }; 61 | 62 | element.dx = function (_) { 63 | if (!arguments.length) { return dx; } 64 | dx = _; 65 | return element; 66 | }; 67 | 68 | element.dy = function (_) { 69 | if (!arguments.length) { return dy; } 70 | dy = _; 71 | return element; 72 | }; 73 | 74 | element.transform = function (_) { 75 | if (!arguments.length) { return transform; } 76 | transform = _; 77 | return element; 78 | }; 79 | 80 | element.class= function (_) { 81 | if (!arguments.length) { return cssClass; } 82 | cssClass = _; 83 | return element; 84 | }; 85 | 86 | element.anchor = function (_) { 87 | if (!arguments.length) { return anchor; } 88 | anchor = _; 89 | return element; 90 | }; 91 | 92 | element.fill = function (_) { 93 | if (!arguments.length) { return fill; } 94 | fill = _; 95 | return element; 96 | }; 97 | 98 | element.text = function (_) { 99 | if (!arguments.length) { return texts; } 100 | texts = _; 101 | return element; 102 | }; 103 | 104 | return element; 105 | }; 106 | }); 107 | -------------------------------------------------------------------------------- /src/modules/functor.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | var builder = require("builder"); 4 | 5 | /** 6 | * Builds and return a function based on key value pairs 7 | * and calls it on a d3 selection. 8 | */ 9 | return function functor() { 10 | var func = function () {}; 11 | var opts = {}; 12 | 13 | function constructor(selection) { 14 | selection.each(function () { 15 | d3.select(this).call(builder(opts, func)); 16 | }); 17 | } 18 | 19 | constructor.function = function (_) { 20 | if (!arguments.length) { return func; } 21 | func = typeof _ !== "function" ? func : _; 22 | return constructor; 23 | }; 24 | 25 | constructor.options = function (_) { 26 | if (!arguments.length) { return opts; } 27 | opts = typeof _ !== "object" ? opts : _; 28 | return constructor; 29 | }; 30 | 31 | return constructor; 32 | }; 33 | }); 34 | -------------------------------------------------------------------------------- /src/modules/helpers/add_event_listener.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a function that adds an eventType, e.g. click, brush, mouseover 3 | * and event listener, e.g. function (e) { console.log(e); } 4 | * to an event object, e.g. { "click": [ listener1, listener2], "brush": [ listener1 ], ... }. 5 | */ 6 | define(function () { 7 | return function (chart) { 8 | return function (eventType, listener) { 9 | var listeners = chart.listeners(); 10 | 11 | if (arguments.length === 1 && listeners[eventType]) { 12 | return listeners[eventType]; 13 | } 14 | if (arguments.length === 2 && typeof listener === "function") { 15 | if (!listeners[eventType]) { listeners[eventType] = []; } 16 | listeners[eventType].push(listener); 17 | } 18 | return chart; 19 | }; 20 | }; 21 | }); -------------------------------------------------------------------------------- /src/modules/helpers/remove_event_listener.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a function that removes event types, e.g: click, brush, mouseover, etc. 3 | * and event listeners, e.g. function (e) { console.log(e); } 4 | * from an event object, e.g. { "click": [ listener1, listener2], "brush": [ listener1 ], ... }. 5 | * Ability to remove one event listener at a time or all listeners for an event type. 6 | */ 7 | define(function () { 8 | return function (chart) { 9 | return function (eventType, listener) { 10 | var listeners = chart.listeners(); 11 | 12 | if (arguments.length === 1 && listeners[eventType]) { 13 | listeners[eventType] = null; 14 | } 15 | if (arguments.length === 2 && typeof listener === "function") { 16 | if (!listeners[eventType]) { return; } 17 | 18 | listeners[eventType] = listeners[eventType].filter(function (handler) { 19 | return handler !== listener; 20 | }); 21 | } 22 | 23 | return chart; 24 | }; 25 | }; 26 | }); -------------------------------------------------------------------------------- /src/modules/helpers/scaletor.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function (_) { 5 | if (typeof _ === "function") { return _; } 6 | if (typeof _ === "string") { 7 | if (_ === "time") { return d3[_].scale(); } 8 | if (_ === "time.utc") { return d3.time.scale.utc(); } 9 | return typeof d3.scale[_] === "function" ? d3.scale[_]() : d3.scale.linear(); 10 | } 11 | return !_ || typeof _ !== "function" ? d3.scale.linear() : _; 12 | }; 13 | }); -------------------------------------------------------------------------------- /src/modules/helpers/target_index.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | return function getIndex(parent, child) { 3 | function isPresent(d) { return d > -1; } 4 | function indexPosition(d, i) { 5 | if (d.length > 1) { return i; } 6 | return d; 7 | } 8 | function filterDown(d) { 9 | if (Array.isArray(d) && !d.length) { return -1; } 10 | return d; 11 | } 12 | 13 | var index = parent.datum() 14 | .map(function (datum) { 15 | var isArray = Array.isArray(child.datum()); 16 | var target = isArray ? child.datum() : [child.datum()]; 17 | 18 | return target.map(function (d) { 19 | return datum.indexOf(d); 20 | }).filter(isPresent); 21 | }) 22 | .map(indexPosition) 23 | .map(filterDown) 24 | .filter(isPresent)[0]; 25 | 26 | if (Array.isArray(index)) { return index[0]; } 27 | 28 | return index; 29 | }; 30 | }); 31 | -------------------------------------------------------------------------------- /src/modules/helpers/timeparser.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | var timeNotation = { 3 | s: "second", 4 | m: "minute", 5 | h: "hour", 6 | d: "day", 7 | w: "week", 8 | M: "month", 9 | y: "year" 10 | }; 11 | 12 | /** 13 | * Function that returns the proper time string 14 | * from its abbreviated form. 15 | * Valid str === [0-9][time abbr], e.g. "20s" 16 | */ 17 | return function (str) { 18 | if (typeof str !== "string") { return; } 19 | 20 | var abbr = str.split(parseFloat(str))[1]; 21 | 22 | if (Object.keys(timeNotation).indexOf(abbr) === -1) { 23 | throw new Error("Invalid time string " + str); 24 | } 25 | 26 | return timeNotation[abbr]; 27 | }; 28 | }); -------------------------------------------------------------------------------- /src/modules/layout/base.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function format() { 5 | // Private variables 6 | var type = "rows"; // available types: 'rows', 'columns', 'grid' 7 | var size = [500, 500]; // [width, height] 8 | var rowScale = d3.scale.linear(); 9 | var columnScale = d3.scale.linear(); 10 | var numOfCols = 0; 11 | 12 | function formatType(length, type, cols) { 13 | var output = {}; 14 | 15 | switch (type) { 16 | case "grid": 17 | output.rows = cols ? Math.ceil(length / cols) : 18 | Math.round(Math.sqrt(length)); 19 | output.columns = cols ? cols : Math.ceil(Math.sqrt(length)); 20 | break; 21 | 22 | case "columns": 23 | output.rows = 1; 24 | output.columns = length; 25 | break; 26 | 27 | default: 28 | output.rows = length; 29 | output.columns = 1; 30 | break; 31 | } 32 | 33 | return output; 34 | } 35 | 36 | function layout(data) { 37 | var format = formatType(data.length, type, numOfCols); 38 | var rows = format.rows; 39 | var columns = format.columns; 40 | var cellWidth = size[0] / columns; 41 | var cellHeight = size[1] / rows; 42 | var cell = 0; 43 | 44 | rowScale.domain([0, rows]).range([0, size[1]]); 45 | columnScale.domain([0, columns]).range([0, size[0]]); 46 | 47 | d3.range(rows).forEach(function (row) { 48 | d3.range(columns).forEach(function (col) { 49 | if (!data[cell]) { return; } 50 | 51 | data[cell].dx = columnScale(col); 52 | data[cell].dy = rowScale(row); 53 | data[cell].height = cellHeight; 54 | data[cell].width = cellWidth; 55 | cell++; 56 | }); 57 | }); 58 | 59 | return data; 60 | } 61 | 62 | // Public API 63 | layout.type = function (_) { 64 | if (!arguments.length) { return type; } 65 | type = _; 66 | return layout; 67 | }; 68 | 69 | layout.columns = function (_) { 70 | if (!arguments.length) { return numOfCols; } 71 | numOfCols = _; 72 | return layout; 73 | }; 74 | 75 | layout.size = function (_) { 76 | if (!arguments.length) { return size; } 77 | size = _; 78 | return layout; 79 | }; 80 | 81 | return layout; 82 | }; 83 | }); 84 | -------------------------------------------------------------------------------- /src/modules/layout/box.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function box() { 5 | // Private variables 6 | var values = function (d) { return d.values; }; 7 | var accessor = function (d) { return d; }; 8 | 9 | function layout(data) { 10 | data.forEach(function (d, i) { 11 | var numbers = accessor.call(this, values.call(this, d, i)); 12 | 13 | d.median = d3.median(numbers); 14 | d.q1 = d3.quantile(numbers, 0.25); 15 | d.q3 = d3.quantile(numbers, 0.75); 16 | d.max = d3.max(numbers); 17 | d.min = d3.min(numbers); 18 | }); 19 | 20 | return data; 21 | } 22 | 23 | // Public API 24 | layout.values = function (_) { 25 | if (!arguments.length) { return values; } 26 | values = _; 27 | return layout; 28 | }; 29 | 30 | layout.accessor = function (_) { 31 | if (!arguments.length) { return accessor; } 32 | accessor = _; 33 | return layout; 34 | }; 35 | 36 | return layout; 37 | }; 38 | }); -------------------------------------------------------------------------------- /src/modules/layout/grid.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function grid() { 5 | // Private variables 6 | var gridSize = [500, 500]; 7 | var rowScale = d3.scale.linear(); 8 | var columnScale = d3.scale.linear(); 9 | 10 | function layout(data) { 11 | var rows = Math.ceil(Math.sqrt(data.length)); 12 | var columns = rows; 13 | var gridCellWidth = gridSize[0] / columns; 14 | var gridCellHeight = gridSize[1] / rows; 15 | var cell = 0; 16 | 17 | rowScale.domain([0, rows]).range([0, gridSize[1]]); 18 | columnScale.domain([0, columns]).range([0, gridSize[0]]); 19 | 20 | d3.range(rows).forEach(function (row) { 21 | d3.range(columns).forEach(function (col) { 22 | if (!data[cell]) { return; } 23 | 24 | data[cell].dx = columnScale(col); 25 | data[cell].dy = rowScale(row); 26 | data[cell].height = gridCellHeight; 27 | data[cell].width = gridCellWidth; 28 | cell++; 29 | }); 30 | }); 31 | 32 | return data; 33 | } 34 | 35 | // Public API 36 | layout.size = function (_) { 37 | if (!arguments.length) { return gridSize; } 38 | gridSize = _; 39 | return layout; 40 | }; 41 | 42 | return layout; 43 | }; 44 | }); -------------------------------------------------------------------------------- /src/modules/valuator.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | /** 3 | * Wrapper function that returns a function 4 | * that returns the argument or an object key. 5 | * If argument is a function, returns the function. 6 | */ 7 | return function (val) { 8 | if (typeof val === "function") { return val; } 9 | if (typeof val === "string") { 10 | return function (d) { return d[val]; }; 11 | } 12 | return function () { return val; }; 13 | }; 14 | }); -------------------------------------------------------------------------------- /src/require.config.js: -------------------------------------------------------------------------------- 1 | require.config({ 2 | baseUrl: "/", 3 | paths: { 4 | jubilee: "src/index", 5 | d3: "node_modules/d3/d3", 6 | functor: "src/modules/functor", 7 | builder: "src/modules/builder", 8 | valuator: "src/modules/valuator" 9 | }, 10 | shim: {}, 11 | packages: [] 12 | }); 13 | -------------------------------------------------------------------------------- /src/start.js: -------------------------------------------------------------------------------- 1 | (function (root, factory) { 2 | if (typeof define === "function" && define.amd) { 3 | define([], factory); 4 | } else { 5 | root.jubilee = factory(); 6 | } 7 | }(this, function () { 8 | -------------------------------------------------------------------------------- /test/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "define": true, 4 | "require": true, 5 | "console": false, 6 | "describe": true, 7 | "it": true, 8 | "beforeEach": true, 9 | "afterEach": true, 10 | "chai": true 11 | }, 12 | "bitwise": true, 13 | "camelcase": true, 14 | "curly": true, 15 | "eqeqeq": true, 16 | "es3": false, 17 | "forin": true, 18 | "freeze": true, 19 | "immed": true, 20 | "indent": 2, 21 | "latedef": false, 22 | "newcap": true, 23 | "noarg": true, 24 | "noempty": true, 25 | "nonbsp": true, 26 | "nonew": true, 27 | "plusplus": false, 28 | "quotmark": "double", 29 | "undef": true, 30 | "unused": "vars", 31 | "strict": false, 32 | "maxerr": 10, 33 | "maxlen": 120, 34 | "boss": true, 35 | "debug": true, 36 | "eqnull": true 37 | } 38 | -------------------------------------------------------------------------------- /test/unit/fixtures/data_generator.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | return function (num) { 3 | return Array.apply(null, new Array(num)) 4 | .map(function (val, i) { 5 | return { 6 | x: +(Math.random() * 100).toFixed(0), 7 | y: +(Math.random() * 100).toFixed(0) 8 | }; 9 | }); 10 | }; 11 | }); -------------------------------------------------------------------------------- /test/unit/fixtures/fixture.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return d3.select("body") 5 | .append("div") 6 | .attr("class", "chart") 7 | .append("svg") 8 | .attr("width", 500) 9 | .attr("height", 500); 10 | }); 11 | -------------------------------------------------------------------------------- /test/unit/fixtures/path_generator.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | var d3 = require("d3"); 3 | 4 | return function (type) { 5 | var pathTypes = { 6 | line: d3.svg.line().x(X).y(Y), 7 | area: d3.svg.area().x(X).y0(0).y1(Y) 8 | }; 9 | 10 | function X(d) { return d.x; } 11 | function Y(d) { return d.y; } 12 | 13 | return pathTypes[type] ? pathTypes[type] : pathTypes.line; 14 | }; 15 | }); 16 | -------------------------------------------------------------------------------- /test/unit/fixtures/remove.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | return function (fixture) { 3 | fixture.selectAll("*").remove(); 4 | fixture.datum(null); 5 | fixture = null; 6 | }; 7 | }); -------------------------------------------------------------------------------- /test/unit/fixtures/remove_children.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | return function (selection) { 3 | selection.selectAll("*").remove(); 4 | }; 5 | }); -------------------------------------------------------------------------------- /test/unit/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Unit tests 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /test/unit/specs/modules/component/axis.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Component: Axis tests", function () { 3 | var d3 = require("d3"); 4 | var axisFunction = require("src/modules/component/axis/axis"); 5 | var axis; 6 | 7 | beforeEach(function () { 8 | axis = axisFunction(); 9 | }); 10 | 11 | it("should return a function", function () { 12 | chai.assert.isFunction(axis); 13 | }); 14 | 15 | describe("scale API", function () { 16 | var linearScale = d3.scale.linear(); 17 | var ordinalScale = d3.scale.ordinal(); 18 | 19 | beforeEach(function () { 20 | axis.scale(linearScale); 21 | }); 22 | 23 | it("should return the scale", function () { 24 | chai.assert.equal(axis.scale(), linearScale); 25 | }); 26 | 27 | it("should set the axis scale", function () { 28 | axis.scale(ordinalScale); 29 | chai.assert.equal(axis.scale(), ordinalScale); 30 | }); 31 | }); 32 | 33 | describe("orient API", function () { 34 | var orient = "bottom"; 35 | var newOrient = "right"; 36 | 37 | beforeEach(function () { 38 | axis.orient(orient); 39 | }); 40 | 41 | it("should return the orient", function () { 42 | chai.assert.equal(axis.orient(), orient); 43 | }); 44 | 45 | it("should set the axis orient", function () { 46 | axis.orient(newOrient); 47 | chai.assert.equal(axis.orient(), newOrient); 48 | }); 49 | }); 50 | 51 | describe("tick API", function () { 52 | var tick = {}; 53 | 54 | it("should return the tick object", function () { 55 | chai.assert.isObject(axis.tick()); 56 | chai.assert.property(axis.tick(), "number"); 57 | chai.assert.property(axis.tick(), "values"); 58 | chai.assert.property(axis.tick(), "format"); 59 | }); 60 | 61 | it("should set tick properties", function () { 62 | var number = tick.number = 10; 63 | axis.tick(tick); 64 | chai.assert.equal(axis.tick().number, number); 65 | }); 66 | }); 67 | 68 | describe("class API", function () { 69 | var gClass = "axis"; 70 | var newClass = "x axis"; 71 | 72 | beforeEach(function () { 73 | axis.class(gClass); 74 | }); 75 | 76 | it("should return the css class", function () { 77 | chai.assert.equal(axis.class(), gClass); 78 | }); 79 | 80 | it("should set the css class property", function () { 81 | axis.class(newClass); 82 | chai.assert.equal(axis.class(), newClass); 83 | }); 84 | }); 85 | 86 | describe("transform API", function () { 87 | var transform = "translate(0,200)"; 88 | var newTransform = "translate(0,400)"; 89 | 90 | beforeEach(function () { 91 | axis.transform(transform); 92 | }); 93 | 94 | it("should return the transform", function () { 95 | chai.assert.equal(axis.transform(), transform); 96 | }); 97 | 98 | it("should set the transform property", function () { 99 | axis.transform(newTransform); 100 | chai.assert.equal(axis.transform(), newTransform); 101 | }); 102 | }); 103 | 104 | describe("title API", function () { 105 | var title = {}; 106 | 107 | it("should return the title object", function () { 108 | chai.assert.isObject(axis.title()); 109 | chai.assert.property(axis.title(), "dx"); 110 | chai.assert.property(axis.title(), "dy"); 111 | chai.assert.property(axis.title(), "transform"); 112 | chai.assert.property(axis.title(), "anchor"); 113 | }); 114 | 115 | it("should set title properties", function () { 116 | var anchor = title.anchor = "start"; 117 | axis.title(title); 118 | chai.assert.equal(axis.title().anchor, anchor); 119 | }); 120 | }); 121 | }); 122 | }); -------------------------------------------------------------------------------- /test/unit/specs/modules/component/brush.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Component: Brush tests", function () { 3 | var d3 = require("d3"); 4 | var brushFunction = require("src/modules/component/events/brush"); 5 | var d3fixture = require("fixtures/fixture"); 6 | var remove = require("fixtures/remove"); 7 | var fixture; 8 | var brush; 9 | 10 | beforeEach(function () { 11 | fixture = d3fixture; 12 | brush = brushFunction(); 13 | 14 | fixture.call(brush); 15 | }); 16 | 17 | afterEach(function () { 18 | remove(fixture); 19 | }); 20 | 21 | it("should return a function", function () { 22 | chai.assert.isFunction(brush); 23 | }); 24 | 25 | describe("margin API", function () { 26 | var margin; 27 | 28 | beforeEach(function () { 29 | margin = {top: 50, right: 0, bottom: 50, left: 0}; 30 | }); 31 | 32 | it("should return the margin", function () { 33 | chai.assert.isObject(brush.margin()); 34 | chai.assert.property(brush.margin(), "top"); 35 | chai.assert.property(brush.margin(), "right"); 36 | chai.assert.property(brush.margin(), "bottom"); 37 | chai.assert.property(brush.margin(), "left"); 38 | }); 39 | 40 | it("should set the margin", function () { 41 | brush.margin(margin); 42 | chai.assert.deepEqual(brush.margin(), margin); 43 | }); 44 | }); 45 | 46 | describe("width API", function () { 47 | var width = 340; 48 | var newWidth = 760; 49 | 50 | beforeEach(function () { 51 | brush.width(width); 52 | }); 53 | 54 | it("should return the width", function () { 55 | chai.assert.equal(brush.width(), width); 56 | }); 57 | 58 | it("should set the width", function () { 59 | brush.width(newWidth); 60 | chai.assert.equal(brush.width(), newWidth); 61 | }); 62 | }); 63 | 64 | describe("height API", function () { 65 | var height = 540; 66 | var newHeight = 360; 67 | 68 | beforeEach(function () { 69 | brush.height(height); 70 | }); 71 | 72 | it("should return the height", function () { 73 | chai.assert.equal(brush.height(), height); 74 | }); 75 | 76 | it("should set the height", function () { 77 | brush.height(newHeight); 78 | chai.assert.equal(brush.height(), newHeight); 79 | }); 80 | }); 81 | 82 | describe("opacity API", function () { 83 | var opacity = 0.8; 84 | var newOpacity = 0.5; 85 | 86 | beforeEach(function () { 87 | brush.opacity(opacity); 88 | }); 89 | 90 | it("should return the opacity", function () { 91 | chai.assert.equal(brush.opacity(), opacity); 92 | }); 93 | 94 | it("should set the opacity", function () { 95 | brush.opacity(newOpacity); 96 | chai.assert.equal(brush.opacity(), newOpacity); 97 | }); 98 | }); 99 | 100 | describe("class API", function () { 101 | var cssClass = "brush"; 102 | var newClass = "special-brush"; 103 | 104 | beforeEach(function () { 105 | brush.class(cssClass); 106 | }); 107 | 108 | it("should return the css class", function () { 109 | chai.assert.equal(brush.class(), cssClass); 110 | }); 111 | 112 | it("should set the css class", function () { 113 | brush.class(newClass); 114 | chai.assert.equal(brush.class(), newClass); 115 | }); 116 | }); 117 | 118 | describe("xScale API", function () { 119 | var linearScale = d3.scale.linear(); 120 | var timeScale = d3.time.scale(); 121 | 122 | beforeEach(function () { 123 | brush.xScale(linearScale); 124 | }); 125 | 126 | it("should return the xScale", function () { 127 | chai.assert.equal(brush.xScale(), linearScale); 128 | }); 129 | 130 | it("should set the xScale", function () { 131 | brush.xScale(timeScale); 132 | chai.assert.equal(brush.xScale(), timeScale); 133 | }); 134 | }); 135 | 136 | describe("yScale API", function () { 137 | var linearScale = d3.scale.linear(); 138 | var ordinalScale = d3.scale.ordinal(); 139 | 140 | beforeEach(function () { 141 | brush.yScale(linearScale); 142 | }); 143 | 144 | it("should return the yScale", function () { 145 | chai.assert.equal(brush.yScale(), linearScale); 146 | }); 147 | 148 | it("should set the yScale", function () { 149 | brush.yScale(ordinalScale); 150 | chai.assert.equal(brush.yScale(), ordinalScale); 151 | }); 152 | }); 153 | 154 | describe("extent API", function () { 155 | var extent = [[0, 200], [0, 200]]; 156 | var newExtent = [1, 10]; 157 | 158 | beforeEach(function () { 159 | brush.extent(extent); 160 | }); 161 | 162 | it("should return the extent", function () { 163 | chai.assert.deepEqual(brush.extent(), extent); 164 | }); 165 | 166 | it("should set the extent", function () { 167 | brush.extent(newExtent); 168 | chai.assert.deepEqual(brush.extent(), newExtent); 169 | }); 170 | }); 171 | 172 | describe("clamp API", function () { 173 | var clamp = true; 174 | 175 | beforeEach(function () { 176 | brush.clamp(clamp); 177 | }); 178 | 179 | it("should return a boolean", function () { 180 | chai.assert.isTrue(brush.clamp()); 181 | }); 182 | 183 | it("should set the clamp", function () { 184 | brush.clamp(false); 185 | chai.assert.isFalse(brush.clamp()); 186 | }); 187 | }); 188 | 189 | describe("brushstart API", function () { 190 | it("should return listeners array", function () { 191 | chai.assert.deepEqual(brush.brushstart(), []); 192 | }); 193 | 194 | it("should append listeners to the brushstart array", function () { 195 | var brushStart = function (e) { console.log(e); }; 196 | brush.brushstart(brushStart); 197 | 198 | chai.assert.deepEqual(brush.brushstart(), [brushStart]); 199 | }); 200 | }); 201 | 202 | describe("brush API", function () { 203 | it("should return listeners array", function () { 204 | chai.assert.deepEqual(brush.brush(), []); 205 | }); 206 | 207 | it("should append listeners to the brush array", function () { 208 | var brushCB = function (e) { console.log(e); }; 209 | brush.brush(brushCB); 210 | 211 | chai.assert.deepEqual(brush.brush(), [brushCB]); 212 | }); 213 | }); 214 | 215 | describe("brushend API", function () { 216 | it("should return listeners array", function () { 217 | chai.assert.deepEqual(brush.brushend(), []); 218 | }); 219 | 220 | it("should append listeners to the brushend array", function () { 221 | var brushend = function (e) { console.log(e); }; 222 | brush.brushend(brushend); 223 | 224 | chai.assert.deepEqual(brush.brushend(), [brushend]); 225 | }); 226 | }); 227 | }); 228 | }); -------------------------------------------------------------------------------- /test/unit/specs/modules/component/clippath.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Element: ClipPath SVG Tests", function () { 3 | var clipPath = require("src/modules/component/clippath"); 4 | var d3fixture = require("fixtures/fixture"); 5 | var remove = require("fixtures/remove"); 6 | var element = clipPath(); 7 | var fixture; 8 | 9 | beforeEach(function () { 10 | fixture = d3fixture; 11 | 12 | fixture 13 | .datum([{}]) // Only render 1 clippath 14 | .call(element); 15 | }); 16 | 17 | afterEach(function () { 18 | remove(fixture); 19 | }); 20 | 21 | it("should return a function", function () { 22 | var isFunction = (typeof element === "function"); 23 | chai.assert.equal(isFunction, true); 24 | }); 25 | 26 | describe("id API", function () { 27 | var defaultID; 28 | 29 | beforeEach(function () { 30 | defaultID = "uniqueID"; 31 | element.id(defaultID); 32 | }); 33 | 34 | it("should get the property", function () { 35 | chai.assert.equal(element.id(), defaultID); 36 | }); 37 | 38 | it("should set the property", function () { 39 | var newID = "newID"; 40 | element.id(newID); 41 | chai.assert.equal(element.id(), newID); 42 | }); 43 | 44 | it("should set the proper value of the DOM attribute", function () { 45 | element.id(defaultID); 46 | fixture.call(element); // Redraw 47 | 48 | fixture.select("clippath") 49 | .each(function () { 50 | chai.assert.equal(this.getAttribute("id"), element.id()); 51 | }); 52 | }); 53 | }); 54 | 55 | describe("transform API", function () { 56 | var defaultTransform; 57 | 58 | beforeEach(function () { 59 | defaultTransform = "translate(0,0)"; 60 | element.transform(defaultTransform); 61 | }); 62 | 63 | it("should get the property", function () { 64 | chai.assert.equal(element.transform(), defaultTransform); 65 | }); 66 | 67 | it("should set the property", function () { 68 | var newTransform = "translate(30,30)"; 69 | element.transform(newTransform); 70 | chai.assert.equal(element.transform(), newTransform); 71 | }); 72 | 73 | it("should set the proper value of the DOM attribute", function () { 74 | element.transform(defaultTransform); 75 | fixture.call(element); // Redraw 76 | 77 | fixture.selectAll("clippath") 78 | .each(function () { 79 | chai.assert.equal(this.getAttribute("transform"), element.transform()); 80 | }); 81 | }); 82 | }); 83 | 84 | describe("x API", function () { 85 | var defaultX; 86 | 87 | beforeEach(function () { 88 | defaultX = 0; 89 | element.x(defaultX); 90 | }); 91 | 92 | it("should get the property", function () { 93 | chai.assert.equal(element.x(), defaultX); 94 | }); 95 | 96 | it("should set the property", function () { 97 | var newX = 5; 98 | element.x(newX); 99 | chai.assert.equal(element.x(), newX); 100 | }); 101 | 102 | it("should set the proper value of the DOM attribute", function () { 103 | element.x(defaultX); 104 | fixture.call(element); // Redraw 105 | 106 | fixture.selectAll("rect") 107 | .each(function () { 108 | chai.assert.equal(this.getAttribute("x"), element.x()); 109 | }); 110 | }); 111 | }); 112 | 113 | describe("y API", function () { 114 | var defaultY; 115 | 116 | beforeEach(function () { 117 | defaultY = 0; 118 | element.y(defaultY); 119 | }); 120 | 121 | it("should get the property", function () { 122 | chai.assert.equal(element.y(), defaultY); 123 | }); 124 | 125 | it("should set the property", function () { 126 | var newY = 5; 127 | element.y(newY); 128 | chai.assert.equal(element.y(), newY); 129 | }); 130 | 131 | it("should set the proper value of the DOM attribute", function () { 132 | element.y(defaultY); 133 | fixture.call(element); // Redraw 134 | 135 | fixture.selectAll("rect") 136 | .each(function () { 137 | chai.assert.equal(this.getAttribute("y"), element.y()); 138 | }); 139 | }); 140 | }); 141 | 142 | describe("width API", function () { 143 | var defaultWidth; 144 | 145 | beforeEach(function () { 146 | defaultWidth = 500; 147 | element.width(defaultWidth); 148 | }); 149 | 150 | it("should get the property", function () { 151 | chai.assert.equal(element.width(), defaultWidth); 152 | }); 153 | 154 | it("should set the property", function () { 155 | var newWidth = 200; 156 | element.width(newWidth); 157 | chai.assert.equal(element.width(), newWidth); 158 | }); 159 | 160 | it("should set the proper value of the DOM attribute", function () { 161 | element.width(defaultWidth); 162 | fixture.call(element); // Redraw 163 | 164 | fixture.selectAll("rect") 165 | .each(function () { 166 | chai.assert.equal(this.getAttribute("width"), element.width()); 167 | }); 168 | }); 169 | }); 170 | 171 | describe("height API", function () { 172 | var defaultHeight; 173 | 174 | beforeEach(function () { 175 | defaultHeight = 500; 176 | element.height(defaultHeight); 177 | }); 178 | 179 | it("should get the property", function () { 180 | chai.assert.equal(element.height(), defaultHeight); 181 | }); 182 | 183 | it("should set the property", function () { 184 | var newHeight = 200; 185 | element.height(newHeight); 186 | chai.assert.equal(element.height(), newHeight); 187 | }); 188 | 189 | it("should set the proper value of the DOM attribute", function () { 190 | element.height(defaultHeight); 191 | fixture.call(element); // Redraw 192 | 193 | fixture.selectAll("rect") 194 | .each(function () { 195 | chai.assert.equal(this.getAttribute("height"), element.height()); 196 | }); 197 | }); 198 | }); 199 | }); 200 | }); 201 | -------------------------------------------------------------------------------- /test/unit/specs/modules/component/events.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Component: Events tests", function () { 3 | var eventsFunction = require("src/modules/component/events/events"); 4 | var d3fixture = require("fixtures/fixture"); 5 | var remove = require("fixtures/remove"); 6 | var totalListenerCount; 7 | var listeners; 8 | var fixture; 9 | var events; 10 | 11 | beforeEach(function () { 12 | fixture = d3fixture; 13 | events = eventsFunction(); 14 | listeners = { 15 | click: [function (e) { console.log(e); }], 16 | brush: [function (brush) { return brush.extent(); }], 17 | mouseover: [function (e, d) { return d; }] 18 | }; 19 | totalListenerCount = 3; 20 | }); 21 | 22 | afterEach(function () { 23 | remove(fixture); 24 | }); 25 | 26 | it("should return a function", function () { 27 | chai.assert.isFunction(events); 28 | }); 29 | 30 | describe("listeners API", function () { 31 | afterEach(function () { 32 | events.listeners({}); 33 | }); 34 | 35 | it("should return the listeners object", function () { 36 | chai.assert.deepEqual(events.listeners(), {}); 37 | }); 38 | 39 | it("should set the listeners object", function () { 40 | events.listeners(listeners); // Add listeners 41 | chai.assert.deepEqual(events.listeners(), listeners); 42 | }); 43 | }); 44 | }); 45 | }); -------------------------------------------------------------------------------- /test/unit/specs/modules/element/circle.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Element: Circle SVG Tests", function () { 3 | var circle = require("src/modules/element/svg/circle"); 4 | var d3fixture = require("fixtures/fixture"); 5 | var data = require("fixtures/data_generator")(10); 6 | var remove = require("fixtures/remove"); 7 | var removeChildren = require("fixtures/remove_children"); 8 | var element = circle(); 9 | var fixture; 10 | 11 | beforeEach(function () { 12 | fixture = d3fixture; 13 | 14 | fixture 15 | .datum(data) 16 | .call(element); 17 | }); 18 | 19 | afterEach(function () { 20 | element = circle(); 21 | remove(fixture); 22 | }); 23 | 24 | it("should return a function", function () { 25 | var isFunction = (typeof element === "function"); 26 | chai.assert.equal(isFunction, true); 27 | }); 28 | 29 | describe("accessor API", function () { 30 | var defaultAccessor; 31 | 32 | beforeEach(function () { 33 | removeChildren(fixture); 34 | defaultAccessor = function (d) { return d; }; 35 | element.accessor(defaultAccessor); 36 | }); 37 | 38 | it("should get the property", function () { 39 | chai.assert.equal(element.accessor(), defaultAccessor); 40 | }); 41 | 42 | it("should set the property", function () { 43 | var newAccessor = function (d) { return d.series; }; 44 | element.accessor(newAccessor); 45 | chai.assert.equal(element.accessor(), newAccessor); 46 | }); 47 | }); 48 | 49 | describe("cx API", function () { 50 | var defaultCX; 51 | 52 | beforeEach(function () { 53 | removeChildren(fixture); 54 | defaultCX = function (d) { return d.x; }; 55 | element.cx(defaultCX); 56 | }); 57 | 58 | it("should get the property", function () { 59 | chai.assert.equal(element.cx(), defaultCX); 60 | }); 61 | 62 | it("should set the property", function () { 63 | var newCX = function (d) { return d.cx; }; 64 | element.cx(newCX); 65 | chai.assert.equal(element.cx(), newCX); 66 | }); 67 | 68 | it("should set the proper value of the DOM attribute", function () { 69 | element.cx(defaultCX); // Set new cx attribute 70 | fixture.call(element); // Redraw circles 71 | 72 | fixture.selectAll("circle") 73 | .each(function (d) { 74 | chai.assert.equal(this.getAttribute("cx"), d.x); 75 | }); 76 | }); 77 | 78 | }); 79 | 80 | describe("cy API", function () { 81 | var defaultCY; 82 | 83 | beforeEach(function () { 84 | removeChildren(fixture); 85 | defaultCY = function (d) { return d.y; }; 86 | element.cy(defaultCY); 87 | }); 88 | 89 | it("should get the property", function () { 90 | chai.assert.equal(element.cy(), defaultCY); 91 | }); 92 | 93 | it("should set the property", function () { 94 | var newCY = function (d) { return d.cy; }; 95 | element.cy(newCY); 96 | chai.assert.equal(element.cy(), newCY); 97 | }); 98 | 99 | it("should set the proper value of the DOM attribute", function () { 100 | element.cy(defaultCY); // Set new cy attribute 101 | fixture.call(element); // Redraw circles 102 | 103 | fixture.selectAll("circle") 104 | .each(function (d) { 105 | chai.assert.equal(this.getAttribute("cy"), d.y); 106 | }); 107 | }); 108 | }); 109 | 110 | describe("radius API", function () { 111 | var defaultRadius; 112 | 113 | beforeEach(function () { 114 | removeChildren(fixture); 115 | defaultRadius = 5; 116 | element.radius(defaultRadius); 117 | }); 118 | 119 | it("should get the property", function () { 120 | chai.assert.equal(element.radius(), defaultRadius); 121 | }); 122 | 123 | it("should set the property", function () { 124 | element.radius(10); 125 | chai.assert.equal(element.radius(), 10); 126 | }); 127 | 128 | it("should set the proper value of the DOM attribute", function () { 129 | element.radius(function (d) { return d.radius; }); // Set new radius attribute 130 | fixture.call(element); // Redraw circles 131 | 132 | fixture.selectAll("circle") 133 | .each(function (d) { 134 | chai.assert.equal(this.getAttribute("r"), d.radius); 135 | }); 136 | }); 137 | }); 138 | 139 | describe("class API", function () { 140 | var defaultClass; 141 | 142 | beforeEach(function () { 143 | removeChildren(fixture); 144 | defaultClass = "circles"; 145 | element.class(defaultClass); 146 | }); 147 | 148 | it("should get the property", function () { 149 | chai.assert.equal(element.class(), defaultClass); 150 | }); 151 | 152 | it("should set the property", function () { 153 | element.class("test"); 154 | chai.assert.equal(element.class(), "test"); 155 | }); 156 | 157 | it("should set the proper value of the DOM attribute", function () { 158 | element.class("dots"); // Set new class attribute 159 | fixture.call(element); // Redraw circles 160 | 161 | fixture.selectAll("circle") 162 | .each(function () { 163 | chai.assert.equal(this.getAttribute("class"), element.class()); 164 | }); 165 | }); 166 | }); 167 | 168 | describe("fill API", function () { 169 | var defaultFill = "#0000FF"; 170 | 171 | beforeEach(function () { 172 | removeChildren(fixture); 173 | element.fill(defaultFill); 174 | }); 175 | 176 | it("should get the property", function () { 177 | chai.assert.equal(element.fill(), defaultFill); 178 | }); 179 | 180 | it("should set the property", function () { 181 | var newFill = "#FF0000"; 182 | element.fill(newFill); 183 | chai.assert.equal(element.fill(), newFill); 184 | }); 185 | 186 | it("should set the proper value of the DOM attribute", function () { 187 | element.fill(defaultFill); // Set new fill attribute 188 | fixture.call(element); // Redraw circles 189 | 190 | fixture.selectAll("circle") 191 | .each(function () { 192 | chai.assert.equal(this.getAttribute("fill"), element.fill()); 193 | }); 194 | }); 195 | }); 196 | 197 | describe("stroke API", function () { 198 | var defaultStroke = "#0000FF"; 199 | 200 | beforeEach(function () { 201 | removeChildren(fixture); 202 | element.stroke(defaultStroke); 203 | }); 204 | 205 | it("should get the property", function () { 206 | chai.assert.equal(element.stroke(), defaultStroke); 207 | }); 208 | 209 | it("should set the property", function () { 210 | var newStroke = "#FF0000"; 211 | element.stroke(newStroke); 212 | chai.assert.equal(element.stroke(), newStroke); 213 | }); 214 | 215 | it("should set the proper value of the DOM attribute", function () { 216 | element.stroke(defaultStroke); // Set new stroke attribute 217 | fixture.call(element); // Redraw circles 218 | 219 | fixture.selectAll("circle") 220 | .each(function () { 221 | chai.assert.equal(this.getAttribute("stroke"), element.stroke()); 222 | }); 223 | }); 224 | }); 225 | 226 | describe("strokeWidth API", function () { 227 | var defaultStrokeWidth = 2; 228 | 229 | beforeEach(function () { 230 | removeChildren(fixture); 231 | element.strokeWidth(defaultStrokeWidth); 232 | }); 233 | 234 | it("should get the property", function () { 235 | chai.assert.equal(element.strokeWidth(), defaultStrokeWidth); 236 | }); 237 | 238 | it("should set the property", function () { 239 | var newStrokeWidth = 5; 240 | element.strokeWidth(newStrokeWidth); 241 | chai.assert.equal(element.strokeWidth(), newStrokeWidth); 242 | }); 243 | 244 | it("should set the proper value of the DOM attribute", function () { 245 | element.strokeWidth(defaultStrokeWidth); // Set new stroke-width attribute 246 | fixture.call(element); // Redraw circles 247 | 248 | fixture.selectAll("circle") 249 | .each(function () { 250 | chai.assert.equal(this.getAttribute("stroke-width"), element.strokeWidth()); 251 | }); 252 | }); 253 | }); 254 | 255 | describe("opacity API", function () { 256 | var defaultOpacity = 1; 257 | 258 | beforeEach(function () { 259 | removeChildren(fixture); 260 | element.opacity(defaultOpacity); 261 | }); 262 | 263 | it("should get the property", function () { 264 | chai.assert.equal(element.opacity(), defaultOpacity); 265 | }); 266 | 267 | it("should set the property", function () { 268 | var newOpacity = 0.5; 269 | element.opacity(newOpacity); 270 | chai.assert.equal(element.opacity(), newOpacity); 271 | }); 272 | 273 | it("should set the proper value of the DOM attribute", function () { 274 | element.opacity(defaultOpacity); // Set new opacity attribute 275 | fixture.call(element); // Redraw circles 276 | 277 | fixture.selectAll("circle") 278 | .each(function () { 279 | chai.assert.equal(this.style.opacity, element.opacity()); 280 | }); 281 | }); 282 | }); 283 | }); 284 | }); 285 | -------------------------------------------------------------------------------- /test/unit/specs/modules/element/ellipse.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Element: Ellipse SVG Tests", function () { 3 | var ellipse = require("src/modules/element/svg/ellipse"); 4 | var d3fixture = require("fixtures/fixture"); 5 | var data = require("fixtures/data_generator")(10); 6 | var remove = require("fixtures/remove"); 7 | var removeChildren = require("fixtures/remove_children"); 8 | var element = ellipse(); 9 | var fixture; 10 | 11 | beforeEach(function () { 12 | fixture = d3fixture; 13 | 14 | fixture 15 | .datum(data) 16 | .call(element); 17 | }); 18 | 19 | afterEach(function () { 20 | remove(fixture); 21 | }); 22 | 23 | it("should return a function", function () { 24 | var isFunction = (typeof element === "function"); 25 | chai.assert.equal(isFunction, true); 26 | }); 27 | 28 | describe("cx API", function () { 29 | var defaultCX; 30 | 31 | beforeEach(function () { 32 | removeChildren(fixture); 33 | defaultCX = function (d) { return d.x; }; 34 | element.cx(defaultCX); 35 | }); 36 | 37 | it("should get the property", function () { 38 | chai.assert.equal(element.cx(), defaultCX); 39 | }); 40 | 41 | it("should set the property", function () { 42 | var newCX = function (d) { return d.cx; }; 43 | element.cx(newCX); 44 | chai.assert.equal(element.cx(), newCX); 45 | }); 46 | 47 | it("should set the proper value of the DOM attribute", function () { 48 | element.cx(defaultCX); 49 | fixture.call(element); // Redraw 50 | 51 | fixture.selectAll("ellipse") 52 | .each(function (d, i) { 53 | chai.assert.equal(this.getAttribute("cx"), d.x); 54 | }); 55 | }); 56 | }); 57 | 58 | describe("y API", function () { 59 | var defaultCY; 60 | 61 | beforeEach(function () { 62 | removeChildren(fixture); 63 | defaultCY = function (d) { return d.y; }; 64 | element.cy(defaultCY); 65 | }); 66 | 67 | it("should get the property", function () { 68 | chai.assert.equal(element.cy(), defaultCY); 69 | }); 70 | 71 | it("should set the property", function () { 72 | var newCY = function (d) { return d.cy; }; 73 | element.cy(newCY); 74 | chai.assert.equal(element.cy(), newCY); 75 | }); 76 | 77 | it("should set the proper value of the DOM attribute", function () { 78 | element.cy(defaultCY); 79 | fixture.call(element); // Redraw 80 | 81 | fixture.selectAll("ellipse") 82 | .each(function (d, i) { 83 | chai.assert.equal(this.getAttribute("cy"), d.y); 84 | }); 85 | }); 86 | }); 87 | 88 | describe("rx API", function () { 89 | var defaultRX; 90 | 91 | beforeEach(function () { 92 | removeChildren(fixture); 93 | defaultRX = 20; 94 | element.rx(defaultRX); 95 | }); 96 | 97 | it("should get the property", function () { 98 | chai.assert.equal(element.rx(), defaultRX); 99 | }); 100 | 101 | it("should set the property", function () { 102 | var newRX = 10; 103 | element.rx(newRX); 104 | chai.assert.equal(element.rx(), newRX); 105 | }); 106 | 107 | it("should set the proper value of the DOM attribute", function () { 108 | element.rx(defaultRX); 109 | fixture.call(element); // Redraw 110 | 111 | fixture.selectAll("ellipse") 112 | .each(function () { 113 | chai.assert.equal(this.getAttribute("rx"), element.rx()); 114 | }); 115 | }); 116 | }); 117 | 118 | describe("ry API", function () { 119 | var defaultRY; 120 | 121 | beforeEach(function () { 122 | removeChildren(fixture); 123 | defaultRY = 20; 124 | element.ry(defaultRY); 125 | }); 126 | 127 | it("should get the property", function () { 128 | chai.assert.equal(element.ry(), defaultRY); 129 | }); 130 | 131 | it("should set the property", function () { 132 | var newRY = 10; 133 | element.ry(newRY); 134 | chai.assert.equal(element.ry(), newRY); 135 | }); 136 | 137 | it("should set the proper value of the DOM attribute", function () { 138 | element.ry(defaultRY); 139 | fixture.call(element); // Redraw 140 | 141 | fixture.selectAll("ellipse") 142 | .each(function () { 143 | chai.assert.equal(this.getAttribute("ry"), element.ry()); 144 | }); 145 | }); 146 | }); 147 | 148 | describe("class API", function () { 149 | var defaultClass; 150 | 151 | beforeEach(function () { 152 | removeChildren(fixture); 153 | defaultClass = "ellipses"; 154 | element.class(defaultClass); 155 | }); 156 | 157 | it("should get the property", function () { 158 | chai.assert.equal(element.class(), defaultClass); 159 | }); 160 | 161 | it("should set the property", function () { 162 | var newClass = "ovals"; 163 | element.class(newClass); 164 | chai.assert.equal(element.class(), newClass); 165 | }); 166 | 167 | it("should set the proper value of the DOM attribute", function () { 168 | element.class(defaultClass); 169 | fixture.call(element); // Redraw 170 | 171 | fixture.selectAll("ellipse") 172 | .each(function () { 173 | chai.assert.equal(this.getAttribute("class"), element.class()); 174 | }); 175 | }); 176 | }); 177 | 178 | describe("fill API", function () { 179 | var defaultFill; 180 | 181 | beforeEach(function () { 182 | removeChildren(fixture); 183 | defaultFill = "#FF0000"; 184 | element.fill(defaultFill); 185 | }); 186 | 187 | it("should get the property", function () { 188 | chai.assert.equal(element.fill(), defaultFill); 189 | }); 190 | 191 | it("should set the property", function () { 192 | var newFill = "#0000FF"; 193 | element.fill(newFill); 194 | chai.assert.equal(element.fill(), newFill); 195 | }); 196 | 197 | it("should set the proper value of the DOM attribute", function () { 198 | element.fill(defaultFill); 199 | fixture.call(element); // Redraw 200 | 201 | fixture.selectAll("ellipse") 202 | .each(function () { 203 | chai.assert.equal(this.getAttribute("fill"), element.fill()); 204 | }); 205 | }); 206 | }); 207 | 208 | describe("opacity API", function () { 209 | var defaultOpacity; 210 | 211 | beforeEach(function () { 212 | removeChildren(fixture); 213 | defaultOpacity = 1; 214 | element.opacity(defaultOpacity); 215 | }); 216 | 217 | it("should get the property", function () { 218 | chai.assert.equal(element.opacity(), defaultOpacity); 219 | }); 220 | 221 | it("should set the property", function () { 222 | var newOpacity = 0.5; 223 | element.opacity(newOpacity); 224 | chai.assert.equal(element.opacity(), newOpacity); 225 | }); 226 | 227 | it("should set the proper value of the DOM attribute", function () { 228 | element.opacity(defaultOpacity); 229 | fixture.call(element); // Redraw 230 | 231 | fixture.selectAll("ellipse") 232 | .each(function () { 233 | chai.assert.equal(this.style.opacity, element.opacity()); 234 | }); 235 | }); 236 | }); 237 | 238 | describe("stroke API", function () { 239 | var defaultStroke; 240 | 241 | beforeEach(function () { 242 | removeChildren(fixture); 243 | defaultStroke = "#FF0000"; 244 | element.stroke(defaultStroke); 245 | }); 246 | 247 | it("should get the property", function () { 248 | chai.assert.equal(element.stroke(), defaultStroke); 249 | }); 250 | 251 | it("should set the property", function () { 252 | var newStroke = "#0000FF"; 253 | element.stroke(newStroke); 254 | chai.assert.equal(element.stroke(), newStroke); 255 | }); 256 | 257 | it("should set the proper value of the DOM attribute", function () { 258 | element.stroke(defaultStroke); 259 | fixture.call(element); // Redraw 260 | 261 | fixture.selectAll("ellipse") 262 | .each(function () { 263 | chai.assert.equal(this.getAttribute("stroke"), element.stroke()); 264 | }); 265 | }); 266 | }); 267 | 268 | describe("strokeWidth API", function () { 269 | var defaultStrokeWidth; 270 | 271 | beforeEach(function () { 272 | removeChildren(fixture); 273 | defaultStrokeWidth = 2; 274 | element.strokeWidth(defaultStrokeWidth); 275 | }); 276 | 277 | it("should get the property", function () { 278 | chai.assert.equal(element.strokeWidth(), defaultStrokeWidth); 279 | }); 280 | 281 | it("should set the property", function () { 282 | var newStrokeWidth = 5; 283 | element.strokeWidth(newStrokeWidth); 284 | chai.assert.equal(element.strokeWidth(), newStrokeWidth); 285 | }); 286 | 287 | it("should set the proper value of the DOM attribute", function () { 288 | element.strokeWidth(defaultStrokeWidth); 289 | fixture.call(element); // Redraw 290 | 291 | fixture.selectAll("ellipse") 292 | .each(function () { 293 | chai.assert.equal(this.getAttribute("stroke-width"), element.strokeWidth()); 294 | }); 295 | }); 296 | }); 297 | }); 298 | }); 299 | -------------------------------------------------------------------------------- /test/unit/specs/modules/element/image.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Element: Image SVG Tests", function () { 3 | var image = require("src/modules/element/svg/image"); 4 | var d3fixture = require("fixtures/fixture"); 5 | var data = require("fixtures/data_generator")(10); 6 | var remove = require("fixtures/remove"); 7 | var removeChildren = require("fixtures/remove_children"); 8 | var element = image(); 9 | var fixture; 10 | 11 | beforeEach(function () { 12 | fixture = d3fixture; 13 | 14 | fixture 15 | .datum(data) 16 | .call(element); 17 | }); 18 | 19 | afterEach(function () { 20 | remove(fixture); 21 | }); 22 | 23 | it("should return a function", function () { 24 | var isFunction = (typeof element === "function"); 25 | chai.assert.equal(isFunction, true); 26 | }); 27 | 28 | describe("x API", function () { 29 | var defaultX; 30 | 31 | beforeEach(function () { 32 | removeChildren(fixture); 33 | defaultX = function (d) { return d.x; }; 34 | element.x(defaultX); 35 | }); 36 | 37 | it("should get the property", function () { 38 | chai.assert.equal(element.x(), defaultX); 39 | }); 40 | 41 | it("should set the property", function () { 42 | var newX = function (d) { return d.imageX; }; 43 | element.x(newX); 44 | chai.assert.equal(element.x(), newX); 45 | }); 46 | 47 | it("should set the proper value of the DOM attribute", function () { 48 | element.x(defaultX); // Set new attribute 49 | fixture.call(element); // Redraw images 50 | 51 | fixture.selectAll("image") 52 | .each(function (d) { 53 | chai.assert.equal(this.getAttribute("x"), d.x); 54 | }); 55 | }); 56 | }); 57 | 58 | describe("y API", function () { 59 | var defaultY; 60 | 61 | beforeEach(function () { 62 | removeChildren(fixture); 63 | defaultY = function (d) { return d.y; }; 64 | element.y(defaultY); 65 | }); 66 | 67 | it("should get the property", function () { 68 | chai.assert.equal(element.y(), defaultY); 69 | }); 70 | 71 | it("should set the property", function () { 72 | var newY = function (d) { return d.imageY; }; 73 | element.y(newY); 74 | chai.assert.equal(element.y(), newY); 75 | }); 76 | 77 | it("should set the proper value of the DOM attribute", function () { 78 | element.y(defaultY); // Set new attribute 79 | fixture.call(element); // Redraw images 80 | 81 | fixture.selectAll("image") 82 | .each(function (d) { 83 | chai.assert.equal(this.getAttribute("y"), d.y); 84 | }); 85 | }); 86 | }); 87 | 88 | describe("width API", function () { 89 | var defaultWidth; 90 | 91 | beforeEach(function () { 92 | removeChildren(fixture); 93 | defaultWidth = 20; 94 | element.width(defaultWidth); 95 | }); 96 | 97 | it("should get the property", function () { 98 | chai.assert.equal(element.width(), defaultWidth); 99 | }); 100 | 101 | it("should set the property", function () { 102 | var newWidth = 10; 103 | element.width(newWidth); 104 | chai.assert.equal(element.width(), newWidth); 105 | }); 106 | 107 | it("should set the proper value of the DOM attribute", function () { 108 | element.width(defaultWidth); // Set new attribute 109 | fixture.call(element); // Redraw images 110 | 111 | fixture.selectAll("image") 112 | .each(function () { 113 | chai.assert.equal(this.getAttribute("width"), element.width()); 114 | }); 115 | }); 116 | }); 117 | 118 | describe("height API", function () { 119 | var defaultHeight; 120 | 121 | beforeEach(function () { 122 | removeChildren(fixture); 123 | defaultHeight = 50; 124 | element.height(defaultHeight); 125 | }); 126 | 127 | it("should get the property", function () { 128 | chai.assert.equal(element.height(), defaultHeight); 129 | }); 130 | 131 | it("should set the property", function () { 132 | var newHeight = 60; 133 | element.height(newHeight); 134 | chai.assert.equal(element.height(), newHeight); 135 | }); 136 | 137 | it("should set the proper value of the DOM attribute", function () { 138 | element.height(defaultHeight); // Set new attribute 139 | fixture.call(element); // Redraw images 140 | 141 | fixture.selectAll("image") 142 | .each(function () { 143 | chai.assert.equal(this.getAttribute("height"), element.height()); 144 | }); 145 | }); 146 | }); 147 | 148 | describe("class API", function () { 149 | 150 | var defaultClass; 151 | 152 | beforeEach(function () { 153 | removeChildren(fixture); 154 | defaultClass = "images"; 155 | element.class(defaultClass); 156 | }); 157 | 158 | it("should get the property", function () { 159 | chai.assert.equal(element.class(), defaultClass); 160 | }); 161 | 162 | it("should set the property", function () { 163 | var newClass = "jubilee"; 164 | element.class(newClass); 165 | chai.assert.equal(element.class(), newClass); 166 | }); 167 | 168 | it("should set the proper value of the DOM attribute", function () { 169 | element.class(defaultClass); // Set new attribute 170 | fixture.call(element); // Redraw images 171 | 172 | fixture.selectAll("image") 173 | .each(function () { 174 | chai.assert.equal(this.getAttribute("class"), element.class()); 175 | }); 176 | }); 177 | }); 178 | 179 | describe("xlink API", function () { 180 | var defaultLink; 181 | 182 | beforeEach(function () { 183 | removeChildren(fixture); 184 | defaultLink = "http://www.filmoria.co.uk/wp-content/uploads/2015/03/jubilee-marvel-2.jpg"; 185 | element.xlink(defaultLink); 186 | }); 187 | 188 | it("should get the property", function () { 189 | chai.assert.equal(element.xlink(), defaultLink); 190 | }); 191 | 192 | it("should set the property", function () { 193 | var newLink= "http://www.empireonline.com/images/image_index/original/51752.jpg"; 194 | element.xlink(newLink); 195 | chai.assert.equal(element.xlink(), newLink); 196 | }); 197 | 198 | it("should set the proper value of the DOM attribute", function () { 199 | element.xlink(defaultLink); // Set new attribute 200 | fixture.call(element); // Redraw images 201 | 202 | fixture.selectAll("image") 203 | .each(function () { 204 | chai.assert.equal(this.getAttribute("href"), element.xlink()); 205 | }); 206 | }); 207 | }); 208 | 209 | describe("preserveAspectRatio API", function () { 210 | var defaultRatio; 211 | 212 | beforeEach(function () { 213 | removeChildren(fixture); 214 | defaultRatio = "defer none"; 215 | element.preserveAspectRatio(defaultRatio); 216 | }); 217 | 218 | it("should get the property", function () { 219 | chai.assert.equal(element.preserveAspectRatio(), defaultRatio); 220 | }); 221 | 222 | it("should set the property", function () { 223 | var newRatio = "defer xMaxYMax"; 224 | element.preserveAspectRatio(newRatio); 225 | chai.assert.equal(element.preserveAspectRatio(), newRatio); 226 | }); 227 | 228 | it("should set the proper value of the DOM attribute", function () { 229 | element.preserveAspectRatio(defaultRatio); // Set new attribute 230 | fixture.call(element); // Redraw images 231 | 232 | fixture.selectAll("image") 233 | .each(function () { 234 | chai.assert.equal(this.getAttribute("preserveAspectRatio"), element.preserveAspectRatio()); 235 | }); 236 | }); 237 | }); 238 | }); 239 | }); 240 | -------------------------------------------------------------------------------- /test/unit/specs/modules/element/line.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Element: Line SVG Tests", function () { 3 | var line = require("src/modules/element/svg/line"); 4 | var d3fixture = require("fixtures/fixture"); 5 | var data = require("fixtures/data_generator")(10); 6 | var remove = require("fixtures/remove"); 7 | var removeChildren = require("fixtures/remove_children"); 8 | var element = line(); 9 | var fixture; 10 | 11 | beforeEach(function () { 12 | fixture = d3fixture; 13 | 14 | fixture 15 | .datum(data) 16 | .call(element); 17 | }); 18 | 19 | afterEach(function () { 20 | remove(fixture); 21 | }); 22 | 23 | it("should return a function", function () { 24 | var isFunction = (typeof element === "function"); 25 | chai.assert.equal(isFunction, true); 26 | }); 27 | 28 | describe("x1 API", function () { 29 | var defaultX1; 30 | 31 | beforeEach(function () { 32 | removeChildren(fixture); 33 | defaultX1 = function (d) { return d.x; }; 34 | element.x1(defaultX1); 35 | }); 36 | 37 | it("should get the property", function () { 38 | chai.assert.equal(element.x1(), defaultX1); 39 | }); 40 | 41 | it("should set the property", function () { 42 | var newX1 = function (d) { return d.x1; }; 43 | element.x1(newX1); 44 | chai.assert.equal(element.x1(), newX1); 45 | }); 46 | 47 | it("should set the proper value of the DOM attribute", function () { 48 | element.x1(defaultX1); 49 | fixture.call(element); // Redraw 50 | 51 | fixture.selectAll("line") 52 | .each(function (d, i) { 53 | chai.assert.equal(this.getAttribute("x1"), d.x); 54 | }); 55 | }); 56 | }); 57 | 58 | describe("x2 API", function () { 59 | var defaultX2; 60 | 61 | beforeEach(function () { 62 | removeChildren(fixture); 63 | defaultX2 = function (d) { return d.x; }; 64 | element.x2(defaultX2); 65 | }); 66 | 67 | it("should get the property", function () { 68 | chai.assert.equal(element.x2(), defaultX2); 69 | }); 70 | 71 | it("should set the property", function () { 72 | var newX2 = function (d) { return d.x2; }; 73 | element.x2(newX2); 74 | chai.assert.equal(element.x2(), newX2); 75 | }); 76 | 77 | it("should set the proper value of the DOM attribute", function () { 78 | element.x2(defaultX2); 79 | fixture.call(element); // Redraw 80 | 81 | fixture.selectAll("line") 82 | .each(function (d, i) { 83 | chai.assert.equal(this.getAttribute("x2"), d.x); 84 | }); 85 | }); 86 | }); 87 | 88 | describe("y1 API", function () { 89 | var defaultY1; 90 | 91 | beforeEach(function () { 92 | removeChildren(fixture); 93 | defaultY1 = function (d) { return d.y; }; 94 | element.y1(defaultY1); 95 | }); 96 | 97 | it("should get the property", function () { 98 | chai.assert.equal(element.y1(), defaultY1); 99 | }); 100 | 101 | it("should set the property", function () { 102 | var newY1 = function (d) { return d.y1; }; 103 | element.y1(newY1); 104 | chai.assert.equal(element.y1(), newY1); 105 | }); 106 | 107 | it("should set the proper value of the DOM attribute", function () { 108 | element.y1(defaultY1); 109 | fixture.call(element); // Redraw 110 | 111 | fixture.selectAll("line") 112 | .each(function (d, i) { 113 | chai.assert.equal(this.getAttribute("y1"), d.y); 114 | }); 115 | }); 116 | }); 117 | 118 | describe("y2 API", function () { 119 | var defaultY2; 120 | 121 | beforeEach(function () { 122 | removeChildren(fixture); 123 | defaultY2 = function (d) { return d.y; }; 124 | element.y2(defaultY2); 125 | }); 126 | 127 | it("should get the property", function () { 128 | chai.assert.equal(element.y2(), defaultY2); 129 | }); 130 | 131 | it("should set the property", function () { 132 | var newY2 = function (d) { return d.y2; }; 133 | element.y2(newY2); 134 | chai.assert.equal(element.y2(), newY2); 135 | }); 136 | 137 | it("should set the proper value of the DOM attribute", function () { 138 | element.y2(defaultY2); 139 | fixture.call(element); // Redraw 140 | 141 | fixture.selectAll("line") 142 | .each(function (d, i) { 143 | chai.assert.equal(this.getAttribute("y2"), d.y); 144 | }); 145 | }); 146 | }); 147 | 148 | describe("class API", function () { 149 | var defaultClass; 150 | 151 | beforeEach(function () { 152 | removeChildren(fixture); 153 | defaultClass = "lines"; 154 | element.class(defaultClass); 155 | }); 156 | 157 | it("should get the property", function () { 158 | chai.assert.equal(element.class(), defaultClass); 159 | }); 160 | 161 | it("should set the property", function () { 162 | var newClass = "edges"; 163 | element.class(newClass); 164 | chai.assert.equal(element.class(), newClass); 165 | }); 166 | 167 | it("should set the proper value of the DOM attribute", function () { 168 | element.class(defaultClass); 169 | fixture.call(element); // Redraw 170 | 171 | fixture.selectAll("line") 172 | .each(function () { 173 | chai.assert.equal(this.getAttribute("class"), element.class()); 174 | }); 175 | }); 176 | }); 177 | 178 | describe("opacity API", function () { 179 | var defaultOpacity; 180 | 181 | beforeEach(function () { 182 | removeChildren(fixture); 183 | defaultOpacity = 1; 184 | element.opacity(defaultOpacity); 185 | }); 186 | 187 | it("should get the property", function () { 188 | chai.assert.equal(element.opacity(), defaultOpacity); 189 | }); 190 | 191 | it("should set the property", function () { 192 | var newOpacity = 0.5; 193 | element.opacity(newOpacity); 194 | chai.assert.equal(element.opacity(), newOpacity); 195 | }); 196 | 197 | it("should set the proper value of the DOM attribute", function () { 198 | element.opacity(defaultOpacity); 199 | fixture.call(element); // Redraw 200 | 201 | fixture.selectAll("line") 202 | .each(function () { 203 | chai.assert.equal(this.style.opacity, element.opacity()); 204 | }); 205 | }); 206 | }); 207 | 208 | describe("stroke API", function () { 209 | var defaultStroke; 210 | 211 | beforeEach(function () { 212 | removeChildren(fixture); 213 | defaultStroke = "#FF0000"; 214 | element.stroke(defaultStroke); 215 | }); 216 | 217 | it("should get the property", function () { 218 | chai.assert.equal(element.stroke(), defaultStroke); 219 | }); 220 | 221 | it("should set the property", function () { 222 | var newStroke = "#0000FF"; 223 | element.stroke(newStroke); 224 | chai.assert.equal(element.stroke(), newStroke); 225 | }); 226 | 227 | it("should set the proper value of the DOM attribute", function () { 228 | element.stroke(defaultStroke); 229 | fixture.call(element); // Redraw 230 | 231 | fixture.selectAll("line") 232 | .each(function () { 233 | chai.assert.equal(this.getAttribute("stroke"), element.stroke()); 234 | }); 235 | }); 236 | }); 237 | 238 | describe("strokeWidth API", function () { 239 | var defaultStrokeWidth; 240 | 241 | beforeEach(function () { 242 | removeChildren(fixture); 243 | defaultStrokeWidth = 2; 244 | element.strokeWidth(defaultStrokeWidth); 245 | }); 246 | 247 | it("should get the property", function () { 248 | chai.assert.equal(element.strokeWidth(), defaultStrokeWidth); 249 | }); 250 | 251 | it("should set the property", function () { 252 | var newStrokeWidth = 5; 253 | element.strokeWidth(newStrokeWidth); 254 | chai.assert.equal(element.strokeWidth(), newStrokeWidth); 255 | }); 256 | 257 | it("should set the proper value of the DOM attribute", function () { 258 | element.strokeWidth(defaultStrokeWidth); 259 | fixture.call(element); // Redraw 260 | 261 | fixture.selectAll("line") 262 | .each(function () { 263 | chai.assert.equal(this.getAttribute("stroke-width"), element.strokeWidth()); 264 | }); 265 | }); 266 | }); 267 | }); 268 | }); 269 | -------------------------------------------------------------------------------- /test/unit/specs/modules/element/path.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Element: Path SVG Tests", function () { 3 | var d3 = require("d3"); 4 | var path = require("src/modules/element/svg/path"); 5 | var d3fixture = require("fixtures/fixture"); 6 | var pathGenerator = require("fixtures/path_generator")("line"); 7 | var data = require("fixtures/data_generator")(10); 8 | var remove = require("fixtures/remove"); 9 | var removeChildren = require("fixtures/remove_children"); 10 | var element; 11 | var fixture; 12 | 13 | beforeEach(function () { 14 | element = path().pathGenerator(pathGenerator); 15 | fixture = d3fixture; 16 | 17 | fixture 18 | .datum([data]) 19 | .call(element); 20 | }); 21 | 22 | afterEach(function () { 23 | remove(fixture); 24 | }); 25 | 26 | it("should return a function", function () { 27 | var isFunction = (typeof element === "function"); 28 | chai.assert.equal(isFunction, true); 29 | }); 30 | 31 | describe("pathGenerator API", function () { 32 | var defaultGenerator; 33 | var areaGenerator; 34 | 35 | beforeEach(function () { 36 | removeChildren(fixture); 37 | defaultGenerator = require("fixtures/path_generator")("line"); 38 | areaGenerator = require("fixtures/path_generator")("area"); 39 | element.pathGenerator(defaultGenerator); 40 | }); 41 | 42 | it("should get the property", function () { 43 | chai.assert.equal(element.pathGenerator(), defaultGenerator); 44 | }); 45 | 46 | it("should set the property", function () { 47 | element.pathGenerator(areaGenerator); 48 | chai.assert.equal(element.pathGenerator(), areaGenerator); 49 | }); 50 | 51 | it("should set the proper value of the DOM attribute", function () { 52 | element.pathGenerator(defaultGenerator); 53 | fixture.call(element); 54 | 55 | fixture.selectAll("path") 56 | .each(function (d) { 57 | chai.assert.equal(this.getAttribute("d"), defaultGenerator(d)); 58 | }); 59 | }); 60 | }); 61 | 62 | describe("accessor API", function () { 63 | var defaultAccessor; 64 | 65 | beforeEach(function () { 66 | defaultAccessor = function (d) { return d; }; 67 | element.accessor(defaultAccessor); 68 | }); 69 | 70 | it("should get the property", function () { 71 | chai.assert.equal(element.accessor(), defaultAccessor); 72 | }); 73 | 74 | it("should set the property", function () { 75 | var newAccessor = function (d) { return d.values; }; 76 | element.accessor(newAccessor); 77 | chai.assert.equal(element.accessor(), newAccessor); 78 | }); 79 | }); 80 | 81 | describe("transform API", function () { 82 | var defaultTransform; 83 | var newTransform; 84 | 85 | beforeEach(function () { 86 | removeChildren(fixture); 87 | defaultTransform = "translate(0,0)"; 88 | newTransform = function (d) { 89 | return "transform(" + d.x + "," + d.y + ")"; 90 | }; 91 | }); 92 | 93 | it("should get the property", function () { 94 | element.transform(defaultTransform); 95 | chai.assert.equal(element.transform(), defaultTransform); 96 | }); 97 | 98 | it("should set the property", function () { 99 | element.transform(newTransform); 100 | chai.assert.equal(element.transform(), newTransform); 101 | }); 102 | 103 | it("should set the proper value of the DOM attribute", function () { 104 | element.transform(defaultTransform); 105 | fixture.call(element); 106 | 107 | fixture.selectAll("path") 108 | .each(function (d) { 109 | chai.assert.equal(this.getAttribute("transform"), defaultTransform); 110 | }); 111 | }); 112 | }); 113 | 114 | describe("class API", function () { 115 | var defaultClass; 116 | 117 | beforeEach(function () { 118 | removeChildren(fixture); 119 | defaultClass = "paths"; 120 | element.class(defaultClass); 121 | }); 122 | 123 | it("should get the property", function () { 124 | chai.assert.equal(element.class(), defaultClass); 125 | }); 126 | 127 | it("should set the property", function () { 128 | var newClass = "lines"; 129 | element.class(newClass); 130 | chai.assert.equal(element.class(), newClass); 131 | }); 132 | 133 | it("should set the proper value of the DOM attribute", function () { 134 | element.class(defaultClass); 135 | fixture.call(element); 136 | 137 | fixture.selectAll("path") 138 | .each(function () { 139 | chai.assert.equal(this.getAttribute("class"), element.class()); 140 | }); 141 | }); 142 | }); 143 | 144 | describe("fill API", function () { 145 | var defaultFill; 146 | 147 | beforeEach(function () { 148 | removeChildren(fixture); 149 | defaultFill = "#FF0000"; 150 | element.fill(defaultFill); 151 | }); 152 | 153 | it("should get the property", function () { 154 | chai.assert.equal(element.fill(), defaultFill); 155 | }); 156 | 157 | it("should set the property", function () { 158 | var newFill = "#0000FF"; 159 | element.fill(newFill); 160 | chai.assert.equal(element.fill(), newFill); 161 | }); 162 | 163 | it("should set the proper value of the DOM attribute", function () { 164 | element.fill(defaultFill); 165 | fixture.call(element); 166 | 167 | fixture.selectAll("path") 168 | .each(function () { 169 | chai.assert.equal(this.getAttribute("fill"), element.fill()); 170 | }); 171 | }); 172 | }); 173 | 174 | describe("opacity API", function () { 175 | var defaultOpacity; 176 | 177 | beforeEach(function () { 178 | removeChildren(fixture); 179 | defaultOpacity = 1; 180 | element.opacity(defaultOpacity); 181 | }); 182 | 183 | it("should get the property", function () { 184 | chai.assert.equal(element.opacity(), defaultOpacity); 185 | }); 186 | 187 | it("should set the property", function () { 188 | var newOpacity = 0.5; 189 | element.opacity(newOpacity); 190 | chai.assert.equal(element.opacity(), newOpacity); 191 | }); 192 | 193 | it("should set the proper value of the DOM attribute", function () { 194 | element.opacity(defaultOpacity); 195 | fixture.call(element); 196 | 197 | fixture.selectAll("path") 198 | .each(function () { 199 | chai.assert.equal(this.style.opacity, element.opacity()); 200 | }); 201 | }); 202 | }); 203 | 204 | describe("stroke API", function () { 205 | var defaultStroke; 206 | 207 | beforeEach(function () { 208 | removeChildren(fixture); 209 | defaultStroke = d3.functor("#FF0000"); 210 | element.stroke(defaultStroke); 211 | }); 212 | 213 | it("should get the property", function () { 214 | chai.assert.equal(element.stroke(), defaultStroke); 215 | }); 216 | 217 | it("should set the property", function () { 218 | var newStroke = d3.functor("#0000FF"); 219 | element.stroke(newStroke); 220 | chai.assert.equal(element.stroke(), newStroke); 221 | }); 222 | 223 | it("should set the proper value of the DOM attribute", function () { 224 | element.stroke(defaultStroke); 225 | fixture.call(element); 226 | 227 | fixture.selectAll("path") 228 | .each(function () { 229 | // element.stroke() returns a function that needs to be called 230 | chai.assert.equal(this.getAttribute("stroke"), element.stroke()()); 231 | }); 232 | }); 233 | }); 234 | 235 | describe("strokeWidth API", function () { 236 | var defaultStrokeWidth; 237 | 238 | beforeEach(function () { 239 | removeChildren(fixture); 240 | defaultStrokeWidth = 2; 241 | element.strokeWidth(defaultStrokeWidth); 242 | }); 243 | 244 | it("should get the property", function () { 245 | chai.assert.equal(element.strokeWidth(), defaultStrokeWidth); 246 | }); 247 | 248 | it("should set the property", function () { 249 | var newStrokeWidth = 5; 250 | element.strokeWidth(newStrokeWidth); 251 | chai.assert.equal(element.strokeWidth(), newStrokeWidth); 252 | }); 253 | 254 | it("should set the proper value of the DOM attribute", function () { 255 | element.strokeWidth(defaultStrokeWidth); 256 | fixture.call(element); 257 | 258 | fixture.selectAll("path") 259 | .each(function () { 260 | chai.assert.equal(this.getAttribute("stroke-width"), element.strokeWidth()); 261 | }); 262 | }); 263 | }); 264 | }); 265 | }); -------------------------------------------------------------------------------- /test/unit/specs/modules/element/rect.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Element: Rect SVG Tests", function () { 3 | var rect = require("src/modules/element/svg/rect"); 4 | var d3fixture = require("fixtures/fixture"); 5 | var data = require("fixtures/data_generator")(10); 6 | var remove = require("fixtures/remove"); 7 | var removeChildren = require("fixtures/remove_children"); 8 | var element = rect(); 9 | var fixture; 10 | 11 | beforeEach(function () { 12 | fixture = d3fixture; 13 | 14 | fixture 15 | .datum(data) 16 | .call(element); 17 | }); 18 | 19 | afterEach(function () { 20 | remove(fixture); 21 | }); 22 | 23 | it("should return a function", function () { 24 | var isFunction = (typeof element === "function"); 25 | chai.assert.equal(isFunction, true); 26 | }); 27 | 28 | describe("x API", function () { 29 | var defaultX; 30 | 31 | beforeEach(function () { 32 | removeChildren(fixture); 33 | defaultX = function (d) { return d.x; }; 34 | element.x(defaultX); 35 | }); 36 | 37 | it("should get the property", function () { 38 | chai.assert.equal(element.x(), defaultX); 39 | }); 40 | 41 | it("should set the property", function () { 42 | var newX = function (d) { return d.rectX; }; 43 | element.x(newX); 44 | chai.assert.equal(element.x(), newX); 45 | }); 46 | 47 | it("should set the proper value of the DOM attribute", function () { 48 | element.x(defaultX); // Set new attribute 49 | fixture.call(element); // Redraw rects 50 | 51 | fixture.selectAll("rect") 52 | .each(function (d) { 53 | chai.assert.equal(this.getAttribute("x"), d.x); 54 | }); 55 | }); 56 | }); 57 | 58 | describe("y API", function () { 59 | var defaultY; 60 | 61 | beforeEach(function () { 62 | removeChildren(fixture); 63 | defaultY = function (d) { return d.y; }; 64 | element.y(defaultY); 65 | }); 66 | 67 | it("should get the property", function () { 68 | chai.assert.equal(element.y(), defaultY); 69 | }); 70 | 71 | it("should set the property", function () { 72 | var newY = function (d) { return d.rectY; }; 73 | element.y(newY); 74 | chai.assert.equal(element.y(), newY); 75 | }); 76 | 77 | it("should set the proper value of the DOM attribute", function () { 78 | element.y(defaultY); // Set new attribute 79 | fixture.call(element); // Redraw rects 80 | 81 | fixture.selectAll("rect") 82 | .each(function (d) { 83 | chai.assert.equal(this.getAttribute("y"), d.y); 84 | }); 85 | }); 86 | }); 87 | 88 | describe("rx API", function () { 89 | var defaultRX; 90 | 91 | beforeEach(function () { 92 | removeChildren(fixture); 93 | defaultRX = 5; 94 | element.rx(defaultRX); 95 | }); 96 | 97 | it("should get the property", function () { 98 | chai.assert.equal(element.rx(), defaultRX); 99 | }); 100 | 101 | it("should set the property", function () { 102 | var newRX = 10; 103 | element.rx(newRX); 104 | chai.assert.equal(element.rx(), newRX); 105 | }); 106 | 107 | it("should set the proper value of the DOM attribute", function () { 108 | element.rx(defaultRX); // Set new attribute 109 | fixture.call(element); // Redraw rects 110 | 111 | fixture.selectAll("rect") 112 | .each(function () { 113 | chai.assert.equal(this.getAttribute("rx"), element.rx()); 114 | }); 115 | }); 116 | }); 117 | 118 | describe("ry API", function () { 119 | var defaultRY; 120 | 121 | beforeEach(function () { 122 | removeChildren(fixture); 123 | defaultRY = 5; 124 | element.ry(defaultRY); 125 | }); 126 | 127 | it("should get the property", function () { 128 | chai.assert.equal(element.ry(), defaultRY); 129 | }); 130 | 131 | it("should set the property", function () { 132 | var newRY = 10; 133 | element.ry(newRY); 134 | chai.assert.equal(element.ry(), newRY); 135 | }); 136 | 137 | it("should set the proper value of the DOM attribute", function () { 138 | element.ry(defaultRY); // Set new attribute 139 | fixture.call(element); // Redraw rects 140 | 141 | fixture.selectAll("rect") 142 | .each(function () { 143 | chai.assert.equal(this.getAttribute("ry"), element.ry()); 144 | }); 145 | }); 146 | }); 147 | 148 | describe("width API", function () { 149 | var defaultWidth; 150 | 151 | beforeEach(function () { 152 | removeChildren(fixture); 153 | defaultWidth = 20; 154 | element.width(defaultWidth); 155 | }); 156 | 157 | it("should get the property", function () { 158 | chai.assert.equal(element.width(), defaultWidth); 159 | }); 160 | 161 | it("should set the property", function () { 162 | var newWidth = 10; 163 | element.width(newWidth); 164 | chai.assert.equal(element.width(), newWidth); 165 | }); 166 | 167 | it("should set the proper value of the DOM attribute", function () { 168 | element.width(defaultWidth); // Set new attribute 169 | fixture.call(element); // Redraw rects 170 | 171 | fixture.selectAll("rect") 172 | .each(function () { 173 | chai.assert.equal(this.getAttribute("width"), element.width()); 174 | }); 175 | }); 176 | }); 177 | 178 | describe("height API", function () { 179 | var defaultHeight; 180 | 181 | beforeEach(function () { 182 | removeChildren(fixture); 183 | defaultHeight = 50; 184 | element.height(defaultHeight); 185 | }); 186 | 187 | it("should get the property", function () { 188 | chai.assert.equal(element.height(), defaultHeight); 189 | }); 190 | 191 | it("should set the property", function () { 192 | var newHeight = 60; 193 | element.height(newHeight); 194 | chai.assert.equal(element.height(), newHeight); 195 | }); 196 | 197 | it("should set the proper value of the DOM attribute", function () { 198 | element.height(defaultHeight); // Set new attribute 199 | fixture.call(element); // Redraw rects 200 | 201 | fixture.selectAll("rect") 202 | .each(function () { 203 | chai.assert.equal(this.getAttribute("height"), element.height()); 204 | }); 205 | }); 206 | }); 207 | 208 | describe("class API", function () { 209 | var defaultClass; 210 | 211 | beforeEach(function () { 212 | removeChildren(fixture); 213 | defaultClass = "rects"; 214 | element.class(defaultClass); 215 | }); 216 | 217 | it("should get the property", function () { 218 | chai.assert.equal(element.class(), defaultClass); 219 | }); 220 | 221 | it("should set the property", function () { 222 | var newClass = "squares"; 223 | element.class(newClass); 224 | chai.assert.equal(element.class(), newClass); 225 | }); 226 | 227 | it("should set the proper value of the DOM attribute", function () { 228 | element.class(defaultClass); // Set new attribute 229 | fixture.call(element); // Redraw rects 230 | 231 | fixture.selectAll("rect") 232 | .each(function () { 233 | chai.assert.equal(this.getAttribute("class"), element.class()); 234 | }); 235 | }); 236 | }); 237 | 238 | describe("fill API", function () { 239 | var defaultFill; 240 | 241 | beforeEach(function () { 242 | removeChildren(fixture); 243 | defaultFill = "#FF0000"; 244 | element.fill(defaultFill); 245 | }); 246 | 247 | it("should get the property", function () { 248 | chai.assert.equal(element.fill(), defaultFill); 249 | }); 250 | 251 | it("should set the property", function () { 252 | var newFill = "#0000FF"; 253 | element.fill(newFill); 254 | chai.assert.equal(element.fill(), newFill); 255 | }); 256 | 257 | it("should set the proper value of the DOM attribute", function () { 258 | element.fill(defaultFill); // Set new attribute 259 | fixture.call(element); // Redraw rects 260 | 261 | fixture.selectAll("rect") 262 | .each(function () { 263 | chai.assert.equal(this.getAttribute("fill"), element.fill()); 264 | }); 265 | }); 266 | }); 267 | 268 | describe("opacity API", function () { 269 | var defaultOpacity; 270 | 271 | beforeEach(function () { 272 | removeChildren(fixture); 273 | defaultOpacity = 1; 274 | element.opacity(defaultOpacity); 275 | }); 276 | 277 | it("should get the property", function () { 278 | chai.assert.equal(element.opacity(), defaultOpacity); 279 | }); 280 | 281 | it("should set the property", function () { 282 | var newOpacity = 0.5; 283 | element.opacity(newOpacity); 284 | chai.assert.equal(element.opacity(), newOpacity); 285 | }); 286 | 287 | it("should set the proper value of the DOM attribute", function () { 288 | element.opacity(defaultOpacity); // Set new attribute 289 | fixture.call(element); // Redraw rects 290 | 291 | fixture.selectAll("rect") 292 | .each(function () { 293 | chai.assert.equal(this.style.opacity, element.opacity()); 294 | }); 295 | }); 296 | }); 297 | 298 | describe("stroke API", function () { 299 | var defaultStroke; 300 | 301 | beforeEach(function () { 302 | removeChildren(fixture); 303 | defaultStroke = "#FF0000"; 304 | element.stroke(defaultStroke); 305 | }); 306 | 307 | it("should get the property", function () { 308 | chai.assert.equal(element.stroke(), defaultStroke); 309 | }); 310 | 311 | it("should set the property", function () { 312 | var newStroke = "#0000FF"; 313 | element.stroke(newStroke); 314 | chai.assert.equal(element.stroke(), newStroke); 315 | }); 316 | 317 | it("should set the proper value of the DOM attribute", function () { 318 | element.stroke(defaultStroke); // Set new attribute 319 | fixture.call(element); // Redraw rects 320 | 321 | fixture.selectAll("rect") 322 | .each(function () { 323 | chai.assert.equal(this.getAttribute("stroke"), element.stroke()); 324 | }); 325 | }); 326 | }); 327 | 328 | describe("strokeWidth API", function () { 329 | var defaultStrokeWidth; 330 | 331 | beforeEach(function () { 332 | removeChildren(fixture); 333 | defaultStrokeWidth = 2; 334 | element.strokeWidth(defaultStrokeWidth); 335 | }); 336 | 337 | it("should get the property", function () { 338 | chai.assert.equal(element.strokeWidth(), defaultStrokeWidth); 339 | }); 340 | 341 | it("should set the property", function () { 342 | var newStrokeWidth = 5; 343 | element.strokeWidth(newStrokeWidth); 344 | chai.assert.equal(element.strokeWidth(), newStrokeWidth); 345 | }); 346 | 347 | it("should set the proper value of the DOM attribute", function () { 348 | element.strokeWidth(defaultStrokeWidth); // Set new attribute 349 | fixture.call(element); // Redraw rects 350 | 351 | fixture.selectAll("rect") 352 | .each(function () { 353 | chai.assert.equal(this.getAttribute("stroke-width"), element.strokeWidth()); 354 | }); 355 | }); 356 | }); 357 | }); 358 | }); -------------------------------------------------------------------------------- /test/unit/specs/modules/element/text.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Element: Text SVG Tests", function () { 3 | var text = require("src/modules/element/svg/text"); 4 | var d3fixture = require("fixtures/fixture"); 5 | var data = require("fixtures/data_generator")(10); 6 | var remove = require("fixtures/remove"); 7 | var removeChildren = require("fixtures/remove_children"); 8 | var element = text(); 9 | var fixture; 10 | 11 | beforeEach(function () { 12 | fixture = d3fixture; 13 | 14 | fixture 15 | .datum(data) 16 | .call(element); 17 | }); 18 | 19 | afterEach(function () { 20 | remove(fixture); 21 | }); 22 | 23 | it("should return a function", function () { 24 | var isFunction = (typeof element === "function"); 25 | chai.assert.equal(isFunction, true); 26 | }); 27 | 28 | describe("x API", function () { 29 | var defaultX; 30 | 31 | beforeEach(function () { 32 | removeChildren(fixture); 33 | defaultX = function (d) { return d.x; }; 34 | element.x(defaultX); 35 | }); 36 | 37 | it("should get the property", function () { 38 | chai.assert.equal(element.x(), defaultX); 39 | }); 40 | 41 | it("should set the property", function () { 42 | var newX = function (d) { return d.cx; }; 43 | element.x(newX); 44 | chai.assert.equal(element.x(), newX); 45 | }); 46 | 47 | it("should set the proper value of the DOM attribute", function () { 48 | element.x(defaultX); 49 | fixture.call(element); 50 | 51 | fixture.selectAll("text") 52 | .each(function (d) { 53 | chai.assert.equal(this.getAttribute("x"), d.x); 54 | }); 55 | }); 56 | 57 | }); 58 | 59 | describe("y API", function () { 60 | var defaultY; 61 | 62 | beforeEach(function () { 63 | removeChildren(fixture); 64 | defaultY = function (d) { return d.y; }; 65 | element.y(defaultY); 66 | }); 67 | 68 | it("should get the property", function () { 69 | chai.assert.equal(element.y(), defaultY); 70 | }); 71 | 72 | it("should set the property", function () { 73 | var newY = function (d) { return d.cy; }; 74 | element.y(newY); 75 | chai.assert.equal(element.y(), newY); 76 | }); 77 | 78 | it("should set the proper value of the DOM attribute", function () { 79 | element.y(defaultY); 80 | fixture.call(element); 81 | 82 | fixture.selectAll("text") 83 | .each(function (d) { 84 | chai.assert.equal(this.getAttribute("y"), d.y); 85 | }); 86 | }); 87 | }); 88 | 89 | describe("dx API", function () { 90 | var defaultDX; 91 | 92 | beforeEach(function () { 93 | removeChildren(fixture); 94 | defaultDX = function (d) { return d.x; }; 95 | element.dx(defaultDX); 96 | }); 97 | 98 | it("should get the property", function () { 99 | chai.assert.equal(element.dx(), defaultDX); 100 | }); 101 | 102 | it("should set the property", function () { 103 | var newDX = function (d) { return d.dx; }; 104 | element.dx(newDX); 105 | chai.assert.equal(element.dx(), newDX); 106 | }); 107 | 108 | it("should set the proper value of the DOM attribute", function () { 109 | element.dx(defaultDX); 110 | fixture.call(element); 111 | 112 | fixture.selectAll("text") 113 | .each(function (d) { 114 | chai.assert.equal(this.getAttribute("dx"), d.x); 115 | }); 116 | }); 117 | 118 | }); 119 | 120 | describe("dy API", function () { 121 | var defaultDY; 122 | 123 | beforeEach(function () { 124 | removeChildren(fixture); 125 | defaultDY = function (d) { return d.y; }; 126 | element.dy(defaultDY); 127 | }); 128 | 129 | it("should get the property", function () { 130 | chai.assert.equal(element.dy(), defaultDY); 131 | }); 132 | 133 | it("should set the property", function () { 134 | var newDY = function (d) { return d.dy; }; 135 | element.dy(newDY); 136 | chai.assert.equal(element.dy(), newDY); 137 | }); 138 | 139 | it("should set the proper value of the DOM attribute", function () { 140 | element.dy(defaultDY); 141 | fixture.call(element); 142 | 143 | fixture.selectAll("text") 144 | .each(function (d) { 145 | chai.assert.equal(this.getAttribute("dy"), d.y); 146 | }); 147 | }); 148 | }); 149 | 150 | describe("class API", function () { 151 | var defaultClass; 152 | 153 | beforeEach(function () { 154 | removeChildren(fixture); 155 | defaultClass = "text"; 156 | element.class(defaultClass); 157 | }); 158 | 159 | it("should get the property", function () { 160 | chai.assert.equal(element.class(), defaultClass); 161 | }); 162 | 163 | it("should set the property", function () { 164 | element.class("test"); 165 | chai.assert.equal(element.class(), "test"); 166 | }); 167 | 168 | it("should set the proper value of the DOM attribute", function () { 169 | element.class("text"); 170 | fixture.call(element); 171 | 172 | fixture.selectAll("text") 173 | .each(function () { 174 | chai.assert.equal(this.getAttribute("class"), element.class()); 175 | }); 176 | }); 177 | }); 178 | 179 | describe("transform API", function () { 180 | var defaultTransform; 181 | var newTransform; 182 | 183 | beforeEach(function () { 184 | removeChildren(fixture); 185 | defaultTransform = "translate(0,0)"; 186 | newTransform = function () { 187 | return "rotate(45)"; 188 | }; 189 | }); 190 | 191 | it("should get the property", function () { 192 | element.transform(defaultTransform); 193 | chai.assert.equal(element.transform(), defaultTransform); 194 | }); 195 | 196 | it("should set the property", function () { 197 | element.transform(newTransform); 198 | chai.assert.equal(element.transform(), newTransform); 199 | }); 200 | 201 | it("should set the proper value of the DOM attribute", function () { 202 | element.transform(defaultTransform); 203 | fixture.call(element); 204 | 205 | fixture.selectAll("path") 206 | .each(function () { 207 | chai.assert.equal(this.getAttribute("transform"), defaultTransform); 208 | }); 209 | }); 210 | }); 211 | 212 | describe("fill API", function () { 213 | var defaultFill = "#0000FF"; 214 | 215 | beforeEach(function () { 216 | removeChildren(fixture); 217 | element.fill(defaultFill); 218 | }); 219 | 220 | it("should get the property", function () { 221 | chai.assert.equal(element.fill(), defaultFill); 222 | }); 223 | 224 | it("should set the property", function () { 225 | var newFill = "#FF0000"; 226 | element.fill(newFill); 227 | chai.assert.equal(element.fill(), newFill); 228 | }); 229 | 230 | it("should set the proper value of the DOM attribute", function () { 231 | element.fill(defaultFill); 232 | fixture.call(element); 233 | 234 | fixture.selectAll("text") 235 | .each(function () { 236 | chai.assert.equal(this.getAttribute("fill"), element.fill()); 237 | }); 238 | }); 239 | }); 240 | 241 | describe("text API", function () { 242 | var defaultText = "value"; 243 | 244 | beforeEach(function () { 245 | removeChildren(fixture); 246 | element.text(defaultText); 247 | }); 248 | 249 | it("should get the property", function () { 250 | chai.assert.equal(element.text(), defaultText); 251 | }); 252 | 253 | it("should set the property", function () { 254 | var newText = "new value"; 255 | element.text(newText); 256 | chai.assert.equal(element.text(), newText); 257 | }); 258 | 259 | it("should set the proper value of the DOM attribute", function () { 260 | element.text(defaultText); 261 | fixture.call(element); 262 | 263 | fixture.selectAll("text") 264 | .each(function () { 265 | chai.assert.equal(this.innerHTML, element.text()); 266 | }); 267 | }); 268 | }); 269 | 270 | describe("anchor API", function () { 271 | var defaultAnchor = "middle"; 272 | 273 | beforeEach(function () { 274 | removeChildren(fixture); 275 | element.anchor(defaultAnchor); 276 | }); 277 | 278 | it("should get the property", function () { 279 | chai.assert.equal(element.anchor(), defaultAnchor); 280 | }); 281 | 282 | it("should set the property", function () { 283 | var newAnchor = "start"; 284 | element.anchor(newAnchor); 285 | chai.assert.equal(element.anchor(), newAnchor); 286 | }); 287 | 288 | it("should set the proper value of the DOM attribute", function () { 289 | element.anchor(defaultAnchor); 290 | fixture.call(element); 291 | 292 | fixture.selectAll("text") 293 | .each(function () { 294 | chai.assert.equal(this.style["text-anchor"], element.anchor()); 295 | }); 296 | }); 297 | }); 298 | }); 299 | }); 300 | -------------------------------------------------------------------------------- /test/unit/specs/modules/functor.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Functor tests", function () { 3 | var functor = require("functor"); 4 | var func = function (selection) { 5 | selection.each(function (data) { 6 | return data; 7 | }); 8 | }; 9 | var options = {}; 10 | var statement = "test works"; 11 | var d3fixture = require("fixtures/fixture"); 12 | var remove = require("fixtures/remove"); 13 | var fixture; 14 | 15 | beforeEach(function () { 16 | fixture = d3fixture; 17 | func.test = function (_) { 18 | if (!arguments.length) { return statement; } 19 | statement = _; 20 | }; 21 | }); 22 | 23 | afterEach(function () { 24 | statement = "test works"; 25 | options = {}; 26 | remove(fixture); 27 | }); 28 | 29 | it("should return a function", function () { 30 | var testFunc = functor(); 31 | chai.assert.isFunction(testFunc); 32 | }); 33 | 34 | describe("function API", function () { 35 | it("should set and return the function", function () { 36 | var testFunc = functor().function(func); 37 | chai.assert.equal(testFunc.function(), func); 38 | }); 39 | }); 40 | 41 | describe("option API", function () { 42 | it("should set and return the options", function () { 43 | var opts = { test: true }; 44 | var testFunc = functor().function(func).options(opts); 45 | chai.assert.deepEqual(testFunc.options(), opts); 46 | }); 47 | }); 48 | 49 | describe("d3 selection as argument", function () { 50 | it("should take a selection as its argument", function () { 51 | var testFunc = functor().function(func); 52 | var data = [1, 2, 3]; 53 | }); 54 | }); 55 | }); 56 | }); -------------------------------------------------------------------------------- /test/unit/specs/modules/helpers/add_event_listener.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("addEventListener tests", function () { 3 | var addEventListener = require("src/modules/helpers/add_event_listener"); 4 | var events = require("src/modules/component/events/events"); 5 | var chart; 6 | var addListener; 7 | 8 | beforeEach(function () { 9 | chart = events(); 10 | addListener = addEventListener(chart); 11 | }); 12 | 13 | afterEach(function () { 14 | chart.listeners({}); 15 | }); 16 | 17 | it("should return a function", function () { 18 | chai.assert.isFunction(addListener); 19 | }); 20 | 21 | it("should add an event type and listener", function () { 22 | var clickFunction = function (e) { return e; }; 23 | addListener("click", clickFunction); 24 | 25 | chai.assert.isArray(chart.listeners().click); 26 | chai.assert.equal(chart.listeners().click[0], clickFunction); 27 | }); 28 | 29 | it("should add an event listener when event type is null", function () { 30 | var clickFunction = function (e) { return e; }; 31 | chart.listeners.click = null; 32 | addListener("click", clickFunction); 33 | 34 | chai.assert.isArray(chart.listeners().click); 35 | chai.assert.equal(chart.listeners().click[0], clickFunction); 36 | }); 37 | 38 | it("should return an array of listeners", function () { 39 | var brushFunction = function (e) { return e; }; 40 | addListener("brush", brushFunction); 41 | 42 | chai.assert.isArray(addListener("brush")); 43 | chai.assert.equal(addListener("brush").length, chart.listeners().brush.length); 44 | }); 45 | }); 46 | }); -------------------------------------------------------------------------------- /test/unit/specs/modules/helpers/remove_event_listener.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("removeEventListener tests", function () { 3 | var removeEventListener = require("src/modules/helpers/remove_event_listener"); 4 | var events = require("src/modules/component/events/events"); 5 | var clickFunction1 = function () { console.log("click function 1"); }; 6 | var clickFunction2 = function () { console.log("click function 2"); }; 7 | var chart; 8 | var removeListener; 9 | 10 | beforeEach(function () { 11 | chart = events(); 12 | chart.listeners({ 13 | click: [ 14 | clickFunction1, 15 | clickFunction2 16 | ] 17 | }); 18 | removeListener = removeEventListener(chart); 19 | }); 20 | 21 | afterEach(function () { 22 | chart.listeners({}); 23 | }); 24 | 25 | it("should return a function", function () { 26 | chai.assert.isFunction(removeListener); 27 | }); 28 | 29 | it("should set event types to null", function () { 30 | removeListener("click"); 31 | chai.assert.equal(chart.listeners().click, null); 32 | }); 33 | 34 | it("should simply return", function () { 35 | var brushFunction = function (e) { console.log(e); }; 36 | removeListener("brush", brushFunction); 37 | chai.assert.isUndefined(chart.listeners().brush); 38 | }); 39 | 40 | it("should remove event listener from listeners array", function () { 41 | removeListener("click", clickFunction2); 42 | chai.assert.equal(chart.listeners().click.length, 1); 43 | chai.assert.equal(chart.listeners().click[0], clickFunction1); 44 | }); 45 | }); 46 | }); -------------------------------------------------------------------------------- /test/unit/specs/modules/helpers/scaletor.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("scaletor tests", function () { 3 | var d3 = require("d3"); 4 | var scaletor = require("src/modules/helpers/scaletor"); 5 | 6 | it("should return a function", function () { 7 | var scales = [ 8 | d3.scale.linear(), 9 | "linear", 10 | function () {} 11 | ]; 12 | 13 | scales.forEach(function (scale) { 14 | chai.assert.isFunction(scaletor(scale)); 15 | }); 16 | }); 17 | 18 | it("should return a proper d3 scale", function () { 19 | var scales = { 20 | linear: d3.scale.linear(), 21 | ordinal: d3.scale.ordinal(), 22 | sqrt: d3.scale.sqrt() 23 | }; 24 | 25 | Object.keys(scales).forEach(function (scale) { 26 | var scaletorDomain = scaletor(scale).domain(); 27 | var d3ScaleDomain = scales[scale].domain(); 28 | chai.assert.deepEqual(scaletorDomain, d3ScaleDomain); 29 | }); 30 | }); 31 | 32 | it("should return a d3 linear scale with invalid argument", function () { 33 | var invalidArgs = ["posture", undefined, null, false]; 34 | 35 | invalidArgs.forEach(function (arg) { 36 | var scale = scaletor(arg); 37 | var d3LinearScaleDomain = d3.scale.linear().domain(); 38 | 39 | chai.assert.deepEqual(scale.domain(), d3LinearScaleDomain); 40 | }); 41 | }); 42 | 43 | it("should return d3 time scales", function () { 44 | var times = ["time", "time.utc"]; 45 | var timeDomain = d3.time.scale().domain(); 46 | 47 | times.forEach(function (str) { 48 | var domain = scaletor(str).domain(); 49 | chai.assert.deepEqual(domain, timeDomain); 50 | }); 51 | }); 52 | }); 53 | }); -------------------------------------------------------------------------------- /test/unit/specs/modules/helpers/timeparser.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("timeparser tests", function () { 3 | var timeParser = require("src/modules/helpers/timeparser"); 4 | var timeNotation = { 5 | s: "second", 6 | m: "minute", 7 | h: "hour", 8 | d: "day", 9 | w: "week", 10 | M: "month", 11 | y: "year" 12 | }; 13 | var arr = Object.keys(timeNotation); 14 | 15 | it("should return undefined if argument is not a string", function () { 16 | var vals = [ 17 | timeParser(true), 18 | timeParser(1), 19 | timeParser({}), 20 | timeParser([]), 21 | timeParser(function () {}) 22 | ]; 23 | 24 | vals.forEach(function (v) { 25 | chai.assert.isUndefined(v); 26 | }); 27 | }); 28 | 29 | it("should return time notation if valid string", function () { 30 | arr.forEach(function (v) { 31 | var timeString = 10 + v; 32 | chai.assert.equal(timeParser(timeString), timeNotation[v]); 33 | }); 34 | }); 35 | 36 | it("should error on an invalid string", function () { 37 | var str = "10D"; 38 | 39 | chai.assert.throw(function () { 40 | timeParser(str); 41 | }, "Invalid time string " + str); 42 | }); 43 | }); 44 | }); -------------------------------------------------------------------------------- /test/unit/specs/modules/layout/base.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Layout: base tests", function() { 3 | var base = require("src/modules/layout/base"); 4 | var data = [{}, {}, {}]; 5 | var size = [300, 300]; 6 | 7 | describe("rows", function () { 8 | var rows; 9 | var rowsData; 10 | 11 | beforeEach(function () { 12 | rows = base().type("rows").size(size); 13 | rowsData = rows(data); 14 | }); 15 | 16 | it("should be a function", function () { 17 | chai.assert.isFunction(rows); 18 | }); 19 | 20 | it("should create rows", function () { 21 | var width = size[0]; 22 | var height = size[1] / rowsData.length; 23 | 24 | rowsData.forEach(function (chart) { 25 | chai.assert.equal(chart.dx, 0); 26 | chai.assert.equal(chart.dy % height, 0); 27 | chai.assert.equal(chart.width, width); 28 | chai.assert.equal(chart.height, height); 29 | }); 30 | }); 31 | }); 32 | 33 | describe("columns", function () { 34 | var cols; 35 | var colsData; 36 | 37 | beforeEach(function () { 38 | cols = base().type("columns").size(size); 39 | colsData = cols(data); 40 | }); 41 | 42 | it("should be a function", function () { 43 | chai.assert.isFunction(cols); 44 | }); 45 | 46 | it("should create columns", function () { 47 | var width = size[0] / colsData.length; 48 | var height = size[1]; 49 | 50 | colsData.forEach(function (chart) { 51 | chai.assert.equal(chart.dx % width, 0); 52 | chai.assert.equal(chart.dy, 0); 53 | chai.assert.equal(chart.width, width); 54 | chai.assert.equal(chart.height, height); 55 | }); 56 | }); 57 | }); 58 | 59 | describe("grid", function () { 60 | var grid; 61 | var gridData; 62 | 63 | beforeEach(function () { 64 | grid = base().type("grid").size(size); 65 | gridData = grid(data); 66 | }); 67 | 68 | it("should be a function", function () { 69 | chai.assert.isFunction(grid); 70 | }); 71 | 72 | it("should create grids", function () { 73 | var width = size[0] / Math.round(Math.sqrt(data.length)); 74 | var height = size[1] / Math.ceil(Math.sqrt(data.length)); 75 | 76 | gridData.forEach(function (chart) { 77 | chai.assert.equal(chart.dx % width, 0); 78 | chai.assert.equal(chart.dy % height, 0); 79 | chai.assert.equal(chart.width, width); 80 | chai.assert.equal(chart.height, height); 81 | }); 82 | }); 83 | }); 84 | }); 85 | }); -------------------------------------------------------------------------------- /test/unit/specs/modules/layout/grid.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("Layout: grid tests", function () { 3 | var gridFunction = require("src/modules/layout/grid"); 4 | var data = [{}, {}, {}]; 5 | var size = [625, 625]; 6 | var grid; 7 | var gridData; 8 | 9 | beforeEach(function () { 10 | grid = gridFunction().size(size); 11 | gridData = grid(data); 12 | }); 13 | 14 | it("should return a function", function () { 15 | chai.assert.isFunction(grid); 16 | }); 17 | 18 | it("should create grids", function () { 19 | var width = size[0] / Math.ceil(Math.sqrt(data.length)); 20 | var height = size[1] / Math.ceil(Math.sqrt(data.length)); 21 | 22 | gridData.forEach(function (chart) { 23 | chai.assert.equal(chart.dx % width, 0); 24 | chai.assert.equal(chart.dy % height, 0); 25 | chai.assert.equal(chart.width, width); 26 | chai.assert.equal(chart.height, height); 27 | }); 28 | }); 29 | }); 30 | }); -------------------------------------------------------------------------------- /test/unit/specs/modules/valuator.js: -------------------------------------------------------------------------------- 1 | define(function (require) { 2 | describe("valuator tests", function () { 3 | var valuator = require("valuator"); 4 | 5 | it("should return a function", function () { 6 | var func = valuator("x"); 7 | chai.assert.isFunction(func); 8 | }); 9 | 10 | it("should return the function passed", function () { 11 | var x = function (d) { return d.x; }; 12 | var func = valuator(x); 13 | chai.assert.equal(func, x); 14 | }); 15 | 16 | it("should return a function that accesses a key (passed as the argument) from an object", function () { 17 | var func = valuator("x"); 18 | var obj = { x: true }; 19 | var val = func(obj); 20 | chai.assert.isTrue(val); 21 | }); 22 | 23 | it("should return the value passed if not string or function", function () { 24 | var arr = [1, true, [1, 2, 3], { a: true }]; 25 | arr.forEach(function (val) { 26 | var func = valuator(val); 27 | chai.assert.deepEqual(func(), val); 28 | }); 29 | }); 30 | }); 31 | }); --------------------------------------------------------------------------------