highcharts-ng-rails 0.0.3 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2d44849fc5f006276f6f570d58cc84cd977e0dfd
4
- data.tar.gz: 47a5f57fc5653de34d947dff8d2dc78ebfff2c5b
3
+ metadata.gz: 5efcce932c820f3505f256d788b361a40c3bd804
4
+ data.tar.gz: c8c84695a4acd68e52c3c751844343cadc892666
5
5
  SHA512:
6
- metadata.gz: c99170b2331eaba3c511d6c7fa98b5c79ce878e3f1f42bb6292d4ca070828f2fcd24b80564f4e501eed8ea159262be7ffa6b303afaeff4fcd7cd62d7e717b370
7
- data.tar.gz: 5e6507837b3b63f84fe381e1c16e7ead84dbb690d4f56208857257708a1eb227d715393404db3442898f3bcf4bba2164f6e32fa470c67464151d4229bd558edf
6
+ metadata.gz: 44f698b6e1775a9ff8226b9f069215a3e784300bc45e5d5e7f8466d0d28c9cc390b88226027a8054c850f10bb29d6bee7b56276383a30f723460e14941046e52
7
+ data.tar.gz: 9daae96317a7a6de351d74b1541df97c36ed83ce977dfed2f40d49e5d1bc673179e2138a995c316345a07a8da0e69d6b40d3f73c15969c8c14d9e47faf170d0b
@@ -7,7 +7,7 @@ This gem just includes [highcharts-ng](https://github.com/pablojim/highcharts-ng
7
7
  Add the gem to the Gemfile
8
8
 
9
9
  gem "highcharts-rails"
10
- gem "highcharts-ng-rails", "~> 0.0.3"
10
+ gem "highcharts-ng-rails", "~> 0.0.7"
11
11
  # The gem version mirrors the included version of highcharts-ng
12
12
 
13
13
  ## Usage
@@ -1,199 +1,352 @@
1
- 'use strict';
2
-
3
- angular.module('highcharts-ng', [])
4
- .directive('highchart', function () {
5
-
6
- function prependMethod(obj, method, func) {
7
- var original = obj[method];
8
- obj[method] = function () {
9
- var args = Array.prototype.slice.call(arguments);
10
- func.apply(this, args);
11
- if(original) {
12
- return original.apply(this, args);
13
- } else {
14
- return;
15
- }
1
+ (function () {
2
+ 'use strict';
3
+ /*global angular: false, Highcharts: false */
16
4
 
17
- };
18
- }
19
-
20
- function deepExtend(destination, source) {
21
- for (var property in source) {
22
- if (source[property] && source[property].constructor &&
23
- source[property].constructor === Object) {
24
- destination[property] = destination[property] || {};
25
- deepExtend(destination[property], source[property]);
5
+ angular.module('highcharts-ng', [])
6
+ .factory('highchartsNGUtils', highchartsNGUtils)
7
+ .directive('highchart', ['highchartsNGUtils', highchart]);
8
+
9
+ function highchartsNGUtils() {
10
+
11
+ return {
12
+
13
+ //IE8 support
14
+ indexOf: function (arr, find, i /*opt*/) {
15
+ if (i === undefined) i = 0;
16
+ if (i < 0) i += arr.length;
17
+ if (i < 0) i = 0;
18
+ for (var n = arr.length; i < n; i++)
19
+ if (i in arr && arr[i] === find)
20
+ return i;
21
+ return -1;
22
+ },
23
+
24
+ prependMethod: function (obj, method, func) {
25
+ var original = obj[method];
26
+ obj[method] = function () {
27
+ var args = Array.prototype.slice.call(arguments);
28
+ func.apply(this, args);
29
+ if (original) {
30
+ return original.apply(this, args);
31
+ } else {
32
+ return;
33
+ }
34
+
35
+ };
36
+ },
37
+
38
+ deepExtend: function deepExtend(destination, source) {
39
+ //Slightly strange behaviour in edge cases (e.g. passing in non objects)
40
+ //But does the job for current use cases.
41
+ if (angular.isArray(source)) {
42
+ destination = angular.isArray(destination) ? destination : [];
43
+ for (var i = 0; i < source.length; i++) {
44
+ destination[i] = deepExtend(destination[i] || {}, source[i]);
45
+ }
46
+ } else if (angular.isObject(source)) {
47
+ for (var property in source) {
48
+ destination[property] = deepExtend(destination[property] || {}, source[property]);
49
+ }
26
50
  } else {
27
- destination[property] = source[property];
51
+ destination = source;
28
52
  }
53
+ return destination;
29
54
  }
30
- return destination;
31
- }
55
+ };
56
+ }
57
+
58
+ function highchart(highchartsNGUtils) {
32
59
 
60
+ // acceptable shared state
33
61
  var seriesId = 0;
34
62
  var ensureIds = function (series) {
35
- series.forEach(function (s) {
63
+ var changed = false;
64
+ angular.forEach(series, function(s) {
36
65
  if (!angular.isDefined(s.id)) {
37
- s.id = "series-" + seriesId++;
66
+ s.id = 'series-' + seriesId++;
67
+ changed = true;
38
68
  }
39
69
  });
40
- }
70
+ return changed;
71
+ };
41
72
 
42
- var defaultOptions = {
43
- chart: {
44
- events: {}
45
- },
46
- title: {},
47
- series: [],
48
- navigator: {enabled: false}
49
- }
73
+ // immutable
74
+ var axisNames = [ 'xAxis', 'yAxis' ];
50
75
 
51
76
  var getMergedOptions = function (scope, element, config) {
52
- var mergedOptions = {}
77
+ var mergedOptions = {};
78
+
79
+ var defaultOptions = {
80
+ chart: {
81
+ events: {}
82
+ },
83
+ title: {},
84
+ subtitle: {},
85
+ series: [],
86
+ credits: {},
87
+ plotOptions: {},
88
+ navigator: {enabled: false}
89
+ };
90
+
53
91
  if (config.options) {
54
- mergedOptions = deepExtend(defaultOptions, config.options);
92
+ mergedOptions = highchartsNGUtils.deepExtend(defaultOptions, config.options);
55
93
  } else {
56
94
  mergedOptions = defaultOptions;
57
95
  }
58
96
  mergedOptions.chart.renderTo = element[0];
59
- if(config.xAxis) {
60
- prependMethod(mergedOptions.chart.events, 'selection', function(e){
61
- var thisChart = this;
62
- if(e.xAxis) {
63
- scope.$apply(function () {
64
- scope.config.xAxis.currentMin = e.xAxis[0].min;
65
- scope.config.xAxis.currentMax = e.xAxis[0].max;
97
+
98
+ angular.forEach(axisNames, function(axisName) {
99
+ if(angular.isDefined(config[axisName])) {
100
+ mergedOptions[axisName] = angular.copy(config[axisName]);
101
+
102
+ if(angular.isDefined(config[axisName].currentMin) ||
103
+ angular.isDefined(config[axisName].currentMax)) {
104
+
105
+ highchartsNGUtils.prependMethod(mergedOptions.chart.events, 'selection', function(e){
106
+ var thisChart = this;
107
+ if (e[axisName]) {
108
+ scope.$apply(function () {
109
+ scope.config[axisName].currentMin = e[axisName][0].min;
110
+ scope.config[axisName].currentMax = e[axisName][0].max;
111
+ });
112
+ } else {
113
+ //handle reset button - zoom out to all
114
+ scope.$apply(function () {
115
+ scope.config[axisName].currentMin = thisChart[axisName][0].dataMin;
116
+ scope.config[axisName].currentMax = thisChart[axisName][0].dataMax;
117
+ });
118
+ }
66
119
  });
67
- } else {
68
- //handle reset button - zoom out to all
69
- scope.$apply(function () {
70
- scope.config.xAxis.currentMin = thisChart.xAxis[0].dataMin;
71
- scope.config.xAxis.currentMax = thisChart.xAxis[0].dataMax;
120
+
121
+ highchartsNGUtils.prependMethod(mergedOptions.chart.events, 'addSeries', function(e){
122
+ scope.config[axisName].currentMin = this[axisName][0].min || scope.config[axisName].currentMin;
123
+ scope.config[axisName].currentMax = this[axisName][0].max || scope.config[axisName].currentMax;
72
124
  });
73
125
  }
74
- });
126
+ }
127
+ });
75
128
 
76
- prependMethod(mergedOptions.chart.events, 'addSeries', function(e){
77
- scope.config.xAxis.currentMin = this.xAxis[0].min || scope.config.xAxis.currentMin;
78
- scope.config.xAxis.currentMax = this.xAxis[0].max || scope.config.xAxis.currentMax;
79
- });
129
+ if(config.title) {
130
+ mergedOptions.title = config.title;
80
131
  }
81
-
82
- if(config.xAxis) {
83
- mergedOptions.xAxis = angular.copy(config.xAxis)
132
+ if (config.subtitle) {
133
+ mergedOptions.subtitle = config.subtitle;
84
134
  }
85
- if(config.title) {
86
- mergedOptions.title = config.title
135
+ if (config.credits) {
136
+ mergedOptions.credits = config.credits;
137
+ }
138
+ if(config.size) {
139
+ if (config.size.width) {
140
+ mergedOptions.chart.width = config.size.width;
141
+ }
142
+ if (config.size.height) {
143
+ mergedOptions.chart.height = config.size.height;
144
+ }
87
145
  }
88
- return mergedOptions
89
- }
146
+ return mergedOptions;
147
+ };
90
148
 
91
149
  var updateZoom = function (axis, modelAxis) {
92
150
  var extremes = axis.getExtremes();
93
151
  if(modelAxis.currentMin !== extremes.dataMin || modelAxis.currentMax !== extremes.dataMax) {
94
152
  axis.setExtremes(modelAxis.currentMin, modelAxis.currentMax, false);
95
153
  }
96
- }
154
+ };
97
155
 
98
- var processExtremes = function(chart, axis) {
156
+ var processExtremes = function(chart, axis, axisName) {
99
157
  if(axis.currentMin || axis.currentMax) {
100
- chart.xAxis[0].setExtremes(axis.currentMin, axis.currentMax, true);
101
- }
102
- }
103
-
104
- var processSeries = function(chart, series) {
105
- var ids = []
106
- if(series) {
107
- ensureIds(series);
108
-
109
- //Find series to add or update
110
- series.forEach(function (s) {
111
- ids.push(s.id)
112
- var chartSeries = chart.get(s.id);
113
- if (chartSeries) {
114
- chartSeries.update(angular.copy(s), false);
115
- } else {
116
- chart.addSeries(angular.copy(s), false)
117
- }
118
- });
119
- }
120
-
121
- //Now remove any missing series
122
- for(var i = chart.series.length - 1; i >= 0; i--) {
123
- var s = chart.series[i];
124
- if (ids.indexOf(s.options.id) < 0) {
125
- s.remove(false);
126
- }
127
- };
128
-
129
- }
130
-
131
- var initialiseChart = function(scope, element, config) {
132
- config || (config = {});
133
- var mergedOptions = getMergedOptions(scope, element, config);
134
- var chart = config.useHighStocks ? new Highcharts.StockChart(mergedOptions) : new Highcharts.Chart(mergedOptions);
135
- if(config.xAxis) {
136
- processExtremes(chart, config.xAxis);
137
- }
138
- processSeries(chart, config.series);
139
- if(config.loading) {
140
- chart.showLoading()
158
+ chart[axisName][0].setExtremes(axis.currentMin, axis.currentMax, true);
141
159
  }
142
- chart.redraw();
143
- return chart;
144
- }
160
+ };
145
161
 
162
+ var chartOptionsWithoutEasyOptions = function (options) {
163
+ return angular.extend({}, options, {data: null, visible: null});
164
+ };
146
165
 
147
166
  return {
148
167
  restrict: 'EAC',
149
168
  replace: true,
150
169
  template: '<div></div>',
151
170
  scope: {
152
- config: '='
171
+ config: '=',
172
+ disableDataWatch: '='
153
173
  },
154
174
  link: function (scope, element, attrs) {
175
+ // We keep some chart-specific variables here as a closure
176
+ // instead of storing them on 'scope'.
155
177
 
156
- var chart = initialiseChart(scope, element, scope.config);
178
+ // prevSeriesOptions is maintained by processSeries
179
+ var prevSeriesOptions = {};
157
180
 
158
- scope.$watch("config.series", function (newSeries, oldSeries) {
159
- //do nothing when called on registration
160
- if (newSeries === oldSeries) return;
161
- processSeries(chart, newSeries);
162
- chart.redraw();
163
- }, true);
181
+ var processSeries = function(series) {
182
+ var i;
183
+ var ids = [];
184
+
185
+ if(series) {
186
+ var setIds = ensureIds(series);
187
+ if(setIds) {
188
+ //If we have set some ids this will trigger another digest cycle.
189
+ //In this scenario just return early and let the next cycle take care of changes
190
+ return false;
191
+ }
192
+
193
+ //Find series to add or update
194
+ angular.forEach(series, function(s) {
195
+ ids.push(s.id);
196
+ var chartSeries = chart.get(s.id);
197
+ if (chartSeries) {
198
+ if (!angular.equals(prevSeriesOptions[s.id], chartOptionsWithoutEasyOptions(s))) {
199
+ chartSeries.update(angular.copy(s), false);
200
+ } else {
201
+ if (s.visible !== undefined && chartSeries.visible !== s.visible) {
202
+ chartSeries.setVisible(s.visible, false);
203
+ }
204
+ chartSeries.setData(angular.copy(s.data), false);
205
+ }
206
+ } else {
207
+ chart.addSeries(angular.copy(s), false);
208
+ }
209
+ prevSeriesOptions[s.id] = chartOptionsWithoutEasyOptions(s);
210
+ });
211
+
212
+ // Shows no data text if all series are empty
213
+ if(scope.config.noData) {
214
+ var chartContainsData = false;
215
+
216
+ for(i = 0; i < series.length; i++) {
217
+ if (series[i].data && series[i].data.length > 0) {
218
+ chartContainsData = true;
219
+
220
+ break;
221
+ }
222
+ }
223
+
224
+ if (!chartContainsData) {
225
+ chart.showLoading(scope.config.noData);
226
+ } else {
227
+ chart.hideLoading();
228
+ }
229
+ }
230
+ }
231
+
232
+ //Now remove any missing series
233
+ for(i = chart.series.length - 1; i >= 0; i--) {
234
+ var s = chart.series[i];
235
+ if (s.options.id !== 'highcharts-navigator-series' && highchartsNGUtils.indexOf(ids, s.options.id) < 0) {
236
+ s.remove(false);
237
+ }
238
+ }
239
+
240
+ return true;
241
+ };
242
+
243
+ // chart is maintained by initChart
244
+ var chart = false;
245
+ var initChart = function() {
246
+ if (chart) chart.destroy();
247
+ prevSeriesOptions = {};
248
+ var config = scope.config || {};
249
+ var mergedOptions = getMergedOptions(scope, element, config);
250
+ var func = config.func || undefined;
251
+ chart = config.useHighStocks ?
252
+ new Highcharts.StockChart(mergedOptions, func) :
253
+ new Highcharts.Chart(mergedOptions, func);
254
+ for (var i = 0; i < axisNames.length; i++) {
255
+ if (config[axisNames[i]]) {
256
+ processExtremes(chart, config[axisNames[i]], axisNames[i]);
257
+ }
258
+ }
259
+ if(config.loading) {
260
+ chart.showLoading();
261
+ }
262
+
263
+ };
264
+ initChart();
265
+
266
+
267
+ if(scope.disableDataWatch){
268
+ scope.$watchCollection('config.series', function (newSeries, oldSeries) {
269
+ processSeries(newSeries);
270
+ chart.redraw();
271
+ });
272
+ } else {
273
+ scope.$watch('config.series', function (newSeries, oldSeries) {
274
+ var needsRedraw = processSeries(newSeries);
275
+ if(needsRedraw) {
276
+ chart.redraw();
277
+ }
278
+ }, true);
279
+ }
164
280
 
165
- scope.$watch("config.title", function (newTitle) {
281
+ scope.$watch('config.title', function (newTitle) {
166
282
  chart.setTitle(newTitle, true);
167
283
  }, true);
168
284
 
169
- scope.$watch("config.loading", function (loading) {
285
+ scope.$watch('config.subtitle', function (newSubtitle) {
286
+ chart.setTitle(true, newSubtitle);
287
+ }, true);
288
+
289
+ scope.$watch('config.loading', function (loading) {
170
290
  if(loading) {
171
- chart.showLoading()
291
+ chart.showLoading();
172
292
  } else {
173
- chart.hideLoading()
293
+ chart.hideLoading();
174
294
  }
175
295
  });
176
296
 
177
- scope.$watch("config.useHighStocks", function (useHighStocks) {
178
- chart.destroy();
179
- chart = initialiseChart(scope, element, scope.config);
297
+ scope.$watch('config.credits.enabled', function (enabled) {
298
+ if (enabled) {
299
+ chart.credits.show();
300
+ } else if (chart.credits) {
301
+ chart.credits.hide();
302
+ }
180
303
  });
181
304
 
182
- scope.$watch("config.xAxis", function (newAxes, oldAxes) {
183
- if (newAxes === oldAxes) return;
184
- if(newAxes) {
185
- chart.xAxis[0].update(newAxes);
186
- updateZoom(chart.xAxis[0], angular.copy(newAxes));
187
- chart.redraw();
188
- }
189
- }, true);
190
- scope.$watch("config.options", function (newOptions, oldOptions, scope) {
305
+ scope.$watch('config.useHighStocks', function (useHighStocks, oldUseHighStocks) {
306
+ if(useHighStocks === oldUseHighStocks) return;
307
+ initChart();
308
+ });
309
+
310
+ angular.forEach(axisNames, function(axisName) {
311
+ scope.$watch('config.' + axisName, function (newAxes, oldAxes) {
312
+ if (newAxes === oldAxes) return;
313
+ if(newAxes) {
314
+ chart[axisName][0].update(newAxes, false);
315
+ updateZoom(chart[axisName][0], angular.copy(newAxes));
316
+ chart.redraw();
317
+ }
318
+ }, true);
319
+ });
320
+ scope.$watch('config.options', function (newOptions, oldOptions, scope) {
191
321
  //do nothing when called on registration
192
322
  if (newOptions === oldOptions) return;
193
- chart.destroy();
194
- chart = initialiseChart(scope, element, scope.config);
323
+ initChart();
324
+ processSeries(scope.config.series);
325
+ chart.redraw();
326
+ }, true);
195
327
 
328
+ scope.$watch('config.size', function (newSize, oldSize) {
329
+ if(newSize === oldSize) return;
330
+ if(newSize) {
331
+ chart.setSize(newSize.width || undefined, newSize.height || undefined);
332
+ }
196
333
  }, true);
334
+
335
+ scope.$on('highchartsng.reflow', function () {
336
+ chart.reflow();
337
+ });
338
+
339
+ scope.$on('$destroy', function() {
340
+ if (chart) {
341
+ chart.destroy();
342
+ setTimeout(function(){
343
+ element.remove();
344
+ }, 0);
345
+ }
346
+ });
347
+
197
348
  }
198
- }
199
- });
349
+ };
350
+ }
351
+
352
+ }());
@@ -1,3 +1,3 @@
1
1
  module HighchartsNG
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.7"
3
3
  end
metadata CHANGED
@@ -1,55 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: highcharts-ng-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Iven Hsu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-01 00:00:00.000000000 Z
11
+ date: 2014-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rails
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '3.1'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.1'
55
55
  description: Gem that includes AngularJS directive for Highcharts (Interactive JavaScript
@@ -60,7 +60,7 @@ executables: []
60
60
  extensions: []
61
61
  extra_rdoc_files: []
62
62
  files:
63
- - .gitignore
63
+ - ".gitignore"
64
64
  - Gemfile
65
65
  - LICENSE
66
66
  - README.markdown
@@ -80,17 +80,17 @@ require_paths:
80
80
  - lib
81
81
  required_ruby_version: !ruby/object:Gem::Requirement
82
82
  requirements:
83
- - - '>='
83
+ - - ">="
84
84
  - !ruby/object:Gem::Version
85
85
  version: '0'
86
86
  required_rubygems_version: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - '>='
88
+ - - ">="
89
89
  - !ruby/object:Gem::Version
90
90
  version: '0'
91
91
  requirements: []
92
92
  rubyforge_project:
93
- rubygems_version: 2.0.3
93
+ rubygems_version: 2.2.2
94
94
  signing_key:
95
95
  specification_version: 4
96
96
  summary: AngularJS directive for Highcharts