highcharts-ng
Advanced tools
Comparing version 0.0.11 to 0.0.12
@@ -0,1 +1,9 @@ | ||
/** | ||
* highcharts-ng | ||
* @version v0.0.12 - 2016-08-07 | ||
* @link https://github.com/pablojim/highcharts-ng | ||
* @author Barry Fitzgerald <> | ||
* @license MIT License, http://www.opensource.org/licenses/MIT | ||
*/ | ||
if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.exports === exports){ | ||
@@ -11,115 +19,62 @@ module.exports = 'highcharts-ng'; | ||
angular.module('highcharts-ng', []) | ||
.provider('highchartsNG', highchartsNGProvider) | ||
.factory('highchartsNG', ['$q', '$window', highchartsNG]) | ||
.directive('highchart', ['highchartsNG', '$timeout', highchart]); | ||
function highchartsNGProvider(){ | ||
var modules = []; | ||
var basePath = false; | ||
var lazyLoad = false; | ||
return { | ||
HIGHCHART: 'highcharts.js', | ||
HIGHSTOCK: 'stock/highstock.js', | ||
basePath: function (p) { | ||
basePath = p; | ||
}, | ||
lazyLoad: function (list) { | ||
if (list === undefined) { | ||
modules = [this.HIGHCHART]; | ||
} else { | ||
modules = list; | ||
} | ||
lazyLoad = true; | ||
}, | ||
$get: ['$window', '$rootScope', function ($window, $rootScope) { | ||
if (!basePath) { | ||
basePath = (window.location.protocol === 'https:' ? 'https' : 'http') + '://code.highcharts.com/'; | ||
} | ||
return highchartsNG($window, $rootScope, lazyLoad, basePath, modules); | ||
}] | ||
//IE8 support | ||
function indexOf(arr, find, i /*opt*/) { | ||
if (i === undefined) i = 0; | ||
if (i < 0) i += arr.length; | ||
if (i < 0) i = 0; | ||
for (var n = arr.length; i < n; i++) | ||
if (i in arr && arr[i] === find) | ||
return i; | ||
return -1; | ||
} | ||
function prependMethod(obj, method, func) { | ||
var original = obj[method]; | ||
obj[method] = function () { | ||
var args = Array.prototype.slice.call(arguments); | ||
func.apply(this, args); | ||
if (original) { | ||
return original.apply(this, args); | ||
} else { | ||
return; | ||
} | ||
}; | ||
} | ||
function highchartsNG($window, $rootScope, lazyload, basePath, modules) { | ||
var readyQueue = []; | ||
var loading = false; | ||
return { | ||
lazyLoad:lazyload, | ||
ready: function (callback, thisArg) { | ||
if (typeof $window.Highcharts !== 'undefined' || !lazyload) { | ||
callback(); | ||
} else { | ||
readyQueue.push([callback, thisArg]); | ||
if (loading) { | ||
return; | ||
} | ||
loading = true; | ||
var self = this; | ||
if (typeof jQuery === 'undefined') { | ||
modules.unshift('adapters/standalone-framework.js'); | ||
} | ||
var doWork = function () { | ||
if (modules.length === 0) { | ||
loading = false; | ||
$rootScope.$apply(function () { | ||
angular.forEach(readyQueue, function (e) { | ||
// invoke callback passing 'thisArg' | ||
e[0].apply(e[1], []); | ||
}); | ||
}); | ||
} else { | ||
var s = modules.shift(); | ||
self.loadScript(s, doWork); | ||
} | ||
}; | ||
doWork(); | ||
} | ||
}, | ||
loadScript: function (path, callback) { | ||
var s = document.createElement('script'); | ||
s.type = 'text/javascript'; | ||
s.src = basePath + path; | ||
s.onload = callback; | ||
document.getElementsByTagName('body')[0].appendChild(s); | ||
}, | ||
//IE8 support | ||
indexOf: function (arr, find, i /*opt*/) { | ||
if (i === undefined) i = 0; | ||
if (i < 0) i += arr.length; | ||
if (i < 0) i = 0; | ||
for (var n = arr.length; i < n; i++) | ||
if (i in arr && arr[i] === find) | ||
return i; | ||
return -1; | ||
}, | ||
prependMethod: function (obj, method, func) { | ||
var original = obj[method]; | ||
obj[method] = function () { | ||
var args = Array.prototype.slice.call(arguments); | ||
func.apply(this, args); | ||
if (original) { | ||
return original.apply(this, args); | ||
} else { | ||
return; | ||
} | ||
function deepExtend(destination, source) { | ||
//Slightly strange behaviour in edge cases (e.g. passing in non objects) | ||
//But does the job for current use cases. | ||
if (angular.isArray(source)) { | ||
destination = angular.isArray(destination) ? destination : []; | ||
for (var i = 0; i < source.length; i++) { | ||
destination[i] = deepExtend(destination[i] || {}, source[i]); | ||
} | ||
} else if (angular.isObject(source)) { | ||
destination = angular.isObject(destination) ? destination : {}; | ||
for (var property in source) { | ||
destination[property] = deepExtend(destination[property] || {}, source[property]); | ||
} | ||
} else { | ||
destination = source; | ||
} | ||
return destination; | ||
} | ||
}; | ||
}, | ||
function highchartsNG($q, $window) { | ||
var highchartsProm = $q.when($window.Highcharts); | ||
deepExtend: function deepExtend(destination, source) { | ||
//Slightly strange behaviour in edge cases (e.g. passing in non objects) | ||
//But does the job for current use cases. | ||
if (angular.isArray(source)) { | ||
destination = angular.isArray(destination) ? destination : []; | ||
for (var i = 0; i < source.length; i++) { | ||
destination[i] = deepExtend(destination[i] || {}, source[i]); | ||
} | ||
} else if (angular.isObject(source)) { | ||
destination = angular.isObject(destination) ? destination : {}; | ||
for (var property in source) { | ||
destination[property] = deepExtend(destination[property] || {}, source[property]); | ||
} | ||
} else { | ||
destination = source; | ||
} | ||
return destination; | ||
function getHighchartsOnce() { | ||
return highchartsProm; | ||
} | ||
return { | ||
getHighcharts: getHighchartsOnce, | ||
ready: function ready(callback, thisArg) { | ||
getHighchartsOnce().then(function() { | ||
callback.call(thisArg); | ||
}); | ||
} | ||
@@ -174,3 +129,3 @@ }; | ||
if (config.options) { | ||
mergedOptions = highchartsNGUtils.deepExtend(defaultOptions, config.options); | ||
mergedOptions = deepExtend(defaultOptions, config.options); | ||
} else { | ||
@@ -183,3 +138,3 @@ mergedOptions = defaultOptions; | ||
if(angular.isDefined(config[axisName])) { | ||
mergedOptions[axisName] = highchartsNGUtils.deepExtend(mergedOptions[axisName] || {}, config[axisName]); | ||
mergedOptions[axisName] = deepExtend(mergedOptions[axisName] || {}, config[axisName]); | ||
@@ -189,3 +144,3 @@ if(angular.isDefined(config[axisName].currentMin) || | ||
highchartsNGUtils.prependMethod(mergedOptions.chart.events, 'selection', function(e){ | ||
prependMethod(mergedOptions.chart.events, 'selection', function(e){ | ||
var thisChart = this; | ||
@@ -206,7 +161,7 @@ if (e[axisName]) { | ||
highchartsNGUtils.prependMethod(mergedOptions.chart.events, 'addSeries', function(e){ | ||
prependMethod(mergedOptions.chart.events, 'addSeries', function(e){ | ||
scope.config[axisName].currentMin = this[axisName][0].min || scope.config[axisName].currentMin; | ||
scope.config[axisName].currentMax = this[axisName][0].max || scope.config[axisName].currentMax; | ||
}); | ||
highchartsNGUtils.prependMethod(mergedOptions[axisName].events, 'setExtremes', function (e) { | ||
prependMethod(mergedOptions[axisName].events, 'setExtremes', function (e) { | ||
if (e.trigger && e.trigger !== 'zoom') { // zoom trigger is handled by selection event | ||
@@ -264,3 +219,3 @@ $timeout(function () { | ||
return angular.extend( | ||
highchartsNGUtils.deepExtend({}, options), | ||
deepExtend({}, options), | ||
{ data: null, visible: null } | ||
@@ -276,230 +231,258 @@ ); | ||
var res = { | ||
restrict: 'EAC', | ||
replace: true, | ||
template: '<div></div>', | ||
scope: { | ||
config: '=', | ||
disableDataWatch: '=' | ||
}, | ||
link: function (scope, element, attrs) { | ||
// We keep some chart-specific variables here as a closure | ||
// instead of storing them on 'scope'. | ||
function linkWithHighcharts(Highcharts, scope, element, attrs) { | ||
// We keep some chart-specific variables here as a closure | ||
// instead of storing them on 'scope'. | ||
// prevSeriesOptions is maintained by processSeries | ||
var prevSeriesOptions = {}; | ||
// prevSeriesOptions is maintained by processSeries | ||
var prevSeriesOptions = {}; | ||
// chart is maintained by initChart | ||
var chart = false; | ||
var processSeries = function(series) { | ||
var i; | ||
var ids = []; | ||
var processSeries = function(series, seriesOld) { | ||
var i; | ||
var ids = []; | ||
if(series) { | ||
var setIds = ensureIds(series); | ||
if(setIds && !scope.disableDataWatch) { | ||
//If we have set some ids this will trigger another digest cycle. | ||
//In this scenario just return early and let the next cycle take care of changes | ||
return false; | ||
} | ||
if(series) { | ||
var setIds = ensureIds(series); | ||
if(setIds && !scope.disableDataWatch) { | ||
//If we have set some ids this will trigger another digest cycle. | ||
//In this scenario just return early and let the next cycle take care of changes | ||
return false; | ||
} | ||
//Find series to add or update | ||
angular.forEach(series, function(s) { | ||
ids.push(s.id); | ||
var chartSeries = chart.get(s.id); | ||
if (chartSeries) { | ||
if (!angular.equals(prevSeriesOptions[s.id], chartOptionsWithoutEasyOptions(s))) { | ||
chartSeries.update(angular.copy(s), false); | ||
} else { | ||
if (s.visible !== undefined && chartSeries.visible !== s.visible) { | ||
chartSeries.setVisible(s.visible, false); | ||
//Find series to add or update | ||
angular.forEach(series, function(s, idx) { | ||
ids.push(s.id); | ||
var chartSeries = chart.get(s.id); | ||
if (chartSeries) { | ||
if (!angular.equals(prevSeriesOptions[s.id], chartOptionsWithoutEasyOptions(s))) { | ||
chartSeries.update(angular.copy(s), false); | ||
} else { | ||
if (s.visible !== undefined && chartSeries.visible !== s.visible) { | ||
chartSeries.setVisible(s.visible, false); | ||
} | ||
// Make sure the current series index can be accessed in seriesOld | ||
if (idx < seriesOld.length) { | ||
var sOld = seriesOld[idx]; | ||
var sCopy = angular.copy(sOld); | ||
// Get the latest data point from the new series | ||
var ptNew = s.data[s.data.length - 1]; | ||
// Check if the new and old series are identical with the latest data point added | ||
// If so, call addPoint without shifting | ||
sCopy.data.push(ptNew); | ||
if (angular.equals(sCopy, s)) { | ||
chartSeries.addPoint(ptNew, false); | ||
} | ||
// Check if the data change was a push and shift operation | ||
// If so, call addPoint WITH shifting | ||
else { | ||
sCopy.data.shift(); | ||
if (angular.equals(sCopy, s)) { | ||
chartSeries.addPoint(ptNew, false, true); | ||
} | ||
else { | ||
chartSeries.setData(angular.copy(s.data), false); | ||
} | ||
} | ||
} | ||
else { | ||
chartSeries.setData(angular.copy(s.data), false); | ||
} | ||
} else { | ||
chart.addSeries(angular.copy(s), false); | ||
} | ||
prevSeriesOptions[s.id] = chartOptionsWithoutEasyOptions(s); | ||
}); | ||
} else { | ||
chart.addSeries(angular.copy(s), false); | ||
} | ||
prevSeriesOptions[s.id] = chartOptionsWithoutEasyOptions(s); | ||
}); | ||
// Shows no data text if all series are empty | ||
if(scope.config.noData) { | ||
var chartContainsData = false; | ||
// Shows no data text if all series are empty | ||
if(scope.config.noData) { | ||
var chartContainsData = false; | ||
for(i = 0; i < series.length; i++) { | ||
if (series[i].data && series[i].data.length > 0) { | ||
chartContainsData = true; | ||
for(i = 0; i < series.length; i++) { | ||
if (series[i].data && series[i].data.length > 0) { | ||
chartContainsData = true; | ||
break; | ||
} | ||
break; | ||
} | ||
} | ||
if (!chartContainsData) { | ||
chart.showLoading(scope.config.noData); | ||
} else { | ||
chart.hideLoading(); | ||
} | ||
if (!chartContainsData) { | ||
chart.showLoading(scope.config.noData); | ||
} else { | ||
chart.hideLoading(); | ||
} | ||
} | ||
} | ||
//Now remove any missing series | ||
for(i = chart.series.length - 1; i >= 0; i--) { | ||
var s = chart.series[i]; | ||
if (s.options.id !== 'highcharts-navigator-series' && highchartsNGUtils.indexOf(ids, s.options.id) < 0) { | ||
s.remove(false); | ||
} | ||
//Now remove any missing series | ||
for(i = chart.series.length - 1; i >= 0; i--) { | ||
var s = chart.series[i]; | ||
if (s.options.id !== 'highcharts-navigator-series' && indexOf(ids, s.options.id) < 0) { | ||
s.remove(false); | ||
} | ||
} | ||
return true; | ||
}; | ||
return true; | ||
}; | ||
// chart is maintained by initChart | ||
var chart = false; | ||
var initChart = function() { | ||
if (chart) chart.destroy(); | ||
prevSeriesOptions = {}; | ||
var config = scope.config || {}; | ||
var mergedOptions = getMergedOptions(scope, element, config); | ||
var func = config.func || undefined; | ||
var chartType = getChartType(scope); | ||
var initChart = function() { | ||
if (chart) chart.destroy(); | ||
prevSeriesOptions = {}; | ||
var config = scope.config || {}; | ||
var mergedOptions = getMergedOptions(scope, element, config); | ||
var func = config.func || undefined; | ||
var chartType = getChartType(scope); | ||
chart = new Highcharts[chartType](mergedOptions, func); | ||
chart = new Highcharts[chartType](mergedOptions, func); | ||
for (var i = 0; i < axisNames.length; i++) { | ||
if (config[axisNames[i]]) { | ||
processExtremes(chart, config[axisNames[i]], axisNames[i]); | ||
} | ||
for (var i = 0; i < axisNames.length; i++) { | ||
if (config[axisNames[i]]) { | ||
processExtremes(chart, config[axisNames[i]], axisNames[i]); | ||
} | ||
if(config.loading) { | ||
chart.showLoading(); | ||
} | ||
config.getHighcharts = function() { | ||
return chart; | ||
}; | ||
} | ||
if(config.loading) { | ||
chart.showLoading(); | ||
} | ||
config.getHighcharts = function() { | ||
return chart; | ||
}; | ||
initChart(); | ||
}; | ||
initChart(); | ||
if(scope.disableDataWatch){ | ||
scope.$watchCollection('config.series', function (newSeries, oldSeries) { | ||
processSeries(newSeries); | ||
chart.redraw(); | ||
}); | ||
} else { | ||
scope.$watch('config.series', function (newSeries, oldSeries) { | ||
var needsRedraw = processSeries(newSeries); | ||
if(needsRedraw) { | ||
chart.redraw(); | ||
} | ||
}, true); | ||
} | ||
scope.$watch('config.title', function (newTitle) { | ||
chart.setTitle(newTitle, true); | ||
}, true); | ||
scope.$watch('config.subtitle', function (newSubtitle) { | ||
chart.setTitle(true, newSubtitle); | ||
}, true); | ||
scope.$watch('config.loading', function (loading) { | ||
if(loading) { | ||
chart.showLoading(loading === true ? null : loading); | ||
} else { | ||
chart.hideLoading(); | ||
} | ||
if(scope.disableDataWatch){ | ||
scope.$watchCollection('config.series', function (newSeries, oldSeries) { | ||
processSeries(newSeries); | ||
chart.redraw(); | ||
}); | ||
scope.$watch('config.noData', function (noData) { | ||
if(scope.config && scope.config.loading) { | ||
chart.showLoading(noData); | ||
} else { | ||
scope.$watch('config.series', function (newSeries, oldSeries) { | ||
var needsRedraw = processSeries(newSeries, oldSeries); | ||
if(needsRedraw) { | ||
chart.redraw(); | ||
} | ||
}, true); | ||
} | ||
scope.$watch('config.credits.enabled', function (enabled) { | ||
if (enabled) { | ||
chart.credits.show(); | ||
} else if (chart.credits) { | ||
chart.credits.hide(); | ||
} | ||
}); | ||
scope.$watch('config.title', function (newTitle) { | ||
chart.setTitle(newTitle, true); | ||
}, true); | ||
scope.$watch(getChartType, function (chartType, oldChartType) { | ||
if (chartType === oldChartType) return; | ||
initChart(); | ||
}); | ||
scope.$watch('config.subtitle', function (newSubtitle) { | ||
chart.setTitle(true, newSubtitle); | ||
}, true); | ||
angular.forEach(axisNames, function(axisName) { | ||
scope.$watch('config.' + axisName, function(newAxes, oldAxes) { | ||
if (newAxes === oldAxes || !newAxes) { | ||
return; | ||
} | ||
scope.$watch('config.loading', function (loading) { | ||
if(loading) { | ||
chart.showLoading(loading === true ? null : loading); | ||
} else { | ||
chart.hideLoading(); | ||
} | ||
}); | ||
scope.$watch('config.noData', function (noData) { | ||
if(scope.config && scope.config.loading) { | ||
chart.showLoading(noData); | ||
} | ||
}, true); | ||
if (angular.isArray(newAxes)) { | ||
scope.$watch('config.credits.enabled', function (enabled) { | ||
if (enabled) { | ||
chart.credits.show(); | ||
} else if (chart.credits) { | ||
chart.credits.hide(); | ||
} | ||
}); | ||
for (var axisIndex = 0; axisIndex < newAxes.length; axisIndex++) { | ||
var axis = newAxes[axisIndex]; | ||
scope.$watch(getChartType, function (chartType, oldChartType) { | ||
if (chartType === oldChartType) return; | ||
initChart(); | ||
}); | ||
if (axisIndex < chart[axisName].length) { | ||
chart[axisName][axisIndex].update(axis, false); | ||
updateZoom(chart[axisName][axisIndex], angular.copy(axis)); | ||
} | ||
angular.forEach(axisNames, function(axisName) { | ||
scope.$watch('config.' + axisName, function(newAxes) { | ||
if (!newAxes) { | ||
return; | ||
} | ||
if (angular.isArray(newAxes)) { | ||
for (var axisIndex = 0; axisIndex < newAxes.length; axisIndex++) { | ||
var axis = newAxes[axisIndex]; | ||
if (axisIndex < chart[axisName].length) { | ||
chart[axisName][axisIndex].update(axis, false); | ||
updateZoom(chart[axisName][axisIndex], angular.copy(axis)); | ||
} | ||
} else { | ||
// update single axis | ||
chart[axisName][0].update(newAxes, false); | ||
updateZoom(chart[axisName][0], angular.copy(newAxes)); | ||
} | ||
chart.redraw(); | ||
}, true); | ||
}); | ||
scope.$watch('config.options', function (newOptions, oldOptions, scope) { | ||
//do nothing when called on registration | ||
if (newOptions === oldOptions) return; | ||
initChart(); | ||
processSeries(scope.config.series); | ||
} else { | ||
// update single axis | ||
chart[axisName][0].update(newAxes, false); | ||
updateZoom(chart[axisName][0], angular.copy(newAxes)); | ||
} | ||
chart.redraw(); | ||
}, true); | ||
}); | ||
scope.$watch('config.options', function (newOptions, oldOptions, scope) { | ||
//do nothing when called on registration | ||
if (newOptions === oldOptions) return; | ||
initChart(); | ||
processSeries(scope.config.series); | ||
chart.redraw(); | ||
}, true); | ||
scope.$watch('config.size', function (newSize, oldSize) { | ||
if(newSize === oldSize) return; | ||
if(newSize) { | ||
chart.setSize(newSize.width || chart.chartWidth, newSize.height || chart.chartHeight); | ||
} | ||
}, true); | ||
scope.$watch('config.size', function (newSize, oldSize) { | ||
if(newSize === oldSize) return; | ||
if(newSize) { | ||
chart.setSize(newSize.width || chart.chartWidth, newSize.height || chart.chartHeight); | ||
} | ||
}, true); | ||
scope.$on('highchartsng.reflow', function () { | ||
chart.reflow(); | ||
}); | ||
scope.$on('highchartsng.reflow', function () { | ||
chart.reflow(); | ||
}); | ||
scope.$on('$destroy', function() { | ||
if (chart) { | ||
try{ | ||
chart.destroy(); | ||
}catch(ex){ | ||
// fail silently as highcharts will throw exception if element doesn't exist | ||
} | ||
$timeout(function(){ | ||
element.remove(); | ||
}, 0); | ||
scope.$on('$destroy', function() { | ||
if (chart) { | ||
try{ | ||
chart.destroy(); | ||
}catch(ex){ | ||
// fail silently as highcharts will throw exception if element doesn't exist | ||
} | ||
}); | ||
$timeout(function(){ | ||
element.remove(); | ||
}, 0); | ||
} | ||
}); | ||
} | ||
function link(scope, element, attrs) { | ||
function highchartsCb(Highcarts) { | ||
linkWithHighcharts(Highcharts, scope, element, attrs); | ||
} | ||
highchartsNGUtils | ||
.getHighcharts() | ||
.then(highchartsCb); | ||
} | ||
return { | ||
restrict: 'EAC', | ||
replace: true, | ||
template: '<div></div>', | ||
scope: { | ||
config: '=', | ||
disableDataWatch: '=' | ||
}, | ||
link: link | ||
}; | ||
// override link fn if lazy loading is enabled | ||
if(highchartsNGUtils.lazyLoad){ | ||
var oldLink = res.link; | ||
res.link = function(){ | ||
var args = arguments; | ||
highchartsNGUtils.ready(function(){ | ||
oldLink.apply(this, args); | ||
}, this); | ||
}; | ||
} | ||
return res; | ||
} | ||
}()); |
/** | ||
* highcharts-ng | ||
* @version v0.0.11 - 2015-09-12 | ||
* @version v0.0.12 - 2016-08-07 | ||
* @link https://github.com/pablojim/highcharts-ng | ||
@@ -8,2 +8,2 @@ * @author Barry Fitzgerald <> | ||
*/ | ||
"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="highcharts-ng"),function(){"use strict";function a(){var a=[],c=!1,d=!1;return{HIGHCHART:"highcharts.js",HIGHSTOCK:"stock/highstock.js",basePath:function(a){c=a},lazyLoad:function(b){a=void 0===b?[this.HIGHCHART]:b,d=!0},$get:["$window","$rootScope",function(e,f){return c||(c=("https:"===window.location.protocol?"https":"http")+"://code.highcharts.com/"),b(e,f,d,c,a)}]}}function b(a,b,c,d,e){var f=[],g=!1;return{lazyLoad:c,ready:function(d,h){if("undefined"==typeof a.Highcharts&&c){if(f.push([d,h]),g)return;g=!0;var i=this;"undefined"==typeof jQuery&&e.unshift("adapters/standalone-framework.js");var j=function(){if(0===e.length)g=!1,b.$apply(function(){angular.forEach(f,function(a){a[0].apply(a[1],[])})});else{var a=e.shift();i.loadScript(a,j)}};j()}else d()},loadScript:function(a,b){var c=document.createElement("script");c.type="text/javascript",c.src=d+a,c.onload=b,document.getElementsByTagName("body")[0].appendChild(c)},indexOf:function(a,b,c){void 0===c&&(c=0),0>c&&(c+=a.length),0>c&&(c=0);for(var d=a.length;d>c;c++)if(c in a&&a[c]===b)return c;return-1},prependMethod:function(a,b,c){var d=a[b];a[b]=function(){var a=Array.prototype.slice.call(arguments);return c.apply(this,a),d?d.apply(this,a):void 0}},deepExtend:function h(a,b){if(angular.isArray(b)){a=angular.isArray(a)?a:[];for(var c=0;c<b.length;c++)a[c]=h(a[c]||{},b[c])}else if(angular.isObject(b)){a=angular.isObject(a)?a:{};for(var d in b)a[d]=h(a[d]||{},b[d])}else a=b;return a}}}function c(a,b){var c=0,d=function(a){var b=!1;return angular.forEach(a,function(a){angular.isDefined(a.id)||(a.id="series-"+c++,b=!0)}),b},e=["xAxis","yAxis"],f={stock:"StockChart",map:"Map",chart:"Chart"},g=function(c,d,f){var g={},h={chart:{events:{}},title:{},subtitle:{},series:[],credits:{},plotOptions:{},navigator:{enabled:!1},xAxis:{events:{}},yAxis:{events:{}}};return g=f.options?a.deepExtend(h,f.options):h,g.chart.renderTo=d[0],angular.forEach(e,function(d){angular.isDefined(f[d])&&(g[d]=a.deepExtend(g[d]||{},f[d]),(angular.isDefined(f[d].currentMin)||angular.isDefined(f[d].currentMax))&&(a.prependMethod(g.chart.events,"selection",function(a){var b=this;a[d]?c.$apply(function(){c.config[d].currentMin=a[d][0].min,c.config[d].currentMax=a[d][0].max}):c.$apply(function(){c.config[d].currentMin=b[d][0].dataMin,c.config[d].currentMax=b[d][0].dataMax})}),a.prependMethod(g.chart.events,"addSeries",function(a){c.config[d].currentMin=this[d][0].min||c.config[d].currentMin,c.config[d].currentMax=this[d][0].max||c.config[d].currentMax}),a.prependMethod(g[d].events,"setExtremes",function(a){a.trigger&&"zoom"!==a.trigger&&b(function(){c.config[d].currentMin=a.min,c.config[d].currentMax=a.max,c.config[d].min=a.min,c.config[d].max=a.max},0)})))}),f.title&&(g.title=f.title),f.subtitle&&(g.subtitle=f.subtitle),f.credits&&(g.credits=f.credits),f.size&&(f.size.width&&(g.chart.width=f.size.width),f.size.height&&(g.chart.height=f.size.height)),g},h=function(a,b){var c=a.getExtremes();(b.currentMin!==c.dataMin||b.currentMax!==c.dataMax)&&(a.setExtremes?a.setExtremes(b.currentMin,b.currentMax,!1):a.detachedsetExtremes(b.currentMin,b.currentMax,!1))},i=function(a,b,c){(b.currentMin||b.currentMax)&&a[c][0].setExtremes(b.currentMin,b.currentMax,!0)},j=function(b){return angular.extend(a.deepExtend({},b),{data:null,visible:null})},k=function(a){return void 0===a.config?"Chart":f[(""+a.config.chartType).toLowerCase()]||(a.config.useHighStocks?"StockChart":"Chart")},l={restrict:"EAC",replace:!0,template:"<div></div>",scope:{config:"=",disableDataWatch:"="},link:function(c,f,l){var m={},n=function(b){var e,f=[];if(b){var g=d(b);if(g&&!c.disableDataWatch)return!1;if(angular.forEach(b,function(a){f.push(a.id);var b=o.get(a.id);b?angular.equals(m[a.id],j(a))?(void 0!==a.visible&&b.visible!==a.visible&&b.setVisible(a.visible,!1),b.setData(angular.copy(a.data),!1)):b.update(angular.copy(a),!1):o.addSeries(angular.copy(a),!1),m[a.id]=j(a)}),c.config.noData){var h=!1;for(e=0;e<b.length;e++)if(b[e].data&&b[e].data.length>0){h=!0;break}h?o.hideLoading():o.showLoading(c.config.noData)}}for(e=o.series.length-1;e>=0;e--){var i=o.series[e];"highcharts-navigator-series"!==i.options.id&&a.indexOf(f,i.options.id)<0&&i.remove(!1)}return!0},o=!1,p=function(){o&&o.destroy(),m={};var a=c.config||{},b=g(c,f,a),d=a.func||void 0,h=k(c);o=new Highcharts[h](b,d);for(var j=0;j<e.length;j++)a[e[j]]&&i(o,a[e[j]],e[j]);a.loading&&o.showLoading(),a.getHighcharts=function(){return o}};p(),c.disableDataWatch?c.$watchCollection("config.series",function(a,b){n(a),o.redraw()}):c.$watch("config.series",function(a,b){var c=n(a);c&&o.redraw()},!0),c.$watch("config.title",function(a){o.setTitle(a,!0)},!0),c.$watch("config.subtitle",function(a){o.setTitle(!0,a)},!0),c.$watch("config.loading",function(a){a?o.showLoading(a===!0?null:a):o.hideLoading()}),c.$watch("config.noData",function(a){c.config&&c.config.loading&&o.showLoading(a)},!0),c.$watch("config.credits.enabled",function(a){a?o.credits.show():o.credits&&o.credits.hide()}),c.$watch(k,function(a,b){a!==b&&p()}),angular.forEach(e,function(a){c.$watch("config."+a,function(b,c){if(b!==c&&b){if(angular.isArray(b))for(var d=0;d<b.length;d++){var e=b[d];d<o[a].length&&(o[a][d].update(e,!1),h(o[a][d],angular.copy(e)))}else o[a][0].update(b,!1),h(o[a][0],angular.copy(b));o.redraw()}},!0)}),c.$watch("config.options",function(a,b,c){a!==b&&(p(),n(c.config.series),o.redraw())},!0),c.$watch("config.size",function(a,b){a!==b&&a&&o.setSize(a.width||o.chartWidth,a.height||o.chartHeight)},!0),c.$on("highchartsng.reflow",function(){o.reflow()}),c.$on("$destroy",function(){if(o){try{o.destroy()}catch(a){}b(function(){f.remove()},0)}})}};if(a.lazyLoad){var m=l.link;l.link=function(){var b=arguments;a.ready(function(){m.apply(this,b)},this)}}return l}angular.module("highcharts-ng",[]).provider("highchartsNG",a).directive("highchart",["highchartsNG","$timeout",c])}(); | ||
"undefined"!=typeof module&&"undefined"!=typeof exports&&module.exports===exports&&(module.exports="highcharts-ng"),function(){"use strict";function a(a,b,c){void 0===c&&(c=0),c<0&&(c+=a.length),c<0&&(c=0);for(var d=a.length;c<d;c++)if(c in a&&a[c]===b)return c;return-1}function b(a,b,c){var d=a[b];a[b]=function(){var a=Array.prototype.slice.call(arguments);return c.apply(this,a),d?d.apply(this,a):void 0}}function c(a,b){if(angular.isArray(b)){a=angular.isArray(a)?a:[];for(var d=0;d<b.length;d++)a[d]=c(a[d]||{},b[d])}else if(angular.isObject(b)){a=angular.isObject(a)?a:{};for(var e in b)a[e]=c(a[e]||{},b[e])}else a=b;return a}function d(a,b){function c(){return d}var d=a.when(b.Highcharts);return{getHighcharts:c,ready:function(a,b){c().then(function(){a.call(b)})}}}function e(d,e){function f(b,c,d,f){var g={},h=!1,k=function(b,d){var e,f=[];if(b){var j=i(b);if(j&&!c.disableDataWatch)return!1;if(angular.forEach(b,function(a,b){f.push(a.id);var c=h.get(a.id);if(c)if(angular.equals(g[a.id],o(a)))if(void 0!==a.visible&&c.visible!==a.visible&&c.setVisible(a.visible,!1),b<d.length){var e=d[b],i=angular.copy(e),j=a.data[a.data.length-1];i.data.push(j),angular.equals(i,a)?c.addPoint(j,!1):(i.data.shift(),angular.equals(i,a)?c.addPoint(j,!1,!0):c.setData(angular.copy(a.data),!1))}else c.setData(angular.copy(a.data),!1);else c.update(angular.copy(a),!1);else h.addSeries(angular.copy(a),!1);g[a.id]=o(a)}),c.config.noData){var k=!1;for(e=0;e<b.length;e++)if(b[e].data&&b[e].data.length>0){k=!0;break}k?h.hideLoading():h.showLoading(c.config.noData)}}for(e=h.series.length-1;e>=0;e--){var l=h.series[e];"highcharts-navigator-series"!==l.options.id&&a(f,l.options.id)<0&&l.remove(!1)}return!0},q=function(){h&&h.destroy(),g={};var a=c.config||{},e=l(c,d,a),f=a.func||void 0,i=p(c);h=new b[i](e,f);for(var k=0;k<j.length;k++)a[j[k]]&&n(h,a[j[k]],j[k]);a.loading&&h.showLoading(),a.getHighcharts=function(){return h}};q(),c.disableDataWatch?c.$watchCollection("config.series",function(a,b){k(a),h.redraw()}):c.$watch("config.series",function(a,b){var c=k(a,b);c&&h.redraw()},!0),c.$watch("config.title",function(a){h.setTitle(a,!0)},!0),c.$watch("config.subtitle",function(a){h.setTitle(!0,a)},!0),c.$watch("config.loading",function(a){a?h.showLoading(a===!0?null:a):h.hideLoading()}),c.$watch("config.noData",function(a){c.config&&c.config.loading&&h.showLoading(a)},!0),c.$watch("config.credits.enabled",function(a){a?h.credits.show():h.credits&&h.credits.hide()}),c.$watch(p,function(a,b){a!==b&&q()}),angular.forEach(j,function(a){c.$watch("config."+a,function(b){if(b){if(angular.isArray(b))for(var c=0;c<b.length;c++){var d=b[c];c<h[a].length&&(h[a][c].update(d,!1),m(h[a][c],angular.copy(d)))}else h[a][0].update(b,!1),m(h[a][0],angular.copy(b));h.redraw()}},!0)}),c.$watch("config.options",function(a,b,c){a!==b&&(q(),k(c.config.series),h.redraw())},!0),c.$watch("config.size",function(a,b){a!==b&&a&&h.setSize(a.width||h.chartWidth,a.height||h.chartHeight)},!0),c.$on("highchartsng.reflow",function(){h.reflow()}),c.$on("$destroy",function(){if(h){try{h.destroy()}catch(a){}e(function(){d.remove()},0)}})}function g(a,b,c){function e(d){f(Highcharts,a,b,c)}d.getHighcharts().then(e)}var h=0,i=function(a){var b=!1;return angular.forEach(a,function(a){angular.isDefined(a.id)||(a.id="series-"+h++,b=!0)}),b},j=["xAxis","yAxis"],k={stock:"StockChart",map:"Map",chart:"Chart"},l=function(a,d,f){var g={},h={chart:{events:{}},title:{},subtitle:{},series:[],credits:{},plotOptions:{},navigator:{enabled:!1},xAxis:{events:{}},yAxis:{events:{}}};return g=f.options?c(h,f.options):h,g.chart.renderTo=d[0],angular.forEach(j,function(d){angular.isDefined(f[d])&&(g[d]=c(g[d]||{},f[d]),(angular.isDefined(f[d].currentMin)||angular.isDefined(f[d].currentMax))&&(b(g.chart.events,"selection",function(b){var c=this;b[d]?a.$apply(function(){a.config[d].currentMin=b[d][0].min,a.config[d].currentMax=b[d][0].max}):a.$apply(function(){a.config[d].currentMin=c[d][0].dataMin,a.config[d].currentMax=c[d][0].dataMax})}),b(g.chart.events,"addSeries",function(b){a.config[d].currentMin=this[d][0].min||a.config[d].currentMin,a.config[d].currentMax=this[d][0].max||a.config[d].currentMax}),b(g[d].events,"setExtremes",function(b){b.trigger&&"zoom"!==b.trigger&&e(function(){a.config[d].currentMin=b.min,a.config[d].currentMax=b.max,a.config[d].min=b.min,a.config[d].max=b.max},0)})))}),f.title&&(g.title=f.title),f.subtitle&&(g.subtitle=f.subtitle),f.credits&&(g.credits=f.credits),f.size&&(f.size.width&&(g.chart.width=f.size.width),f.size.height&&(g.chart.height=f.size.height)),g},m=function(a,b){var c=a.getExtremes();b.currentMin===c.dataMin&&b.currentMax===c.dataMax||(a.setExtremes?a.setExtremes(b.currentMin,b.currentMax,!1):a.detachedsetExtremes(b.currentMin,b.currentMax,!1))},n=function(a,b,c){(b.currentMin||b.currentMax)&&a[c][0].setExtremes(b.currentMin,b.currentMax,!0)},o=function(a){return angular.extend(c({},a),{data:null,visible:null})},p=function(a){return void 0===a.config?"Chart":k[(""+a.config.chartType).toLowerCase()]||(a.config.useHighStocks?"StockChart":"Chart")};return{restrict:"EAC",replace:!0,template:"<div></div>",scope:{config:"=",disableDataWatch:"="},link:g}}angular.module("highcharts-ng",[]).factory("highchartsNG",["$q","$window",d]).directive("highchart",["highchartsNG","$timeout",e])}(); |
{ | ||
"name": "highcharts-ng", | ||
"version": "0.0.11", | ||
"version": "0.0.12", | ||
"description": "highcharts-ng", | ||
@@ -18,31 +18,29 @@ "keywords": [ | ||
}, | ||
"licenses": [ | ||
{ | ||
"type": "MIT" | ||
} | ||
], | ||
"license": "MIT", | ||
"devDependencies": { | ||
"grunt": "~0.4.1", | ||
"grunt-contrib-jshint": "~0.11.3", | ||
"grunt-contrib-concat": "~0.5.1", | ||
"grunt-contrib-uglify": "~0.9.2", | ||
"grunt-contrib-watch": "~0.6.1", | ||
"grunt-contrib-clean": "~0.6.0", | ||
"grunt-contrib-connect": "~0.11.2", | ||
"grunt-contrib-less": "~1.0.1", | ||
"angular": "^1.5.7", | ||
"angular-mocks": "^1.5.7", | ||
"connect-livereload": "~0.5.3", | ||
"grunt": "^1.0.1", | ||
"grunt-banner": "^0.6.0", | ||
"grunt-bump": "^0.8.0", | ||
"grunt-cli": "^1.2.0", | ||
"grunt-contrib-clean": "^1.0.0", | ||
"grunt-contrib-concat": "^1.0.1", | ||
"grunt-contrib-connect": "^1.0.2", | ||
"grunt-contrib-copy": "^1.0.0", | ||
"grunt-contrib-jshint": "^1.0.0", | ||
"grunt-contrib-uglify": "^1.0.1", | ||
"grunt-contrib-watch": "^1.0.0", | ||
"grunt-karma": "^2.0.0", | ||
"grunt-open": "~0.2.2", | ||
"grunt-karma": "~0.12.0", | ||
"grunt-ng-annotate": "1.0.1", | ||
"grunt-bump": "0.5.0", | ||
"matchdep": "~0.3.0", | ||
"karma-script-launcher": "~0.1.0", | ||
"karma-chrome-launcher": "~0.2.0", | ||
"karma-firefox-launcher": "~0.1.0", | ||
"karma-html2js-preprocessor": "~0.1.0", | ||
"karma-jasmine": "~0.3.6", | ||
"karma-requirejs": "~0.2.0", | ||
"karma-coffee-preprocessor": "~0.3.0", | ||
"karma-phantomjs-launcher": "~0.2.1", | ||
"karma": "~0.13.9" | ||
"jasmine-core": "^2.4.1", | ||
"jquery": "^3.1.0", | ||
"karma": "^1.1.1", | ||
"karma-chrome-launcher": "^1.0.1", | ||
"karma-coverage": "^1.1.0", | ||
"karma-jasmine": "^1.0.2", | ||
"karma-phantomjs-launcher": "^1.0.1", | ||
"load-grunt-tasks": "^3.5.0", | ||
"phantomjs-prebuilt": "^2.1.7" | ||
}, | ||
@@ -52,3 +50,4 @@ "scripts": { | ||
}, | ||
"browser": "./dist/highcharts-ng.js" | ||
"main": "./dist/highcharts-ng", | ||
"dependencies": {} | ||
} |
@@ -10,3 +10,3 @@ highcharts-ng | ||
Current Version (0.0.10) | ||
Current Version (0.0.11) | ||
--------------- | ||
@@ -28,6 +28,2 @@ | ||
*(optional)* If you don't include jQuery in your page, you have to use Highcharts' *Standalone Adapter* (else, it will not work): | ||
```<script src="http://code.highcharts.com/adapters/standalone-framework.js"></script>``` | ||
Add Highcharts to your Angular app config: | ||
@@ -37,23 +33,2 @@ | ||
If you don't want to add additional scripts, you may use lazyload: | ||
``` | ||
app.config(['highchartsNGProvider', function (highchartsNGProvider) { | ||
highchartsNGProvider.lazyLoad();// will load hightcharts (and standalone framework if jquery is not present) from code.hightcharts.com | ||
highchartsNGProvider.lazyLoad([highchartsNGProvider.HIGHCHART/HIGHSTOCK, "maps/modules/map.js", "mapdata/custom/world.js"]);// you may add any additional modules and they will be loaded in the same sequence | ||
highchartsNGProvider.basePath("/js/"); // change base path for scripts, default is http(s)://code.highcharts.com/ | ||
}]); | ||
app.controller(["highchartsNG", function(highchartsNG){ | ||
// do anything you like | ||
// ... | ||
highchartsNG.ready(function(){ | ||
// init chart config, see lazyload example | ||
},this); | ||
}); | ||
``` | ||
Make a chart! | ||
@@ -63,3 +38,3 @@ | ||
__Warning__: The `chartConfig` object is _slightly different_ than the default highcharts config object. ( _Please see the FAQ below for details_ ) | ||
__Warning__: The `chartConfig` object is _slightly different_ than the default Highcharts config object. ( _Please see the FAQ below for details_ ) | ||
@@ -69,7 +44,7 @@ - See http://pablojim.github.io/highcharts-ng/examples/example.html for an extended example. Also Available in the example directory - thanks @crusat | ||
- Example with dynamic x-axis: http://jsfiddle.net/pablojim/7cAq3/ | ||
- Basic highstocks example http://jsfiddle.net/pablojim/r88yszk0/ | ||
- Basic Highstocks example http://jsfiddle.net/pablojim/r88yszk0/ | ||
- Support for Highmaps - see: http://rawgit.com/pablojim/highcharts-ng/master/example/maps/example.html | ||
- Getting access to the Chart object/Add a print button - http://jsfiddle.net/pablojim/m4pcpv5g/ | ||
The `chartConfig` attribute mentioned above resembles an exploded highcharts options object: | ||
The `chartConfig` attribute mentioned above resembles an exploded Highcharts options object: | ||
@@ -95,3 +70,3 @@ ```javascript | ||
//Series object (optional) - a list of series using normal highcharts series options. | ||
//Series object (optional) - a list of series using normal Highcharts series options. | ||
series: [{ | ||
@@ -104,7 +79,7 @@ data: [10, 15, 12, 8, 7] | ||
}, | ||
//Boolean to control showng loading status on chart (optional) | ||
//Boolean to control showing loading status on chart (optional) | ||
//Could be a string if you want to show specific loading text. | ||
loading: false, | ||
//Configuration for the xAxis (optional). Currently only one x axis can be dynamically controlled. | ||
//properties currentMin and currentMax provied 2-way binding to the chart's maximimum and minimum | ||
//properties currentMin and currentMax provided 2-way binding to the chart's maximum and minimum | ||
xAxis: { | ||
@@ -115,3 +90,3 @@ currentMin: 0, | ||
}, | ||
//Whether to use HighStocks instead of HighCharts (optional). Defaults to false. | ||
//Whether to use Highstocks instead of Highcharts (optional). Defaults to false. | ||
useHighStocks: false, | ||
@@ -132,4 +107,4 @@ //size (optional) if left out the chart will default to size of the div or something sensible. | ||
NOTE: | ||
A common error is to put other highcharts options directly into the chartConfig. | ||
In general if the highcharts option you want isn't listed above you probably want to put it in chartConfig.options | ||
A common error is to put other Highcharts options directly into the chartConfig. | ||
In general if the Highcharts option you want isn't listed above you probably want to put it in chartConfig.options | ||
@@ -157,2 +132,3 @@ The Highcharts object can be accessed with ```chartConfig.getHighcharts()```. 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. | ||
- Navigator/scrollbar cannot run with liveRedraw enabled at this time | ||
- Highcharts <=3 requires jQuery or ```<script src="http://code.highcharts.com/3/adapters/standalone-framework.js"></script>``` | ||
- Needs tests! | ||
@@ -167,4 +143,4 @@ | ||
*At least half of all issues filed are due to this. Before you file an issue read this!* | ||
A common error is to put other highcharts options directly into the chartConfig. | ||
In general if the highcharts option you want isn't listed above you probably want to put it in chartConfig.options. | ||
A common error is to put other Highcharts options directly into the chartConfig. | ||
In general if the Highcharts option you want isn't listed above you probably want to put it in chartConfig.options. | ||
@@ -177,9 +153,9 @@ - How do I get access to the chart object? | ||
- Why don't you just use the standard highcharts format? | ||
- Why don't you just use the standard Highcharts format? | ||
Lets consider the below snippet. | ||
Let's consider the below snippet. | ||
``` | ||
$scope.chartConfig = { | ||
options: {...}, //highcharts options - using standard highcharts config | ||
options: {...}, //Highcharts options - using standard Highcharts config | ||
//other "dynamic" options | ||
@@ -190,9 +166,9 @@ title: {...} | ||
``` | ||
In the ```chartConfig``` object above the ```options``` property is a standard highcharts options object. e.g. anything you can pass into ````new Highcharts.Chart(options);``` works here. | ||
In the ```chartConfig``` object above the ```options``` property is a standard Highcharts options object. e.g. anything you can pass into ````new Highcharts.Chart(options);``` works here. | ||
This options object is watched for changes. When something changes here the whole chart is recreated. | ||
The other dynamic properties are ones that we can change without affecting the whole chart - using the api at http://api.highcharts.com/highcharts#Chart e.g. if you change the title we can call chart.setTitle and not have to recreate the whole chart. Splitting them out from the main options object means we can watch them separately. | ||
The other dynamic properties are ones that we can change without affecting the whole chart - using the API at http://api.highcharts.com/highcharts#Chart e.g. if you change the title we can call chart.setTitle and not have to recreate the whole chart. Splitting them out from the main options object means we can watch them separately. | ||
So anything that has an api to change is declared outside the main options object. | ||
So anything that has an API to change is declared outside the main options object. | ||
@@ -224,8 +200,42 @@ Hope this makes sense! | ||
Lazy loading | ||
------------ | ||
If you used to use the lazyload feature, this has been moved to a separate | ||
module. It is recommended to use a module loader such as Webpack or browserify | ||
instead. | ||
```html | ||
<script src="path/to/highcharts-ng/dist/lazyload.js"></script> | ||
``` | ||
``` | ||
var myapp = angular.module('myapp', ["highcharts-ng-lazyload"]);``` | ||
app.config(['highchartsNGProvider', function (highchartsNGProvider) { | ||
highchartsNGProvider.lazyLoad();// will load hightcharts (and standalone framework if jquery is not present) from code.hightcharts.com | ||
highchartsNGProvider.lazyLoad([highchartsNGProvider.HIGHCHART/HIGHSTOCK, "maps/modules/map.js", "mapdata/custom/world.js"]);// you may add any additional modules and they will be loaded in the same sequence | ||
highchartsNGProvider.basePath("/js/"); // change base path for scripts, default is http(s)://code.highcharts.com/ | ||
}]); | ||
app.controller(["highchartsNG", function(highchartsNG){ | ||
// do anything you like | ||
// ... | ||
highchartsNG.getHighcharts().then(function(Highcharts){ | ||
// init chart config, see lazyload example | ||
}); | ||
}); | ||
``` | ||
Versions | ||
-------------- | ||
Version 0.0.11 | ||
---------------- | ||
- Bug fix for console error with missing yAxis | ||
Version 0.0.10 | ||
@@ -232,0 +242,0 @@ ---------------- |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
68594
16
931
288
25
1