├── .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.