├── .editorconfig
├── .gitignore
├── .jshintrc
├── .npmignore
├── .travis.yml
├── CONTRIBUTING.md
├── Gruntfile.js
├── ISSUE_TEMPLATE.md
├── LICENSE
├── README.md
├── bower.json
├── dist
├── highcharts-ng.css
├── highcharts-ng.js
└── highcharts-ng.min.js
├── example
├── charts
│ ├── app.js
│ ├── general-example.html
│ ├── highstocks-app.js
│ └── highstocks-example.html
├── lazyload
│ ├── app.js
│ └── example.html
└── maps
│ ├── app.js
│ └── example.html
├── jsfiddles
├── basic
│ ├── demo.details
│ ├── demo.html
│ └── demo.js
├── disabled_change_detection
│ ├── demo.details
│ ├── demo.html
│ └── demo.js
├── dynamic_axis
│ ├── demo.details
│ ├── demo.html
│ └── demo.js
├── multi_axis
│ ├── demo.details
│ ├── demo.html
│ └── demo.js
├── polar
│ ├── demo.css
│ ├── demo.details
│ ├── demo.html
│ └── demo.js
├── recreating
│ ├── demo.details
│ ├── demo.html
│ └── demo.js
└── resizing
│ ├── demo.details
│ ├── demo.html
│ └── demo.js
├── karma.conf.js
├── package.json
├── src
├── highcharts-ng.css
└── highcharts-ng.js
└── test
├── .jshintrc
├── highcharts-mock.js
└── spec
└── highcharts-ng.js
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /bower_components/
2 | /node_modules/
3 | npm-debug.log
4 |
5 | /.idea/
6 | .DS_Store
7 | coverage
8 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "browser": true,
4 | "esnext": true,
5 | "bitwise": true,
6 | "camelcase": true,
7 | "curly": false,
8 | "eqeqeq": true,
9 | "immed": true,
10 | "indent": 2,
11 | "latedef": "nofunc",
12 | "newcap": true,
13 | "noarg": true,
14 | "quotmark": "single",
15 | "regexp": true,
16 | "undef": true,
17 | "unused": false,
18 | "strict": true,
19 | "globalstrict": false,
20 | "trailing": true,
21 | "smarttabs": true,
22 | "predef": [
23 | "angular",
24 | "Highcharts"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /bower_components/
2 | /node_modules/
3 | npm-debug.log
4 |
5 | /.idea/
6 | .DS_Store
7 |
8 | /test/
9 | /src/
10 | /example/
11 | .editorconfig
12 | bower.json
13 | CONTRIBUTING.md
14 | Gruntfile.js
15 | karma.conf.js
16 | README.md
17 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '6.3'
4 | sudo: false
5 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | ### New Issues/Bugs/Feature Requests etc.
4 | Please submit any problems you find - that's how things get better! To make life easier though it's best to fork one of the example jsfiddles and edit it so that it shows your problem. It's fine if it doesn't work (that's often the point!)
5 |
6 | ### Editing files
7 | Please don't edit files in the `dist` subdirectory as they are generated via Grunt. You'll find source code in the `src` subdirectory!
8 |
9 | ### Code style
10 | Regarding code style like indentation and whitespace, **follow the conventions you see used in the source already.**
11 |
12 | ### PhantomJS
13 | While Grunt can run the included unit tests via [PhantomJS](http://phantomjs.org/), this shouldn't be considered a substitute for the real thing. Please be sure to test the `test/*.html` unit test file(s) in _actual_ browsers.
14 |
15 | ## Modifying the code
16 | First, ensure that you have the latest [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) installed.
17 |
18 | Test that Grunt's CLI and Bower are installed by running `grunt --version` and `bower --version`. If the commands aren't found, run `npm install -g grunt-cli bower`. For more information about installing the tools, see the [getting started with Grunt guide](http://gruntjs.com/getting-started) or [bower.io](http://bower.io/) respectively.
19 |
20 | 1. Fork and clone the repo.
21 | 1. Run `npm install` to install all build dependencies (including Grunt).
22 | 1. Run `bower install` to install the front-end dependencies.
23 | 1. Run `grunt` to grunt this project.
24 |
25 | Assuming that you don't see any red, you're ready to go. Just be sure to run `grunt` after making any changes, to ensure that nothing is broken.
26 |
27 | ## Submitting pull requests
28 |
29 | 1. Create a new branch, please don't work in your `master` branch directly.
30 | 1. Add failing tests for the change you want to make. Run `grunt` to see the tests fail.
31 | 1. Fix stuff.
32 | 1. Run `grunt` to see if the tests pass. Repeat steps 2-4 until done.
33 | 1. Open `test/*.html` unit test file(s) in actual browser to ensure tests pass everywhere.
34 | 1. Update the documentation to reflect any changes.
35 | 1. Push to your fork and submit a pull request.
36 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | // Generated on 2013-11-30 using generator-angular-component 0.2.3
2 | 'use strict';
3 |
4 | module.exports = function(grunt) {
5 |
6 | // Configurable paths
7 | var yoConfig = {
8 | livereload: 35729,
9 | src: 'src',
10 | dist: 'dist'
11 | };
12 |
13 | // Livereload setup
14 | var lrSnippet = require('connect-livereload')({port: yoConfig.livereload});
15 | var mountFolder = function (connect, dir) {
16 | return connect.static(require('path').resolve(dir));
17 | };
18 |
19 | require('load-grunt-tasks')(grunt);
20 |
21 | // Project configuration
22 | grunt.initConfig({
23 | pkg: grunt.file.readJSON('package.json'),
24 | yo: yoConfig,
25 | meta: {
26 | banner: '/**\n' +
27 | ' * <%= pkg.name %>\n' +
28 | ' * @version v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
29 | ' * @link <%= pkg.homepage %>\n' +
30 | ' * @author <%= pkg.author.name %> <<%= pkg.author.email %>>\n' +
31 | ' * @license MIT License, http://www.opensource.org/licenses/MIT\n' +
32 | ' */\n'
33 | },
34 | open: {
35 | server: {
36 | path: 'http://localhost:<%= connect.options.port %>'
37 | }
38 | },
39 | clean: {
40 | dist: {
41 | files: [{
42 | dot: true,
43 | src: [
44 | '.tmp',
45 | '<%= yo.dist %>/*',
46 | '!<%= yo.dist %>/.git*'
47 | ]
48 | }]
49 | },
50 | server: '.tmp'
51 | },
52 | watch: {
53 | gruntfile: {
54 | files: '<%= jshint.gruntfile.src %>',
55 | tasks: ['jshint:gruntfile']
56 | },
57 | app: {
58 | files: [
59 | '{.tmp,<%= yo.src %>}/{,*/}*.js'
60 | ],
61 | options: {
62 | livereload: yoConfig.livereload
63 | }
64 | },
65 | test: {
66 | files: '<%= jshint.test.src %>',
67 | tasks: ['jshint:test', 'qunit']
68 | }
69 | },
70 | connect: {
71 | options: {
72 | port: 9000,
73 | hostname: '0.0.0.0' // Change this to '0.0.0.0' to access the server from outside.
74 | },
75 | livereload: {
76 | options: {
77 | middleware: function (connect) {
78 | return [
79 | lrSnippet,
80 | mountFolder(connect, '.tmp'),
81 | mountFolder(connect, yoConfig.src)
82 | ];
83 | }
84 | }
85 | }
86 | },
87 | jshint: {
88 | gruntfile: {
89 | options: {
90 | jshintrc: '.jshintrc'
91 | },
92 | src: 'Gruntfile.js'
93 | },
94 | src: {
95 | options: {
96 | jshintrc: '.jshintrc'
97 | },
98 | src: ['<%= yo.src %>/{,*/}*.js']
99 | },
100 | test: {
101 | options: {
102 | jshintrc: 'test/.jshintrc'
103 | },
104 | src: ['test/**/*.js']
105 | }
106 | },
107 | karma: {
108 | options: {
109 | configFile: 'karma.conf.js',
110 | browsers: ['PhantomJS']
111 | },
112 | unit: {
113 | singleRun: true
114 | },
115 | server: {
116 | autoWatch: true
117 | }
118 | },
119 | copy: {
120 | dist: {
121 | expand: true,
122 | cwd: '<%= yo.src %>',
123 | src: '**',
124 | dest: '<%= yo.dist %>'
125 | }
126 | },
127 | usebanner: {
128 | dist: {
129 | options: {
130 | position: 'top',
131 | banner: '<%= meta.banner %>'
132 | },
133 | files: {
134 | src: [ '<%= yo.dist %>/*.js' ]
135 | }
136 | }
137 | },
138 | uglify: {
139 | options: {
140 | banner: '<%= meta.banner %>'
141 | },
142 | dist: {
143 | files: {
144 | '<%= copy.dist.dest %>/<%= pkg.name %>.min.js': '<%= copy.dist.dest %>/<%= pkg.name %>.js',
145 | }
146 | }
147 | }
148 | });
149 |
150 | grunt.registerTask('test', [
151 | 'jshint',
152 | 'karma:unit'
153 | ]);
154 |
155 | grunt.registerTask('build', [
156 | 'clean:dist',
157 | 'copy:dist',
158 | 'usebanner:dist',
159 | 'uglify:dist'
160 | ]);
161 |
162 | grunt.registerTask('release', [
163 | 'test',
164 | 'bump-only',
165 | 'build',
166 | 'bump-commit'
167 | ]);
168 |
169 | grunt.registerTask('default', ['build']);
170 |
171 | };
172 |
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 | ## Link to jsfiddle showing the issue.
3 |
4 |
5 |
6 | ## Expected Behaviour
7 |
8 |
9 |
10 |
11 | ## Current Behaviour
12 |
13 |
14 |
15 | ## Your Environment
16 |
17 | * Version of highcharts-ng used:
18 | * Browser Name and version:
19 | * Operating System and version (desktop or mobile):
20 | * Link to your project:
21 |
22 |
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2013 Barry Fitzgerald http://pablojim.mit-license.org/
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.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | highcharts-ng
2 | =============
3 |
4 | AngularJS directive for Highcharts
5 |
6 | A simple Angularjs directive for Highcharts.
7 |
8 |
9 | Examples
10 | --------
11 |
12 | See example in ./example/charts/general-example.html (https://rawgit.com/pablojim/highcharts-ng/master/example/charts/general-example.html)
13 |
14 | Also:
15 |
16 | - Basic: http://jsfiddle.net/gh/get/jquery/3.1.1/pablojim/highcharts-ng/tree/master/jsfiddles/basic/
17 | - Polar Chart: http://jsfiddle.net/gh/get/jquery/3.1.1/pablojim/highcharts-ng/tree/master/jsfiddles/polar/
18 | - Multi Axis: http://jsfiddle.net/gh/get/jquery/3.1.1/pablojim/highcharts-ng/tree/master/jsfiddles/multi_axis/
19 | - Resizing to screen size: http://jsfiddle.net/gh/get/jquery/3.1.1/pablojim/highcharts-ng/tree/master/jsfiddles/resizing/
20 | - Disabled change detection http://jsfiddle.net/gh/get/jquery/3.1.1/pablojim/highcharts-ng/tree/master/jsfiddles/disabled_change_detection/
21 | - Recreating chart http://jsfiddle.net/gh/get/jquery/3.1.1/pablojim/highcharts-ng/tree/master/jsfiddles/recreating/
22 |
23 | License
24 | -------
25 | This library is available under the MIT license. However it and is a wrapper for Highcharts. Highcharts itself has an own license. So make sure to follow their license as well (https://github.com/highcharts/highcharts/blob/master/license.txt)
26 |
27 | Note: You need to include the Highcharts library your self. It is not included in this repository.
28 |
29 | Current Version
30 | ---------------
31 | **Needs Highcharts/Highstock >= 5.0.0**
32 |
33 | **Only supports AngularJS >= 1.5.8**
34 |
35 | **Configuration Format is not compatible with highcharts-ng 0.x.0**
36 |
37 |
38 | **Setup:**
39 |
40 | Install with npm:
41 |
42 | ```bash
43 | npm install highcharts-ng
44 | ```
45 |
46 | or with bower:
47 |
48 | ```bash
49 | bower install highcharts-ng --save
50 | ```
51 |
52 | Add highcharts as project dependency with npm
53 | ```bash
54 | npm install highcharts
55 | ```
56 |
57 | or with bower:
58 |
59 | ```bash
60 | bower install highcharts --save
61 | ```
62 |
63 | Add references to Highcharts/Highstocks:
64 |
65 | ```html
66 |
67 | ```
68 |
69 | or
70 |
71 | ```html
72 |
73 | ```
74 |
75 | Add Highcharts to your Angular app config:
76 |
77 | ```javascript
78 | var myapp = angular.module('myapp', ["highcharts-ng"]);
79 | ```
80 |
81 | (optional) if you have some problems with resizing the chart to screen size, include the highcharts-ng css file
82 |
83 | ```html
84 |
85 | ```
86 |
87 | Make a chart!
88 |
89 | ```html
90 |
91 | ```
92 |
93 | The `chartConfig` object should be the same as a normal highcharts configuration. Any options that work in highcharts should work here also. To use highstock charts, you just need to add `chartType: 'stock'` to your `chartConfig`.
94 |
95 | It is **Highly Recommended** to give all Series and Axes a distinct ID.
96 |
97 | All properties on the chart configuration are optional. If you don't need a feature best to leave it out completely - Highcharts will usually default to something sensible. Each property is watched for changes by angularjs.
98 |
99 | After construction the Highcharts Chart object can be accessed with ```chartConfig.getChartObj()```. This is a simple way to access all the Highcharts API that is not currently managed by this directive. See the JSFiddle basic example to see how this is used to call the print function of Highcharts.
100 |
101 | Sometimes it could make sense to create an entire new Highcharts Chart instead of updating the previous one. For this to happen, you need to pass an entire new chart configuration object to the component instead of updating the previous configuration object. (See example section above)
102 |
103 | If you know the chart data is not going to change, you can disabled the changeDetection to improve performance. This can be done with the attribute ```disable-change-detection="true"```. However this really only affects charts with huge data sets. (See example section above)
104 |
105 | Features:
106 | ---------
107 |
108 | - Adding and removing series
109 | - Setting/Updating Chart options
110 | - Updating the chart title
111 | - Resizes with screen size changes.
112 | - Providing a custom changeDetection function or expression - for speed a custom changeDetection function can be provided to save dirty checking the full chart config.
113 |
114 | Features Not Supported that were previously supported:
115 | ------------------------------------------------------
116 | - 2 way binding to chart xAxis. (use chartConfig.getChartObj() to get axis values)
117 | - Control of Loading status though the config (use chartConfig.getChartObj() to get axis values)
118 | Both of these should be possible to add with the right PR
119 | - Use of add and remove points on dynamically updated series
120 |
121 |
122 | Caveats:
123 | --------
124 |
125 | - Due to many equality checks the directive maybe slow with large datasets - try using changeDetection instead
126 | - Whole Chart/Series is often redrawn where a simple update of data would suffice
127 | - If you don't assign ids to your series - incremental ids will be added. This may mean extra redraws.
128 | - Needs more tests!
129 |
130 | FAQ:
131 | --------
132 |
133 |
134 | - Whats different to previous 0.0.X versions?
135 |
136 | This version is much much simpler and should be more stable. Some features however are still to be implemented
137 | e.g. 2-way binding to axes and loading functionality
138 |
139 | - How do I get access to the chart object?
140 |
141 | You can use `config.getChartObj`. 95% of the time you should not need this and should instead change the chartConfig instead.
142 |
143 | Be careful - if you manually change something with the chart object that is also in the chartConfig the chart and the config may end up out of sync.
144 |
145 | - Why don't you just use the standard Highcharts format?
146 |
147 | Since 1.0.0, vanilla Highcharts objects are supported!
148 |
149 |
150 |
151 | Versions
152 | --------
153 |
154 | Version 1.2.1
155 | -------------
156 | Fixes https://github.com/pablojim/highcharts-ng/issues/592
157 |
158 |
159 | Version 1.2.0
160 | -------------
161 | Remove explicit dependency on Highcharts due to licensing concerns and also allows user to choose between Highcharts and Highstocks.
162 |
163 | - added support for $onChanges, added new binding to disable change detection https://github.com/pablojim/highcharts-ng/pull/622
164 |
165 | Thanks to @ngehlert and others for their contributions.
166 |
167 | Version 1.1.0
168 | -------------
169 | Now has explicit dependency on highcharts.js.
170 |
171 | - Fix for resizing https://github.com/pablojim/highcharts-ng/issues/550
172 | - Added module loader support https://github.com/pablojim/highcharts-ng/commit/508df111886c4be8b26e82cb6d3e2303f17efed8
173 | Thanks to @houssemba and others for the contributions.
174 |
175 | Version 1.0.1
176 | -------------
177 | - Fix for for multiple yAxes https://github.com/pablojim/highcharts-ng/issues/201
178 |
179 | Version 1.0.0
180 | -------------
181 | - only support Highchart/Highstock >= 5.0.0
182 | - only support AngularJS >= 1.5.8 (see https://github.com/toddmotto/angular-component for lower versions)
183 | - Move to AngularJS Component
184 | - Now supports vanilla Highcharts config
185 | - Supports custom change detection functions
186 | - Should be much more stable and less bugs
187 | - 2 way axes binding no longer supported
188 | - loading property no longer supported
189 |
190 | Version 0.0.13
191 | --------------
192 | - Minor bugfix
193 |
194 | Version 0.0.12
195 | --------------
196 | - use addPoint where possible
197 | - seperate lazyloader - thanks @graingert
198 | - Lots of updates and fixes - thanks @graingert
199 |
200 | Version 0.0.11
201 | ----------------
202 | - Bug fix for console error with missing yAxis
203 |
204 | Version 0.0.10
205 | ----------------
206 | - Bug fix for 0.0.9 - problems with deep extend
207 |
208 | Version 0.0.9
209 | ----------------
210 | - Lazy loading - thanks @FDIM
211 | - Better navigator support - thanks @ASethi77
212 | - Lots of bug fixes - thanks to all contributors
213 |
214 | Version 0.0.8
215 | ----------------
216 | - added config.getHighcharts - thanks @ValentinH
217 | - Lots of bug fixes - thanks to all contributors
218 | - Now with support for Highmaps - see: http://rawgit.com/pablojim/highcharts-ng/master/example/maps/example.html
219 |
220 | Version 0.0.7
221 | ----------------
222 | - Better support for large data series - thanks @f1ghtingfalcons
223 | - Lots of bug fixes - thanks to all contributors
224 |
225 | Version 0.0.6
226 | ----------------
227 | - Added no data logic - thanks @eranbetzalel
228 | - Added reflow event thanks @pajooh
229 | - Added example for size setting
230 | - Minor bug fixes
231 |
232 | Version 0.0.5
233 | ----------------
234 | - Now watches size property
235 | - More robust checks around axes
236 |
237 | Version 0.0.4
238 | ----------------
239 | - Fix to minimised file
240 |
241 | Version 0.0.3
242 | ----------------
243 | - Migrated to grunt, bower and npm
244 | - Bug fixes
245 | - Some speedups
246 |
247 | Version 0.0.2
248 | ----------------
249 | - Removed JQuery dependency
250 | - Allowed for null config option
251 |
252 | Version 0.0.1 (not compatible with current version)
253 | ----------------
254 |
255 | ```html
256 |
257 | ```
258 |
259 | See an example here: [http://jsfiddle.net/pablojim/46rhz/](http://jsfiddle.net/pablojim/46rhz/)
260 |
261 |
262 | [](https://travis-ci.org/pablojim/highcharts-ng)
263 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "highcharts-ng",
3 | "description": "An AngularJS directive for Highcharts, Highstocks or Highmaps",
4 | "keywords": [
5 | "angularjs",
6 | "angular",
7 | "charts",
8 | "highcharts",
9 | "highstocks",
10 | "highmaps"
11 | ],
12 | "ignore": [
13 | "test",
14 | "src",
15 | "example",
16 | ".travis.yml"
17 | ],
18 | "version": "1.2.2-dev",
19 | "main": "dist/highcharts-ng.js",
20 | "license": "MIT",
21 | "authors": [
22 | { "name": "Barry Fitzgerald" }
23 | ],
24 | "dependencies": {},
25 | "devDependencies": {}
26 | }
27 |
--------------------------------------------------------------------------------
/dist/highcharts-ng.css:
--------------------------------------------------------------------------------
1 | highchart {
2 | display: block;
3 | width: 100%;
4 | max-width: 100%;
5 | }
6 |
--------------------------------------------------------------------------------
/dist/highcharts-ng.js:
--------------------------------------------------------------------------------
1 | /**
2 | * highcharts-ng
3 | * @version v1.2.2-dev - 2018-05-14
4 | * @link https://github.com/pablojim/highcharts-ng
5 | * @author Barry Fitzgerald <>
6 | * @license MIT License, http://www.opensource.org/licenses/MIT
7 | */
8 |
9 | if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.exports === exports){
10 | module.exports = 'highcharts-ng';
11 | }
12 |
13 | (function () {
14 | 'use strict';
15 | /*global angular: false*/
16 | var Highcharts = null;
17 |
18 | if (window && window.Highcharts) {
19 | Highcharts = window.Highcharts;
20 | } else if (typeof module !== 'undefined' && typeof exports !== 'undefined' &&
21 | module.exports === 'highcharts-ng'
22 | ) {
23 | Highcharts = require('highcharts');
24 | }
25 |
26 |
27 | angular.module('highcharts-ng', [])
28 | .component('highchart', {
29 | bindings: {
30 | config: '<',
31 | changeDetection: '<',
32 | disableChangeDetection: '<'
33 | },
34 | controller: HighChartNGController
35 | });
36 |
37 | HighChartNGController.$inject = ['$element', '$timeout'];
38 |
39 | function HighChartNGController($element, $timeout) {
40 | var initialized = false;
41 | var seriesId = 0;
42 | var yAxisId = 0;
43 | var xAxisId = 0;
44 | var ctrl = this;
45 | var prevConfig = {};
46 | var mergedConfig = {};
47 | var detector = ctrl.changeDetection || angular.equals;
48 |
49 | this.$onInit = function () {
50 | initChart();
51 | initialized = true;
52 | };
53 |
54 | this.$onChanges = function(changesObject) {
55 | if (changesObject.config && changesObject.config.currentValue !== undefined) {
56 | if (!initialized) {
57 | return;
58 | }
59 | initChart();
60 | }
61 | };
62 |
63 | this.removeItems = function (newItems, chartItems, id, toIgnore) {
64 | if (newItems && Array.isArray(newItems)) {
65 | var ids = ensureIds(newItems, id);
66 | for (var i = chartItems.length - 1; i >= 0; i -= 1) {
67 | var a = chartItems[i];
68 | if ((toIgnore.indexOf(a.options.id) < 0) && (ids.indexOf(a.options.id) < 0)) {
69 | //if we don't set redraw to true, it can create
70 | //glitches in the chart's rendering where the series
71 | //doesn't completely re-render
72 | a.remove(true);
73 | }
74 | }
75 | }
76 |
77 | };
78 |
79 | this.removeUnlinkedObjects = function (mergedConfig) {
80 | /*
81 | Removes unlinked objects, items that have been removed in the config,
82 | but not yet removed from the HighChart object
83 | */
84 | //First check to see if there are any axes that need to be removed
85 | //If a series is linked to the axis, it will be removed by HighCharts
86 | this.removeItems(mergedConfig.yAxis, ctrl.chart.yAxis, yAxisId, 'navigator-y-axis');
87 | this.removeItems(mergedConfig.xAxis, ctrl.chart.xAxis, xAxisId, 'navigator-x-axis');
88 | this.removeItems(mergedConfig.series, ctrl.chart.series, seriesId, 'highcharts-navigator-series');
89 | //TODO do we need to handle removing series from the config that highcharts has removed as part
90 | //of removing axes?
91 | };
92 |
93 | this.addAnyNewAxes = function (configAxes, chart, isX) {
94 | if (configAxes && Array.isArray(configAxes)) {
95 | angular.forEach(configAxes, function (s) {
96 | if (!chart.get(s.id)) {
97 | chart.addAxis(s, isX);
98 | }
99 | });
100 | }
101 | };
102 |
103 | this.$doCheck = function () {
104 | if (ctrl.disableChangeDetection === true) {
105 | return;
106 | }
107 | if (!detector(ctrl.config, prevConfig)) {
108 | prevConfig = angular.merge({}, ctrl.config);
109 | mergedConfig = getMergedOptions($element, ctrl.config, seriesId);
110 |
111 | //Remove any unlinked objects before adding
112 | this.removeUnlinkedObjects(mergedConfig);
113 |
114 | //Allows dynamic adding Axes
115 | this.addAnyNewAxes(mergedConfig.yAxis, ctrl.chart, false);
116 | this.addAnyNewAxes(mergedConfig.xAxis, ctrl.chart, true);
117 |
118 | //Allows dynamic adding of series
119 | if (mergedConfig.series) {
120 | // Add any new series
121 | angular.forEach(ctrl.config.series, function (s) {
122 | if (!ctrl.chart.get(s.id)) {
123 | ctrl.chart.addSeries(s);
124 | }
125 | });
126 | }
127 |
128 | ctrl.chart.update(mergedConfig, true);
129 | }
130 | };
131 |
132 | this.$onDestroy = function () {
133 | if (ctrl.chart) {
134 | try {
135 | ctrl.chart.destroy();
136 | } catch (ex) {
137 | // fail silently as highcharts will throw exception if element doesn't exist
138 | }
139 |
140 | $timeout(function () {
141 | $element.remove();
142 | }, 0);
143 | }
144 | };
145 |
146 | function initChart() {
147 | prevConfig = angular.merge({}, ctrl.config);
148 | mergedConfig = getMergedOptions($element, ctrl.config, seriesId);
149 | ctrl.chart = new Highcharts[getChartType(mergedConfig)](mergedConfig);
150 | ctrl.config.getChartObj = function () {
151 | return ctrl.chart;
152 | };
153 |
154 | // Fix resizing bug
155 | // https://github.com/pablojim/highcharts-ng/issues/550
156 | var originalWidth = $element[0].clientWidth;
157 | var originalHeight = $element[0].clientHeight;
158 | $timeout(function () {
159 | if ($element[0].clientWidth !== 0 && $element[0].clientHeight !== 0 && ($element[0].clientWidth !== originalWidth || $element[0].clientHeight !== originalHeight)) {
160 | ctrl.chart.reflow();
161 | }
162 | }, 0, false);
163 | }
164 | }
165 |
166 |
167 | function getMergedOptions(element, config, seriesId) {
168 | var mergedOptions = {};
169 |
170 | var defaultOptions = {
171 | chart: {
172 | events: {}
173 | },
174 | title: {},
175 | subtitle: {},
176 | series: [],
177 | credits: {},
178 | plotOptions: {},
179 | navigator: {},
180 | };
181 |
182 | if (config) {
183 | //check all series and axis ids are set
184 | if (config.series) {
185 | ensureIds(config.series, seriesId);
186 | }
187 |
188 | mergedOptions = angular.merge(defaultOptions, config);
189 | } else {
190 | mergedOptions = defaultOptions;
191 | }
192 | mergedOptions.chart.renderTo = element[0];
193 |
194 | //check chart type is set
195 | return mergedOptions;
196 | }
197 |
198 | var chartTypeMap = {
199 | 'stock': 'StockChart',
200 | 'map': 'Map',
201 | 'chart': 'Chart'
202 | };
203 |
204 | function getChartType(config) {
205 | if (config === undefined || config.chartType === undefined) return 'Chart';
206 | return chartTypeMap[('' + config.chartType).toLowerCase()];
207 | }
208 |
209 | function ensureIds(chartCollection, collectionId) {
210 | /*
211 | Ensures each item in the iteratble chartCollection has an id,
212 | and if not auto-generates one incrementing collectionId
213 | */
214 | var ids = [];
215 | angular.forEach(chartCollection, function (s) {
216 | if (!angular.isDefined(s.id)) {
217 | collectionId += 1;
218 | s.id = 'cc-' + collectionId;
219 | }
220 | ids.push(s.id);
221 | });
222 |
223 | return ids;
224 | }
225 |
226 |
227 | }());
228 |
--------------------------------------------------------------------------------
/dist/highcharts-ng.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * highcharts-ng
3 | * @version v1.2.2-dev - 2018-05-14
4 | * @link https://github.com/pablojim/highcharts-ng
5 | * @author Barry Fitzgerald <>
6 | * @license MIT License, http://www.opensource.org/licenses/MIT
7 | */
8 | "undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="highcharts-ng"),function(){"use strict";function a(a,f){function g(){m=angular.merge({},l.config),n=b(a,l.config,i),l.chart=new(e[c(n)])(n),l.config.getChartObj=function(){return l.chart};var d=a[0].clientWidth,g=a[0].clientHeight;f(function(){0===a[0].clientWidth||0===a[0].clientHeight||a[0].clientWidth===d&&a[0].clientHeight===g||l.chart.reflow()},0,!1)}var h=!1,i=0,j=0,k=0,l=this,m={},n={},o=l.changeDetection||angular.equals;this.$onInit=function(){g(),h=!0},this.$onChanges=function(a){if(a.config&&void 0!==a.config.currentValue){if(!h)return;g()}},this.removeItems=function(a,b,c,e){if(a&&Array.isArray(a))for(var f=d(a,c),g=b.length-1;g>=0;g-=1){var h=b[g];e.indexOf(h.options.id)<0&&f.indexOf(h.options.id)<0&&h.remove(!0)}},this.removeUnlinkedObjects=function(a){this.removeItems(a.yAxis,l.chart.yAxis,j,"navigator-y-axis"),this.removeItems(a.xAxis,l.chart.xAxis,k,"navigator-x-axis"),this.removeItems(a.series,l.chart.series,i,"highcharts-navigator-series")},this.addAnyNewAxes=function(a,b,c){a&&Array.isArray(a)&&angular.forEach(a,function(a){b.get(a.id)||b.addAxis(a,c)})},this.$doCheck=function(){l.disableChangeDetection!==!0&&(o(l.config,m)||(m=angular.merge({},l.config),n=b(a,l.config,i),this.removeUnlinkedObjects(n),this.addAnyNewAxes(n.yAxis,l.chart,!1),this.addAnyNewAxes(n.xAxis,l.chart,!0),n.series&&angular.forEach(l.config.series,function(a){l.chart.get(a.id)||l.chart.addSeries(a)}),l.chart.update(n,!0)))},this.$onDestroy=function(){if(l.chart){try{l.chart.destroy()}catch(b){}f(function(){a.remove()},0)}}}function b(a,b,c){var e={},f={chart:{events:{}},title:{},subtitle:{},series:[],credits:{},plotOptions:{},navigator:{}};return b?(b.series&&d(b.series,c),e=angular.merge(f,b)):e=f,e.chart.renderTo=a[0],e}function c(a){return void 0===a||void 0===a.chartType?"Chart":f[(""+a.chartType).toLowerCase()]}function d(a,b){var c=[];return angular.forEach(a,function(a){angular.isDefined(a.id)||(b+=1,a.id="cc-"+b),c.push(a.id)}),c}var e=null;window&&window.Highcharts?e=window.Highcharts:"undefined"!=typeof module&&"undefined"!=typeof exports&&"highcharts-ng"===module.exports&&(e=require("highcharts")),angular.module("highcharts-ng",[]).component("highchart",{bindings:{config:"<",changeDetection:"<",disableChangeDetection:"<"},controller:a}),a.$inject=["$element","$timeout"];var f={stock:"StockChart",map:"Map",chart:"Chart"}}();
--------------------------------------------------------------------------------
/example/charts/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var myapp = angular.module('myapp', ["highcharts-ng"]);
4 |
5 | myapp.controller('myctrl', function ($scope) {
6 |
7 | $scope.chartTypes = [
8 | {"id": "line", "title": "Line"},
9 | {"id": "spline", "title": "Smooth line"},
10 | {"id": "area", "title": "Area"},
11 | {"id": "areaspline", "title": "Smooth area"},
12 | {"id": "column", "title": "Column"},
13 | {"id": "bar", "title": "Bar"},
14 | {"id": "pie", "title": "Pie"},
15 | {"id": "scatter", "title": "Scatter"}
16 | ];
17 |
18 | $scope.dashStyles = [
19 | {"id": "Solid", "title": "Solid"},
20 | {"id": "ShortDash", "title": "ShortDash"},
21 | {"id": "ShortDot", "title": "ShortDot"},
22 | {"id": "ShortDashDot", "title": "ShortDashDot"},
23 | {"id": "ShortDashDotDot", "title": "ShortDashDotDot"},
24 | {"id": "Dot", "title": "Dot"},
25 | {"id": "Dash", "title": "Dash"},
26 | {"id": "LongDash", "title": "LongDash"},
27 | {"id": "DashDot", "title": "DashDot"},
28 | {"id": "LongDashDot", "title": "LongDashDot"},
29 | {"id": "LongDashDotDot", "title": "LongDashDotDot"}
30 | ];
31 |
32 | $scope.chartSeries = [
33 | {"name": "Some data", "data": [1, 2, 4, 7, 3], id: 's1'},
34 | {"name": "Some data 3", "data": [3, 1, null, 5, 2], connectNulls: true, id: 's2'},
35 | {"name": "Some data 2", "data": [5, 2, 2, 3, 5], type: "column", id: 's3'},
36 | {"name": "My Super Column", "data": [1, 1, 2, 3, 2], type: "column", id: 's4'}
37 | ];
38 |
39 | $scope.chartStack = [
40 | {"id": '', "title": "No"},
41 | {"id": "normal", "title": "Normal"},
42 | {"id": "percent", "title": "Percent"}
43 | ];
44 |
45 | $scope.addPoints = function () {
46 | var seriesArray = $scope.chartConfig.series;
47 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
48 | seriesArray[rndIdx].data = seriesArray[rndIdx].data.concat([1, 10, 20]);
49 | };
50 |
51 | var seriesId = 0;
52 | var yAxisId = 0;
53 | var xAxisId = 0;
54 |
55 | $scope.addAxis = function(xy) {
56 | /*
57 | Adds a Y Axis
58 | */
59 | var id;
60 | var axis;
61 | if (xy==='y') {
62 | yAxisId += 1;
63 | id = yAxisId;
64 | axis = 'yAxis';
65 | } else {
66 | xAxisId += 1;
67 | id = xAxisId;
68 | axis = 'xAxis';
69 | }
70 |
71 |
72 | var rnd = [];
73 | for (var i = 0; i < 10; i++) {
74 | rnd.push(Math.floor(Math.random() * 20) + 1);
75 | }
76 | if (!$scope.chartConfig[axis]) {
77 | $scope.chartConfig[axis] = [];
78 | }
79 | $scope.chartConfig[axis].push({
80 | min: Math.min.apply(null, rnd),
81 | max: Math.max.apply(null, rnd),
82 | title: {
83 | text: xy + "-Axis" + id.toString()
84 | },
85 | id: xy + 'Axis_' + id
86 | });
87 | };
88 |
89 |
90 | $scope.addSeries = function () {
91 | var rnd = []
92 | for (var i = 0; i < 10; i++) {
93 | rnd.push(Math.floor(Math.random() * 20) + 1)
94 | }
95 | var sId = '__series' + seriesId++;
96 | $scope.chartConfig.series.push({
97 | data: rnd,
98 | id: sId
99 | });
100 | };
101 |
102 | $scope.removeRandomSeries = function () {
103 | var seriesArray = $scope.chartConfig.series;
104 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
105 | seriesArray.splice(rndIdx, 1);
106 | };
107 |
108 | $scope.removeSeries = function (id) {
109 | var seriesArray = $scope.chartConfig.series;
110 | seriesArray.splice(id, 1);
111 | };
112 |
113 | $scope.toggleHighCharts = function () {
114 | this.chartConfig.useHighStocks = !this.chartConfig.useHighStocks;
115 | };
116 |
117 | $scope.replaceAllSeries = function () {
118 | var data = [
119 | { name: "first", data: [10], id: 'a' },
120 | { name: "second", data: [3], id: 'b' },
121 | { name: "third", data: [13], id: 'c' }
122 | ];
123 | $scope.chartConfig.series = data;
124 | };
125 |
126 | $scope.chartConfig = {
127 |
128 | chart: {
129 | height: 500,
130 | width: 500,
131 | type: 'line'
132 | },
133 | plotOptions: {
134 | series: {
135 | stacking: ''
136 | }
137 | },
138 | series: $scope.chartSeries,
139 | title: {
140 | text: 'Hello'
141 | }
142 | }
143 |
144 | $scope.reflow = function () {
145 | $scope.$broadcast('highchartsng.reflow');
146 | };
147 |
148 |
149 | });
150 |
--------------------------------------------------------------------------------
/example/charts/general-example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Highcharts-ng example
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | {{ chartConfig | json }}
29 |
30 |
31 | {{ chartConfig }}
32 |
33 |
34 |
{{chartConfig.getChartObj().chartHeight}}
35 |
36 |
37 |
Title
38 |
Subtitle
39 |
Width
40 |
Height
41 |
Default Type
42 |
Stack
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
Min:
53 |
Max:
54 |
Series
55 |
56 |
57 |
Title
58 |
Type
59 |
Color
60 |
Width
61 |
Dash Style
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/example/charts/highstocks-app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var myapp = angular.module('myapp', ["highcharts-ng"]);
4 |
5 | myapp.controller('myctrl', function ($scope) {
6 |
7 |
8 | $scope.chartConfig = {
9 | subtitle: {
10 | text: 'Click and drag to zoom in.'
11 | },
12 | chart: {
13 | height: 500,
14 | width: 500,
15 | backgroundColor: 'transparent',
16 | zoomType: 'xy',
17 | resetZoomButton: {
18 | position: {
19 | x: 0,
20 | y: -35
21 | },
22 | theme: {
23 | fill: 'white',
24 | stroke: 'silver',
25 | r: 0,
26 | states: {
27 | hover: {
28 | fill: '#41739D',
29 | style: {
30 | color: 'white'
31 | }
32 | }
33 | }
34 | }
35 | }
36 | },
37 | navigator: {
38 | enabled: true,
39 | series: {
40 | data: []
41 | }
42 | },
43 | rangeSelector: {
44 | enabled: false
45 | },
46 | plotOptions: {
47 | series: {
48 | lineWidth: 1,
49 | fillOpacity: 0.5
50 |
51 | },
52 | column: {
53 | stacking: 'normal'
54 | },
55 | area: {
56 | stacking: 'normal',
57 | marker: {
58 | enabled: false
59 | }
60 | }
61 |
62 | },
63 | exporting: false,
64 | xAxis: [{
65 | type: 'datetime'
66 | }],
67 | yAxis: [
68 |
69 | { // Primary yAxis
70 |
71 | min: 0,
72 | allowDecimals: false,
73 | title: {
74 | text: 'number of notification',
75 | style: {
76 | color: '#80a3ca'
77 | }
78 | },
79 | labels: {
80 | format: '{value}',
81 | style: {
82 | color: '#80a3ca'
83 | }
84 | }
85 |
86 |
87 | },
88 | { // Secondary yAxis
89 | min: 0,
90 | allowDecimals: false,
91 | title: {
92 | text: 'usage time',
93 | style: {
94 | color: '#c680ca'
95 | }
96 | },
97 | labels: {
98 | format: '{value}',
99 | style: {
100 | color: '#c680ca'
101 | }
102 | },
103 | opposite: true
104 |
105 | }
106 | ],
107 |
108 | legend: {
109 | enabled: false
110 | },
111 | title: {
112 | text: ' '
113 | },
114 | credits: {
115 | enabled: false
116 | },
117 |
118 | loading: false,
119 | tooltip: {
120 | crosshairs: [
121 | {
122 | width: 1,
123 | dashStyle: 'dash',
124 | color: '#898989'
125 | },
126 | {
127 | width: 1,
128 | dashStyle: 'dash',
129 | color: '#898989'
130 | }
131 | ],
132 | headerFormat: '',
133 | pointFormat: '{series.name}
{point.y:,.0f} {series.tooltipOptions.valueSuffix}
',
134 | borderWidth: 1,
135 | borderRadius: 5,
136 | borderColor: '#a4a4a4',
137 | shadow: false,
138 | useHTML: true,
139 | percentageDecimals: 2,
140 | backgroundColor: "rgba(255,255,255,.7)",
141 | style: {
142 | padding: 0
143 | },
144 | shared: true
145 |
146 | },
147 |
148 | series: [
149 | {
150 | id: 'iphoneNotificationData',
151 | name: 'Notifications',
152 | data: [[1426204800000, 12], [1426464000000, 6], [1426550400000, 10], [1426636800000, 3]],
153 | type: 'column',
154 | yAxis: 0,
155 | color: '#80a3ca'
156 | },
157 | {
158 | id: 'iphoneUsageData',
159 | name: 'Usage Time',
160 | data: [[1426291200000, 5], [1426809600000, 26]],
161 | type: 'line',
162 | yAxis: 1,
163 | tooltip: {
164 | valueSuffix: ' sec'
165 | },
166 | color: '#c680ca'
167 | }
168 | ],
169 |
170 |
171 |
172 | };
173 |
174 |
175 | });
176 |
--------------------------------------------------------------------------------
/example/charts/highstocks-example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
22 |
23 |
24 | HighStocks Example
25 |
26 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/example/lazyload/app.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Simple highcharts-ng maps example.
3 | */
4 | angular
5 | .module('app', ['highcharts-ng-lazyload'])
6 | .config(['highchartsNGProvider', function (highchartsNGProvider) {
7 | highchartsNGProvider.lazyLoad([highchartsNGProvider.HIGHCHART, "maps/modules/map.js", "mapdata/custom/world.js"]);
8 | }])
9 | .controller('MapController', function (highchartsNG, $scope) {
10 | var countries = {
11 | europe: 'France, Germany, Russia',
12 | asia: 'Japan, China'
13 | },
14 | defaultSeriesData = {
15 | allAreas: false,
16 | name: '',
17 | countries: '',
18 | data: [],
19 | dataLabels: {
20 | enabled: true,
21 | color: 'white',
22 | formatter: function () {
23 | if (this.point.value) {
24 | return this.point.name;
25 | }
26 | }
27 | },
28 | tooltip: {
29 | enabled: true,
30 | headerFormat: '',
31 | pointFormat: '{point.name}: {series.name}'
32 | }
33 | };
34 |
35 | this.makeSeries = function (name, countries) {
36 | var seriesData = angular.copy(defaultSeriesData);
37 |
38 | seriesData.name = name;
39 | seriesData.countries = countries;
40 | seriesData.data = this.makeSeriesData(countries);
41 |
42 | return seriesData;
43 | };
44 |
45 | this.makeSeriesData = function (string) {
46 | var list = ('' + string).split(','),
47 | data = [];
48 |
49 | angular.forEach(list, function (country) {
50 | data.push({
51 | name: country.replace(/^\s+|\s+$/, ''),
52 | value: 1
53 | });
54 | });
55 |
56 | return data;
57 | };
58 |
59 | this.setSeriesData = function (series, string) {
60 | series.data = this.makeSeriesData(string);
61 | };
62 |
63 | this.addSeries = function () {
64 | $scope.chartConfig.series.push(this.makeSeries());
65 | };
66 |
67 | this.removeSeries = function (key) {
68 | $scope.chartConfig.series.splice(key, 1);
69 |
70 | if (1 == $scope.chartConfig.series.length) {
71 | $scope.chartConfig.series[0].allAreas = true;
72 | }
73 | };
74 | $scope.chartConfig = {
75 | options: {
76 | legend: {
77 | enabled: false
78 | },
79 | plotOptions: {
80 |
81 | },
82 | },
83 | chartType: 'map',
84 | title: {
85 | text: 'Highcharts-ng map example'
86 | },
87 | series: [
88 | this.makeSeries('Europe', countries.europe),
89 | this.makeSeries('Asia', countries.asia)
90 | ]
91 | };
92 |
93 | $scope.chartConfig.series[0].allAreas = true;
94 | highchartsNG.getHighcharts().then(function(Highcharts){
95 | $scope.chartConfig.options.plotOptions.map = {
96 | mapData: Highcharts.maps['custom/world'],
97 | joinBy: ['name']
98 | };
99 | });
100 | });
101 |
--------------------------------------------------------------------------------
/example/lazyload/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Highcharts-ng maps example
7 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/example/maps/app.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Simple highcharts-ng maps example.
3 | */
4 | angular
5 | .module('app', ['highcharts-ng'])
6 | .controller('MapController', function() {
7 | var countries = {
8 | europe: 'France, Germany, Russia',
9 | asia: 'Japan, China'
10 | },
11 | defaultSeriesData = {
12 | allAreas: false,
13 | name: '',
14 | countries: '',
15 | data: [],
16 | dataLabels: {
17 | enabled: true,
18 | color: 'white',
19 | formatter: function () {
20 | if (this.point.value) {
21 | return this.point.name;
22 | }
23 | }
24 | },
25 | tooltip: {
26 | enabled: true,
27 | headerFormat: '',
28 | pointFormat: '{point.name}: {series.name}'
29 | }
30 | }
31 | ;
32 |
33 | this.makeSeries = function(name, countries) {
34 | var seriesData = angular.copy(defaultSeriesData);
35 |
36 | seriesData.name = name;
37 | seriesData.countries = countries;
38 | seriesData.data = this.makeSeriesData(countries);
39 |
40 | return seriesData;
41 | };
42 |
43 | this.makeSeriesData = function(string) {
44 | var list = ('' + string).split(','),
45 | data = []
46 | ;
47 |
48 | angular.forEach(list, function(country) {
49 | data.push({
50 | name: country.replace(/^\s+|\s+$/, ''),
51 | value: 1
52 | });
53 | });
54 |
55 | return data;
56 | };
57 |
58 | this.setSeriesData = function(series, string) {
59 | series.data = this.makeSeriesData(string);
60 | };
61 |
62 | this.addSeries = function() {
63 | this.config.series.push(this.makeSeries());
64 | };
65 |
66 | this.removeSeries = function(key) {
67 | this.config.series.splice(key, 1);
68 |
69 | if (1 == this.config.series.length) {
70 | this.config.series[0].allAreas = true;
71 | }
72 | };
73 |
74 | this.config = {
75 | legend: {
76 | enabled: false
77 | },
78 | plotOptions: {
79 | map: {
80 | mapData: Highcharts.maps['custom/world'],
81 | joinBy: ['name']
82 | }
83 | },
84 | animation: true,
85 | chartType: 'map',
86 | title: {
87 | text: 'Highcharts-ng map example'
88 | },
89 | series: [
90 | this.makeSeries('Europe', countries.europe),
91 | this.makeSeries('Asia', countries.asia)
92 | ]
93 | };
94 |
95 | this.config.series[0].allAreas = true;
96 | })
97 | ;
98 |
--------------------------------------------------------------------------------
/example/maps/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Highcharts-ng maps example
6 |
7 |
8 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/jsfiddles/basic/demo.details:
--------------------------------------------------------------------------------
1 | ---
2 | name: Basic Highcharts-ng demo
3 | description: Basic Highcharts-ng demo
4 | authors:
5 | - pablojim
6 | normalize_css: no
7 | ...
8 |
--------------------------------------------------------------------------------
/jsfiddles/basic/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/jsfiddles/basic/demo.js:
--------------------------------------------------------------------------------
1 | //See: https://github.com/pablojim/highcharts-ng
2 |
3 | $(function () {
4 | var myapp = angular.module('myapp', ["highcharts-ng"]);
5 |
6 | myapp.controller('myctrl', function ($scope) {
7 |
8 | $scope.addPoints = function () {
9 | var seriesArray = $scope.chartConfig.series
10 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
11 | seriesArray[rndIdx].data = seriesArray[rndIdx].data.concat([1, 10, 20])
12 | };
13 |
14 | var series = 0;
15 | $scope.addSeries = function () {
16 | var rnd = []
17 | for (var i = 0; i < 10; i++) {
18 | rnd.push(Math.floor(Math.random() * 20) + 1)
19 | }
20 | $scope.chartConfig.series.push({
21 | data: rnd,
22 | id: 'series_' + series++
23 | })
24 | }
25 |
26 | $scope.removeRandomSeries = function () {
27 | var seriesArray = $scope.chartConfig.series
28 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
29 | seriesArray.splice(rndIdx, 1)
30 | }
31 |
32 | $scope.swapChartType = function () {
33 | if (this.chartConfig.chart.type === 'line') {
34 | this.chartConfig.chart.type = 'bar'
35 | } else {
36 | this.chartConfig.chart.type = 'line'
37 | this.chartConfig.chart.zoomType = 'x'
38 | }
39 | }
40 |
41 | $scope.chartConfig = {
42 | chart: {
43 | type: 'bar'
44 | },
45 | series: [{
46 | data: [10, 15, 12, 8, 7],
47 | id: 'series1'
48 | }],
49 | title: {
50 | text: 'Hello'
51 | }
52 | }
53 |
54 | });
55 | })
56 |
--------------------------------------------------------------------------------
/jsfiddles/disabled_change_detection/demo.details:
--------------------------------------------------------------------------------
1 | ---
2 | name: Disabled change detection demo
3 | description: Disabled change detection Highcharts-ng demo
4 | authors:
5 | - ngehlert
6 | normalize_css: no
7 | ...
8 |
--------------------------------------------------------------------------------
/jsfiddles/disabled_change_detection/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/jsfiddles/disabled_change_detection/demo.js:
--------------------------------------------------------------------------------
1 | //See: https://github.com/pablojim/highcharts-ng
2 |
3 | $(function () {
4 | var myapp = angular.module('myapp', ["highcharts-ng"]);
5 |
6 | myapp.controller('myctrl', function ($scope) {
7 |
8 | $scope.addPoints = function () {
9 | var seriesArray = $scope.chartConfig.series
10 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
11 | seriesArray[rndIdx].data = seriesArray[rndIdx].data.concat([1, 10, 20])
12 | };
13 |
14 | var series = 0;
15 | $scope.addSeries = function () {
16 | var rnd = []
17 | for (var i = 0; i < 10; i++) {
18 | rnd.push(Math.floor(Math.random() * 20) + 1)
19 | }
20 | $scope.chartConfig.series.push({
21 | data: rnd,
22 | id: 'series_' + series++
23 | })
24 | }
25 |
26 | $scope.removeRandomSeries = function () {
27 | var seriesArray = $scope.chartConfig.series
28 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
29 | seriesArray.splice(rndIdx, 1)
30 | }
31 |
32 | $scope.swapChartType = function () {
33 | if (this.chartConfig.chart.type === 'line') {
34 | this.chartConfig.chart.type = 'bar'
35 | } else {
36 | this.chartConfig.chart.type = 'line'
37 | this.chartConfig.chart.zoomType = 'x'
38 | }
39 | }
40 |
41 | $scope.chartConfig = {
42 | chart: {
43 | type: 'bar'
44 | },
45 | series: [{
46 | data: [10, 15, 12, 8, 7],
47 | id: 'series1'
48 | }],
49 | title: {
50 | text: 'Hello'
51 | }
52 | }
53 |
54 | });
55 | })
56 |
--------------------------------------------------------------------------------
/jsfiddles/dynamic_axis/demo.details:
--------------------------------------------------------------------------------
1 | ---
2 | name: Basic Highcharts-ng demo
3 | description: Dynamic axis Highcharts-ng demo
4 | authors:
5 | - yoshi9143
6 | normalize_css: no
7 | ...
8 |
--------------------------------------------------------------------------------
/jsfiddles/dynamic_axis/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/jsfiddles/dynamic_axis/demo.js:
--------------------------------------------------------------------------------
1 | //See: https://github.com/pablojim/highcharts-ng
2 |
3 | $(function () {
4 | var myapp = angular.module('myapp', ["highcharts-ng"]);
5 |
6 | myapp.controller('myctrl', function ($scope) {
7 |
8 | $scope.addPoints = function () {
9 | var seriesArray = $scope.chartConfig.series;
10 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
11 | seriesArray[rndIdx].data = seriesArray[rndIdx].data.concat([1, 10, 20]);
12 | };
13 |
14 | var seriesIdx = 0;
15 | var yAxisIdx = 0;
16 | $scope.addYAxisFromSeries = function(seriesData) {
17 | /*
18 | Adds a Y Axis given seriesData (Array)
19 | */
20 | yAxisIdx += 1;
21 | $scope.chartConfig.yAxis.push({
22 | min: Math.min.apply(null, seriesData),
23 | max: Math.max.apply(null, seriesData),
24 | title: {
25 | text: "Y-Axis" + yAxisIdx.toString()
26 | },
27 | id: 'yAxis_' + yAxisIdx
28 | });
29 | };
30 |
31 | $scope.addSeries = function () {
32 | seriesIdx += 1;
33 | var rnd = [];
34 | for (var i = 0; i < 10; i++) {
35 | rnd.push(Math.floor(Math.random() * 20) + 1);
36 | }
37 | $scope.addYAxisFromSeries(rnd);
38 | $scope.chartConfig.series.push({
39 | data: rnd,
40 | yAxis: 'yAxis_' + yAxisIdx,
41 | id: 'series_' + seriesIdx
42 | });
43 | }
44 |
45 | $scope.removeRandomSeries = function () {
46 | var seriesArray = $scope.chartConfig.series;
47 | var yAxisArray = $scope.chartConfig.yAxis;
48 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
49 | seriesArray.splice(rndIdx, 1);
50 | yAxisArray.splice(rndIdx, 1);
51 | }
52 |
53 | $scope.chartConfig = {
54 | chart: {
55 | type: 'line'
56 | },
57 | navigator: {
58 | enabled: true
59 | },
60 | series: [{
61 | data: [10, 15, 12, 8, 7, 3, 5, 7, 10, 12, 5],
62 | yAxis: 'yAxis_0',
63 | id: 'series_0'
64 | }],
65 | title: {
66 | text: 'Hello'
67 | },
68 | xAxis: [{
69 | type: 'datetime'
70 | }],
71 | yAxis: [{ // Primary yAxis
72 | title: {
73 | text: 'number of notification',
74 | },
75 | id: 'yAxis_0'
76 | }],
77 | };
78 |
79 | });
80 | })
81 |
--------------------------------------------------------------------------------
/jsfiddles/multi_axis/demo.details:
--------------------------------------------------------------------------------
1 | ---
2 | name: Basic Highcharts-ng demo
3 | description: Multi axis Highcharts-ng demo
4 | authors:
5 | - pablojim
6 | normalize_css: no
7 | ...
8 |
--------------------------------------------------------------------------------
/jsfiddles/multi_axis/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/jsfiddles/multi_axis/demo.js:
--------------------------------------------------------------------------------
1 | //See: https://github.com/pablojim/highcharts-ng
2 |
3 | $(function () {
4 | var myapp = angular.module('myapp', ["highcharts-ng"]);
5 |
6 | myapp.controller('myctrl', function ($scope) {
7 |
8 | $scope.addPoints = function () {
9 | var seriesArray = $scope.chartConfig.series;
10 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
11 | seriesArray[rndIdx].data = seriesArray[rndIdx].data.concat([1, 10, 20]);
12 | };
13 |
14 | var series = 0;
15 | $scope.addSeries = function () {
16 | var rnd = [];
17 | for (var i = 0; i < 10; i++) {
18 | rnd.push(Math.floor(Math.random() * 20) + 1);
19 | }
20 | $scope.chartConfig.series.push({
21 | data: rnd,
22 | id: 'series_' + series++
23 | });
24 | }
25 |
26 | $scope.removeRandomSeries = function () {
27 | var seriesArray = $scope.chartConfig.series
28 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
29 | seriesArray.splice(rndIdx, 1);
30 | }
31 |
32 | $scope.chartConfig = {
33 | chart: {
34 | type: 'line'
35 | },
36 | series: [{
37 | data: [10, 15, 12, 8, 7],
38 | id: 'series1'
39 | }],
40 | title: {
41 | text: 'Hello'
42 | },
43 | xAxis: [{
44 | type: 'datetime'
45 | }],
46 | yAxis: [{ // Primary yAxis
47 | title: {
48 | text: 'number of notification',
49 | }
50 | }, { // Secondary yAxis
51 | title: {
52 | text: 'usage time',
53 | },
54 | opposite: true
55 | }],
56 | };
57 |
58 | });
59 | })
60 |
--------------------------------------------------------------------------------
/jsfiddles/polar/demo.css:
--------------------------------------------------------------------------------
1 | highchart {
2 | width: 100%;
3 | display: block;
4 | }
5 |
--------------------------------------------------------------------------------
/jsfiddles/polar/demo.details:
--------------------------------------------------------------------------------
1 | ---
2 | name: Highcharts-ng Polar
3 | description: A Highcharts-ng polar example.
4 | resources:
5 | ...
6 |
--------------------------------------------------------------------------------
/jsfiddles/polar/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/jsfiddles/polar/demo.js:
--------------------------------------------------------------------------------
1 | $(function () {
2 | //See: https://github.com/pablojim/highcharts-ng
3 | var myapp = angular.module('myapp', ["highcharts-ng"]);
4 |
5 | myapp.controller('myctrl', function ($scope) {
6 |
7 | $scope.addPoints = function () {
8 | var seriesArray = $scope.chartConfig.series
9 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
10 | seriesArray[rndIdx].data = seriesArray[rndIdx].data.concat([1, 10, 20])
11 | };
12 |
13 | var series = 0;
14 | $scope.addSeries = function () {
15 | var rnd = []
16 | for (var i = 0; i < 10; i++) {
17 | rnd.push(Math.floor(Math.random() * 20) + 1)
18 | }
19 | $scope.chartConfig.series.push({
20 | data: rnd,
21 | id: 'series_' + series++
22 | })
23 | }
24 |
25 | $scope.removeRandomSeries = function () {
26 | var seriesArray = $scope.chartConfig.series
27 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
28 | seriesArray.splice(rndIdx, 1)
29 | }
30 |
31 | $scope.swapChartType = function () {
32 | this.chartConfig.chart.polar = !this.chartConfig.chart.polar;
33 |
34 | }
35 |
36 | $scope.chartConfig = {
37 | chart: {
38 | polar: true
39 | },
40 |
41 | title: {
42 | text: 'Highcharts Polar Chart'
43 | },
44 |
45 | pane: {
46 | startAngle: 0,
47 | endAngle: 360
48 | },
49 |
50 | xAxis: {
51 | tickInterval: 45,
52 | min: 0,
53 | max: 360,
54 | labels: {
55 | formatter: function () {
56 | return this.value + '°';
57 | }
58 | }
59 | },
60 |
61 | yAxis: {
62 | min: 0
63 | },
64 |
65 | plotOptions: {
66 | series: {
67 | pointStart: 0,
68 | pointInterval: 45
69 | },
70 | column: {
71 | pointPadding: 0,
72 | groupPadding: 0
73 | }
74 | },
75 |
76 | series: [{
77 | type: 'column',
78 | name: 'Column',
79 | data: [8, 7, 6, 5, 4, 3, 2, 1],
80 | pointPlacement: 'between'
81 | }, {
82 | type: 'line',
83 | name: 'Line',
84 | data: [1, 2, 3, 4, 5, 6, 7, 8]
85 | }, {
86 | type: 'area',
87 | name: 'Area',
88 | data: [1, 8, 2, 7, 3, 6, 4, 5]
89 | }]
90 | }
91 |
92 | });
93 | })
94 |
--------------------------------------------------------------------------------
/jsfiddles/recreating/demo.details:
--------------------------------------------------------------------------------
1 | ---
2 | name: Recreating chart demo
3 | description: Recreating chart demo
4 | authors:
5 | - ngehlert
6 | normalize_css: no
7 | ...
8 |
--------------------------------------------------------------------------------
/jsfiddles/recreating/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/jsfiddles/recreating/demo.js:
--------------------------------------------------------------------------------
1 | //See: https://github.com/pablojim/highcharts-ng
2 |
3 | $(function () {
4 | var myapp = angular.module('myapp', ["highcharts-ng"]);
5 |
6 | myapp.controller('myctrl', function ($scope) {
7 |
8 | $scope.addPoints = function () {
9 | var seriesArray = $scope.chartConfig.series
10 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
11 | seriesArray[rndIdx].data = seriesArray[rndIdx].data.concat([1, 10, 20])
12 |
13 | // this is the important row, creating a new object
14 | $scope.chartConfig = angular.copy(this.chartConfig);
15 | };
16 |
17 | var series = 0;
18 | $scope.addSeries = function () {
19 | var rnd = []
20 | for (var i = 0; i < 10; i++) {
21 | rnd.push(Math.floor(Math.random() * 20) + 1)
22 | }
23 | $scope.chartConfig.series.push({
24 | data: rnd,
25 | id: 'series_' + series++
26 | })
27 |
28 | // this is the important row, creating a new object
29 | $scope.chartConfig = angular.copy(this.chartConfig);
30 | }
31 |
32 | $scope.removeRandomSeries = function () {
33 | var seriesArray = $scope.chartConfig.series
34 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
35 | seriesArray.splice(rndIdx, 1)
36 |
37 | // this is the important row, creating a new object
38 | $scope.chartConfig = angular.copy(this.chartConfig);
39 | }
40 |
41 | $scope.swapChartType = function () {
42 | if (this.chartConfig.chart.type === 'line') {
43 | this.chartConfig.chart.type = 'bar'
44 | } else {
45 | this.chartConfig.chart.type = 'line'
46 | this.chartConfig.chart.zoomType = 'x'
47 | }
48 |
49 | // this is the important row, creating a new object
50 | $scope.chartConfig = angular.copy(this.chartConfig);
51 | };
52 |
53 | $scope.chartConfig = {
54 | chart: {
55 | type: 'bar'
56 | },
57 | series: [{
58 | data: [10, 15, 12, 8, 7],
59 | id: 'series1'
60 | }],
61 | title: {
62 | text: 'Hello'
63 | }
64 | }
65 |
66 | });
67 | })
68 |
--------------------------------------------------------------------------------
/jsfiddles/resizing/demo.details:
--------------------------------------------------------------------------------
1 | ---
2 | name: Resizing demo
3 | description: Resizing the chart to scren size
4 | authors:
5 | - pablojim
6 | - houssemba
7 | normalize_css: no
8 | ...
9 |
--------------------------------------------------------------------------------
/jsfiddles/resizing/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/jsfiddles/resizing/demo.js:
--------------------------------------------------------------------------------
1 | //See: https://github.com/pablojim/highcharts-ng
2 |
3 | $(function () {
4 | var myapp = angular.module('myapp', ["highcharts-ng"]);
5 |
6 | myapp.controller('myctrl', function ($scope) {
7 |
8 | $scope.addPoints = function () {
9 | var seriesArray = $scope.chartConfig.series
10 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
11 | seriesArray[rndIdx].data = seriesArray[rndIdx].data.concat([1, 10, 20])
12 | };
13 |
14 | var series = 0;
15 | $scope.addSeries = function () {
16 | var rnd = []
17 | for (var i = 0; i < 10; i++) {
18 | rnd.push(Math.floor(Math.random() * 20) + 1)
19 | }
20 | $scope.chartConfig.series.push({
21 | data: rnd,
22 | id: 'series_' + series++
23 | })
24 | }
25 |
26 | $scope.removeRandomSeries = function () {
27 | var seriesArray = $scope.chartConfig.series
28 | var rndIdx = Math.floor(Math.random() * seriesArray.length);
29 | seriesArray.splice(rndIdx, 1)
30 | }
31 |
32 | $scope.swapChartType = function () {
33 | if (this.chartConfig.chart.type === 'line') {
34 | this.chartConfig.chart.type = 'bar'
35 | } else {
36 | this.chartConfig.chart.type = 'line'
37 | this.chartConfig.chart.zoomType = 'x'
38 | }
39 | }
40 |
41 | $scope.chartConfig = {
42 | chart: {
43 | type: 'bar'
44 | },
45 | series: [{
46 | data: [10, 15, 12, 8, 7],
47 | id: 'series1'
48 | }],
49 | title: {
50 | text: 'Hello'
51 | }
52 | }
53 |
54 | });
55 | })
56 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | module.exports = function(config) {
3 | config.set({
4 |
5 | // base path, that will be used to resolve files and exclude
6 | basePath: '',
7 |
8 | preprocessors: {
9 | 'app/scripts/**/*.js': 'coverage'
10 | },
11 |
12 | frameworks: ['jasmine'],
13 |
14 | // list of files / patterns to load in the browser
15 | files: [
16 | 'node_modules/angular/angular.js',
17 | 'node_modules/jquery/dist/jquery.js',
18 | 'node_modules/angular-mocks/angular-mocks.js',
19 | 'test/highcharts-mock.js',
20 | 'src/*.js',
21 | 'test/spec/*.js'
22 | ],
23 |
24 | // list of files to exclude
25 | exclude: [],
26 |
27 | // test results reporter to use
28 | // possible values: dots || progress || growl
29 | reporters: ['progress', 'coverage'],
30 |
31 | // web server port
32 | port: 8080,
33 |
34 | // cli runner port
35 | runnerPort: 9100,
36 |
37 | // enable / disable colors in the output (reporters and logs)
38 | colors: true,
39 |
40 | // level of logging
41 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
42 | logLevel: 'LOG_INFO',
43 |
44 | // enable / disable watching file and executing tests whenever any file changes
45 | autoWatch: false,
46 |
47 | // Start these browsers, currently available:
48 | // - Chrome
49 | // - ChromeCanary
50 | // - Firefox
51 | // - Opera
52 | // - Safari (only Mac)
53 | // - PhantomJS
54 | // - IE (only Windows)
55 | browsers: ['Chrome'],
56 |
57 | // If browser does not capture in given timeout [ms], kill it
58 | captureTimeout: 5000,
59 |
60 | // Continuous Integration mode
61 | // if true, it capture browsers, run tests and exit
62 | singleRun: false,
63 |
64 | coverageReporter: {
65 | type: 'html',
66 | dir: 'coverage/'
67 | },
68 | plugins: [
69 | require('karma-jasmine'),
70 | require('karma-coverage'),
71 | require('karma-phantomjs-launcher'),
72 | require('karma-chrome-launcher'),
73 | ]
74 |
75 | });
76 | };
77 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "highcharts-ng",
3 | "version": "1.2.2-dev",
4 | "description": "highcharts-ng",
5 | "keywords": [
6 | "angular"
7 | ],
8 | "homepage": "https://github.com/pablojim/highcharts-ng",
9 | "author": {
10 | "name": "Barry Fitzgerald",
11 | "email": "",
12 | "url": "https://github.com/pablojim"
13 | },
14 | "repository": {
15 | "type": "git",
16 | "url": "https://github.com/pablojim/highcharts-ng.git"
17 | },
18 | "license": "MIT",
19 | "devDependencies": {
20 | "angular": "^1.5.7",
21 | "angular-mocks": "^1.5.7",
22 | "connect-livereload": "~0.5.3",
23 | "grunt": "^1.0.1",
24 | "grunt-banner": "^0.6.0",
25 | "grunt-bump": "^0.8.0",
26 | "grunt-cli": "^1.2.0",
27 | "grunt-contrib-clean": "^1.0.0",
28 | "grunt-contrib-concat": "^1.0.1",
29 | "grunt-contrib-connect": "^1.0.2",
30 | "grunt-contrib-copy": "^1.0.0",
31 | "grunt-contrib-jshint": "^1.0.0",
32 | "grunt-contrib-uglify": "^1.0.1",
33 | "grunt-contrib-watch": "^1.0.0",
34 | "grunt-karma": "^2.0.0",
35 | "grunt-open": "~0.2.2",
36 | "jasmine-core": "^2.4.1",
37 | "jquery": "^3.1.0",
38 | "karma": "^1.1.1",
39 | "karma-chrome-launcher": "^1.0.1",
40 | "karma-coverage": "^1.1.0",
41 | "karma-jasmine": "^1.0.2",
42 | "karma-phantomjs-launcher": "^1.0.1",
43 | "load-grunt-tasks": "^3.5.0",
44 | "phantomjs-prebuilt": "^2.1.7"
45 | },
46 | "scripts": {
47 | "build": "grunt",
48 | "test": "grunt test"
49 | },
50 | "main": "./dist/highcharts-ng",
51 | "dependencies": {
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/highcharts-ng.css:
--------------------------------------------------------------------------------
1 | highchart {
2 | display: block;
3 | width: 100%;
4 | max-width: 100%;
5 | }
6 |
--------------------------------------------------------------------------------
/src/highcharts-ng.js:
--------------------------------------------------------------------------------
1 | if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.exports === exports){
2 | module.exports = 'highcharts-ng';
3 | }
4 |
5 | (function () {
6 | 'use strict';
7 | /*global angular: false*/
8 | var Highcharts = null;
9 |
10 | if (window && window.Highcharts) {
11 | Highcharts = window.Highcharts;
12 | } else if (typeof module !== 'undefined' && typeof exports !== 'undefined' &&
13 | module.exports === 'highcharts-ng'
14 | ) {
15 | Highcharts = require('highcharts');
16 | }
17 |
18 |
19 | angular.module('highcharts-ng', [])
20 | .component('highchart', {
21 | bindings: {
22 | config: '<',
23 | changeDetection: '<',
24 | disableChangeDetection: '<'
25 | },
26 | controller: HighChartNGController
27 | });
28 |
29 | HighChartNGController.$inject = ['$element', '$timeout'];
30 |
31 | function HighChartNGController($element, $timeout) {
32 | var initialized = false;
33 | var seriesId = 0;
34 | var yAxisId = 0;
35 | var xAxisId = 0;
36 | var ctrl = this;
37 | var prevConfig = {};
38 | var mergedConfig = {};
39 | var detector = ctrl.changeDetection || angular.equals;
40 |
41 | this.$onInit = function () {
42 | initChart();
43 | initialized = true;
44 | };
45 |
46 | this.$onChanges = function(changesObject) {
47 | if (changesObject.config && changesObject.config.currentValue !== undefined) {
48 | if (!initialized) {
49 | return;
50 | }
51 | initChart();
52 | }
53 | };
54 |
55 | this.removeItems = function (newItems, chartItems, id, toIgnore) {
56 | if (newItems && Array.isArray(newItems)) {
57 | var ids = ensureIds(newItems, id);
58 | for (var i = chartItems.length - 1; i >= 0; i -= 1) {
59 | var a = chartItems[i];
60 | if ((toIgnore.indexOf(a.options.id) < 0) && (ids.indexOf(a.options.id) < 0)) {
61 | //if we don't set redraw to true, it can create
62 | //glitches in the chart's rendering where the series
63 | //doesn't completely re-render
64 | a.remove(true);
65 | }
66 | }
67 | }
68 |
69 | };
70 |
71 | this.removeUnlinkedObjects = function (mergedConfig) {
72 | /*
73 | Removes unlinked objects, items that have been removed in the config,
74 | but not yet removed from the HighChart object
75 | */
76 | //First check to see if there are any axes that need to be removed
77 | //If a series is linked to the axis, it will be removed by HighCharts
78 | this.removeItems(mergedConfig.yAxis, ctrl.chart.yAxis, yAxisId, 'navigator-y-axis');
79 | this.removeItems(mergedConfig.xAxis, ctrl.chart.xAxis, xAxisId, 'navigator-x-axis');
80 | this.removeItems(mergedConfig.series, ctrl.chart.series, seriesId, 'highcharts-navigator-series');
81 | //TODO do we need to handle removing series from the config that highcharts has removed as part
82 | //of removing axes?
83 | };
84 |
85 | this.addAnyNewAxes = function (configAxes, chart, isX) {
86 | if (configAxes && Array.isArray(configAxes)) {
87 | angular.forEach(configAxes, function (s) {
88 | if (!chart.get(s.id)) {
89 | chart.addAxis(s, isX);
90 | }
91 | });
92 | }
93 | };
94 |
95 | this.$doCheck = function () {
96 | if (ctrl.disableChangeDetection === true) {
97 | return;
98 | }
99 | if (!detector(ctrl.config, prevConfig)) {
100 | prevConfig = angular.merge({}, ctrl.config);
101 | mergedConfig = getMergedOptions($element, ctrl.config, seriesId);
102 |
103 | //Remove any unlinked objects before adding
104 | this.removeUnlinkedObjects(mergedConfig);
105 |
106 | //Allows dynamic adding Axes
107 | this.addAnyNewAxes(mergedConfig.yAxis, ctrl.chart, false);
108 | this.addAnyNewAxes(mergedConfig.xAxis, ctrl.chart, true);
109 |
110 | //Allows dynamic adding of series
111 | if (mergedConfig.series) {
112 | // Add any new series
113 | angular.forEach(ctrl.config.series, function (s) {
114 | if (!ctrl.chart.get(s.id)) {
115 | ctrl.chart.addSeries(s);
116 | }
117 | });
118 | }
119 |
120 | ctrl.chart.update(mergedConfig, true);
121 | }
122 | };
123 |
124 | this.$onDestroy = function () {
125 | if (ctrl.chart) {
126 | try {
127 | ctrl.chart.destroy();
128 | } catch (ex) {
129 | // fail silently as highcharts will throw exception if element doesn't exist
130 | }
131 |
132 | $timeout(function () {
133 | $element.remove();
134 | }, 0);
135 | }
136 | };
137 |
138 | function initChart() {
139 | prevConfig = angular.merge({}, ctrl.config);
140 | mergedConfig = getMergedOptions($element, ctrl.config, seriesId);
141 | ctrl.chart = new Highcharts[getChartType(mergedConfig)](mergedConfig);
142 | ctrl.config.getChartObj = function () {
143 | return ctrl.chart;
144 | };
145 |
146 | // Fix resizing bug
147 | // https://github.com/pablojim/highcharts-ng/issues/550
148 | var originalWidth = $element[0].clientWidth;
149 | var originalHeight = $element[0].clientHeight;
150 | $timeout(function () {
151 | if ($element[0].clientWidth !== 0 && $element[0].clientHeight !== 0 && ($element[0].clientWidth !== originalWidth || $element[0].clientHeight !== originalHeight)) {
152 | ctrl.chart.reflow();
153 | }
154 | }, 0, false);
155 | }
156 | }
157 |
158 |
159 | function getMergedOptions(element, config, seriesId) {
160 | var mergedOptions = {};
161 |
162 | var defaultOptions = {
163 | chart: {
164 | events: {}
165 | },
166 | title: {},
167 | subtitle: {},
168 | series: [],
169 | credits: {},
170 | plotOptions: {},
171 | navigator: {},
172 | };
173 |
174 | if (config) {
175 | //check all series and axis ids are set
176 | if (config.series) {
177 | ensureIds(config.series, seriesId);
178 | }
179 |
180 | mergedOptions = angular.merge(defaultOptions, config);
181 | } else {
182 | mergedOptions = defaultOptions;
183 | }
184 | mergedOptions.chart.renderTo = element[0];
185 |
186 | //check chart type is set
187 | return mergedOptions;
188 | }
189 |
190 | var chartTypeMap = {
191 | 'stock': 'StockChart',
192 | 'map': 'Map',
193 | 'chart': 'Chart'
194 | };
195 |
196 | function getChartType(config) {
197 | if (config === undefined || config.chartType === undefined) return 'Chart';
198 | return chartTypeMap[('' + config.chartType).toLowerCase()];
199 | }
200 |
201 | function ensureIds(chartCollection, collectionId) {
202 | /*
203 | Ensures each item in the iteratble chartCollection has an id,
204 | and if not auto-generates one incrementing collectionId
205 | */
206 | var ids = [];
207 | angular.forEach(chartCollection, function (s) {
208 | if (!angular.isDefined(s.id)) {
209 | collectionId += 1;
210 | s.id = 'cc-' + collectionId;
211 | }
212 | ids.push(s.id);
213 | });
214 |
215 | return ids;
216 | }
217 |
218 |
219 | }());
220 |
--------------------------------------------------------------------------------
/test/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "browser": true,
4 | "esnext": true,
5 | "bitwise": true,
6 | "camelcase": false,
7 | "curly": false,
8 | "eqeqeq": true,
9 | "immed": true,
10 | "indent": 2,
11 | "latedef": true,
12 | "newcap": true,
13 | "noarg": true,
14 | "quotmark": "single",
15 | "regexp": true,
16 | "undef": true,
17 | "unused": false,
18 | "strict": false,
19 | "globalstrict": false,
20 | "trailing": true,
21 | "smarttabs": true,
22 | "predef": [
23 | "$",
24 | "angular",
25 | "describe",
26 | "beforeEach",
27 | "afterEach",
28 | "inject",
29 | "it",
30 | "expect",
31 | "HighCharts",
32 | "window",
33 | "module",
34 | "jasmine"
35 | ]
36 | }
37 |
--------------------------------------------------------------------------------
/test/highcharts-mock.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | window.Highcharts = (function () {
4 | var ns = {};
5 |
6 | ns.reset = function () {
7 | ns.chart = jasmine.createSpyObj('chart', [
8 | 'redraw',
9 | 'setTitle',
10 | 'hideLoading',
11 | 'destroy',
12 | 'get',
13 | 'addSeries',
14 | 'update']);
15 | ns.chart.series = [];
16 | ns.usedChartConstructor = null;
17 | ns.options = null;
18 | };
19 |
20 | ns.Chart = function (opt) {
21 | ns.options = opt;
22 | ns.usedChartConstructor = 'Chart';
23 | return ns.chart;
24 | };
25 | ns.StockChart = function (opt) {
26 | ns.options = opt;
27 | ns.usedChartConstructor = 'StockChart';
28 | return this.chart;
29 | };
30 | ns.Map = function (opt) {
31 | ns.options = opt;
32 | ns.usedChartConstructor = 'Map';
33 | return ns.chart;
34 | };
35 | return ns;
36 | }());
37 |
38 |
39 |
--------------------------------------------------------------------------------
/test/spec/highcharts-ng.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('Module: highchartsNg', function () {
4 | var scope,
5 | $sandbox,
6 | $compile,
7 | $timeout,
8 | options,
9 | title,
10 | destroyed,
11 | usedChartConstructor,
12 | chart;
13 |
14 |
15 | // load the controller's module
16 | beforeEach(module('highcharts-ng'));
17 |
18 | beforeEach(inject(function ($injector, $rootScope, _$compile_, _$timeout_) {
19 | title = {};
20 | destroyed = false;
21 | scope = $rootScope;
22 |
23 | window.Highcharts.reset();
24 | chart = window.Highcharts.chart;
25 |
26 | $compile = _$compile_;
27 | $timeout = _$timeout_;
28 |
29 | $sandbox = $('').appendTo($('body'));
30 | }));
31 |
32 | afterEach(function () {
33 | $sandbox.remove();
34 | scope.$destroy();
35 | });
36 |
37 | var templates = {
38 | 'default': {
39 | scope: {chartConfig: {}},
40 | element: ''
41 | },
42 | 'simpleChartConfig': {
43 | scope: {
44 | chartConfig: {
45 | chart: {type: 'bar'},
46 | series: [{data: [1, 2]}]
47 | }
48 | },
49 | element: ''
50 | },
51 | 'stockChartConfig': {
52 | scope: {
53 | chartConfig: {
54 | chartType: 'stock'
55 | }
56 | },
57 | element: ''
58 | }
59 | };
60 |
61 | function compileDirective(template) {
62 | template = template ? templates[template] : templates['default'];
63 | angular.extend(scope, template.scope || templates['default'].scope);
64 | var $element = $(template.element).appendTo($sandbox);
65 | $element = $compile($element)(scope);
66 | scope.$digest();
67 | return $element;
68 | }
69 |
70 | it('uses default options', function () {
71 | compileDirective();
72 |
73 | expect(options).not.toBe({});
74 | });
75 |
76 | it('passes options to highcharts', function () {
77 | compileDirective('simpleChartConfig');
78 | options = window.Highcharts.options;
79 | expect(options.chart.type).toBe('bar');
80 | expect(options.chart.series).toBe(templates.simpleChartConfig.series);
81 | });
82 |
83 | describe('Respects chartType', function () {
84 | beforeEach(function () {
85 | compileDirective('stockChartConfig');
86 | });
87 |
88 | it('uses highstocks', function () {
89 | usedChartConstructor = window.Highcharts.usedChartConstructor;
90 | expect(usedChartConstructor).toBe('StockChart');
91 | });
92 | });
93 |
94 | describe('when the scope is destroyed', function () {
95 | var elm;
96 |
97 | beforeEach(function () {
98 | elm = compileDirective();
99 | scope.$destroy();
100 | });
101 |
102 | it('destroys the chart', function () {
103 | expect(chart.destroy).toHaveBeenCalled();
104 | });
105 |
106 | it('removes the element', function () {
107 | $timeout.flush();
108 |
109 | expect($sandbox.children().length).toBe(0);
110 | });
111 | });
112 | });
113 |
--------------------------------------------------------------------------------