├── .editorconfig ├── .gitattributes ├── .gitignore ├── .gitmodules ├── .jshintrc ├── CHANGELOG.md ├── CONTRIBUTING.md ├── MIT-LICENSE ├── README.md ├── angularD3 ├── directives │ ├── arc.coffee │ ├── area.coffee │ ├── axis.coffee │ ├── bars.coffee │ ├── chart.coffee │ ├── data.coffee │ ├── gradient.coffee │ ├── include.coffee │ ├── line.coffee │ └── pie.coffee ├── index.coffee ├── locale │ ├── ca-ES.js │ ├── de-CH.js │ ├── de-DE.js │ ├── en-CA.js │ ├── en-GB.js │ ├── en-US.js │ ├── es-ES.js │ ├── fi-FI.js │ ├── fr-CA.js │ ├── fr-FR.js │ ├── he-IL.js │ ├── hu-HU.js │ ├── it-IT.js │ ├── ja-JP.js │ ├── ko-KR.js │ ├── mk-MK.js │ ├── nl-NL.js │ ├── pl-PL.js │ ├── pt-BR.js │ ├── ru-RU.js │ ├── sv-SE.js │ └── zh-CN.js └── services │ ├── d3locale.coffee │ └── d3service.coffee ├── app ├── .buildignore ├── .htaccess ├── 404.html ├── data │ ├── data.csv │ └── donutData.csv ├── favicon.ico ├── index.html ├── index.js ├── robots.txt ├── scripts │ ├── app.coffee │ ├── main.coffee │ ├── main_controller.coffee │ └── main_view.html └── styles │ ├── index.scss │ ├── main.scss │ └── theme │ └── default.scss ├── bower.json ├── dist ├── angularD3.js └── angularD3.js.map ├── index.js ├── package.json └── webpack.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .tmp 3 | .sass-cache 4 | app/components 5 | .sublime-* 6 | *.log 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "docs"] 2 | path = docs 3 | url = git@github.com:wealthbar/angular-d3.git 4 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "es5": true, 5 | "esnext": true, 6 | "bitwise": true, 7 | "camelcase": true, 8 | "curly": true, 9 | "eqeqeq": true, 10 | "immed": true, 11 | "indent": 2, 12 | "latedef": true, 13 | "newcap": true, 14 | "noarg": true, 15 | "quotmark": "single", 16 | "regexp": true, 17 | "undef": true, 18 | "unused": true, 19 | "strict": true, 20 | "trailing": true, 21 | "smarttabs": true, 22 | "globals": { 23 | "angular": false 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 0.1.1 2 | ===== 3 | 4 | - Add localization support through D3 5 | - Adds the d3locale service 6 | - Merge fix from PR #37 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Guidelines for Contributing 2 | 3 | ## House Rules 4 | 5 | 1. Respect the indentation (2 spaces) and coding style you see, don't mix 6 | styles 7 | 2. Respect the use of Coffeescript (pull-requests or issues asking to migrate 8 | to Javascript will be roundhouse kicked) 9 | 10 | ## Getting Started 11 | 12 | We use Grunt to build and test Angular-D3 and Bower to manage dependencies. You 13 | can get started by first cloning the repository (fork it if you want to submit 14 | pull-requests). The follow these steps: 15 | 16 | ```sh 17 | # Install Bower and Grunt if you don't have them already 18 | npm install -g grunt-cli 19 | npm install -g bower 20 | 21 | # Install Bower dependencies 22 | bower install 23 | 24 | # List Grunt Tasks 25 | 26 | grunt --help 27 | 28 | # Start Development Server 29 | 30 | grunt server 31 | ``` 32 | 33 | ## Submitting A Pull Request 34 | 35 | We don't have any strict requirements on pull requests at this point. This 36 | policy will probably change as we approach a 1.0 version. For now we welcome 37 | any pull requests, particularly those adding new directives for chart elements 38 | or features. 39 | 40 | And last but not least, thanks for contributing! 41 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 WealthBar Financial Services inc. 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 | # AngularJS-D3 Module 2 | 3 | A set of AngularJS directives that provides a declarative syntax for building 4 | common charts using D3. 5 | 6 | ## Installing 7 | 8 | AngularD3 is available via Bower as `angularD3` 9 | 10 | ``` 11 | bower install angularD3 12 | ``` 13 | 14 | AngularD3 is available via NPM as `angular_d3` 15 | 16 | ``` 17 | npm install angular_d3 18 | ``` 19 | 20 | ## Project Goals 21 | 22 | This provides an AngularJS module called `ad3` which in turn provides a 23 | declarative HTML syntax for using D3 with AngularJS. The syntax has been 24 | inspired in part by [Radian](https://github.com/openbrainsrc/Radian) however 25 | at the time of starting this Radian was not available as an OSS project. 26 | 27 | The goals of AngularD3 are: 28 | 29 | - Provide a simple declarative syntax for common D3 graphs and charts 30 | - An extensible core allowing for almost anything possible D3 to be expressed with a custom directive. You are able to both extend the existing chart visuals as well as create entirely new ones. One example might be adding special elements/labels that have their positions bound to data points based on the chart axes. 31 | - Designed the "Angular Way (tm)" using similar style to extensibility and directive communication used by Angular directives like form and input. AngularD3 provides a `d3Chart` directive which provides `d3ChartController` analagously to `ngFormController` 32 | - 100% stylable via CSS, with some added D3 'sugar' like allowing the use of the built in color scales with pie charts or being able to bind to a color scale from data. 33 | - The ability to create custom directives that can both extend existing chart layouts as well as create new ones. 34 | 35 | The overall goal of this project is to create a basic set of D3 36 | directives that are sufficiently complete for flexible 37 | charts of most common types. To start: Bar, Line, Area, Pie, Arc. Additional 38 | chart elements, can be added either to enhance existing chart types or to create 39 | new ones simply by requiring `d3ChartController`. 40 | 41 | AngularD3 is designed to provide enough flexibility to allow you to extend it with 42 | custom directives to do anything you could conceive of with D3 with no limitations, but 43 | still provide a convenient set of default functionality. Creating most simple graphs 44 | should be built in, while unlimited customization is still possible with relative ease. 45 | 46 | If you have ideas and are interested in lending a hand, please open an issue, 47 | submit a pull request or just ping me 48 | [@chrismnicola](https://twitter.com/chrismnicola). This could be the beginning 49 | of beautiful friendship. 50 | 51 | ## Current Directives 52 | 53 | - d3-chart - Provides the top level directives meant to contain the rest of the 54 | chart declarations. 55 | - d3-data - Provides a declarative way to load data into the current scope 56 | directly from a URL 57 | - d3-axis - Defines an axis and provide it's range and location (top, left, 58 | bottom, right) 59 | - d3-area - Define an area graph 60 | - d3-line - Defines a line graph 61 | - d3-bars - Defines a set of bars for a bar chart 62 | - d3-gradient - Support for dynamically generating SVG gradients with data 63 | - d3-include - Supports including arbitrary SVG with the chart 64 | 65 | The directives are meant to be used to compost charts like so: 66 | 67 | ```html 68 | 69 | 70 |
71 | 72 | 73 | 74 | 75 | 76 | 77 |
78 | ``` 79 | 80 | The `d3-chart` directive will first append `` to 81 | itself and then each inner directives will attach their own elements, using D3, 82 | from there. The `d3ChartController` provides access to its root `` element via 83 | `getChart()` so that child directives can append themselves. 84 | 85 | The `d3-data` directive provides a way of declaratively binding data, but this 86 | is entirely optional and it simply is a convenient way to bind a CSV data from 87 | any url directly to your current scope. 88 | 89 | Documentation will be forthcoming as things develop but for now you will have 90 | to rely on a quick reading of the code. 91 | 92 | ## Try it out 93 | 94 | This project uses NPM and Webpack. To run it clone this repo and run: 95 | 96 | ``` 97 | npm install 98 | npm start 99 | ``` 100 | 101 | ## Building 102 | 103 | You can build a minified `angularD3.js` which will be saved in `/dist` by running 104 | 105 | npm run-script build 106 | 107 | You can also update the docs which will be saved in `/docs` by running 108 | 109 | npm run-script docs 110 | 111 | ## Feature Roadmap 112 | 113 | - [x] Basic chart forms for: Area, Line and Bars 114 | - [x] Supports multiple axis and multiple charts can be stacked 115 | - [x] Dynamically updating charts supporting animations (should be able to 116 | display and track incoming time-series data) 117 | - [x] Data source directives to declaratively specify and load external data 118 | sources and support D3's built in parsers for CSV, TSV, etc. 119 | - [ ] Customizable chart legends 120 | - [ ] Customizable and flexible labels 121 | - [ ] Mouse and touch overlay support 122 | - [ ] Scatter and Bubble plots 123 | - [ ] Bullet charts 124 | - [x] Stacked area charts 125 | 126 | If you have any other ideas for me, or feel like contributing to help add any 127 | of this missing functionality, I encourage you to submit a pull request. 128 | 129 | ## License 130 | 131 | Angular-D3 is free software under the [MIT licence](http://opensource.org/licenses/MIT) and may be redistributed under the terms specified in the MIT-LICENSE file. 132 | -------------------------------------------------------------------------------- /angularD3/directives/arc.coffee: -------------------------------------------------------------------------------- 1 | d3 = require('d3') 2 | 3 | angular.module('ad3').directive 'd3Arc', -> 4 | defaults = -> 5 | x: 0 6 | y: 1 7 | innerRadius: 0 8 | labelRadius: 0 9 | transition: "cubic-in-out" 10 | transitionDuration: 1000 11 | value: 'value' 12 | label: 'label' 13 | 14 | restrict: 'E' 15 | 16 | require: '^d3Chart' 17 | 18 | link: (scope, el, attrs, chartController) -> 19 | options = angular.extend(defaults(), attrs) 20 | 21 | chart = chartController.getChart() 22 | innerRadius = parseFloat(options.innerRadius) 23 | labelRadius = parseFloat(options.labelRadius) 24 | 25 | center = null 26 | arcPath = null 27 | arcLabel = null 28 | redraw = (data) -> 29 | center ||= chartController.getChart().append("g").attr("class", "arc") 30 | arcPath ||= center.append("path") 31 | arcLabel ||= center.append("text") 32 | .attr("class", "arc-label") 33 | .attr("dy", "0.35em") 34 | .style("text-anchor", "middle") 35 | 36 | return unless data? and data.length isnt 0 37 | 38 | radius = Math.min(chartController.innerWidth, chartController.innerHeight)/2 39 | 40 | center.attr("transform", "translate(" + radius + "," + radius + ")") 41 | 42 | arc = d3.svg.arc() 43 | .outerRadius(radius) 44 | .innerRadius(radius * innerRadius) 45 | .startAngle(0) 46 | .endAngle((d) -> d/100 * 2 * Math.PI) 47 | 48 | arcTween = (d) -> 49 | @_current ?= 0 50 | i = d3.interpolate(@_current, d) 51 | @_current = d 52 | (t) -> arc(i(t)) 53 | 54 | labelArc = d3.svg.arc() 55 | .outerRadius(radius * labelRadius) 56 | .innerRadius(radius * labelRadius) 57 | 58 | arcPath.datum(data[options.value]) 59 | .transition() 60 | .ease(options.transition) 61 | .duration(options.transitionDuration) 62 | .attrTween("d", arcTween) 63 | 64 | arcLabel.text(data[options.label]) 65 | 66 | chartController.registerElement(redraw, options.order) 67 | -------------------------------------------------------------------------------- /angularD3/directives/area.coffee: -------------------------------------------------------------------------------- 1 | angular.module('ad3').directive 'd3Area', -> 2 | defaults = -> {} 3 | 4 | restrict: 'E' 5 | require: '^d3Chart' 6 | scope: 7 | columns: '=' 8 | 9 | link: ($scope, $el, $attrs, chartController) -> 10 | # todo: DRY this up in line, area and bar directives 11 | options = angular.extend(defaults(), $attrs) 12 | x = chartController.getScale(options.xscale or options.x) 13 | y = chartController.getScale(options.yscale or options.y) 14 | 15 | if options.vertical 16 | area = d3.svg.area() 17 | .y((d) -> x(d.x)) 18 | .x0(0) 19 | .x1((d) -> y(d.y)) 20 | areaStacked = d3.svg.area() 21 | .y((d) -> x(d.x)) 22 | .x0((d) -> y(d.y0)) 23 | .x1((d) -> y(d.y + d.y0)) 24 | else 25 | area = d3.svg.area() 26 | .x((d) -> x(d.x)) 27 | .y0(-> chartController.innerHeight) 28 | .y1((d) -> y(d.y)) 29 | areaStacked = d3.svg.area() 30 | .x((d) -> x(d.x)) 31 | .y0((d) -> y(d.y0)) 32 | .y1((d) -> y(d.y + d.y0)) 33 | 34 | areaElement = null 35 | redraw = (data) -> 36 | areaElement ||= chartController.getChart().append("g") 37 | .attr("class", "area") 38 | return unless data? and data.length isnt 0 39 | columns = options.y if options.y? 40 | if $scope.columns? 41 | columns = $scope.columns 42 | return unless columns? 43 | if angular.isString columns 44 | columns = columns.split(',').map((c) -> c.trim()) 45 | return if columns.length is 0 46 | 47 | mappedData = for name in columns 48 | name: name 49 | values: for value in data 50 | x: value[options.x] 51 | y: value[name] 52 | stack = d3.layout.stack().values((d) -> d.values) 53 | stack.offset(options.offset) if options.offset? 54 | stackedData = stack(mappedData) 55 | 56 | charts = areaElement.selectAll('path.area').data(stackedData) 57 | charts.enter().append("path") 58 | charts.attr("class", (d) -> "area #{d.name}") 59 | .transition() 60 | .duration(500) 61 | .attr("d", (d,i) -> if i is 0 then area(d.values) else areaStacked(d.values)) 62 | charts.exit() 63 | .attr("d", (d,i) -> if i is 0 then area(d.values) else areaStacked(d.values)) 64 | .remove() 65 | 66 | $scope.$watch 'columns', chartController.redraw, true 67 | chartController.registerElement(redraw, options.order) 68 | -------------------------------------------------------------------------------- /angularD3/directives/axis.coffee: -------------------------------------------------------------------------------- 1 | angular.module('ad3').directive 'd3Axis', ['d3locale', (d3locale) -> 2 | defaults = -> 3 | orientation: 'bottom' 4 | ticks: '5' 5 | extent: false 6 | 7 | priority: 1 8 | restrict: 'E' 9 | require: '^d3Chart' 10 | scope: 11 | customTimeFormat: '=' 12 | filter: '=' 13 | tickValues: '=' 14 | 15 | link: ($scope, $el, $attrs, chartController) -> 16 | options = angular.extend(defaults(), $attrs) 17 | 18 | range = -> 19 | if options.orientation is 'top' or options.orientation is 'bottom' 20 | if options.reverse? 21 | [chartController.innerWidth, 0] 22 | else 23 | [0 ,chartController.innerWidth] 24 | else 25 | if options.reverse? 26 | [0, chartController.innerHeight] 27 | else 28 | [chartController.innerHeight, 0] 29 | 30 | translation = -> 31 | if options.orientation is 'bottom' 32 | "translate(0, #{chartController.innerHeight})" 33 | else if options.orientation is 'top' 34 | "translate(0, 0)" 35 | else if options.orientation is 'left' 36 | "translate(0, 0)" 37 | else if options.orientation is 'right' 38 | "translate(#{chartController.innerWidth}, 0)" 39 | 40 | if options.scale is 'time' 41 | scale = d3.time.scale() 42 | else if options.scale 43 | scale = d3.scale[options.scale]() 44 | else 45 | scale = d3.scale.linear() 46 | 47 | getAxis = -> 48 | axis = d3.svg.axis().scale(scale).orient(options.orientation) 49 | if options.ticks 50 | axis.ticks(options.ticks) 51 | if options.timeScale 52 | axis.ticks(d3.time[options.timeScale], options.timeInterval) 53 | if $scope.tickValues 54 | axis.tickValues($scope.tickValues) 55 | if options.tickSize 56 | tickSize = options.tickSize.split(',') 57 | axis.innerTickSize(tickSize[0]) 58 | axis.outerTickSize(tickSize[1]) 59 | if $scope.customTimeFormat? 60 | # We copy this because D3 is bad and mutates the time format. 61 | # See: https://github.com/mbostock/d3/issues/1769 62 | format = d3.time.format.multi(angular.copy($scope.customTimeFormat)) 63 | axis.tickFormat((value) -> format(new Date(value))) 64 | if options.timeFormat? 65 | format = d3.time.format(options.timeFormat) 66 | axis.tickFormat((value) -> format(new Date(value))) 67 | else if options.format? 68 | format = d3.format(options.format) 69 | axis.tickFormat(format) 70 | axis 71 | 72 | positionLabel = (label) -> 73 | if options.orientation is 'bottom' 74 | label.attr("x", "#{chartController.innerWidth / 2}") 75 | .attr("dy", "#{chartController.margin.bottom}") 76 | .attr("style", "text-anchor: middle;") 77 | else if options.orientation is 'top' 78 | label.attr("x", "#{chartController.innerWidth / 2}") 79 | .attr("dy", "#{-chartController.margin.top}") 80 | .attr("style", "text-anchor: middle;") 81 | else if options.orientation is 'left' 82 | label.attr("x", "-#{chartController.innerHeight / 2}") 83 | .attr("dy", "#{-chartController.margin.left + 18}") 84 | .attr("style", "text-anchor: middle;") 85 | .attr("transform", "rotate(-90)") 86 | else if options.orientation is 'right' 87 | label.attr("x", "#{chartController.innerHeight / 2}") 88 | .attr("dy", "#{-chartController.margin.right + 18}") 89 | .attr("style", "text-anchor: middle;") 90 | .attr("transform", "rotate(90)") 91 | 92 | drawGrid = (grid, axis) -> 93 | if options.orientation is 'bottom' 94 | grid.call(axis.tickSize(chartController.innerHeight, 0, 0) 95 | .tickFormat('') 96 | ) 97 | else if options.orientation is 'top' 98 | grid.attr("transform", "translate(0, #{chartController.innerHeight})") 99 | .call(axis.tickSize(chartController.innerHeight, 0, 0) 100 | .tickFormat('') 101 | ) 102 | else if options.orientation is 'left' 103 | grid.attr("transform", "translate(#{chartController.innerWidth}, 0)") 104 | .call(axis.tickSize(chartController.innerWidth, 0, 0) 105 | .tickFormat('') 106 | ) 107 | else if options.orientation is 'right' 108 | grid.call(axis.tickSize(chartController.innerWidth, 0, 0) 109 | .tickFormat('') 110 | ) 111 | 112 | adjustTickLabels = (g) -> 113 | tickLabels = g.selectAll('.tick text') 114 | if options.tickDy 115 | tickLabels.attr('dy', options.tickDy) 116 | if options.tickDx 117 | tickLabels.attr('dx', options.tickDx) 118 | if options.tickAnchor 119 | tickLabels.style('text-anchor', options.tickAnchor) 120 | lastTickLabels = d3.select(tickLabels[0].slice(-1)[0]) 121 | if options.lastTickDy 122 | lastTickLabels.attr('dy', options.lastTickDy) 123 | if options.lastTickDx 124 | lastTickLabels.attr('dx', options.lastTickDx) 125 | if options.lastTickAnchor 126 | lastTickLabels.style('text-anchor', options.lastTickAnchor) 127 | firstTickLabels = d3.select(tickLabels[0][0]) 128 | if options.firstTickDy 129 | firstTickLabels.attr('dy', options.firstTickDy) 130 | if options.firstTickDx 131 | firstTickLabels.attr('dx', options.firstTickDx) 132 | if options.listTickAnchor 133 | firstTickLabels.style('text-anchor', options.firstTickAnchor) 134 | 135 | axisElement = null 136 | grid = null 137 | label = null 138 | 139 | redraw = (data) -> 140 | return unless data? and data.length isnt 0 141 | # Append x-axis to chart 142 | axisElement ||= chartController.getChart().append("g") 143 | .attr("class", "axis axis-#{options.orientation} axis-#{options.name}") 144 | .attr("transform", translation()) 145 | if options.label 146 | label ||= axisElement.append("text").attr("class", "axis-label").text(options.label) 147 | if options.grid 148 | grid ||= chartController.getChart().append("g") 149 | .attr("class", "axis-grid axis-grid-#{options.name}") 150 | 151 | axis = getAxis() 152 | positionLabel(label.transition().duration(500)) if label 153 | axisElement.transition().duration(500) 154 | .attr("transform", translation()) 155 | .call(axis) 156 | .selectAll('tick text') 157 | .tween("attr.dx", null) 158 | .tween("attr.dy", null) 159 | .tween("style.text-anchor", null) 160 | 161 | drawGrid(grid.transition().duration(500), axis) if grid? 162 | tickLabels = axisElement.selectAll('.tick text') 163 | axisElement.call(adjustTickLabels) 164 | 165 | updateScale = (data) -> 166 | return unless data? and data.length isnt 0 167 | scale.range(range()) 168 | if options.domain 169 | data 170 | if $scope.filter 171 | domainValues = $scope.filter(data) 172 | else 173 | domainValues = (datum[options.name] for datum in data) 174 | if options.extent 175 | scale.domain d3.extent domainValues 176 | else 177 | scale.domain [0, d3.max domainValues] 178 | 179 | chartController.addScale(options.name, scale, updateScale) 180 | chartController.registerElement(redraw, options.order) 181 | $scope.$watchCollection 'tickValues', chartController.redraw 182 | $scope.$watchCollection 'customTimeFormat', chartController.redraw 183 | $scope.$watch 'filter', chartController.redraw 184 | $scope.$watch 'tickValues', chartController.redraw 185 | ] 186 | -------------------------------------------------------------------------------- /angularD3/directives/bars.coffee: -------------------------------------------------------------------------------- 1 | angular.module('ad3').directive 'd3Bars', -> 2 | defaults = -> 3 | x: 0 4 | y: 1 5 | width: 15 6 | 7 | restrict: 'E' 8 | 9 | require: '^d3Chart' 10 | 11 | link: (scope, el, attrs, chartController) -> 12 | options = angular.extend(defaults(), attrs) 13 | x = chartController.getScale(options.xscale or options.x) 14 | y = chartController.getScale(options.yscale or options.y) 15 | 16 | chart = chartController.getChart() 17 | height = chartController.innerHeight 18 | width = options.width 19 | 20 | barsElements = null 21 | redraw = (data) -> 22 | barsElements ||= chartController.getChart().append("g") 23 | .attr("class", "bars") 24 | return unless data? and data.length isnt 0 25 | bars = barsElements.selectAll("rect.bar").data(data) 26 | bars.exit().transition().duration(500) 27 | .attr("y", -> chartController.innerHeight) 28 | .attr("height", 0) 29 | .remove() 30 | bars.transition().duration(500) 31 | .attr("x", (d) -> x(d[options.x]) - width/2) 32 | .attr("y", (d) -> y(d[options.y])) 33 | .attr("height", (d) -> chartController.innerHeight - y(d[options.y])) 34 | .attr("width", width) 35 | bars.enter() 36 | .append("rect") 37 | .attr("class", (d,i) -> "bar bar-#{i}") 38 | .attr("x", (d) -> x(d[options.x]) - width/2) 39 | .attr("width", width) 40 | .attr("y", -> chartController.innerHeight) 41 | .attr("height", 0) 42 | .transition().duration(500) 43 | .attr("y", (d) -> y(d[options.y])) 44 | .attr("height", (d) -> chartController.innerHeight - y(d[options.y])) 45 | 46 | chartController.registerElement(redraw, options.order) 47 | -------------------------------------------------------------------------------- /angularD3/directives/chart.coffee: -------------------------------------------------------------------------------- 1 | angular.module('ad3').directive 'd3Chart', -> 2 | restrict: 'EA' 3 | scope: 4 | margin: '=' 5 | data: '=' 6 | 7 | controller: ['$scope', '$element', '$attrs', '$window', '$timeout', 8 | ($scope, $el, $attrs, $window, $timeout) -> 9 | scales = $scope.scales = {} 10 | elements = $scope.elements = [] 11 | 12 | @margin = $scope.margin or { top: 10, right: 10, bottom: 10, left: 10 } 13 | svg = d3.select($el[0]).append('svg').attr('class', "d3") 14 | .attr("width", "100%") 15 | .attr("height", "100%") 16 | 17 | # Used to calculated widths based on SVG margins 18 | width = -> $el[0].offsetWidth 19 | height = -> $el[0].offsetHeight 20 | 21 | chart = svg.append("g") 22 | .attr("transform", "translate(" + @margin.left + "," + @margin.top + ")") 23 | 24 | @getSvg = -> svg 25 | @getChart = -> chart 26 | @addScale = (name, scale, update) -> scales[name] = { scale: scale, update: update } 27 | @getScale = (name) -> scales[name].scale 28 | @registerElement = (el, order = 0) -> elements.push { redraw: el, order: Number(order) } 29 | 30 | updateSize = => 31 | if @width != width() or @height != height() 32 | @width = width() 33 | @height = height() 34 | @innerWidth = @width - @margin.left - @margin.right 35 | @innerHeight = @height - @margin.top - @margin.bottom 36 | # Redraw if the chart size has changed 37 | @redraw() 38 | 39 | sortOrder = (a, b) -> a.order - b.order 40 | debounce = null 41 | @redraw = => 42 | # We don't bother to redraw if the chart isn't visible 43 | return if debounce or @width is 0 or @height is 0 44 | debounce = $timeout => 45 | debounce = null 46 | data = $scope.data 47 | for name, scale of scales 48 | scale.update(data) 49 | for element in elements.sort(sortOrder) 50 | element.redraw(data) 51 | , $attrs.updateInterval or 200 52 | 53 | $window.addEventListener 'resize', updateSize 54 | 55 | if $attrs.watch is 'deep' 56 | $scope.$watch 'data', @redraw, true 57 | else 58 | $scope.$watch 'data', @redraw 59 | 60 | # We check the size on all scope events since scope can affect chart 61 | # visibility and if the chart area is resized while not visible it won't 62 | # update. 63 | $scope.$watch updateSize 64 | 65 | updateSize() 66 | return 67 | ] 68 | -------------------------------------------------------------------------------- /angularD3/directives/data.coffee: -------------------------------------------------------------------------------- 1 | angular.module('ad3').directive 'd3Data',['d3Service', (d3) -> 2 | restrict: 'E' 3 | scope: 4 | accessor: '=' 5 | callback: '=' 6 | data: '=' 7 | link: ($scope, $el, $attrs) -> 8 | src = $attrs.src 9 | d3.csv(src, $scope.accessor, $scope.callback).then (rows) -> 10 | $scope.data = rows 11 | , -> throw('Error loading CSV via D3') 12 | ] 13 | -------------------------------------------------------------------------------- /angularD3/directives/gradient.coffee: -------------------------------------------------------------------------------- 1 | angular.module('ad3').directive 'd3Gradient', -> 2 | defaults = { transition: 500 } 3 | 4 | restrict: 'E' 5 | require: '^d3Chart' 6 | 7 | link: ($scope, $el, $attrs, chartController) -> 8 | svg = chartController.getSvg() 9 | 10 | gradient = svg.insert("defs", 'g') 11 | .append("linearGradient") 12 | .attr("id", $attrs.ref) 13 | 14 | ['x1', 'x2', 'y1', 'y2'].forEach (attr) -> 15 | $attrs.$observe attr, (val) -> gradient.attr(attr, val) 16 | 17 | transition = defaults.transition 18 | $attrs.$observe 'transition', (val) -> transition = val if val? 19 | 20 | $scope.$watch $attrs.stops, (stops) -> 21 | return unless stops? 22 | stops = gradient.selectAll('stop').data(stops) 23 | stops.enter().append('stop') 24 | stops.attr('offset', (d) -> d.offset) 25 | .attr('stop-color', (d) -> d.color) 26 | .attr('stop-opacity', (d) -> if d.opacity? then d.opacity else 1) 27 | stops.exit().remove() 28 | -------------------------------------------------------------------------------- /angularD3/directives/include.coffee: -------------------------------------------------------------------------------- 1 | # d3-include 2 | # 3 | # Allows arbitrary SVG content to be injected into the chart 4 | # 5 | # Todo: Consider making this work more like ng-include and allowing it to fetch 6 | # the SVG content from view templates. 7 | 8 | angular.module('ad3').directive 'd3Include', -> 9 | restrict: 'E' 10 | require: '^d3Chart' 11 | link: ($scope, $el, $attrs, chartController) -> 12 | chart = chartController.getChart() 13 | includes = chart.append('g').attr('class', 'includes') 14 | includes.html($el.html()) 15 | -------------------------------------------------------------------------------- /angularD3/directives/line.coffee: -------------------------------------------------------------------------------- 1 | angular.module('ad3').directive 'd3Line', -> 2 | defaults = -> 3 | x: 0 4 | y: 1 5 | 6 | restrict: 'E' 7 | 8 | require: '^d3Chart' 9 | 10 | link: (scope, el, attrs, chartController) -> 11 | options = angular.extend(defaults(), attrs) 12 | x = chartController.getScale(options.xscale or options.x) 13 | y = chartController.getScale(options.yscale or options.y) 14 | 15 | line = d3.svg.line() 16 | .x((d) -> x(d[options.x])) 17 | .y((d) -> y(d[options.y])) 18 | 19 | linePath = null 20 | redraw = (data) -> 21 | linePath ||= chartController.getChart().append("path") 22 | .attr("class", "line line-#{options.name or options.y}") 23 | .style("fill", "none") 24 | .style("stroke", options.stroke) 25 | 26 | return unless data? and data.length isnt 0 27 | linePath.datum(data) 28 | .transition() 29 | .duration(500) 30 | .attr("d", line) 31 | 32 | chartController.registerElement(redraw, options.order) 33 | -------------------------------------------------------------------------------- /angularD3/directives/pie.coffee: -------------------------------------------------------------------------------- 1 | angular.module('ad3').directive 'd3Pie', -> 2 | defaults = -> 3 | x: 0 4 | y: 1 5 | innerRadius: 0 6 | labelRadius: 0.7 7 | transition: "cubic-in-out" 8 | transitionDuration: 800 9 | minOffset: 12 10 | value: 'value' 11 | 12 | restrict: 'E' 13 | 14 | require: '^d3Chart' 15 | 16 | link: (scope, el, attrs, chartController) -> 17 | options = angular.extend(defaults(), attrs) 18 | 19 | chart = chartController.getChart() 20 | innerRadius = parseFloat(options.innerRadius) 21 | labelRadius = parseFloat(options.labelRadius) 22 | 23 | if attrs.colors 24 | colorScale = switch attrs.colors 25 | when 'category20' 26 | d3.scale.category20() 27 | when 'category20b' 28 | d3.scale.category20b() 29 | when 'category20c' 30 | d3.scale.category20c() 31 | 32 | pie = d3.layout.pie().sort(null) 33 | .value((d) -> d[options.value]) 34 | 35 | _current = null 36 | 37 | center = null 38 | redraw = (data) -> 39 | center ||= chartController.getChart().append("g").attr("class", "pie") 40 | 41 | return unless data? and data.length isnt 0 42 | 43 | radius = Math.min(chartController.innerWidth, chartController.innerHeight)/2 44 | 45 | center.attr("transform", "translate(" + radius + "," + radius + ")") 46 | 47 | arc = d3.svg.arc() 48 | .outerRadius(radius) 49 | .innerRadius(radius * innerRadius) 50 | 51 | arcTween = (a) -> 52 | i = d3.interpolate(@_current, a) 53 | @_current = i(0) 54 | (t) -> arc(i(t)) 55 | 56 | labelArc = d3.svg.arc() 57 | .outerRadius(radius * labelRadius) 58 | .innerRadius(radius * labelRadius) 59 | 60 | slice = center.selectAll(".pie").data(pie(data)) 61 | 62 | slice.enter().append("path") 63 | .attr("class", (d,i) -> "pie pie-#{i}") 64 | .attr("d", arc) 65 | .each((d) -> @_current = d) 66 | 67 | slice.style('fill', (d,i) -> 68 | if colorScale then colorScale(i) else d[attrs.color]) if attrs.colors 69 | 70 | slice.exit().remove() 71 | 72 | slice.transition() 73 | .ease(options.transition) 74 | .duration(options.transitionDuration) 75 | .attrTween("d", arcTween) 76 | 77 | if options.label 78 | prevbb = null 79 | padding = +options.minOffset 80 | getPosition = (d, i) -> 81 | position = labelArc.centroid(d) 82 | 83 | if options.avoidCollisions 84 | # Basic collision adjustment, doesn't seem to quite work all the time. 85 | # Adapted from: http://stackoverflow.com/a/20645255/235243 86 | 87 | relativePosition = [position[0], position[1]] 88 | if @_position 89 | relativePosition[0] -= @_position[0] 90 | relativePosition[1] -= @_position[1] 91 | 92 | # Translate and pad the bounding rectangle for collision detection 93 | thisbb = _.transform @getBoundingClientRect(), (r, v, k) -> 94 | switch k 95 | when 'left' 96 | r[k] = v - padding + relativePosition[0] 97 | when 'top' 98 | r[k] = v - padding + relativePosition[1] 99 | when 'right' 100 | r[k] = v + padding + relativePosition[0] 101 | when 'bottom' 102 | r[k] = v + padding + relativePosition[1] 103 | 104 | if prevbb and !( 105 | thisbb.right < prevbb.left || 106 | thisbb.left > prevbb.right || 107 | thisbb.bottom < prevbb.top || 108 | thisbb.top > prevbb.bottom) 109 | ctx = thisbb.left + (thisbb.right - thisbb.left)/2 110 | cty = thisbb.top + (thisbb.bottom - thisbb.top)/2 111 | cpx = prevbb.left + (prevbb.right - prevbb.left)/2 112 | cpy = prevbb.top + (prevbb.bottom - prevbb.top)/2 113 | offset = Math.sqrt(Math.pow(ctx - cpx, 2) + Math.pow(cty - cpy, 2))/2 114 | offsetArc = d3.svg.arc() 115 | .outerRadius(radius * labelRadius + offset) 116 | .innerRadius(radius * labelRadius + offset) 117 | position = offsetArc.centroid(d) 118 | 119 | @_position = position 120 | prevbb = thisbb 121 | 122 | "translate(#{position})" 123 | 124 | label = center.selectAll("text").data(pie(data)) 125 | 126 | label.enter().append("text") 127 | .style("text-anchor", "middle") 128 | .attr("class", (d,i) -> "pie-label pie-label-#{i}") 129 | 130 | label.exit().remove() 131 | 132 | label.text((d,i) -> data[i][options.label]) 133 | 134 | label.transition() 135 | .ease(options.transition) 136 | .duration(options.transitionDuration) 137 | .attr("transform", getPosition) 138 | 139 | chartController.registerElement(redraw, options.order) 140 | -------------------------------------------------------------------------------- /angularD3/index.coffee: -------------------------------------------------------------------------------- 1 | angular = require('angular') 2 | 3 | angular.module('ad3', []) 4 | 5 | require('./services/d3service') 6 | require('./services/d3locale') 7 | require('./directives/arc') 8 | require('./directives/area') 9 | require('./directives/axis') 10 | require('./directives/bars') 11 | require('./directives/chart') 12 | require('./directives/data') 13 | require('./directives/gradient') 14 | require('./directives/include') 15 | require('./directives/line') 16 | require('./directives/pie') 17 | -------------------------------------------------------------------------------- /angularD3/locale/ca-ES.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: ".", 4 | grouping: [3], 5 | currency: ["", " €"], 6 | dateTime: "%A, %e de %B de %Y, %X", 7 | date: "%d/%m/%Y", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], 10 | days: ["diumenge", "dilluns", "dimarts", "dimecres", "dijous", "divendres", "dissabte"], 11 | shortDays: ["dg.", "dl.", "dt.", "dc.", "dj.", "dv.", "ds."], 12 | months: ["gener", "febrer", "març", "abril", "maig", "juny", "juliol", "agost", "setembre", "octubre", "novembre", "desembre"], 13 | shortMonths: ["gen.", "febr.", "març", "abr.", "maig", "juny", "jul.", "ag.", "set.", "oct.", "nov.", "des."] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/de-CH.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: "'", 4 | grouping: [3], 5 | currency: ["", " CHF"], 6 | dateTime: "%A, der %e. %B %Y, %X", 7 | date: "%d.%m.%Y", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], // unused 10 | days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"], 11 | shortDays: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"], 12 | months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], 13 | shortMonths: ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/de-DE.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: ".", 4 | grouping: [3], 5 | currency: ["", " €"], 6 | dateTime: "%A, der %e. %B %Y, %X", 7 | date: "%d.%m.%Y", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], // unused 10 | days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"], 11 | shortDays: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"], 12 | months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], 13 | shortMonths: ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/en-CA.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ".", 3 | thousands: ",", 4 | grouping: [3], 5 | currency: ["$", ""], 6 | dateTime: "%a %b %e %X %Y", 7 | date: "%Y-%m-%d", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], 10 | days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], 11 | shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], 12 | months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], 13 | shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/en-GB.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ".", 3 | thousands: ",", 4 | grouping: [3], 5 | currency: ["£", ""], 6 | dateTime: "%a %e %b %X %Y", 7 | date: "%d/%m/%Y", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], 10 | days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], 11 | shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], 12 | months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], 13 | shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/en-US.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ".", 3 | thousands: ",", 4 | grouping: [3], 5 | currency: ["$", ""], 6 | dateTime: "%a %b %e %X %Y", 7 | date: "%m/%d/%Y", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], 10 | days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], 11 | shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], 12 | months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], 13 | shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/es-ES.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: ".", 4 | grouping: [3], 5 | currency: ["", " €"], 6 | dateTime: "%A, %e de %B de %Y, %X", 7 | date: "%d/%m/%Y", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], 10 | days: ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"], 11 | shortDays: ["dom", "lun", "mar", "mié", "jue", "vie", "sáb"], 12 | months: ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"], 13 | shortMonths: ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/fi-FI.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: "\xa0", 4 | grouping: [3], 5 | currency: ["", "\xa0€"], 6 | dateTime: "%A, %-d. %Bta %Y klo %X", 7 | date: "%-d.%-m.%Y", 8 | time: "%H:%M:%S", 9 | periods: ["a.m.", "p.m."], 10 | days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai"], 11 | shortDays: ["Su", "Ma", "Ti", "Ke", "To", "Pe", "La"], 12 | months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"], 13 | shortMonths: ["Tammi", "Helmi", "Maalis", "Huhti", "Touko", "Kesä", "Heinä", "Elo", "Syys", "Loka", "Marras", "Joulu"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/fr-CA.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: "\xa0", 4 | grouping: [3], 5 | currency: ["", " $"], 6 | dateTime: "%a %e %b %Y %X", 7 | date: "%Y-%m-%d", 8 | time: "%H:%M:%S", 9 | periods: ["", ""], 10 | days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"], 11 | shortDays: ["dim", "lun", "mar", "mer", "jeu", "ven", "sam"], 12 | months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"], 13 | shortMonths: ["jan", "fév", "mar", "avr", "mai", "jui", "jul", "aoû", "sep", "oct", "nov", "déc"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/fr-FR.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: ".", 4 | grouping: [3], 5 | currency: ["", " €"], 6 | dateTime: "%A, le %e %B %Y, %X", 7 | date: "%d/%m/%Y", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], // unused 10 | days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"], 11 | shortDays: ["dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."], 12 | months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"], 13 | shortMonths: ["janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc."] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/he-IL.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ".", 3 | thousands: ",", 4 | grouping: [3], 5 | currency: ["₪", ""], 6 | dateTime: "%A, %e ב%B %Y %X", 7 | date: "%d.%m.%Y", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], 10 | days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת"], 11 | shortDays: ["א׳", "ב׳", "ג׳", "ד׳", "ה׳", "ו׳", "ש׳"], 12 | months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"], 13 | shortMonths: ["ינו׳", "פבר׳", "מרץ", "אפר׳", "מאי", "יוני", "יולי", "אוג׳", "ספט׳", "אוק׳", "נוב׳", "דצמ׳"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/hu-HU.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: "\xa0", 4 | grouping: [3], 5 | currency: ["", "\xa0Ft"], 6 | dateTime: "%Y. %B %-e., %A %X", 7 | date: "%Y. %m. %d.", 8 | time: "%H:%M:%S", 9 | periods: ["de.", "du."], // unused 10 | days: ["vasárnap", "hétfő", "kedd", "szerda", "csütörtök", "péntek", "szombat"], 11 | shortDays: ["V", "H", "K", "Sze", "Cs", "P", "Szo"], 12 | months: ["január", "február", "március", "április", "május", "június", "július", "augusztus", "szeptember", "október", "november", "december"], 13 | shortMonths: ["jan.", "feb.", "már.", "ápr.", "máj.", "jún.", "júl.", "aug.", "szept.", "okt.", "nov.", "dec."] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/it-IT.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: ".", 4 | grouping: [3], 5 | currency: ["€", ""], 6 | dateTime: "%A %e %B %Y, %X", 7 | date: "%d/%m/%Y", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], // unused 10 | days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"], 11 | shortDays: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"], 12 | months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"], 13 | shortMonths: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/ja-JP.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ".", 3 | thousands: ",", 4 | grouping: [3], 5 | currency: ["", "円"], 6 | dateTime: "%Y %b %e %a %X", 7 | date: "%Y/%m/%d", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], 10 | days: ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"], 11 | shortDays: ["日", "月", "火", "水", "木", "金", "土"], 12 | months: ["睦月", "如月", "弥生", "卯月", "皐月", "水無月", "文月", "葉月", "長月", "神無月", "霜月", "師走"], 13 | shortMonths: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/ko-KR.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ".", 3 | thousands: ",", 4 | grouping: [3], 5 | currency: ["₩", ""], 6 | dateTime: "%Y/%m/%d %a %X", 7 | date: "%Y/%m/%d", 8 | time: "%H:%M:%S", 9 | periods: ["오전", "오후"], 10 | days: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"], 11 | shortDays: ["일", "월", "화", "수", "목", "금", "토"], 12 | months: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"], 13 | shortMonths: ["1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/mk-MK.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: ".", 4 | grouping: [3], 5 | currency: ["", " ден."], 6 | dateTime: "%A, %e %B %Y г. %X", 7 | date: "%d.%m.%Y", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], 10 | days: ["недела", "понеделник", "вторник", "среда", "четврток", "петок", "сабота"], 11 | shortDays: ["нед", "пон", "вто", "сре", "чет", "пет", "саб"], 12 | months: ["јануари", "февруари", "март", "април", "мај", "јуни", "јули", "август", "септември", "октомври", "ноември", "декември"], 13 | shortMonths: ["јан", "фев", "мар", "апр", "мај", "јун", "јул", "авг", "сеп", "окт", "ное", "дек"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/nl-NL.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: ".", 4 | grouping: [3], 5 | currency: ["€ ", ""], 6 | dateTime: "%a %e %B %Y %T", 7 | date: "%d-%m-%Y", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], // unused 10 | days: ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"], 11 | shortDays: ["zo", "ma", "di", "wo", "do", "vr", "za"], 12 | months: ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"], 13 | shortMonths: ["jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/pl-PL.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: ".", 4 | grouping: [3], 5 | currency: ["", "zł"], 6 | dateTime: "%A, %e %B %Y, %X", 7 | date: "%d/%m/%Y", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], // unused 10 | days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"], 11 | shortDays: ["Niedz.", "Pon.", "Wt.", "Śr.", "Czw.", "Pt.", "Sob."], 12 | months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"], 13 | shortMonths: ["Stycz.", "Luty", "Marz.", "Kwie.", "Maj", "Czerw.", "Lipc.", "Sierp.", "Wrz.", "Paźdz.", "Listop.", "Grudz."]/* In Polish language abbraviated months are not commonly used so there is a dispute about the proper abbraviations. */ 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/pt-BR.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ',', 3 | thousands: '.', 4 | grouping: [3], 5 | currency: ['R$', ''], 6 | dateTime: '%A, %e de %B de %Y. %X', 7 | date: '%d/%m/%Y', 8 | time: '%H:%M:%S', 9 | periods: ['AM', 'PM'], 10 | days: ['Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado'], 11 | shortDays: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'], 12 | months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'], 13 | shortMonths: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/ru-RU.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: "\xa0", 4 | grouping: [3], 5 | currency: ["", " руб."], 6 | dateTime: "%A, %e %B %Y г. %X", 7 | date: "%d.%m.%Y", 8 | time: "%H:%M:%S", 9 | periods: ["AM", "PM"], 10 | days: ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"], 11 | shortDays: ["вс", "пн", "вт", "ср", "чт", "пт", "сб"], 12 | months: ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"], 13 | shortMonths: ["янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/sv-SE.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ",", 3 | thousands: "\xa0", 4 | grouping: [3], 5 | currency: ["", "SEK"], 6 | dateTime: "%A den %d %B %Y %X", 7 | date: "%Y-%m-%d", 8 | time: "%H:%M:%S", 9 | periods: ["fm", "em"], 10 | days: ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag"], 11 | shortDays: ["Sön", "Mån", "Tis", "Ons", "Tor", "Fre", "Lör"], 12 | months: ["Januari", "Februari", "Mars", "April", "Maj", "Juni", "Juli", "Augusti", "September", "Oktober", "November", "December"], 13 | shortMonths: ["Jan", "Feb", "Mar", "Apr", "Maj", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/locale/zh-CN.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | decimal: ".", 3 | thousands: ",", 4 | grouping: [3], 5 | currency: ["¥", ""], 6 | dateTime: "%a %b %e %X %Y", 7 | date: "%Y/%-m/%-d", 8 | time: "%H:%M:%S", 9 | periods: ["上午", "下午"], 10 | days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"], 11 | shortDays: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"], 12 | months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], 13 | shortMonths: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"] 14 | }; 15 | -------------------------------------------------------------------------------- /angularD3/services/d3locale.coffee: -------------------------------------------------------------------------------- 1 | d3 = require('d3') 2 | 3 | # d3Locale 4 | # 5 | # Usage 6 | # module.config(['d3localeProvider', (d3localeProvider) -> 7 | # d3localeProvider.setLocales({ 8 | # "en-us": require('angularD3/locale/en-US'), 9 | # "fr-ca": require('angularD3/locale/fr-CA'), 10 | # "zh-cn": require('angularD3/locale/zh-CN'), 11 | # }) 12 | #]).run(['d3locale', (d3locale) -> 13 | # d3locale.setLang('en-us') 14 | # ]) 15 | 16 | angular.module('ad3').provider 'd3locale', -> 17 | localeDefinitions = {} 18 | 19 | @setLocales = (definitions) -> 20 | localeDefinitions = definitions 21 | 22 | @$get = -> 23 | updateLocale = (locale) -> 24 | d3.format = locale.numberFormat 25 | d3.time.format = locale.timeFormat 26 | 27 | return { 28 | setLang: (lang) -> 29 | try 30 | locale = d3.locale(localeDefinitions[lang.toLowerCase()]) 31 | updateLocale(locale) 32 | catch err 33 | throw "d3locale error: '#{lang}' is a locale that either does not exist, or has not been loaded properly." 34 | 35 | setLocale: (locale) -> 36 | updateLocale(d3.locale(locale)) 37 | } 38 | 39 | @ 40 | -------------------------------------------------------------------------------- /angularD3/services/d3service.coffee: -------------------------------------------------------------------------------- 1 | d3 = require('d3') 2 | 3 | angular.module('ad3').provider 'd3Service', () -> 4 | defaults = @defaults = {} 5 | 6 | @$get = ['$cacheFactory', '$rootScope', '$q', ($cacheFactory, $rootScope, $q) -> 7 | cache = defaults.cache or $cacheFactory('d3Service') 8 | 9 | csv: (src, accessor, callback) -> 10 | deferred = $q.defer() 11 | cached = cache.get(src) 12 | if cached 13 | callback(rows) if callback 14 | deferred.resolve(cached) 15 | d3.csv src, accessor, (rows) -> 16 | $rootScope.$apply -> 17 | callback(rows) if callback 18 | if rows 19 | cache.put(src, rows) 20 | deferred.resolve(rows) 21 | else 22 | deferred.reject() 23 | return deferred.promise 24 | ] 25 | 26 | @ 27 | -------------------------------------------------------------------------------- /app/.buildignore: -------------------------------------------------------------------------------- 1 | *.coffee -------------------------------------------------------------------------------- /app/.htaccess: -------------------------------------------------------------------------------- 1 | # Apache configuration file 2 | # httpd.apache.org/docs/2.2/mod/quickreference.html 3 | 4 | # Note .htaccess files are an overhead, this logic should be in your Apache 5 | # config if possible: httpd.apache.org/docs/2.2/howto/htaccess.html 6 | 7 | # Techniques in here adapted from all over, including: 8 | # Kroc Camen: camendesign.com/.htaccess 9 | # perishablepress.com/press/2006/01/10/stupid-htaccess-tricks/ 10 | # Sample .htaccess file of CMS MODx: modxcms.com 11 | 12 | 13 | # ---------------------------------------------------------------------- 14 | # Better website experience for IE users 15 | # ---------------------------------------------------------------------- 16 | 17 | # Force the latest IE version, in various cases when it may fall back to IE7 mode 18 | # github.com/rails/rails/commit/123eb25#commitcomment-118920 19 | # Use ChromeFrame if it's installed for a better experience for the poor IE folk 20 | 21 | 22 | Header set X-UA-Compatible "IE=Edge,chrome=1" 23 | # mod_headers can't match by content-type, but we don't want to send this header on *everything*... 24 | 25 | Header unset X-UA-Compatible 26 | 27 | 28 | 29 | 30 | # ---------------------------------------------------------------------- 31 | # Cross-domain AJAX requests 32 | # ---------------------------------------------------------------------- 33 | 34 | # Serve cross-domain Ajax requests, disabled by default. 35 | # enable-cors.org 36 | # code.google.com/p/html5security/wiki/CrossOriginRequestSecurity 37 | 38 | # 39 | # Header set Access-Control-Allow-Origin "*" 40 | # 41 | 42 | 43 | # ---------------------------------------------------------------------- 44 | # CORS-enabled images (@crossorigin) 45 | # ---------------------------------------------------------------------- 46 | 47 | # Send CORS headers if browsers request them; enabled by default for images. 48 | # developer.mozilla.org/en/CORS_Enabled_Image 49 | # blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html 50 | # hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/ 51 | # wiki.mozilla.org/Security/Reviews/crossoriginAttribute 52 | 53 | 54 | 55 | # mod_headers, y u no match by Content-Type?! 56 | 57 | SetEnvIf Origin ":" IS_CORS 58 | Header set Access-Control-Allow-Origin "*" env=IS_CORS 59 | 60 | 61 | 62 | 63 | 64 | # ---------------------------------------------------------------------- 65 | # Webfont access 66 | # ---------------------------------------------------------------------- 67 | 68 | # Allow access from all domains for webfonts. 69 | # Alternatively you could only whitelist your 70 | # subdomains like "subdomain.example.com". 71 | 72 | 73 | 74 | Header set Access-Control-Allow-Origin "*" 75 | 76 | 77 | 78 | 79 | # ---------------------------------------------------------------------- 80 | # Proper MIME type for all files 81 | # ---------------------------------------------------------------------- 82 | 83 | # JavaScript 84 | # Normalize to standard type (it's sniffed in IE anyways) 85 | # tools.ietf.org/html/rfc4329#section-7.2 86 | AddType application/javascript js jsonp 87 | AddType application/json json 88 | 89 | # Audio 90 | AddType audio/ogg oga ogg 91 | AddType audio/mp4 m4a f4a f4b 92 | 93 | # Video 94 | AddType video/ogg ogv 95 | AddType video/mp4 mp4 m4v f4v f4p 96 | AddType video/webm webm 97 | AddType video/x-flv flv 98 | 99 | # SVG 100 | # Required for svg webfonts on iPad 101 | # twitter.com/FontSquirrel/status/14855840545 102 | AddType image/svg+xml svg svgz 103 | AddEncoding gzip svgz 104 | 105 | # Webfonts 106 | AddType application/vnd.ms-fontobject eot 107 | AddType application/x-font-ttf ttf ttc 108 | AddType font/opentype otf 109 | AddType application/x-font-woff woff 110 | 111 | # Assorted types 112 | AddType image/x-icon ico 113 | AddType image/webp webp 114 | AddType text/cache-manifest appcache manifest 115 | AddType text/x-component htc 116 | AddType application/xml rss atom xml rdf 117 | AddType application/x-chrome-extension crx 118 | AddType application/x-opera-extension oex 119 | AddType application/x-xpinstall xpi 120 | AddType application/octet-stream safariextz 121 | AddType application/x-web-app-manifest+json webapp 122 | AddType text/x-vcard vcf 123 | AddType application/x-shockwave-flash swf 124 | AddType text/vtt vtt 125 | 126 | 127 | # ---------------------------------------------------------------------- 128 | # Allow concatenation from within specific js and css files 129 | # ---------------------------------------------------------------------- 130 | 131 | # e.g. Inside of script.combined.js you could have 132 | # 133 | # 134 | # and they would be included into this single file. 135 | 136 | # This is not in use in the boilerplate as it stands. You may 137 | # choose to use this technique if you do not have a build process. 138 | 139 | # 140 | # Options +Includes 141 | # AddOutputFilterByType INCLUDES application/javascript application/json 142 | # SetOutputFilter INCLUDES 143 | # 144 | 145 | # 146 | # Options +Includes 147 | # AddOutputFilterByType INCLUDES text/css 148 | # SetOutputFilter INCLUDES 149 | # 150 | 151 | 152 | # ---------------------------------------------------------------------- 153 | # Gzip compression 154 | # ---------------------------------------------------------------------- 155 | 156 | 157 | 158 | # Force deflate for mangled headers developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping/ 159 | 160 | 161 | SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding 162 | RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding 163 | 164 | 165 | 166 | # HTML, TXT, CSS, JavaScript, JSON, XML, HTC: 167 | 168 | FilterDeclare COMPRESS 169 | FilterProvider COMPRESS DEFLATE resp=Content-Type $text/html 170 | FilterProvider COMPRESS DEFLATE resp=Content-Type $text/css 171 | FilterProvider COMPRESS DEFLATE resp=Content-Type $text/plain 172 | FilterProvider COMPRESS DEFLATE resp=Content-Type $text/xml 173 | FilterProvider COMPRESS DEFLATE resp=Content-Type $text/x-component 174 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/javascript 175 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/json 176 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xml 177 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/xhtml+xml 178 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/rss+xml 179 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/atom+xml 180 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/vnd.ms-fontobject 181 | FilterProvider COMPRESS DEFLATE resp=Content-Type $image/svg+xml 182 | FilterProvider COMPRESS DEFLATE resp=Content-Type $image/x-icon 183 | FilterProvider COMPRESS DEFLATE resp=Content-Type $application/x-font-ttf 184 | FilterProvider COMPRESS DEFLATE resp=Content-Type $font/opentype 185 | FilterChain COMPRESS 186 | FilterProtocol COMPRESS DEFLATE change=yes;byteranges=no 187 | 188 | 189 | 190 | # Legacy versions of Apache 191 | AddOutputFilterByType DEFLATE text/html text/plain text/css application/json 192 | AddOutputFilterByType DEFLATE application/javascript 193 | AddOutputFilterByType DEFLATE text/xml application/xml text/x-component 194 | AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml 195 | AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype 196 | 197 | 198 | 199 | 200 | 201 | # ---------------------------------------------------------------------- 202 | # Expires headers (for better cache control) 203 | # ---------------------------------------------------------------------- 204 | 205 | # These are pretty far-future expires headers. 206 | # They assume you control versioning with filename-based cache busting 207 | # Additionally, consider that outdated proxies may miscache 208 | # www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/ 209 | 210 | # If you don't use filenames to version, lower the CSS and JS to something like 211 | # "access plus 1 week". 212 | 213 | 214 | ExpiresActive on 215 | 216 | # Perhaps better to whitelist expires rules? Perhaps. 217 | ExpiresDefault "access plus 1 month" 218 | 219 | # cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5) 220 | ExpiresByType text/cache-manifest "access plus 0 seconds" 221 | 222 | # Your document html 223 | ExpiresByType text/html "access plus 0 seconds" 224 | 225 | # Data 226 | ExpiresByType text/xml "access plus 0 seconds" 227 | ExpiresByType application/xml "access plus 0 seconds" 228 | ExpiresByType application/json "access plus 0 seconds" 229 | 230 | # Feed 231 | ExpiresByType application/rss+xml "access plus 1 hour" 232 | ExpiresByType application/atom+xml "access plus 1 hour" 233 | 234 | # Favicon (cannot be renamed) 235 | ExpiresByType image/x-icon "access plus 1 week" 236 | 237 | # Media: images, video, audio 238 | ExpiresByType image/gif "access plus 1 month" 239 | ExpiresByType image/png "access plus 1 month" 240 | ExpiresByType image/jpeg "access plus 1 month" 241 | ExpiresByType video/ogg "access plus 1 month" 242 | ExpiresByType audio/ogg "access plus 1 month" 243 | ExpiresByType video/mp4 "access plus 1 month" 244 | ExpiresByType video/webm "access plus 1 month" 245 | 246 | # HTC files (css3pie) 247 | ExpiresByType text/x-component "access plus 1 month" 248 | 249 | # Webfonts 250 | ExpiresByType application/x-font-ttf "access plus 1 month" 251 | ExpiresByType font/opentype "access plus 1 month" 252 | ExpiresByType application/x-font-woff "access plus 1 month" 253 | ExpiresByType image/svg+xml "access plus 1 month" 254 | ExpiresByType application/vnd.ms-fontobject "access plus 1 month" 255 | 256 | # CSS and JavaScript 257 | ExpiresByType text/css "access plus 1 year" 258 | ExpiresByType application/javascript "access plus 1 year" 259 | 260 | 261 | 262 | 263 | # ---------------------------------------------------------------------- 264 | # Prevent mobile network providers from modifying your site 265 | # ---------------------------------------------------------------------- 266 | 267 | # The following header prevents modification of your code over 3G on some 268 | # European providers. 269 | # This is the official 'bypass' suggested by O2 in the UK. 270 | 271 | # 272 | # Header set Cache-Control "no-transform" 273 | # 274 | 275 | 276 | # ---------------------------------------------------------------------- 277 | # ETag removal 278 | # ---------------------------------------------------------------------- 279 | 280 | # FileETag None is not enough for every server. 281 | 282 | Header unset ETag 283 | 284 | 285 | # Since we're sending far-future expires, we don't need ETags for 286 | # static content. 287 | # developer.yahoo.com/performance/rules.html#etags 288 | FileETag None 289 | 290 | 291 | # ---------------------------------------------------------------------- 292 | # Stop screen flicker in IE on CSS rollovers 293 | # ---------------------------------------------------------------------- 294 | 295 | # The following directives stop screen flicker in IE on CSS rollovers - in 296 | # combination with the "ExpiresByType" rules for images (see above). 297 | 298 | # BrowserMatch "MSIE" brokenvary=1 299 | # BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1 300 | # BrowserMatch "Opera" !brokenvary 301 | # SetEnvIf brokenvary 1 force-no-vary 302 | 303 | 304 | # ---------------------------------------------------------------------- 305 | # Set Keep-Alive Header 306 | # ---------------------------------------------------------------------- 307 | 308 | # Keep-Alive allows the server to send multiple requests through one 309 | # TCP-connection. Be aware of possible disadvantages of this setting. Turn on 310 | # if you serve a lot of static content. 311 | 312 | # 313 | # Header set Connection Keep-Alive 314 | # 315 | 316 | 317 | # ---------------------------------------------------------------------- 318 | # Cookie setting from iframes 319 | # ---------------------------------------------------------------------- 320 | 321 | # Allow cookies to be set from iframes (for IE only) 322 | # If needed, specify a path or regex in the Location directive. 323 | 324 | # 325 | # Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"" 326 | # 327 | 328 | 329 | # ---------------------------------------------------------------------- 330 | # Start rewrite engine 331 | # ---------------------------------------------------------------------- 332 | 333 | # Turning on the rewrite engine is necessary for the following rules and 334 | # features. FollowSymLinks must be enabled for this to work. 335 | 336 | # Some cloud hosting services require RewriteBase to be set: goo.gl/HOcPN 337 | # If using the h5bp in a subdirectory, use `RewriteBase /foo` instead where 338 | # 'foo' is your directory. 339 | 340 | # If your web host doesn't allow the FollowSymlinks option, you may need to 341 | # comment it out and use `Options +SymLinksOfOwnerMatch`, but be aware of the 342 | # performance impact: http://goo.gl/Mluzd 343 | 344 | 345 | Options +FollowSymlinks 346 | # Options +SymLinksIfOwnerMatch 347 | Options +FollowSymlinks 348 | RewriteEngine On 349 | # RewriteBase / 350 | 351 | 352 | 353 | # ---------------------------------------------------------------------- 354 | # Suppress or force the "www." at the beginning of URLs 355 | # ---------------------------------------------------------------------- 356 | 357 | # The same content should never be available under two different URLs - 358 | # especially not with and without "www." at the beginning, since this can cause 359 | # SEO problems (duplicate content). That's why you should choose one of the 360 | # alternatives and redirect the other one. 361 | 362 | # By default option 1 (no "www.") is activated. 363 | # no-www.org/faq.php?q=class_b 364 | 365 | # If you'd prefer to use option 2, just comment out all option 1 lines 366 | # and uncomment option 2. 367 | 368 | # IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME! 369 | 370 | # ---------------------------------------------------------------------- 371 | 372 | # Option 1: 373 | # Rewrite "www.example.com -> example.com". 374 | 375 | 376 | RewriteCond %{HTTPS} !=on 377 | RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] 378 | RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] 379 | 380 | 381 | # ---------------------------------------------------------------------- 382 | 383 | # Option 2: 384 | # Rewrite "example.com -> www.example.com". 385 | # Be aware that the following rule might not be a good idea if you use "real" 386 | # subdomains for certain parts of your website. 387 | 388 | # 389 | # RewriteCond %{HTTPS} !=on 390 | # RewriteCond %{HTTP_HOST} !^www\..+$ [NC] 391 | # RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] 392 | # 393 | 394 | 395 | # ---------------------------------------------------------------------- 396 | # Built-in filename-based cache busting 397 | # ---------------------------------------------------------------------- 398 | 399 | # If you're not using the build script to manage your filename version revving, 400 | # you might want to consider enabling this, which will route requests for 401 | # /css/style.20110203.css to /css/style.css 402 | 403 | # To understand why this is important and a better idea than all.css?v1231, 404 | # read: github.com/h5bp/html5-boilerplate/wiki/cachebusting 405 | 406 | # 407 | # RewriteCond %{REQUEST_FILENAME} !-f 408 | # RewriteCond %{REQUEST_FILENAME} !-d 409 | # RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L] 410 | # 411 | 412 | 413 | # ---------------------------------------------------------------------- 414 | # Prevent SSL cert warnings 415 | # ---------------------------------------------------------------------- 416 | 417 | # Rewrite secure requests properly to prevent SSL cert warnings, e.g. prevent 418 | # https://www.example.com when your cert only allows https://secure.example.com 419 | 420 | # 421 | # RewriteCond %{SERVER_PORT} !^443 422 | # RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L] 423 | # 424 | 425 | 426 | # ---------------------------------------------------------------------- 427 | # Prevent 404 errors for non-existing redirected folders 428 | # ---------------------------------------------------------------------- 429 | 430 | # without -MultiViews, Apache will give a 404 for a rewrite if a folder of the 431 | # same name does not exist. 432 | # webmasterworld.com/apache/3808792.htm 433 | 434 | Options -MultiViews 435 | 436 | 437 | # ---------------------------------------------------------------------- 438 | # Custom 404 page 439 | # ---------------------------------------------------------------------- 440 | 441 | # You can add custom pages to handle 500 or 403 pretty easily, if you like. 442 | # If you are hosting your site in subdirectory, adjust this accordingly 443 | # e.g. ErrorDocument 404 /subdir/404.html 444 | ErrorDocument 404 /404.html 445 | 446 | 447 | # ---------------------------------------------------------------------- 448 | # UTF-8 encoding 449 | # ---------------------------------------------------------------------- 450 | 451 | # Use UTF-8 encoding for anything served text/plain or text/html 452 | AddDefaultCharset utf-8 453 | 454 | # Force UTF-8 for a number of file formats 455 | AddCharset utf-8 .atom .css .js .json .rss .vtt .xml 456 | 457 | 458 | # ---------------------------------------------------------------------- 459 | # A little more security 460 | # ---------------------------------------------------------------------- 461 | 462 | # To avoid displaying the exact version number of Apache being used, add the 463 | # following to httpd.conf (it will not work in .htaccess): 464 | # ServerTokens Prod 465 | 466 | # "-Indexes" will have Apache block users from browsing folders without a 467 | # default document Usually you should leave this activated, because you 468 | # shouldn't allow everybody to surf through every folder on your server (which 469 | # includes rather private places like CMS system folders). 470 | 471 | Options -Indexes 472 | 473 | 474 | # Block access to "hidden" directories or files whose names begin with a 475 | # period. This includes directories used by version control systems such as 476 | # Subversion or Git. 477 | 478 | RewriteCond %{SCRIPT_FILENAME} -d [OR] 479 | RewriteCond %{SCRIPT_FILENAME} -f 480 | RewriteRule "(^|/)\." - [F] 481 | 482 | 483 | # Block access to backup and source files. These files may be left by some 484 | # text/html editors and pose a great security danger, when anyone can access 485 | # them. 486 | 487 | Order allow,deny 488 | Deny from all 489 | Satisfy All 490 | 491 | 492 | # If your server is not already configured as such, the following directive 493 | # should be uncommented in order to set PHP's register_globals option to OFF. 494 | # This closes a major security hole that is abused by most XSS (cross-site 495 | # scripting) attacks. For more information: http://php.net/register_globals 496 | # 497 | # IF REGISTER_GLOBALS DIRECTIVE CAUSES 500 INTERNAL SERVER ERRORS: 498 | # 499 | # Your server does not allow PHP directives to be set via .htaccess. In that 500 | # case you must make this change in your php.ini file instead. If you are 501 | # using a commercial web host, contact the administrators for assistance in 502 | # doing this. Not all servers allow local php.ini files, and they should 503 | # include all PHP configurations (not just this one), or you will effectively 504 | # reset everything to PHP defaults. Consult www.php.net for more detailed 505 | # information about setting PHP directives. 506 | 507 | # php_flag register_globals Off 508 | 509 | # Rename session cookie to something else, than PHPSESSID 510 | # php_value session.name sid 511 | 512 | # Disable magic quotes (This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.) 513 | # php_flag magic_quotes_gpc Off 514 | 515 | # Do not show you are using PHP 516 | # Note: Move this line to php.ini since it won't work in .htaccess 517 | # php_flag expose_php Off 518 | 519 | # Level of log detail - log all errors 520 | # php_value error_reporting -1 521 | 522 | # Write errors to log file 523 | # php_flag log_errors On 524 | 525 | # Do not display errors in browser (production - Off, development - On) 526 | # php_flag display_errors Off 527 | 528 | # Do not display startup errors (production - Off, development - On) 529 | # php_flag display_startup_errors Off 530 | 531 | # Format errors in plain text 532 | # Note: Leave this setting 'On' for xdebug's var_dump() output 533 | # php_flag html_errors Off 534 | 535 | # Show multiple occurrence of error 536 | # php_flag ignore_repeated_errors Off 537 | 538 | # Show same errors from different sources 539 | # php_flag ignore_repeated_source Off 540 | 541 | # Size limit for error messages 542 | # php_value log_errors_max_len 1024 543 | 544 | # Don't precede error with string (doesn't accept empty string, use whitespace if you need) 545 | # php_value error_prepend_string " " 546 | 547 | # Don't prepend to error (doesn't accept empty string, use whitespace if you need) 548 | # php_value error_append_string " " 549 | 550 | # Increase cookie security 551 | 552 | php_value session.cookie_httponly true 553 | 554 | -------------------------------------------------------------------------------- /app/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Not Found :( 6 | 141 | 142 | 143 |
144 |

Not found :(

145 |

Sorry, but the page you were trying to view does not exist.

146 |

It looks like this was the result of either:

147 | 151 | 154 | 155 |
156 | 157 | 158 | -------------------------------------------------------------------------------- /app/data/data.csv: -------------------------------------------------------------------------------- 1 | date,savings,total,optimal 2 | 2001-01-01, 10, 10, 50 3 | 2001-02-01, 90, 100, 100 4 | 2001-03-01, 30, 130, 150 5 | 2001-04-01, 45, 175, 200 6 | 2001-05-01, 50, 225, 250 7 | 2001-06-01, 75, 300, 300 8 | 2001-07-01, 10, 310, 350 9 | 2001-08-01, 30, 340, 400 10 | 2001-09-01, 65, 405, 450 11 | 2001-10-01, 100, 505, 500 12 | 2001-11-01, 110, 615, 550 13 | 2001-12-01, 80, 695, 600 14 | 2002-01-01, 35, 730, 650 15 | 2002-02-01, 70, 800, 700 16 | 2002-03-01, 150, 950, 750 17 | -------------------------------------------------------------------------------- /app/data/donutData.csv: -------------------------------------------------------------------------------- 1 | age,population 2 | <5,2704659 3 | 5-13,4499890 4 | 14-17,2159981 5 | 18-24,3853788 6 | 25-44,14106543 7 | 45-64,8819342 8 | ≥65,612463 -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WealthBar/angular-d3/d8c5cc32aff2df18eb337255751e6a446a5ad4e3/app/favicon.ico -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Angular D3 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |

Angular D3

15 |

A set of basic directives that support declarative charts and graphs powered by D3

16 |

Get the source on GitHub

17 |

Toggle chart format locale: 18 | en-US / 19 | fr-CA / 20 | zh-CN 21 |

22 |
23 |
24 |
25 |
26 |
27 | 41 |
42 |
43 |
44 |
45 |
46 |
47 | 49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | window.$ = window.jQuery = require('jquery') 2 | 3 | require('./scripts/app') 4 | 5 | require('bootstrap/js/scrollspy') 6 | require("bootstrap/dist/css/bootstrap"); 7 | require('./styles') 8 | -------------------------------------------------------------------------------- /app/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org 2 | 3 | User-agent: * 4 | -------------------------------------------------------------------------------- /app/scripts/app.coffee: -------------------------------------------------------------------------------- 1 | angular = require('angular') 2 | angular.module('angularD3App', ['ad3']). 3 | config(['d3localeProvider', (d3localeProvider) -> 4 | d3localeProvider.setLocales({ 5 | "en-us": require('../../angularD3/locale/en-US'), 6 | "fr-ca": require('../../angularD3/locale/fr-CA'), 7 | "zh-cn": require('../../angularD3/locale/zh-CN'), 8 | }) 9 | ]). 10 | run(['d3locale', '$location', (d3locale, $location) -> 11 | lang = $location.search().locale || "en-US" 12 | $('html').attr('lang', lang) 13 | d3locale.setLang(lang) 14 | ]) 15 | require('./main') 16 | -------------------------------------------------------------------------------- /app/scripts/main.coffee: -------------------------------------------------------------------------------- 1 | controller = require('./main_controller') 2 | view = require('./main_view.html') 3 | 4 | angular.module('angularD3App').directive 'main', -> 5 | controller: controller 6 | templateUrl: view 7 | -------------------------------------------------------------------------------- /app/scripts/main_controller.coffee: -------------------------------------------------------------------------------- 1 | dataUrl = require('../data/data.csv') 2 | donutDataUrl = require('../data/donutData.csv') 3 | 4 | module.exports = ['$scope', '$interval', '$location', ($scope, $interval, $location) -> 5 | $scope.dataUrl = dataUrl 6 | $scope.donutDataUrl = donutDataUrl 7 | $scope.$watch '', -> 8 | $('body').scrollspy('refresh') 9 | 10 | $scope.arcs = 11 | arc1: { value: 60, label: '60%' } 12 | arc2: { value: 90, label: '90%' } 13 | 14 | $interval -> 15 | val = Math.random() * 100 16 | $scope.arcs.arc1 = { value: val, label: "#{val.toFixed(0)}%" } 17 | , 1000 * 5 18 | 19 | $interval -> 20 | val = Math.random() * 100 21 | $scope.arcs.arc2 = { value: val, label: "#{val.toFixed(0)}%" } 22 | , 1000 * 5 23 | 24 | $interval -> 25 | if $scope.columns.length == 3 26 | $scope.columns = ['savings', 'optimal'] 27 | else 28 | $scope.columns = ['savings', 'total', 'optimal'] 29 | , 1000 * 10 30 | 31 | $scope.stackDomain = (data) -> 32 | values = for value in data 33 | Number(value.savings) + Number(value.total) + Number(value.optimal) 34 | 35 | $scope.parseValues = (row) -> 36 | for k, v of row 37 | # http://stackoverflow.com/a/1830844/235243 38 | if k is 'date' 39 | row[k] = new Date(v.trim()) 40 | else if !isNaN(parseFloat(v)) && isFinite(v) 41 | row[k] = +v 42 | row 43 | 44 | $scope.log = (data) -> 45 | console.log(data) 46 | 47 | $scope.columns = ['savings', 'total', 'optimal'] 48 | 49 | $scope.tickValues = [200, 400, 600, 800] 50 | 51 | $scope.gradient = [ 52 | { offset: '0%', color: '#098aae', opacity: 0.6 }, 53 | { offset: '100%', color: '#684684', opacity: 0.9 } 54 | ] 55 | 56 | $scope.customTimeFormat = [ 57 | ["%a %d", (d) -> d.getDay() && d.getDate() != 1], 58 | ["%b %d", (d) -> d.getDate() != 1], 59 | ["%b", (d) -> d.getMonth()], 60 | ["%Y", -> true] 61 | ] 62 | ] 63 | -------------------------------------------------------------------------------- /app/scripts/main_view.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 |
6 |

Basic Graphs

7 |

Basic line, area and bar charts can be composed together in the same chart.

8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 |
18 | 19 |
20 |

Stacked Areas

21 |

Area charts can be stacked by specifying multiple y propeties

22 |
23 | 28 | 32 | 33 |
34 |
35 | 36 |
37 |

Pie and Donut Charts

38 |
39 |
40 | 41 |
42 |
43 | 44 |
45 |
46 |
47 | 48 |
49 |

Arc Charts

50 |
51 |
52 | 53 |
54 |
55 | 56 |
57 |
58 |
59 |
60 | -------------------------------------------------------------------------------- /app/styles/index.scss: -------------------------------------------------------------------------------- 1 | @import "theme/default"; 2 | @import "main"; 3 | -------------------------------------------------------------------------------- /app/styles/main.scss: -------------------------------------------------------------------------------- 1 | /* Will be compiled down to a single stylesheet with your sass files */ 2 | 3 | body { 4 | margin-top: 40px; 5 | } 6 | 7 | section { 8 | margin-bottom: 40px; 9 | } 10 | 11 | [d3-chart] { 12 | height: 400px; 13 | } 14 | 15 | footer { 16 | min-height: 500px; 17 | } 18 | 19 | #side-nav.affix { 20 | width: 100%; 21 | top: 40px; 22 | margin: 0 auto; 23 | @media (min-width: 768px) { 24 | max-width: 758px; 25 | } 26 | @media (min-width: 992px) { 27 | max-width: 970px; 28 | } 29 | @media (min-width: 1200px) { 30 | max-width: 1200px; 31 | } 32 | ul { 33 | width: 25%; 34 | padding: 0 15px; 35 | margin-left: -15px; 36 | z-index: 2; 37 | } 38 | } 39 | 40 | #graphs { 41 | .d3 .area { 42 | fill: url(#gradient); 43 | } 44 | } 45 | @-moz-document url-prefix() { 46 | #graphs .d3 .area { 47 | fill: url(/#gradient); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/styles/theme/default.scss: -------------------------------------------------------------------------------- 1 | $blue: #098aae; 2 | $violet: #684684; 3 | $green: #00a79d; 4 | $orange: #eda646; 5 | $black: #222222; 6 | 7 | /* Axis */ 8 | 9 | .d3 .axis { 10 | line { fill: none; stroke-width: 1px; stroke: $black; opacity: 0.5; } 11 | path { fill: none; stroke-width: 1px; stroke: $black; opacity: 0.5; } 12 | text { fill: $black; } 13 | } 14 | 15 | .d3 .axis-grid { 16 | line { fill: none; stroke-width: 1px; stroke: $black; opacity: 0.5; } 17 | text { display: none; } 18 | } 19 | 20 | /* Area Chart */ 21 | 22 | .d3 .area { 23 | fill: $blue; 24 | stroke-width: 0px; 25 | stroke: $black; 26 | } 27 | 28 | /* Line Chart */ 29 | 30 | .d3 .line { 31 | fill: none; 32 | stroke-width: 1.5px; 33 | stroke: $black; 34 | } 35 | 36 | /* Bar Chart */ 37 | 38 | .d3 .bar { 39 | fill: $orange; 40 | stroke-width: 0px; 41 | stroke: $black; 42 | opacity: 0.7; 43 | } 44 | 45 | /* Pie Chart */ 46 | 47 | .d3 { 48 | .pie.pie-0 path { fill: #98abc5; } 49 | .pie.pie-1 path { fill: #8a89a6; } 50 | .pie.pie-2 path { fill: #7b6888; } 51 | .pie.pie-3 path { fill: #6b486b; } 52 | .pie.pie-4 path { fill: #a05d56; } 53 | .pie.pie-5 path { fill: #d0743c; } 54 | .pie.pie-6 path { fill: #ff8c00; } 55 | } 56 | 57 | /* Simple Arcs */ 58 | 59 | .d3 path.arc { 60 | fill: #98abc5; 61 | } 62 | 63 | .simple-arc1 .d3 .arc { 64 | fill: #98abc5; 65 | } 66 | 67 | .simple-arc2 .d3 .arc { 68 | fill: #d0743c; 69 | } 70 | 71 | .area.savings { 72 | fill: #d0743c; 73 | } 74 | 75 | 76 | .area.optimal { 77 | fill: #98abc5; 78 | } 79 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angularD3", 3 | "version": "0.1.1", 4 | "main": "dist/angularD3.js", 5 | "ignore": [ 6 | ".*", 7 | "app", 8 | "node_modules", 9 | "bower_components", 10 | "test", 11 | "tests" 12 | ], 13 | "dependencies": { 14 | "d3": "~3.4", 15 | "angular": "*" 16 | }, 17 | "homepage": "http://wealthbar.github.io/angular-d3", 18 | "authors": [ 19 | "Chris Nicola " 20 | ], 21 | "description": "AngularJS chart directives and other integrations for D3.js", 22 | "keywords": [ 23 | "AngularJS", 24 | "D3", 25 | "D3.js", 26 | "charts" 27 | ], 28 | "license": "MIT" 29 | } 30 | -------------------------------------------------------------------------------- /dist/angularD3.js: -------------------------------------------------------------------------------- 1 | !function(t){function r(e){if(n[e])return n[e].exports;var i=n[e]={exports:{},id:e,loaded:!1};return t[e].call(i.exports,i,i.exports,r),i.loaded=!0,i.exports}var n={};return r.m=t,r.c=n,r.p="",r(0)}([function(t,r,n){n(12)},function(t,r){t.exports=d3},function(t,r,n){var e;e=n(1),angular.module("ad3").directive("d3Arc",function(){var t;return t=function(){return{x:0,y:1,innerRadius:0,labelRadius:0,transition:"cubic-in-out",transitionDuration:1e3,value:"value",label:"label"}},{restrict:"E",require:"^d3Chart",link:function(r,n,i,a){var o,u,l,c,s,d,f,h;return f=angular.extend(t(),i),c=a.getChart(),s=parseFloat(f.innerRadius),d=parseFloat(f.labelRadius),l=null,u=null,o=null,h=function(t){var r,n,i,c;return l||(l=a.getChart().append("g").attr("class","arc")),u||(u=l.append("path")),o||(o=l.append("text").attr("class","arc-label").attr("dy","0.35em").style("text-anchor","middle")),null!=t&&0!==t.length?(c=Math.min(a.innerWidth,a.innerHeight)/2,l.attr("transform","translate("+c+","+c+")"),r=e.svg.arc().outerRadius(c).innerRadius(c*s).startAngle(0).endAngle(function(t){return t/100*2*Math.PI}),n=function(t){var n;return null==this._current&&(this._current=0),n=e.interpolate(this._current,t),this._current=t,function(t){return r(n(t))}},i=e.svg.arc().outerRadius(c*d).innerRadius(c*d),u.datum(t[f.value]).transition().ease(f.transition).duration(f.transitionDuration).attrTween("d",n),o.text(t[f.label])):void 0},a.registerElement(h,f.order)}}})},function(t,r){angular.module("ad3").directive("d3Area",function(){var t;return t=function(){return{}},{restrict:"E",require:"^d3Chart",scope:{columns:"="},link:function(r,n,e,i){var a,o,u,l,c,s,d;return l=angular.extend(t(),e),s=i.getScale(l.xscale||l.x),d=i.getScale(l.yscale||l.y),l.vertical?(a=d3.svg.area().y(function(t){return s(t.x)}).x0(0).x1(function(t){return d(t.y)}),u=d3.svg.area().y(function(t){return s(t.x)}).x0(function(t){return d(t.y0)}).x1(function(t){return d(t.y+t.y0)})):(a=d3.svg.area().x(function(t){return s(t.x)}).y0(function(){return i.innerHeight}).y1(function(t){return d(t.y)}),u=d3.svg.area().x(function(t){return s(t.x)}).y0(function(t){return d(t.y0)}).y1(function(t){return d(t.y+t.y0)})),o=null,c=function(t){var n,e,c,s,d,f,h;return o||(o=i.getChart().append("g").attr("class","area")),null!=t&&0!==t.length&&(null!=l.y&&(e=l.y),null!=r.columns&&(e=r.columns),null!=e&&(angular.isString(e)&&(e=e.split(",").map(function(t){return t.trim()})),0!==e.length))?(c=function(){var r,n,i;for(i=[],r=0,n=e.length;n>r;r++)s=e[r],i.push({name:s,values:function(){var r,n,e;for(e=[],r=0,n=t.length;n>r;r++)h=t[r],e.push({x:h[l.x],y:h[s]});return e}()});return i}(),d=d3.layout.stack().values(function(t){return t.values}),null!=l.offset&&d.offset(l.offset),f=d(c),n=o.selectAll("path.area").data(f),n.enter().append("path"),n.attr("class",function(t){return"area "+t.name}).transition().duration(500).attr("d",function(t,r){return 0===r?a(t.values):u(t.values)}),n.exit().attr("d",function(t,r){return 0===r?a(t.values):u(t.values)}).remove()):void 0},r.$watch("columns",i.redraw,!0),i.registerElement(c,l.order)}}})},function(t,r){angular.module("ad3").directive("d3Axis",["d3locale",function(t){var r;return r=function(){return{orientation:"bottom",ticks:"5",extent:!1}},{priority:1,restrict:"E",require:"^d3Chart",scope:{customTimeFormat:"=",filter:"=",tickValues:"="},link:function(t,n,e,i){var a,o,u,l,c,s,d,f,h,g,m,p,v;return d=angular.extend(r(),e),h=function(){return"top"===d.orientation||"bottom"===d.orientation?null!=d.reverse?[i.innerWidth,0]:[0,i.innerWidth]:null!=d.reverse?[0,i.innerHeight]:[i.innerHeight,0]},p=function(){return"bottom"===d.orientation?"translate(0, "+i.innerHeight+")":"top"===d.orientation?"translate(0, 0)":"left"===d.orientation?"translate(0, 0)":"right"===d.orientation?"translate("+i.innerWidth+", 0)":void 0},m="time"===d.scale?d3.time.scale():d.scale?d3.scale[d.scale]():d3.scale.linear(),l=function(){var r,n,e;return r=d3.svg.axis().scale(m).orient(d.orientation),d.ticks&&r.ticks(d.ticks),d.timeScale&&r.ticks(d3.time[d.timeScale],d.timeInterval),t.tickValues&&r.tickValues(t.tickValues),d.tickSize&&(e=d.tickSize.split(","),r.innerTickSize(e[0]),r.outerTickSize(e[1])),null!=t.customTimeFormat&&(n=d3.time.format.multi(angular.copy(t.customTimeFormat)),r.tickFormat(function(t){return n(new Date(t))})),null!=d.timeFormat?(n=d3.time.format(d.timeFormat),r.tickFormat(function(t){return n(new Date(t))})):null!=d.format&&(n=d3.format(d.format),r.tickFormat(n)),r},f=function(t){return"bottom"===d.orientation?t.attr("x",""+i.innerWidth/2).attr("dy",""+i.margin.bottom).attr("style","text-anchor: middle;"):"top"===d.orientation?t.attr("x",""+i.innerWidth/2).attr("dy",""+-i.margin.top).attr("style","text-anchor: middle;"):"left"===d.orientation?t.attr("x","-"+i.innerHeight/2).attr("dy",""+(-i.margin.left+18)).attr("style","text-anchor: middle;").attr("transform","rotate(-90)"):"right"===d.orientation?t.attr("x",""+i.innerHeight/2).attr("dy",""+(-i.margin.right+18)).attr("style","text-anchor: middle;").attr("transform","rotate(90)"):void 0},u=function(t,r){return"bottom"===d.orientation?t.call(r.tickSize(i.innerHeight,0,0).tickFormat("")):"top"===d.orientation?t.attr("transform","translate(0, "+i.innerHeight+")").call(r.tickSize(i.innerHeight,0,0).tickFormat("")):"left"===d.orientation?t.attr("transform","translate("+i.innerWidth+", 0)").call(r.tickSize(i.innerWidth,0,0).tickFormat("")):"right"===d.orientation?t.call(r.tickSize(i.innerWidth,0,0).tickFormat("")):void 0},a=function(t){var r,n,e;return e=t.selectAll(".tick text"),d.tickDy&&e.attr("dy",d.tickDy),d.tickDx&&e.attr("dx",d.tickDx),d.tickAnchor&&e.style("text-anchor",d.tickAnchor),n=d3.select(e[0].slice(-1)[0]),d.lastTickDy&&n.attr("dy",d.lastTickDy),d.lastTickDx&&n.attr("dx",d.lastTickDx),d.lastTickAnchor&&n.style("text-anchor",d.lastTickAnchor),r=d3.select(e[0][0]),d.firstTickDy&&r.attr("dy",d.firstTickDy),d.firstTickDx&&r.attr("dx",d.firstTickDx),d.listTickAnchor?r.style("text-anchor",d.firstTickAnchor):void 0},o=null,c=null,s=null,g=function(t){var r,n;if(null!=t&&0!==t.length)return o||(o=i.getChart().append("g").attr("class","axis axis-"+d.orientation+" axis-"+d.name).attr("transform",p())),d.label&&(s||(s=o.append("text").attr("class","axis-label").text(d.label))),d.grid&&(c||(c=i.getChart().append("g").attr("class","axis-grid axis-grid-"+d.name))),r=l(),s&&f(s.transition().duration(500)),o.transition().duration(500).attr("transform",p()).call(r).selectAll("tick text").tween("attr.dx",null).tween("attr.dy",null).tween("style.text-anchor",null),null!=c&&u(c.transition().duration(500),r),n=o.selectAll(".tick text"),o.call(a)},v=function(r){var n,e;if(null!=r&&0!==r.length)return m.range(h()),d.domain,e=t.filter?t.filter(r):function(){var t,e,i;for(i=[],t=0,e=r.length;e>t;t++)n=r[t],i.push(n[d.name]);return i}(),d.extent?m.domain(d3.extent(e)):m.domain([0,d3.max(e)])},i.addScale(d.name,m,v),i.registerElement(g,d.order),t.$watchCollection("tickValues",i.redraw),t.$watchCollection("customTimeFormat",i.redraw),t.$watch("filter",i.redraw),t.$watch("tickValues",i.redraw)}}}])},function(t,r){angular.module("ad3").directive("d3Bars",function(){var t;return t=function(){return{x:0,y:1,width:15}},{restrict:"E",require:"^d3Chart",link:function(r,n,e,i){var a,o,u,l,c,s,d,f;return l=angular.extend(t(),e),d=i.getScale(l.xscale||l.x),f=i.getScale(l.yscale||l.y),o=i.getChart(),u=i.innerHeight,s=l.width,a=null,c=function(t){var r;return a||(a=i.getChart().append("g").attr("class","bars")),null!=t&&0!==t.length?(r=a.selectAll("rect.bar").data(t),r.exit().transition().duration(500).attr("y",function(){return i.innerHeight}).attr("height",0).remove(),r.transition().duration(500).attr("x",function(t){return d(t[l.x])-s/2}).attr("y",function(t){return f(t[l.y])}).attr("height",function(t){return i.innerHeight-f(t[l.y])}).attr("width",s),r.enter().append("rect").attr("class",function(t,r){return"bar bar-"+r}).attr("x",function(t){return d(t[l.x])-s/2}).attr("width",s).attr("y",function(){return i.innerHeight}).attr("height",0).transition().duration(500).attr("y",function(t){return f(t[l.y])}).attr("height",function(t){return i.innerHeight-f(t[l.y])})):void 0},i.registerElement(c,l.order)}}})},function(t,r){angular.module("ad3").directive("d3Chart",function(){return{restrict:"EA",scope:{margin:"=",data:"="},controller:["$scope","$element","$attrs","$window","$timeout",function(t,r,n,e,i){var a,o,u,l,c,s,d,f,h;c=t.scales={},u=t.elements=[],this.margin=t.margin||{top:10,right:10,bottom:10,left:10},d=d3.select(r[0]).append("svg").attr("class","d3").attr("width","100%").attr("height","100%"),h=function(){return r[0].offsetWidth},l=function(){return r[0].offsetHeight},a=d.append("g").attr("transform","translate("+this.margin.left+","+this.margin.top+")"),this.getSvg=function(){return d},this.getChart=function(){return a},this.addScale=function(t,r,n){return c[t]={scale:r,update:n}},this.getScale=function(t){return c[t].scale},this.registerElement=function(t,r){return null==r&&(r=0),u.push({redraw:t,order:Number(r)})},f=function(t){return function(){return t.width!==h()||t.height!==l()?(t.width=h(),t.height=l(),t.innerWidth=t.width-t.margin.left-t.margin.right,t.innerHeight=t.height-t.margin.top-t.margin.bottom,t.redraw()):void 0}}(this),s=function(t,r){return t.order-r.order},o=null,this.redraw=function(r){return function(){return o||0===r.width||0===r.height?void 0:o=i(function(){var r,n,e,i,a,l,d,f;o=null,r=t.data;for(a in c)f=c[a],f.update(r);for(l=u.sort(s),d=[],e=0,i=l.length;i>e;e++)n=l[e],d.push(n.redraw(r));return d},n.updateInterval||200)}}(this),e.addEventListener("resize",f),"deep"===n.watch?t.$watch("data",this.redraw,!0):t.$watch("data",this.redraw),t.$watch(f),f()}]}})},function(t,r){angular.module("ad3").directive("d3Data",["d3Service",function(t){return{restrict:"E",scope:{accessor:"=",callback:"=",data:"="},link:function(r,n,e){var i;return i=e.src,t.csv(i,r.accessor,r.callback).then(function(t){return r.data=t},function(){throw"Error loading CSV via D3"})}}}])},function(t,r){angular.module("ad3").directive("d3Gradient",function(){var t;return t={transition:500},{restrict:"E",require:"^d3Chart",link:function(r,n,e,i){var a,o,u;return o=i.getSvg(),a=o.insert("defs","g").append("linearGradient").attr("id",e.ref),["x1","x2","y1","y2"].forEach(function(t){return e.$observe(t,function(r){return a.attr(t,r)})}),u=t.transition,e.$observe("transition",function(t){return null!=t?u=t:void 0}),r.$watch(e.stops,function(t){return null!=t?(t=a.selectAll("stop").data(t),t.enter().append("stop"),t.attr("offset",function(t){return t.offset}).attr("stop-color",function(t){return t.color}).attr("stop-opacity",function(t){return null!=t.opacity?t.opacity:1}),t.exit().remove()):void 0})}}})},function(t,r){angular.module("ad3").directive("d3Include",function(){return{restrict:"E",require:"^d3Chart",link:function(t,r,n,e){var i,a;return i=e.getChart(),a=i.append("g").attr("class","includes"),a.html(r.html())}}})},function(t,r){angular.module("ad3").directive("d3Line",function(){var t;return t=function(){return{x:0,y:1}},{restrict:"E",require:"^d3Chart",link:function(r,n,e,i){var a,o,u,l,c,s;return u=angular.extend(t(),e),c=i.getScale(u.xscale||u.x),s=i.getScale(u.yscale||u.y),a=d3.svg.line().x(function(t){return c(t[u.x])}).y(function(t){return s(t[u.y])}),o=null,l=function(t){return o||(o=i.getChart().append("path").attr("class","line line-"+(u.name||u.y)).style("fill","none").style("stroke",u.stroke)),null!=t&&0!==t.length?o.datum(t).transition().duration(500).attr("d",a):void 0},i.registerElement(l,u.order)}}})},function(t,r){angular.module("ad3").directive("d3Pie",function(){var t;return t=function(){return{x:0,y:1,innerRadius:0,labelRadius:.7,transition:"cubic-in-out",transitionDuration:800,minOffset:12,value:"value"}},{restrict:"E",require:"^d3Chart",link:function(r,n,e,i){var a,o,u,l,c,s,d,f,h;return d=angular.extend(t(),e),u=i.getChart(),c=parseFloat(d.innerRadius),s=parseFloat(d.labelRadius),e.colors&&(l=function(){switch(e.colors){case"category20":return d3.scale.category20();case"category20b":return d3.scale.category20b();case"category20c":return d3.scale.category20c()}}()),f=d3.layout.pie().sort(null).value(function(t){return t[d.value]}),a=null,o=null,h=function(t){var r,n,a,u,h,g,m,p,v;return o||(o=i.getChart().append("g").attr("class","pie")),null!=t&&0!==t.length?(p=Math.min(i.innerWidth,i.innerHeight)/2,o.attr("transform","translate("+p+","+p+")"),r=d3.svg.arc().outerRadius(p).innerRadius(p*c),n=function(t){var n;return n=d3.interpolate(this._current,t),this._current=n(0),function(t){return r(n(t))}},h=d3.svg.arc().outerRadius(p*s).innerRadius(p*s),v=o.selectAll(".pie").data(f(t)),v.enter().append("path").attr("class",function(t,r){return"pie pie-"+r}).attr("d",r).each(function(t){return this._current=t}),e.colors&&v.style("fill",function(t,r){return l?l(r):t[e.color]}),v.exit().remove(),v.transition().ease(d.transition).duration(d.transitionDuration).attrTween("d",n),d.label?(m=null,g=+d.minOffset,a=function(t,r){var n,e,i,a,o,u,l,c,f;return l=h.centroid(t),d.avoidCollisions&&(c=[l[0],l[1]],this._position&&(c[0]-=this._position[0],c[1]-=this._position[1]),f=_.transform(this.getBoundingClientRect(),function(t,r,n){switch(n){case"left":return t[n]=r-g+c[0];case"top":return t[n]=r-g+c[1];case"right":return t[n]=r+g+c[0];case"bottom":return t[n]=r+g+c[1]}}),m&&!(f.rightm.right||f.bottomm.bottom)&&(i=f.left+(f.right-f.left)/2,a=f.top+(f.bottom-f.top)/2,n=m.left+(m.right-m.left)/2,e=m.top+(m.bottom-m.top)/2,o=Math.sqrt(Math.pow(i-n,2)+Math.pow(a-e,2))/2,u=d3.svg.arc().outerRadius(p*s+o).innerRadius(p*s+o),l=u.centroid(t)),this._position=l,m=f),"translate("+l+")"},u=o.selectAll("text").data(f(t)),u.enter().append("text").style("text-anchor","middle").attr("class",function(t,r){return"pie-label pie-label-"+r}),u.exit().remove(),u.text(function(r,n){return t[n][d.label]}),u.transition().ease(d.transition).duration(d.transitionDuration).attr("transform",a)):void 0):void 0},i.registerElement(h,d.order)}}})},function(t,r,n){var e;e=n(15),e.module("ad3",[]),n(14),n(13),n(2),n(3),n(4),n(5),n(6),n(7),n(8),n(9),n(10),n(11)},function(t,r,n){var e;e=n(1),angular.module("ad3").provider("d3locale",function(){var t;return t={},this.setLocales=function(r){return t=r},this.$get=function(){var r;return r=function(t){return e.format=t.numberFormat,e.time.format=t.timeFormat},{setLang:function(n){var i,a,o;try{return o=e.locale(t[n.toLowerCase()]),r(o)}catch(a){throw i=a,"d3locale error: '"+n+"' is a locale that either does not exist, or has not been loaded properly."}},setLocale:function(t){return r(e.locale(t))}}},this})},function(t,r,n){var e;e=n(1),angular.module("ad3").provider("d3Service",function(){var t;return t=this.defaults={},this.$get=["$cacheFactory","$rootScope","$q",function(r,n,i){var a;return a=t.cache||r("d3Service"),{csv:function(t,r,o){var u,l;return l=i.defer(),u=a.get(t),u&&(o&&o(rows),l.resolve(u)),e.csv(t,r,function(r){return n.$apply(function(){return o&&o(r),r?(a.put(t,r),l.resolve(r)):l.reject()})}),l.promise}}}],this})},function(t,r){t.exports=angular}]); 2 | //# sourceMappingURL=angularD3.js.map -------------------------------------------------------------------------------- /dist/angularD3.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["angularD3.js","webpack/bootstrap 8bf28550a687135190f4","./index.js","external \"d3\"","./angularD3/directives/arc.coffee","./angularD3/directives/area.coffee","./angularD3/directives/axis.coffee","./angularD3/directives/bars.coffee","./angularD3/directives/chart.coffee","./angularD3/directives/data.coffee","./angularD3/directives/gradient.coffee","./angularD3/directives/include.coffee","./angularD3/directives/line.coffee","./angularD3/directives/pie.coffee","./angularD3/index.coffee","./angularD3/services/d3locale.coffee","./angularD3/services/d3service.coffee","external \"angular\""],"names":["modules","__webpack_require__","moduleId","installedModules","exports","module","id","loaded","call","m","c","p","d3","angular","directive","defaults","x","y","innerRadius","labelRadius","transition","transitionDuration","value","label","restrict","require","link","scope","el","attrs","chartController","arcLabel","arcPath","center","chart","options","redraw","extend","getChart","parseFloat","data","arc","arcTween","labelArc","radius","append","attr","style","length","Math","min","innerWidth","innerHeight","svg","outerRadius","startAngle","endAngle","d","PI","i","this","_current","interpolate","t","datum","ease","duration","attrTween","text","registerElement","order","columns","$scope","$el","$attrs","area","areaElement","areaStacked","getScale","xscale","yscale","vertical","x0","x1","y0","y1","charts","mappedData","name","stack","stackedData","isString","split","map","trim","j","len","results","push","values","k","len1","results1","layout","offset","selectAll","enter","exit","remove","$watch","d3locale","orientation","ticks","extent","priority","customTimeFormat","filter","tickValues","adjustTickLabels","axisElement","drawGrid","getAxis","grid","positionLabel","range","scale","translation","updateScale","reverse","time","linear","axis","format","tickSize","orient","timeScale","timeInterval","innerTickSize","outerTickSize","multi","copy","tickFormat","Date","timeFormat","margin","bottom","top","left","right","g","firstTickLabels","lastTickLabels","tickLabels","tickDy","tickDx","tickAnchor","select","slice","lastTickDy","lastTickDx","lastTickAnchor","firstTickDy","firstTickDx","listTickAnchor","firstTickAnchor","tween","domainValues","domain","max","addScale","$watchCollection","width","barsElements","height","bars","controller","$window","$timeout","debounce","elements","scales","sortOrder","updateSize","offsetWidth","offsetHeight","getSvg","update","Number","_this","a","b","element","ref","sort","updateInterval","addEventListener","watch","accessor","callback","src","csv","then","rows","gradient","insert","forEach","$observe","val","stops","color","opacity","includes","html","line","linePath","stroke","minOffset","colorScale","pie","colors","category20","category20b","category20c","getPosition","padding","prevbb","each","cpx","cpy","ctx","cty","offsetArc","position","relativePosition","thisbb","centroid","avoidCollisions","_position","_","transform","getBoundingClientRect","r","v","sqrt","pow","provider","localeDefinitions","setLocales","definitions","$get","updateLocale","locale","numberFormat","setLang","lang","err","error","toLowerCase","setLocale","$cacheFactory","$rootScope","$q","cache","cached","deferred","defer","get","resolve","$apply","put","reject","promise"],"mappings":"CAAS,SAAUA,GCInB,QAAAC,GAAAC,GAGA,GAAAC,EAAAD,GACA,MAAAC,GAAAD,GAAAE,OAGA,IAAAC,GAAAF,EAAAD,IACAE,WACAE,GAAAJ,EACAK,QAAA,EAUA,OANAP,GAAAE,GAAAM,KAAAH,EAAAD,QAAAC,IAAAD,QAAAH,GAGAI,EAAAE,QAAA,EAGAF,EAAAD,QAvBA,GAAAD,KAqCA,OATAF,GAAAQ,EAAAT,EAGAC,EAAAS,EAAAP,EAGAF,EAAAU,EAAA,GAGAV,EAAA,KDMM,SAASI,EAAQD,EAASH,GE5ChCA,EAAA,KFmDM,SAASI,EAAQD,GGnDvBC,EAAAD,QAAAQ,IHyDM,SAASP,EAAQD,EAASH,GIzDhC,GAAAW,KAAKX,EAAQ,GAEbY,QAAQR,OAAO,OAAOS,UAAU,QAAS,WACvC,GAAAC,EJ0EC,OI1EDA,GAAW,WJ+DR,OI9DDC,EAAG,EACHC,EAAG,EACHC,YAAa,EACbC,YAAa,EACbC,WAAY,eACZC,mBAAoB,IACpBC,MAAO,QACPC,MAAO,WAETC,SAAU,IAEVC,QAAS,WAETC,KAAM,SAACC,EAAOC,EAAIC,EAAOC,GACvB,GAAAC,GAAAC,EAAAC,EAAAC,EAAAhB,EAAAC,EAAAgB,EAAAC,CJmGG,OInGHD,GAAUtB,QAAQwB,OAAOtB,IAAYc,GAErCK,EAAQJ,EAAgBQ,WACxBpB,EAAcqB,WAAWJ,EAAQjB,aACjCC,EAAcoB,WAAWJ,EAAQhB,aAEjCc,EAAS,KACTD,EAAU,KACVD,EAAW,KACXK,EAAS,SAACI,GACR,GAAAC,GAAAC,EAAAC,EAAAC,CAOA,OAPAX,OAAWH,EAAgBQ,WAAWO,OAAO,KAAKC,KAAK,QAAS,QAChEd,MAAYC,EAAOY,OAAO,SAC1Bd,MAAaE,EAAOY,OAAO,QACxBC,KAAK,QAAS,aACdA,KAAK,KAAM,UACXC,MAAM,cAAe,WAEV,MAAAP,GAA2B,IAAjBA,EAAKQ,QAE7BJ,EAASK,KAAKC,IAAIpB,EAAgBqB,WAAYrB,EAAgBsB,aAAa,EAE3EnB,EAAOa,KAAK,YAAa,aAAeF,EAAU,IAAMA,EAAS,KAEjEH,EAAM7B,EAAGyC,IAAIZ,MACVa,YAAYV,GACZ1B,YAAY0B,EAAS1B,GACrBqC,WAAW,GACXC,SAAS,SAACC,GJuDR,MIvDcA,GAAE,IAAM,EAAIR,KAAKS,KAEpChB,EAAW,SAACe,GACV,GAAAE,EJ6DG,OALqB,OAAjBC,KAAKC,WIxDZD,KAACC,SAAY,GACbF,EAAI/C,EAAGkD,YAAYF,KAACC,SAAUJ,GAC9BG,KAACC,SAAWJ,EACZ,SAACM,GJ2DI,MI3DEtB,GAAIkB,EAAEI,MAEfpB,EAAW/B,EAAGyC,IAAIZ,MACfa,YAAYV,EAASzB,GACrBD,YAAY0B,EAASzB,GAExBa,EAAQgC,MAAMxB,EAAKL,EAAQb,QACxBF,aACA6C,KAAK9B,EAAQf,YACb8C,SAAS/B,EAAQd,oBACjB8C,UAAU,IAAKzB,GAElBX,EAASqC,KAAK5B,EAAKL,EAAQZ,SA5B3B,QA8BFO,EAAgBuC,gBAAgBjC,EAAQD,EAAQmC,YJ4D9C,SAASjE,EAAQD,GK7HvBS,QAAQR,OAAO,OAAOS,UAAU,SAAU,WACxC,GAAAC,ELmIC,OKnIDA,GAAW,WLiIR,WK/HHS,SAAU,IACVC,QAAS,WACTE,OACE4C,QAAS,KAEX7C,KAAM,SAAC8C,EAAQC,EAAKC,EAAQ5C,GAE1B,GAAA6C,GAAAC,EAAAC,EAAA1C,EAAAC,EAAApB,EAAAC,CL4OG,OK5OHkB,GAAUtB,QAAQwB,OAAOtB,IAAY2D,GACrC1D,EAAIc,EAAgBgD,SAAS3C,EAAQ4C,QAAU5C,EAAQnB,GACvDC,EAAIa,EAAgBgD,SAAS3C,EAAQ6C,QAAU7C,EAAQlB,GAEpDkB,EAAQ8C,UACTN,EAAO/D,GAAGyC,IAAIsB,OACX1D,EAAE,SAACwC,GLiID,MKjIOzC,GAAEyC,EAAEzC,KACbkE,GAAG,GACHC,GAAG,SAAC1B,GLiIF,MKjIQxC,GAAEwC,EAAExC,KACjB4D,EAAcjE,GAAGyC,IAAIsB,OAClB1D,EAAE,SAACwC,GLkID,MKlIOzC,GAAEyC,EAAEzC,KACbkE,GAAG,SAACzB,GLmIF,MKnIQxC,GAAEwC,EAAE2B,MACdD,GAAG,SAAC1B,GLoIF,MKpIQxC,GAAEwC,EAAExC,EAAIwC,EAAE2B,QAEvBT,EAAO/D,GAAGyC,IAAIsB,OACX3D,EAAE,SAACyC,GLqID,MKrIOzC,GAAEyC,EAAEzC,KACboE,GAAG,WLsID,MKtIItD,GAAgBsB,cACtBiC,GAAG,SAAC5B,GLuIF,MKvIQxC,GAAEwC,EAAExC,KACjB4D,EAAcjE,GAAGyC,IAAIsB,OAClB3D,EAAE,SAACyC,GLwID,MKxIOzC,GAAEyC,EAAEzC,KACboE,GAAG,SAAC3B,GLyIF,MKzIQxC,GAAEwC,EAAE2B,MACdC,GAAG,SAAC5B,GL0IF,MK1IQxC,GAAEwC,EAAExC,EAAIwC,EAAE2B,OAEzBR,EAAc,KACdxC,EAAS,SAACI,GACR,GAAA8C,GAAAf,EAAAgB,EAAAC,EAAAC,EAAAC,EAAApE,CAEA,OAFAsD,OAAgB9C,EAAgBQ,WAAWO,OAAO,KAC/CC,KAAK,QAAS,SACH,MAAAN,GAA2B,IAAjBA,EAAKQ,SACN,MAAAb,EAAAlB,IAAvBsD,EAAUpC,EAAQlB,GACf,MAAAuD,EAAAD,UACDA,EAAUC,EAAOD,SACL,MAAAA,IACX1D,QAAQ8E,SAASpB,KAClBA,EAAUA,EAAQqB,MAAM,KAAKC,IAAI,SAACnF,GLmJ7B,MKnJmCA,GAAEoF,UAChB,IAAlBvB,EAAQvB,UAElBuC,EAAA,WLuJK,GAAIQ,GAAGC,EAAKC,CAEZ,KKzJQA,KAAAF,EAAA,EAAAC,EAAAzB,EAAAvB,OAAAgD,EAAAD,ML0JNP,EAAOjB,EAAQwB,GACfE,EAAQC,MK1JbV,KAAMA,EACNW,OAAA,WL4JS,GAAIC,GAAGC,EAAMC,CAEb,KK9JDA,KAAAF,EAAA,EAAAC,EAAA7D,EAAAQ,OAAAqD,EAAAD,ML+JG9E,EAAQkB,EAAK4D,GACbE,EAASJ,MK/JlBlF,EAAGM,EAAMa,EAAQnB,GACjBC,EAAGK,EAAMkE,ILmKF,OAAOc,OAIb,OAAOL,MKtKZR,EAAQ7E,GAAG2F,OAAOd,QAAQU,OAAO,SAAC1C,GLyK7B,MKzKmCA,GAAE0C,SACV,MAAAhE,EAAAqE,QAAhCf,EAAMe,OAAOrE,EAAQqE,QACrBd,EAAcD,EAAMF,GAEpBD,EAASV,EAAY6B,UAAU,aAAajE,KAAKkD,GACjDJ,EAAOoB,QAAQ7D,OAAO,QACtByC,EAAOxC,KAAK,QAAS,SAACW,GL4KjB,MK5KuB,QAAQA,EAAE+B,OACnCpE,aACA8C,SAAS,KACTpB,KAAK,IAAK,SAACW,EAAEE,GAAM,MAAQ,KAALA,EAAYgB,EAAKlB,EAAE0C,QAAatB,EAAYpB,EAAE0C,UACvEb,EAAOqB,OACJ7D,KAAK,IAAK,SAACW,EAAEE,GAAM,MAAQ,KAALA,EAAYgB,EAAKlB,EAAE0C,QAAatB,EAAYpB,EAAE0C,UACpES,UA1BH,QA4BFpC,EAAOqC,OAAO,UAAW/E,EAAgBM,QAAQ,GACjDN,EAAgBuC,gBAAgBjC,EAAQD,EAAQmC,YL4L9C,SAASjE,EAAQD,GM9PvBS,QAAQR,OAAO,OAAOS,UAAU,UAAW,WAAY,SAACgG,GACtD,GAAA/F,ENyQG,OMzQHA,GAAW,WNmQN,OMlQHgG,YAAa,SACbC,MAAO,IACPC,QAAQ,KAEVC,SAAU,EACV1F,SAAU,IACVC,QAAS,WACTE,OACEwF,iBAAkB,IAClBC,OAAQ,IACRC,WAAY,KAEd3F,KAAM,SAAC8C,EAAQC,EAAKC,EAAQ5C,GAC1B,GAAAwF,GAAAC,EAAAC,EAAAC,EAAAC,EAAAnG,EAAAY,EAAAwF,EAAAC,EAAAxF,EAAAyF,EAAAC,EAAAC,CN4bK,OM5bL5F,GAAUtB,QAAQwB,OAAOtB,IAAY2D,GAErCkD,EAAQ,WACN,MAA0B,QAAvBzF,EAAQ4E,aAA+C,WAAvB5E,EAAQ4E,YACtC,MAAA5E,EAAA6F,SACAlG,EAAgBqB,WAAY,IAE5B,EAAGrB,EAAgBqB,YAEnB,MAAAhB,EAAA6F,SACA,EAAGlG,EAAgBsB,cAEnBtB,EAAgBsB,YAAa,IAEpC0E,EAAc,WACZ,MAA0B,WAAvB3F,EAAQ4E,YACT,gBAAgBjF,EAAgBsB,YAAY,IACf,QAAvBjB,EAAQ4E,YACd,kBAC6B,SAAvB5E,EAAQ4E,YACd,kBAC6B,UAAvB5E,EAAQ4E,YACd,aAAajF,EAAgBqB,WAAW,OADrC,QAIL0E,EADkB,SAAjB1F,EAAQ0F,MACDjH,GAAGqH,KAAKJ,QACV1F,EAAQ0F,MACNjH,GAAGiH,MAAM1F,EAAQ0F,SAEjBjH,GAAGiH,MAAMK,SAEnBT,EAAU,WACR,GAAAU,GAAAC,EAAAC,CNwSK,OMxSLF,GAAOvH,GAAGyC,IAAI8E,OAAON,MAAMA,GAAOS,OAAOnG,EAAQ4E,aAC9C5E,EAAQ6E,OACTmB,EAAKnB,MAAM7E,EAAQ6E,OAClB7E,EAAQoG,WACTJ,EAAKnB,MAAMpG,GAAGqH,KAAK9F,EAAQoG,WAAYpG,EAAQqG,cAC9ChE,EAAO6C,YACRc,EAAKd,WAAW7C,EAAO6C,YACtBlF,EAAQkG,WACTA,EAAWlG,EAAQkG,SAASzC,MAAM,KAClCuC,EAAKM,cAAcJ,EAAS,IAC5BF,EAAKO,cAAcL,EAAS,KAC3B,MAAA7D,EAAA2C,mBAGDiB,EAASxH,GAAGqH,KAAKG,OAAOO,MAAM9H,QAAQ+H,KAAKpE,EAAO2C,mBAClDgB,EAAKU,WAAW,SAACvH,GN6QV,MM7QoB8G,GAAW,GAAAU,MAAKxH,OAC1C,MAAAa,EAAA4G,YACDX,EAASxH,GAAGqH,KAAKG,OAAOjG,EAAQ4G,YAChCZ,EAAKU,WAAW,SAACvH,GNgRV,MMhRoB8G,GAAW,GAAAU,MAAKxH,OACrC,MAAAa,EAAAiG,SACNA,EAASxH,GAAGwH,OAAOjG,EAAQiG,QAC3BD,EAAKU,WAAWT,IAClBD,GAEFR,EAAgB,SAACpG,GACf,MAA0B,WAAvBY,EAAQ4E,YACTxF,EAAMuB,KAAK,IAAK,GAAGhB,EAAgBqB,WAAa,GAC7CL,KAAK,KAAM,GAAGhB,EAAgBkH,OAAOC,QACrCnG,KAAK,QAAS,wBACY,QAAvBX,EAAQ4E,YACdxF,EAAMuB,KAAK,IAAK,GAAGhB,EAAgBqB,WAAa,GAC7CL,KAAK,KAAM,IAAIhB,EAAgBkH,OAAOE,KACtCpG,KAAK,QAAS,wBACY,SAAvBX,EAAQ4E,YACdxF,EAAMuB,KAAK,IAAK,IAAIhB,EAAgBsB,YAAc,GAC/CN,KAAK,KAAM,KAAIhB,EAAgBkH,OAAOG,KAAO,KAC7CrG,KAAK,QAAS,wBACdA,KAAK,YAAa,eACQ,UAAvBX,EAAQ4E,YACdxF,EAAMuB,KAAK,IAAK,GAAGhB,EAAgBsB,YAAc,GAC9CN,KAAK,KAAM,KAAIhB,EAAgBkH,OAAOI,MAAQ,KAC9CtG,KAAK,QAAS,wBACdA,KAAK,YAAa,cAJlB,QAMP0E,EAAW,SAACE,EAAMS,GAChB,MAA0B,WAAvBhG,EAAQ4E,YACTW,EAAKlH,KAAK2H,EAAKE,SAASvG,EAAgBsB,YAAa,EAAG,GACrDyF,WAAW,KAEe,QAAvB1G,EAAQ4E,YACdW,EAAK5E,KAAK,YAAa,gBAAgBhB,EAAgBsB,YAAY,KAChE5C,KAAK2H,EAAKE,SAASvG,EAAgBsB,YAAa,EAAG,GACnDyF,WAAW,KAEe,SAAvB1G,EAAQ4E,YACdW,EAAK5E,KAAK,YAAa,aAAahB,EAAgBqB,WAAW,QAC5D3C,KAAK2H,EAAKE,SAASvG,EAAgBqB,WAAY,EAAG,GAClD0F,WAAW,KAEe,UAAvB1G,EAAQ4E,YACdW,EAAKlH,KAAK2H,EAAKE,SAASvG,EAAgBqB,WAAY,EAAG,GACpD0F,WAAW,KAFX,QAKPvB,EAAmB,SAAC+B,GAClB,GAAAC,GAAAC,EAAAC,CAmBA,OAnBAA,GAAaH,EAAE5C,UAAU,cACtBtE,EAAQsH,QACTD,EAAW1G,KAAK,KAAMX,EAAQsH,QAC7BtH,EAAQuH,QACTF,EAAW1G,KAAK,KAAMX,EAAQuH,QAC7BvH,EAAQwH,YACTH,EAAWzG,MAAM,cAAeZ,EAAQwH,YAC1CJ,EAAiB3I,GAAGgJ,OAAOJ,EAAW,GAAGK,MAAM,IAAI,IAChD1H,EAAQ2H,YACTP,EAAezG,KAAK,KAAMX,EAAQ2H,YACjC3H,EAAQ4H,YACTR,EAAezG,KAAK,KAAMX,EAAQ4H,YACjC5H,EAAQ6H,gBACTT,EAAexG,MAAM,cAAeZ,EAAQ6H,gBAC9CV,EAAkB1I,GAAGgJ,OAAOJ,EAAW,GAAG,IACvCrH,EAAQ8H,aACTX,EAAgBxG,KAAK,KAAMX,EAAQ8H,aAClC9H,EAAQ+H,aACTZ,EAAgBxG,KAAK,KAAMX,EAAQ+H,aAClC/H,EAAQgI,eACTb,EAAgBvG,MAAM,cAAeZ,EAAQiI,iBAD/C,QAGF7C,EAAc,KACdG,EAAO,KACPnG,EAAQ,KAERa,EAAS,SAACI,GACR,GAAA2F,GAAAqB,CAAA,IAAc,MAAAhH,GAA2B,IAAjBA,EAAKQ,ON6RxB,MM3RLuE,OAAgBzF,EAAgBQ,WAAWO,OAAO,KAC/CC,KAAK,QAAS,aAAaX,EAAQ4E,YAAY,SAAQ5E,EAAQqD,MAC/D1C,KAAK,YAAagF,MAClB3F,EAAQZ,QACTA,MAAUgG,EAAY1E,OAAO,QAAQC,KAAK,QAAS,cAAcsB,KAAKjC,EAAQZ,SAC7EY,EAAQuF,OACTA,MAAS5F,EAAgBQ,WAAWO,OAAO,KACxCC,KAAK,QAAS,uBAAuBX,EAAQqD,QAElD2C,EAAOV,IAC4ClG,GAAnDoG,EAAcpG,EAAMH,aAAa8C,SAAS,MAC1CqD,EAAYnG,aAAa8C,SAAS,KAC/BpB,KAAK,YAAagF,KAClBtH,KAAK2H,GACL1B,UAAU,aACR4D,MAAM,UAAW,MACjBA,MAAM,UAAW,MACjBA,MAAM,oBAAqB,MAEmB,MAAA3C,GAAnDF,EAASE,EAAKtG,aAAa8C,SAAS,KAAMiE,GAC1CqB,EAAajC,EAAYd,UAAU,cACnCc,EAAY/G,KAAK8G,IAEnBS,EAAc,SAACvF,GACb,GAAAwB,GAAAsG,CAAA,IAAc,MAAA9H,GAA2B,IAAjBA,EAAKQ,OAQ7B,MAPA6E,GAAMD,MAAMA,KACTzF,EAAQoI,OAGTD,EADC9F,EAAO4C,OACO5C,EAAO4C,OAAO5E,GAE7B,WN2QO,GAAImB,GAAGqC,EAAKC,CAEZ,KM7QSA,KAAAtC,EAAA,EAAAqC,EAAAxD,EAAAQ,OAAAgD,EAAArC,MN8QPK,EAAQxB,EAAKmB,GACbsC,EAAQC,KM/QDlC,EAAM7B,EAAQqD,MNiRvB,OAAOS,MMhRb9D,EAAQ8E,OACTY,EAAM0C,OAAO3J,GAAGqG,OAAOqD,IAEvBzC,EAAM0C,QAAQ,EAAG3J,GAAG4J,IAAIF,MAE5BxI,EAAgB2I,SAAStI,EAAQqD,KAAMqC,EAAOE,GAC9CjG,EAAgBuC,gBAAgBjC,EAAQD,EAAQmC,OAChDE,EAAOkG,iBAAiB,aAAc5I,EAAgBM,QACtDoC,EAAOkG,iBAAiB,mBAAoB5I,EAAgBM,QAC5DoC,EAAOqC,OAAO,SAAU/E,EAAgBM,QACxCoC,EAAOqC,OAAO,aAAc/E,EAAgBM,cN6R1C,SAAS/B,EAAQD,GOpdvBS,QAAQR,OAAO,OAAOS,UAAU,SAAU,WACxC,GAAAC,EP8dC,OO9dDA,GAAW,WPwdR,OOvdDC,EAAG,EACHC,EAAG,EACH0J,MAAO,MAETnJ,SAAU,IAEVC,QAAS,WAETC,KAAM,SAACC,EAAOC,EAAIC,EAAOC,GACvB,GAAA8I,GAAA1I,EAAA2I,EAAA1I,EAAAC,EAAAuI,EAAA3J,EAAAC,CP6fG,OO7fHkB,GAAUtB,QAAQwB,OAAOtB,IAAYc,GACrCb,EAAIc,EAAgBgD,SAAS3C,EAAQ4C,QAAU5C,EAAQnB,GACvDC,EAAIa,EAAgBgD,SAAS3C,EAAQ6C,QAAU7C,EAAQlB,GAEvDiB,EAAQJ,EAAgBQ,WACxBuI,EAAS/I,EAAgBsB,YACzBuH,EAAQxI,EAAQwI,MAEhBC,EAAe,KACfxI,EAAS,SAACI,GACR,GAAAsI,EAEA,OAFAF,OAAiB9I,EAAgBQ,WAAWO,OAAO,KAChDC,KAAK,QAAS,SACH,MAAAN,GAA2B,IAAjBA,EAAKQ,QAC7B8H,EAAOF,EAAanE,UAAU,YAAYjE,KAAKA,GAC/CsI,EAAKnE,OAAOvF,aAAa8C,SAAS,KAC/BpB,KAAK,IAAK,WPydR,MOzdWhB,GAAgBsB,cAC7BN,KAAK,SAAU,GACf8D,SACHkE,EAAK1J,aAAa8C,SAAS,KACxBpB,KAAK,IAAK,SAACW,GPwdT,MOxdezC,GAAEyC,EAAEtB,EAAQnB,IAAM2J,EAAM,IACzC7H,KAAK,IAAK,SAACW,GPydT,MOzdexC,GAAEwC,EAAEtB,EAAQlB,MAC7B6B,KAAK,SAAU,SAACW,GP0dd,MO1doB3B,GAAgBsB,YAAcnC,EAAEwC,EAAEtB,EAAQlB,MAChE6B,KAAK,QAAS6H,GACjBG,EAAKpE,QACF7D,OAAO,QACPC,KAAK,QAAS,SAACW,EAAEE,GPydf,MOzdqB,WAAWA,IAClCb,KAAK,IAAK,SAACW,GP0dT,MO1dezC,GAAEyC,EAAEtB,EAAQnB,IAAM2J,EAAM,IACzC7H,KAAK,QAAS6H,GACd7H,KAAK,IAAK,WP0dR,MO1dWhB,GAAgBsB,cAC7BN,KAAK,SAAU,GACf1B,aAAa8C,SAAS,KACtBpB,KAAK,IAAK,SAACW,GPydT,MOzdexC,GAAEwC,EAAEtB,EAAQlB,MAC7B6B,KAAK,SAAU,SAACW,GP0dd,MO1doB3B,GAAgBsB,YAAcnC,EAAEwC,EAAEtB,EAAQlB,OApBnE,QAsBFa,EAAgBuC,gBAAgBjC,EAAQD,EAAQmC,YPme9C,SAASjE,EAAQD,GQhhBvBS,QAAQR,OAAO,OAAOS,UAAU,UAAW,WRmhBxC,OQlhBDU,SAAU,KACVG,OACEqH,OAAQ,IACRxG,KAAM,KAERuI,YAAa,SAAU,WAAY,SAAU,UAAW,WACxD,SAACvG,EAAQC,EAAKC,EAAQsG,EAASC,GAC7B,GAAA/I,GAAAgJ,EAAAC,EAAAN,EAAAO,EAAAC,EAAAhI,EAAAiI,EAAAX,CAAAS,GAAS5G,EAAO4G,UAChBD,EAAW3G,EAAO2G,YAElBvH,KAACoF,OAASxE,EAAOwE,SAAYE,IAAK,GAAIE,MAAO,GAAIH,OAAQ,GAAIE,KAAM,IACnE9F,EAAMzC,GAAGgJ,OAAOnF,EAAI,IAAI5B,OAAO,OAAOC,KAAK,QAAS,MACjDA,KAAK,QAAS,QACdA,KAAK,SAAU,QAGlB6H,EAAQ,WRqhBD,MQrhBIlG,GAAI,GAAG8G,aAClBV,EAAS,WRuhBF,MQvhBKpG,GAAI,GAAG+G,cAEnBtJ,EAAQmB,EAAIR,OAAO,KAChBC,KAAK,YAAa,aAAec,KAACoF,OAAOG,KAAO,IAAMvF,KAACoF,OAAOE,IAAM,KAEvEtF,KAAC6H,OAAS,WRshBH,MQthBMpI,IACbO,KAACtB,SAAW,WRwhBL,MQxhBQJ,IACf0B,KAAC6G,SAAW,SAACjF,EAAMqC,EAAO6D,GR0hBnB,MQ1hB8BN,GAAO5F,IAAUqC,MAAOA,EAAO6D,OAAQA,IAC5E9H,KAACkB,SAAW,SAACU,GR+hBN,MQ/hBe4F,GAAO5F,GAAMqC,OACnCjE,KAACS,gBAAkB,SAACzC,EAAI0C,GRoiBjB,MAHa,OAATA,IQjiBaA,EAAQ,GAAM6G,EAASjF,MAAO9D,OAAQR,EAAI0C,MAAOqH,OAAOrH,MAEhFgH,EAAa,SAAAM,GRwiBN,MQxiBM,YACX,MAAGA,GAACjB,QAASA,KAAWiB,EAACf,SAAUA,KACjCe,EAACjB,MAAQA,IACTiB,EAACf,OAASA,IACVe,EAACzI,WAAayI,EAACjB,MAAQiB,EAAC5C,OAAOG,KAAOyC,EAAC5C,OAAOI,MAC9CwC,EAACxI,YAAcwI,EAACf,OAASe,EAAC5C,OAAOE,IAAM0C,EAAC5C,OAAOC,OAE/C2C,EAACxJ,UANH,SADWwB,MASbyH,EAAY,SAACQ,EAAGC,GR0iBT,MQ1iBeD,GAAEvH,MAAQwH,EAAExH,OAClC4G,EAAW,KACXtH,KAACxB,OAAS,SAAAwJ,GR4iBH,MQ5iBG,YAER,MAAUV,IAAsB,IAAVU,EAACjB,OAAyB,IAAXiB,EAACf,OAAtC,OACAK,EAAWD,EAAS,WAClB,GAAAzI,GAAAuJ,EAAApI,EAAAqC,EAAAR,EAAAwG,EAAA/F,EAAA4B,CAAAqD,GAAW,KACX1I,EAAOgC,EAAOhC,IACd,KAAAgD,IAAA4F,GR+iBSvD,EAAQuD,EAAO5F,GQ9iBtBqC,EAAM6D,OAAOlJ,ERmjBR,KQljBPwJ,EAAAb,EAAAc,KAAAZ,GAAApF,KAAAtC,EAAA,EAAAqC,EAAAgG,EAAAhJ,OAAAgD,EAAArC,MRmjBSoI,EAAUC,EAAIrI,GACdsC,EAAQC,KQnjBf6F,EAAQ3J,OAAOI,GRqjBV,OAAOyD,IQpjBdvB,EAAOwH,gBAAkB,OAVnBtI,MAYVoH,EAAQmB,iBAAiB,SAAUb,GAEhB,SAAhB5G,EAAO0H,MACR5H,EAAOqC,OAAO,OAAQjD,KAACxB,QAAQ,GAE/BoC,EAAOqC,OAAO,OAAQjD,KAACxB,QAKzBoC,EAAOqC,OAAOyE,GAEdA,UR0jBE,SAASjL,EAAQD,GS1nBvBS,QAAQR,OAAO,OAAOS,UAAU,UAAU,YAAa,SAACF,GT8nBnD,OS7nBHY,SAAU,IACVG,OACE0K,SAAU,IACVC,SAAU,IACV9J,KAAM,KACRd,KAAM,SAAC8C,EAAQC,EAAKC,GAClB,GAAA6H,ETioBK,OSjoBLA,GAAM7H,EAAO6H,IACb3L,EAAG4L,IAAID,EAAK/H,EAAO6H,SAAU7H,EAAO8H,UAAUG,KAAK,SAACC,GTioB7C,MShoBLlI,GAAOhC,KAAOkK,GACd,WAAG,KAAM,mCT2oBT,SAASrM,EAAQD,GUrpBvBS,QAAQR,OAAO,OAAOS,UAAU,aAAc,WAC5C,GAAAC,EV2pBC,OU3pBDA,IAAaK,WAAY,MAEzBI,SAAU,IACVC,QAAS,WAETC,KAAM,SAAC8C,EAAQC,EAAKC,EAAQ5C,GAC1B,GAAA6K,GAAAtJ,EAAAjC,CVuqBG,OUvqBHiC,GAAMvB,EAAgB2J,SAEtBkB,EAAWtJ,EAAIuJ,OAAO,OAAQ,KAC3B/J,OAAO,kBACPC,KAAK,KAAM4B,EAAOsH,MAEpB,KAAM,KAAM,KAAM,MAAMa,QAAQ,SAAC/J,GVupB7B,MUtpBH4B,GAAOoI,SAAShK,EAAM,SAACiK,GVupBlB,MUvpB0BJ,GAAS7J,KAAKA,EAAMiK,OAErD3L,EAAaL,EAASK,WACtBsD,EAAOoI,SAAS,aAAc,SAACC,GAAQ,MAAoB,OAAAA,EAApB3L,EAAa2L,EAAb,SAEvCvI,EAAOqC,OAAOnC,EAAOsI,MAAO,SAACA,GAC3B,MAAc,OAAAA,GACdA,EAAQL,EAASlG,UAAU,QAAQjE,KAAKwK,GACxCA,EAAMtG,QAAQ7D,OAAO,QACrBmK,EAAMlK,KAAK,SAAU,SAACW,GV8pBjB,MU9pBuBA,GAAE+C,SAC3B1D,KAAK,aAAc,SAACW,GV+pBlB,MU/pBwBA,GAAEwJ,QAC5BnK,KAAK,eAAgB,SAACW,GAAM,MAAG,OAAAA,EAAAyJ,QAAgBzJ,EAAEyJ,QAAa,IACjEF,EAAMrG,OAAOC,UANb,cVorBA,SAASvG,EAAQD,GWjsBvBS,QAAQR,OAAO,OAAOS,UAAU,YAAa,WXosB1C,OWnsBDU,SAAU,IACVC,QAAS,WACTC,KAAM,SAAC8C,EAAQC,EAAKC,EAAQ5C,GAC1B,GAAAI,GAAAiL,CXusBG,OWvsBHjL,GAAQJ,EAAgBQ,WACxB6K,EAAWjL,EAAMW,OAAO,KAAKC,KAAK,QAAS,YAC3CqK,EAASC,KAAK3I,EAAI2I,aX6sBhB,SAAS/M,EAAQD,GY1tBvBS,QAAQR,OAAO,OAAOS,UAAU,SAAU,WACxC,GAAAC,EZmuBC,OYnuBDA,GAAW,WZ8tBR,OY7tBDC,EAAG,EACHC,EAAG,KAELO,SAAU,IAEVC,QAAS,WAETC,KAAM,SAACC,EAAOC,EAAIC,EAAOC,GACvB,GAAAuL,GAAAC,EAAAnL,EAAAC,EAAApB,EAAAC,CZ+uBG,OY/uBHkB,GAAUtB,QAAQwB,OAAOtB,IAAYc,GACrCb,EAAIc,EAAgBgD,SAAS3C,EAAQ4C,QAAU5C,EAAQnB,GACvDC,EAAIa,EAAgBgD,SAAS3C,EAAQ6C,QAAU7C,EAAQlB,GAEvDoM,EAAOzM,GAAGyC,IAAIgK,OACXrM,EAAE,SAACyC,GZ8tBD,MY9tBOzC,GAAEyC,EAAEtB,EAAQnB,MACrBC,EAAE,SAACwC,GZ+tBD,MY/tBOxC,GAAEwC,EAAEtB,EAAQlB,MAExBqM,EAAW,KACXlL,EAAS,SAACI,GAMR,MALA8K,OAAaxL,EAAgBQ,WAAWO,OAAO,QAC5CC,KAAK,QAAS,cAAaX,EAAQqD,MAAQrD,EAAQlB,IACnD8B,MAAM,OAAQ,QACdA,MAAM,SAAUZ,EAAQoL,SAEb,MAAA/K,GAA2B,IAAjBA,EAAKQ,OAC7BsK,EAAStJ,MAAMxB,GACZpB,aACA8C,SAAS,KACTpB,KAAK,IAAKuK,GAJb,QAMFvL,EAAgBuC,gBAAgBjC,EAAQD,EAAQmC,YZkuB9C,SAASjE,EAAQD,GajwBvBS,QAAQR,OAAO,OAAOS,UAAU,QAAS,WACvC,GAAAC,EbgxBC,OahxBDA,GAAW,WbqwBR,OapwBDC,EAAG,EACHC,EAAG,EACHC,YAAa,EACbC,YAAa,GACbC,WAAY,eACZC,mBAAoB,IACpBmM,UAAW,GACXlM,MAAO,WAETE,SAAU,IAEVC,QAAS,WAETC,KAAM,SAACC,EAAOC,EAAIC,EAAOC,GACvB,GAAA+B,GAAA5B,EAAAC,EAAAuL,EAAAvM,EAAAC,EAAAgB,EAAAuL,EAAAtL,Cb+2BG,Oa/2BHD,GAAUtB,QAAQwB,OAAOtB,IAAYc,GAErCK,EAAQJ,EAAgBQ,WACxBpB,EAAcqB,WAAWJ,EAAQjB,aACjCC,EAAcoB,WAAWJ,EAAQhB,aAE9BU,EAAM8L,SACPF,EAAA,WAAa,OAAO5L,EAAM8L,QAAb,IACN,abswBE,MarwBL/M,IAAGiH,MAAM+F,YAFA,KAGN,cbswBE,MarwBLhN,IAAGiH,MAAMgG,aAJA,KAKN,cbswBE,MarwBLjN,IAAGiH,MAAMiG,mBAEfJ,EAAM9M,GAAG2F,OAAOmH,MAAMzB,KAAK,MACxB3K,MAAM,SAACmC,GbuwBL,MavwBWA,GAAEtB,EAAQb,SAE1BuC,EAAW,KAEX5B,EAAS,KACTG,EAAS,SAACI,GACR,GAAAC,GAAAC,EAAAqL,EAAAxM,EAAAoB,EAAAqL,EAAAC,EAAArL,EAAAiH,CAEA,OAFA5H,OAAWH,EAAgBQ,WAAWO,OAAO,KAAKC,KAAK,QAAS,QAElD,MAAAN,GAA2B,IAAjBA,EAAKQ,QAE7BJ,EAASK,KAAKC,IAAIpB,EAAgBqB,WAAYrB,EAAgBsB,aAAa,EAE3EnB,EAAOa,KAAK,YAAa,aAAeF,EAAS,IAAMA,EAAS,KAEhEH,EAAM7B,GAAGyC,IAAIZ,MACVa,YAAYV,GACZ1B,YAAY0B,EAAS1B,GAExBwB,EAAW,SAACmJ,GACV,GAAAlI,EbqwBG,OarwBHA,GAAI/C,GAAGkD,YAAYF,KAACC,SAAUgI,GAC9BjI,KAACC,SAAWF,EAAE,GACd,SAACI,GbowBI,MapwBEtB,GAAIkB,EAAEI,MAEfpB,EAAW/B,GAAGyC,IAAIZ,MACfa,YAAYV,EAASzB,GACrBD,YAAY0B,EAASzB,GAExB0I,EAAQ5H,EAAOwE,UAAU,QAAQjE,KAAKkL,EAAIlL,IAE1CqH,EAAMnD,QAAQ7D,OAAO,QAClBC,KAAK,QAAS,SAACW,EAAEE,GbiwBf,MajwBsB,WAAWA,IACnCb,KAAK,IAAKL,GACVyL,KAAK,SAACzK,GbiwBJ,MajwBUG,MAACC,SAAWJ,IAGgC5B,EAAM8L,QADjE9D,EAAM9G,MAAM,OAAQ,SAACU,EAAEE,GACrB,MAAG8J,GAAgBA,EAAW9J,GAAQF,EAAE5B,EAAMoL,SAEhDpD,EAAMlD,OAAOC,SAEbiD,EAAMzI,aACH6C,KAAK9B,EAAQf,YACb8C,SAAS/B,EAAQd,oBACjB8C,UAAU,IAAKzB,GAEfP,EAAQZ,OACT0M,EAAS,KACTD,GAAW7L,EAAQqL,UACnBO,EAAc,SAACtK,EAAGE,GAChB,GAAAwK,GAAAC,EAAAC,EAAAC,EAAA9H,EAAA+H,EAAAC,EAAAC,EAAAC,CbkyBG,OalyBHF,GAAW7L,EAASgM,SAASlL,GAE1BtB,EAAQyM,kBAITH,GAAoBD,EAAS,GAAIA,EAAS,IACvC5K,KAACiL,YACFJ,EAAiB,IAAM7K,KAACiL,UAAU,GAClCJ,EAAiB,IAAM7K,KAACiL,UAAU,IAGpCH,EAASI,EAAEC,UAAUnL,KAACoL,wBAAyB,SAACC,EAAGC,EAAG9I,GACpD,OAAOA,GAAP,IACO,Ob+vBA,Ma9vBH6I,GAAE7I,GAAK8I,EAAIlB,EAAUS,EAAiB,EAF1C,KAGO,Mb+vBA,Ma9vBHQ,GAAE7I,GAAK8I,EAAIlB,EAAUS,EAAiB,EAJ1C,KAKO,Qb+vBA,Ma9vBHQ,GAAE7I,GAAK8I,EAAIlB,EAAUS,EAAiB,EAN1C,KAOO,Sb+vBA,Ma9vBHQ,GAAE7I,GAAK8I,EAAIlB,EAAUS,EAAiB,MAEzCR,KACDS,EAAOtF,MAAQ6E,EAAO9E,MACtBuF,EAAOvF,KAAO8E,EAAO7E,OACrBsF,EAAOzF,OAASgF,EAAO/E,KACvBwF,EAAOxF,IAAM+E,EAAOhF,UACpBoF,EAAMK,EAAOvF,MAAQuF,EAAOtF,MAAQsF,EAAOvF,MAAM,EACjDmF,EAAMI,EAAOxF,KAAOwF,EAAOzF,OAASyF,EAAOxF,KAAK,EAChDiF,EAAMF,EAAO9E,MAAQ8E,EAAO7E,MAAQ6E,EAAO9E,MAAM,EACjDiF,EAAMH,EAAO/E,KAAO+E,EAAOhF,OAASgF,EAAO/E,KAAK,EAChD1C,EAASvD,KAAKkM,KAAKlM,KAAKmM,IAAIf,EAAMF,EAAK,GAAKlL,KAAKmM,IAAId,EAAMF,EAAK,IAAI,EACpEG,EAAY3N,GAAGyC,IAAIZ,MAChBa,YAAYV,EAASzB,EAAcqF,GACnCtF,YAAY0B,EAASzB,EAAcqF,GACtCgI,EAAWD,EAAUI,SAASlL,IAEhCG,KAACiL,UAAYL,EACbP,EAASS,GAEX,aAAaF,EAAS,KAExBjN,EAAQU,EAAOwE,UAAU,QAAQjE,KAAKkL,EAAIlL,IAE1CjB,EAAMmF,QAAQ7D,OAAO,QAClBE,MAAM,cAAe,UACrBD,KAAK,QAAS,SAACW,EAAEE,GbuvBf,MavvBqB,uBAAuBA,IAEjDpC,EAAMoF,OAAOC,SAEbrF,EAAM6C,KAAK,SAACX,EAAEE,GbuvBT,MavvBenB,GAAKmB,GAAGxB,EAAQZ,SAEpCA,EAAMH,aACH6C,KAAK9B,EAAQf,YACb8C,SAAS/B,EAAQd,oBACjByB,KAAK,YAAaiL,IA5DvB,QApCA,QAkGFjM,EAAgBuC,gBAAgBjC,EAAQD,EAAQmC,Yb6vB9C,SAASjE,EAAQD,EAASH,Gcv4BhC,GAAAY,KAAUZ,EAAQ,IAElBY,EAAQR,OAAO,UAEfJ,EAAQ,IACRA,EAAQ,IACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,GACRA,EAAQ,IACRA,EAAQ,Kd25BF,SAASI,EAAQD,EAASH,Ge16BhC,GAAAW,KAAKX,EAAQ,GAebY,QAAQR,OAAO,OAAOgP,SAAS,WAAY,WACzC,GAAAC,Ef47BC,Oe57BDA,MAEA1L,KAAC2L,WAAa,SAACC,Gfk6BZ,Mej6BDF,GAAoBE,GAEtB5L,KAAC6L,KAAO,WACN,GAAAC,EAIA,OAJAA,GAAe,SAACC,Gfo6Bb,Men6BD/O,GAAGwH,OAASuH,EAAOC,aACnBhP,EAAGqH,KAAKG,OAASuH,EAAO5G,aAGxB8G,QAAS,SAACC,GACR,GAAAC,GAAAC,EAAAL,CAAA,Kfq6BG,Mep6BDA,GAAS/O,EAAG+O,OAAOL,EAAkBQ,EAAKG,gBAC1CP,EAAaC,GAFf,MAAAK,GAIE,KADID,GAAAC,EACE,oBAAoBF,EAAK,+EAEnCI,UAAW,SAACP,Gfs6BT,Mer6BDD,GAAa9O,EAAG+O,OAAOA,OAG7B/L,Qf46BI,SAASvD,EAAQD,EAASH,GgBl9BhC,GAAAW,KAAKX,EAAQ,GAEbY,QAAQR,OAAO,OAAOgP,SAAS,YAAa,WAC1C,GAAAtO,EhBy/BC,OgBz/BDA,GAAW6C,KAAC7C,YAEZ6C,KAAC6L,MAAQ,gBAAiB,aAAc,KAAM,SAACU,EAAeC,EAAYC,GACxE,GAAAC,EhBy9BG,OgBz9BHA,GAAQvP,EAASuP,OAASH,EAAc,cAExC3D,IAAK,SAACD,EAAKF,EAAUC,GACnB,GAAAiE,GAAAC,CAaA,OAbAA,GAAWH,EAAGI,QACdF,EAASD,EAAMI,IAAInE,GAChBgE,IACiBjE,GAAlBA,EAASI,MACT8D,EAASG,QAAQJ,IACnB3P,EAAG4L,IAAID,EAAKF,EAAU,SAACK,GhB69BhB,MgB59BL0D,GAAWQ,OAAO,WAEhB,MADkBtE,IAAlBA,EAASI,GACNA,GACD4D,EAAMO,IAAItE,EAAKG,GACf8D,EAASG,QAAQjE,IAEjB8D,EAASM,aACRN,EAASO,YAGpBnN,QhBy+BI,SAASvD,EAAQD,GiBlgCvBC,EAAAD,QAAAS","file":"angularD3.js","sourcesContent":["/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t__webpack_require__(12)\n\n\n/***/ },\n/* 1 */\n/***/ function(module, exports) {\n\n\tmodule.exports = d3;\n\n/***/ },\n/* 2 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar d3;\n\t\n\td3 = __webpack_require__(1);\n\t\n\tangular.module('ad3').directive('d3Arc', function() {\n\t var defaults;\n\t defaults = function() {\n\t return {\n\t x: 0,\n\t y: 1,\n\t innerRadius: 0,\n\t labelRadius: 0,\n\t transition: \"cubic-in-out\",\n\t transitionDuration: 1000,\n\t value: 'value',\n\t label: 'label'\n\t };\n\t };\n\t return {\n\t restrict: 'E',\n\t require: '^d3Chart',\n\t link: function(scope, el, attrs, chartController) {\n\t var arcLabel, arcPath, center, chart, innerRadius, labelRadius, options, redraw;\n\t options = angular.extend(defaults(), attrs);\n\t chart = chartController.getChart();\n\t innerRadius = parseFloat(options.innerRadius);\n\t labelRadius = parseFloat(options.labelRadius);\n\t center = null;\n\t arcPath = null;\n\t arcLabel = null;\n\t redraw = function(data) {\n\t var arc, arcTween, labelArc, radius;\n\t center || (center = chartController.getChart().append(\"g\").attr(\"class\", \"arc\"));\n\t arcPath || (arcPath = center.append(\"path\"));\n\t arcLabel || (arcLabel = center.append(\"text\").attr(\"class\", \"arc-label\").attr(\"dy\", \"0.35em\").style(\"text-anchor\", \"middle\"));\n\t if (!((data != null) && data.length !== 0)) {\n\t return;\n\t }\n\t radius = Math.min(chartController.innerWidth, chartController.innerHeight) / 2;\n\t center.attr(\"transform\", \"translate(\" + radius + \",\" + radius + \")\");\n\t arc = d3.svg.arc().outerRadius(radius).innerRadius(radius * innerRadius).startAngle(0).endAngle(function(d) {\n\t return d / 100 * 2 * Math.PI;\n\t });\n\t arcTween = function(d) {\n\t var i;\n\t if (this._current == null) {\n\t this._current = 0;\n\t }\n\t i = d3.interpolate(this._current, d);\n\t this._current = d;\n\t return function(t) {\n\t return arc(i(t));\n\t };\n\t };\n\t labelArc = d3.svg.arc().outerRadius(radius * labelRadius).innerRadius(radius * labelRadius);\n\t arcPath.datum(data[options.value]).transition().ease(options.transition).duration(options.transitionDuration).attrTween(\"d\", arcTween);\n\t return arcLabel.text(data[options.label]);\n\t };\n\t return chartController.registerElement(redraw, options.order);\n\t }\n\t };\n\t});\n\n\n/***/ },\n/* 3 */\n/***/ function(module, exports) {\n\n\tangular.module('ad3').directive('d3Area', function() {\n\t var defaults;\n\t defaults = function() {\n\t return {};\n\t };\n\t return {\n\t restrict: 'E',\n\t require: '^d3Chart',\n\t scope: {\n\t columns: '='\n\t },\n\t link: function($scope, $el, $attrs, chartController) {\n\t var area, areaElement, areaStacked, options, redraw, x, y;\n\t options = angular.extend(defaults(), $attrs);\n\t x = chartController.getScale(options.xscale || options.x);\n\t y = chartController.getScale(options.yscale || options.y);\n\t if (options.vertical) {\n\t area = d3.svg.area().y(function(d) {\n\t return x(d.x);\n\t }).x0(0).x1(function(d) {\n\t return y(d.y);\n\t });\n\t areaStacked = d3.svg.area().y(function(d) {\n\t return x(d.x);\n\t }).x0(function(d) {\n\t return y(d.y0);\n\t }).x1(function(d) {\n\t return y(d.y + d.y0);\n\t });\n\t } else {\n\t area = d3.svg.area().x(function(d) {\n\t return x(d.x);\n\t }).y0(function() {\n\t return chartController.innerHeight;\n\t }).y1(function(d) {\n\t return y(d.y);\n\t });\n\t areaStacked = d3.svg.area().x(function(d) {\n\t return x(d.x);\n\t }).y0(function(d) {\n\t return y(d.y0);\n\t }).y1(function(d) {\n\t return y(d.y + d.y0);\n\t });\n\t }\n\t areaElement = null;\n\t redraw = function(data) {\n\t var charts, columns, mappedData, name, stack, stackedData, value;\n\t areaElement || (areaElement = chartController.getChart().append(\"g\").attr(\"class\", \"area\"));\n\t if (!((data != null) && data.length !== 0)) {\n\t return;\n\t }\n\t if (options.y != null) {\n\t columns = options.y;\n\t }\n\t if ($scope.columns != null) {\n\t columns = $scope.columns;\n\t }\n\t if (columns == null) {\n\t return;\n\t }\n\t if (angular.isString(columns)) {\n\t columns = columns.split(',').map(function(c) {\n\t return c.trim();\n\t });\n\t }\n\t if (columns.length === 0) {\n\t return;\n\t }\n\t mappedData = (function() {\n\t var j, len, results;\n\t results = [];\n\t for (j = 0, len = columns.length; j < len; j++) {\n\t name = columns[j];\n\t results.push({\n\t name: name,\n\t values: (function() {\n\t var k, len1, results1;\n\t results1 = [];\n\t for (k = 0, len1 = data.length; k < len1; k++) {\n\t value = data[k];\n\t results1.push({\n\t x: value[options.x],\n\t y: value[name]\n\t });\n\t }\n\t return results1;\n\t })()\n\t });\n\t }\n\t return results;\n\t })();\n\t stack = d3.layout.stack().values(function(d) {\n\t return d.values;\n\t });\n\t if (options.offset != null) {\n\t stack.offset(options.offset);\n\t }\n\t stackedData = stack(mappedData);\n\t charts = areaElement.selectAll('path.area').data(stackedData);\n\t charts.enter().append(\"path\");\n\t charts.attr(\"class\", function(d) {\n\t return \"area \" + d.name;\n\t }).transition().duration(500).attr(\"d\", function(d, i) {\n\t if (i === 0) {\n\t return area(d.values);\n\t } else {\n\t return areaStacked(d.values);\n\t }\n\t });\n\t return charts.exit().attr(\"d\", function(d, i) {\n\t if (i === 0) {\n\t return area(d.values);\n\t } else {\n\t return areaStacked(d.values);\n\t }\n\t }).remove();\n\t };\n\t $scope.$watch('columns', chartController.redraw, true);\n\t return chartController.registerElement(redraw, options.order);\n\t }\n\t };\n\t});\n\n\n/***/ },\n/* 4 */\n/***/ function(module, exports) {\n\n\tangular.module('ad3').directive('d3Axis', [\n\t 'd3locale', function(d3locale) {\n\t var defaults;\n\t defaults = function() {\n\t return {\n\t orientation: 'bottom',\n\t ticks: '5',\n\t extent: false\n\t };\n\t };\n\t return {\n\t priority: 1,\n\t restrict: 'E',\n\t require: '^d3Chart',\n\t scope: {\n\t customTimeFormat: '=',\n\t filter: '=',\n\t tickValues: '='\n\t },\n\t link: function($scope, $el, $attrs, chartController) {\n\t var adjustTickLabels, axisElement, drawGrid, getAxis, grid, label, options, positionLabel, range, redraw, scale, translation, updateScale;\n\t options = angular.extend(defaults(), $attrs);\n\t range = function() {\n\t if (options.orientation === 'top' || options.orientation === 'bottom') {\n\t if (options.reverse != null) {\n\t return [chartController.innerWidth, 0];\n\t } else {\n\t return [0, chartController.innerWidth];\n\t }\n\t } else {\n\t if (options.reverse != null) {\n\t return [0, chartController.innerHeight];\n\t } else {\n\t return [chartController.innerHeight, 0];\n\t }\n\t }\n\t };\n\t translation = function() {\n\t if (options.orientation === 'bottom') {\n\t return \"translate(0, \" + chartController.innerHeight + \")\";\n\t } else if (options.orientation === 'top') {\n\t return \"translate(0, 0)\";\n\t } else if (options.orientation === 'left') {\n\t return \"translate(0, 0)\";\n\t } else if (options.orientation === 'right') {\n\t return \"translate(\" + chartController.innerWidth + \", 0)\";\n\t }\n\t };\n\t if (options.scale === 'time') {\n\t scale = d3.time.scale();\n\t } else if (options.scale) {\n\t scale = d3.scale[options.scale]();\n\t } else {\n\t scale = d3.scale.linear();\n\t }\n\t getAxis = function() {\n\t var axis, format, tickSize;\n\t axis = d3.svg.axis().scale(scale).orient(options.orientation);\n\t if (options.ticks) {\n\t axis.ticks(options.ticks);\n\t }\n\t if (options.timeScale) {\n\t axis.ticks(d3.time[options.timeScale], options.timeInterval);\n\t }\n\t if ($scope.tickValues) {\n\t axis.tickValues($scope.tickValues);\n\t }\n\t if (options.tickSize) {\n\t tickSize = options.tickSize.split(',');\n\t axis.innerTickSize(tickSize[0]);\n\t axis.outerTickSize(tickSize[1]);\n\t }\n\t if ($scope.customTimeFormat != null) {\n\t format = d3.time.format.multi(angular.copy($scope.customTimeFormat));\n\t axis.tickFormat(function(value) {\n\t return format(new Date(value));\n\t });\n\t }\n\t if (options.timeFormat != null) {\n\t format = d3.time.format(options.timeFormat);\n\t axis.tickFormat(function(value) {\n\t return format(new Date(value));\n\t });\n\t } else if (options.format != null) {\n\t format = d3.format(options.format);\n\t axis.tickFormat(format);\n\t }\n\t return axis;\n\t };\n\t positionLabel = function(label) {\n\t if (options.orientation === 'bottom') {\n\t return label.attr(\"x\", \"\" + (chartController.innerWidth / 2)).attr(\"dy\", \"\" + chartController.margin.bottom).attr(\"style\", \"text-anchor: middle;\");\n\t } else if (options.orientation === 'top') {\n\t return label.attr(\"x\", \"\" + (chartController.innerWidth / 2)).attr(\"dy\", \"\" + (-chartController.margin.top)).attr(\"style\", \"text-anchor: middle;\");\n\t } else if (options.orientation === 'left') {\n\t return label.attr(\"x\", \"-\" + (chartController.innerHeight / 2)).attr(\"dy\", \"\" + (-chartController.margin.left + 18)).attr(\"style\", \"text-anchor: middle;\").attr(\"transform\", \"rotate(-90)\");\n\t } else if (options.orientation === 'right') {\n\t return label.attr(\"x\", \"\" + (chartController.innerHeight / 2)).attr(\"dy\", \"\" + (-chartController.margin.right + 18)).attr(\"style\", \"text-anchor: middle;\").attr(\"transform\", \"rotate(90)\");\n\t }\n\t };\n\t drawGrid = function(grid, axis) {\n\t if (options.orientation === 'bottom') {\n\t return grid.call(axis.tickSize(chartController.innerHeight, 0, 0).tickFormat(''));\n\t } else if (options.orientation === 'top') {\n\t return grid.attr(\"transform\", \"translate(0, \" + chartController.innerHeight + \")\").call(axis.tickSize(chartController.innerHeight, 0, 0).tickFormat(''));\n\t } else if (options.orientation === 'left') {\n\t return grid.attr(\"transform\", \"translate(\" + chartController.innerWidth + \", 0)\").call(axis.tickSize(chartController.innerWidth, 0, 0).tickFormat(''));\n\t } else if (options.orientation === 'right') {\n\t return grid.call(axis.tickSize(chartController.innerWidth, 0, 0).tickFormat(''));\n\t }\n\t };\n\t adjustTickLabels = function(g) {\n\t var firstTickLabels, lastTickLabels, tickLabels;\n\t tickLabels = g.selectAll('.tick text');\n\t if (options.tickDy) {\n\t tickLabels.attr('dy', options.tickDy);\n\t }\n\t if (options.tickDx) {\n\t tickLabels.attr('dx', options.tickDx);\n\t }\n\t if (options.tickAnchor) {\n\t tickLabels.style('text-anchor', options.tickAnchor);\n\t }\n\t lastTickLabels = d3.select(tickLabels[0].slice(-1)[0]);\n\t if (options.lastTickDy) {\n\t lastTickLabels.attr('dy', options.lastTickDy);\n\t }\n\t if (options.lastTickDx) {\n\t lastTickLabels.attr('dx', options.lastTickDx);\n\t }\n\t if (options.lastTickAnchor) {\n\t lastTickLabels.style('text-anchor', options.lastTickAnchor);\n\t }\n\t firstTickLabels = d3.select(tickLabels[0][0]);\n\t if (options.firstTickDy) {\n\t firstTickLabels.attr('dy', options.firstTickDy);\n\t }\n\t if (options.firstTickDx) {\n\t firstTickLabels.attr('dx', options.firstTickDx);\n\t }\n\t if (options.listTickAnchor) {\n\t return firstTickLabels.style('text-anchor', options.firstTickAnchor);\n\t }\n\t };\n\t axisElement = null;\n\t grid = null;\n\t label = null;\n\t redraw = function(data) {\n\t var axis, tickLabels;\n\t if (!((data != null) && data.length !== 0)) {\n\t return;\n\t }\n\t axisElement || (axisElement = chartController.getChart().append(\"g\").attr(\"class\", \"axis axis-\" + options.orientation + \" axis-\" + options.name).attr(\"transform\", translation()));\n\t if (options.label) {\n\t label || (label = axisElement.append(\"text\").attr(\"class\", \"axis-label\").text(options.label));\n\t }\n\t if (options.grid) {\n\t grid || (grid = chartController.getChart().append(\"g\").attr(\"class\", \"axis-grid axis-grid-\" + options.name));\n\t }\n\t axis = getAxis();\n\t if (label) {\n\t positionLabel(label.transition().duration(500));\n\t }\n\t axisElement.transition().duration(500).attr(\"transform\", translation()).call(axis).selectAll('tick text').tween(\"attr.dx\", null).tween(\"attr.dy\", null).tween(\"style.text-anchor\", null);\n\t if (grid != null) {\n\t drawGrid(grid.transition().duration(500), axis);\n\t }\n\t tickLabels = axisElement.selectAll('.tick text');\n\t return axisElement.call(adjustTickLabels);\n\t };\n\t updateScale = function(data) {\n\t var datum, domainValues;\n\t if (!((data != null) && data.length !== 0)) {\n\t return;\n\t }\n\t scale.range(range());\n\t if (options.domain) {\n\t data;\n\t }\n\t if ($scope.filter) {\n\t domainValues = $scope.filter(data);\n\t } else {\n\t domainValues = (function() {\n\t var i, len, results;\n\t results = [];\n\t for (i = 0, len = data.length; i < len; i++) {\n\t datum = data[i];\n\t results.push(datum[options.name]);\n\t }\n\t return results;\n\t })();\n\t }\n\t if (options.extent) {\n\t return scale.domain(d3.extent(domainValues));\n\t } else {\n\t return scale.domain([0, d3.max(domainValues)]);\n\t }\n\t };\n\t chartController.addScale(options.name, scale, updateScale);\n\t chartController.registerElement(redraw, options.order);\n\t $scope.$watchCollection('tickValues', chartController.redraw);\n\t $scope.$watchCollection('customTimeFormat', chartController.redraw);\n\t $scope.$watch('filter', chartController.redraw);\n\t return $scope.$watch('tickValues', chartController.redraw);\n\t }\n\t };\n\t }\n\t]);\n\n\n/***/ },\n/* 5 */\n/***/ function(module, exports) {\n\n\tangular.module('ad3').directive('d3Bars', function() {\n\t var defaults;\n\t defaults = function() {\n\t return {\n\t x: 0,\n\t y: 1,\n\t width: 15\n\t };\n\t };\n\t return {\n\t restrict: 'E',\n\t require: '^d3Chart',\n\t link: function(scope, el, attrs, chartController) {\n\t var barsElements, chart, height, options, redraw, width, x, y;\n\t options = angular.extend(defaults(), attrs);\n\t x = chartController.getScale(options.xscale || options.x);\n\t y = chartController.getScale(options.yscale || options.y);\n\t chart = chartController.getChart();\n\t height = chartController.innerHeight;\n\t width = options.width;\n\t barsElements = null;\n\t redraw = function(data) {\n\t var bars;\n\t barsElements || (barsElements = chartController.getChart().append(\"g\").attr(\"class\", \"bars\"));\n\t if (!((data != null) && data.length !== 0)) {\n\t return;\n\t }\n\t bars = barsElements.selectAll(\"rect.bar\").data(data);\n\t bars.exit().transition().duration(500).attr(\"y\", function() {\n\t return chartController.innerHeight;\n\t }).attr(\"height\", 0).remove();\n\t bars.transition().duration(500).attr(\"x\", function(d) {\n\t return x(d[options.x]) - width / 2;\n\t }).attr(\"y\", function(d) {\n\t return y(d[options.y]);\n\t }).attr(\"height\", function(d) {\n\t return chartController.innerHeight - y(d[options.y]);\n\t }).attr(\"width\", width);\n\t return bars.enter().append(\"rect\").attr(\"class\", function(d, i) {\n\t return \"bar bar-\" + i;\n\t }).attr(\"x\", function(d) {\n\t return x(d[options.x]) - width / 2;\n\t }).attr(\"width\", width).attr(\"y\", function() {\n\t return chartController.innerHeight;\n\t }).attr(\"height\", 0).transition().duration(500).attr(\"y\", function(d) {\n\t return y(d[options.y]);\n\t }).attr(\"height\", function(d) {\n\t return chartController.innerHeight - y(d[options.y]);\n\t });\n\t };\n\t return chartController.registerElement(redraw, options.order);\n\t }\n\t };\n\t});\n\n\n/***/ },\n/* 6 */\n/***/ function(module, exports) {\n\n\tangular.module('ad3').directive('d3Chart', function() {\n\t return {\n\t restrict: 'EA',\n\t scope: {\n\t margin: '=',\n\t data: '='\n\t },\n\t controller: [\n\t '$scope', '$element', '$attrs', '$window', '$timeout', function($scope, $el, $attrs, $window, $timeout) {\n\t var chart, debounce, elements, height, scales, sortOrder, svg, updateSize, width;\n\t scales = $scope.scales = {};\n\t elements = $scope.elements = [];\n\t this.margin = $scope.margin || {\n\t top: 10,\n\t right: 10,\n\t bottom: 10,\n\t left: 10\n\t };\n\t svg = d3.select($el[0]).append('svg').attr('class', \"d3\").attr(\"width\", \"100%\").attr(\"height\", \"100%\");\n\t width = function() {\n\t return $el[0].offsetWidth;\n\t };\n\t height = function() {\n\t return $el[0].offsetHeight;\n\t };\n\t chart = svg.append(\"g\").attr(\"transform\", \"translate(\" + this.margin.left + \",\" + this.margin.top + \")\");\n\t this.getSvg = function() {\n\t return svg;\n\t };\n\t this.getChart = function() {\n\t return chart;\n\t };\n\t this.addScale = function(name, scale, update) {\n\t return scales[name] = {\n\t scale: scale,\n\t update: update\n\t };\n\t };\n\t this.getScale = function(name) {\n\t return scales[name].scale;\n\t };\n\t this.registerElement = function(el, order) {\n\t if (order == null) {\n\t order = 0;\n\t }\n\t return elements.push({\n\t redraw: el,\n\t order: Number(order)\n\t });\n\t };\n\t updateSize = (function(_this) {\n\t return function() {\n\t if (_this.width !== width() || _this.height !== height()) {\n\t _this.width = width();\n\t _this.height = height();\n\t _this.innerWidth = _this.width - _this.margin.left - _this.margin.right;\n\t _this.innerHeight = _this.height - _this.margin.top - _this.margin.bottom;\n\t return _this.redraw();\n\t }\n\t };\n\t })(this);\n\t sortOrder = function(a, b) {\n\t return a.order - b.order;\n\t };\n\t debounce = null;\n\t this.redraw = (function(_this) {\n\t return function() {\n\t if (debounce || _this.width === 0 || _this.height === 0) {\n\t return;\n\t }\n\t return debounce = $timeout(function() {\n\t var data, element, i, len, name, ref, results, scale;\n\t debounce = null;\n\t data = $scope.data;\n\t for (name in scales) {\n\t scale = scales[name];\n\t scale.update(data);\n\t }\n\t ref = elements.sort(sortOrder);\n\t results = [];\n\t for (i = 0, len = ref.length; i < len; i++) {\n\t element = ref[i];\n\t results.push(element.redraw(data));\n\t }\n\t return results;\n\t }, $attrs.updateInterval || 200);\n\t };\n\t })(this);\n\t $window.addEventListener('resize', updateSize);\n\t if ($attrs.watch === 'deep') {\n\t $scope.$watch('data', this.redraw, true);\n\t } else {\n\t $scope.$watch('data', this.redraw);\n\t }\n\t $scope.$watch(updateSize);\n\t updateSize();\n\t }\n\t ]\n\t };\n\t});\n\n\n/***/ },\n/* 7 */\n/***/ function(module, exports) {\n\n\tangular.module('ad3').directive('d3Data', [\n\t 'd3Service', function(d3) {\n\t return {\n\t restrict: 'E',\n\t scope: {\n\t accessor: '=',\n\t callback: '=',\n\t data: '='\n\t },\n\t link: function($scope, $el, $attrs) {\n\t var src;\n\t src = $attrs.src;\n\t return d3.csv(src, $scope.accessor, $scope.callback).then(function(rows) {\n\t return $scope.data = rows;\n\t }, function() {\n\t throw 'Error loading CSV via D3';\n\t });\n\t }\n\t };\n\t }\n\t]);\n\n\n/***/ },\n/* 8 */\n/***/ function(module, exports) {\n\n\tangular.module('ad3').directive('d3Gradient', function() {\n\t var defaults;\n\t defaults = {\n\t transition: 500\n\t };\n\t return {\n\t restrict: 'E',\n\t require: '^d3Chart',\n\t link: function($scope, $el, $attrs, chartController) {\n\t var gradient, svg, transition;\n\t svg = chartController.getSvg();\n\t gradient = svg.insert(\"defs\", 'g').append(\"linearGradient\").attr(\"id\", $attrs.ref);\n\t ['x1', 'x2', 'y1', 'y2'].forEach(function(attr) {\n\t return $attrs.$observe(attr, function(val) {\n\t return gradient.attr(attr, val);\n\t });\n\t });\n\t transition = defaults.transition;\n\t $attrs.$observe('transition', function(val) {\n\t if (val != null) {\n\t return transition = val;\n\t }\n\t });\n\t return $scope.$watch($attrs.stops, function(stops) {\n\t if (stops == null) {\n\t return;\n\t }\n\t stops = gradient.selectAll('stop').data(stops);\n\t stops.enter().append('stop');\n\t stops.attr('offset', function(d) {\n\t return d.offset;\n\t }).attr('stop-color', function(d) {\n\t return d.color;\n\t }).attr('stop-opacity', function(d) {\n\t if (d.opacity != null) {\n\t return d.opacity;\n\t } else {\n\t return 1;\n\t }\n\t });\n\t return stops.exit().remove();\n\t });\n\t }\n\t };\n\t});\n\n\n/***/ },\n/* 9 */\n/***/ function(module, exports) {\n\n\tangular.module('ad3').directive('d3Include', function() {\n\t return {\n\t restrict: 'E',\n\t require: '^d3Chart',\n\t link: function($scope, $el, $attrs, chartController) {\n\t var chart, includes;\n\t chart = chartController.getChart();\n\t includes = chart.append('g').attr('class', 'includes');\n\t return includes.html($el.html());\n\t }\n\t };\n\t});\n\n\n/***/ },\n/* 10 */\n/***/ function(module, exports) {\n\n\tangular.module('ad3').directive('d3Line', function() {\n\t var defaults;\n\t defaults = function() {\n\t return {\n\t x: 0,\n\t y: 1\n\t };\n\t };\n\t return {\n\t restrict: 'E',\n\t require: '^d3Chart',\n\t link: function(scope, el, attrs, chartController) {\n\t var line, linePath, options, redraw, x, y;\n\t options = angular.extend(defaults(), attrs);\n\t x = chartController.getScale(options.xscale || options.x);\n\t y = chartController.getScale(options.yscale || options.y);\n\t line = d3.svg.line().x(function(d) {\n\t return x(d[options.x]);\n\t }).y(function(d) {\n\t return y(d[options.y]);\n\t });\n\t linePath = null;\n\t redraw = function(data) {\n\t linePath || (linePath = chartController.getChart().append(\"path\").attr(\"class\", \"line line-\" + (options.name || options.y)).style(\"fill\", \"none\").style(\"stroke\", options.stroke));\n\t if (!((data != null) && data.length !== 0)) {\n\t return;\n\t }\n\t return linePath.datum(data).transition().duration(500).attr(\"d\", line);\n\t };\n\t return chartController.registerElement(redraw, options.order);\n\t }\n\t };\n\t});\n\n\n/***/ },\n/* 11 */\n/***/ function(module, exports) {\n\n\tangular.module('ad3').directive('d3Pie', function() {\n\t var defaults;\n\t defaults = function() {\n\t return {\n\t x: 0,\n\t y: 1,\n\t innerRadius: 0,\n\t labelRadius: 0.7,\n\t transition: \"cubic-in-out\",\n\t transitionDuration: 800,\n\t minOffset: 12,\n\t value: 'value'\n\t };\n\t };\n\t return {\n\t restrict: 'E',\n\t require: '^d3Chart',\n\t link: function(scope, el, attrs, chartController) {\n\t var _current, center, chart, colorScale, innerRadius, labelRadius, options, pie, redraw;\n\t options = angular.extend(defaults(), attrs);\n\t chart = chartController.getChart();\n\t innerRadius = parseFloat(options.innerRadius);\n\t labelRadius = parseFloat(options.labelRadius);\n\t if (attrs.colors) {\n\t colorScale = (function() {\n\t switch (attrs.colors) {\n\t case 'category20':\n\t return d3.scale.category20();\n\t case 'category20b':\n\t return d3.scale.category20b();\n\t case 'category20c':\n\t return d3.scale.category20c();\n\t }\n\t })();\n\t }\n\t pie = d3.layout.pie().sort(null).value(function(d) {\n\t return d[options.value];\n\t });\n\t _current = null;\n\t center = null;\n\t redraw = function(data) {\n\t var arc, arcTween, getPosition, label, labelArc, padding, prevbb, radius, slice;\n\t center || (center = chartController.getChart().append(\"g\").attr(\"class\", \"pie\"));\n\t if (!((data != null) && data.length !== 0)) {\n\t return;\n\t }\n\t radius = Math.min(chartController.innerWidth, chartController.innerHeight) / 2;\n\t center.attr(\"transform\", \"translate(\" + radius + \",\" + radius + \")\");\n\t arc = d3.svg.arc().outerRadius(radius).innerRadius(radius * innerRadius);\n\t arcTween = function(a) {\n\t var i;\n\t i = d3.interpolate(this._current, a);\n\t this._current = i(0);\n\t return function(t) {\n\t return arc(i(t));\n\t };\n\t };\n\t labelArc = d3.svg.arc().outerRadius(radius * labelRadius).innerRadius(radius * labelRadius);\n\t slice = center.selectAll(\".pie\").data(pie(data));\n\t slice.enter().append(\"path\").attr(\"class\", function(d, i) {\n\t return \"pie pie-\" + i;\n\t }).attr(\"d\", arc).each(function(d) {\n\t return this._current = d;\n\t });\n\t if (attrs.colors) {\n\t slice.style('fill', function(d, i) {\n\t if (colorScale) {\n\t return colorScale(i);\n\t } else {\n\t return d[attrs.color];\n\t }\n\t });\n\t }\n\t slice.exit().remove();\n\t slice.transition().ease(options.transition).duration(options.transitionDuration).attrTween(\"d\", arcTween);\n\t if (options.label) {\n\t prevbb = null;\n\t padding = +options.minOffset;\n\t getPosition = function(d, i) {\n\t var cpx, cpy, ctx, cty, offset, offsetArc, position, relativePosition, thisbb;\n\t position = labelArc.centroid(d);\n\t if (options.avoidCollisions) {\n\t relativePosition = [position[0], position[1]];\n\t if (this._position) {\n\t relativePosition[0] -= this._position[0];\n\t relativePosition[1] -= this._position[1];\n\t }\n\t thisbb = _.transform(this.getBoundingClientRect(), function(r, v, k) {\n\t switch (k) {\n\t case 'left':\n\t return r[k] = v - padding + relativePosition[0];\n\t case 'top':\n\t return r[k] = v - padding + relativePosition[1];\n\t case 'right':\n\t return r[k] = v + padding + relativePosition[0];\n\t case 'bottom':\n\t return r[k] = v + padding + relativePosition[1];\n\t }\n\t });\n\t if (prevbb && !(thisbb.right < prevbb.left || thisbb.left > prevbb.right || thisbb.bottom < prevbb.top || thisbb.top > prevbb.bottom)) {\n\t ctx = thisbb.left + (thisbb.right - thisbb.left) / 2;\n\t cty = thisbb.top + (thisbb.bottom - thisbb.top) / 2;\n\t cpx = prevbb.left + (prevbb.right - prevbb.left) / 2;\n\t cpy = prevbb.top + (prevbb.bottom - prevbb.top) / 2;\n\t offset = Math.sqrt(Math.pow(ctx - cpx, 2) + Math.pow(cty - cpy, 2)) / 2;\n\t offsetArc = d3.svg.arc().outerRadius(radius * labelRadius + offset).innerRadius(radius * labelRadius + offset);\n\t position = offsetArc.centroid(d);\n\t }\n\t this._position = position;\n\t prevbb = thisbb;\n\t }\n\t return \"translate(\" + position + \")\";\n\t };\n\t label = center.selectAll(\"text\").data(pie(data));\n\t label.enter().append(\"text\").style(\"text-anchor\", \"middle\").attr(\"class\", function(d, i) {\n\t return \"pie-label pie-label-\" + i;\n\t });\n\t label.exit().remove();\n\t label.text(function(d, i) {\n\t return data[i][options.label];\n\t });\n\t return label.transition().ease(options.transition).duration(options.transitionDuration).attr(\"transform\", getPosition);\n\t }\n\t };\n\t return chartController.registerElement(redraw, options.order);\n\t }\n\t };\n\t});\n\n\n/***/ },\n/* 12 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar angular;\n\t\n\tangular = __webpack_require__(15);\n\t\n\tangular.module('ad3', []);\n\t\n\t__webpack_require__(14);\n\t\n\t__webpack_require__(13);\n\t\n\t__webpack_require__(2);\n\t\n\t__webpack_require__(3);\n\t\n\t__webpack_require__(4);\n\t\n\t__webpack_require__(5);\n\t\n\t__webpack_require__(6);\n\t\n\t__webpack_require__(7);\n\t\n\t__webpack_require__(8);\n\t\n\t__webpack_require__(9);\n\t\n\t__webpack_require__(10);\n\t\n\t__webpack_require__(11);\n\n\n/***/ },\n/* 13 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar d3;\n\t\n\td3 = __webpack_require__(1);\n\t\n\tangular.module('ad3').provider('d3locale', function() {\n\t var localeDefinitions;\n\t localeDefinitions = {};\n\t this.setLocales = function(definitions) {\n\t return localeDefinitions = definitions;\n\t };\n\t this.$get = function() {\n\t var updateLocale;\n\t updateLocale = function(locale) {\n\t d3.format = locale.numberFormat;\n\t return d3.time.format = locale.timeFormat;\n\t };\n\t return {\n\t setLang: function(lang) {\n\t var err, error, locale;\n\t try {\n\t locale = d3.locale(localeDefinitions[lang.toLowerCase()]);\n\t return updateLocale(locale);\n\t } catch (error) {\n\t err = error;\n\t throw \"d3locale error: '\" + lang + \"' is a locale that either does not exist, or has not been loaded properly.\";\n\t }\n\t },\n\t setLocale: function(locale) {\n\t return updateLocale(d3.locale(locale));\n\t }\n\t };\n\t };\n\t return this;\n\t});\n\n\n/***/ },\n/* 14 */\n/***/ function(module, exports, __webpack_require__) {\n\n\tvar d3;\n\t\n\td3 = __webpack_require__(1);\n\t\n\tangular.module('ad3').provider('d3Service', function() {\n\t var defaults;\n\t defaults = this.defaults = {};\n\t this.$get = [\n\t '$cacheFactory', '$rootScope', '$q', function($cacheFactory, $rootScope, $q) {\n\t var cache;\n\t cache = defaults.cache || $cacheFactory('d3Service');\n\t return {\n\t csv: function(src, accessor, callback) {\n\t var cached, deferred;\n\t deferred = $q.defer();\n\t cached = cache.get(src);\n\t if (cached) {\n\t if (callback) {\n\t callback(rows);\n\t }\n\t deferred.resolve(cached);\n\t }\n\t d3.csv(src, accessor, function(rows) {\n\t return $rootScope.$apply(function() {\n\t if (callback) {\n\t callback(rows);\n\t }\n\t if (rows) {\n\t cache.put(src, rows);\n\t return deferred.resolve(rows);\n\t } else {\n\t return deferred.reject();\n\t }\n\t });\n\t });\n\t return deferred.promise;\n\t }\n\t };\n\t }\n\t ];\n\t return this;\n\t});\n\n\n/***/ },\n/* 15 */\n/***/ function(module, exports) {\n\n\tmodule.exports = angular;\n\n/***/ }\n/******/ ]);\n\n\n/** WEBPACK FOOTER **\n ** angularD3.js\n **/"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap 8bf28550a687135190f4\n **/","require('./angularD3')\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./index.js\n ** module id = 0\n ** module chunks = 0\n **/","module.exports = d3;\n\n\n/*****************\n ** WEBPACK FOOTER\n ** external \"d3\"\n ** module id = 1\n ** module chunks = 0\n **/","d3 = require('d3')\n\nangular.module('ad3').directive 'd3Arc', ->\n defaults = ->\n x: 0\n y: 1\n innerRadius: 0\n labelRadius: 0\n transition: \"cubic-in-out\"\n transitionDuration: 1000\n value: 'value'\n label: 'label'\n\n restrict: 'E'\n\n require: '^d3Chart'\n\n link: (scope, el, attrs, chartController) ->\n options = angular.extend(defaults(), attrs)\n\n chart = chartController.getChart()\n innerRadius = parseFloat(options.innerRadius)\n labelRadius = parseFloat(options.labelRadius)\n\n center = null\n arcPath = null\n arcLabel = null\n redraw = (data) ->\n center ||= chartController.getChart().append(\"g\").attr(\"class\", \"arc\")\n arcPath ||= center.append(\"path\")\n arcLabel ||= center.append(\"text\")\n .attr(\"class\", \"arc-label\")\n .attr(\"dy\", \"0.35em\")\n .style(\"text-anchor\", \"middle\")\n\n return unless data? and data.length isnt 0\n\n radius = Math.min(chartController.innerWidth, chartController.innerHeight)/2\n\n center.attr(\"transform\", \"translate(\" + radius + \",\" + radius + \")\")\n\n arc = d3.svg.arc()\n .outerRadius(radius)\n .innerRadius(radius * innerRadius)\n .startAngle(0)\n .endAngle((d) -> d/100 * 2 * Math.PI)\n\n arcTween = (d) ->\n @_current ?= 0\n i = d3.interpolate(@_current, d)\n @_current = d\n (t) -> arc(i(t))\n\n labelArc = d3.svg.arc()\n .outerRadius(radius * labelRadius)\n .innerRadius(radius * labelRadius)\n\n arcPath.datum(data[options.value])\n .transition()\n .ease(options.transition)\n .duration(options.transitionDuration)\n .attrTween(\"d\", arcTween)\n\n arcLabel.text(data[options.label])\n\n chartController.registerElement(redraw, options.order)\n\n\n\n/** WEBPACK FOOTER **\n ** ./angularD3/directives/arc.coffee\n **/","angular.module('ad3').directive 'd3Area', ->\n defaults = -> {}\n\n restrict: 'E'\n require: '^d3Chart'\n scope:\n columns: '='\n\n link: ($scope, $el, $attrs, chartController) ->\n # todo: DRY this up in line, area and bar directives\n options = angular.extend(defaults(), $attrs)\n x = chartController.getScale(options.xscale or options.x)\n y = chartController.getScale(options.yscale or options.y)\n\n if options.vertical\n area = d3.svg.area()\n .y((d) -> x(d.x))\n .x0(0)\n .x1((d) -> y(d.y))\n areaStacked = d3.svg.area()\n .y((d) -> x(d.x))\n .x0((d) -> y(d.y0))\n .x1((d) -> y(d.y + d.y0))\n else\n area = d3.svg.area()\n .x((d) -> x(d.x))\n .y0(-> chartController.innerHeight)\n .y1((d) -> y(d.y))\n areaStacked = d3.svg.area()\n .x((d) -> x(d.x))\n .y0((d) -> y(d.y0))\n .y1((d) -> y(d.y + d.y0))\n\n areaElement = null\n redraw = (data) ->\n areaElement ||= chartController.getChart().append(\"g\")\n .attr(\"class\", \"area\")\n return unless data? and data.length isnt 0\n columns = options.y if options.y?\n if $scope.columns?\n columns = $scope.columns\n return unless columns?\n if angular.isString columns\n columns = columns.split(',').map((c) -> c.trim())\n return if columns.length is 0\n\n mappedData = for name in columns\n name: name\n values: for value in data\n x: value[options.x]\n y: value[name]\n stack = d3.layout.stack().values((d) -> d.values)\n stack.offset(options.offset) if options.offset?\n stackedData = stack(mappedData)\n\n charts = areaElement.selectAll('path.area').data(stackedData)\n charts.enter().append(\"path\")\n charts.attr(\"class\", (d) -> \"area #{d.name}\")\n .transition()\n .duration(500)\n .attr(\"d\", (d,i) -> if i is 0 then area(d.values) else areaStacked(d.values))\n charts.exit()\n .attr(\"d\", (d,i) -> if i is 0 then area(d.values) else areaStacked(d.values))\n .remove()\n\n $scope.$watch 'columns', chartController.redraw, true\n chartController.registerElement(redraw, options.order)\n\n\n\n/** WEBPACK FOOTER **\n ** ./angularD3/directives/area.coffee\n **/","angular.module('ad3').directive 'd3Axis', ['d3locale', (d3locale) ->\n defaults = ->\n orientation: 'bottom'\n ticks: '5'\n extent: false\n\n priority: 1\n restrict: 'E'\n require: '^d3Chart'\n scope:\n customTimeFormat: '='\n filter: '='\n tickValues: '='\n\n link: ($scope, $el, $attrs, chartController) ->\n options = angular.extend(defaults(), $attrs)\n\n range = ->\n if options.orientation is 'top' or options.orientation is 'bottom'\n if options.reverse?\n [chartController.innerWidth, 0]\n else\n [0 ,chartController.innerWidth]\n else\n if options.reverse?\n [0, chartController.innerHeight]\n else\n [chartController.innerHeight, 0]\n\n translation = ->\n if options.orientation is 'bottom'\n \"translate(0, #{chartController.innerHeight})\"\n else if options.orientation is 'top'\n \"translate(0, 0)\"\n else if options.orientation is 'left'\n \"translate(0, 0)\"\n else if options.orientation is 'right'\n \"translate(#{chartController.innerWidth}, 0)\"\n\n if options.scale is 'time'\n scale = d3.time.scale()\n else if options.scale\n scale = d3.scale[options.scale]()\n else\n scale = d3.scale.linear()\n\n getAxis = ->\n axis = d3.svg.axis().scale(scale).orient(options.orientation)\n if options.ticks\n axis.ticks(options.ticks)\n if options.timeScale\n axis.ticks(d3.time[options.timeScale], options.timeInterval)\n if $scope.tickValues\n axis.tickValues($scope.tickValues)\n if options.tickSize\n tickSize = options.tickSize.split(',')\n axis.innerTickSize(tickSize[0])\n axis.outerTickSize(tickSize[1])\n if $scope.customTimeFormat?\n # We copy this because D3 is bad and mutates the time format.\n # See: https://github.com/mbostock/d3/issues/1769\n format = d3.time.format.multi(angular.copy($scope.customTimeFormat))\n axis.tickFormat((value) -> format(new Date(value)))\n if options.timeFormat?\n format = d3.time.format(options.timeFormat)\n axis.tickFormat((value) -> format(new Date(value)))\n else if options.format?\n format = d3.format(options.format)\n axis.tickFormat(format)\n axis\n\n positionLabel = (label) ->\n if options.orientation is 'bottom'\n label.attr(\"x\", \"#{chartController.innerWidth / 2}\")\n .attr(\"dy\", \"#{chartController.margin.bottom}\")\n .attr(\"style\", \"text-anchor: middle;\")\n else if options.orientation is 'top'\n label.attr(\"x\", \"#{chartController.innerWidth / 2}\")\n .attr(\"dy\", \"#{-chartController.margin.top}\")\n .attr(\"style\", \"text-anchor: middle;\")\n else if options.orientation is 'left'\n label.attr(\"x\", \"-#{chartController.innerHeight / 2}\")\n .attr(\"dy\", \"#{-chartController.margin.left + 18}\")\n .attr(\"style\", \"text-anchor: middle;\")\n .attr(\"transform\", \"rotate(-90)\")\n else if options.orientation is 'right'\n label.attr(\"x\", \"#{chartController.innerHeight / 2}\")\n .attr(\"dy\", \"#{-chartController.margin.right + 18}\")\n .attr(\"style\", \"text-anchor: middle;\")\n .attr(\"transform\", \"rotate(90)\")\n\n drawGrid = (grid, axis) ->\n if options.orientation is 'bottom'\n grid.call(axis.tickSize(chartController.innerHeight, 0, 0)\n .tickFormat('')\n )\n else if options.orientation is 'top'\n grid.attr(\"transform\", \"translate(0, #{chartController.innerHeight})\")\n .call(axis.tickSize(chartController.innerHeight, 0, 0)\n .tickFormat('')\n )\n else if options.orientation is 'left'\n grid.attr(\"transform\", \"translate(#{chartController.innerWidth}, 0)\")\n .call(axis.tickSize(chartController.innerWidth, 0, 0)\n .tickFormat('')\n )\n else if options.orientation is 'right'\n grid.call(axis.tickSize(chartController.innerWidth, 0, 0)\n .tickFormat('')\n )\n\n adjustTickLabels = (g) ->\n tickLabels = g.selectAll('.tick text')\n if options.tickDy\n tickLabels.attr('dy', options.tickDy)\n if options.tickDx\n tickLabels.attr('dx', options.tickDx)\n if options.tickAnchor\n tickLabels.style('text-anchor', options.tickAnchor)\n lastTickLabels = d3.select(tickLabels[0].slice(-1)[0])\n if options.lastTickDy\n lastTickLabels.attr('dy', options.lastTickDy)\n if options.lastTickDx\n lastTickLabels.attr('dx', options.lastTickDx)\n if options.lastTickAnchor\n lastTickLabels.style('text-anchor', options.lastTickAnchor)\n firstTickLabels = d3.select(tickLabels[0][0])\n if options.firstTickDy\n firstTickLabels.attr('dy', options.firstTickDy)\n if options.firstTickDx\n firstTickLabels.attr('dx', options.firstTickDx)\n if options.listTickAnchor\n firstTickLabels.style('text-anchor', options.firstTickAnchor)\n\n axisElement = null\n grid = null\n label = null\n\n redraw = (data) ->\n return unless data? and data.length isnt 0\n # Append x-axis to chart\n axisElement ||= chartController.getChart().append(\"g\")\n .attr(\"class\", \"axis axis-#{options.orientation} axis-#{options.name}\")\n .attr(\"transform\", translation())\n if options.label\n label ||= axisElement.append(\"text\").attr(\"class\", \"axis-label\").text(options.label)\n if options.grid\n grid ||= chartController.getChart().append(\"g\")\n .attr(\"class\", \"axis-grid axis-grid-#{options.name}\")\n\n axis = getAxis()\n positionLabel(label.transition().duration(500)) if label\n axisElement.transition().duration(500)\n .attr(\"transform\", translation())\n .call(axis)\n .selectAll('tick text')\n .tween(\"attr.dx\", null)\n .tween(\"attr.dy\", null)\n .tween(\"style.text-anchor\", null)\n\n drawGrid(grid.transition().duration(500), axis) if grid?\n tickLabels = axisElement.selectAll('.tick text')\n axisElement.call(adjustTickLabels)\n\n updateScale = (data) ->\n return unless data? and data.length isnt 0\n scale.range(range())\n if options.domain\n data\n if $scope.filter\n domainValues = $scope.filter(data)\n else\n domainValues = (datum[options.name] for datum in data)\n if options.extent\n scale.domain d3.extent domainValues\n else\n scale.domain [0, d3.max domainValues]\n\n chartController.addScale(options.name, scale, updateScale)\n chartController.registerElement(redraw, options.order)\n $scope.$watchCollection 'tickValues', chartController.redraw\n $scope.$watchCollection 'customTimeFormat', chartController.redraw\n $scope.$watch 'filter', chartController.redraw\n $scope.$watch 'tickValues', chartController.redraw\n]\n\n\n\n/** WEBPACK FOOTER **\n ** ./angularD3/directives/axis.coffee\n **/","angular.module('ad3').directive 'd3Bars', ->\n defaults = ->\n x: 0\n y: 1\n width: 15\n\n restrict: 'E'\n\n require: '^d3Chart'\n\n link: (scope, el, attrs, chartController) ->\n options = angular.extend(defaults(), attrs)\n x = chartController.getScale(options.xscale or options.x)\n y = chartController.getScale(options.yscale or options.y)\n\n chart = chartController.getChart()\n height = chartController.innerHeight\n width = options.width\n\n barsElements = null\n redraw = (data) ->\n barsElements ||= chartController.getChart().append(\"g\")\n .attr(\"class\", \"bars\")\n return unless data? and data.length isnt 0\n bars = barsElements.selectAll(\"rect.bar\").data(data)\n bars.exit().transition().duration(500)\n .attr(\"y\", -> chartController.innerHeight)\n .attr(\"height\", 0)\n .remove()\n bars.transition().duration(500)\n .attr(\"x\", (d) -> x(d[options.x]) - width/2)\n .attr(\"y\", (d) -> y(d[options.y]))\n .attr(\"height\", (d) -> chartController.innerHeight - y(d[options.y]))\n .attr(\"width\", width)\n bars.enter()\n .append(\"rect\")\n .attr(\"class\", (d,i) -> \"bar bar-#{i}\")\n .attr(\"x\", (d) -> x(d[options.x]) - width/2)\n .attr(\"width\", width)\n .attr(\"y\", -> chartController.innerHeight)\n .attr(\"height\", 0)\n .transition().duration(500)\n .attr(\"y\", (d) -> y(d[options.y]))\n .attr(\"height\", (d) -> chartController.innerHeight - y(d[options.y]))\n\n chartController.registerElement(redraw, options.order)\n\n\n\n/** WEBPACK FOOTER **\n ** ./angularD3/directives/bars.coffee\n **/","angular.module('ad3').directive 'd3Chart', ->\n restrict: 'EA'\n scope:\n margin: '='\n data: '='\n\n controller: ['$scope', '$element', '$attrs', '$window', '$timeout',\n ($scope, $el, $attrs, $window, $timeout) ->\n scales = $scope.scales = {}\n elements = $scope.elements = []\n\n @margin = $scope.margin or { top: 10, right: 10, bottom: 10, left: 10 }\n svg = d3.select($el[0]).append('svg').attr('class', \"d3\")\n .attr(\"width\", \"100%\")\n .attr(\"height\", \"100%\")\n\n # Used to calculated widths based on SVG margins\n width = -> $el[0].offsetWidth\n height = -> $el[0].offsetHeight\n\n chart = svg.append(\"g\")\n .attr(\"transform\", \"translate(\" + @margin.left + \",\" + @margin.top + \")\")\n\n @getSvg = -> svg\n @getChart = -> chart\n @addScale = (name, scale, update) -> scales[name] = { scale: scale, update: update }\n @getScale = (name) -> scales[name].scale\n @registerElement = (el, order = 0) -> elements.push { redraw: el, order: Number(order) }\n\n updateSize = =>\n if @width != width() or @height != height()\n @width = width()\n @height = height()\n @innerWidth = @width - @margin.left - @margin.right\n @innerHeight = @height - @margin.top - @margin.bottom\n # Redraw if the chart size has changed\n @redraw()\n\n sortOrder = (a, b) -> a.order - b.order\n debounce = null\n @redraw = =>\n # We don't bother to redraw if the chart isn't visible\n return if debounce or @width is 0 or @height is 0\n debounce = $timeout =>\n debounce = null\n data = $scope.data\n for name, scale of scales\n scale.update(data)\n for element in elements.sort(sortOrder)\n element.redraw(data)\n , $attrs.updateInterval or 200\n\n $window.addEventListener 'resize', updateSize\n\n if $attrs.watch is 'deep'\n $scope.$watch 'data', @redraw, true\n else\n $scope.$watch 'data', @redraw\n\n # We check the size on all scope events since scope can affect chart\n # visibility and if the chart area is resized while not visible it won't\n # update.\n $scope.$watch updateSize\n\n updateSize()\n return\n ]\n\n\n\n/** WEBPACK FOOTER **\n ** ./angularD3/directives/chart.coffee\n **/","angular.module('ad3').directive 'd3Data',['d3Service', (d3) ->\n restrict: 'E'\n scope:\n accessor: '='\n callback: '='\n data: '='\n link: ($scope, $el, $attrs) ->\n src = $attrs.src\n d3.csv(src, $scope.accessor, $scope.callback).then (rows) ->\n $scope.data = rows\n , -> throw('Error loading CSV via D3')\n]\n\n\n\n/** WEBPACK FOOTER **\n ** ./angularD3/directives/data.coffee\n **/","angular.module('ad3').directive 'd3Gradient', ->\n defaults = { transition: 500 }\n\n restrict: 'E'\n require: '^d3Chart'\n\n link: ($scope, $el, $attrs, chartController) ->\n svg = chartController.getSvg()\n\n gradient = svg.insert(\"defs\", 'g')\n .append(\"linearGradient\")\n .attr(\"id\", $attrs.ref)\n\n ['x1', 'x2', 'y1', 'y2'].forEach (attr) ->\n $attrs.$observe attr, (val) -> gradient.attr(attr, val)\n\n transition = defaults.transition\n $attrs.$observe 'transition', (val) -> transition = val if val?\n\n $scope.$watch $attrs.stops, (stops) ->\n return unless stops?\n stops = gradient.selectAll('stop').data(stops)\n stops.enter().append('stop')\n stops.attr('offset', (d) -> d.offset)\n .attr('stop-color', (d) -> d.color)\n .attr('stop-opacity', (d) -> if d.opacity? then d.opacity else 1)\n stops.exit().remove()\n\n\n\n/** WEBPACK FOOTER **\n ** ./angularD3/directives/gradient.coffee\n **/","# d3-include\n#\n# Allows arbitrary SVG content to be injected into the chart\n#\n# Todo: Consider making this work more like ng-include and allowing it to fetch\n# the SVG content from view templates.\n\nangular.module('ad3').directive 'd3Include', ->\n restrict: 'E'\n require: '^d3Chart'\n link: ($scope, $el, $attrs, chartController) ->\n chart = chartController.getChart()\n includes = chart.append('g').attr('class', 'includes')\n includes.html($el.html())\n\n\n\n/** WEBPACK FOOTER **\n ** ./angularD3/directives/include.coffee\n **/","angular.module('ad3').directive 'd3Line', ->\n defaults = ->\n x: 0\n y: 1\n\n restrict: 'E'\n\n require: '^d3Chart'\n\n link: (scope, el, attrs, chartController) ->\n options = angular.extend(defaults(), attrs)\n x = chartController.getScale(options.xscale or options.x)\n y = chartController.getScale(options.yscale or options.y)\n\n line = d3.svg.line()\n .x((d) -> x(d[options.x]))\n .y((d) -> y(d[options.y]))\n\n linePath = null\n redraw = (data) ->\n linePath ||= chartController.getChart().append(\"path\")\n .attr(\"class\", \"line line-#{options.name or options.y}\")\n .style(\"fill\", \"none\")\n .style(\"stroke\", options.stroke)\n\n return unless data? and data.length isnt 0\n linePath.datum(data)\n .transition()\n .duration(500)\n .attr(\"d\", line)\n\n chartController.registerElement(redraw, options.order)\n\n\n\n/** WEBPACK FOOTER **\n ** ./angularD3/directives/line.coffee\n **/","angular.module('ad3').directive 'd3Pie', ->\n defaults = ->\n x: 0\n y: 1\n innerRadius: 0\n labelRadius: 0.7\n transition: \"cubic-in-out\"\n transitionDuration: 800\n minOffset: 12\n value: 'value'\n\n restrict: 'E'\n\n require: '^d3Chart'\n\n link: (scope, el, attrs, chartController) ->\n options = angular.extend(defaults(), attrs)\n\n chart = chartController.getChart()\n innerRadius = parseFloat(options.innerRadius)\n labelRadius = parseFloat(options.labelRadius)\n\n if attrs.colors\n colorScale = switch attrs.colors\n when 'category20'\n d3.scale.category20()\n when 'category20b'\n d3.scale.category20b()\n when 'category20c'\n d3.scale.category20c()\n\n pie = d3.layout.pie().sort(null)\n .value((d) -> d[options.value])\n\n _current = null\n\n center = null\n redraw = (data) ->\n center ||= chartController.getChart().append(\"g\").attr(\"class\", \"pie\")\n\n return unless data? and data.length isnt 0\n\n radius = Math.min(chartController.innerWidth, chartController.innerHeight)/2\n\n center.attr(\"transform\", \"translate(\" + radius + \",\" + radius + \")\")\n\n arc = d3.svg.arc()\n .outerRadius(radius)\n .innerRadius(radius * innerRadius)\n\n arcTween = (a) ->\n i = d3.interpolate(@_current, a)\n @_current = i(0)\n (t) -> arc(i(t))\n\n labelArc = d3.svg.arc()\n .outerRadius(radius * labelRadius)\n .innerRadius(radius * labelRadius)\n\n slice = center.selectAll(\".pie\").data(pie(data))\n\n slice.enter().append(\"path\")\n .attr(\"class\", (d,i) -> \"pie pie-#{i}\")\n .attr(\"d\", arc)\n .each((d) -> @_current = d)\n\n slice.style('fill', (d,i) ->\n if colorScale then colorScale(i) else d[attrs.color]) if attrs.colors\n\n slice.exit().remove()\n\n slice.transition()\n .ease(options.transition)\n .duration(options.transitionDuration)\n .attrTween(\"d\", arcTween)\n\n if options.label\n prevbb = null\n padding = +options.minOffset\n getPosition = (d, i) ->\n position = labelArc.centroid(d)\n\n if options.avoidCollisions\n # Basic collision adjustment, doesn't seem to quite work all the time.\n # Adapted from: http://stackoverflow.com/a/20645255/235243\n\n relativePosition = [position[0], position[1]]\n if @_position\n relativePosition[0] -= @_position[0]\n relativePosition[1] -= @_position[1]\n\n # Translate and pad the bounding rectangle for collision detection\n thisbb = _.transform @getBoundingClientRect(), (r, v, k) ->\n switch k\n when 'left'\n r[k] = v - padding + relativePosition[0]\n when 'top'\n r[k] = v - padding + relativePosition[1]\n when 'right'\n r[k] = v + padding + relativePosition[0]\n when 'bottom'\n r[k] = v + padding + relativePosition[1]\n\n if prevbb and !(\n thisbb.right < prevbb.left ||\n thisbb.left > prevbb.right ||\n thisbb.bottom < prevbb.top ||\n thisbb.top > prevbb.bottom)\n ctx = thisbb.left + (thisbb.right - thisbb.left)/2\n cty = thisbb.top + (thisbb.bottom - thisbb.top)/2\n cpx = prevbb.left + (prevbb.right - prevbb.left)/2\n cpy = prevbb.top + (prevbb.bottom - prevbb.top)/2\n offset = Math.sqrt(Math.pow(ctx - cpx, 2) + Math.pow(cty - cpy, 2))/2\n offsetArc = d3.svg.arc()\n .outerRadius(radius * labelRadius + offset)\n .innerRadius(radius * labelRadius + offset)\n position = offsetArc.centroid(d)\n\n @_position = position\n prevbb = thisbb\n\n \"translate(#{position})\"\n\n label = center.selectAll(\"text\").data(pie(data))\n\n label.enter().append(\"text\")\n .style(\"text-anchor\", \"middle\")\n .attr(\"class\", (d,i) -> \"pie-label pie-label-#{i}\")\n\n label.exit().remove()\n\n label.text((d,i) -> data[i][options.label])\n\n label.transition()\n .ease(options.transition)\n .duration(options.transitionDuration)\n .attr(\"transform\", getPosition)\n\n chartController.registerElement(redraw, options.order)\n\n\n\n/** WEBPACK FOOTER **\n ** ./angularD3/directives/pie.coffee\n **/","angular = require('angular')\n\nangular.module('ad3', [])\n\nrequire('./services/d3service')\nrequire('./services/d3locale')\nrequire('./directives/arc')\nrequire('./directives/area')\nrequire('./directives/axis')\nrequire('./directives/bars')\nrequire('./directives/chart')\nrequire('./directives/data')\nrequire('./directives/gradient')\nrequire('./directives/include')\nrequire('./directives/line')\nrequire('./directives/pie')\n\n\n\n/** WEBPACK FOOTER **\n ** ./angularD3/index.coffee\n **/","d3 = require('d3')\n\n# d3Locale\n#\n# Usage\n# module.config(['d3localeProvider', (d3localeProvider) ->\n# d3localeProvider.setLocales({\n# \"en-us\": require('angularD3/locale/en-US'),\n# \"fr-ca\": require('angularD3/locale/fr-CA'),\n# \"zh-cn\": require('angularD3/locale/zh-CN'),\n# })\n#]).run(['d3locale', (d3locale) ->\n# d3locale.setLang('en-us')\n# ])\n\nangular.module('ad3').provider 'd3locale', ->\n localeDefinitions = {}\n\n @setLocales = (definitions) ->\n localeDefinitions = definitions\n\n @$get = ->\n updateLocale = (locale) ->\n d3.format = locale.numberFormat\n d3.time.format = locale.timeFormat\n\n return {\n setLang: (lang) ->\n try\n locale = d3.locale(localeDefinitions[lang.toLowerCase()])\n updateLocale(locale)\n catch err\n throw \"d3locale error: '#{lang}' is a locale that either does not exist, or has not been loaded properly.\"\n\n setLocale: (locale) ->\n updateLocale(d3.locale(locale))\n }\n\n @\n\n\n\n/** WEBPACK FOOTER **\n ** ./angularD3/services/d3locale.coffee\n **/","d3 = require('d3')\n\nangular.module('ad3').provider 'd3Service', () ->\n defaults = @defaults = {}\n\n @$get = ['$cacheFactory', '$rootScope', '$q', ($cacheFactory, $rootScope, $q) ->\n cache = defaults.cache or $cacheFactory('d3Service')\n\n csv: (src, accessor, callback) ->\n deferred = $q.defer()\n cached = cache.get(src)\n if cached\n callback(rows) if callback\n deferred.resolve(cached)\n d3.csv src, accessor, (rows) ->\n $rootScope.$apply ->\n callback(rows) if callback\n if rows\n cache.put(src, rows)\n deferred.resolve(rows)\n else\n deferred.reject()\n return deferred.promise\n ]\n\n @\n\n\n\n/** WEBPACK FOOTER **\n ** ./angularD3/services/d3service.coffee\n **/","module.exports = angular;\n\n\n/*****************\n ** WEBPACK FOOTER\n ** external \"angular\"\n ** module id = 15\n ** module chunks = 0\n **/"],"sourceRoot":""} -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | require('./angularD3') 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular_d3", 3 | "version": "0.1.1", 4 | "description": "AngularJS chart directives and other integrations for D3.js", 5 | "keywords": [ 6 | "AngularJS", 7 | "D3", 8 | "D3.js", 9 | "charts" 10 | ], 11 | "bugs": { 12 | "url": "https://github.com/WealthBar/angualr-d3/issues" 13 | }, 14 | "author": "Chris Nicola (https://twitter.com/chrismnicola)", 15 | "license": "MIT", 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/WealthBar/angular-d3.git" 19 | }, 20 | "main": "dist/angularD3.js", 21 | "dependencies": { 22 | "angular": "^1.4.8", 23 | "d3": "^3.5.9" 24 | }, 25 | "devDependencies": { 26 | "angular": "^1.4.8", 27 | "bootstrap": "^3.3.6", 28 | "coffee-loader": "^0.7.2", 29 | "coffee-script": "^1.10.0", 30 | "css-loader": "^0.23.0", 31 | "d3": "^3.5.9", 32 | "extract-text-webpack-plugin": "^0.9.1", 33 | "file-loader": "^0.8.5", 34 | "html-loader": "^0.4.0", 35 | "html-webpack-plugin": "^1.7.0", 36 | "jquery": "^2.1.4", 37 | "less": "^2.5.3", 38 | "less-loader": "^2.2.2", 39 | "ngtemplate-loader": "^1.3.1", 40 | "node-sass": "^3.4.2", 41 | "sass-loader": "^3.1.2", 42 | "style-loader": "^0.13.0", 43 | "webpack": "^1.12.9", 44 | "webpack-dev-server": "^1.14.0" 45 | }, 46 | "scripts": { 47 | "start": "webpack-dev-server", 48 | "build": "BUILD_ASSETS=true webpack -p", 49 | "docs": "BUILD_DOCS=true webpack -p" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | // Example webpack configuration with asset fingerprinting in production. 2 | 'use strict'; 3 | 4 | var path = require('path'); 5 | var url = require('url'); 6 | var webpack = require('webpack'); 7 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 8 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 9 | 10 | var PATHS = { 11 | app: path.join(__dirname, 'app'), 12 | angularD3: './index.js', 13 | dist: path.join(__dirname, 'dist'), 14 | docs: path.join(__dirname, 'docs'), 15 | styles: path.join(__dirname, 'app/styles/index.scss'), 16 | } 17 | 18 | var config = { 19 | entry: { 20 | "angularD3": PATHS.angularD3, 21 | "app": PATHS.app 22 | }, 23 | resolve: { extensions: ['', '.js', '.coffee', '.css', '.scss', '.less'], }, 24 | output: { 25 | path: PATHS.dist, 26 | filename: "[name].js" 27 | }, 28 | module: { 29 | loaders: [ 30 | { test: /\.coffee$/, loader: "coffee-loader" }, 31 | { test: /\.css$/, loader: ExtractTextPlugin.extract("style", "css") }, 32 | { test: /\.scss$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader?sourceMap!sass-loader?sourceMap") }, 33 | { test: /\.(ttf|svg|png|gif|jpg|woff|woff2|eot|csv)$/, loader: "file" }, 34 | { test: /\.html$/, loader: "ngtemplate!html" }, 35 | ] 36 | }, 37 | plugins: [ 38 | new ExtractTextPlugin("[name].css") 39 | ] 40 | } 41 | 42 | if (process.env.BUILD_ASSETS === "true") { 43 | console.log("Building assets...") 44 | config.entry = { "angularD3": PATHS.angularD3 } 45 | config.devtool = 'source-map' 46 | config.output.devtoolModuleFilenameTemplate = '[resourcePath]' 47 | config.output.devtoolFallbackModuleFilenameTemplate = '[resourcePath]?[hash]' 48 | config.externals ={ "angular": "angular", "d3": "d3"} 49 | 50 | } else if (process.env.BUILD_DOCS === "true") { 51 | config.devtool = 'source-map' 52 | config.output.path = PATHS.docs 53 | config.output.devtoolModuleFilenameTemplate = '[resourcePath]' 54 | config.output.devtoolFallbackModuleFilenameTemplate = '[resourcePath]?[hash]' 55 | config.plugins.push ( 56 | new HtmlWebpackPlugin({ 57 | template: path.join(PATHS.app, 'index.html'), 58 | favicon: path.join(PATHS.app, 'favicon.ico'), 59 | inject: 'body' 60 | }) 61 | ) 62 | } else { 63 | config.devtool = 'source-map' 64 | config.plugins.push ( 65 | new HtmlWebpackPlugin({ 66 | template: path.join(PATHS.app, 'index.html'), 67 | favicon: path.join(PATHS.app, 'favicon.ico'), 68 | inject: 'body' 69 | }) 70 | ) 71 | } 72 | 73 | module.exports = config; 74 | --------------------------------------------------------------------------------