File "angular-fusioncharts.js"
Full Path: /home/analogde/www/php/integrations/angularjs/js/angular-fusioncharts.js
File size: 27.9 KB
MIME-type: text/plain
Charset: utf-8
// The MIT License (MIT)
//
// Copyright (c) 2014 FusionCharts, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
(function() {
var fc = angular.module('ng-fusioncharts', []),
scope = {
width: '@',
height: '@',
data: '@',
dataset: '@',
categories: '@',
chart: '@',
linkeddata: '@',
trendlines: '@',
vtrendlines: '@',
annotations: '@',
colorrange: '@',
lineset: '@',
axis: '@',
connectors: '@',
pointers: '@',
value: '@',
processes: '@',
tasks: '@',
rows: '@',
columns: '@',
map: '@',
markers: '@',
initialized: '&',
datasourceDt: '=datasourceDt'
},
fcEvents = [
'beforelinkeditemopen',
'linkeditemopened',
'beforelinkeditemclose',
'linkeditemclosed',
'printreadystatechange',
'dataloadrequestcompleted',
'dataloaderror',
'dataloadcancelled',
'dataloadrequestcancelled',
'dataupdated',
'dataupdatecancelled',
'dataloadrequested',
'beforedataupdate',
'realtimeupdatecomplete',
'chartcleared',
'slicingend',
'slicingstart',
'entityrollout',
'entityrollover',
'entityclick',
'connectorrollover',
'connectorrollout',
'connectorclick',
'markerrollover',
'markerrollout',
'markerclick',
'pagenavigated',
'rotationend',
'rotationstart',
'centerlabelrollover',
'centerlabelrollout',
'centerlabelclick',
'centerlabelchanged',
'chartclick',
'chartmousemove',
'chartrollover',
'chartrollout',
'backgroundloaded',
'backgroundloaderror',
'legenditemclicked',
'legenditemrollover',
'legenditemrollout',
'logorollover',
'logorollout',
'logoclick',
'logoloaded',
'logoloaderror',
'beforeexport',
'exported',
'exportcancelled',
'beforeprint',
'printcomplete',
'printcancelled',
'datalabelclick',
'datalabelrollover',
'datalabelrollout',
'scrollstart',
'scrollend',
'onscroll',
'zoomreset',
'zoomedout',
'zoomedin',
'zoomed',
'zoommodechanged',
'pinned',
'datarestored',
'beforedatasubmit',
'datasubmiterror',
'datasubmitted',
'datasubmitcancelled',
'chartupdated',
'nodeadded',
'nodeupdated',
'nodedeleted',
'connectoradded',
'connectorupdated',
'connectordeleted',
'labeladded',
'labeldeleted',
'selectionremoved',
'selectionstart',
'selectionend',
'labelclick',
'labelrollover',
'labelrollout',
'labeldragstart',
'labeldragend',
'dataplotdragstart',
'dataplotdragend',
'processclick',
'processrollover',
'processrollout',
'categoryclick',
'categoryrollover',
'categoryrollout',
'milestoneclick',
'milestonerollover',
'milestonerollout',
'charttypechanged',
'overlaybuttonclick',
'loaded',
'rendered',
'drawcomplete',
'rendercomplete',
'datainvalid',
'dataxmlinvalid',
'dataloaded',
'nodatatodisplay',
'legendpointerdragstart',
'legendpointerdragstop',
'legendrangeupdated',
'alertcomplete',
'realtimeupdateerror',
'dataplotrollover',
'dataplotrollout',
'dataplotclick',
'linkclicked',
'beforerender',
'rendercancelled',
'beforeresize',
'resized',
'resizecancelled',
'beforedispose',
'disposed',
'disposecancelled',
'linkedchartinvoked',
'beforedrilldown',
'drilldown',
'beforedrillup',
'drillup',
'drilldowncancelled',
'drillupcancelled'
],
currIndex,
eventName,
eventsLen = fcEvents.length;
for (currIndex = 0; currIndex < eventsLen; currIndex++) {
eventName =
'fcevent' +
fcEvents[currIndex][0].toUpperCase() +
fcEvents[currIndex].slice(1);
scope[eventName] = '&';
}
fc.directive('fusioncharts', [
'$http',
function($http) {
return {
scope: scope,
link: function(scope, element, attrs) {
function updateData() {
// no need to check for key. datasourceDt is 2 way binded.
// also scope.datasourceDt.key = data; is logically wrong.
chart.setJSONData(scope.datasourceDt);
}
function createWatchersForAttrs(datasource) {
const keys = Object.keys(datasource);
keys.forEach(function(key) {
const isDeep = key !== 'data';
scope.$watch(
'datasourceDt.' + key,
function(newData, oldData) {
if (newData !== oldData && isDeep) updateData();
},
isDeep
);
});
}
var observeConf = {
// non-data componenet observers
NDCObserver: {
width: {
ifExist: false,
observer: function(newVal) {
if (newVal && chartConfigObject.width != newVal) {
chartConfigObject.width = newVal;
chart.resizeTo(scope.width, scope.height);
}
}
},
height: {
ifExist: false,
observer: function(newVal) {
if (newVal && chartConfigObject.height != newVal) {
chartConfigObject.height = newVal;
chart.resizeTo(scope.width, scope.height);
}
}
},
datasource: {
ifExist: true,
observer: function(newVal) {
if (dataStringStore.dataSource != newVal) {
dataStringStore.dataSource = newVal;
if (chartConfigObject.dataFormat === 'json') {
chartConfigObject.dataSource = JSON.parse(newVal);
setChartData();
} else {
chartConfigObject.dataSource = newVal;
if (chartConfigObject.dataFormat === 'xml') {
chart.setXMLData(newVal);
} else if (chartConfigObject.dataFormat === 'jsonurl') {
chart.setJSONUrl(newVal);
} else if (chartConfigObject.dataFormat === 'xmlurl') {
chart.setXMLUrl(newVal);
}
}
}
}
},
type: {
ifExist: false,
observer: function(newVal) {
if (newVal && chartConfigObject.type != newVal) {
chartConfigObject.type = newVal;
// createFCChart();
chart.chartType(newVal);
}
}
},
config: {
ifExist: false,
observer: function(newVal) {
var configObj,
attr,
doReRender = false;
if (newVal) {
configObj = JSON.parse(newVal);
for (attr in configObj) {
// detect the value change
if (chartConfigObject[attr] != configObj[attr]) {
doReRender = true;
chartConfigObject[attr] = configObj[attr];
}
}
if (doReRender) {
createFCChart();
}
}
}
}
},
// data componenet observers
DCObserver: {
chart: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.chart != newVal
) {
dataStringStore.chart = newVal;
chartConfigObject.dataSource.chart = JSON.parse(newVal);
setChartData();
}
}
},
data: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.data != newVal
) {
dataStringStore.data = newVal;
chartConfigObject.dataSource.data = JSON.parse(newVal);
setChartData();
}
}
},
categories: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.categories != newVal
) {
dataStringStore.categories = newVal;
chartConfigObject.dataSource.categories = JSON.parse(
newVal
);
setChartData();
}
}
},
dataset: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.dataset != newVal
) {
dataStringStore.dataset = newVal;
chartConfigObject.dataSource.dataset = JSON.parse(newVal);
setChartData();
}
}
},
linkeddata: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.linkeddata != newVal
) {
dataStringStore.linkeddata = newVal;
chartConfigObject.dataSource.linkeddata = JSON.parse(
newVal
);
setChartData();
}
}
},
trendlines: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.trendlines != newVal
) {
dataStringStore.trendlines = newVal;
chartConfigObject.dataSource.trendlines = JSON.parse(
newVal
);
setChartData();
}
}
},
vtrendlines: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.vtrendlines != newVal
) {
dataStringStore.vtrendlines = newVal;
chartConfigObject.dataSource.vtrendlines = JSON.parse(
newVal
);
setChartData();
}
}
},
annotations: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.annotations != newVal
) {
dataStringStore.annotations = newVal;
chartConfigObject.dataSource.annotations = JSON.parse(
newVal
);
setChartData();
}
}
},
colorrange: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.colorrange != newVal
) {
dataStringStore.colorrange = newVal;
chartConfigObject.dataSource.colorrange = JSON.parse(
newVal
);
setChartData();
}
}
},
lineset: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.lineset != newVal
) {
dataStringStore.lineset = newVal;
chartConfigObject.dataSource.lineset = JSON.parse(newVal);
setChartData();
}
}
},
axis: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.axis != newVal
) {
dataStringStore.axis = newVal;
chartConfigObject.dataSource.axis = JSON.parse(newVal);
setChartData();
}
}
},
connectors: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.connectors != newVal
) {
dataStringStore.connectors = newVal;
chartConfigObject.dataSource.connectors = JSON.parse(
newVal
);
setChartData();
}
}
},
pointers: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.pointers != newVal
) {
dataStringStore.pointers = newVal;
chartConfigObject.dataSource.pointers = JSON.parse(
newVal
);
setChartData();
}
}
},
value: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.value != newVal
) {
dataStringStore.value = newVal;
chartConfigObject.dataSource.value = JSON.parse(newVal);
setChartData();
}
}
},
processes: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.processes != newVal
) {
dataStringStore.processes = newVal;
chartConfigObject.dataSource.processes = JSON.parse(
newVal
);
setChartData();
}
}
},
tasks: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.tasks != newVal
) {
dataStringStore.tasks = newVal;
chartConfigObject.dataSource.tasks = JSON.parse(newVal);
setChartData();
}
}
},
rows: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.rows != newVal
) {
dataStringStore.rows = newVal;
chartConfigObject.dataSource.rows = JSON.parse(newVal);
setChartData();
}
}
},
columns: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.columns != newVal
) {
dataStringStore.columns = newVal;
chartConfigObject.dataSource.columns = JSON.parse(newVal);
setChartData();
}
}
},
map: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.map != newVal
) {
dataStringStore.map = newVal;
chartConfigObject.dataSource.map = JSON.parse(newVal);
setChartData();
}
}
},
markers: {
ifExist: true,
observer: function(newVal) {
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource == 'object' &&
dataStringStore.markers != newVal
) {
dataStringStore.markers = newVal;
chartConfigObject.dataSource.markers = JSON.parse(newVal);
setChartData();
}
}
}
}
},
eventsObj = {},
attribs = Object.keys(attrs),
chart = null,
events = {
'*': function(ev, props) {
if (eventsObj.hasOwnProperty(ev.eventType)) {
eventsObj[ev.eventType](ev, props);
}
}
},
setDataTimer,
setChartData = function() {
// clear previous dataUpdate timer
if (setDataTimer) {
clearTimeout(setDataTimer);
}
// Update the data with setTimeout
// This will solve the issue of consiquitive data update within very small interval
setDataTimer = setTimeout(function() {
if (chart && chart.setJSONData) {
chart.setJSONData(chartConfigObject.dataSource);
}
}, 0);
// chart.setJSONData(chartConfigObject.dataSource);
},
createFCChart = function() {
// dispose if previous chart exists
if (chart && chart.dispose) {
chart.dispose();
}
chart = new FusionCharts(chartConfigObject);
scope.initialized && scope.initialized({ chart: chart });
for (currIndex = 0; currIndex < eventsLen; currIndex++) {
eventName =
'fcevent' +
fcEvents[currIndex][0].toUpperCase() +
fcEvents[currIndex].slice(1);
// assign all events on chart instance
(function(eventName) {
chart.addEventListener(fcEvents[currIndex], function(
event,
args
) {
scope[eventName] &&
scope[eventName]({ event: event, args: args });
});
})(eventName);
}
/* @todo validate the ready function whether it can be replaced in a better way */
angular.element(document).ready(function() {
element.ready(function() {
// Render the chart only when angular is done compiling the element and DOM.
chart = chart.render();
scope[attrs.chartobject] = chart;
});
});
},
dataStringStore = {},
i,
attr,
_eobj,
key,
observableAttr,
chartConfigObject,
configObj,
dataComponent,
eventScopeArr,
l;
if (attrs.events) {
eventScopeArr = attrs.events.split('.');
l = eventScopeArr.length;
_eobj = scope.$parent;
for (i = 0; i < l; i += 1) {
_eobj = _eobj && _eobj[eventScopeArr[i]];
}
if (_eobj) {
for (key in _eobj) {
if (_eobj.hasOwnProperty(key)) {
eventsObj[key.toLowerCase()] = _eobj[key];
}
}
}
}
for (i = 0; i < attribs.length; i++) {
attr = attribs[i];
if (attr.match(/^on/i)) {
key = attr.slice(2).toLowerCase();
eventsObj[key] = scope.$parent[attrs[attr]];
}
}
chartConfigObject = {
type: attrs.type,
width: attrs.width,
height: attrs.height,
renderAt: element[0],
id: attrs.chartid,
dataFormat: attrs.dataformat || 'json',
dataSource: {},
events: events
};
for (observableAttr in observeConf.NDCObserver) {
attrConfig = observeConf.NDCObserver[observableAttr];
if (attrConfig.ifExist === false || attrs[observableAttr]) {
attrs.$observe(observableAttr, attrConfig.observer);
}
}
if (attrs.datasource) {
chartConfigObject.dataSource =
chartConfigObject.dataFormat === 'json'
? JSON.parse(attrs.datasource)
: attrs.datasource;
dataStringStore.dataSource = attrs.datasource;
}
for (observableAttr in observeConf.DCObserver) {
attrConfig = observeConf.DCObserver[observableAttr];
dataComponent = attrs[observableAttr];
if (dataComponent) {
attrs.$observe(observableAttr, attrConfig.observer);
dataStringStore[observableAttr] = dataComponent;
if (
chartConfigObject.dataFormat === 'json' &&
typeof chartConfigObject.dataSource === 'object'
) {
chartConfigObject.dataSource[observableAttr] = JSON.parse(
dataComponent
);
}
} else if (attrConfig.ifExist === false) {
attrs.$observe(observableAttr, attrConfig.observer);
}
}
// add configurations from config
if (attrs.config) {
configObj = JSON.parse(attrs.config);
for (attr in configObj) {
chartConfigObject[attr] = configObj[attr];
}
}
createFCChart();
if (attrs.type.toLowerCase() === 'timeseries' && scope.datasourceDt) {
scope.$watch(
'datasourceDt.data',
function(newData, oldData) {
if (newData !== oldData) updateData();
},
false
);
createWatchersForAttrs(scope.datasourceDt);
// set the data anyway, initially.
chart.setJSONData(scope.datasourceDt);
} else if (scope.datasourceDt) {
attrs.datasourceDt = scope.datasourceDt;
chartConfigObject.dataSource = scope.datasourceDt;
dataStringStore.dataSource = scope.datasourceDt;
setChartData();
scope.$watch(
'datasourceDt',
function(newData, oldData) {
if (newData !== oldData) {
chartConfigObject.dataSource = scope.datasourceDt;
dataStringStore.dataSource = scope.datasourceDt;
setChartData();
if (chartConfigObject.dataFormat === 'json') {
setChartData();
} else {
if (chartConfigObject.dataFormat === 'xml') {
chart.setXMLData(newData);
} else if (chartConfigObject.dataFormat === 'jsonurl') {
chart.setJSONUrl(newData);
} else if (chartConfigObject.dataFormat === 'xmlurl') {
chart.setXMLUrl(newData);
}
}
}
},
true
);
}
scope.$on('$destroy', function() {
// on destroy free used resources to avoid memory leaks
if (chart && chart.dispose) {
chart.dispose();
}
});
}
};
}
]);
})();