mirror of
https://github.com/bendtherules/line_chart_demo.git
synced 2026-08-18 22:03:16 +00:00
31292 lines
1.3 MiB
Plaintext
31292 lines
1.3 MiB
Plaintext
|
|
(function (factory) {
|
|
if (typeof module === 'object' && typeof module.exports !== "undefined") {
|
|
module.exports = factory;
|
|
} else {
|
|
factory(FusionCharts);
|
|
}
|
|
}(function (FusionCharts) {
|
|
|
|
/**
|
|
* @private
|
|
* @module fusioncharts.renderer.javascript.legend-gradient
|
|
*/
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-gradientlegend', function() {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
pluckNumber = lib.pluckNumber,
|
|
pluck = lib.pluck,
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
graphics = lib.graphics,
|
|
dehashify = lib.dehashify,
|
|
hashify = lib.hashify,
|
|
convertColor = graphics.convertColor,
|
|
RGBtoHex = graphics.RGBtoHex,
|
|
HEXtoRGB = graphics.HEXtoRGB,
|
|
getLightColor = graphics.getLightColor,
|
|
getValidColor = graphics.getValidColor,
|
|
compositionKeys = {},
|
|
isIE = lib.isIE,
|
|
TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')',
|
|
legendManager,
|
|
DEF_COLOR = lib.COLOR_BLACK,
|
|
FORMER_SLIDER_INDEX = false,
|
|
LATER_SLIDER_INDEX = true,
|
|
PERCENT_STR = '%',
|
|
COMMA_STR = ',',
|
|
hasOwnProp = ({}).hasOwnProperty,
|
|
M = 'M',
|
|
L = 'L',
|
|
animType = 'easeIn',
|
|
componentPoolFactory,
|
|
universalPool = {};
|
|
|
|
// Utility functions
|
|
|
|
/*
|
|
* Recursively merges two objects.
|
|
* Source is object from where the properties will be copied and sink is destination object where the props are to
|
|
* be copied. If the property is already present in sink, it wont copy the property.
|
|
*
|
|
* Example: After merging the sink will be changed and returned
|
|
* src = { | sink = { | sink = {
|
|
* a: 1, | b: 33, | a: 1,
|
|
* b: 2, | c: 44, | b: 33,
|
|
* obj1: { | obj2: { | c: 44,
|
|
* m: 1, | w: 11, | obj1: {
|
|
* n: 2 | x: 22 | m: 1,
|
|
* }, | } | n: 2
|
|
* obj2: { | | },
|
|
* x: 1, | | obj2: {
|
|
* y: 2, | | w: 11,
|
|
* z: 3 | | x: 22,
|
|
* } | | y: 2,
|
|
* } | | z: 3
|
|
* | | }
|
|
* | | }
|
|
*
|
|
* @param: source {Object} - The object from where the props are to be copied
|
|
* @param: sink {Object} - The object where the props are to be merged
|
|
* @return {Object} - The reference to the sink object which was passed
|
|
*/
|
|
function merge (source, sink) {
|
|
(function rec (source, sink) {
|
|
var sourceVal,
|
|
prop;
|
|
|
|
for (prop in source) {
|
|
// Iterates for every property in souce
|
|
if (!hasOwnProp.call(source, prop)) {
|
|
// Igoners if the property does not belong to the object directly, it might resides on the prototype
|
|
// chain
|
|
continue;
|
|
}
|
|
|
|
sourceVal = source[prop];
|
|
if (sink[prop] === undefined) {
|
|
// Assigns the value / ref if the value of the same property is undefined (it's not checked whether
|
|
// the key is directly or indirectly present on the object) in the sink.
|
|
sink[prop] = sourceVal;
|
|
} else if (typeof sourceVal === 'object' && typeof sourceVal !== null) {
|
|
// If the value is another object recursively perform the merging.
|
|
|
|
// @todo check if the value is function, array etc. If it happens this will execute unpredictively,
|
|
// Its not implmented because it would more condition.
|
|
rec(sourceVal, sink[prop]);
|
|
}
|
|
}
|
|
})(source, sink);
|
|
|
|
return sink;
|
|
}
|
|
|
|
/*
|
|
* Takes care of sanity checking of the color to some extent.
|
|
* If no color is passed, ie called as getValidHexColor() it returns the default color. If incorrect color is passed
|
|
* it returns false.
|
|
*
|
|
* @param code {String} - color code in string
|
|
* @return {String | Boolean} - false if invalid color is passed, otherwise the same color or default color if no
|
|
* no color is passed
|
|
*/
|
|
function getValidHexColor (code) {
|
|
var color = code ? code : DEF_COLOR;
|
|
|
|
return getValidColor(color) || DEF_COLOR;
|
|
}
|
|
|
|
/*
|
|
* Returns the opposite LIGHT color of a color. If the color is alraedy light, wont get much difference.
|
|
*
|
|
* @param code {String} - color code in string
|
|
* @return {String} - Lightest (approx) color code of the color sent
|
|
*/
|
|
function getOppositeColor (code) {
|
|
return getLightColor(code, 1);
|
|
}
|
|
|
|
function getColorBetween(range1, range2, value) {
|
|
/*jshint newcap: false */
|
|
var value1 = range1.value,
|
|
code1 = range1.code,
|
|
rgb1 = HEXtoRGB(code1),
|
|
value2 = range2.value,
|
|
code2 = range2.code,
|
|
rgb2 = HEXtoRGB(code2),
|
|
diff,
|
|
rgb;
|
|
|
|
diff = value2 - value1;
|
|
|
|
rgb = [
|
|
Math.round(rgb1[0] + (((rgb2[0] - rgb1[0]) / diff) * (value - value1))),
|
|
Math.round(rgb1[1] + (((rgb2[1] - rgb1[1]) / diff) * (value - value1))),
|
|
Math.round(rgb1[2] + (((rgb2[2] - rgb1[2]) / diff) * (value - value1)))
|
|
];
|
|
|
|
return RGBtoHex(rgb);
|
|
/*jshint newcap: true */
|
|
}
|
|
|
|
function normalizeFontSizeAppend(obj) {
|
|
var fontSize = obj.fontSize + '',
|
|
normalizeFontSize;
|
|
|
|
if (!fontSize) { return obj; }
|
|
|
|
normalizeFontSize = fontSize.replace(/(\d+)(px)*/, '$1px');
|
|
obj.fontSize = normalizeFontSize;
|
|
|
|
return obj;
|
|
}
|
|
|
|
function isInvalid(arg){
|
|
if (arg === undefined || typeof arg === 'undefined' || arg === null) {
|
|
return true;
|
|
} else if (arg !== arg) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
compositionKeys.CAPTION = 'CAPTION';
|
|
compositionKeys.LEGEND_BODY = 'LEGEND_BODY';
|
|
compositionKeys.AXIS_LABEL = 'LEGEND_LABEL';
|
|
compositionKeys.LEGEND_AXIS = 'LEGEND_AXIS';
|
|
compositionKeys.RANGE = 'RANGE';
|
|
compositionKeys.AXIS_VALUE = 'AXIS_VALUE';
|
|
|
|
legendManager = (function () {
|
|
var layers,
|
|
components,
|
|
chart,
|
|
defaultConf = {},
|
|
config;
|
|
|
|
defaultConf.legendCarpetConf = {
|
|
spreadFactor : 0.85,
|
|
allowDrag: false,
|
|
captionAlignment: 'center',
|
|
padding: {
|
|
v: 3,
|
|
h: 3
|
|
},
|
|
style : {
|
|
'fill' : '#e4d9c1',
|
|
'stroke' : '#c4b89d'
|
|
}
|
|
};
|
|
|
|
defaultConf.legendCaptionConf = {
|
|
spreadFactor: 0.2,
|
|
padding: {
|
|
v: 2,
|
|
h: 2
|
|
},
|
|
style : {
|
|
fill: '#786B50',
|
|
fontFamily: 'sans-serif',
|
|
fontSize: '12px',
|
|
fontWeight: 'bold',
|
|
fontStyle: 'normal'
|
|
},
|
|
bound: {
|
|
style: {
|
|
stroke: 'none'
|
|
}
|
|
}
|
|
};
|
|
|
|
defaultConf.legendBodyConf = {
|
|
spreadFactor: 0.8,
|
|
padding: {
|
|
v: 2,
|
|
h: 2
|
|
},
|
|
bound: {
|
|
style: {
|
|
stroke: 'none'
|
|
}
|
|
}
|
|
};
|
|
|
|
defaultConf.legendAxisConf = {
|
|
legendAxisHeight: 11,
|
|
spreadFactor: 0.4,
|
|
padding: {
|
|
v: 1,
|
|
h: 1
|
|
},
|
|
style : {
|
|
stroke: 'none',
|
|
'stroke-opacity': 0,
|
|
'stroke-width': 1
|
|
},
|
|
line: {
|
|
grooveLength: 3,
|
|
offset: 8,
|
|
style: {
|
|
stroke: 'rgba(255, 255, 255, 0.65)',
|
|
'stroke-width': 1.5
|
|
}
|
|
},
|
|
shadow : {
|
|
style : {
|
|
stroke : 'none',
|
|
fill : toRaphaelColor({
|
|
FCcolor: {
|
|
alpha : '25,0,0',
|
|
angle : 360,
|
|
color : '000000,FFFFFF,FFFFFF',
|
|
ratio : '0,30,40'
|
|
}
|
|
})
|
|
}
|
|
},
|
|
bound: {
|
|
style: {
|
|
stroke: 'none'
|
|
}
|
|
}
|
|
};
|
|
|
|
defaultConf.sliderGroupConf = {
|
|
showTooltip: 1,
|
|
outerCircle : {
|
|
rFactor: 1.4,
|
|
style: {
|
|
fill: TRACKER_FILL,
|
|
stroke: '#757575',
|
|
'stroke-width': 3
|
|
}
|
|
},
|
|
innerCircle : {
|
|
rFactor: 0.65,
|
|
style: {
|
|
fill: TRACKER_FILL,
|
|
stroke: '#FFFFFF'
|
|
}
|
|
}
|
|
};
|
|
|
|
defaultConf.axisTextItemConf = {
|
|
spreadFactor: 0.3,
|
|
padding: {
|
|
v: 1,
|
|
h: 1
|
|
},
|
|
style : {
|
|
fill: '#786B50',
|
|
fontFamily: 'sans-serif',
|
|
fontSize: '12px',
|
|
fontWeight: 'normal',
|
|
fontStyle: 'normal'
|
|
}
|
|
};
|
|
|
|
function normalizePreprocessedData (confArr) {
|
|
var numberFormatter = components.numberFormatter,
|
|
index,
|
|
length,
|
|
rawVal;
|
|
|
|
for (index = 0, length = confArr.length; index < length; index++) {
|
|
rawVal = confArr[index].maxvalue;
|
|
|
|
if (!rawVal) {
|
|
continue;
|
|
}
|
|
|
|
confArr[index].maxvalue = numberFormatter.getCleanValue(rawVal);
|
|
}
|
|
}
|
|
|
|
return {
|
|
init : function (options) {
|
|
chart = options.chart;
|
|
layers = chart.graphics;
|
|
components = chart.components;
|
|
},
|
|
|
|
setConf : function (conf) {
|
|
config = conf;
|
|
},
|
|
|
|
legacyDataParser : function (data, extremes) {
|
|
var colormanagerConf = {},
|
|
numberFormatter = components.numberFormatter,
|
|
colorConfArr,
|
|
colorConf,
|
|
startColor,
|
|
endColor,
|
|
index,
|
|
validColor,
|
|
length,
|
|
colorRange,
|
|
value,
|
|
dispValue,
|
|
mapByPercent,
|
|
isMaxValPresent,
|
|
obj;
|
|
|
|
if (!data) {
|
|
return false;
|
|
}
|
|
|
|
colormanagerConf.mapByPercent = mapByPercent = !!(pluckNumber(data.mapbypercent, 0));
|
|
colorConfArr = data.color || [];
|
|
|
|
if (data.minvalue === undefined) {
|
|
data.minvalue = extremes.min !== undefined ? (mapByPercent ? 0 : extremes.min) : 0;
|
|
}
|
|
|
|
if (data.maxvalue === undefined) {
|
|
data.maxvalue = extremes.max !== undefined ? (mapByPercent ? 100 : extremes.max) : 100;
|
|
}
|
|
|
|
isMaxValPresent = false;
|
|
for (index = 0, length = colorConfArr.length; index < length; index++) {
|
|
if (colorConfArr[index].maxvalue) {
|
|
isMaxValPresent = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!isMaxValPresent) {
|
|
colorConfArr = [];
|
|
}
|
|
|
|
startColor = data.code;
|
|
|
|
colorRange = colormanagerConf.colorRange = [];
|
|
colormanagerConf.gradient = !!pluckNumber(data.gradient, 1);
|
|
|
|
// If no additional color array is provided as part of generating the gradient, creates the start and
|
|
// end value to create the gradient
|
|
if (!colorConfArr.length) {
|
|
if (startColor) {
|
|
// If start color is mentioned, create a gradient starting from default color to the mentioned
|
|
// color
|
|
endColor = getValidHexColor(startColor);
|
|
startColor = getValidHexColor();
|
|
} else {
|
|
// If no color is mentioned, create a gradient of two opposite color
|
|
startColor = getValidHexColor();
|
|
endColor = getOppositeColor(startColor);
|
|
}
|
|
|
|
colorConfArr.push({
|
|
code: endColor,
|
|
maxvalue: data.maxvalue,
|
|
label: undefined
|
|
});
|
|
|
|
} else {
|
|
startColor = getValidHexColor(startColor);
|
|
}
|
|
|
|
normalizePreprocessedData(colorConfArr);
|
|
|
|
colorConfArr = colorConfArr.sort(function (m, n) {
|
|
return m.maxvalue - n.maxvalue;
|
|
});
|
|
|
|
value = dispValue = data.minvalue && numberFormatter.getCleanValue(data.minvalue);
|
|
dispValue = (value !== undefined || value !== null) && (mapByPercent ? value + PERCENT_STR :
|
|
numberFormatter.legendValue(value));
|
|
colorRange.push({
|
|
code: dehashify(startColor),
|
|
value: value,
|
|
displayValue: dispValue,
|
|
label: data.startlabel
|
|
});
|
|
|
|
for (index = 0, length = colorConfArr.length; index < length; index++) {
|
|
colorConf = colorConfArr[index];
|
|
validColor = getValidHexColor(colorConf.code || colorConf.color);
|
|
|
|
value = dispValue = colorConf.maxvalue;
|
|
|
|
if(isNaN(parseInt(value, 10))) { continue; }
|
|
|
|
dispValue = (value !== undefined || value !== null) && (mapByPercent ? value + PERCENT_STR :
|
|
numberFormatter.legendValue(value));
|
|
|
|
colorRange.push(obj = new Object({
|
|
code: dehashify(validColor),
|
|
value: value,
|
|
displayValue: dispValue,
|
|
label: colorConf.label || colorConf.displayvalue
|
|
}));
|
|
}
|
|
|
|
colorRange[colorRange.length - 1].label = data.endlabel || colorConf.label;
|
|
|
|
return colormanagerConf;
|
|
|
|
},
|
|
|
|
getDefaultConf: function (key) {
|
|
return defaultConf[key];
|
|
}
|
|
};
|
|
})();
|
|
|
|
componentPoolFactory = function (chart) {
|
|
var chartId = chart.chartInstance.id,
|
|
pool = universalPool[chartId] || (universalPool[chartId] = {});
|
|
|
|
|
|
return (function () {
|
|
var elemTypes,
|
|
actions = {},
|
|
paper;
|
|
|
|
elemTypes = {
|
|
KEY_RECT : 'rect',
|
|
KEY_TEXT : 'text',
|
|
KEY_GROUP: 'group',
|
|
KEY_CIRCLE: 'circle',
|
|
KEY_PATH: 'path'
|
|
};
|
|
|
|
actions[elemTypes.KEY_RECT] = function (group) {
|
|
return paper.rect(group);
|
|
};
|
|
|
|
actions[elemTypes.KEY_TEXT] = function (attr, group) {
|
|
return paper.text(attr, group);
|
|
};
|
|
|
|
actions[elemTypes.KEY_GROUP] = function (groupName, parentGroup) {
|
|
return paper.group(groupName, parentGroup);
|
|
};
|
|
|
|
actions[elemTypes.KEY_CIRCLE] = function (group) {
|
|
return paper.circle(group);
|
|
};
|
|
|
|
actions[elemTypes.KEY_PATH] = function (pathStr, group) {
|
|
return paper.path(pathStr, group);
|
|
};
|
|
|
|
function _hideRecursive () {
|
|
var keyLevel1,
|
|
keyLevel2,
|
|
objLevel1,
|
|
val,
|
|
index, length;
|
|
|
|
for (keyLevel1 in pool) {
|
|
objLevel1 = pool[keyLevel1];
|
|
|
|
for (keyLevel2 in objLevel1) {
|
|
val = objLevel1[keyLevel2];
|
|
|
|
if (val instanceof Array) {
|
|
for (index = 0, length = val.length; index < length; index++) {
|
|
val[index] && val[index].hide();
|
|
}
|
|
} else {
|
|
val.hide();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
init: function (renderer) {
|
|
paper = renderer;
|
|
|
|
_hideRecursive();
|
|
},
|
|
|
|
emptyPool: function () {
|
|
pool = universalPool[chartId] = {};
|
|
},
|
|
|
|
getChart: function () {
|
|
return chart;
|
|
},
|
|
|
|
getComponent: function (id, elemType, storeTillReCall) {
|
|
var idSpecificPool = pool[id],
|
|
multiInstance,
|
|
instance,
|
|
inst,
|
|
instanceRetrieved = 0;
|
|
|
|
|
|
if (!idSpecificPool) {
|
|
idSpecificPool = pool[id] = {};
|
|
}
|
|
|
|
instance = idSpecificPool[elemType];
|
|
|
|
if ((instance && !(instance instanceof Array)) ||
|
|
(instance instanceof Array && instance.length > 0)) {
|
|
return function () {
|
|
if (storeTillReCall) {
|
|
inst = instance[instanceRetrieved++];
|
|
if (inst) {
|
|
return inst.show();
|
|
} else {
|
|
return instance[instanceRetrieved] = actions[elemType].apply(this, arguments);
|
|
}
|
|
}
|
|
|
|
return instance.show();
|
|
};
|
|
}
|
|
|
|
return function () {
|
|
if (storeTillReCall) {
|
|
multiInstance = idSpecificPool[elemType] || (idSpecificPool[elemType] = []);
|
|
instance = actions[elemType].apply(this, arguments);
|
|
multiInstance.push(instance);
|
|
|
|
return instance.show();
|
|
}
|
|
|
|
return idSpecificPool[elemType] = actions[elemType].apply(this, arguments);
|
|
};
|
|
|
|
},
|
|
|
|
hideAll: function () {
|
|
_hideRecursive();
|
|
},
|
|
|
|
getKeys: function () {
|
|
return elemTypes;
|
|
}
|
|
};
|
|
})();
|
|
};
|
|
|
|
function LegendBase (carpet, componentPool) {
|
|
this.carpet = carpet;
|
|
this._componentPool = componentPool;
|
|
}
|
|
|
|
LegendBase.prototype.constructor = LegendBase;
|
|
|
|
LegendBase.prototype.draw = function (options) {
|
|
options.componentPool = this._componentPool;
|
|
return this.carpet.draw(options);
|
|
};
|
|
|
|
LegendBase.prototype.getLogicalSpace = function (options, recalculate) {
|
|
options.componentPool = this._componentPool;
|
|
return this.carpet.getLogicalSpace(options, recalculate);
|
|
};
|
|
|
|
LegendBase.prototype.dispose = function () {
|
|
this.carpet && this.carpet.group && this.carpet.group.remove();
|
|
this._componentPool.emptyPool();
|
|
};
|
|
|
|
function LegendCarpet (conf) {
|
|
this.conf = conf;
|
|
this._id = 'GL_CARPET';
|
|
|
|
// Save the components which are the building block of the whole legend. Like: The background rect,
|
|
// text, slider, color axis etc.
|
|
this.compositionsByCategory = {};
|
|
this.node = undefined;
|
|
this.group = undefined;
|
|
this._lSpace = undefined;
|
|
this.autoRecalculate = false;
|
|
this.groupName = 'fc-gradient-legend';
|
|
this.moveInstructions = {};
|
|
}
|
|
|
|
LegendCarpet.prototype.constructor = LegendCarpet;
|
|
|
|
LegendCarpet.prototype.addCompositions = function (instance, category) {
|
|
this.compositionsByCategory[category] = instance;
|
|
};
|
|
|
|
LegendCarpet.prototype.getBoundingBox = function (options) {
|
|
var conf = this.conf,
|
|
spreadFactor = conf.spreadFactor,
|
|
refSide = options.refSide,
|
|
alignment = options.alignment,
|
|
refOffset = options.refOffset,
|
|
x = options.x,
|
|
y = options.y,
|
|
lWidth;
|
|
|
|
|
|
lWidth = conf.width = refSide * spreadFactor;
|
|
|
|
if (alignment && (x === undefined || x === null)) {
|
|
x = ((refOffset + refSide) / 2) - lWidth / 2;
|
|
}
|
|
|
|
return {
|
|
width: lWidth,
|
|
height: options.maxOtherSide,
|
|
x: x,
|
|
y: y
|
|
};
|
|
};
|
|
|
|
LegendCarpet.prototype.getPostCalcDecisions = function (bBox, componentsArea) {
|
|
var conf = this.conf,
|
|
padding = conf.padding,
|
|
cat,
|
|
totalHeightTaken = 0;
|
|
|
|
for (cat in componentsArea) {
|
|
totalHeightTaken += componentsArea[cat].height || 0;
|
|
}
|
|
|
|
bBox.height = totalHeightTaken + 2 * padding.v;
|
|
};
|
|
|
|
LegendCarpet.prototype.getLogicalSpace = function (options, recalculate) {
|
|
var lSpace = this._lSpace,
|
|
conf = this.conf,
|
|
padding = conf.padding,
|
|
compositionsByCategory = this.compositionsByCategory,
|
|
composition,
|
|
bBox,
|
|
effectivePlotArea,
|
|
compositionLSPace,
|
|
compositionHeight = 0,
|
|
componentsArea = { },
|
|
category,
|
|
compositionPlotArea,
|
|
autoRecalculate,
|
|
heightNotUsed = 0;
|
|
|
|
if (lSpace && !recalculate) {
|
|
lSpace.isImpure = true;
|
|
// If logical space has already been calculated and recalculate flag is on, return without recalculating.
|
|
return lSpace;
|
|
} else {
|
|
autoRecalculate = false;
|
|
}
|
|
|
|
lSpace = this._lSpace = bBox = this.getBoundingBox(options);
|
|
|
|
if (isInvalid(lSpace.x) || isInvalid(lSpace.y) || isInvalid(lSpace.height) || isInvalid(lSpace.width)) {
|
|
this.autoRecalculate = true;
|
|
}
|
|
|
|
// Copy the props
|
|
effectivePlotArea = merge(bBox, {});
|
|
|
|
// The logical rect inside which the composition are drawn
|
|
effectivePlotArea.height -= 2 * padding.v;
|
|
effectivePlotArea.width -= 2 * padding.h;
|
|
effectivePlotArea.x += padding.h;
|
|
effectivePlotArea.y += padding.v;
|
|
|
|
for (category in compositionsByCategory) {
|
|
composition = compositionsByCategory[category];
|
|
|
|
compositionPlotArea = merge(effectivePlotArea, {});
|
|
compositionPlotArea.y += compositionHeight;
|
|
compositionHeight = effectivePlotArea.height * composition.conf.spreadFactor;
|
|
compositionPlotArea.height = compositionHeight + heightNotUsed;
|
|
|
|
compositionLSPace = composition.getLogicalSpace(merge(compositionPlotArea, {}), options, recalculate);
|
|
|
|
heightNotUsed = compositionPlotArea.height - compositionLSPace.height;
|
|
|
|
componentsArea[category] = compositionLSPace;
|
|
|
|
compositionHeight = compositionLSPace.height;
|
|
}
|
|
|
|
this.getPostCalcDecisions(bBox, componentsArea);
|
|
|
|
this._lSpace = bBox;
|
|
return bBox;
|
|
};
|
|
|
|
LegendCarpet.prototype.setupDragging = function () {
|
|
var group = this. group,
|
|
dx = 0,
|
|
dy = 0,
|
|
idx = 0,
|
|
idy = 0;
|
|
|
|
group.css({cursor: 'move'});
|
|
group.drag(function (_dx, _dy) {
|
|
dx = _dx;
|
|
dy = _dy;
|
|
group.attr({
|
|
transform: 't' + (idx + dx) + ',' + (idy + dy)
|
|
});
|
|
}, function () {
|
|
idx += dx;
|
|
idy += dy;
|
|
}, function () { });
|
|
};
|
|
|
|
LegendCarpet.prototype.draw = function (options) {
|
|
var conf = this.conf,
|
|
compositionsByCategory = this.compositionsByCategory,
|
|
paper = options.paper,
|
|
parentGroup = options.parentGroup,
|
|
componentPool = options.componentPool,
|
|
chart = componentPool.getChart(),
|
|
group,
|
|
node,
|
|
category,
|
|
composition,
|
|
lSpace,
|
|
compositionRes,
|
|
animDuration = chart.get('config', 'animationObj').duration,
|
|
instanceFn,
|
|
keys = componentPool.getKeys();
|
|
|
|
this.getLogicalSpace(options, this.autoRecalculate);
|
|
lSpace = this._lSpace;
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
|
|
this.group = group = instanceFn(this.groupName, parentGroup);
|
|
|
|
group.attr({
|
|
opacity: 0
|
|
});
|
|
|
|
group.animate({
|
|
opacity: 1
|
|
}, animDuration, animType);
|
|
|
|
// The main rect outside all the composition
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
|
|
this.node = node = instanceFn(group).attr(lSpace).css(conf.style);
|
|
|
|
for (category in compositionsByCategory) {
|
|
composition = compositionsByCategory[category];
|
|
|
|
compositionRes = composition.draw(conf.captionAlignment, lSpace, {
|
|
colorRange: options.colorRange,
|
|
numberFormatter: options.numberFormatter,
|
|
paper: paper,
|
|
parentLayer: group,
|
|
smartLabel: options.smartLabel,
|
|
moveInstructions : this.moveInstructions[category],
|
|
componentPool: options.componentPool
|
|
});
|
|
}
|
|
|
|
conf.allowDrag && this.setupDragging();
|
|
return this.node;
|
|
};
|
|
|
|
|
|
function VerticalLegendCarpet () {
|
|
LegendCarpet.apply(this, arguments);
|
|
}
|
|
|
|
VerticalLegendCarpet.prototype = Object.create(LegendCarpet.prototype);
|
|
VerticalLegendCarpet.prototype.constructor = VerticalLegendCarpet;
|
|
|
|
VerticalLegendCarpet.prototype.getBoundingBox = function (options) {
|
|
var conf = this.conf,
|
|
spreadFactor = conf.spreadFactor,
|
|
refSide = options.refSide,
|
|
alignment = options.alignment,
|
|
refOffset = options.refOffset,
|
|
x = options.x,
|
|
y = options.y,
|
|
lHeight;
|
|
|
|
|
|
lHeight = conf.height = refSide * spreadFactor;
|
|
|
|
if (alignment && (y === undefined || y === null)) {
|
|
y = ((refOffset + refSide) / 2) - lHeight / 2;
|
|
}
|
|
|
|
return {
|
|
width: options.maxOtherSide,
|
|
height: lHeight,
|
|
x: x,
|
|
y: y
|
|
};
|
|
};
|
|
|
|
VerticalLegendCarpet.prototype.getPostCalcDecisions = function (bBox, componentsArea) {
|
|
var conf = this.conf,
|
|
padding = conf.padding,
|
|
maxWidth = Number.NEGATIVE_INFINITY,
|
|
width,
|
|
cat,
|
|
move = this.moveInstructions,
|
|
diff;
|
|
|
|
LegendCarpet.prototype.getPostCalcDecisions.apply(this, arguments);
|
|
|
|
for (cat in componentsArea) {
|
|
width = componentsArea[cat].width;
|
|
maxWidth = maxWidth < width ? width : maxWidth;
|
|
}
|
|
|
|
bBox.width = maxWidth + 2 * padding.h;
|
|
|
|
for (cat in componentsArea) {
|
|
width = componentsArea[cat].width;
|
|
if (diff = maxWidth - width) {
|
|
move[cat] = 't' + diff / 2 + ',0';
|
|
}
|
|
}
|
|
};
|
|
|
|
function LegendCaption (text, conf) {
|
|
this.rawText = text;
|
|
this.conf = conf;
|
|
this._id = 'GL_CAPTION';
|
|
|
|
this.node = undefined;
|
|
this.bound = undefined;
|
|
this._lSpace = undefined;
|
|
}
|
|
|
|
LegendCaption.prototype.constructor = LegendCaption;
|
|
|
|
LegendCaption.LEFT = {
|
|
x: function (smartText, boundingBox) {
|
|
return boundingBox.x + smartText.width / 2 + 2;
|
|
}
|
|
};
|
|
|
|
LegendCaption.RIGHT = {
|
|
x: function (smartText, boundingBox) {
|
|
return boundingBox.x + boundingBox.width - smartText.width / 2 - 2;
|
|
}
|
|
};
|
|
|
|
LegendCaption.CENTER = {
|
|
x: function (smartText, boundingBox) {
|
|
return boundingBox.x + (boundingBox.width / 2);
|
|
}
|
|
};
|
|
|
|
LegendCaption.prototype.getLogicalSpace = function (bBox, options, recalculate) {
|
|
var conf = this.conf,
|
|
padding = conf.padding,
|
|
lSpace = this._lSpace,
|
|
text = this.rawText,
|
|
componentPool = options.componentPool,
|
|
chart = componentPool.getChart(),
|
|
smartLabel,
|
|
effectivePlotArea,
|
|
smartText,
|
|
copyOfStyle;
|
|
|
|
if (lSpace && !recalculate) {
|
|
lSpace.isImpure = true;
|
|
// If logical space has already been calculated and recalculate flag is on, return without recalculating.
|
|
return lSpace;
|
|
}
|
|
|
|
lSpace = this._lSpace = {
|
|
bound: {
|
|
height: 0,
|
|
width: 0
|
|
},
|
|
|
|
node: {
|
|
logicArea: undefined,
|
|
smartText: undefined
|
|
}
|
|
};
|
|
|
|
smartLabel = options.smartLabel;
|
|
|
|
if (!text) {
|
|
return lSpace.bound;
|
|
}
|
|
|
|
effectivePlotArea = merge(bBox, {});
|
|
|
|
// The logical rect inside which the composition are drawn
|
|
effectivePlotArea.height -= 2 * padding.v;
|
|
effectivePlotArea.width -= 2 * padding.h;
|
|
effectivePlotArea.x += padding.h;
|
|
effectivePlotArea.y += padding.v;
|
|
|
|
smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
|
|
copyOfStyle = merge(this.conf.style, {});
|
|
normalizeFontSizeAppend(copyOfStyle);
|
|
|
|
smartLabel.setStyle(this._metaStyle = copyOfStyle);
|
|
smartText = smartLabel.getSmartText(text, effectivePlotArea.width, effectivePlotArea.height);
|
|
|
|
effectivePlotArea.height = smartText.height;
|
|
effectivePlotArea.width = smartText.width;
|
|
|
|
bBox.height = smartText.height + 2 * padding.v;
|
|
bBox.width = smartText.width + 2 * padding.h;
|
|
|
|
lSpace.node.smartText = smartText;
|
|
lSpace.node.logicArea = effectivePlotArea;
|
|
lSpace.bound = bBox;
|
|
|
|
return bBox;
|
|
};
|
|
|
|
LegendCaption.prototype.draw = function () {
|
|
var conf = this.conf,
|
|
smartLabel,
|
|
paper,
|
|
layer,
|
|
boundAttr = conf.bound || {},
|
|
group,
|
|
bound,
|
|
instanceFn,
|
|
boundingArea,
|
|
lSpace,
|
|
normalizedX,
|
|
x,
|
|
bBox,
|
|
options,
|
|
node,
|
|
componentPool,
|
|
keys;
|
|
|
|
if (arguments.length >= 3) {
|
|
x = arguments[0];
|
|
bBox = arguments[1];
|
|
options = arguments[2];
|
|
} else if (arguments.length >= 2){
|
|
x = arguments[0];
|
|
options = arguments[1];
|
|
}
|
|
|
|
smartLabel = options.smartLabel;
|
|
paper = options.paper;
|
|
layer = options.parentLayer;
|
|
componentPool = options.componentPool;
|
|
keys = componentPool.getKeys();
|
|
|
|
// Separate group for caption and the bounding rect
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
|
|
this.group = group = instanceFn('legend-caption', layer).css(conf.style);
|
|
|
|
//group = paper.group('legend-caption', layer);
|
|
|
|
this.getLogicalSpace(bBox, options);
|
|
lSpace = this._lSpace;
|
|
|
|
node = lSpace.node;
|
|
boundingArea = lSpace.bound;
|
|
|
|
// Bounding rect
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
|
|
this.bound = bound = instanceFn(group).attr(boundingArea).css(boundAttr.style);
|
|
//bound = this.bound = paper.rect(boundingArea, group).css(boundAttr.style);
|
|
|
|
normalizedX = typeof x === 'string' ? LegendCaption[x.toUpperCase()].x(node.smartText, bBox || node.logicArea)
|
|
: x;
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_TEXT);
|
|
this.node = instanceFn({ }, group).attr({
|
|
text: node.smartText.text,
|
|
x: normalizedX,
|
|
y: node.logicArea.y + (node.smartText.height / 2),
|
|
lineHeight: this._metaStyle.lineHeight,
|
|
fill: conf.style.fill
|
|
});
|
|
|
|
return {
|
|
group: group,
|
|
bound: bound,
|
|
node: this.node
|
|
};
|
|
};
|
|
|
|
|
|
|
|
function LegendBody (colorRange, conf, childTextConf) {
|
|
this.colorRange = colorRange;
|
|
this.conf = conf;
|
|
this.childTextConf = childTextConf;
|
|
this._id = 'GL_BODY';
|
|
|
|
this.bound = undefined;
|
|
this.compositionsByCategory = {};
|
|
this._lSpace = undefined;
|
|
}
|
|
|
|
// Space calculation order
|
|
LegendBody.SC_STACK = [
|
|
compositionKeys.AXIS_LABEL,
|
|
compositionKeys.LEGEND_AXIS,
|
|
compositionKeys.AXIS_VALUE
|
|
];
|
|
|
|
LegendBody.DARW_STACK = [
|
|
compositionKeys.AXIS_VALUE,
|
|
compositionKeys.LEGEND_AXIS,
|
|
compositionKeys.AXIS_LABEL
|
|
];
|
|
|
|
LegendBody.prototype.constructor = LegendBody;
|
|
|
|
LegendBody.prototype.addCompositions = function (instance, category) {
|
|
this.compositionsByCategory[category] = instance;
|
|
};
|
|
|
|
LegendBody.prototype.getCompositionPlotAreaFor = function (effectivePlotArea) {
|
|
var plotArea;
|
|
|
|
plotArea = merge(effectivePlotArea, {});
|
|
|
|
return function (compositionAreaOffset, sf) {
|
|
compositionAreaOffset = compositionAreaOffset || {};
|
|
|
|
plotArea.y += compositionAreaOffset.height || 0;
|
|
plotArea.height = effectivePlotArea.height * sf;
|
|
|
|
return plotArea;
|
|
};
|
|
};
|
|
|
|
LegendBody.prototype.getSpaceTaken = function (spaceObj) {
|
|
return spaceObj.height;
|
|
};
|
|
|
|
LegendBody.prototype.updateEffectivePlotArea = function (bBox, effectivePlotArea, val) {
|
|
var conf = this.conf,
|
|
padding = conf.padding;
|
|
|
|
effectivePlotArea.height = val;
|
|
bBox.height = val + 2 * padding.v;
|
|
};
|
|
|
|
LegendBody.prototype.getLogicalSpace = function (bBox, options, recalculate) {
|
|
var lSpace = this._lSpace,
|
|
conf = this.conf,
|
|
padding = conf.padding,
|
|
compositionsByCategory = this.compositionsByCategory,
|
|
composition,
|
|
compositionPlotArea,
|
|
compositionAreaOffset,
|
|
effectivePlotArea,
|
|
getCompositionPlotArea,
|
|
spaceTaken = 0,
|
|
index,
|
|
length;
|
|
|
|
if (lSpace && !recalculate) {
|
|
lSpace.isImpure = true;
|
|
// If logical space has already been calculated and recalculate flag is on, return without recalculating.
|
|
return lSpace;
|
|
}
|
|
|
|
lSpace = this._lSpace = {
|
|
bound: {
|
|
height: 0,
|
|
width: 0
|
|
},
|
|
|
|
node: {
|
|
logicArea: undefined
|
|
}
|
|
};
|
|
|
|
effectivePlotArea = merge(bBox, {});
|
|
|
|
// The logical rect inside which the composition are drawn
|
|
effectivePlotArea.height -= 2 * padding.v;
|
|
effectivePlotArea.width -= 2 * padding.h;
|
|
effectivePlotArea.x += padding.h;
|
|
effectivePlotArea.y += padding.v;
|
|
|
|
getCompositionPlotArea = this.getCompositionPlotAreaFor(effectivePlotArea);
|
|
|
|
options.colorRange = this.colorRange;
|
|
|
|
for (index = 0, length = LegendBody.SC_STACK.length; index < length; index++) {
|
|
if (!(composition = compositionsByCategory[LegendBody.SC_STACK[index]])) {
|
|
continue;
|
|
}
|
|
|
|
compositionPlotArea = getCompositionPlotArea(compositionAreaOffset, composition.conf.spreadFactor);
|
|
compositionAreaOffset = composition.getLogicalSpace(merge(compositionPlotArea, {}), options, recalculate);
|
|
|
|
spaceTaken += this.getSpaceTaken(compositionAreaOffset);
|
|
}
|
|
|
|
this.updateEffectivePlotArea(bBox, effectivePlotArea, spaceTaken);
|
|
|
|
lSpace.node.logicArea = effectivePlotArea;
|
|
lSpace.bound = bBox;
|
|
|
|
return bBox;
|
|
};
|
|
|
|
LegendBody.prototype.draw = function () {
|
|
var childTextConf = this.childTextConf,
|
|
conf = this.conf,
|
|
boundStyle = conf.bound.style || {},
|
|
compositionsByCategory = this.compositionsByCategory,
|
|
paper,
|
|
layer,
|
|
bound,
|
|
colorRange,
|
|
composition,
|
|
legendBodyGroup,
|
|
bBox,
|
|
componentPool,
|
|
lSpace,
|
|
x,
|
|
options,
|
|
index,
|
|
length,
|
|
instanceFn,
|
|
keys;
|
|
|
|
|
|
if (arguments.length >= 3) {
|
|
x = arguments[0];
|
|
bBox = arguments[1];
|
|
options = arguments[2];
|
|
} else if (arguments.length >= 2){
|
|
x = arguments[0];
|
|
options = arguments[1];
|
|
}
|
|
|
|
paper = options.paper;
|
|
layer = options.parentLayer;
|
|
colorRange = options.colorRange;
|
|
componentPool = options.componentPool;
|
|
keys = componentPool.getKeys();
|
|
|
|
this.getLogicalSpace(bBox, options);
|
|
lSpace = this._lSpace;
|
|
// debugger
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
|
|
legendBodyGroup = instanceFn('legend-body', layer).attr({
|
|
transform: 't0,0'
|
|
}).css(childTextConf.style);
|
|
//legendBodyGroup = paper.group('legend-body', layer);
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
|
|
this.bound = bound = instanceFn(legendBodyGroup).attr(lSpace.bound).css(boundStyle);
|
|
//bound = this.bound = paper.rect(lSpace.bound, legendBodyGroup).css(boundStyle);
|
|
|
|
|
|
options.colorRange = this.colorRange;
|
|
options.parentLayer = legendBodyGroup;
|
|
for (index = 0, length = LegendBody.DARW_STACK.length; index < length; index++) {
|
|
if (!(composition = compositionsByCategory[LegendBody.DARW_STACK[index]])) {
|
|
continue;
|
|
}
|
|
|
|
composition.draw(options);
|
|
}
|
|
|
|
if (options.moveInstructions) {
|
|
legendBodyGroup.attr({
|
|
transform: options.moveInstructions
|
|
});
|
|
}
|
|
|
|
return {
|
|
bound: bound,
|
|
group: legendBodyGroup
|
|
};
|
|
};
|
|
|
|
function VerticalLegendBody () {
|
|
LegendBody.apply(this, arguments);
|
|
}
|
|
|
|
VerticalLegendBody.prototype = Object.create(LegendBody.prototype);
|
|
VerticalLegendBody.prototype.constructor = VerticalLegendBody;
|
|
|
|
VerticalLegendBody.prototype.getCompositionPlotAreaFor = function (effectivePlotArea) {
|
|
var plotArea;
|
|
|
|
plotArea = merge(effectivePlotArea, {});
|
|
|
|
return function (compositionAreaOffset, sf) {
|
|
compositionAreaOffset = compositionAreaOffset || {};
|
|
|
|
plotArea.x += compositionAreaOffset.width || 0;
|
|
plotArea.width = effectivePlotArea.width * sf;
|
|
|
|
return plotArea;
|
|
};
|
|
};
|
|
|
|
VerticalLegendBody.prototype.updateEffectivePlotArea = function (bBox, effectivePlotArea, val) {
|
|
var conf = this.conf,
|
|
padding = conf.padding;
|
|
|
|
effectivePlotArea.width = val;
|
|
bBox.width = val + 2 * padding.h;
|
|
};
|
|
|
|
VerticalLegendBody.prototype.getSpaceTaken = function (spaceObj) {
|
|
return spaceObj.width;
|
|
};
|
|
|
|
function LegendLabels(conf) {
|
|
this.conf = conf;
|
|
this._id = 'GL_LABELS';
|
|
}
|
|
|
|
LegendLabels.prototype.constructor = LegendLabels;
|
|
|
|
LegendLabels.prototype.getEffectivePlotArea = function (area) {
|
|
var conf = this.conf,
|
|
padding = conf.padding;
|
|
|
|
// The logical rect inside which the composition are drawn
|
|
area.height -= 2 * padding.v;
|
|
area.width -= 2 * padding.h;
|
|
area.x += padding.h;
|
|
area.y += padding.v;
|
|
this.node = [];
|
|
|
|
return area;
|
|
};
|
|
|
|
LegendLabels.prototype.getLogicalSpace = function (bBox, options, recalculate) {
|
|
var lSpace = this._lSpace,
|
|
conf = this.conf,
|
|
padding = conf.padding,
|
|
cRange,
|
|
smartLabel,
|
|
crDataObj,
|
|
index,
|
|
length,
|
|
labelHeights = [],
|
|
leftBound,
|
|
rightBound,
|
|
plotArea,
|
|
label,
|
|
valueRatio,
|
|
stop,
|
|
zerothStop,
|
|
lsTexts,
|
|
maxHeight,
|
|
effectivePlotArea,
|
|
testSmartLabel,
|
|
noOfLabels = 0,
|
|
nextRefPoint,
|
|
currPoint,
|
|
leftStop,
|
|
smartText,
|
|
ni,
|
|
copyOfStyle,
|
|
componentPool = options.componentPool,
|
|
chart = componentPool.getChart(),
|
|
normalizedDataArr = [];
|
|
|
|
if (lSpace && !recalculate) {
|
|
lSpace.isImpure = true;
|
|
// If logical space has already been calculated and recalculate flag is on, return without recalculating.
|
|
return lSpace;
|
|
}
|
|
|
|
cRange = options.colorRange;
|
|
smartLabel = options.smartLabel;
|
|
valueRatio = cRange.getCumulativeValueRatio();
|
|
crDataObj = cRange.colorRange;
|
|
|
|
lSpace = this._lSpace = {
|
|
bound: {
|
|
height: 0,
|
|
width: 0
|
|
},
|
|
|
|
node: {
|
|
logicArea: undefined,
|
|
smartTexts: []
|
|
}
|
|
};
|
|
|
|
lsTexts = lSpace.node.smartTexts;
|
|
|
|
plotArea = merge(bBox, {});
|
|
|
|
// The logical rect inside which the composition are drawn
|
|
effectivePlotArea = this.getEffectivePlotArea(plotArea);
|
|
|
|
smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
|
|
copyOfStyle = merge(conf.style, {});
|
|
normalizeFontSizeAppend(this._metaStyle = copyOfStyle);
|
|
|
|
smartLabel.setStyle(copyOfStyle);
|
|
testSmartLabel = smartLabel.getSmartText('W');
|
|
|
|
for (index = 0, length = crDataObj.length; index < length; index++) {
|
|
label = crDataObj[index].label;
|
|
|
|
if (!label) {
|
|
lsTexts[index] = undefined;
|
|
continue;
|
|
}
|
|
|
|
noOfLabels++;
|
|
normalizedDataArr.push({
|
|
oriIndex: index,
|
|
label: label
|
|
});
|
|
}
|
|
|
|
length = normalizedDataArr.length;
|
|
|
|
if (length === 0) {
|
|
return {
|
|
height: 0,
|
|
width: 0
|
|
};
|
|
}
|
|
|
|
if (length > 1) {
|
|
stop = ((valueRatio[normalizedDataArr[length - 1].oriIndex] -
|
|
valueRatio[normalizedDataArr[0].oriIndex]) / 2) * effectivePlotArea.width / 100;
|
|
} else {
|
|
stop = Math.max(valueRatio[normalizedDataArr[0].oriIndex], 100 -
|
|
valueRatio[normalizedDataArr[0].oriIndex]) / 2 * effectivePlotArea.width / 100;
|
|
}
|
|
|
|
zerothStop = stop;
|
|
|
|
// first scale Label
|
|
smartText = smartLabel.getSmartText(normalizedDataArr[0].label, zerothStop, effectivePlotArea.height);
|
|
smartText.x = valueRatio[normalizedDataArr[0].oriIndex] * effectivePlotArea.width / 100;
|
|
leftBound = smartText.x + smartText.width;
|
|
labelHeights.push(smartText.height);
|
|
lsTexts[normalizedDataArr[0].oriIndex] = smartText;
|
|
|
|
//last scale label
|
|
smartText = smartLabel.getSmartText(normalizedDataArr[length - 1].label,
|
|
zerothStop, effectivePlotArea.height);
|
|
smartText.x = valueRatio[normalizedDataArr[length - 1].oriIndex] * effectivePlotArea.width / 100;
|
|
rightBound = smartText.x - smartText.width;
|
|
labelHeights.push(smartText.height);
|
|
lsTexts[normalizedDataArr[length - 1].oriIndex] = smartText;
|
|
|
|
leftStop = leftBound;
|
|
for (index = 1; index < length - 1; index++) {
|
|
label = normalizedDataArr[index].label;
|
|
ni = normalizedDataArr[index].oriIndex;
|
|
|
|
smartText = undefined;
|
|
|
|
nextRefPoint = index + 1 === length - 1 ? rightBound : valueRatio[normalizedDataArr[index + 1].oriIndex] *
|
|
effectivePlotArea.width / 100;
|
|
|
|
currPoint = valueRatio[normalizedDataArr[index].oriIndex] * effectivePlotArea.width / 100;
|
|
|
|
stop = Math.min(currPoint - leftStop, nextRefPoint - currPoint);
|
|
|
|
if (stop > 2 * testSmartLabel.width) {
|
|
smartText = smartLabel.getSmartText(label, stop, effectivePlotArea.height);
|
|
smartText.x = valueRatio[ni] * effectivePlotArea.width / 100;
|
|
|
|
leftStop = stop;
|
|
labelHeights.push(smartText.height);
|
|
}
|
|
|
|
lsTexts[normalizedDataArr[index].oriIndex] = smartText;
|
|
}
|
|
|
|
maxHeight = Math.max.apply(Math, labelHeights);
|
|
|
|
effectivePlotArea.height = maxHeight;
|
|
bBox.height = maxHeight + 2 * padding.v;
|
|
|
|
lSpace.node.logicArea = effectivePlotArea;
|
|
lSpace.bound = bBox;
|
|
|
|
return bBox;
|
|
};
|
|
|
|
LegendLabels.prototype.draw = function () {
|
|
var paper,
|
|
layer,
|
|
bound,
|
|
conf = this.conf,
|
|
boundStyle = conf.bound && conf.bound.style || {
|
|
stroke: 'none'
|
|
},
|
|
cRange,
|
|
componentPool,
|
|
legendLabelsGroup,
|
|
bBox,
|
|
smartText,
|
|
lSpace,
|
|
crDataObj,
|
|
valueRatio,
|
|
options,
|
|
index,
|
|
logicArea,
|
|
lsTexts,
|
|
length,
|
|
pos = {},
|
|
instanceFn,
|
|
keys;
|
|
|
|
|
|
if (arguments.length >= 2) {
|
|
bBox = arguments[0];
|
|
options = arguments[1];
|
|
} else if (arguments.length >= 1){
|
|
options = arguments[0];
|
|
}
|
|
|
|
paper = options.paper;
|
|
layer = options.parentLayer;
|
|
cRange = options.colorRange;
|
|
valueRatio = cRange.getCumulativeValueRatio();
|
|
crDataObj = cRange.colorRange;
|
|
componentPool = options.componentPool;
|
|
keys = componentPool.getKeys();
|
|
|
|
this.getLogicalSpace(bBox, options);
|
|
lSpace = this._lSpace;
|
|
logicArea = lSpace.node.logicArea;
|
|
lsTexts = lSpace.node.smartTexts;
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
|
|
legendLabelsGroup = instanceFn('legend-labels', layer);
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
|
|
this.bound = bound = instanceFn(legendLabelsGroup).attr(lSpace.bound).css(boundStyle);
|
|
|
|
// legendLabelsGroup.transform('R0');
|
|
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_TEXT, true);
|
|
for (index = 0, length = lsTexts.length; index < length; index++) {
|
|
smartText = lsTexts[index];
|
|
|
|
if (!smartText) {
|
|
continue;
|
|
}
|
|
|
|
pos.y = logicArea.y + smartText.height / 2;
|
|
|
|
if (index === length - 1) {
|
|
pos.x = logicArea.x + smartText.x - smartText.width / 2;
|
|
} else if (index){
|
|
pos.x = logicArea.x + smartText.x;
|
|
} else {
|
|
pos.x = logicArea.x + smartText.x + smartText.width / 2;
|
|
}
|
|
|
|
this.node.push(instanceFn({}, legendLabelsGroup).attr({
|
|
text: smartText.text,
|
|
x: pos.x,
|
|
y: pos.y,
|
|
lineHeight: this._metaStyle.lineHeight,
|
|
fill: conf.style.fill
|
|
}).transform('R0'));
|
|
}
|
|
|
|
return {
|
|
group: legendLabelsGroup,
|
|
bound: bound,
|
|
node: this.node
|
|
};
|
|
};
|
|
|
|
function VerticalLegendLabels () {
|
|
LegendLabels.apply(this, arguments);
|
|
}
|
|
|
|
VerticalLegendLabels.prototype = Object.create(LegendLabels.prototype);
|
|
VerticalLegendLabels.prototype.constructor = VerticalLegendLabels;
|
|
|
|
VerticalLegendLabels.prototype.getLogicalSpace = function (bBox, options, recalculate) {
|
|
var lSpace = this._lSpace,
|
|
conf = this.conf,
|
|
padding = conf.padding,
|
|
cRange,
|
|
smartLabel,
|
|
crDataObj,
|
|
index,
|
|
length,
|
|
labelHeights = [],
|
|
leftBound,
|
|
rightBound,
|
|
plotArea,
|
|
label,
|
|
valueRatio,
|
|
stop,
|
|
zerothStop,
|
|
lsTexts,
|
|
maxHeight,
|
|
effectivePlotArea,
|
|
testSmartLabel,
|
|
noOfLabels = 0,
|
|
nextRefPoint,
|
|
currPoint,
|
|
leftStop,
|
|
smartText,
|
|
ni,
|
|
copyOfStyle,
|
|
componentPool = options.componentPool,
|
|
chart = componentPool.getChart(),
|
|
normalizedDataArr = [];
|
|
|
|
if (lSpace && !recalculate) {
|
|
lSpace.isImpure = true;
|
|
// If logical space has already been calculated and recalculate flag is on, return without recalculating.
|
|
return lSpace;
|
|
}
|
|
|
|
cRange = options.colorRange;
|
|
smartLabel = options.smartLabel;
|
|
valueRatio = cRange.getCumulativeValueRatio();
|
|
crDataObj = cRange.colorRange;
|
|
|
|
lSpace = this._lSpace = {
|
|
bound: {
|
|
height: 0,
|
|
width: 0
|
|
},
|
|
|
|
node: {
|
|
logicArea: undefined,
|
|
smartTexts: []
|
|
}
|
|
};
|
|
|
|
lsTexts = lSpace.node.smartTexts;
|
|
|
|
plotArea = merge(bBox, {});
|
|
|
|
// The logical rect inside which the composition are drawn
|
|
effectivePlotArea = this.getEffectivePlotArea(plotArea);
|
|
|
|
smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
|
|
copyOfStyle = merge(conf.style, {});
|
|
normalizeFontSizeAppend(this._metaStyle = copyOfStyle);
|
|
|
|
smartLabel.setStyle(copyOfStyle);
|
|
testSmartLabel = smartLabel.getSmartText('W');
|
|
|
|
for (index = 0, length = crDataObj.length; index < length; index++) {
|
|
label = crDataObj[index].label;
|
|
|
|
if (!label) {
|
|
lsTexts[index] = undefined;
|
|
continue;
|
|
}
|
|
|
|
noOfLabels++;
|
|
normalizedDataArr.push({
|
|
oriIndex: index,
|
|
label: label
|
|
});
|
|
}
|
|
|
|
length = normalizedDataArr.length;
|
|
|
|
if (length === 0) {
|
|
return {
|
|
height: 0,
|
|
width: 0
|
|
};
|
|
}
|
|
|
|
if (length > 1) {
|
|
stop = ((valueRatio[normalizedDataArr[length - 1].oriIndex] -
|
|
valueRatio[normalizedDataArr[0].oriIndex]) / 2) * effectivePlotArea.height / 100;
|
|
} else {
|
|
stop = Math.max(valueRatio[normalizedDataArr[0].oriIndex], 100 -
|
|
valueRatio[normalizedDataArr[0].oriIndex]) / 2 * effectivePlotArea.height / 100;
|
|
}
|
|
|
|
zerothStop = stop;
|
|
|
|
// first scale Label
|
|
smartText = smartLabel.getSmartText(normalizedDataArr[0].label, zerothStop, effectivePlotArea.width);
|
|
smartText.y = valueRatio[normalizedDataArr[0].oriIndex] * effectivePlotArea.height / 100;
|
|
leftBound = smartText.y + smartText.width;
|
|
labelHeights.push(smartText.height);
|
|
lsTexts[normalizedDataArr[0].oriIndex] = smartText;
|
|
|
|
//last scale label
|
|
smartText = smartLabel.getSmartText(normalizedDataArr[length - 1].label, zerothStop, effectivePlotArea.width);
|
|
smartText.y = valueRatio[normalizedDataArr[length - 1].oriIndex] * effectivePlotArea.height / 100;
|
|
rightBound = smartText.y - smartText.width;
|
|
labelHeights.push(smartText.height);
|
|
lsTexts[normalizedDataArr[length - 1].oriIndex] = smartText;
|
|
|
|
leftStop = leftBound;
|
|
for (index = 1; index < length - 1; index++) {
|
|
label = normalizedDataArr[index].label;
|
|
ni = normalizedDataArr[index].oriIndex;
|
|
|
|
smartText = undefined;
|
|
|
|
nextRefPoint = index + 1 === length - 1 ? rightBound : valueRatio[normalizedDataArr[index + 1].oriIndex] *
|
|
effectivePlotArea.height / 100;
|
|
|
|
currPoint = valueRatio[normalizedDataArr[index].oriIndex] * effectivePlotArea.height / 100;
|
|
|
|
stop = Math.min(currPoint - leftStop, nextRefPoint - currPoint);
|
|
|
|
if (stop > 2 * testSmartLabel.width) {
|
|
smartText = smartLabel.getSmartText(label, stop, effectivePlotArea.width);
|
|
smartText.y = valueRatio[ni] * effectivePlotArea.height / 100;
|
|
|
|
leftStop = stop;
|
|
labelHeights.push(smartText.height);
|
|
}
|
|
|
|
lsTexts[normalizedDataArr[index].oriIndex] = smartText;
|
|
}
|
|
|
|
maxHeight = Math.max.apply(Math, labelHeights);
|
|
|
|
effectivePlotArea.width = maxHeight;
|
|
bBox.width = maxHeight + 2 * padding.v;
|
|
|
|
lSpace.node.logicArea = effectivePlotArea;
|
|
lSpace.bound = bBox;
|
|
|
|
return bBox;
|
|
};
|
|
|
|
VerticalLegendLabels.prototype.draw = function () {
|
|
var paper,
|
|
layer,
|
|
bound,
|
|
conf = this.conf,
|
|
boundStyle = conf.bound && conf.bound.style || {
|
|
stroke: 'none'
|
|
},
|
|
cRange,
|
|
componentPool,
|
|
legendLabelsGroup,
|
|
bBox,
|
|
smartText,
|
|
lSpace,
|
|
crDataObj,
|
|
valueRatio,
|
|
options,
|
|
index,
|
|
logicArea,
|
|
lsTexts,
|
|
length,
|
|
pos = {},
|
|
instanceFn,
|
|
keys;
|
|
|
|
|
|
if (arguments.length >= 2) {
|
|
bBox = arguments[0];
|
|
options = arguments[1];
|
|
} else if (arguments.length >= 1){
|
|
options = arguments[0];
|
|
}
|
|
|
|
paper = options.paper;
|
|
layer = options.parentLayer;
|
|
cRange = options.colorRange;
|
|
valueRatio = cRange.getCumulativeValueRatio();
|
|
crDataObj = cRange.colorRange;
|
|
componentPool = options.componentPool;
|
|
keys = componentPool.getKeys();
|
|
|
|
this.getLogicalSpace(bBox, options);
|
|
lSpace = this._lSpace;
|
|
logicArea = lSpace.node.logicArea;
|
|
lsTexts = lSpace.node.smartTexts;
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
|
|
legendLabelsGroup = instanceFn('legend-labels', layer);
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
|
|
this.bound = bound = instanceFn(legendLabelsGroup).attr(lSpace.bound).css(boundStyle);
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_TEXT, true);
|
|
for (index = 0, length = lsTexts.length; index < length; index++) {
|
|
smartText = lsTexts[index];
|
|
|
|
if (!smartText) {
|
|
continue;
|
|
}
|
|
|
|
pos.x = logicArea.x + smartText.height / 2;
|
|
|
|
if (index === length - 1) {
|
|
pos.y = logicArea.y + smartText.y - smartText.width / 2;
|
|
} else if (index){
|
|
pos.y = logicArea.y + smartText.y;
|
|
} else {
|
|
pos.y = logicArea.y + smartText.y + smartText.width / 2;
|
|
}
|
|
|
|
this.node.push(instanceFn({}, legendLabelsGroup).attr({
|
|
text: smartText.text,
|
|
x: pos.x,
|
|
y: pos.y,
|
|
lineHeight: this._metaStyle.lineHeight,
|
|
fill: conf.style.fill
|
|
}).transform('R270,' + pos.x + ',' + pos.y));
|
|
}
|
|
|
|
return {
|
|
group: legendLabelsGroup,
|
|
bound: bound,
|
|
node: this.node
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
function LegendValues () {
|
|
LegendLabels.apply(this, arguments);
|
|
this._id = 'GL_VALUES';
|
|
}
|
|
|
|
LegendValues.prototype = Object.create(LegendLabels.prototype);
|
|
LegendValues.prototype.constructor = LegendValues;
|
|
|
|
LegendValues.prototype.getLogicalSpace = function (bBox, options, recalculate) {
|
|
var lSpace = this._lSpace,
|
|
conf = this.conf,
|
|
padding = conf.padding,
|
|
componentPool = options.componentPool,
|
|
chart = componentPool.getChart(),
|
|
cRange,
|
|
smartLabel,
|
|
crDataObj,
|
|
smartText,
|
|
index,
|
|
length,
|
|
valueRatio,
|
|
stop,
|
|
nextRefPoint,
|
|
currPoint,
|
|
zerothStop,
|
|
labelHeights = [],
|
|
leftBound,
|
|
leftStop,
|
|
rightBound,
|
|
maxHeight,
|
|
effectivePlotArea,
|
|
val,
|
|
dispValue,
|
|
testSmartLabel,
|
|
copyOfStyle,
|
|
lsTexts;
|
|
|
|
if (lSpace && !recalculate) {
|
|
lSpace.isImpure = true;
|
|
// If logical space has already been calculated and recalculate flag is on, return without recalculating.
|
|
return lSpace;
|
|
}
|
|
|
|
cRange = options.colorRange;
|
|
smartLabel = options.smartLabel;
|
|
crDataObj = cRange.colorRange;
|
|
valueRatio = cRange.getCumulativeValueRatio();
|
|
|
|
lSpace = this._lSpace = {
|
|
bound: {
|
|
height: 0,
|
|
width: 0
|
|
},
|
|
|
|
node: {
|
|
logicArea: undefined,
|
|
smartTexts: []
|
|
}
|
|
};
|
|
|
|
lsTexts = lSpace.node.smartTexts;
|
|
effectivePlotArea = merge(bBox, {});
|
|
|
|
// The logical rect inside which the composition are drawn
|
|
effectivePlotArea.height -= 2 * padding.v;
|
|
effectivePlotArea.width -= 2 * padding.h;
|
|
effectivePlotArea.x += padding.h;
|
|
effectivePlotArea.y += padding.v;
|
|
|
|
smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
|
|
copyOfStyle = merge(conf.style, {});
|
|
normalizeFontSizeAppend(this._metaStyle = copyOfStyle);
|
|
|
|
smartLabel.setStyle(copyOfStyle);
|
|
testSmartLabel = smartLabel.getSmartText('W');
|
|
|
|
length = crDataObj.length;
|
|
zerothStop = stop = ((valueRatio[length - 1] - valueRatio[0]) / 2) * effectivePlotArea.width / 100;
|
|
|
|
// first scale Label
|
|
dispValue = crDataObj[0].displayValue;
|
|
smartText = smartLabel.getSmartText((typeof dispValue !== 'string' && dispValue !== undefined) &&
|
|
dispValue.toString() || dispValue, zerothStop, effectivePlotArea.height);
|
|
smartText.x = valueRatio[0] * effectivePlotArea.width / 100;
|
|
leftBound = smartText.x + smartText.width;
|
|
labelHeights.push(smartText.height);
|
|
lsTexts[0] = smartText;
|
|
|
|
//last scale label
|
|
smartText = smartLabel.getSmartText(crDataObj[length - 1].displayValue,
|
|
zerothStop, effectivePlotArea.height);
|
|
smartText.x = valueRatio[length - 1] * effectivePlotArea.width / 100;
|
|
rightBound = smartText.x - smartText.width;
|
|
labelHeights.push(smartText.height);
|
|
lsTexts[length - 1] = smartText;
|
|
|
|
leftStop = leftBound;
|
|
for (index = 1; index < length - 1; index++) {
|
|
smartText = undefined;
|
|
|
|
val = crDataObj[index].displayValue;
|
|
|
|
nextRefPoint = index + 1 === length - 1 ? rightBound : valueRatio[index + 1] *
|
|
effectivePlotArea.width / 100;
|
|
currPoint = valueRatio[index] * effectivePlotArea.width / 100;
|
|
|
|
stop = Math.min(currPoint - leftStop, nextRefPoint - currPoint);
|
|
|
|
if (stop > 1.5 * testSmartLabel.width) {
|
|
smartText = smartLabel.getSmartText(val, 2 * stop, effectivePlotArea.height);
|
|
smartText.x = valueRatio[index] * effectivePlotArea.width / 100;
|
|
leftStop = stop;
|
|
labelHeights.push(smartText.height);
|
|
}
|
|
|
|
lsTexts[index] = smartText;
|
|
}
|
|
|
|
maxHeight = Math.max.apply(Math, labelHeights);
|
|
|
|
effectivePlotArea.height = maxHeight;
|
|
bBox.height = maxHeight + 2 * padding.v;
|
|
|
|
lSpace.node.logicArea = effectivePlotArea;
|
|
lSpace.bound = bBox;
|
|
|
|
return bBox;
|
|
};
|
|
|
|
LegendValues.prototype.draw = function () {
|
|
var conf = this.conf,
|
|
boundStyle = conf.bound && conf.bound.style || {
|
|
stroke: 'none'
|
|
},
|
|
keys,
|
|
pos = {},
|
|
paper,
|
|
layer,
|
|
bound,
|
|
legendValuesGroup,
|
|
componentPool,
|
|
bBox,
|
|
lSpace,
|
|
smartLabel,
|
|
logicArea,
|
|
options,
|
|
cRange,
|
|
valueRatio,
|
|
index,
|
|
length,
|
|
smartTexts,
|
|
smartText,
|
|
instanceFn,
|
|
numberFormatter;
|
|
|
|
|
|
if (arguments.length >= 2) {
|
|
bBox = arguments[0];
|
|
options = arguments[1];
|
|
} else if (arguments.length >= 1){
|
|
options = arguments[0];
|
|
}
|
|
|
|
paper = options.paper;
|
|
layer = options.parentLayer;
|
|
smartLabel = options.smartLabel,
|
|
cRange = options.colorRange;
|
|
numberFormatter = options.numberFormatter,
|
|
valueRatio = cRange.getCumulativeValueRatio();
|
|
componentPool = options.componentPool;
|
|
keys = componentPool.getKeys();
|
|
|
|
this.getLogicalSpace(bBox, options);
|
|
lSpace = this._lSpace;
|
|
logicArea = lSpace.node.logicArea;
|
|
smartTexts = lSpace.node.smartTexts;
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
|
|
legendValuesGroup = instanceFn('legend-values', layer);
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
|
|
this.bound = bound = instanceFn(legendValuesGroup).attr(lSpace.bound).css(boundStyle);
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_TEXT, true);
|
|
for (index = 0, length = valueRatio.length; index < length; index++) {
|
|
smartText = smartTexts[index];
|
|
|
|
if (!smartText) {
|
|
continue;
|
|
}
|
|
|
|
pos.y = logicArea.y + smartText.height / 2;
|
|
|
|
if (index === length - 1) {
|
|
pos.x = logicArea.x + smartText.x - smartText.width / 2;
|
|
} else if (index){
|
|
pos.x = logicArea.x + smartText.x;
|
|
} else {
|
|
pos.x = logicArea.x + smartText.x + smartText.width / 2;
|
|
}
|
|
|
|
instanceFn({}, legendValuesGroup).attr({
|
|
text: smartText.text,
|
|
x: pos.x,
|
|
y: pos.y,
|
|
lineHeight: this._metaStyle.lineHeight,
|
|
fill: conf.style.fill
|
|
});
|
|
|
|
}
|
|
|
|
return {
|
|
group: legendValuesGroup,
|
|
bound: bound
|
|
};
|
|
};
|
|
|
|
|
|
function VerticalLegendValues () {
|
|
LegendValues.apply(this, arguments);
|
|
this._id = 'GL_VALUES';
|
|
}
|
|
|
|
VerticalLegendValues.prototype = Object.create(LegendValues.prototype);
|
|
VerticalLegendValues.prototype.constructor = VerticalLegendValues;
|
|
|
|
VerticalLegendValues.prototype.getLogicalSpace = function (bBox, options, recalculate) {
|
|
var lSpace = this._lSpace,
|
|
conf = this.conf,
|
|
padding = conf.padding,
|
|
componentPool = options.componentPool,
|
|
chart = componentPool.getChart(),
|
|
cRange,
|
|
smartLabel,
|
|
crDataObj,
|
|
smartText,
|
|
index,
|
|
length,
|
|
valueRatio,
|
|
stop,
|
|
nextRefPoint,
|
|
currPoint,
|
|
effectivePlotArea,
|
|
zerothStop,
|
|
labelWidths = [],
|
|
topBound,
|
|
topStop,
|
|
maxWidth,
|
|
bottomBound,
|
|
val,
|
|
copyOfStyle,
|
|
testSmartLabel,
|
|
lsTexts;
|
|
|
|
if (lSpace && !recalculate) {
|
|
lSpace.isImpure = true;
|
|
// If logical space has already been calculated and recalculate flag is on, return without recalculating.
|
|
return lSpace;
|
|
}
|
|
|
|
cRange = options.colorRange;
|
|
smartLabel = options.smartLabel;
|
|
crDataObj = cRange.colorRange;
|
|
valueRatio = cRange.getCumulativeValueRatio();
|
|
|
|
lSpace = this._lSpace = {
|
|
bound: {
|
|
height: 0,
|
|
width: 0
|
|
},
|
|
|
|
node: {
|
|
logicArea: undefined,
|
|
smartTexts: []
|
|
}
|
|
};
|
|
|
|
lsTexts = lSpace.node.smartTexts;
|
|
effectivePlotArea = merge(bBox, {});
|
|
|
|
// The logical rect inside which the composition are drawn
|
|
effectivePlotArea.height -= 2 * padding.v;
|
|
effectivePlotArea.width -= 2 * padding.h;
|
|
effectivePlotArea.x += padding.h;
|
|
effectivePlotArea.y += padding.v;
|
|
|
|
smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
|
|
copyOfStyle = merge(conf.style, {});
|
|
normalizeFontSizeAppend(copyOfStyle);
|
|
|
|
smartLabel.setStyle(this._metaStyle = copyOfStyle);
|
|
testSmartLabel = smartLabel.getSmartText('W');
|
|
|
|
length = crDataObj.length;
|
|
zerothStop = stop = ((valueRatio[length - 1] - valueRatio[0]) / 2) * effectivePlotArea.height / 100;
|
|
|
|
// first scale Label
|
|
smartText = smartLabel.getSmartText(crDataObj[0].displayValue,
|
|
effectivePlotArea.width, zerothStop);
|
|
smartText.y = valueRatio[0] * effectivePlotArea.height / 100;
|
|
topBound = smartText.y + smartText.width;
|
|
labelWidths.push(smartText.width);
|
|
lsTexts[0] = smartText;
|
|
|
|
//last scale label
|
|
smartText = smartLabel.getSmartText(crDataObj[length - 1].displayValue,
|
|
effectivePlotArea.width, zerothStop);
|
|
smartText.y = valueRatio[length - 1] * effectivePlotArea.height / 100;
|
|
bottomBound = smartText.y - smartText.height;
|
|
labelWidths.push(smartText.width);
|
|
lsTexts[length - 1] = smartText;
|
|
|
|
topStop = topBound;
|
|
for (index = 1; index < length - 1; index++) {
|
|
smartText = undefined;
|
|
|
|
val = crDataObj[index].displayValue;
|
|
|
|
nextRefPoint = index + 1 === length - 1 ? bottomBound : valueRatio[index + 1] *
|
|
effectivePlotArea.height / 100;
|
|
currPoint = valueRatio[index] * effectivePlotArea.height / 100;
|
|
|
|
stop = Math.min(currPoint - topStop, nextRefPoint - currPoint);
|
|
|
|
if (stop > 2 * testSmartLabel.height) {
|
|
smartText = smartLabel.getSmartText(val, effectivePlotArea.width, 2 * stop);
|
|
smartText.y = valueRatio[index] * effectivePlotArea.height / 100;
|
|
|
|
topStop = stop;
|
|
labelWidths.push(smartText.width);
|
|
}
|
|
|
|
lsTexts[index] = smartText;
|
|
}
|
|
|
|
maxWidth = Math.max.apply(Math, labelWidths);
|
|
|
|
effectivePlotArea.width = maxWidth;
|
|
bBox.width = maxWidth + 2 * padding.h;
|
|
|
|
lSpace.node.logicArea = effectivePlotArea;
|
|
lSpace.bound = bBox;
|
|
|
|
return bBox;
|
|
};
|
|
|
|
VerticalLegendValues.prototype.draw = function () {
|
|
var paper,
|
|
layer,
|
|
bound,
|
|
conf = this.conf,
|
|
boundStyle = conf.bound && conf.bound.style || {
|
|
stroke: 'none'
|
|
},
|
|
legendValuesGroup,
|
|
bBox,
|
|
lSpace,
|
|
smartLabel,
|
|
logicArea,
|
|
options,
|
|
cRange,
|
|
valueRatio,
|
|
smartTexts,
|
|
smartText,
|
|
index,
|
|
length,
|
|
pos = {},
|
|
componentPool,
|
|
instanceFn,
|
|
keys;
|
|
|
|
|
|
if (arguments.length >= 2) {
|
|
bBox = arguments[0];
|
|
options = arguments[1];
|
|
} else if (arguments.length >= 1){
|
|
options = arguments[0];
|
|
}
|
|
|
|
paper = options.paper;
|
|
layer = options.parentLayer;
|
|
smartLabel = options.smartLabel,
|
|
cRange = options.colorRange;
|
|
valueRatio = cRange.getCumulativeValueRatio();
|
|
componentPool = options.componentPool;
|
|
keys = componentPool.getKeys();
|
|
|
|
this.getLogicalSpace(bBox, options);
|
|
lSpace = this._lSpace;
|
|
logicArea = lSpace.node.logicArea;
|
|
smartTexts = lSpace.node.smartTexts;
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
|
|
legendValuesGroup = instanceFn('legend-values', layer);
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT);
|
|
this.bound = bound = instanceFn(legendValuesGroup).attr(lSpace.bound).css(boundStyle);
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_TEXT, true);
|
|
for (index = 0, length = valueRatio.length; index < length; index++) {
|
|
smartText = smartTexts[index];
|
|
|
|
if (!smartText) {
|
|
continue;
|
|
}
|
|
|
|
pos.x = logicArea.x + smartText.width / 2;
|
|
|
|
if (index === length - 1) {
|
|
pos.y = logicArea.y + smartText.y - smartText.height / 2;
|
|
} else if (index){
|
|
pos.y = logicArea.y + smartText.y;
|
|
} else {
|
|
pos.y = logicArea.y + smartText.y + smartText.height / 2;
|
|
}
|
|
|
|
instanceFn({ }, legendValuesGroup).attr({
|
|
text: smartText.text,
|
|
x: pos.x,
|
|
y: pos.y,
|
|
lineHeight: this._metaStyle.lineHeight,
|
|
fill: conf.style.fill
|
|
});
|
|
|
|
}
|
|
|
|
return {
|
|
group: legendValuesGroup,
|
|
bound: bound
|
|
};
|
|
};
|
|
|
|
function LegendAxis (conf) {
|
|
this.conf = conf;
|
|
this._id = 'FL_AXIS';
|
|
|
|
this.node = undefined;
|
|
this.shadow = undefined;
|
|
this.markerLine = undefined;
|
|
this.compositionsByCategory = {};
|
|
}
|
|
|
|
LegendAxis.prototype.constructor = LegendAxis;
|
|
|
|
LegendAxis.prototype.addCompositions = function (instance, category) {
|
|
this.compositionsByCategory[category] = instance;
|
|
};
|
|
|
|
LegendAxis.prototype.getLogicalSpace = function (bBox, options, recalculate) {
|
|
var lSpace = this._lSpace,
|
|
conf = this.conf,
|
|
padding = conf.padding,
|
|
heightTakenLower,
|
|
heightTakenUpper,
|
|
heightTaken,
|
|
axisThickness = conf.legendAxisHeight,
|
|
compositionsByCategory = this.compositionsByCategory,
|
|
sliderG,
|
|
effectivePlotArea,
|
|
slider,
|
|
sliderSpace,
|
|
sliderExtraDiam = 0;
|
|
|
|
if (lSpace && !recalculate) {
|
|
lSpace.isImpure = true;
|
|
// If logical space has already been calculated and recalculate flag is on, return without recalculating.
|
|
return lSpace;
|
|
}
|
|
|
|
lSpace = this._lSpace = {
|
|
bound: {
|
|
height: 0,
|
|
width: 0
|
|
},
|
|
|
|
node: {
|
|
logicArea: undefined
|
|
}
|
|
};
|
|
|
|
effectivePlotArea = merge(bBox, {});
|
|
|
|
// The logical rect inside which the composition are drawn
|
|
effectivePlotArea.height -= 2 * padding.v;
|
|
effectivePlotArea.width -= 2 * padding.h;
|
|
effectivePlotArea.x += padding.h;
|
|
effectivePlotArea.y += padding.v;
|
|
|
|
heightTakenLower = (axisThickness / 2) + conf.line.offset;
|
|
heightTakenUpper = axisThickness / 2;
|
|
|
|
sliderG = compositionsByCategory[compositionKeys.RANGE];
|
|
if (sliderG) {
|
|
slider = sliderG.sliders[false];
|
|
sliderSpace = slider.conf.outerCircle.rFactor * axisThickness;
|
|
heightTakenUpper += sliderExtraDiam = Math.max(sliderSpace / 2 - axisThickness / 2, 0);
|
|
}
|
|
|
|
// @todo Change the height and width of bBox
|
|
effectivePlotArea.y += sliderExtraDiam;
|
|
effectivePlotArea.height = heightTaken = heightTakenUpper + heightTakenLower + sliderExtraDiam;
|
|
bBox.height = heightTaken + 2 * padding.v;
|
|
|
|
lSpace.node.logicArea = effectivePlotArea;
|
|
lSpace.bound = bBox;
|
|
|
|
return bBox;
|
|
};
|
|
|
|
LegendAxis.prototype.getDrawableAxisArea = function (parentBoundingRect) {
|
|
var conf = this.conf,
|
|
x = parentBoundingRect.x,
|
|
y = parentBoundingRect.y,
|
|
width = parentBoundingRect.width,
|
|
height = conf.legendAxisHeight,
|
|
r = conf.legendAxisHeight / 2;
|
|
|
|
return {
|
|
x: x,
|
|
y: y,
|
|
width: width,
|
|
height: height,
|
|
r: r
|
|
};
|
|
};
|
|
|
|
LegendAxis.prototype.preDrawingRangeParam = function (drawableArea) {
|
|
var y = drawableArea.y + (drawableArea.height / 2),
|
|
calculationBase = drawableArea.height;
|
|
|
|
return {
|
|
y: y,
|
|
calculationBase: calculationBase,
|
|
rangeStart: drawableArea.x,
|
|
rangeEnd: drawableArea.x + drawableArea.width,
|
|
prop: 'y'
|
|
};
|
|
};
|
|
|
|
LegendAxis.prototype.getScaleMarkerPathStr = function (oriAxisRect, valueRatio) {
|
|
var axisRect = merge(oriAxisRect, {}),
|
|
conf = this.conf,
|
|
lineAttr = conf.line,
|
|
index,
|
|
length,
|
|
ratio,
|
|
covered,
|
|
markerStartY,
|
|
tickStr = '',
|
|
lineStr = '';
|
|
|
|
axisRect.x += axisRect.r;
|
|
axisRect.width -= 2 * axisRect.r;
|
|
markerStartY = axisRect.y + axisRect.height;
|
|
|
|
for (index = 0, length = valueRatio.length; index < length; index++) {
|
|
ratio = valueRatio[index];
|
|
covered = axisRect.x + (ratio * axisRect.width / 100);
|
|
|
|
tickStr += M + (covered) + COMMA_STR + (markerStartY - lineAttr.grooveLength) +
|
|
L + (covered) + COMMA_STR + (markerStartY + lineAttr.offset);
|
|
}
|
|
|
|
lineStr += M + (axisRect.x) + COMMA_STR + (markerStartY + lineAttr.offset) +
|
|
L + (axisRect.x + axisRect.width) + COMMA_STR + (markerStartY + lineAttr.offset);
|
|
|
|
return tickStr + lineStr;
|
|
};
|
|
|
|
LegendAxis.prototype.getColorGradient = function (colorRange) {
|
|
return {
|
|
axis: colorRange.getBoxFill(),
|
|
shadow: toRaphaelColor({
|
|
FCcolor: {
|
|
alpha : '25,0,0',
|
|
angle : 90,
|
|
color : '000000,FFFFFF,FFFFFF',
|
|
ratio : '0,30,40'
|
|
}
|
|
})
|
|
};
|
|
};
|
|
|
|
LegendAxis.prototype.draw = function () {
|
|
var paper,
|
|
layer,
|
|
bound,
|
|
conf = this.conf,
|
|
boundAttr = conf.bound || {},
|
|
lineAttr = conf.line,
|
|
boundStyle = boundAttr.style || {},
|
|
node,
|
|
bBox,
|
|
category,
|
|
compositionsByCategory = this.compositionsByCategory,
|
|
cRange,
|
|
valueRatio,
|
|
composition,
|
|
compositionMes,
|
|
legendAxisGroup,
|
|
rangeParams,
|
|
grad,
|
|
oriAxisRect,
|
|
lSpace,
|
|
options,
|
|
instanceFn,
|
|
keys,
|
|
componentPool,
|
|
scaleLine;
|
|
|
|
|
|
if (arguments.length >= 2) {
|
|
bBox = arguments[0];
|
|
options = arguments[1];
|
|
} else if (arguments.length >= 1){
|
|
options = arguments[0];
|
|
}
|
|
|
|
paper = options.paper;
|
|
layer = options.parentLayer;
|
|
cRange = options.colorRange;
|
|
valueRatio = cRange.getCumulativeValueRatio();
|
|
componentPool = options.componentPool;
|
|
keys = componentPool.getKeys();
|
|
|
|
|
|
this.getLogicalSpace(bBox, options);
|
|
lSpace = this._lSpace;
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
|
|
legendAxisGroup = instanceFn('legend-axis', layer);
|
|
//legendAxisGroup = paper.group('legend-axis', layer);
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_RECT, true);
|
|
|
|
this.bound = bound = instanceFn(legendAxisGroup).attr(lSpace.bound).css(boundStyle);
|
|
//bound = this.bound = paper.rect(lSpace.bound, legendAxisGroup).css(boundStyle);
|
|
|
|
oriAxisRect = this.getDrawableAxisArea(lSpace.node.logicArea);
|
|
grad = this.getColorGradient(cRange);
|
|
conf.style.fill = grad.axis;
|
|
conf.shadow.style.fill = grad.shadow;
|
|
|
|
// node = this.node = paper.rect(oriAxisRect, legendAxisGroup).css(conf.style);
|
|
// this.shadow = paper.rect(oriAxisRect, legendAxisGroup).css(conf.shadow.style);
|
|
node = this.node = instanceFn(legendAxisGroup).attr(oriAxisRect).css(conf.style);
|
|
this.shadow = instanceFn(legendAxisGroup).attr(oriAxisRect).css(conf.shadow.style);
|
|
|
|
scaleLine = this.getScaleMarkerPathStr(oriAxisRect, valueRatio);
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_PATH);
|
|
instanceFn('M0,0', legendAxisGroup)
|
|
.attr({ path: scaleLine }).css(lineAttr.style);
|
|
|
|
for (category in compositionsByCategory) {
|
|
composition = compositionsByCategory[category];
|
|
|
|
switch (category) {
|
|
case compositionKeys.RANGE:
|
|
rangeParams = this.preDrawingRangeParam(oriAxisRect);
|
|
|
|
options[rangeParams.prop] = rangeParams[rangeParams.prop];
|
|
options.key = rangeParams.prop;
|
|
options.rCalcBase = rangeParams.calculationBase;
|
|
options.parentLayer = legendAxisGroup;
|
|
|
|
compositionMes = composition.draw(rangeParams.rangeStart,rangeParams.rangeEnd, options);
|
|
}
|
|
}
|
|
};
|
|
|
|
function VerticalLegendAxis () {
|
|
LegendAxis.apply(this, arguments);
|
|
}
|
|
|
|
VerticalLegendAxis.prototype = Object.create(LegendAxis.prototype);
|
|
VerticalLegendAxis.prototype.constructor = VerticalLegendAxis;
|
|
|
|
VerticalLegendAxis.prototype.getLogicalSpace = function (bBox, options, recalculate) {
|
|
var lSpace = this._lSpace,
|
|
conf = this.conf,
|
|
padding = conf.padding,
|
|
widthTakenLower,
|
|
widthTakenUpper,
|
|
widthTaken,
|
|
axisThickness = conf.legendAxisHeight,
|
|
compositionsByCategory = this.compositionsByCategory,
|
|
sliderG,
|
|
slider,
|
|
effectivePlotArea,
|
|
sliderSpace,
|
|
sliderExtraDiam = 0;
|
|
|
|
if (lSpace && !recalculate) {
|
|
lSpace.isImpure = true;
|
|
// If logical space has already been calculated and recalculate flag is on, return without recalculating.
|
|
return lSpace;
|
|
}
|
|
|
|
lSpace = this._lSpace = {
|
|
bound: {
|
|
height: 0,
|
|
width: 0
|
|
},
|
|
|
|
node: {
|
|
logicArea: undefined
|
|
}
|
|
};
|
|
|
|
effectivePlotArea = merge(bBox, {});
|
|
|
|
// The logical rect inside which the composition are drawn
|
|
effectivePlotArea.height -= 2 * padding.v;
|
|
effectivePlotArea.width -= 2 * padding.h;
|
|
effectivePlotArea.x += padding.h;
|
|
effectivePlotArea.y += padding.v;
|
|
|
|
widthTakenLower = (axisThickness / 2) + conf.line.offset;
|
|
widthTakenUpper = axisThickness / 2;
|
|
|
|
sliderG = compositionsByCategory[compositionKeys.RANGE];
|
|
if (sliderG) {
|
|
slider = sliderG.sliders[false];
|
|
sliderSpace = slider.conf.outerCircle.rFactor * axisThickness;
|
|
widthTakenUpper += sliderExtraDiam = Math.max(sliderSpace / 2 - axisThickness / 2, 0);
|
|
}
|
|
|
|
effectivePlotArea.x += sliderExtraDiam;
|
|
effectivePlotArea.width = widthTaken = widthTakenUpper + widthTakenLower + sliderExtraDiam;
|
|
bBox.width = widthTaken + 2 * padding.v;
|
|
|
|
lSpace.node.logicArea = effectivePlotArea;
|
|
lSpace.bound = bBox;
|
|
|
|
return bBox;
|
|
};
|
|
|
|
VerticalLegendAxis.prototype.getDrawableAxisArea = function (parentBoundingRect) {
|
|
var conf = this.conf;
|
|
|
|
return {
|
|
x: parentBoundingRect.x,
|
|
y: parentBoundingRect.y,
|
|
width: conf.legendAxisHeight,
|
|
height: parentBoundingRect.height,
|
|
r: conf.legendAxisHeight / 2
|
|
};
|
|
};
|
|
|
|
VerticalLegendAxis.prototype.getScaleMarkerPathStr = function (oriAxisRect, valueRatio) {
|
|
var axisRect = merge(oriAxisRect, {}),
|
|
conf = this.conf,
|
|
lineAttr = conf.line,
|
|
index,
|
|
ratio,
|
|
length,
|
|
markerStartX,
|
|
covered,
|
|
tickStr = '',
|
|
lineStr = '';
|
|
|
|
axisRect.y += axisRect.r;
|
|
axisRect.height -= 2 * axisRect.r;
|
|
markerStartX = axisRect.x + axisRect.width;
|
|
|
|
for (index = 0, length = valueRatio.length; index < length; index++) {
|
|
ratio = valueRatio[index];
|
|
covered = axisRect.y + (ratio * axisRect.height / 100);
|
|
|
|
tickStr += M + (markerStartX - lineAttr.grooveLength) + COMMA_STR + (covered) +
|
|
L + (markerStartX + lineAttr.offset) + COMMA_STR + (covered);
|
|
}
|
|
|
|
lineStr += M + (markerStartX + lineAttr.offset) + COMMA_STR + (axisRect.y) +
|
|
L + (markerStartX + lineAttr.offset) + COMMA_STR + (axisRect.y + axisRect.height);
|
|
|
|
return tickStr + lineStr;
|
|
};
|
|
|
|
VerticalLegendAxis.prototype.getColorGradient = function (colorRange) {
|
|
return {
|
|
axis: colorRange.getBoxFill(true),
|
|
shadow: toRaphaelColor({
|
|
FCcolor: {
|
|
alpha : '25,0,0',
|
|
angle : 360,
|
|
color : '000000,FFFFFF,FFFFFF',
|
|
ratio : '0,30,40'
|
|
}
|
|
})
|
|
};
|
|
};
|
|
|
|
VerticalLegendAxis.prototype.preDrawingRangeParam = function (drawableArea) {
|
|
var x = drawableArea.x + (drawableArea.width / 2),
|
|
calculationBase = drawableArea.width;
|
|
|
|
return {
|
|
x: x,
|
|
calculationBase: calculationBase,
|
|
rangeStart: drawableArea.y,
|
|
rangeEnd: drawableArea.y + drawableArea.height,
|
|
prop: 'x'
|
|
};
|
|
};
|
|
|
|
function SliderGroup (conf) {
|
|
var sliderConf = conf,
|
|
options = {};
|
|
|
|
this._id = 'GL_SG1';
|
|
this.conf = conf;
|
|
|
|
options.conf = sliderConf;
|
|
|
|
this.extremes = [];
|
|
this.sliders = {};
|
|
|
|
options.sliderGroup = this;
|
|
this.valueRange = [];
|
|
this.callbacks = [];
|
|
|
|
this.sliders[FORMER_SLIDER_INDEX] = new Slider(FORMER_SLIDER_INDEX, options, this._id +
|
|
'_' + (+FORMER_SLIDER_INDEX));
|
|
this.sliders[LATER_SLIDER_INDEX] = new Slider(LATER_SLIDER_INDEX, options, this._id +
|
|
'_' + (+LATER_SLIDER_INDEX));
|
|
}
|
|
|
|
SliderGroup.prototype.constructor = SliderGroup;
|
|
|
|
|
|
SliderGroup.prototype.initRange = function (slider, updatedRange) {
|
|
var sliderIndex = slider.sliderIndex;
|
|
|
|
this.extremes[+sliderIndex] = updatedRange;
|
|
};
|
|
|
|
SliderGroup.prototype.updateRange = function (slider, updatedRange) {
|
|
var sliderIndex = slider.sliderIndex,
|
|
sliders = this.sliders,
|
|
s = sliders[!sliderIndex];
|
|
|
|
s.updateSwingRange(sliderIndex, updatedRange);
|
|
};
|
|
|
|
SliderGroup.prototype.reset = function () {
|
|
var options = {};
|
|
|
|
options.conf = this.conf;
|
|
options.sliderGroup = this;
|
|
|
|
// @todo do it from a more generalized way
|
|
this.sliders[FORMER_SLIDER_INDEX] = new Slider(FORMER_SLIDER_INDEX, options, this._id +
|
|
'_' + (+FORMER_SLIDER_INDEX));
|
|
this.sliders[LATER_SLIDER_INDEX] = new Slider(LATER_SLIDER_INDEX, options, this._id +
|
|
'_' + (+LATER_SLIDER_INDEX));
|
|
|
|
this.draw.apply(this, this._drawParams);
|
|
};
|
|
|
|
SliderGroup.prototype.clearListeners = function () {
|
|
this.callbacks.length = 0;
|
|
};
|
|
|
|
SliderGroup.prototype.draw = function (rangeStart, rangeEnd, options) {
|
|
var sliders = this.sliders,
|
|
lSlider = sliders[FORMER_SLIDER_INDEX],
|
|
rSlider = sliders[LATER_SLIDER_INDEX],
|
|
cRange = options.colorRange,
|
|
colorRange = cRange.colorRange,
|
|
componentPool = options.componentPool,
|
|
chart = this._fcChart = componentPool.getChart(),
|
|
oneSliderMes;
|
|
|
|
this.getValueFormPixel = function (valueStart, valueEnd, pixelStart, pixelEnd) {
|
|
var unit = (valueEnd - valueStart) / (pixelEnd - pixelStart);
|
|
|
|
this.getValueFormPixel = function (pixel) {
|
|
return valueStart + (unit * pixel);
|
|
};
|
|
};
|
|
|
|
this.updateWhenInMove = function (numberFormatter, mapByPercent) {
|
|
this.updateWhenInMove = function (slider, val) {
|
|
var extremes = this.extremes,
|
|
sliderIndex = slider.sliderIndex,
|
|
nVal,
|
|
value;
|
|
|
|
if (sliderIndex) {
|
|
nVal = extremes[1] - extremes[0] + val;
|
|
} else {
|
|
nVal = val;
|
|
}
|
|
|
|
value = this.getValueFormPixel(nVal);
|
|
|
|
if (!mapByPercent) {
|
|
value = numberFormatter.legendValue(value);
|
|
} else {
|
|
value = parseFloat(value).toFixed(2) + PERCENT_STR;
|
|
}
|
|
|
|
return value;
|
|
};
|
|
};
|
|
|
|
this._drawParams = [rangeStart, rangeEnd, options];
|
|
this.updateWhenInMove(chart.components.numberFormatter, cRange.mapByPercent);
|
|
|
|
oneSliderMes = lSlider.draw(rangeStart, colorRange[0].displayValue, options[options.key], options);
|
|
oneSliderMes = rSlider.draw(rangeEnd, colorRange[colorRange.length - 1].displayValue, options[options.key],
|
|
options);
|
|
|
|
lSlider.swing = this.extremes.slice(0);
|
|
rSlider.swing = this.extremes.slice(0);
|
|
|
|
this.getValueFormPixel(colorRange[0].value, colorRange[colorRange.length - 1].value,
|
|
this.extremes[0], this.extremes[1]);
|
|
|
|
return oneSliderMes;
|
|
};
|
|
|
|
SliderGroup.prototype.registerListener = function (fn, context, params) {
|
|
this.callbacks.push({
|
|
fn: fn,
|
|
context: context,
|
|
params: params || []
|
|
});
|
|
};
|
|
|
|
SliderGroup.prototype.updateWhenInRest = function (slider, val) {
|
|
var sliders = this.sliders,
|
|
extremes = this.extremes,
|
|
sliderIndex = slider.sliderIndex,
|
|
lValue,
|
|
rValue,
|
|
cIndex,
|
|
cLength,
|
|
callbacks = this.callbacks,
|
|
cb,
|
|
params;
|
|
|
|
if (sliderIndex) {
|
|
lValue = sliders[!sliderIndex].currPos;
|
|
rValue = extremes[1] - extremes[0] + val;
|
|
} else {
|
|
lValue = val;
|
|
rValue = extremes[1] - extremes[0] + sliders[!sliderIndex].currPos;
|
|
}
|
|
|
|
for (cIndex = 0, cLength = callbacks.length; cIndex < cLength; cIndex++) {
|
|
cb = callbacks[cIndex];
|
|
params = cb.params.slice(0);
|
|
params.unshift(this.getValueFormPixel(rValue));
|
|
params.unshift(this.getValueFormPixel(lValue));
|
|
cb.fn.apply(cb.context, params);
|
|
}
|
|
};
|
|
|
|
SliderGroup.prototype.dragStarted = function (self) {
|
|
var sliders = this.sliders,
|
|
extremes = this.extremes,
|
|
conf = self.conf,
|
|
chart = this._fcChart;
|
|
|
|
global.raiseEvent ('legendpointerdragstart', {
|
|
pointerIndex: +self.sliderIndex,
|
|
pointers: [{
|
|
value: this.getValueFormPixel(sliders[false].currPos)
|
|
}, {
|
|
value: this.getValueFormPixel(extremes[1] - extremes[0] + sliders[true].currPos)
|
|
}],
|
|
legendPointerHeight: conf.outerRadius,
|
|
legendPointerWidth: conf.innerRadius,
|
|
outerRadius: conf.outerRadius,
|
|
innerRadius: conf.innerRadius
|
|
}, chart.chartInstance, [chart.id]);
|
|
};
|
|
|
|
|
|
SliderGroup.prototype.dragCompleted = function (self, isDragged, newVal) {
|
|
var sliders = this.sliders,
|
|
extremes = this.extremes,
|
|
conf = self.conf,
|
|
minValue = this.getValueFormPixel(sliders[false].currPos),
|
|
maxValue = this.getValueFormPixel(extremes[1] - extremes[0] + sliders[true].currPos),
|
|
chart = this._fcChart,
|
|
newMinValue,
|
|
newMaxValue;
|
|
|
|
if (!self.sliderIndex) {
|
|
newMinValue = this.getValueFormPixel(newVal);
|
|
newMaxValue = maxValue;
|
|
} else {
|
|
newMinValue = minValue;
|
|
newMaxValue = this.getValueFormPixel(extremes[1] - extremes[0] + newVal);
|
|
}
|
|
|
|
if (isDragged) {
|
|
global.raiseEvent ('legendrangeupdated', {
|
|
previousMinValue: minValue,
|
|
previousMaxValue: maxValue,
|
|
minValue: newMinValue,
|
|
maxValue: newMaxValue
|
|
}, chart.chartInstance, [chart.id]);
|
|
}
|
|
|
|
global.raiseEvent ('legendpointerdragstop', {
|
|
pointerIndex: +self.sliderIndex,
|
|
pointers: [{
|
|
value: minValue
|
|
}, {
|
|
value: maxValue
|
|
}],
|
|
legendPointerHeight: conf.outerRadius,
|
|
legendPointerWidth: conf.innerRadius,
|
|
outerRadius: conf.outerRadius,
|
|
innerRadius: conf.innerRadius
|
|
}, chart.chartInstance, [chart.id]);
|
|
};
|
|
|
|
function Slider (sliderIndex, options, id) {
|
|
this.conf = options.conf;
|
|
this.sliderIndex = sliderIndex;
|
|
this.rangeGroup = options.sliderGroup;
|
|
this._id = id;
|
|
|
|
this.node = undefined;
|
|
this.tracker = undefined;
|
|
this.currPos = 0;
|
|
this.swing = [];
|
|
}
|
|
|
|
Slider.prototype.constructor = Slider;
|
|
|
|
Slider.prototype.updateSwingRange = function (index, value) {
|
|
this.swing[+index] = value;
|
|
};
|
|
|
|
// @todo: Who should be responsible for reset, range or individual slider
|
|
// Slider.prototype.reset = function () {
|
|
// var node = this.node,
|
|
// tracker = this.tracker,
|
|
// conf = this.conf,
|
|
// dragAPI;
|
|
|
|
// if (!node) {
|
|
// return;
|
|
// }
|
|
|
|
// node.attr({
|
|
// transform: 't0,0'
|
|
// });
|
|
|
|
// this.currPos = 0;
|
|
// this.swing = [];
|
|
|
|
// };
|
|
|
|
Slider.prototype.draw = function (rangeStart, scaleVal, position, options) {
|
|
var layer = options.parentLayer,
|
|
conf = this.conf,
|
|
ocConf = conf.outerCircle,
|
|
icConf = conf.innerCircle,
|
|
ocRadius = Math.ceil((ocConf.rFactor * options.rCalcBase ) / 2),
|
|
icRadius = Math.ceil((icConf.rFactor * options.rCalcBase ) / 2),
|
|
icThickness = ocRadius - icRadius,
|
|
group,
|
|
rangeGroup = this.rangeGroup,
|
|
sliderIndex = this.sliderIndex,
|
|
dragAPI,
|
|
strokeWidthOffset,
|
|
x,
|
|
y,
|
|
tracker,
|
|
instanceFn,
|
|
iniRange,
|
|
componentPool = options.componentPool,
|
|
keys = componentPool.getKeys();
|
|
|
|
conf.outerRadius = ocRadius;
|
|
conf.innerRadius = icRadius;
|
|
|
|
this._scaleVal = scaleVal;
|
|
|
|
icConf.style['stroke-width'] = icThickness;
|
|
strokeWidthOffset = Math.ceil(ocConf.style['stroke-width'] / 2);
|
|
icRadius += strokeWidthOffset;
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_GROUP);
|
|
group = this.node = instanceFn('fc-gl-slider', layer).attr({
|
|
'cursor' : 'pointer',
|
|
'transform': 't0,0'
|
|
});
|
|
|
|
|
|
if (options.key === 'x') {
|
|
x = position;
|
|
y = rangeStart;
|
|
y += sliderIndex ? -(icRadius) : +icRadius;
|
|
iniRange = y;
|
|
} else {
|
|
x = rangeStart;
|
|
y = position;
|
|
x += sliderIndex ? -(icRadius) : +icRadius;
|
|
iniRange = x;
|
|
}
|
|
|
|
rangeGroup.initRange(this, iniRange);
|
|
|
|
instanceFn = componentPool.getComponent(this._id, keys.KEY_CIRCLE, true);
|
|
instanceFn(group).attr({
|
|
cx: x,
|
|
cy: y,
|
|
r: ocRadius
|
|
}).css(ocConf.style);
|
|
instanceFn(group).attr({
|
|
cx: x,
|
|
cy: y,
|
|
r: icRadius
|
|
}).css(icConf.style);
|
|
|
|
tracker = this.tracker = instanceFn(group).attr({
|
|
cx: x,
|
|
cy: y,
|
|
r: ocRadius + 5,
|
|
ishot: true,
|
|
fill: TRACKER_FILL,
|
|
stroke: 0,
|
|
cursor: 'pointer'
|
|
}).trackTooltip(conf.showTooltip ? true : false).tooltip(scaleVal, null, null, true);
|
|
|
|
this._dragAPI = dragAPI = this.getDragAPI(options.key === 'x');
|
|
|
|
tracker.undrag();
|
|
tracker.drag(dragAPI.dragging, dragAPI.dragStart, dragAPI.dragEnd);
|
|
|
|
return {
|
|
translateAscending: ocRadius + strokeWidthOffset
|
|
};
|
|
};
|
|
|
|
Slider.prototype.getDragAPI = function (verticalDragging) {
|
|
var self = this,
|
|
node = self.node,
|
|
index = self.sliderIndex,
|
|
range = self.rangeGroup,
|
|
swing,
|
|
lastDisplacement,
|
|
timeoutId,
|
|
innerRadius = self.conf.innerRadius,
|
|
spaceSaved = innerRadius,
|
|
isDragged;
|
|
|
|
return {
|
|
dragging : function () {
|
|
var left,
|
|
right,
|
|
d,
|
|
event;
|
|
|
|
event = arguments[4];
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
|
|
if (verticalDragging) {
|
|
d = arguments[1];
|
|
} else {
|
|
d = arguments[0];
|
|
}
|
|
|
|
if (index) {
|
|
left = swing[0] - swing[1] + spaceSaved;
|
|
right = 0;
|
|
} else {
|
|
left = 0;
|
|
right = swing[1] - swing[0] - spaceSaved;
|
|
}
|
|
|
|
if ((self.currPos + d) < left || (self.currPos + d) > right) {
|
|
return;
|
|
}
|
|
|
|
node.attr({
|
|
transform : verticalDragging ? 't0,' + (self.currPos + d) :
|
|
't' + (self.currPos + d) + ',' + 0
|
|
});
|
|
|
|
lastDisplacement = d;
|
|
|
|
timeoutId && clearTimeout(timeoutId);
|
|
timeoutId = setTimeout(function () {
|
|
range.updateWhenInRest(self, self.currPos + d);
|
|
}, 100);
|
|
|
|
self.tracker.tooltip(range.updateWhenInMove(self, self.currPos + d), null, null, true);
|
|
isDragged = true;
|
|
|
|
return true;
|
|
},
|
|
|
|
dragStart : function (x, y, event) {
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
|
|
node.attr({
|
|
transform : verticalDragging ? 't0,' + self.currPos :
|
|
't' + self.currPos + ',' + 0
|
|
});
|
|
|
|
swing = swing || self.swing;
|
|
|
|
isDragged = false;
|
|
|
|
range.dragStarted(self);
|
|
},
|
|
|
|
dragEnd : function () {
|
|
var newPos;
|
|
range.dragCompleted(self, isDragged, self.currPos + lastDisplacement);
|
|
|
|
if (!isDragged) {
|
|
return;
|
|
}
|
|
|
|
timeoutId && clearTimeout(timeoutId);
|
|
timeoutId = setTimeout(function () {
|
|
range.updateWhenInRest(self, self.currPos);
|
|
}, 100);
|
|
|
|
self.currPos += lastDisplacement;
|
|
newPos = swing[+index] + self.currPos;
|
|
range.updateRange(self, newPos);
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
function ColorRange (data, options, chart) {
|
|
var numberFormatter = chart.components.numberFormatter,
|
|
index,
|
|
length,
|
|
range,
|
|
min,
|
|
max,
|
|
minRange,
|
|
maxRange,
|
|
minValue,
|
|
maxValue,
|
|
mapByPercent;
|
|
|
|
this.data = data;
|
|
this.options = options || {};
|
|
mapByPercent = this.mapByPercent = !!data.mapByPercent;
|
|
this.appender = '';
|
|
|
|
min = this.mapByPercent ? 0 : options.min;
|
|
max = this.mapByPercent ? 100 : options.max;
|
|
|
|
if (data.colorRange.length === 2) {
|
|
minRange = data.colorRange[0];
|
|
maxRange = data.colorRange[1];
|
|
|
|
minValue = minRange.value = isInvalid(minRange.value) ? min : minRange.value;
|
|
maxValue = maxRange.value = isInvalid(maxRange.value) ? max : maxRange.value;
|
|
|
|
if (minValue === maxValue) {
|
|
minValue = minRange.value = min;
|
|
maxValue = maxRange.value = max;
|
|
}
|
|
|
|
minRange.displayValue = mapByPercent ? minValue + PERCENT_STR : numberFormatter.legendValue(minValue);
|
|
maxRange.displayValue = mapByPercent ? maxValue + PERCENT_STR : numberFormatter.legendValue(maxValue);
|
|
}
|
|
|
|
if ((isInvalid(min) && isInvalid(minRange.value)) || (isInvalid(max) && isInvalid(minRange.value)) ||
|
|
!data.gradient) {
|
|
this._preparationGoneWrong = true;
|
|
} else {
|
|
this._preparationGoneWrong = false;
|
|
}
|
|
|
|
range = this.colorRange = data.colorRange.sort(function (m, n) { return m.value - n.value; });
|
|
this.valueRatio = undefined;
|
|
this.values = [];
|
|
|
|
for (index = 0, length = range.length; index < length; index++) {
|
|
this.values.push(range[index].value);
|
|
}
|
|
}
|
|
|
|
ColorRange.prototype.constructor = ColorRange;
|
|
|
|
ColorRange.prototype.getValueRatio = function () {
|
|
var colorRange = this.colorRange,
|
|
currentRange,
|
|
index,
|
|
length = colorRange.length,
|
|
ratio = this.valueRatio,
|
|
maxValue = colorRange[length - 1].value,
|
|
minValue = colorRange[0].value,
|
|
range = maxValue - minValue,
|
|
itemValuePercent,
|
|
lastValue = 0;
|
|
|
|
if (ratio) {
|
|
return ratio;
|
|
}
|
|
|
|
ratio = this.valueRatio = [];
|
|
for (index = 0; index < length; index++) {
|
|
currentRange = colorRange[index];
|
|
itemValuePercent = (currentRange.value - minValue) / range;
|
|
|
|
ratio.push((itemValuePercent - lastValue) * 100);
|
|
lastValue = itemValuePercent;
|
|
}
|
|
|
|
return ratio;
|
|
};
|
|
|
|
ColorRange.prototype.getCumulativeValueRatio = function () {
|
|
var colorRange = this.colorRange,
|
|
currentRange,
|
|
index,
|
|
length = colorRange.length,
|
|
firstValue = colorRange[0].value,
|
|
lastValue = colorRange[length - 1].value,
|
|
ratio = [];
|
|
|
|
for (index = 0; index < length; index++) {
|
|
currentRange = colorRange[index];
|
|
ratio.push((currentRange.value - firstValue) / (lastValue - firstValue) * 100);
|
|
}
|
|
return ratio;
|
|
};
|
|
|
|
ColorRange.prototype.getBoxFill = function (isVertical) {
|
|
var colorRange = this.colorRange,
|
|
currentRange,
|
|
index,
|
|
length = colorRange.length,
|
|
color = [],
|
|
raphColorArg,
|
|
angle;
|
|
|
|
angle = isVertical ? 90 : 0;
|
|
|
|
for (index = 0; index < length; index++) {
|
|
currentRange = colorRange[index];
|
|
color.push(currentRange.code);
|
|
}
|
|
|
|
raphColorArg = {
|
|
FCcolor: {
|
|
alpha: '100,100,100',
|
|
angle: angle,
|
|
color: color.join(COMMA_STR),
|
|
ratio: this.getValueRatio().join(COMMA_STR)
|
|
}
|
|
};
|
|
|
|
return toRaphaelColor(raphColorArg);
|
|
};
|
|
|
|
ColorRange.prototype.getColorByValue = function (nVal) {
|
|
var valueArr = this.values,
|
|
colorRange = this.colorRange,
|
|
length,
|
|
index,
|
|
rangeOutSideColor,
|
|
color;
|
|
|
|
if (nVal === undefined || nVal === null) {
|
|
return;
|
|
}
|
|
|
|
for (index = 0, length = valueArr.length; index < length; index++) {
|
|
if (nVal === valueArr[index]) {
|
|
color = colorRange[index].code;
|
|
break;
|
|
} else if (!index && nVal < valueArr[index]) {
|
|
rangeOutSideColor = true;
|
|
break;
|
|
} else if (index === length - 1 && nVal > valueArr[index]) {
|
|
rangeOutSideColor = true;
|
|
break;
|
|
}else if (nVal > valueArr[index] && nVal < valueArr[index + 1]) {
|
|
color = getColorBetween(colorRange[index], colorRange[index + 1], nVal);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (rangeOutSideColor) {
|
|
return;
|
|
}
|
|
|
|
return color;
|
|
};
|
|
|
|
|
|
function GradientLegend () {
|
|
LegendBase.apply(this, arguments);
|
|
}
|
|
|
|
GradientLegend.prototype = Object.create(LegendBase.prototype);
|
|
GradientLegend.prototype.constructor = GradientLegend;
|
|
|
|
FusionCharts.register('component', ['gradientLegend', 'gradientLegend', {
|
|
pIndex: 1,
|
|
|
|
enabled: false,
|
|
/*
|
|
* Initializes the component.
|
|
* Calling this would create instance of colorRange. Which can be used to access the api of the same.
|
|
* Configure is called when the second level of init is called. The second level is explained below.
|
|
*
|
|
*
|
|
* Example use
|
|
* legend = new (FusionCharts.register('component',['gradientLegend', 'gradientLegend']))();
|
|
*
|
|
* 1st level - fn = legend.init({chart: chart});
|
|
* 2nd level - fn({min: 100, max: 1000, maxOtherSide: 150});
|
|
*
|
|
* Or putting it together - legend.init({chart: chart, dataExtremes: {min: 100, max: 1000, maxOtherSide: 150}})
|
|
* colorRange = legend.colorRange
|
|
*
|
|
*
|
|
* @param options {Object} - A simple key value pair needed for init.
|
|
* {
|
|
* chart: chartInstance,
|
|
* dataExtremes: optional data extreme of the datasets in the form
|
|
* {
|
|
* max: maximum value,
|
|
* min: minimum value,
|
|
* maxOtherSide: Optional maximum other side measurement. This takes the maximum allowed height for
|
|
* a horizontal legend and width for vertical legend.
|
|
* },
|
|
* }
|
|
*
|
|
* @return {Function | undefined} - If the dataExtremes are provided return undefined, else returns a function
|
|
* where it is to be fed.
|
|
*/
|
|
init: function (options) {
|
|
var componentAPI = this,
|
|
iapi = options.chart,
|
|
dataExtremes,
|
|
cr,
|
|
nData,
|
|
fcChart;
|
|
|
|
/*
|
|
* Performs 2nd level of initialization.
|
|
* Injects the colorRange in the API object.
|
|
*
|
|
* @param de {Object} - A simple key value pair needed for 2nd level of init. See the above dataExtremes obj
|
|
*/
|
|
function continueInit (de) {
|
|
// Extracts raw FC Chart data and parse it to prepare data for colorRange. This kind of acts like a
|
|
// adapter.
|
|
componentAPI.data = options.chart.jsonData.colorrange;
|
|
nData = componentAPI.nData = legendManager.legacyDataParser(componentAPI.data, de);
|
|
|
|
if (!nData) {
|
|
// If no valid data is present, sets a flag not to draw the legend . This will be read by subsequent
|
|
// calls.
|
|
componentAPI._dontPlot = true;
|
|
return;
|
|
}
|
|
|
|
// Starts prepaeparing the drawOptions object which is needed during the final drawing and space
|
|
// management.
|
|
componentAPI.drawOptions = {
|
|
smartLabel: iapi.linkedItems.smartLabel,
|
|
colorRange: (componentAPI.colorRange = cr = new ColorRange(nData, de, fcChart)),
|
|
maxOtherSide: de.maxOtherSide
|
|
};
|
|
|
|
componentAPI._dontPlot = false;
|
|
cr && cr._preparationGoneWrong && (componentAPI._dontPlot = true);
|
|
|
|
componentAPI._recalculateLogicalSpace = true;
|
|
|
|
// Parse all the legend releted attrs.
|
|
componentAPI._configure();
|
|
}
|
|
|
|
// Initiates the legend manager by providing the access to the chart object.
|
|
legendManager.init(options);
|
|
|
|
// Saves the reference of chart for internal use, in case
|
|
fcChart = componentAPI._chart = options.chart;
|
|
componentAPI._cpool = componentPoolFactory(fcChart);
|
|
|
|
if (!(dataExtremes = options.dataExtremes)) {
|
|
// If the dataExtremes is not provided, return the function for 2nd level of init
|
|
return continueInit;
|
|
}
|
|
|
|
// If provided perform the 2nd level of init internally by giving the feel to the user that init happened
|
|
// in one single shot
|
|
continueInit(dataExtremes);
|
|
},
|
|
|
|
/*
|
|
* Parses all the FC attributes for gradient legend
|
|
*/
|
|
_configure: function () {
|
|
var componentAPI = this,
|
|
chart = componentAPI._chart,
|
|
chartAttrs = chart.jsonData.chart,
|
|
conf = componentAPI.conf = {},
|
|
outCanvasBaseFont = chartAttrs.outcnvbasefont,
|
|
outCanvasBaseFontSize = chartAttrs.outcnvbasefontsize,
|
|
outCanvasBaseFontColor = chartAttrs.outcnvbasefontcolor,
|
|
labelStyle = chart.config.dataLabelStyle,
|
|
fColor,
|
|
fFamily,
|
|
fSize,
|
|
fWeight,
|
|
cfColor,
|
|
cfFamily,
|
|
cfSize,
|
|
cfWeight,
|
|
axisBorderColor,
|
|
axisBorderAlpha;
|
|
|
|
conf.caption = pluck(chartAttrs.legendcaption);
|
|
conf.legendPosition = pluck(chartAttrs.legendposition, 'bottom').toLowerCase();
|
|
conf.showLegend = pluckNumber(chartAttrs.showlegend, 1);
|
|
conf.interactiveLegend = pluckNumber(chartAttrs.interactivelegend, 1);
|
|
conf.showLegendLabels = pluckNumber(chartAttrs.showlegendlabels, 1);
|
|
|
|
fColor = chartAttrs.legenditemfontcolor || outCanvasBaseFontColor;
|
|
fFamily = chartAttrs.legenditemfont || outCanvasBaseFont;
|
|
fSize = chartAttrs.legenditemfontsize || outCanvasBaseFontSize;
|
|
fWeight = pluckNumber(chartAttrs.legenditemfontbold, 0);
|
|
|
|
cfColor = chartAttrs.legendcaptionfontcolor || outCanvasBaseFontColor;
|
|
cfFamily = chartAttrs.legendcaptionfont || outCanvasBaseFont;
|
|
cfSize = chartAttrs.legendcaptionfontsize || outCanvasBaseFontSize;
|
|
cfWeight = pluckNumber(chartAttrs.legendcaptionfontbold, 1);
|
|
|
|
axisBorderColor = chartAttrs.legendaxisbordercolor ?
|
|
hashify(dehashify(chartAttrs.legendaxisbordercolor)) : undefined;
|
|
|
|
axisBorderAlpha = axisBorderColor ? pluckNumber(chartAttrs.legendaxisborderalpha, 100) / 100 :
|
|
undefined;
|
|
|
|
// We do this like this so that, it becomes easy to override the default configuartion. The default conf was
|
|
// created in this format.
|
|
conf.axisTextItemConf = {
|
|
style: {
|
|
fill: fColor ? convertColor(pluck(fColor)) : labelStyle.color,
|
|
fontFamily: fFamily ? pluck(fFamily) : labelStyle.fontFamily,
|
|
fontSize: fSize ? pluckNumber(fSize) : labelStyle.fontSize.match(/\d+/)[0],
|
|
fontWeight: fWeight ? 'bold' : labelStyle.fontWeight
|
|
}
|
|
};
|
|
|
|
conf.legendCaptionConf = {
|
|
style : {
|
|
fill: cfColor ? convertColor(pluck(cfColor)) : labelStyle.color,
|
|
fontFamily: cfFamily ? pluck(cfFamily) : labelStyle.fontFamily,
|
|
fontSize: cfSize ? pluckNumber(cfSize) : labelStyle.fontSize.match(/\d+/)[0],
|
|
fontWeight: cfWeight ? 'bold' : labelStyle.fontWeight,
|
|
fontStyle: 'normal'
|
|
}
|
|
};
|
|
|
|
conf.legendAxisConf = {
|
|
legendAxisHeight: 11,
|
|
style : {
|
|
stroke: axisBorderColor,
|
|
'stroke-opacity': axisBorderAlpha
|
|
},
|
|
line: {
|
|
style: {
|
|
stroke: convertColor(pluck(chartAttrs.legendscalelinecolor, 'FFF8E9'),
|
|
pluckNumber(chartAttrs.legendscalelinealpha, 100)),
|
|
'stroke-width': pluckNumber(chartAttrs.legendscalelinethickness)
|
|
}
|
|
}
|
|
};
|
|
|
|
conf.sliderGroupConf = {
|
|
showTooltip: pluckNumber(chartAttrs.showtooltip, 1),
|
|
outerCircle : {
|
|
rFactor: pluckNumber(chartAttrs.sliderdiameterfactor),
|
|
style: {
|
|
stroke: convertColor(pluck(chartAttrs.legendpointerbordercolor, '757575'),
|
|
pluckNumber(chartAttrs.legendpointerborderalpha, 100))
|
|
}
|
|
},
|
|
innerCircle : {
|
|
rFactor: pluckNumber(chartAttrs.sliderholediameterfactor),
|
|
style: {
|
|
stroke: convertColor(pluck(chartAttrs.legendpointercolor, 'FFFFFF'),
|
|
pluckNumber(chartAttrs.legendpointeralpha, 100))
|
|
}
|
|
}
|
|
};
|
|
|
|
conf.legendCarpetConf = {
|
|
spreadFactor : pluckNumber(chartAttrs.legendspreadfactor),
|
|
allowDrag: !!pluckNumber(chartAttrs.legendallowdrag, 0),
|
|
captionAlignment: pluck(chartAttrs.legendcaptionalignment, 'center'),
|
|
style : {
|
|
'fill' : convertColor(pluck(chartAttrs.legendbgcolor, 'e4d9c1'),
|
|
pluckNumber(chartAttrs.legendbgalpha, 100)),
|
|
'stroke' : convertColor(pluck(chartAttrs.legendbordercolor, 'c4b89d'),
|
|
pluckNumber(chartAttrs.legendborderalpha, 100)),
|
|
'stroke-width': pluckNumber(chartAttrs.legendborderthickness, 1)
|
|
}
|
|
};
|
|
},
|
|
|
|
/*
|
|
* This takes care of the instance creation of various component based on attrs. Dependency injection /
|
|
* component injection is managed from here.
|
|
* This is not meant to be called from outside. This gets called internally.
|
|
*/
|
|
postConfigureInit : function () {
|
|
var componentAPI = this,
|
|
conf = componentAPI.conf,
|
|
caption,
|
|
carpet,
|
|
axis,
|
|
sGroup,
|
|
gl,
|
|
ovrdConf,
|
|
ovrdTextConf,
|
|
body,
|
|
labels,
|
|
values;
|
|
|
|
// Container for the component instances.
|
|
componentAPI.elem = {};
|
|
|
|
// The details of the various components and their relationship is written at the top.
|
|
|
|
if (conf.caption) {
|
|
// If caption is present, create a instance of the same
|
|
ovrdConf = merge(legendManager.getDefaultConf('legendCaptionConf'), conf.legendCaptionConf);
|
|
caption = new LegendCaption(conf.caption, ovrdConf);
|
|
}
|
|
|
|
if (conf.interactiveLegend) {
|
|
// If interactiveLegend is attr is present, creates the sliders of the legend.
|
|
|
|
// Override the default conf with the user given one.
|
|
ovrdConf = merge(legendManager.getDefaultConf('sliderGroupConf'), conf.sliderGroupConf);
|
|
componentAPI.elem.sGroup = sGroup = new SliderGroup(ovrdConf);
|
|
componentAPI.listeners && componentAPI.listeners.length > 0 &&
|
|
sGroup.registerListener.apply(sGroup, componentAPI.listeners);
|
|
}
|
|
|
|
ovrdConf = merge(legendManager.getDefaultConf('legendCarpetConf'), conf.legendCarpetConf);
|
|
|
|
if (conf.legendPosition === 'bottom') {
|
|
// If the legend to be placed at bottom
|
|
|
|
// The reference side would be width and will be covered the complete canvasWidth.
|
|
// The max of other side is given by maxOtherSide.
|
|
// The margin is taken from canvasLeft
|
|
componentAPI.drawOptions.refSideKey = 'canvasWidth';
|
|
componentAPI.drawOptions.refOffsetKey = 'canvasLeft';
|
|
|
|
// Creates a horizontal capet, axis, labels and values component
|
|
carpet = new LegendCarpet(ovrdConf);
|
|
|
|
ovrdTextConf = merge(legendManager.getDefaultConf('axisTextItemConf'), conf.axisTextItemConf);
|
|
|
|
body = new LegendBody(componentAPI.drawOptions.colorRange,
|
|
legendManager.getDefaultConf('legendBodyConf'), ovrdTextConf);
|
|
|
|
axis = new LegendAxis(merge(legendManager.getDefaultConf('legendAxisConf'), conf.legendAxisConf));
|
|
|
|
conf.showLegendLabels && (labels = new LegendLabels(ovrdTextConf));
|
|
values = new LegendValues(ovrdTextConf);
|
|
} else {
|
|
// If the legend to be placed at bottom
|
|
|
|
// The reference side would be height and will be covered the complete canvasWidth.
|
|
// The max of other side is given by maxOtherSide.
|
|
// The margin is taken from canvasTop
|
|
componentAPI.drawOptions.refSideKey = 'canvasHeight';
|
|
componentAPI.drawOptions.refOffsetKey = 'canvasTop';
|
|
|
|
ovrdTextConf = merge(legendManager.getDefaultConf('axisTextItemConf'), conf.axisTextItemConf);
|
|
|
|
carpet = new VerticalLegendCarpet(ovrdConf);
|
|
body = new VerticalLegendBody(componentAPI.drawOptions.colorRange,
|
|
legendManager.getDefaultConf('legendBodyConf'), ovrdTextConf);
|
|
|
|
axis = new VerticalLegendAxis(merge(legendManager.getDefaultConf('legendAxisConf'),
|
|
conf.legendAxisConf));
|
|
|
|
conf.showLegendLabels && (labels = new VerticalLegendLabels(ovrdTextConf));
|
|
values = new VerticalLegendValues(ovrdTextConf);
|
|
}
|
|
|
|
// If the slider group is defined, inject as component. Slider group is component of axis.
|
|
sGroup && axis.addCompositions(sGroup, compositionKeys.RANGE);
|
|
|
|
// Adds component to the body if available
|
|
labels && body.addCompositions(labels, compositionKeys.AXIS_LABEL);
|
|
body.addCompositions(axis, compositionKeys.LEGEND_AXIS);
|
|
body.addCompositions(values, compositionKeys.AXIS_VALUE);
|
|
|
|
// Adds the body and the caption to the carpet
|
|
caption && carpet.addCompositions(caption, compositionKeys.CAPTION);
|
|
carpet.addCompositions(body, compositionKeys.LEGEND_BODY);
|
|
|
|
// Finally creates the gradient legend.
|
|
componentAPI.elem.gl = gl = new GradientLegend(carpet, componentAPI._cpool);
|
|
},
|
|
|
|
notifyWhenUpdate: function (fn, context, params) {
|
|
var componentAPI = this,
|
|
rGroup;
|
|
|
|
rGroup = componentAPI.elem && componentAPI.elem.sGroup;
|
|
if (rGroup) {
|
|
rGroup.registerListener(fn, context, params);
|
|
} else {
|
|
componentAPI.listeners = [fn, context, params];
|
|
}
|
|
},
|
|
|
|
dispose: function () {
|
|
var componentAPI = this;
|
|
|
|
componentAPI.elem && componentAPI.elem.gl && componentAPI.elem.gl.dispose();
|
|
componentAPI.elem = {};
|
|
},
|
|
|
|
getLogicalSpace: function (maxOtherSide) {
|
|
var componentAPI = this,
|
|
conf = componentAPI.conf,
|
|
zeroArea = {
|
|
height: 0,
|
|
width: 0
|
|
},
|
|
drawOptions = componentAPI.drawOptions,
|
|
refSideKey,
|
|
chart = componentAPI._chart,
|
|
refOffsetKey;
|
|
|
|
// @todo redundancy in calculating the reference side. Make it from a organized procedure call.
|
|
if (!componentAPI._recalculateLogicalSpace) {
|
|
refSideKey = drawOptions.refSideKey;
|
|
refOffsetKey = drawOptions.refOffsetKey;
|
|
|
|
componentAPI.drawOptions.refSide = chart.config[refSideKey];
|
|
componentAPI.drawOptions.refOffset = chart.config[refOffsetKey];
|
|
|
|
(componentAPI._logicalArea = componentAPI.elem.gl.getLogicalSpace(componentAPI.drawOptions, true));
|
|
return componentAPI._logicalArea || zeroArea;
|
|
}
|
|
|
|
if (componentAPI._dontPlot) {
|
|
return zeroArea;
|
|
}
|
|
|
|
componentAPI._recalculateLogicalSpace = false;
|
|
componentAPI.postConfigureInit();
|
|
|
|
if (!conf.showLegend) {
|
|
return zeroArea;
|
|
}
|
|
|
|
refSideKey = drawOptions.refSideKey;
|
|
refOffsetKey = drawOptions.refOffsetKey;
|
|
|
|
componentAPI.drawOptions.refSide = chart.config[refSideKey];
|
|
componentAPI.drawOptions.refOffset = chart.config[refOffsetKey];
|
|
|
|
componentAPI.drawOptions.maxOtherSide = maxOtherSide || componentAPI.drawOptions.maxOtherSide;
|
|
return componentAPI.elem.gl &&
|
|
(componentAPI._logicalArea = componentAPI.elem.gl.getLogicalSpace(componentAPI.drawOptions, true));
|
|
},
|
|
|
|
resetLegend: function() {
|
|
var componentAPI = this,
|
|
rGroup;
|
|
|
|
rGroup = componentAPI.elem && componentAPI.elem.sGroup;
|
|
if (rGroup) {
|
|
rGroup.reset();
|
|
}
|
|
},
|
|
|
|
clearListeners: function () {
|
|
var componentAPI = this,
|
|
rGroup;
|
|
|
|
rGroup = componentAPI.elem && componentAPI.elem.sGroup;
|
|
if (rGroup) {
|
|
rGroup.clearListeners();
|
|
}
|
|
},
|
|
|
|
draw: function (x, y, options) {
|
|
var componentAPI = this,
|
|
conf = componentAPI.conf,
|
|
measurement,
|
|
node;
|
|
|
|
if (componentAPI._dontPlot) {
|
|
return;
|
|
}
|
|
|
|
componentAPI._cpool.init(options.paper);
|
|
|
|
if (!conf.showLegend) {
|
|
componentAPI.enabled = false;
|
|
return;
|
|
}
|
|
|
|
componentAPI.drawOptions.paper = options.paper;
|
|
componentAPI.drawOptions.parentGroup = options.parentGroup;
|
|
componentAPI.drawOptions.x = x;
|
|
componentAPI.drawOptions.y = y;
|
|
componentAPI.drawOptions.maxOtherSide = componentAPI.drawOptions.maxOtherSide || options.maxOtherSide;
|
|
|
|
node = componentAPI.elem.gl.draw(componentAPI.drawOptions);
|
|
measurement = node.getBBox();
|
|
|
|
conf.xPos = measurement.x;
|
|
conf.yPos = measurement.y;
|
|
conf.height = measurement.height;
|
|
conf.width = measurement.width;
|
|
|
|
componentAPI.enabled = true;
|
|
}
|
|
|
|
}]);
|
|
}]);
|
|
|
|
/**!
|
|
* @license FusionCharts JavaScript Library
|
|
* Copyright FusionCharts Technologies LLP
|
|
* License Information at <http://www.fusioncharts.com/license>
|
|
*
|
|
* @version 3.12.0
|
|
*/
|
|
/**
|
|
* @private
|
|
* @module fusioncharts.renderer.javascript.msstepline
|
|
*/
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-msstepline', function() {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname),
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
chartAPI = lib.chartAPI,
|
|
pluckNumber = lib.pluckNumber,
|
|
pluck = lib.pluck,
|
|
Image = win.Image,
|
|
preDefStr = lib.preDefStr,
|
|
schedular = lib.schedular,
|
|
LINE = preDefStr.line,
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
getFirstValue = lib.getFirstValue,
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
dataLabelStr = preDefStr.dataLabelStr,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
hiddenStr = preDefStr.hiddenStr,
|
|
SETROLLOVERATTR = 'setRolloverAttr',
|
|
SETROLLOUTATTR = 'setRolloutAttr',
|
|
math = Math,
|
|
mathMax = math.max,
|
|
hasTouch = lib.hasTouch,
|
|
TOUCH_THRESHOLD_PIXELS = lib.TOUCH_THRESHOLD_PIXELS,
|
|
CLICK_THRESHOLD_PIXELS = lib.CLICK_THRESHOLD_PIXELS,
|
|
HTP = hasTouch ? TOUCH_THRESHOLD_PIXELS : CLICK_THRESHOLD_PIXELS,
|
|
M = 'M',
|
|
H = 'H',
|
|
V = 'V',
|
|
ROUND = preDefStr.ROUND,
|
|
miterStr = preDefStr.miterStr,
|
|
UNDEFINED,
|
|
NORMALSTRING = 'normal';
|
|
|
|
chartAPI('msstepline', {
|
|
friendlyName: 'Multi-series Step Line Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType: 'msstepline',
|
|
defaultPlotShadow: 1,
|
|
applicableDSList: {'msstepline': true}
|
|
}, chartAPI.mscartesian, {
|
|
drawverticaljoins: 1,
|
|
useforwardsteps: 1,
|
|
zeroplanethickness: 1,
|
|
zeroplanealpha: 40,
|
|
showzeroplaneontop: 0,
|
|
enablemousetracking: true
|
|
}, chartAPI.areabase);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-msstepline',
|
|
function () {
|
|
var COMPONENT = 'component',
|
|
DATASET_GROUP = 'datasetGroup';
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET_GROUP, 'msstepline', {
|
|
},'line']);
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'MSStepLine', {
|
|
type: 'msstepline',
|
|
_addLegend: function () {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
conf = dataset.config,
|
|
legend = chart.components.legend,
|
|
drawAnchors = pluckNumber(conf.drawanchors, 1),
|
|
config = {
|
|
enabled: conf.includeinlegend,
|
|
type : LINE,
|
|
/* In case of scatter (a child chartAPI of line),
|
|
line is drawn in legend only when drawLine is set
|
|
to true. */
|
|
drawLine: pluck(conf.drawLine, true),
|
|
fillColor : toRaphaelColor({
|
|
color: conf.anchorbgcolor,
|
|
alpha: conf.anchorbgalpha
|
|
}),
|
|
strokeColor: toRaphaelColor({
|
|
color: conf.anchorbordercolor,
|
|
alpha: '100'
|
|
}),
|
|
rawFillColor: conf.anchorbgcolor,
|
|
rawStrokeColor: conf.anchorbordercolor,
|
|
anchorSide: drawAnchors ? conf.anchorsides : 0,
|
|
strokeWidth: conf.anchorborderthickness,
|
|
label : getFirstValue(dataset.JSONData.seriesname),
|
|
lineWidth: conf.linethickness
|
|
};
|
|
dataset.legendItemId = legend.addItems(dataset, dataset.legendInteractivity, config);
|
|
},
|
|
draw: function () {// retrive requitrd objects
|
|
var dataSet = this,
|
|
JSONData = dataSet.JSONData,
|
|
chart = dataSet.chart,
|
|
jobList = chart.getJobList(),
|
|
chartComponents = chart.components,
|
|
conf = dataSet.config,
|
|
datasetIndex = dataSet.index || dataSet.positionIndex,
|
|
chartConfig = chart.config,
|
|
len,
|
|
i,
|
|
paper = chartComponents.paper,
|
|
xAxis = chartComponents.xAxis[0],
|
|
yAxis = dataSet.yAxis,
|
|
xPos,
|
|
yPos,
|
|
layers = chart.graphics,
|
|
dataLabelsLayer = layers.datalabelsGroup,
|
|
toolText,
|
|
label,
|
|
setElement,
|
|
hotElement,
|
|
setLink,
|
|
setValue,
|
|
eventArgs,
|
|
displayValue,
|
|
dataStore = dataSet.components.data,
|
|
dataObj,
|
|
setRolloutAttr,
|
|
setRolloverAttr,
|
|
removeDataArr = dataSet.components.removeDataArr || [],
|
|
removeDataArrLen = removeDataArr.length,
|
|
lineThickness = conf.linethickness,
|
|
container = dataSet.graphics.container,
|
|
connectNullData = chartConfig.connectnulldata,
|
|
group = layers.datasetGroup,
|
|
hoverEffects,
|
|
shadow = conf.shadow,
|
|
anchorShadow,
|
|
dataLabelContainer = dataSet.graphics.dataLabelContainer,
|
|
anchorProps = {},
|
|
imgRef,
|
|
symbol,
|
|
config,
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
dummyAnimElem = animationObj.dummyObj,
|
|
dummyAnimObj = animationObj.animObj,
|
|
animationDuration = animationObj.duration,
|
|
pool = dataSet.components.pool || [],
|
|
showValue,
|
|
pathAttr,
|
|
EVENTARGS = 'eventArgs',
|
|
/*
|
|
Called when transpose animation is completed
|
|
for hiding the dataset
|
|
*/
|
|
animCallBack = function() {
|
|
if (dataSet.visible === false && (dataSet._conatinerHidden === false ||
|
|
dataSet._conatinerHidden=== undefined)) {
|
|
container.lineGroup.hide();
|
|
container.lineShadowGroup.hide();
|
|
container.anchorShadowGroup.hide();
|
|
container.anchorGroup.hide();
|
|
dataLabelContainer && dataLabelContainer.hide();
|
|
dataSet._conatinerHidden = true;
|
|
}
|
|
},
|
|
/*
|
|
Called when the initial animation compeletes
|
|
for showing the dataset
|
|
*/
|
|
initAnimCallBack = function () {
|
|
group.lineConnector.attr({
|
|
'clip-rect': null
|
|
});
|
|
// fix for ie11
|
|
group.lineConnector.node && group.lineConnector.node.removeAttribute('clip-path');
|
|
if (dataSet.visible !== false) {
|
|
container.lineShadowGroup.show();
|
|
container.anchorShadowGroup.show();
|
|
container.anchorGroup.show();
|
|
dataLabelContainer && dataLabelContainer.show();
|
|
}
|
|
// animCompleteFn();
|
|
},
|
|
animFlag = true,
|
|
setTooltext,
|
|
connector,
|
|
dashStyle,
|
|
yBase = yAxis.getAxisBase(),
|
|
yBasePos = yAxis.yBasePos = yAxis.getAxisPosition(yBase),
|
|
clipConf = chartComponents.canvas.config.clip,
|
|
clipCanvasInit = clipConf['clip-canvas-init'].slice(0),
|
|
clipCanvas = clipConf['clip-canvas'].slice(0),
|
|
lineDashStyle = conf.lineDashStyle,
|
|
lineColorObj = {
|
|
color: conf.linecolor,
|
|
alpha: conf.alpha
|
|
},
|
|
setColor,
|
|
setDashStyle,
|
|
lineSegmentChange,
|
|
colorObj,
|
|
linePath = [],
|
|
lscthash,
|
|
lineDrawing = 0,
|
|
mainLinePath = [],
|
|
lastYPos = null,
|
|
lastXPos,
|
|
lastMoveCommand = [],
|
|
initialAnimation = false,
|
|
connectorShadow,
|
|
MAX_MITER_LINEJOIN = 2,
|
|
cosmeticAttrs,
|
|
lineElement = dataSet.graphics.lineElement,
|
|
visible = dataSet.visible,
|
|
drawVerticalJoins = conf.drawverticaljoins,
|
|
useForwardSteps = conf.useforwardsteps,
|
|
labelElement,
|
|
imageElement,
|
|
polypath,
|
|
animType = animationObj.animType,
|
|
isNewElem,
|
|
noOfImages = 0,
|
|
catLabel,
|
|
halfStep = chart.config.stepatmiddle ? xAxis.getPVR() * 0.5 : 0,
|
|
radius,
|
|
borderThickness,
|
|
topAnchorPos,
|
|
bottomAnchorPos,
|
|
canvasTop = chartConfig.canvasTop,
|
|
canvasBottom = chartConfig.canvasBottom;
|
|
|
|
conf.imagesLoaded = 0;
|
|
/*
|
|
* Creating lineConnector group and appending it to dataset layer if not created
|
|
* Lineconnector group has the anchorgroups of all datasets
|
|
*/
|
|
group.lineConnector = group.lineConnector ||
|
|
paper.group('line-connector', group);
|
|
// Create dataset container if not created
|
|
if (!container) {
|
|
container = dataSet.graphics.container = {
|
|
lineShadowGroup: paper.group('connector-shadow', group.lineConnector),
|
|
anchorShadowGroup: paper.group('anchor-shadow', group.lineConnector),
|
|
lineGroup: paper.group(LINE, group.lineConnector),
|
|
anchorGroup: paper.group('anchors', group.lineConnector)
|
|
};
|
|
if (!visible) {
|
|
container.lineShadowGroup.hide();
|
|
container.anchorShadowGroup.hide();
|
|
container.lineGroup.hide();
|
|
container.anchorGroup.hide();
|
|
}
|
|
|
|
}
|
|
|
|
if (!dataStore) {
|
|
dataStore = dataSet.components.data = [];
|
|
}
|
|
|
|
if (!dataLabelContainer) {
|
|
dataLabelContainer = dataSet.graphics.dataLabelContainer = dataSet.graphics.dataLabelContainer ||
|
|
paper.group(dataLabelStr, dataLabelsLayer);
|
|
if (!visible) {
|
|
dataLabelContainer.hide();
|
|
}
|
|
}
|
|
|
|
if (visible) {
|
|
container.lineShadowGroup.show();
|
|
container.anchorShadowGroup.show();
|
|
container.lineGroup.show();
|
|
container.anchorGroup.show();
|
|
dataLabelContainer.show();
|
|
}
|
|
len = xAxis.getCategoryLen();
|
|
//create plot elements
|
|
for (i=0; i<len; i++) {
|
|
dataObj = dataStore[i];
|
|
if (!dataObj) {
|
|
continue;
|
|
}
|
|
config = dataObj.config;
|
|
setValue = config.setValue;
|
|
setLink = config.setLink;
|
|
setTooltext = config.setLevelTooltext;
|
|
showValue = config.showValue;
|
|
anchorProps = config.anchorProps;
|
|
symbol = anchorProps.symbol;
|
|
anchorShadow = anchorProps.shadow;
|
|
displayValue = config.displayValue;
|
|
setElement = dataObj.graphics.element;
|
|
imageElement = dataObj.graphics.image;
|
|
hotElement = dataObj.graphics.hotElement;
|
|
labelElement = dataObj.graphics.label;
|
|
// Creating the data object if not created
|
|
if (!dataObj) {
|
|
dataObj = dataStore[i] = {
|
|
graphics : {}
|
|
};
|
|
}
|
|
// If value is null
|
|
if (setValue === null) {
|
|
lastMoveCommand.length = 0;
|
|
if (!connectNullData) {
|
|
lastYPos = null;
|
|
}
|
|
setElement && setElement.hide();
|
|
imageElement && imageElement.hide();
|
|
labelElement && labelElement.hide();
|
|
hotElement && hotElement.hide();
|
|
}
|
|
else {
|
|
// Storing the color Object of this data
|
|
colorObj = {
|
|
color: config.color,
|
|
alpha: config.alpha
|
|
};
|
|
dashStyle = config.dashStyle;
|
|
xPos = xAxis.getAxisPosition(i);
|
|
// On hiding a dataset the y position of the hidden dataset is set to yBasePos
|
|
if (!dataSet.visible && animationDuration) {
|
|
yPos = yBasePos;
|
|
}
|
|
else {
|
|
yPos = yAxis.getAxisPosition(setValue);
|
|
}
|
|
hoverEffects = config.hoverEffects;
|
|
anchorProps.isAnchorHoverRadius = hoverEffects.anchorRadius;
|
|
|
|
radius = anchorProps.radius;
|
|
borderThickness = anchorProps.borderThickness;
|
|
|
|
topAnchorPos = yPos - radius - (borderThickness / 2);
|
|
bottomAnchorPos = yPos + radius + (borderThickness / 2);
|
|
|
|
topAnchorPos < canvasTop && (chartConfig.toleranceTop = mathMax(chartConfig.toleranceTop || 0,
|
|
canvasTop - topAnchorPos));
|
|
bottomAnchorPos > canvasBottom && (chartConfig.toleranceBottom = mathMax(
|
|
chartConfig.toleranceBottom || 0, bottomAnchorPos - canvasBottom));
|
|
|
|
label = config.label;
|
|
catLabel = xAxis.getLabel(i);
|
|
|
|
if (!chartConfig.showtooltip) {
|
|
toolText = BLANKSTRING;
|
|
}
|
|
else {
|
|
toolText = config.toolText + (setTooltext ? BLANKSTRING : config.toolTipValue);
|
|
}
|
|
|
|
config.finalTooltext = toolText;
|
|
|
|
eventArgs = config.eventArgs || (config.eventArgs = {});
|
|
// Storing the event arguments
|
|
eventArgs.index = i;
|
|
eventArgs.link = setLink;
|
|
eventArgs.value = setValue;
|
|
eventArgs.displayValue = displayValue;
|
|
eventArgs.categoryLabel = catLabel;
|
|
eventArgs.toolText = toolText;
|
|
eventArgs.id = conf.userID;
|
|
eventArgs.datasetIndex = datasetIndex;
|
|
eventArgs.datasetName = JSONData.seriesname;
|
|
eventArgs.visible = visible;
|
|
|
|
isNewElem = false;
|
|
// If imageurl is present
|
|
if (anchorProps.imageUrl) {
|
|
config.anchorImageLoaded = false;
|
|
dataObj._xPos = xPos;
|
|
dataObj._yPos = yPos;
|
|
imgRef = new Image();
|
|
imgRef.onload = this._onAnchorImageLoad(dataSet, i, eventArgs, xPos, yPos);
|
|
imgRef.onerror = this._onErrorSetter(dataSet, i);
|
|
imgRef.src = anchorProps.imageUrl;
|
|
noOfImages++;
|
|
}
|
|
else {
|
|
imageElement && imageElement.hide();
|
|
polypath = [symbol[1] || 2, xPos, yPos,
|
|
anchorProps.radius, anchorProps.startAngle, anchorProps.dip];
|
|
cosmeticAttrs = {
|
|
fill: toRaphaelColor({
|
|
color: anchorProps.bgColor,
|
|
alpha: anchorProps.bgAlpha
|
|
}),
|
|
stroke: toRaphaelColor({
|
|
color: anchorProps.borderColor,
|
|
alpha: anchorProps.borderAlpha
|
|
}),
|
|
'stroke-width': anchorProps.borderThickness,
|
|
visibility: !anchorProps.radius ? hiddenStr : visible
|
|
};
|
|
// Create anchor element if not created
|
|
if (!setElement) {
|
|
if (pool.element && pool.element.length) {
|
|
setElement = dataObj.graphics.element = pool.element.shift();
|
|
}
|
|
else {
|
|
isNewElem = true;
|
|
setElement = dataObj.graphics.element = paper.polypath(container.anchorGroup);
|
|
setElement.attr({
|
|
polypath: polypath
|
|
});
|
|
}
|
|
}
|
|
|
|
setElement.show().animateWith(dummyAnimElem, dummyAnimObj, {
|
|
polypath: polypath
|
|
}, animationDuration, animType, animFlag && animCallBack);
|
|
|
|
setElement.attr(cosmeticAttrs)
|
|
.shadow(anchorShadow, container.anchorShadowGroup)
|
|
.data('hoverEnabled', hoverEffects.enabled)
|
|
.data(EVENTARGS,eventArgs);
|
|
animFlag = false;
|
|
}
|
|
|
|
connector = dataObj.graphics.connector;
|
|
if (hoverEffects.enabled) {
|
|
setRolloverAttr = {
|
|
polypath: [hoverEffects.anchorSides || 2,
|
|
xPos, yPos,
|
|
hoverEffects.anchorRadius,
|
|
hoverEffects.startAngle,
|
|
hoverEffects.dip
|
|
],
|
|
fill: toRaphaelColor({
|
|
color: hoverEffects.anchorColor,
|
|
alpha: hoverEffects.anchorBgAlpha
|
|
}),
|
|
stroke: toRaphaelColor({
|
|
color: hoverEffects.anchorBorderColor,
|
|
alpha: hoverEffects.anchorBorderAlpha
|
|
}),
|
|
'stroke-width': hoverEffects.anchorBorderThickness
|
|
};
|
|
setRolloutAttr = {
|
|
polypath: [anchorProps.sides, xPos, yPos,
|
|
anchorProps.radius, anchorProps.startAngle, 0
|
|
],
|
|
fill: toRaphaelColor({
|
|
color: anchorProps.bgColor,
|
|
alpha: anchorProps.bgAlpha
|
|
}),
|
|
stroke: toRaphaelColor({
|
|
color: anchorProps.borderColor,
|
|
alpha: anchorProps.borderAlpha
|
|
}),
|
|
'stroke-width': anchorProps.borderThickness
|
|
};
|
|
setElement && setElement
|
|
.data('anchorRadius', anchorProps.radius)
|
|
.data('anchorHoverRadius', hoverEffects.anchorRadius)
|
|
.data('hoverEnabled', hoverEffects.enabled)
|
|
.data(SETROLLOVERATTR, setRolloverAttr)
|
|
.data(SETROLLOUTATTR, setRolloutAttr)
|
|
.data(EVENTARGS,eventArgs);
|
|
}
|
|
|
|
config.trackerConfig || (config.trackerConfig = {});
|
|
|
|
config.trackerConfig.trackerRadius = mathMax(anchorProps.radius,
|
|
hoverEffects && hoverEffects.anchorRadius || 0, HTP) +
|
|
((anchorProps.borderThickness || 0) / 2);
|
|
// // anchor Radius of hot element is set to maximum of hover radius and anchor radius
|
|
// anchorRadius = mathMax(anchorProps.radius,
|
|
// hoverEffects &&
|
|
// hoverEffects.anchorRadius || 0, HTP);
|
|
|
|
/*
|
|
if colorObj and dash style of this data is different from
|
|
the previous data then a new line segment is to be created
|
|
*/
|
|
lineSegmentChange = (lscthash !== [
|
|
toRaphaelColor(colorObj || lineColorObj),
|
|
dashStyle || lineDashStyle
|
|
].join(':'));
|
|
// If the y position of the last value is not null
|
|
if (lastYPos !== null) {
|
|
if (lastMoveCommand.length) {
|
|
linePath = linePath.concat(lastMoveCommand);
|
|
lastMoveCommand.length = 0;
|
|
}
|
|
// move to the starting position of the line segment
|
|
if (!linePath.join(BLANKSTRING)) {
|
|
linePath.push(M, lastXPos, lastYPos);
|
|
}
|
|
if (useForwardSteps) {
|
|
linePath.push(H, xPos - halfStep);
|
|
if (drawVerticalJoins) {
|
|
linePath.push(V, yPos);
|
|
}
|
|
else {
|
|
linePath.push(M, xPos - halfStep, yPos);
|
|
}
|
|
if (halfStep) {
|
|
linePath.push(H, xPos);
|
|
}
|
|
}
|
|
else {
|
|
if (drawVerticalJoins) {
|
|
linePath.push(V, yPos);
|
|
}
|
|
else {
|
|
linePath.push(M, lastXPos, yPos);
|
|
}
|
|
linePath.push(H, xPos);
|
|
}
|
|
// If a new line segment is to be created
|
|
if (lineSegmentChange) {
|
|
// If a connector path is to drawn
|
|
if (!lineDrawing) {
|
|
if (!connector) {
|
|
connector = dataObj.graphics.connector = paper.path(linePath,
|
|
container.lineGroup);
|
|
initialAnimation = true;
|
|
}
|
|
|
|
connector.animateWith(dummyAnimElem, dummyAnimObj, {
|
|
path: linePath
|
|
}, animationDuration, animType, animFlag && animCallBack);
|
|
|
|
connector.attr({
|
|
'stroke-dasharray': setDashStyle,
|
|
'stroke-width': lineThickness,
|
|
'stroke': setColor,
|
|
'stroke-linecap': ROUND,
|
|
'stroke-linejoin': lineThickness >
|
|
MAX_MITER_LINEJOIN ? ROUND : miterStr
|
|
})
|
|
.shadow(connectorShadow, container.lineShadowGroup);
|
|
animFlag = false;
|
|
|
|
}
|
|
// Else appending the path to main Line path
|
|
else {
|
|
mainLinePath = mainLinePath.concat(linePath);
|
|
}
|
|
linePath = [];
|
|
}
|
|
// Hide the unused disjoint lines and push it to pool for reusing it next time when new
|
|
// disjoint lines will be drawn
|
|
if (!lineSegmentChange) {
|
|
if (connector) {
|
|
connector.hide();
|
|
}
|
|
}
|
|
} else {
|
|
// Pushing the x y position of move command to lastMoveCommand array
|
|
lastMoveCommand.push(M, xPos, yPos);
|
|
}
|
|
// Storing the xPos and yPos of this data for next iterations
|
|
lastXPos = xPos;
|
|
lastYPos = yPos;
|
|
setColor = toRaphaelColor(colorObj || lineColorObj);
|
|
if (colorObj) {
|
|
connectorShadow = {
|
|
opacity: colorObj && colorObj.alpha/100
|
|
};
|
|
}
|
|
else {
|
|
connectorShadow = shadow;
|
|
}
|
|
setDashStyle = dashStyle || lineDashStyle;
|
|
/*If color,alpha or dashed is not defined for this data
|
|
then line drawing is set to 1 so the path of this data is
|
|
appended to mainLinePath and not the connector path
|
|
*/
|
|
if (pluck(config.color, config.alpha, config.dashed) === UNDEFINED) {
|
|
lineDrawing = 1;
|
|
}
|
|
else {
|
|
lineDrawing = 0;
|
|
}
|
|
lscthash = [setColor, setDashStyle].join(':');
|
|
/*Storing the x position and y position in dataObject for future reference
|
|
For example - when drawing labels we need this xPos and yPos
|
|
*/
|
|
dataObj._xPos = xPos;
|
|
dataObj._yPos = yPos;
|
|
|
|
!anchorProps.imageUrl && this.drawLabel(i);
|
|
}
|
|
}
|
|
|
|
conf.noOfImages = conf.totalImages = noOfImages;
|
|
|
|
if (noOfImages === 0) {
|
|
jobList.labelDrawID.push(schedular.addJob(dataSet.drawLabel, dataSet, [],
|
|
lib.priorityList.label));
|
|
}
|
|
|
|
|
|
if (linePath.length) {
|
|
mainLinePath = mainLinePath.concat(linePath);
|
|
}
|
|
pathAttr = {
|
|
path: mainLinePath
|
|
};
|
|
cosmeticAttrs = {
|
|
'stroke-dasharray': lineDashStyle,
|
|
'stroke-width': lineThickness,
|
|
'stroke': toRaphaelColor(lineColorObj),
|
|
'stroke-linecap': ROUND,
|
|
/* for lines even with thickness as 2 we need to have round line join
|
|
otherwise the line join may look like exceeding the correct position
|
|
*/
|
|
'stroke-linejoin': lineThickness >= MAX_MITER_LINEJOIN ? ROUND : miterStr
|
|
};
|
|
if (!lineElement) {
|
|
lineElement = dataSet.graphics.lineElement = paper.path({
|
|
path: mainLinePath
|
|
}, container.lineGroup);
|
|
initialAnimation = true;
|
|
}
|
|
|
|
lineElement.show().animateWith(dummyAnimElem, dummyAnimObj,
|
|
pathAttr, animationDuration, animType, animFlag && animCallBack);
|
|
|
|
lineElement.attr(cosmeticAttrs)
|
|
.shadow(shadow, container.lineShadowGroup);
|
|
animFlag = false;
|
|
|
|
if (animationDuration && visible && initialAnimation) {
|
|
container.anchorGroup.hide();
|
|
container.lineShadowGroup.hide();
|
|
container.anchorShadowGroup.hide();
|
|
dataLabelContainer.hide();
|
|
group.lineConnector.attr({
|
|
'clip-rect': clipCanvasInit
|
|
})
|
|
.animateWith(dummyAnimElem, dummyAnimObj, {
|
|
'clip-rect': clipCanvas
|
|
}, animationDuration, NORMALSTRING, initAnimCallBack);
|
|
}
|
|
for (i = 0; i < removeDataArrLen; i++) {
|
|
dataSet._removeDataVisuals(removeDataArr.shift());
|
|
}
|
|
dataSet.drawn = true;
|
|
}
|
|
}, LINE, {
|
|
drawverticaljoins : undefined,
|
|
useforwardsteps : undefined
|
|
}]);
|
|
}]);
|
|
|
|
/**!
|
|
* @license FusionCharts JavaScript Library
|
|
* Copyright FusionCharts Technologies LLP
|
|
* License Information at <http://www.fusioncharts.com/license>
|
|
*
|
|
* @version 3.12.0
|
|
*/
|
|
/**
|
|
* @private
|
|
* @module fusioncharts.renderer.javascript.powercharts
|
|
* @requires fusioncharts.renderer.javascript.msstepline
|
|
* @requires fusioncharts.renderer.javascript.legend-gradient
|
|
* @requires fusioncharts.renderer.javascript.js-component-toolbox
|
|
* @export fusioncharts.powercharts.js
|
|
*/
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-powercharts',
|
|
function() {
|
|
// Adding FC_ChartUpdated event to eventList
|
|
// for dragCharts
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
R = lib.Raphael,
|
|
pluckNumber = lib.pluckNumber,
|
|
math = Math,
|
|
mathSin = math.sin,
|
|
mathCos = math.cos,
|
|
mathPI = math.PI,
|
|
deg2rad = mathPI / 180,
|
|
M = 'M',
|
|
L = 'L',
|
|
Z = 'Z',
|
|
A = 'A',
|
|
getArcPath = function(cX, cY, startX, startY, endX, endY, rX, rY, isClockWise, isLargeArc) {
|
|
return [A, rX, rY, 0, isLargeArc, isClockWise, endX, endY];
|
|
};
|
|
|
|
lib.eventList.chartupdated = 'FC_ChartUpdated';
|
|
lib.eventList.dataposted = 'FC_DataPosted';
|
|
lib.eventList.dataposterror = 'FC_DataPostError';
|
|
lib.eventList.datarestored = 'FC_DataRestored';
|
|
|
|
// Add custom symbol to Raphael
|
|
R.addSymbol({
|
|
resizeIcon: function(x, y, radius) {
|
|
var
|
|
LINE_GAP = pluckNumber(radius, 15) / 3,
|
|
LINE_DIS = 3,
|
|
paths = [],
|
|
i;
|
|
|
|
if (LINE_GAP < 0) {
|
|
LINE_GAP = -LINE_GAP;
|
|
radius = -radius;
|
|
x += radius - LINE_GAP / 2;
|
|
y += radius - LINE_GAP / 2;
|
|
}
|
|
|
|
for (i = 3; i > 0; i -= 1) {
|
|
paths.push(M, x - LINE_GAP * i, y - LINE_DIS,
|
|
L, x - LINE_DIS, y - LINE_GAP * i);
|
|
}
|
|
return paths;
|
|
},
|
|
closeIcon: function(x, y, r) {
|
|
var
|
|
icoX = x,
|
|
icoY = y,
|
|
rad = r * 1.3,
|
|
startAngle = 43 * deg2rad,
|
|
// to prevent cos and sin of start and end from becoming
|
|
// equal on 360 arcs
|
|
endAngle = 48 * deg2rad,
|
|
startX = icoX + rad * mathCos(startAngle),
|
|
startY = icoY + rad * mathSin(startAngle),
|
|
endX = icoX + rad * mathCos(endAngle),
|
|
endY = icoY + rad * mathSin(endAngle),
|
|
paths,
|
|
r1 = 0.71 * (r - 2), //(r - 2) * 0.5,
|
|
r2 = 0.71 * (r - 2), //(r - 2) * 0.87,
|
|
|
|
arcPath = getArcPath(icoX, icoY, startX, startY, endX,
|
|
endY, rad, rad, 0, 1);
|
|
|
|
paths = [M, startX, startY];
|
|
paths = paths.concat(arcPath);
|
|
paths = paths.concat([
|
|
M, x + r1, y - r2,
|
|
L, x - r1, y + r2,
|
|
M, x - r1, y - r2,
|
|
L, x + r1, y + r2
|
|
]);
|
|
|
|
return paths;
|
|
},
|
|
configureIcon: function(x, y, r) {
|
|
r = r - 1;
|
|
var k = 0.5,
|
|
l = 0.25,
|
|
r1 = r * 0.71,
|
|
r2 = (r + 2) * 0.71,
|
|
x1 = x - r,
|
|
y1 = y - r,
|
|
x2 = x + r,
|
|
y2 = y + r,
|
|
x3 = x + k,
|
|
y3 = y + k,
|
|
x4 = x - k,
|
|
y4 = y - k,
|
|
|
|
x5 = x1 - 2,
|
|
y5 = y1 - 2,
|
|
x6 = x2 + 2,
|
|
y6 = y2 + 2,
|
|
x7 = x + r1,
|
|
y7 = y + r1,
|
|
x8 = x - r1,
|
|
y8 = y - r1,
|
|
x9 = x + r2,
|
|
y9 = y + r2,
|
|
x10 = x - r2,
|
|
y10 = y - r2,
|
|
paths;
|
|
|
|
paths = [M, x1, y3, L, x5, y3, x5, y4, x1, y4,
|
|
x8 - l, y8 + l, x10 - l, y10 + l, x10 + l, y10 - l, x8 + l, y8 - l,
|
|
x4, y1, x4, y5, x3, y5, x3, y1,
|
|
x7 - l, y8 - l, x9 - l, y10 - l, x9 + l, y10 + l, x7 + l, y8 + l,
|
|
x2, y4, x6, y4, x6, y3, x2, y3,
|
|
x7 + l, y7 - l, x9 + l, y9 - l, x9 - l, y9 + l, x7 - l, y7 + l,
|
|
x3, y2, x3, y6, x4, y6, x4, y2,
|
|
x8 + l, y7 + l, x10 + l, y9 + l, x10 - l, y9 - l, x8 - l, y7 - l, Z
|
|
];
|
|
return paths;
|
|
},
|
|
axisIcon: function(x, y, r) {
|
|
r = r - 1;
|
|
var r1 = r * 0.33,
|
|
r2 = r / 2,
|
|
x1 = x - r,
|
|
y1 = y - r,
|
|
x2 = x + r2,
|
|
y2 = y + r,
|
|
x3 = x - r2,
|
|
y3 = y + r1,
|
|
y4 = y - r1,
|
|
paths;
|
|
|
|
paths = [M, x1, y1, L, x2, y1, x2, y2, x1, y2, M, x3, y3, L, x2, y3,
|
|
M, x3, y4, L, x2, y4
|
|
];
|
|
return paths;
|
|
},
|
|
loggerIcon: function(x, y, r) {
|
|
r = r - 1;
|
|
x = x - r;
|
|
y = y - r;
|
|
var r2 = r * 2,
|
|
x1 = x + r2,
|
|
x2 = x + 2,
|
|
x3 = x1 - 2,
|
|
y1 = y + 2,
|
|
y2 = y1 + r,
|
|
y3 = y2 + 2,
|
|
paths;
|
|
|
|
paths = [M, x, y, L, x1, y, x1, y1, x3, y1, x3, y2, x1, y2, x1, y3,
|
|
x, y3, x, y2, x2, y2, x2, y1, x, y1, x, y
|
|
];
|
|
return paths;
|
|
}
|
|
});
|
|
|
|
global.addEventListener('rendered', function(event) {
|
|
var chartObj = event.sender,
|
|
state = chartObj.__state,
|
|
iapi = chartObj.jsVars && chartObj.jsVars.instanceAPI;
|
|
if (chartObj.disposed) {
|
|
return;
|
|
}
|
|
if (!state.listenersAdded && iapi && typeof iapi.getCollatedData === 'function') {
|
|
chartObj.addEventListener(['chartupdated', 'dataupdated', 'rendered'], function(event) {
|
|
delete event.sender.__state.hasStaleData;
|
|
});
|
|
state.listenersAdded = true;
|
|
}
|
|
});
|
|
}
|
|
]);
|
|
|
|
/* jshint ignore: start */
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-spline', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
math = Math,
|
|
mathRound = math.round,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI;
|
|
|
|
chartAPI('spline', {
|
|
friendlyName: 'Spline Chart',
|
|
standaloneInit: true,
|
|
singleseries: true,
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType: 'msspline',
|
|
defaultPlotShadow: 1,
|
|
applicableDSList: {'spline': true},
|
|
/**
|
|
* getSplineExtremities is called to get back the maximum and minimum y values of the vertical envelope
|
|
* of a spline. The data may contain null data values, to be tackled based on the connectNullData setting.
|
|
* For connectNullData = 0, the curve splits into separate spline curves, to be tackled via recursivion,
|
|
* as below. The parameters index and limits are left blank for the initial call to this method, used only
|
|
* for recursion, tackled from within the method.
|
|
*/
|
|
getSplineExtremities: function (data, chartWidth, connectNullData, index, limits) {
|
|
// array to hold the pertinent data only, required for gradients' calculations
|
|
var arrKnot = [],
|
|
validValueFound = false,
|
|
u = index || 0,
|
|
chart = this;
|
|
|
|
limits = limits || { max: Number.MIN_VALUE, min: Number.MAX_VALUE };
|
|
|
|
// populating arrKnot with pertinent data by iterating and checking
|
|
for (; u < data.length; ++u) {
|
|
|
|
// checking for if the first valid data value is found
|
|
if (!validValueFound) {
|
|
// if data value is valid
|
|
if (!isNaN (data[u].config.setValue) && data[u].config.setValue !== null) {
|
|
validValueFound = true;
|
|
// just ingore the null/invalid data value, for the first valid data value is yet to be found
|
|
} else {
|
|
continue;
|
|
}
|
|
// reach this position if the first valid data value is found for this data value itself
|
|
arrKnot.push ( {
|
|
index : u,
|
|
y : data[u].config.setValue
|
|
});
|
|
// if valid first data value is already found
|
|
} else {
|
|
// for invalid data value
|
|
if (isNaN (data[u].config.setValue) || data[u].config.setValue === null) {
|
|
if (connectNullData) {
|
|
// just ignore the data
|
|
continue;
|
|
} else {
|
|
// split here, to end the curve and start a new curve
|
|
break;
|
|
}
|
|
} else {
|
|
arrKnot.push ( {
|
|
index : u,
|
|
y : data[u].config.setValue
|
|
});
|
|
}
|
|
}
|
|
}
|
|
// spline curve is possible for a set of plots with more than 2 points
|
|
if (arrKnot.length > 2) {
|
|
// Examine the spline curve to find the min-max vertically
|
|
chart.evalSplineExtremities (arrKnot, chartWidth, limits);
|
|
}
|
|
//
|
|
// recursion is required for the case of a series splitted into multiple subset of points due to
|
|
// existence of null data entries in the series
|
|
if (u < data.length && !connectNullData) {
|
|
chart.getSplineExtremities (data, chartWidth, connectNullData, u, limits);
|
|
}
|
|
return limits;
|
|
},
|
|
/**
|
|
*
|
|
* evalSplineExtremities is called to evaluate the vertical extremities of the bounding box of the spline.
|
|
*/
|
|
evalSplineExtremities: function (arrKnot, chartWidth, limits) {
|
|
// object to store gradients at spline plots
|
|
var objGrad = { },
|
|
chart = this,
|
|
u, i, t, calcValue, delX;
|
|
|
|
// Below, each gradient is initialised to zero
|
|
for (i = 0; i < arrKnot.length; ++ i) {
|
|
// getting the original index for this data
|
|
t = arrKnot[i].index;
|
|
// initialised to zero
|
|
objGrad ['D' + t] = 0;
|
|
}
|
|
|
|
// The following iteration is a mathematical purpose - iterative method of approximation with faster
|
|
// convergence. The more the number of iteration, more precise are the approximate solutions.
|
|
for (u = 0; u < 10; ++ u) {
|
|
// iteration for convergence towards actual solutions
|
|
for (i = 0; i < arrKnot.length; ++ i) {
|
|
if (i === 0) {
|
|
calcValue = (3 * (arrKnot [i + 1].y - arrKnot[i].y) -
|
|
objGrad ['D' + arrKnot[i + 1].index]) / 2;
|
|
} else if (i === arrKnot.length - 1) {
|
|
calcValue = (3 * (arrKnot[i].y - arrKnot[i - 1].y) -
|
|
objGrad ['D' + arrKnot[i - 1].index]) / 2;
|
|
} else {
|
|
calcValue = (3 * (arrKnot[i + 1].y - arrKnot[i - 1].y) -
|
|
objGrad ['D' + arrKnot[i + 1].index] - objGrad ['D' + arrKnot[i - 1].index]) / 4;
|
|
}
|
|
// gradient value updated in repository for use in subsequent loop/turn for faster convergence
|
|
objGrad ['D' + arrKnot[i].index] = calcValue;
|
|
}
|
|
}
|
|
|
|
// Since, canvas width is not ready as yet, chart width is used instead to get as close as possible to
|
|
// the required x-interval between two consecutive spline plots
|
|
delX = mathRound (chartWidth / (arrKnot.length - 1));
|
|
|
|
// each spline constitutes of a number of smaller curves, each joining two consecutive pioints.
|
|
for (i = 1; i < arrKnot.length; ++ i) {
|
|
// find the max-min y-values for the bounding box of the unit curve
|
|
chart.getSegmentExtremities (i, arrKnot, objGrad, limits, delX);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* getSegmentExtremities method is aclled to process unit curves constituting a spline
|
|
* and evaluate the vertical limits of the curve.
|
|
*/
|
|
getSegmentExtremities: function (index, data, objGradientStore, limits, delX) {
|
|
// storing the reference of the repository of coordinates of the points
|
|
var arrKnot = data,
|
|
i = index,
|
|
j = 0,
|
|
slope1, slope2, a1, a2, a3, a4, maxY, minY, k, n, t, y1;
|
|
|
|
// slopes of the curve at the two extremes of the spline
|
|
slope1 = objGradientStore ['D' + arrKnot[j].index];
|
|
slope2 = objGradientStore ['D' + arrKnot[i].index];
|
|
// calculating the four coefficients characterising the cubic polynomial
|
|
a1 = arrKnot[j].y;
|
|
a2 = slope1;
|
|
a3 = 3 * (arrKnot[i].y - arrKnot[j].y) - 2 * slope1 - slope2;
|
|
a4 = 2 * (arrKnot[j].y - arrKnot[i].y) + slope1 + slope2;
|
|
|
|
maxY = limits.max;
|
|
minY = limits.min;
|
|
|
|
for (k = 0, n = delX; k <= n; k++) {
|
|
t = k / n;
|
|
y1 = a1 + a2 * t + a3 * t * t + a4 * t * t * t;
|
|
|
|
if (y1 < minY) {
|
|
minY = y1;
|
|
}
|
|
|
|
if (y1 > maxY) {
|
|
maxY = y1;
|
|
}
|
|
}
|
|
|
|
limits.max = maxY;
|
|
limits.min = minY;
|
|
}
|
|
}, chartAPI.sscartesian, {
|
|
minimizetendency: 0,
|
|
zeroplanethickness: 1,
|
|
zeroplanealpha: 40,
|
|
showzeroplaneontop: 0,
|
|
enablemousetracking: true
|
|
}, chartAPI.areabase);
|
|
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-splinearea', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
HUNDREDSTRING = lib.HUNDREDSTRING,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI;
|
|
|
|
chartAPI('splinearea', {
|
|
friendlyName: 'Spline Area Chart',
|
|
standaloneInit: true,
|
|
hasLegend: false,
|
|
singleseries: true,
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType: 'mssplinearea',
|
|
defaultPlotShadow: 0
|
|
}, chartAPI.spline, {
|
|
anchoralpha: HUNDREDSTRING,
|
|
minimizetendency: 0,
|
|
enablemousetracking: true
|
|
}, chartAPI.areabase);
|
|
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-msspline', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI;
|
|
|
|
chartAPI('msspline', {
|
|
standaloneInit: true,
|
|
friendlyName: 'Multi-series Spline Chart',
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType : 'msspline',
|
|
applicableDSList: {'msspline': true},
|
|
defaultPlotShadow: 1,
|
|
getSplineExtremities: chartAPI.spline.getSplineExtremities,
|
|
evalSplineExtremities: chartAPI.spline.evalSplineExtremities,
|
|
getSegmentExtremities: chartAPI.spline.getSegmentExtremities
|
|
}, chartAPI.mscartesian, {
|
|
minimizetendency: 0,
|
|
zeroplanethickness: 1,
|
|
zeroplanealpha: 40,
|
|
showzeroplaneontop: 0,
|
|
enablemousetracking: true
|
|
}, chartAPI.areabase);
|
|
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-mssplinearea', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI;
|
|
|
|
chartAPI('mssplinearea', {
|
|
friendlyName: 'Multi-series Spline Area Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType: 'mssplinearea',
|
|
defaultPlotShadow: 0
|
|
}, chartAPI.msspline, {
|
|
minimizetendency: 0,
|
|
enablemousetracking: true
|
|
}, chartAPI.areabase);
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-mssplinedy', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI;
|
|
|
|
chartAPI('mssplinedy', {
|
|
friendlyName: 'Multi-series Dual Y-Axis Spline Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
isDual: true,
|
|
defaultDatasetType : 'msspline',
|
|
applicableDSList: {'msspline': true},
|
|
getSplineExtremities: chartAPI.spline.getSplineExtremities,
|
|
evalSplineExtremities: chartAPI.spline.evalSplineExtremities,
|
|
getSegmentExtremities: chartAPI.spline.getSegmentExtremities
|
|
}, chartAPI.msdybasecartesian, {
|
|
minimizetendency: 0,
|
|
zeroplanethickness: 1,
|
|
zeroplanealpha: 40,
|
|
showzeroplaneontop: 0
|
|
}, chartAPI.msspline);
|
|
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-multiaxisline', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
pluck = lib.pluck,
|
|
pluckNumber = lib.pluckNumber,
|
|
preDefStr = lib.preDefStr,
|
|
sStr = preDefStr.sStr,
|
|
COMPONENT = 'component',
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
DATASET = 'dataset',
|
|
UNDEFINED,
|
|
DATASET_GROUP = 'datasetGroup',
|
|
defaultFontStr = preDefStr.defaultFontStr,
|
|
pluckFontSize = lib.pluckFontSize, // To get the valid font size (filters negative values)
|
|
divLineAlphaStr = preDefStr.divLineAlphaStr,
|
|
divLineAlpha3DStr = preDefStr.divLineAlpha3DStr,
|
|
componentDispose = lib.componentDispose,
|
|
chartPaletteStr = lib.chartPaletteStr = {
|
|
chart2D: {
|
|
bgColor : 'bgColor',
|
|
bgAlpha : 'bgAlpha',
|
|
bgAngle : 'bgAngle',
|
|
bgRatio : 'bgRatio',
|
|
canvasBgColor : 'canvasBgColor',
|
|
canvasBaseColor : 'canvasBaseColor',
|
|
divLineColor : 'divLineColor',
|
|
legendBgColor : 'legendBgColor',
|
|
legendBorderColor : 'legendBorderColor',
|
|
toolTipbgColor : 'toolTipbgColor',
|
|
toolTipBorderColor : 'toolTipBorderColor',
|
|
baseFontColor : 'baseFontColor',
|
|
anchorBgColor : 'anchorBgColor'
|
|
},
|
|
chart3D : {
|
|
bgColor : 'bgColor3D',
|
|
bgAlpha : 'bgAlpha3D',
|
|
bgAngle : 'bgAngle3D',
|
|
bgRatio : 'bgRatio3D',
|
|
canvasBgColor : 'canvasBgColor3D',
|
|
canvasBaseColor : 'canvasBaseColor3D',
|
|
divLineColor : 'divLineColor3D',
|
|
divLineAlpha : divLineAlpha3DStr,
|
|
legendBgColor : 'legendBgColor3D',
|
|
legendBorderColor : 'legendBorderColor3D',
|
|
toolTipbgColor : 'toolTipbgColor3D',
|
|
toolTipBorderColor : 'toolTipBorderColor3D',
|
|
baseFontColor : 'baseFontColor3D',
|
|
anchorBgColor : 'anchorBgColor3D'
|
|
}
|
|
},
|
|
AXIS = 'axis',
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
colorStrings = preDefStr.colors,
|
|
convertColor = lib.graphics.convertColor,
|
|
extend2 = lib.extend2, //old: jarendererExtend / margecolone
|
|
altVGridColorStr = preDefStr.altVGridColorStr,
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
isIE = lib.isIE,
|
|
TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
|
|
COMMA = ',',
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
hasTouch = lib.hasTouch,
|
|
math = Math,
|
|
mathMax = math.max,
|
|
mathMin = math.min,
|
|
POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
|
|
COLOR_000000 = colorStrings.c000000,
|
|
altVGridAlphaStr = preDefStr.altVGridAlphaStr,
|
|
chartAPI = lib.chartAPI;
|
|
|
|
chartAPI('multiaxisline', {
|
|
friendlyName: 'Multi-axis Line Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType: 'multiaxisline',
|
|
defaultPlotShadow: 1,
|
|
axisPaddingLeft: 0,
|
|
axisPaddingRight: 0,
|
|
applicableDSList: { LINE: true },
|
|
_createDatasets : function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
chartConfig = iapi.config,
|
|
//graphics = iapi.graphics,
|
|
//datasetGroup = graphics.datasetGroup,
|
|
dataObj = iapi.jsonData,
|
|
dataset = dataObj.axis,
|
|
length,
|
|
i,
|
|
j,
|
|
diff,
|
|
subDataset,
|
|
datasetStore,
|
|
datasetStoreLen,
|
|
curDatasetStoreLen = 0,
|
|
datasetObj,
|
|
subDatasetLen,
|
|
defaultSeriesType = iapi.defaultDatasetType,
|
|
applicableDSList = iapi.applicableDSList,
|
|
legend = components.legend,
|
|
legendItems = legend.components.items || [],
|
|
GroupManager,
|
|
dsType,
|
|
DsClass,
|
|
DsGroupClass,
|
|
datasetJSON,
|
|
isStacked = iapi.config.isstacked,
|
|
groupManagerName,
|
|
parentyaxis,
|
|
dsCount = { },
|
|
count = 0,
|
|
axisDataSetMap,
|
|
JSONData,
|
|
prevDataLength,
|
|
currDataLength;
|
|
|
|
if (!dataset) {
|
|
iapi.setChartMessage();
|
|
return;
|
|
}
|
|
length = dataset.length;
|
|
iapi.config.categories = dataObj.categories && dataObj.categories[0].category;
|
|
|
|
datasetStore = components.dataset || (components.dataset = []);
|
|
datasetStoreLen = datasetStore.length;
|
|
axisDataSetMap = chartConfig.axisDataSetMap = [];
|
|
for (i=0; i<length; i++) {
|
|
|
|
subDataset = dataset[i].dataset;
|
|
axisDataSetMap[i] = [];
|
|
if (!subDataset) {
|
|
continue;
|
|
}
|
|
subDatasetLen = subDataset.length;
|
|
curDatasetStoreLen += subDatasetLen;
|
|
for (j = 0; j < subDatasetLen; j++) {
|
|
datasetJSON = subDataset[j];
|
|
datasetJSON.seriesname && (datasetJSON.seriesname = parseUnsafeString(datasetJSON.seriesname));
|
|
parentyaxis = datasetJSON.parentyaxis || BLANKSTRING;
|
|
if (iapi.isDual && parentyaxis.toLowerCase () === sStr) {
|
|
dsType = pluck (datasetJSON.renderas, iapi.sDefaultDatasetType);
|
|
}
|
|
else {
|
|
dsType = pluck (datasetJSON.renderas, defaultSeriesType);
|
|
}
|
|
dsType = dsType && dsType.toLowerCase ();
|
|
if (!applicableDSList[dsType]) {
|
|
dsType = defaultSeriesType;
|
|
}
|
|
|
|
/// get the DsClass
|
|
DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
|
|
if (DsClass) {
|
|
if (dsCount[dsType] === UNDEFINED) {
|
|
dsCount[dsType] = 0;
|
|
}
|
|
else {
|
|
dsCount[dsType]++;
|
|
}
|
|
groupManagerName = 'datasetGroup_' + dsType;
|
|
// get the ds group class
|
|
DsGroupClass = FusionCharts.register(COMPONENT, [DATASET_GROUP, dsType]);
|
|
GroupManager = components[groupManagerName];
|
|
if (DsGroupClass && !GroupManager) {
|
|
GroupManager = components[groupManagerName] = new DsGroupClass ();
|
|
GroupManager.chart = iapi;
|
|
GroupManager.init ();
|
|
// groupManager.init (components, graphics);
|
|
// groupManager.dataSetsLen = length;
|
|
}
|
|
|
|
// If the dataset does not exists.
|
|
if (!datasetStore[count]) {
|
|
// create the dataset Object
|
|
datasetObj = new DsClass ();
|
|
datasetStore.push (datasetObj);
|
|
datasetObj.chart = iapi;
|
|
datasetObj.index = i;
|
|
// set axis index to refer the right axis
|
|
datasetObj.axisIndex = i;
|
|
axisDataSetMap[i].push(count);
|
|
count += 1;
|
|
// add to group manager
|
|
GroupManager && (isStacked ? GroupManager.addDataSet (datasetObj, 0, dsCount[dsType]) :
|
|
GroupManager.addDataSet (datasetObj, dsCount[dsType], 0));
|
|
datasetObj.init (datasetJSON);
|
|
}
|
|
// If the dataset exists incase the chart is updated using setChartData() method.
|
|
else {
|
|
datasetObj = datasetStore[count];
|
|
JSONData = datasetObj.JSONData;
|
|
prevDataLength = JSONData.data ? JSONData.data.length : 0;
|
|
currDataLength = datasetJSON.data ? datasetJSON.data.length : 0;
|
|
// Removing data plots if the number of current data plots
|
|
// is more than the existing ones.
|
|
if (prevDataLength > currDataLength) {
|
|
datasetObj.removeData(currDataLength - 1, prevDataLength - currDataLength, false);
|
|
}
|
|
datasetObj.JSONData = datasetJSON;
|
|
datasetObj.index = i;
|
|
datasetObj.axisIndex = i;
|
|
datasetObj.configure();
|
|
// set axis index to refer the right axis
|
|
axisDataSetMap[i].push(count);
|
|
count += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// When the number of datasets entered vis setChartData is less than the existing dataset then
|
|
// dispose the extra datasets.
|
|
if (datasetStoreLen > curDatasetStoreLen) {
|
|
diff = datasetStoreLen - curDatasetStoreLen;
|
|
|
|
for (j = curDatasetStoreLen; j < datasetStoreLen; j ++ ) {
|
|
componentDispose.call(datasetStore[j]);
|
|
}
|
|
datasetStore.splice(curDatasetStoreLen, diff);
|
|
|
|
legendItems.splice(curDatasetStoreLen, diff);
|
|
}
|
|
},
|
|
_createAxes : function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
CartesianAxis = FusionCharts.register (COMPONENT, [AXIS, 'cartesian']),
|
|
xAxis;
|
|
|
|
components.yAxis = [];
|
|
components.xAxis = [];
|
|
components.xAxis[0] = xAxis = new CartesianAxis ();
|
|
xAxis.chart = iapi;
|
|
xAxis.init ();
|
|
// set the chart categories
|
|
iapi._setCategories ();
|
|
},
|
|
_feedAxesRawData : function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
chartConfig = iapi.config,
|
|
colorM = components.colorManager,
|
|
numberFormatter = components.numberFormatter,
|
|
dataObj = iapi.jsonData,
|
|
chartAttrs = dataObj.chart,
|
|
xAxisConf,
|
|
yAxisConf,
|
|
is3d = iapi.is3d,
|
|
palleteString = is3d ? chartPaletteStr.chart3D : chartPaletteStr.chart2D,
|
|
CartesianAxis = FusionCharts.register (COMPONENT, [AXIS, 'cartesian']),
|
|
yAxis,
|
|
xAxis,
|
|
axes,
|
|
i,
|
|
len,
|
|
isOpposit,
|
|
axisJson,
|
|
plotColor,
|
|
leftAxes,
|
|
rightAxes,
|
|
axesMap,
|
|
axisHEXColor,
|
|
axisColor,
|
|
gridLineWidth,
|
|
tickWidth,
|
|
axisLineThickness,
|
|
showAxis,
|
|
checkBoxChecked = false,
|
|
count = 0,
|
|
j,
|
|
jlen;
|
|
|
|
|
|
xAxisConf = {
|
|
outCanfontFamily: pluck (chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
|
|
outCanfontSize: pluckFontSize (chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
|
|
outCancolor: pluck (chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
|
|
colorM.getColor (palleteString.baseFontColor)).replace (/^#? ([a-f0-9]+)/ig, '#$1'),
|
|
axisNamePadding: chartAttrs.xaxisnamepadding,
|
|
axisValuePadding: chartAttrs.labelpadding,
|
|
axisNameFont: chartAttrs.xaxisnamefont,
|
|
axisNameFontSize: chartAttrs.xaxisnamefontsize,
|
|
axisNameFontColor: chartAttrs.xaxisnamefontcolor,
|
|
axisNameFontBold: chartAttrs.xaxisnamefontbold,
|
|
axisNameFontItalic: chartAttrs.xaxisnamefontitalic,
|
|
axisNameBgColor: chartAttrs.xaxisnamebgcolor,
|
|
axisNameBorderColor: chartAttrs.xaxisnamebordercolor,
|
|
axisNameAlpha: chartAttrs.xaxisnamealpha,
|
|
axisNameFontAlpha: chartAttrs.xaxisnamefontalpha,
|
|
axisNameBgAlpha: chartAttrs.xaxisnamebgalpha,
|
|
axisNameBorderAlpha: chartAttrs.xaxisnameborderalpha,
|
|
axisNameBorderPadding: chartAttrs.xaxisnameborderpadding,
|
|
axisNameBorderRadius: chartAttrs.xaxisnameborderradius,
|
|
axisNameBorderThickness: chartAttrs.xaxisnameborderthickness,
|
|
axisNameBorderDashed: chartAttrs.xaxisnameborderdashed,
|
|
axisNameBorderDashLen: chartAttrs.xaxisnameborderdashlen,
|
|
axisNameBorderDashGap: chartAttrs.xaxisnameborderdashgap,
|
|
useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
|
|
divLineColor: pluck (chartAttrs.vdivlinecolor, chartAttrs.divlinecolor,
|
|
colorM.getColor (palleteString.divLineColor)),
|
|
divLineAlpha: pluck (chartAttrs.vdivlinealpha, chartAttrs.divlinealpha,
|
|
is3d ? colorM.getColor(divLineAlpha3DStr) : colorM.getColor (divLineAlphaStr)),
|
|
divLineThickness: pluckNumber (chartAttrs.vdivlinethickness, chartAttrs.divlinethickness, 1),
|
|
divLineIsDashed: Boolean (pluckNumber (chartAttrs.vdivlinedashed, chartAttrs.vdivlineisdashed,
|
|
chartAttrs.divlinedashed, chartAttrs.divlineisdashed, 0)),
|
|
divLineDashLen: pluckNumber (chartAttrs.vdivlinedashlen, chartAttrs.divlinedashlen, 4),
|
|
divLineDashGap: pluckNumber (chartAttrs.vdivlinedashgap, chartAttrs.divlinedashgap, 2),
|
|
showAlternateGridColor: pluckNumber (chartAttrs.showalternatevgridcolor, 0),
|
|
alternateGridColor: pluck (chartAttrs.alternatevgridcolor, colorM.getColor (altVGridColorStr)),
|
|
alternateGridAlpha: pluck (chartAttrs.alternatevgridalpha, colorM.getColor (altVGridAlphaStr)),
|
|
numDivLines: chartAttrs.numvdivlines,
|
|
labelFont: chartAttrs.labelfont,
|
|
labelFontSize: chartAttrs.labelfontsize,
|
|
labelFontColor: chartAttrs.labelfontcolor,
|
|
labelFontBold : chartAttrs.labelfontbold,
|
|
labelFontItalic : chartAttrs.labelfontitalic,
|
|
labelFontAlpha: chartAttrs.labelalpha,
|
|
maxLabelHeight : chartAttrs.maxlabelheight,
|
|
axisName: chartAttrs.xaxisname,
|
|
axisMinValue: chartAttrs.xaxisminvalue,
|
|
axisMaxValue: chartAttrs.xaxismaxvalue,
|
|
setAdaptiveMin: chartAttrs.setadaptivexmin,
|
|
adjustDiv: chartAttrs.adjustvdiv,
|
|
labelDisplay: chartAttrs.labeldisplay,
|
|
showLabels: chartAttrs.showlabels,
|
|
rotateLabels: chartAttrs.rotatelabels,
|
|
slantLabel: pluckNumber (chartAttrs.slantlabels, chartAttrs.slantlabel),
|
|
labelStep: pluckNumber (chartAttrs.labelstep, chartAttrs.xaxisvaluesstep),
|
|
showAxisValues: pluckNumber (chartAttrs.showxaxisvalues, chartAttrs.showxaxisvalue),
|
|
showLimits: chartAttrs.showvlimits,
|
|
showDivLineValues: pluckNumber (chartAttrs.showvdivlinevalues, chartAttrs.showvdivlinevalues),
|
|
showZeroPlane: chartAttrs.showvzeroplane,
|
|
zeroPlaneColor: chartAttrs.vzeroplanecolor,
|
|
zeroPlaneThickness: chartAttrs.vzeroplanethickness,
|
|
zeroPlaneAlpha: chartAttrs.vzeroplanealpha,
|
|
showZeroPlaneValue: chartAttrs.showvzeroplanevalue,
|
|
trendlineColor: chartAttrs.trendlinecolor,
|
|
trendlineToolText: chartAttrs.trendlinetooltext,
|
|
trendlineThickness: chartAttrs.trendlinethickness,
|
|
trendlineAlpha: chartAttrs.trendlinealpha,
|
|
showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
|
|
showAxisLine: pluckNumber (chartAttrs.showxaxisline, chartAttrs.showaxislines,
|
|
chartAttrs.drawAxisLines, 0),
|
|
axisLineThickness: pluckNumber (chartAttrs.xaxislinethickness, chartAttrs.axislinethickness, 1),
|
|
axisLineAlpha: pluckNumber (chartAttrs.xaxislinealpha, chartAttrs.axislinealpha, 100),
|
|
axisLineColor: pluck (chartAttrs.xaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
|
|
};
|
|
yAxisConf = {
|
|
outCanfontFamily: pluck (chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
|
|
outCanfontSize: pluckFontSize (chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
|
|
outCancolor: pluck (chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
|
|
colorM.getColor (palleteString.baseFontColor)).replace (/^#? ([a-f0-9]+)/ig, '#$1'),
|
|
useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
|
|
showAlternateGridColor: 0,
|
|
axisNameFont: chartAttrs.yaxisnamefont,
|
|
axisNameFontSize: chartAttrs.yaxisnamefontsize,
|
|
axisNameFontColor: chartAttrs.yaxisnamefontcolor,
|
|
axisNameFontBold: chartAttrs.yaxisnamefontbold,
|
|
axisNameFontItalic: chartAttrs.yaxisnamefontitalic,
|
|
axisNameBgColor: chartAttrs.yaxisnamebgcolor,
|
|
axisNameBorderColor: chartAttrs.yaxisnamebordercolor,
|
|
axisNameAlpha: chartAttrs.yaxisnamealpha,
|
|
axisNameFontAlpha: chartAttrs.yaxisnamefontalpha,
|
|
axisNameBgAlpha: chartAttrs.yaxisnamebgalpha,
|
|
axisNameBorderAlpha: chartAttrs.yaxisnameborderalpha,
|
|
axisNameBorderPadding: chartAttrs.yaxisnameborderpadding,
|
|
axisNameBorderRadius: chartAttrs.yaxisnameborderradius,
|
|
axisNameBorderThickness: chartAttrs.yaxisnameborderthickness,
|
|
axisNameBorderDashed: chartAttrs.yaxisnameborderdashed,
|
|
axisNameBorderDashLen: chartAttrs.yaxisnameborderdashlen,
|
|
axisNameBorderDashGap: chartAttrs.yaxisnameborderdashgap
|
|
};
|
|
// xAxisConf.vtrendlines = dataObj.vtrendlines;
|
|
// yAxisConf.trendlines = dataObj.trendlines;
|
|
xAxis = components.xAxis[0];
|
|
xAxis.setCommonConfigArr (xAxisConf, false, false, false);
|
|
xAxis.configure();
|
|
chartConfig.axesArr = {
|
|
leftAxes : [],
|
|
rightAxes : [],
|
|
axesMap : [],
|
|
checkBox : [],
|
|
leftSideSelected : false
|
|
};
|
|
leftAxes = chartConfig.axesArr.leftAxes = [];
|
|
rightAxes = chartConfig.axesArr.rightAxes = [];
|
|
axesMap = chartConfig.axesArr.axesMap = [];
|
|
axes = dataObj.axis || [];
|
|
for (i = 0, len = axes.length; i < len; i += 1) {
|
|
if (!components.yAxis[i]) {
|
|
yAxis = components.yAxis[i] = new CartesianAxis ();
|
|
yAxis.chart = iapi;
|
|
yAxis.init ();
|
|
} else {
|
|
yAxis = components.yAxis[i];
|
|
}
|
|
axisJson = axes[i];
|
|
checkBoxChecked = false;
|
|
for (j = 0, jlen = axisJson.dataset ? axisJson.dataset.length : 0; j < jlen; j += 1) {
|
|
if(Number(axisJson.dataset[j].visible) !== 0 ) {
|
|
checkBoxChecked = true;
|
|
}
|
|
}
|
|
showAxis = pluckNumber(axisJson.showaxis, 1);
|
|
plotColor = colorM.getPlotColor(i);
|
|
axisHEXColor = pluck(axisJson.color, chartAttrs.axiscolor,
|
|
plotColor);
|
|
axisColor = convertColor(axisHEXColor, 100);
|
|
gridLineWidth = pluckNumber(axisJson.divlinethickness,
|
|
chartAttrs.divlinethickness, 1);
|
|
tickWidth = pluckNumber(axisJson.tickwidth, chartAttrs.axistickwidth, 2);
|
|
axisLineThickness = pluckNumber(axisJson.axislinethickness, chartAttrs.axislinethickness, 2);
|
|
isOpposit = !(pluckNumber(axisJson.axisonleft,1));
|
|
if (isOpposit) {
|
|
axesMap.push({'side' : 'r', 'index' : rightAxes.length, showAxis : showAxis,
|
|
checkBoxChecked : checkBoxChecked});
|
|
rightAxes.push({'index' : i, showAxis : showAxis,
|
|
checkBoxChecked : checkBoxChecked});
|
|
} else {
|
|
if (showAxis) {
|
|
chartConfig.axesArr.leftSideSelected = true;
|
|
}
|
|
axesMap.push({'side' : 'l', 'index' : leftAxes.length, showAxis : showAxis,
|
|
checkBoxChecked : checkBoxChecked});
|
|
leftAxes.push({'index' : i, showAxis : showAxis,
|
|
checkBoxChecked : checkBoxChecked});
|
|
}
|
|
//add axis configuration
|
|
yAxisConf.labelStep = pluckNumber(axisJson.yaxisvaluesstep, axisJson.yaxisvaluestep,
|
|
chartAttrs.yaxisvaluesstep, chartAttrs.yaxisvaluestep);
|
|
yAxisConf.axisMaxValue = axisJson.maxvalue;
|
|
//yAxisConf.tickWidth = tickWidth;
|
|
yAxisConf.axisMinValue = axisJson.minvalue;
|
|
yAxisConf.setAdaptiveMin = pluckNumber(axisJson.setadaptiveymin, chartAttrs.setadaptiveymin);
|
|
yAxisConf.numDivLines = pluckNumber(axisJson.numdivlines, chartAttrs.numdivlines, 4);
|
|
yAxisConf.adjustDiv = pluckNumber(axisJson.adjustdiv, chartAttrs.adjustdiv);
|
|
yAxisConf.showAxisValues = pluckNumber(axisJson.showyaxisvalues,
|
|
axisJson.showyaxisvalue, chartAttrs.showyaxisvalues, chartAttrs.showyaxisvalue, 1);
|
|
yAxisConf.showLimits = pluckNumber(axisJson.showlimits, chartAttrs.showyaxislimits,
|
|
chartAttrs.showlimits, yAxisConf.showAxisValues);
|
|
yAxisConf.showDivLineValues = pluckNumber(axisJson.showdivlinevalue,
|
|
chartAttrs.showdivlinevalues, axisJson.showdivlinevalues,
|
|
yAxisConf.showAxisValues);
|
|
yAxisConf.showZeroPlane = pluckNumber(axisJson.showzeroplane, chartAttrs.showzeroplane);
|
|
yAxisConf.showZeroPlaneValue = pluckNumber(axisJson.showzeroplanevalue,
|
|
chartAttrs.showzeroplanevalue);
|
|
yAxisConf.zeroPlaneColor = axisJson.zeroplanecolor;
|
|
yAxisConf.zeroPlaneThickness = pluckNumber(axisJson.zeroplanethickness, axisJson.divlinethickness,
|
|
chartConfig.zeroplanethickness, 2),
|
|
yAxisConf.zeroPlaneAlpha = pluckNumber(axisJson.zeroplanealpha, axisJson.divlinealpha,
|
|
chartConfig.zeroplanealpha),
|
|
yAxisConf.showZeroPlaneOnTop = chartConfig.showzeroplaneontop,
|
|
yAxisConf.divLineColor = pluck(axisJson.divlinecolor, axisHEXColor);
|
|
yAxisConf.divLineAlpha = pluckNumber(axisJson.divlinealpha, chartAttrs.divlinealpha,
|
|
colorM.getColor(divLineAlphaStr), 100);
|
|
yAxisConf.divLineThickness = gridLineWidth;
|
|
yAxisConf.divLineIsDashed = Boolean (pluckNumber(axisJson.divlinedashed, axisJson.divlineisdashed,
|
|
chartAttrs.divlinedashed, chartAttrs.divlineisdashed, 0));
|
|
yAxisConf.divLineDashLen = pluckNumber(axisJson.divlinedashlen,
|
|
chartAttrs.divlinedashlen, 4);
|
|
yAxisConf.divLineDashGap = pluckNumber(axisJson.divlinedashgap,
|
|
chartAttrs.divlinedashgap, 2);
|
|
|
|
yAxisConf.showAxisLine = 1;
|
|
yAxisConf.axisLineThickness = axisLineThickness;
|
|
yAxisConf.axisLineAlpha = 100;
|
|
yAxisConf.axisLineColor = axisHEXColor;
|
|
yAxisConf.tickLength = tickWidth;
|
|
yAxisConf.tickColor = axisHEXColor;
|
|
yAxisConf.tickAlpha = 100;
|
|
yAxisConf.tickWidth = axisLineThickness;
|
|
yAxisConf.axisName = axisJson.title;
|
|
yAxisConf.rotateAxisName = 1;
|
|
yAxis.setCommonConfigArr ((extend2({},yAxisConf)), true, false, isOpposit);
|
|
yAxis.configure();
|
|
numberFormatter.parseMLAxisConf(axisJson, i);
|
|
if (pluckNumber(axisJson.showaxis) === 0) {
|
|
yAxis.hide();
|
|
yAxis.setAxisConfig({
|
|
axisIndex : i,
|
|
drawAxisLineWRTCanvas : false,
|
|
drawLabels : false,
|
|
drawPlotlines : false,
|
|
drawAxisLine : false,
|
|
drawPlotBands : false,
|
|
drawAxisName : false,
|
|
drawTrendLines : false,
|
|
drawTrendLabels : false,
|
|
drawTick : false,
|
|
drawTickMinor : false
|
|
});
|
|
} else {
|
|
yAxis.show();
|
|
yAxis.setAxisConfig({
|
|
axisIndex : i,
|
|
drawAxisLineWRTCanvas : false,
|
|
drawLabels : true,
|
|
drawPlotlines : true,
|
|
drawAxisLine : true,
|
|
drawPlotBands : true,
|
|
drawAxisName : true,
|
|
drawTrendLines : true,
|
|
drawTrendLabels : true,
|
|
drawTick : true,
|
|
drawTickMinor : true
|
|
});
|
|
}
|
|
count += 1;
|
|
}
|
|
for (i = count, len = components.yAxis.length; i < len; i += 1) {
|
|
components.yAxis[i].hide();
|
|
}
|
|
},
|
|
_setAxisLimits: function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
chartConfig = iapi.config,
|
|
axis = chartConfig.axisDataSetMap,
|
|
dataset = components.dataset,
|
|
yAxis = components.yAxis,
|
|
length = axis.length,
|
|
i,
|
|
infMin = -Infinity,
|
|
infMax = +Infinity,
|
|
max = infMin,
|
|
min = infMax,
|
|
j,
|
|
len,
|
|
maxminObj;
|
|
|
|
for (i=0; i<length; i += 1) {
|
|
for (j = 0, len = axis[i].length; j < len; j += 1) {
|
|
maxminObj = dataset[axis[i][j]].getDataLimits ();
|
|
max = mathMax (max, maxminObj.max);
|
|
min = mathMin (min, maxminObj.min);
|
|
}
|
|
if(min === Infinity) {
|
|
min = 0;
|
|
}
|
|
if(max === -Infinity) {
|
|
max = min + 1;
|
|
}
|
|
yAxis[i].setDataLimit (max, min);
|
|
max = infMin;
|
|
min = infMax;
|
|
}
|
|
|
|
// for (groupManager in groupManagerObj) {
|
|
// yAxisIndex = groupManagerObj[groupManager].yAxisIndex;
|
|
// maxminObj = groupManagerObj[groupManager].getDataLimits ();
|
|
// max = mathMax (max, maxminObj.max);
|
|
// min = mathMin (min, maxminObj.min);
|
|
// sYMax = mathMax (sYMax, maxminObj.sYMax);
|
|
// sYMin = mathMin (sYMin, maxminObj.sYMin);
|
|
// }
|
|
// if (syncAxisLimits) {
|
|
// actualMax = mathMax (max, sYMax);
|
|
// actualMin = mathMin (min, sYMin);
|
|
// yAxis[0].setDataLimit (actualMax, actualMin);
|
|
// yAxis[1].setDataLimit (actualMax, actualMin);
|
|
// }
|
|
// else {
|
|
// max = getSafeValue (max);
|
|
// min = getSafeValue (min);
|
|
// sYMax = getSafeValue (sYMax);
|
|
// sYMin = getSafeValue (sYMin);
|
|
// yAxis[0].setDataLimit (max, min);
|
|
// yAxis[1].setDataLimit (sYMax, sYMin);
|
|
// }
|
|
|
|
// // will give the divline of the active axis
|
|
// divLineCount = yAxis[0].getDivLineCount ();
|
|
// // // setting the inactive axis to forcefully have the same divlines
|
|
// yAxis[1].setAxisConfig ( {
|
|
// numDivLines : divLineCount,
|
|
// adjustDiv : 0
|
|
// });
|
|
// if ((xMax !== infMin) || (xMin !== infMax)) {
|
|
// xAxis[0].config.xaxisrange = {
|
|
// max : xMax,
|
|
// min : xMin
|
|
// };
|
|
// xAxis[0].setDataLimit (xMax, xMin);
|
|
// }
|
|
},
|
|
_spaceManager: function () {
|
|
// todo marge _allocateSpace and _spacemanager
|
|
var spaceForActionBar,
|
|
actionBarSpace,
|
|
availableWidth,
|
|
availableHeight,
|
|
iapi = this,
|
|
config = iapi.config,
|
|
axesArr = config.axesArr,
|
|
components = iapi.components,
|
|
legendPosition = config.legendPosition,
|
|
axis = config.axisDataSetMap,
|
|
xAxis = components.xAxis,
|
|
yAxis = components.yAxis,
|
|
hasLegend = iapi.hasLegend,
|
|
xDepth = config.xDepth,
|
|
yDepth = config.yDepth,
|
|
legend = components.legend,
|
|
canvasBaseDepth = config.canvasBaseDepth,
|
|
canvasBasePadding = config.canvasBasePadding,
|
|
axesPadding = config.axesPadding,
|
|
shift = 0,
|
|
rightPadding = 0,
|
|
leftPadding = 0,
|
|
length = axis.length,
|
|
i,
|
|
yAxisSpaceUsed,
|
|
axesMap,
|
|
leftAxes,
|
|
rightAxes,
|
|
allotedSpace,
|
|
mappedAxis,
|
|
is3d = iapi.is3D,
|
|
chartAttrs = iapi.jsonData.chart,
|
|
showBorder = pluckNumber (chartAttrs.showborder, is3d ? 0 : 1),
|
|
canvasBorderWidth = components.canvas.config.canvasBorderWidth,
|
|
chartBorderWidth =
|
|
config.borderWidth = showBorder ? pluckNumber (chartAttrs.borderthickness, 1) : 0,
|
|
canvasMarginTop = config.canvasMarginTop,
|
|
canvasMarginBottom = config.canvasMarginBottom,
|
|
canvasMarginLeft = config.canvasMarginLeft,
|
|
canvasMarginRight = config.canvasMarginRight,
|
|
minCanvasHeight = config.minCanvasHeight,
|
|
minCanvasWidth = config.minCanvasWidth,
|
|
height = config.height,
|
|
width = config.width,
|
|
diff,
|
|
heightAdjust = false,
|
|
widthAdjust = false,
|
|
top,
|
|
bottom,
|
|
left,
|
|
right,
|
|
currentCanvasHeight,
|
|
currentCanvasWidth,
|
|
origCanvasTopMargin = config.origCanvasTopMargin,
|
|
origCanvasBottomMargin = config.origCanvasBottomMargin,
|
|
origCanvasLeftMargin = config.origCanvasLeftMargin,
|
|
origCanvasRightMargin = config.origCanvasRightMargin,
|
|
sum;
|
|
//****** Manage space
|
|
iapi._allocateSpace ( {
|
|
top : chartBorderWidth,
|
|
bottom : chartBorderWidth,
|
|
left : chartBorderWidth,
|
|
right : chartBorderWidth
|
|
});
|
|
|
|
iapi._allocateSpace ( {
|
|
left : config.canvasMarginLeft,
|
|
right : config.canvasMarginRight
|
|
});
|
|
//****** Manage space
|
|
axesMap = axesArr.axesMap;
|
|
leftAxes = axesArr.leftAxes;
|
|
rightAxes = axesArr.rightAxes;
|
|
if (legendPosition === 'right') {
|
|
allotedSpace = config.canvasWidth * 0.3;
|
|
}
|
|
else {
|
|
allotedSpace = config.canvasHeight * 0.3;
|
|
}
|
|
//No space is allocated for legend drawing in single series charts
|
|
((hasLegend !== false) && xAxis) && iapi._allocateSpace
|
|
(legend._manageLegendPosition (allotedSpace));
|
|
|
|
for (i=0; i<length; i += 1) {
|
|
if (axesMap[i].showaxis === 0) {
|
|
continue;
|
|
}
|
|
availableWidth = config.canvasWidth * 0.7;
|
|
yAxisSpaceUsed = yAxis[i].placeAxis (availableWidth);
|
|
yAxis[i] && iapi._allocateSpace (yAxisSpaceUsed);
|
|
mappedAxis = axesMap[i];
|
|
if (mappedAxis.side === 'r') {
|
|
rightAxes[mappedAxis.index].width = yAxisSpaceUsed.right;
|
|
rightPadding += axesPadding;
|
|
} else {
|
|
leftAxes[mappedAxis.index].width = yAxisSpaceUsed.left;
|
|
leftPadding += axesPadding;
|
|
}
|
|
}
|
|
spaceForActionBar = config.availableHeight * 0.225;
|
|
actionBarSpace = iapi._manageActionBarSpace && iapi._manageActionBarSpace(spaceForActionBar) || {};
|
|
iapi._allocateSpace(actionBarSpace);
|
|
|
|
availableHeight = (legendPosition === POSITION_BOTTOM) ? config.canvasHeight * 0.6 :
|
|
config.canvasWidth * 0.6;
|
|
iapi._manageChartMenuBar(availableHeight);
|
|
availableWidth = config.canvasWidth * 0.7;
|
|
if (availableWidth > (rightPadding + leftPadding)) {
|
|
iapi._allocateSpace ({
|
|
'left' : leftPadding,
|
|
'right' : rightPadding
|
|
});
|
|
}
|
|
availableHeight = config.canvasHeight * 0.6;
|
|
xAxis[0] && iapi._allocateSpace (xAxis[0].placeAxis (availableHeight));
|
|
// alocate the space for datasets
|
|
availableHeight = config.canvasHeight * 0.325;
|
|
iapi._getDSspace && iapi._allocateSpace (iapi._getDSspace (availableHeight));
|
|
|
|
if (yDepth) {
|
|
iapi._allocateSpace ( {
|
|
bottom : yDepth
|
|
});
|
|
shift = xDepth + canvasBasePadding + canvasBaseDepth;
|
|
}
|
|
|
|
iapi._allocateSpace ( {
|
|
top : canvasBorderWidth,
|
|
bottom : canvasBorderWidth,
|
|
left : canvasBorderWidth,
|
|
right : canvasBorderWidth
|
|
});
|
|
// Allocate space for canvas margin only if the margin is less than the margin entered by the user.
|
|
top = canvasMarginTop > config.canvasTop ? (canvasMarginTop - config.canvasTop) : 0;
|
|
bottom = canvasMarginBottom > (height - config.canvasBottom) ?
|
|
(canvasMarginBottom + config.canvasBottom - height) : 0;
|
|
left = canvasMarginLeft > config.canvasLeft ? (canvasMarginLeft - config.canvasLeft) : 0;
|
|
right = canvasMarginRight > (width - config.canvasRight) ?
|
|
(canvasMarginRight + config.canvasRight - width) : 0;
|
|
|
|
iapi._allocateSpace ( {
|
|
top : top,
|
|
bottom : bottom,
|
|
left : left,
|
|
right : right
|
|
});
|
|
// Forcing canvas height to its minimum
|
|
if (heightAdjust) {
|
|
sum = origCanvasTopMargin + origCanvasBottomMargin;
|
|
currentCanvasHeight = config.canvasHeight;
|
|
if (currentCanvasHeight > minCanvasHeight) {
|
|
diff = currentCanvasHeight - minCanvasHeight;
|
|
top = diff * origCanvasTopMargin / sum;
|
|
bottom = diff * origCanvasBottomMargin / sum;
|
|
}
|
|
iapi._allocateSpace ( {
|
|
top : top,
|
|
bottom : bottom
|
|
});
|
|
}
|
|
|
|
// Forcing canvas width to its minimum
|
|
if (widthAdjust) {
|
|
sum = origCanvasLeftMargin + origCanvasRightMargin;
|
|
currentCanvasWidth = config.canvasWidth;
|
|
if (currentCanvasWidth > minCanvasWidth) {
|
|
diff = currentCanvasWidth - minCanvasWidth;
|
|
left = diff * origCanvasLeftMargin / sum;
|
|
right = diff * origCanvasRightMargin / sum;
|
|
}
|
|
iapi._allocateSpace ( {
|
|
left : left,
|
|
right : right
|
|
});
|
|
}
|
|
|
|
config.actualCanvasMarginTop = top;
|
|
config.actualCanvasMarginLeft = left;
|
|
config.actualCanvasMarginRight = right;
|
|
config.actualCanvasMarginBottom = bottom;
|
|
},
|
|
_postSpaceManagement : function () {
|
|
var iapi = this,
|
|
config = iapi.config,
|
|
components = iapi.components,
|
|
xAxis = components.xAxis && components.xAxis[0],
|
|
legend = components.legend,
|
|
xDepth = config.xDepth,
|
|
canvasConfig = components.canvas.config,
|
|
canvasBorderWidth = canvasConfig.canvasBorderWidth,
|
|
canvasPadding = canvasConfig.canvasPadding,
|
|
canvasPaddingLeft = canvasConfig.canvasPaddingLeft,
|
|
canvasPaddingRight = canvasConfig.canvasPaddingRight;
|
|
|
|
xAxis && xAxis.setAxisDimention ( {
|
|
x : config.canvasLeft + (xDepth || 0) + mathMax(canvasPaddingLeft, canvasPadding),
|
|
y : config.canvasBottom + (config.shift || 0) + canvasBorderWidth,
|
|
opposite : config.canvasTop - canvasBorderWidth,
|
|
axisLength : config.canvasWidth - (xDepth || 0) - mathMax(canvasPaddingLeft, canvasPadding) -
|
|
mathMax(canvasPaddingRight, canvasPadding)
|
|
});
|
|
|
|
xAxis && xAxis.shiftLabels (-xDepth, 0);
|
|
legend.postSpaceManager();
|
|
},
|
|
_resuffelAxis : function () {
|
|
var data = this.data('axisDetails'),
|
|
iapi = data.iapi,
|
|
config = iapi.config,
|
|
axesArr = config.axesArr,
|
|
prevAxis,
|
|
axesMap,
|
|
leftAxes,
|
|
rightAxes,
|
|
swapIndex,
|
|
i,
|
|
swapFromIndex;
|
|
|
|
axesMap = axesArr.axesMap;
|
|
leftAxes = axesArr.leftAxes;
|
|
rightAxes = axesArr.rightAxes;
|
|
if (data.position === 'l') {
|
|
|
|
for (i = leftAxes.length - 1; i > data.index; i--) {
|
|
if (leftAxes[i].showAxis) {
|
|
swapIndex = i;
|
|
swapFromIndex = data.index;
|
|
break;
|
|
}
|
|
}
|
|
if (swapIndex !== undefined) {
|
|
prevAxis = extend2({},leftAxes[swapFromIndex]);
|
|
leftAxes[swapFromIndex] = extend2({}, leftAxes[swapIndex]);
|
|
leftAxes[swapIndex] = extend2({}, prevAxis);
|
|
}
|
|
if (axesArr.leftSideSelected && swapIndex === undefined) {
|
|
return;
|
|
}
|
|
axesArr.leftSideSelected = true;
|
|
} else {
|
|
for (i = 0; i < data.index; i++) {
|
|
if (rightAxes[i].showAxis) {
|
|
swapIndex = i;
|
|
swapFromIndex = data.index;
|
|
break;
|
|
}
|
|
}
|
|
if (swapIndex !== undefined) {
|
|
prevAxis = extend2({},rightAxes[swapFromIndex]);
|
|
rightAxes[swapFromIndex] = extend2({}, rightAxes[swapIndex]);
|
|
rightAxes[swapIndex] = extend2({}, prevAxis);
|
|
}
|
|
if (!axesArr.leftSideSelected && swapIndex === undefined) {
|
|
return;
|
|
}
|
|
axesArr.leftSideSelected = false;
|
|
}
|
|
iapi._drawAxis(true);
|
|
},
|
|
_dolegendInteraction : function () {
|
|
var iapi = arguments[1],
|
|
checkbox = this,
|
|
axisIndex = arguments[0],
|
|
dataSets = iapi.components.dataset,
|
|
legend = iapi.components.legend,
|
|
i;
|
|
|
|
if (checkbox.checked) {
|
|
for (i in dataSets) {
|
|
if(dataSets.hasOwnProperty(i)) {
|
|
if (!dataSets[i].visible && dataSets[i].axisIndex === axisIndex) {
|
|
dataSets[i].show();
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for (i in dataSets) {
|
|
if(dataSets.hasOwnProperty(i)) {
|
|
if (dataSets[i].visible && dataSets[i].axisIndex === axisIndex) {
|
|
dataSets[i].hide();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
legend.drawLegend();
|
|
},
|
|
_drawAxis : function (onlyY) {
|
|
var iapi = this,
|
|
config = iapi.config,
|
|
axesArr = config.axesArr,
|
|
components = iapi.components,
|
|
yAxis = components.yAxis || [],
|
|
xAxis = components.xAxis || [],
|
|
paper = components.paper,
|
|
allowAxisShift = config.allowAxisShift,
|
|
allowSelection = config.allowSelection,
|
|
axisHotElement = iapi.graphics.axisHotElement || [],
|
|
trackerContainer = iapi.graphics.trackerContainer,
|
|
checkBoxContainer = iapi.graphics.buttonGroup,
|
|
canvasConfig = components.canvas.config,
|
|
canvasBorderWidth = canvasConfig.canvasBorderWidth,
|
|
canvasPaddingTop = canvasConfig.canvasPaddingTop,
|
|
canvasPaddingBottom = canvasConfig.canvasPaddingBottom,
|
|
axesPadding = config.axesPadding,
|
|
tb = this.components.tb,
|
|
leftPadding = 0,
|
|
rightPadding = 0,
|
|
counter = 0,
|
|
x,
|
|
y,
|
|
height,
|
|
width,
|
|
eventI,
|
|
eventLen,
|
|
axesMap,
|
|
leftAxes,
|
|
rightAxes,
|
|
i,
|
|
length,
|
|
axis,
|
|
attr,
|
|
hotElement,
|
|
toolBox,
|
|
toolBoxAPI,
|
|
CheckboxSymbol,
|
|
axisNamePadding,
|
|
animationDuration,
|
|
transposeAnimDuration,
|
|
animType,
|
|
axisIndex,
|
|
checkboxes,
|
|
checkbox,
|
|
transposeX,
|
|
transposeY,
|
|
checkboxTopPadding = 4,
|
|
isSelectedDrawn = false,
|
|
cbIdCount = 0,
|
|
animObj,
|
|
dummyObj;
|
|
|
|
animationDuration = iapi.get(configStr, animationObjStr);
|
|
animObj = animationDuration.animObj;
|
|
dummyObj = animationDuration.dummyObj;
|
|
transposeAnimDuration = animationDuration.transposeAnimDuration;
|
|
animType = animationDuration.animType;
|
|
toolBox = components.tb || (components.tb =
|
|
new (FusionCharts.register(COMPONENT, ['toolbox', 'toolbox']))());
|
|
toolBox.init({
|
|
iAPI: iapi,
|
|
graphics: iapi.graphics,
|
|
chart: iapi,
|
|
components: components
|
|
});
|
|
toolBoxAPI = components.toolBoxAPI;
|
|
CheckboxSymbol = toolBoxAPI.CheckboxSymbol;
|
|
axesMap = axesArr.axesMap;
|
|
leftAxes = axesArr.leftAxes;
|
|
rightAxes = axesArr.rightAxes;
|
|
checkboxes = axesArr.checkBox;
|
|
for (i in checkboxes) {
|
|
if (checkboxes.hasOwnProperty(i)) {
|
|
checkboxes[i].checkbox.hide();
|
|
}
|
|
}
|
|
attr = {
|
|
cursor: 'col-resize',
|
|
stroke: TRACKER_FILL,
|
|
fill: TRACKER_FILL,
|
|
ishot: true,
|
|
visibility: true
|
|
};
|
|
for (length = i = leftAxes.length - 1; i >= 0; i -= 1) {
|
|
if (leftAxes[i].showAxis === 0) {
|
|
continue;
|
|
}
|
|
x = config.canvasLeft - canvasBorderWidth - leftPadding - axesPadding;
|
|
y = config.canvasTop + canvasPaddingTop;
|
|
height = config.canvasHeight - canvasPaddingTop - canvasPaddingBottom;
|
|
width = leftAxes[i].width;
|
|
axisIndex = leftAxes[i].index;
|
|
axis = yAxis[axisIndex];
|
|
axis.setAxisDimention ( {
|
|
x : x,
|
|
y : y,
|
|
opposite : config.canvasRight + canvasBorderWidth,
|
|
axisLength : height
|
|
});
|
|
leftPadding += width + axesPadding;
|
|
if (!isSelectedDrawn && axesArr.leftSideSelected) {
|
|
axis.setAxisConfig({
|
|
'isActive' : true,
|
|
'axisNameAlignCanvas' : true,
|
|
'drawAxisNameFromBottom' : true
|
|
});
|
|
isSelectedDrawn = true;
|
|
} else {
|
|
axis.setAxisConfig({
|
|
'isActive' : false,
|
|
'axisNameAlignCanvas' : true,
|
|
'drawAxisNameFromBottom' : true
|
|
});
|
|
}
|
|
|
|
if (allowSelection) {
|
|
if (!checkboxes[axisIndex]) {
|
|
checkbox = checkboxes[axisIndex] = {};
|
|
checkbox.checkbox = new CheckboxSymbol(BLANKSTRING, true, cbIdCount++, tb.pId);
|
|
checkbox.checkbox.conf = toolBox.getDefaultConfiguration();
|
|
|
|
checkbox.checkbox.attachEventHandlers({
|
|
click : {
|
|
fn : iapi._dolegendInteraction,
|
|
args : [axisIndex, iapi]
|
|
}
|
|
});
|
|
|
|
checkbox.checkbox.draw(x - width, y + height + checkboxTopPadding, {
|
|
parentLayer: checkBoxContainer
|
|
});
|
|
checkbox.checkboxPrePos = {
|
|
x : x - width,
|
|
y : y + height + checkboxTopPadding
|
|
};
|
|
} else {
|
|
checkbox = checkboxes[axisIndex];
|
|
transposeX = (x - width) - (checkboxes[axisIndex].checkboxPrePos.x);
|
|
transposeY = (y + height + checkboxTopPadding) - (checkboxes[axisIndex].checkboxPrePos.y);
|
|
checkbox.checkbox.show();
|
|
checkbox.checkbox.attachEventHandlers({
|
|
click : {
|
|
fn : iapi._dolegendInteraction,
|
|
args : [axisIndex, iapi]
|
|
}
|
|
});
|
|
if (transposeAnimDuration) {
|
|
checkbox.checkbox.node.animateWith(dummyObj, animObj,
|
|
{transform: 't'+transposeX+COMMA+transposeY},
|
|
transposeAnimDuration, animType);
|
|
} else {
|
|
checkbox.checkbox.node.attr({transform: 't'+transposeX+COMMA+transposeY});
|
|
}
|
|
}
|
|
checkbox.checkbox.node.attr({
|
|
stroke : toRaphaelColor({
|
|
color: config.checkBoxColor,
|
|
alpha: 100
|
|
})
|
|
});
|
|
|
|
checkbox.checkbox.node.attr({
|
|
'stroke-width' : [1, 2]
|
|
});
|
|
if (config.axisConfigured) {
|
|
if (leftAxes[i].checkBoxChecked) {
|
|
checkbox.checkbox.check();
|
|
} else {
|
|
checkbox.checkbox.uncheck();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (allowAxisShift) {
|
|
attr.x = x - width;
|
|
attr.y = y;
|
|
attr.width = width;
|
|
attr.height = height;
|
|
// Creating the hot element if not created
|
|
if (axisHotElement[counter]) {
|
|
hotElement = axisHotElement[counter].attr(attr);
|
|
hotElement.show();
|
|
// remove the events from the elements
|
|
for (eventI = 0, eventLen = hotElement.events.length; eventI < eventLen; eventI++ ) {
|
|
hotElement.events[eventI].unbind();
|
|
hotElement.events.splice(eventI, 1);
|
|
eventLen -= 1;
|
|
}
|
|
}
|
|
else {
|
|
hotElement = axisHotElement[counter] = paper.rect(attr, trackerContainer);
|
|
}
|
|
|
|
hotElement
|
|
.data('axisDetails', {
|
|
iapi : iapi,
|
|
position : 'l',
|
|
index : i
|
|
});
|
|
if (hasTouch) {
|
|
hotElement.touchstart(iapi._resuffelAxis);
|
|
} else {
|
|
hotElement.mousedown(iapi._resuffelAxis);
|
|
}
|
|
|
|
counter += 1;
|
|
}
|
|
|
|
}
|
|
for (i = 0, length = rightAxes.length; i < length; i += 1 ) {
|
|
if (rightAxes[i].showAxis === 0) {
|
|
continue;
|
|
}
|
|
axisIndex = rightAxes[i].index;
|
|
axis = yAxis[axisIndex];
|
|
x = config.canvasRight + canvasBorderWidth + rightPadding + axesPadding;
|
|
y = config.canvasTop + canvasPaddingTop;
|
|
height = config.canvasHeight - canvasPaddingTop - canvasPaddingBottom;
|
|
width = rightAxes[i].width;
|
|
axis.setAxisDimention ( {
|
|
x : x,
|
|
y : y,
|
|
opposite : config.canvasLeft - canvasBorderWidth,
|
|
axisLength : height
|
|
});
|
|
rightPadding += rightAxes[i].width + axesPadding;
|
|
if (!isSelectedDrawn && !axesArr.leftSideSelected) {
|
|
axis.setAxisConfig({
|
|
'isActive' : true,
|
|
'axisNameAlignCanvas' : true,
|
|
'drawAxisNameFromBottom' : true
|
|
});
|
|
isSelectedDrawn = true;
|
|
} else {
|
|
axis.setAxisConfig({
|
|
'isActive' : false,
|
|
'axisNameAlignCanvas' : true,
|
|
'drawAxisNameFromBottom' : true
|
|
});
|
|
}
|
|
axisNamePadding = axis.getAxisConfig('axisNamePadding');
|
|
if (allowSelection) {
|
|
if (!checkboxes[axisIndex]) {
|
|
checkbox = checkboxes[axisIndex] = {};
|
|
checkbox.checkbox = new CheckboxSymbol(BLANKSTRING, true, cbIdCount++, tb.pId);
|
|
checkbox.checkbox.conf = toolBox.getDefaultConfiguration();
|
|
checkbox.checkbox.attachEventHandlers({
|
|
click : {
|
|
fn : iapi._dolegendInteraction,
|
|
args : [axisIndex, iapi]
|
|
}
|
|
});
|
|
checkbox.checkbox.draw(x + axisNamePadding, y + height + checkboxTopPadding, {
|
|
parentLayer: checkBoxContainer
|
|
});
|
|
checkbox.checkboxPrePos = {
|
|
x : x - width,
|
|
y : y + height + checkboxTopPadding
|
|
};
|
|
} else {
|
|
checkbox = checkboxes[axisIndex];
|
|
transposeX = (x - width) - (checkbox.checkboxPrePos.x);
|
|
transposeY = (y + height + checkboxTopPadding) - (checkbox.checkboxPrePos.y);
|
|
checkbox.checkbox.show();
|
|
checkbox.checkbox.attachEventHandlers({
|
|
click : {
|
|
fn : iapi._dolegendInteraction,
|
|
args : [axisIndex, iapi]
|
|
}
|
|
});
|
|
if (transposeAnimDuration) {
|
|
checkbox.checkbox.node.animateWith(dummyObj, animObj,
|
|
{transform: 't'+transposeX+COMMA+transposeY},
|
|
transposeAnimDuration, animType);
|
|
} else {
|
|
checkbox.checkbox.node.attr({transform: 't'+transposeX+COMMA+transposeY});
|
|
}
|
|
}
|
|
checkbox.checkbox.node.attr({
|
|
stroke : toRaphaelColor({
|
|
color: config.checkBoxColor,
|
|
alpha: 100
|
|
})
|
|
});
|
|
|
|
checkbox.checkbox.node.attr({
|
|
'stroke-width' : [1, 2]
|
|
});
|
|
if (config.axisConfigured) {
|
|
if (rightAxes[i].checkBoxChecked) {
|
|
checkbox.checkbox.check();
|
|
} else {
|
|
checkbox.checkbox.uncheck();
|
|
}
|
|
}
|
|
}
|
|
if (allowAxisShift) {
|
|
attr.x = x;
|
|
attr.y = y;
|
|
attr.width = width;
|
|
attr.height = height;
|
|
// Creating the hot element if not created
|
|
if (axisHotElement[counter]) {
|
|
hotElement = axisHotElement[counter].attr(attr);
|
|
hotElement.show();
|
|
// remove the events from the elements
|
|
for (eventI = 0, eventLen = hotElement.events.length; eventI < eventLen; eventI++ ) {
|
|
hotElement.events[eventI].unbind();
|
|
hotElement.events.splice(eventI, 1);
|
|
eventLen -= 1;
|
|
}
|
|
}
|
|
else {
|
|
hotElement = axisHotElement[counter] = paper.rect(attr, trackerContainer);
|
|
}
|
|
hotElement
|
|
.data('axisDetails', {
|
|
iapi : iapi,
|
|
position : 'r',
|
|
index : i
|
|
});
|
|
if (hasTouch) {
|
|
hotElement.touchstart(iapi._resuffelAxis);
|
|
} else {
|
|
hotElement.mousedown(iapi._resuffelAxis);
|
|
}
|
|
|
|
counter += 1;
|
|
}
|
|
}
|
|
iapi.graphics.axisHotElement = axisHotElement;
|
|
for (i = counter, length = axisHotElement.length; i < length; i += 1) {
|
|
axisHotElement[i].hide();
|
|
}
|
|
if (!onlyY) {
|
|
for (i = 0, length = xAxis.length; i < length; i++) {
|
|
xAxis[i].draw ();
|
|
}
|
|
}
|
|
for (i = 0, length = yAxis.length; i < length; i++) {
|
|
yAxis[i].draw ();
|
|
}
|
|
config.axisConfigured = false;
|
|
}
|
|
|
|
}, chartAPI.mscartesian, {
|
|
enablemousetracking: true
|
|
}, chartAPI.areabase);
|
|
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-inversemsline', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI,
|
|
preDefStr = lib.preDefStr,
|
|
LINE = preDefStr.line;
|
|
|
|
chartAPI('inversemsline', {
|
|
friendlyName: 'Inverted Y-Axis Multi-series Line Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType: LINE,
|
|
defaultPlotShadow: 1,
|
|
applicableDSList: {LINE: true}
|
|
}, chartAPI.msinversecartesian, {
|
|
zeroplanethickness: 1,
|
|
zeroplanealpha: 40,
|
|
showzeroplaneontop: 0,
|
|
enablemousetracking: true
|
|
}, chartAPI.areabase);
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-inversemsarea', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI;
|
|
|
|
chartAPI('inversemsarea', {
|
|
friendlyName: 'Inverted Y-Axis Multi-series Area Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType: 'area',
|
|
applicableDSList: {'area': true}
|
|
}, chartAPI.msinversecartesian, {
|
|
enablemousetracking: true
|
|
}, chartAPI.areabase);
|
|
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-inversemscolumn2d', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI,
|
|
preDefStr = lib.preDefStr,
|
|
COLUMN = preDefStr.column;
|
|
|
|
chartAPI('inversemscolumn2d', {
|
|
friendlyName: 'Inverted Y-Axis Multi-series Column Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType: COLUMN,
|
|
applicableDSList: {COLUMN: true},
|
|
isInverse : true
|
|
}, chartAPI.msinversecartesian, {
|
|
enablemousetracking: true
|
|
});
|
|
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-logmsline', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
preDefStr = lib.preDefStr,
|
|
LINE = preDefStr.line,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI;
|
|
|
|
chartAPI('logmsline', {
|
|
standaloneInit: true,
|
|
friendlyName: 'Multi-series Line Chart',
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType : LINE,
|
|
defaultPlotShadow: 1,
|
|
applicableDSList: {LINE: true}
|
|
}, chartAPI.mslog, {
|
|
zeroplanethickness: 1,
|
|
enablemousetracking: true,
|
|
zeroplanealpha: 40,
|
|
showzeroplaneontop: 0
|
|
}, chartAPI.areabase);
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-logmscolumn2d', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
preDefStr = lib.preDefStr,
|
|
COLUMN = preDefStr.column,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI;
|
|
chartAPI('logmscolumn2d', {
|
|
friendlyName: 'Multi-series Log Column Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType: COLUMN,
|
|
applicableDSList: {COLUMN: true}
|
|
}, chartAPI.mslog, {
|
|
enablemousetracking: true
|
|
});
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-logstackedcolumn2d', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI;
|
|
|
|
chartAPI('logstackedcolumn2d', {
|
|
friendlyName: 'Stacked Log Column Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel
|
|
}, chartAPI.logmscolumn2d, {
|
|
isstacked: true
|
|
});
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-errorbar2d', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI;
|
|
|
|
chartAPI('errorbar2d', {
|
|
friendlyName: 'Error Bar Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
showValues: 0,
|
|
isErrorChart: true,
|
|
fireGroupEvent: true,
|
|
hasLegend: true,
|
|
defaultDatasetType : 'errorbar2d',
|
|
applicableDSList: {'errorbar2d': true},
|
|
eiMethods : { }
|
|
}, chartAPI.mscartesian, {
|
|
enablemousetracking: true
|
|
});
|
|
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-errorline', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI;
|
|
|
|
chartAPI('errorline', {
|
|
friendlyName: 'Error Line Chart',
|
|
useErrorGroup: true,
|
|
isErrorChart: true,
|
|
fireGroupEvent: true,
|
|
creditLabel: creditLabel,
|
|
defaultPlotShadow: 1,
|
|
axisPaddingLeft: 0,
|
|
axisPaddingRight: 0,
|
|
canvasPaddingModifiers: ['anchor', 'errorbar'],
|
|
defaultDatasetType : 'errorline',
|
|
applicableDSList: {'errorline': true}
|
|
}, chartAPI.mscartesian, {
|
|
zeroplanethickness: 1,
|
|
zeroplanealpha: 40,
|
|
showzeroplaneontop: 0,
|
|
enablemousetracking: true
|
|
}, chartAPI.areabase);
|
|
}]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-errorscatter', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
chartAPI = lib.chartAPI,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);
|
|
|
|
chartAPI('errorscatter', {
|
|
friendlyName: 'Error Scatter Chart',
|
|
isXY: true,
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType: 'errorscatter',
|
|
applicableDSList: {'errorscatter': true},
|
|
defaultZeroPlaneHighlighted: false,
|
|
useErrorGroup: true,
|
|
isErrorChart: true,
|
|
fireGroupEvent: true,
|
|
initAnimation: true
|
|
}, chartAPI.scatterBase, {
|
|
enablemousetracking: true
|
|
});
|
|
}]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-waterfall2d', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
chartAPI = lib.chartAPI,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname),
|
|
each = lib.each,
|
|
TRUE_STRING = 'true',
|
|
ONE_STRING = '1';
|
|
|
|
//In the new architechture, changing the rendererId and setting a flag true for singleSeries.
|
|
chartAPI('waterfall2d', {
|
|
standaloneInit: true,
|
|
friendlyName: 'Waterfall Chart',
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType : 'Waterfall2D',
|
|
applicableDSList: {
|
|
'Waterfall2D': true
|
|
},
|
|
singleseries: true,
|
|
hasLegend: false,
|
|
/*
|
|
* Seggregates the original data to data and vline.
|
|
* @param data: Original data used for seggregation.
|
|
* @return Object: JSON data to be used further by the child components, e.g. dataSet.
|
|
*/
|
|
_dataSegregator: function (data) {
|
|
var dataOnlyArr = [],
|
|
catOnlyArr = [];
|
|
|
|
each (data, function (data, i) {
|
|
if (!(data.vline === TRUE_STRING || data.vline === true || data.vline === 1 ||
|
|
data.vline === ONE_STRING)) {
|
|
dataOnlyArr.push (data);
|
|
}
|
|
else {
|
|
catOnlyArr.push({
|
|
index: i,
|
|
data: data
|
|
});
|
|
}
|
|
});
|
|
return {
|
|
data: dataOnlyArr,
|
|
catData: catOnlyArr
|
|
};
|
|
}
|
|
}, chartAPI.sscartesian, {
|
|
enablemousetracking: true
|
|
});
|
|
}]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-multilevelpie', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
chartAPI = lib.chartAPI,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname),
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
preDefStr = lib.preDefStr,
|
|
sStr = preDefStr.sStr,
|
|
pluck = lib.pluck,
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
UNDEFINED;
|
|
|
|
/////////////// MultiLevelPie ///////////
|
|
///function to add mspie data
|
|
chartAPI('multilevelpie', {
|
|
standaloneInit: true,
|
|
friendlyName: 'Multi-level Pie Chart',
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType : 'multiLevelPie',
|
|
applicableDSList: {
|
|
'multiLevelPie': true
|
|
},
|
|
is3d: true,
|
|
//disable legend
|
|
hasLegend: false,
|
|
hasCanvas: false,
|
|
_createDatasets : function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
//graphics = iapi.graphics,
|
|
//datasetGroup = graphics.datasetGroup,
|
|
dataObj = iapi.jsonData,
|
|
dataset = dataObj.dataset || [],
|
|
length = dataset.length,
|
|
i,
|
|
//j,
|
|
//subDataset,
|
|
datasetStore,
|
|
datasetObj,
|
|
//subDatasetLen,
|
|
defaultSeriesType = iapi.defaultDatasetType,
|
|
applicableDSList = iapi.applicableDSList,
|
|
dsType,
|
|
DsClass,
|
|
datasetJSON,
|
|
parentyaxis,
|
|
categories = [],
|
|
catLength,
|
|
dsCount = {};
|
|
|
|
categories = (iapi.config.categories = dataObj.category || []);
|
|
catLength = categories.length;
|
|
|
|
if(!length && catLength){
|
|
dataset = categories;
|
|
length = catLength;
|
|
}
|
|
// if the data has no categories in them.
|
|
if (!catLength) {
|
|
iapi.setChartMessage();
|
|
}
|
|
datasetStore = components.dataset || (components.dataset = []);
|
|
|
|
for(i = 0; i < length; i += 1) {
|
|
|
|
datasetJSON = dataset[i];
|
|
datasetJSON.seriesname && (datasetJSON.seriesname = parseUnsafeString(datasetJSON.seriesname));
|
|
parentyaxis = datasetJSON.parentyaxis || BLANKSTRING;
|
|
if (parentyaxis.toLowerCase() === sStr) {
|
|
dsType = pluck(datasetJSON.renderas, iapi.sDefaultDatasetType);
|
|
}
|
|
else {
|
|
dsType = pluck(datasetJSON.renderas, defaultSeriesType);
|
|
}
|
|
dsType = dsType && dsType.toLowerCase();
|
|
if (!applicableDSList[dsType]) {
|
|
dsType = defaultSeriesType;
|
|
}
|
|
|
|
/// get the DsClass
|
|
DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
|
|
if (DsClass) {
|
|
if (dsCount[dsType] === UNDEFINED) {
|
|
dsCount[dsType] = 0;
|
|
}
|
|
else {
|
|
dsCount[dsType]++;
|
|
}
|
|
// If the dataset does not exists.
|
|
if (!datasetStore[0]) {
|
|
// create the dataset Object
|
|
datasetObj = new DsClass ();
|
|
datasetStore.push (datasetObj);
|
|
datasetObj.chart = iapi;
|
|
datasetObj.index = i;
|
|
}
|
|
else {
|
|
datasetObj = datasetStore[0];
|
|
datasetObj.JSONData = datasetJSON;
|
|
}
|
|
datasetObj.init (dataset);
|
|
}
|
|
}
|
|
},
|
|
_spaceManager: function () {
|
|
var availableHeight,
|
|
iapi = this,
|
|
config = iapi.config;
|
|
//****** Manage space
|
|
iapi._allocateSpace(iapi._manageActionBarSpace &&
|
|
iapi._manageActionBarSpace(config.availableHeight * 0.225) || {});
|
|
availableHeight = config.canvasHeight * 0.7;
|
|
// a space manager that manages the space for the tools as well as the captions.
|
|
iapi._manageChartMenuBar(availableHeight);
|
|
}
|
|
}, chartAPI.guageBase);
|
|
}]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-radar', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
chartAPI = lib.chartAPI,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);
|
|
|
|
/*--/ Chart Api for Radar /--*/
|
|
chartAPI('radar', {
|
|
friendlyName: 'Radar Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType : 'radar',
|
|
applicableDSList: {'radar': true},
|
|
hasLegend: true,
|
|
areaAlpha: 50,
|
|
defaultPlotShadow: 0,
|
|
_postSpaceManagement : function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
config = iapi.config,
|
|
yAxis = components.yAxis && components.yAxis[0],
|
|
legend = components.legend;
|
|
|
|
yAxis.setAxisDimention ( {
|
|
x : config.canvasLeft + config.canvasWidth/2,
|
|
y : config.canvasTop,
|
|
axisLength : config.canvasHeight/2
|
|
});
|
|
legend.postSpaceManager();
|
|
},
|
|
_mouseEvtHandler: function (e) {
|
|
return chartAPI.dragbase._mouseEvtHandler.call(this, e);
|
|
}
|
|
|
|
}, chartAPI.mspolar, {
|
|
radarradius: 0,
|
|
radarborderthickness: 2,
|
|
showvalues: 0,
|
|
plotfillalpha: 50,
|
|
enablemousetracking: true
|
|
}, chartAPI.areabase);
|
|
}]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dragbase', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
doc = win.document,
|
|
preDefStr = lib.preDefStr,
|
|
colorStrings = preDefStr.colors,
|
|
COLOR_FFFFFF = colorStrings.FFFFFF,
|
|
ZEROSTRING = lib.ZEROSTRING,
|
|
UNDERSCORE = preDefStr.UNDERSCORE,
|
|
BLANK = lib.BLANKSTRING,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
getValidValue = lib.getValidValue,
|
|
pluckNumber = lib.pluckNumber,
|
|
extend2 = lib.extend2,
|
|
hasSVG = lib.hasSVG,
|
|
isIE = lib.isIE,
|
|
dropHash = lib.regex.dropHash,
|
|
HASHSTRING = lib.HASHSTRING,
|
|
NONE = 'none',
|
|
PXSTRING = 'px',
|
|
schedular = lib.schedular,
|
|
priorityList = lib.priorityList,
|
|
extend = function(a, b) {
|
|
var n;
|
|
if (!a) {
|
|
a = {};
|
|
}
|
|
for (n in b) {
|
|
a[n] = b[n];
|
|
}
|
|
return a;
|
|
},
|
|
MOUSEOUT = 'mouseout',
|
|
MOUSEMOVE = 'mousemove',
|
|
COMPONENT = 'component',
|
|
addEvent = lib.addEvent,
|
|
removeEvent = lib.removeEvent,
|
|
PX = PXSTRING,
|
|
math = Math,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
hasTouch = lib.hasTouch,
|
|
convertColor = lib.graphics.convertColor,
|
|
chartAPI = lib.chartAPI,
|
|
xssEncode = global.xssEncode,
|
|
createElement = lib.createElement;
|
|
|
|
chartAPI('dragbase', {
|
|
configure: function () {
|
|
var iapi = this,
|
|
jsonData = iapi.jsonData,
|
|
chartAttr = jsonData.chart,
|
|
fontSize,
|
|
chartConfig;
|
|
iapi.base.base.configure.call(this);
|
|
chartConfig = iapi.config;
|
|
chartConfig.formAction = getValidValue(chartAttr.formaction);
|
|
|
|
if (chartAttr.submitdataasxml === ZEROSTRING && !chartAttr.formdataformat) {
|
|
chartAttr.formdataformat = global.dataFormats.CSV;
|
|
}
|
|
|
|
chartConfig.formDataFormat = pluck(chartAttr.formdataformat,
|
|
global.dataFormats.XML);
|
|
chartConfig.formTarget = pluck(chartAttr.formtarget, '_self');
|
|
chartConfig.formMethod = pluck(chartAttr.formmethod, 'POST');
|
|
chartConfig.submitFormAsAjax = pluckNumber(chartAttr.submitformusingajax, 1);
|
|
chartConfig.restoreBtnTitle = pluck(chartAttr.restorebtntitle, 'Restore');
|
|
chartConfig.submitBtnTitle = pluck(chartAttr.formbtntitle, 'Submit');
|
|
|
|
// Form Button
|
|
chartConfig.showFormBtn = pluckNumber(chartAttr.showformbtn, 1) && chartConfig.formAction;
|
|
chartConfig.showRestoreBtn = pluckNumber(chartAttr.showrestorebtn, 1);
|
|
chartConfig.formBtnTitle = pluck(chartAttr.formbtntitle, 'Submit');
|
|
chartConfig.formBtnBorderColor = pluck(chartAttr.formbtnbordercolor, 'CBCBCB');
|
|
chartConfig.formBtnBgColor = pluck(chartAttr.formbtnbgcolor, COLOR_FFFFFF);
|
|
chartConfig.btnPadding = pluckNumber(chartAttr.btnpadding, 7); //2 px more for better presentation
|
|
chartConfig.btnSpacing = pluckNumber(chartAttr.btnspacing, 5);
|
|
chartConfig.formBtnStyle = {
|
|
fontSize: chartConfig.style.outCanfontSize,
|
|
fontFamily: chartConfig.style.outCanfontFamily,
|
|
fontWeight: 'bold'
|
|
};
|
|
chartConfig.formBtnLabelFill = chartConfig.style.outCancolor;
|
|
if (chartAttr.btntextcolor) {
|
|
chartConfig.formBtnLabelFill = chartAttr.btntextcolor.replace(dropHash, HASHSTRING);
|
|
}
|
|
if ((fontSize = pluckNumber(chartAttr.btnfontsize)) >= 0) {
|
|
chartConfig.formBtnStyle.fontSize = fontSize + PX;
|
|
}
|
|
chartConfig.restoreBtnWidth = pluckNumber(chartAttr.restorebtnwidth, 0);
|
|
chartConfig.formBtnWidth = pluckNumber(chartAttr.formbtnwidth, 0);
|
|
// Restore Button configuration
|
|
chartConfig.restoreBtnBorderColor = pluck(chartAttr.restorebtnbordercolor,
|
|
chartConfig.formBtnBorderColor);
|
|
chartConfig.restoreBtnBgColor = pluck(chartAttr.restorebtnbgcolor,
|
|
chartConfig.formBtnBgColor);
|
|
chartConfig.restoreBtnStyle = {
|
|
fontSize: chartConfig.formBtnStyle.fontSize,
|
|
fontFamily: chartConfig.formBtnStyle.fontFamily,
|
|
fontWeight: 'bold'
|
|
};
|
|
chartConfig.restoreBtnLabelFill = chartConfig.formBtnLabelFill;
|
|
if (chartAttr.toolbary || chartAttr.toolbarx) {
|
|
chartConfig.spaceHardCoded = true;
|
|
}
|
|
else {
|
|
delete chartConfig.spaceHardCoded;
|
|
}
|
|
},
|
|
_createToolBox: function () {
|
|
var chart = this,
|
|
toolBox = chart.components.tb || (chart.components.tb =
|
|
new (FusionCharts.register(COMPONENT, ['toolbox', 'toolbox']))()),
|
|
toolBoxAPI, conf, SymbolStore, ComponentGroup, HorizontalToolbar,
|
|
components = chart.components,
|
|
buttonGroup,
|
|
submitBtn,
|
|
toolConf,
|
|
toolbox,
|
|
Symbol,
|
|
restoreBtn,
|
|
SmartLabel = chart.linkedItems.smartLabel,
|
|
chartConf = chart.config,
|
|
SymbolWithContext,
|
|
showRestoreBtn = chartConf.showRestoreBtn,
|
|
formAction = chartConf.formAction,
|
|
restoreBtnTitle = chartConf.restoreBtnTitle,
|
|
submitBtnTitle = chartConf.submitBtnTitle,
|
|
formBtnStyle = chartConf.formBtnStyle,
|
|
restoreBtnStyle = chartConf.restoreBtnStyle,
|
|
restoreBtnWidth = chartConf.restoreBtnWidth,
|
|
restoreBtnBgColor = chartConf.restoreBtnBgColor,
|
|
restoreBtnBorderColor = chartConf.restoreBtnBorderColor,
|
|
formBtnBgColor = chartConf.formBtnBgColor,
|
|
formBtnBorderColor = chartConf.formBtnBorderColor,
|
|
restoreBtnLabelFill = chartConf.restoreBtnLabelFill,
|
|
formBtnLabelFill = chartConf.formBtnLabelFill,
|
|
btnSpacing = chartConf.btnSpacing,
|
|
padding = chartConf.btnPadding,
|
|
formBtnWidth = chartConf.formBtnWidth,
|
|
formBtnHeight,
|
|
restoreBtnHeight,
|
|
chartMenuBar = components.chartMenuBar,
|
|
dimensions,
|
|
actionBar = components.actionBar,
|
|
pId;
|
|
/* Do not reconfigure the toolbox if its already drawn.
|
|
This flag is set falsy on each time configurations
|
|
are updated. */
|
|
if (chartMenuBar && chartMenuBar.drawn || actionBar && actionBar.drawn) {
|
|
return;
|
|
}
|
|
pId = toolBox.init({
|
|
graphics: chart.graphics || (chart.graphics = {}),
|
|
chart: chart,
|
|
components: chart.components
|
|
});
|
|
|
|
toolBox.pId = pId;
|
|
|
|
toolBoxAPI = components.toolBoxAPI = toolBox.getAPIInstances(toolBox.ALIGNMENT_HORIZONTAL);
|
|
SymbolStore = toolBoxAPI.SymbolStore;
|
|
ComponentGroup = toolBoxAPI.ComponentGroup;
|
|
HorizontalToolbar = toolBoxAPI.Toolbar;
|
|
Symbol = toolBoxAPI.Symbol;
|
|
SymbolWithContext = toolBoxAPI.SymbolWithContext;
|
|
toolConf = toolBox.getDefaultConfiguration();
|
|
conf = toolBox.getDefaultConfiguration();
|
|
restoreBtn = new Symbol(restoreBtnTitle, true, (toolBox.idCount = toolBox.idCount || 0,
|
|
toolBox.idCount++), toolBox.pId);
|
|
submitBtn = new Symbol(submitBtnTitle, true, toolBox.idCount++, toolBox.pId);
|
|
|
|
chartAPI.mscartesian._createToolBox.call(chart);
|
|
|
|
if (chartConf.spaceHardCoded) {
|
|
// preference is given to the chartMenuBar, if not exist, its the action bar.
|
|
actionBar = components.actionBar = components.chartMenuBar || components.actionBar;
|
|
}
|
|
if (!(actionBar = components.actionBar)) {
|
|
toolbox = new HorizontalToolbar(toolBox.idCount++, toolBox.pId);
|
|
actionBar = (components.actionBar = toolbox);
|
|
}
|
|
|
|
chart.addConfigureOptions && chart.addConfigureOptions();
|
|
|
|
buttonGroup = new ComponentGroup(toolBox.idCount++, toolBox.pId);
|
|
SmartLabel.useEllipsesOnOverflow(chartConf.useEllipsesWhenOverflow);
|
|
SmartLabel.setStyle(restoreBtnStyle);
|
|
dimensions = SmartLabel.getOriSize(restoreBtnTitle);
|
|
restoreBtnWidth = mathMax(dimensions.width, restoreBtnWidth);
|
|
restoreBtnHeight = dimensions.height;
|
|
SmartLabel.setStyle(formBtnStyle);
|
|
dimensions = SmartLabel.getOriSize(submitBtnTitle);
|
|
formBtnWidth = mathMax(formBtnWidth, dimensions.width);
|
|
formBtnHeight = dimensions.height;
|
|
restoreBtn.conf.width = restoreBtnWidth + padding;
|
|
submitBtn.conf.width = formBtnWidth + padding;
|
|
restoreBtn.conf.stroke = convertColor(restoreBtnBorderColor, 100);
|
|
restoreBtn.conf.height = restoreBtnHeight + padding;
|
|
submitBtn.conf.height = formBtnHeight + padding;
|
|
submitBtn.conf.fill = convertColor(formBtnBgColor, 100);
|
|
submitBtn.conf.labelFill = convertColor(formBtnLabelFill, 100);
|
|
restoreBtn.conf.fill = convertColor(restoreBtnBgColor, 100);
|
|
restoreBtn.conf.labelFill = convertColor(restoreBtnLabelFill, 100);
|
|
submitBtn.conf.stroke = convertColor(formBtnBorderColor, 100);
|
|
submitBtn.conf.btnTextStyle.fontSize = formBtnStyle.fontSize;
|
|
restoreBtn.conf.btnTextStyle.fontSize = restoreBtnStyle.fontSize;
|
|
conf.spacing = btnSpacing;
|
|
buttonGroup.setConfiguaration({
|
|
buttons : conf,
|
|
group : {
|
|
fill : convertColor(COLOR_FFFFFF, 0),
|
|
borderThickness : 0
|
|
}
|
|
});
|
|
if (showRestoreBtn) {
|
|
buttonGroup.addSymbol(restoreBtn);
|
|
// Restore Button
|
|
restoreBtn.attachEventHandlers({
|
|
click: function () {
|
|
chart.restoreData();
|
|
}
|
|
});
|
|
}
|
|
|
|
if (formAction) {
|
|
buttonGroup.addSymbol(submitBtn);
|
|
submitBtn.attachEventHandlers({
|
|
click: function () {
|
|
chart.submitData(global);
|
|
}
|
|
});
|
|
}
|
|
// The restore and Submit buttons should always be placed in the bottom.
|
|
buttonGroup.btnConfig.vAlign = 'b';
|
|
|
|
actionBar.addComponent(buttonGroup);
|
|
actionBar.toolbarConfig.fill = convertColor('EBEBEB', 0);
|
|
actionBar.toolbarConfig.borderThickness = 0;
|
|
},
|
|
addConfigureOptions: function () {
|
|
var chart = this,
|
|
chartMenuTools = chart.chartMenuTools,
|
|
components = chart.components,
|
|
actionBar = components.actionBar,
|
|
chartMenuBar = components.chartMenuBar,
|
|
componentGroup = (chartMenuBar || actionBar).componentGroups[0],
|
|
symbolList = componentGroup.symbolList[0],
|
|
sListRef = symbolList.getListRefernce(),
|
|
chartAttr = chart.jsonData.chart,
|
|
allowAxisChange = pluckNumber(chartAttr.allowaxischange, 1),
|
|
setChartTools = chartMenuTools.set,
|
|
configureTools = [
|
|
{
|
|
'Increase Upper Limit' : {
|
|
handler: function () {
|
|
var yAxis = chart.components.yAxis[0],
|
|
axisRange = yAxis.config.axisRange,
|
|
max = axisRange.max,
|
|
tickInterval = axisRange.tickInterval;
|
|
chart.changeUpperLimits(max + tickInterval);
|
|
},
|
|
action: 'click'
|
|
}
|
|
},
|
|
{
|
|
'Increase Lower Limit': {
|
|
handler: function () {
|
|
var yAxis = chart.components.yAxis[0],
|
|
axisRange = yAxis.config.axisRange,
|
|
min = axisRange.min,
|
|
tickInterval = axisRange.tickInterval;
|
|
chart.changeLowerLimits(min + tickInterval);
|
|
},
|
|
action: 'click'
|
|
}
|
|
},
|
|
{
|
|
'Decrease Upper Limit': {
|
|
handler: function () {
|
|
var yAxis = chart.components.yAxis[0],
|
|
axisRange = yAxis.config.axisRange,
|
|
max = axisRange.max,
|
|
tickInterval = axisRange.tickInterval;
|
|
chart.changeUpperLimits(max - tickInterval);
|
|
},
|
|
action: 'click'
|
|
}
|
|
},
|
|
{
|
|
'Decrease Lower Limit': {
|
|
handler: function () {
|
|
var yAxis = chart.components.yAxis[0],
|
|
axisRange = yAxis.config.axisRange,
|
|
min = axisRange.min,
|
|
tickInterval = axisRange.tickInterval;
|
|
chart.changeLowerLimits(min - tickInterval);
|
|
},
|
|
action: 'click'
|
|
}
|
|
}
|
|
];
|
|
if (allowAxisChange) {
|
|
setChartTools(configureTools);
|
|
sListRef.appendAsList(configureTools);
|
|
}
|
|
|
|
},
|
|
drawAxisUpdateUI: function() {
|
|
var chart = this,
|
|
chartGraphics = chart.graphics,
|
|
yAxis = chart.components.yAxis[0],
|
|
axisRange = yAxis.config.axisRange,
|
|
axisLabels = yAxis.getAxisConfig('extremeLabels') || [],
|
|
chartConf = chart.config,
|
|
min = axisRange.min,
|
|
max = axisRange.max,
|
|
maxLabel = axisLabels.lastLabel.graphic,
|
|
minLabel = axisLabels.firstLabel.graphic,
|
|
container = chart.linkedItems.container,
|
|
inCanvasStyle = chart.config.style.inCanvasStyle || {},
|
|
inputStyle = extend({
|
|
outline: NONE, // prevent chrome outlining
|
|
'-webkit-appearance': NONE, // disable ios background
|
|
filter: 'alpha(opacity=0)', // IE opacity
|
|
position: 'absolute',
|
|
background: 'transparent',
|
|
border: '1px solid #cccccc',
|
|
textAlign: 'right',
|
|
top: 0,
|
|
left: 0,
|
|
width: 50,
|
|
zIndex: 20,
|
|
opacity: 0,
|
|
borderRadius: 0,
|
|
display: 'block'
|
|
}, inCanvasStyle),
|
|
hashify = lib.hashify,
|
|
poi = {
|
|
max: {
|
|
label: maxLabel,
|
|
value: max
|
|
},
|
|
min: {
|
|
label: minLabel,
|
|
value: min
|
|
}
|
|
},
|
|
poiObj,
|
|
label,
|
|
value,
|
|
oldValue,
|
|
box,
|
|
isMaxLabel,
|
|
inputElement,
|
|
showRangeError,
|
|
inputWidth,
|
|
inputLeft,
|
|
item,
|
|
doAxisUpdate = function(value, oldvalue, isMax) {
|
|
var success;
|
|
// do not update if value has not changed
|
|
if (value === oldvalue + BLANKSTRING) {
|
|
return null;
|
|
}
|
|
|
|
success = isMax ?
|
|
chart.changeUpperLimits(Number(value), true) :
|
|
chart.changeLowerLimits(Number(value), true);
|
|
|
|
if (!success && showRangeError) {
|
|
chart.showMessage('Sorry! Not enough range gap to modify axis limit to ' +
|
|
(Number(value) || ZEROSTRING) +
|
|
'.<br />Please modify the data values to be within range.<br /> <br />' +
|
|
'(click anywhere on the chart to close this message)', true);
|
|
}
|
|
|
|
return success;
|
|
},
|
|
onFocus = function (){
|
|
var ele = this,
|
|
inCanvasStyle = chart.config.style.inCanvasStyle || {},
|
|
styleObj = {
|
|
opacity: 1,
|
|
filter: 'alpha(opacity=100)', // IE opacity
|
|
color: inCanvasStyle.color
|
|
},
|
|
item;
|
|
|
|
if (styleObj.color) {
|
|
styleObj.color = hashify(styleObj.color);
|
|
}
|
|
ele.value = ele.dataValue;
|
|
|
|
for (item in styleObj) {
|
|
ele.style[item] = styleObj[item];
|
|
}
|
|
|
|
ele.justFocussed = true;
|
|
ele.hasFocus = true;
|
|
ele.axisLabel && ele.axisLabel.hide();
|
|
if (!chart.graphics.hiddenAxisLabels) {
|
|
chart.graphics.hiddenAxisLabels = [];
|
|
}
|
|
chart.graphics.hiddenAxisLabels.push(ele.axisLabel);
|
|
},
|
|
onMouseUp = (function () {
|
|
return function() {
|
|
|
|
|
|
var ele = this;
|
|
if (ele.justFocussed) {
|
|
|
|
ele.justFocussed = false;
|
|
if (!hasTouch) {
|
|
setTimeout(function() {
|
|
ele.select();
|
|
}, 0);
|
|
}
|
|
}
|
|
};
|
|
})(),
|
|
onBlur = function () {
|
|
var ele = this,
|
|
newValue = ele.value,
|
|
oldValue = ele.oldValue,
|
|
isMaxLabel = ele.isMaxLabel,
|
|
success = doAxisUpdate(newValue, oldValue,
|
|
isMaxLabel);
|
|
|
|
if (success !== true) {
|
|
ele.style.opacity = 0;
|
|
ele.style.filter = 'alpha(opacity=0)';
|
|
// IE opacity
|
|
ele.axisLabel && ele.axisLabel.show();
|
|
}
|
|
|
|
if (isIE) {
|
|
// To call the actual blur on the element in case of IE
|
|
doc.getElementsByTagName('body')[0].focus &&
|
|
doc.getElementsByTagName('body')[0].focus();
|
|
}
|
|
|
|
ele.justFocussed = false;
|
|
ele.hasFocus = false;
|
|
},
|
|
onKeyUp = function (e) {
|
|
var ele = this,
|
|
keyCode = e.originalEvent.keyCode,
|
|
newValue = ele.value,
|
|
oldValue = ele.oldValue,
|
|
isMaxLabel = ele.isMaxLabel,
|
|
success;
|
|
|
|
if (keyCode === 13) {
|
|
success = doAxisUpdate(newValue, oldValue,
|
|
isMaxLabel);
|
|
if (success === false) {
|
|
ele.style.color = '#dd0000';
|
|
}
|
|
else {
|
|
lib.dem.fire(ele, 'blur', e);
|
|
}
|
|
} else if (keyCode === 27) {
|
|
ele.value = oldValue;
|
|
lib.dem.fire(ele, 'blur', e);
|
|
}
|
|
},
|
|
defaultAction = function (inputElement) {
|
|
return function(e) {
|
|
if (inputElement.parentNode) {
|
|
lib.dem.fire(inputElement, 'blur', e);
|
|
}
|
|
};
|
|
},
|
|
destroyFn = function (inputElement, defaultAction) {
|
|
return function() {
|
|
removeEvent(chart, 'defaultprevented', defaultAction);
|
|
inputElement.parentNode.removeChild(inputElement);
|
|
|
|
};
|
|
},
|
|
defaultActionIE = function (inputElement) {
|
|
return function(e) {
|
|
if (e.srcElement !== inputElement && inputElement.hasFocus) {
|
|
lib.dem.fire(inputElement, 'blur', e);
|
|
}
|
|
};
|
|
},
|
|
destroyFnIE = function (inputElement, defaultAction) {
|
|
return function() {
|
|
removeEvent(container, 'mousedown', defaultAction);
|
|
inputElement.parentNode.removeChild(inputElement);
|
|
};
|
|
},
|
|
defActionFn,
|
|
defActionFnIE,
|
|
prop;
|
|
|
|
for (prop in poi) {
|
|
poiObj = poi[prop];
|
|
label = poiObj.label;
|
|
value = poiObj.value;
|
|
oldValue = (poiObj.oldValue = value);
|
|
box = label && label.getBBox();
|
|
isMaxLabel = prop === 'max' ? true : false;
|
|
|
|
if (!chartGraphics.inputElements) {
|
|
chartGraphics.inputElements = {};
|
|
}
|
|
inputElement = chartGraphics.inputElements[prop];
|
|
|
|
// Take precaution to ensure that we do not do any computation
|
|
// in case chart is destroyed.
|
|
if (!(box && label)) {
|
|
if (inputElement) {
|
|
inputElement.style.display = 'none';
|
|
}
|
|
continue;
|
|
}
|
|
|
|
// Decide the width and position of inputbox.
|
|
inputWidth = box.x + box.width - chartConf.marginLeft;
|
|
inputLeft = chartConf.canvasLeft - inputWidth - (hasSVG ? 4 : 5);
|
|
|
|
extend(inputStyle, {
|
|
top: (box.y + (hasSVG ? -1 : 0)) + PX,
|
|
left: inputLeft + PX,
|
|
width: inputWidth + PX
|
|
});
|
|
|
|
if (!inputElement) {
|
|
// Create the input-box element and provide its initial attrs
|
|
// and styling.
|
|
inputElement = chartGraphics.inputElements[prop] = createElement(
|
|
'input', {
|
|
type: 'text',
|
|
value: value,
|
|
name: value || BLANKSTRING
|
|
}, container, true);
|
|
|
|
// Add events to make the textboxes visible on focus and hide
|
|
// when not.
|
|
lib.dem.listen(inputElement, ['focus', 'mouseup', 'blur', 'keyup'], [
|
|
onFocus,
|
|
onMouseUp,
|
|
onBlur,
|
|
onKeyUp
|
|
]);
|
|
|
|
// Mark it for no event prevention
|
|
inputElement.setAttribute('isOverlay', 'true');
|
|
|
|
// When out of textbox is clicked, we need to emulate blur event.
|
|
// This is because the container grabs the mousedown event for
|
|
// better UX.
|
|
if (hasSVG) {
|
|
addEvent(container, 'defaultprevented', defActionFn = defaultAction(inputElement));
|
|
// cleanup
|
|
addEvent(container, 'destroy', destroyFn(inputElement, defActionFn));
|
|
} else {
|
|
addEvent(container, 'mousedown', defActionFnIE = defaultActionIE(inputElement));
|
|
// cleanup
|
|
addEvent(container, 'destroy', destroyFnIE(inputElement, defActionFnIE));
|
|
}
|
|
|
|
}
|
|
inputElement.dataValue = value;
|
|
if (inputStyle.color) {
|
|
inputStyle.color = hashify(inputStyle.color);
|
|
}
|
|
for (item in inputStyle) {
|
|
inputElement.style[item] = inputStyle[item];
|
|
}
|
|
inputElement.value = value;
|
|
inputElement.oldValue = value;
|
|
inputElement.name = value || BLANKSTRING;
|
|
inputElement.axisLabel = label;
|
|
inputElement.isMaxLabel = isMaxLabel;
|
|
}
|
|
},
|
|
changeUpperLimits: function (upperLimit) {
|
|
var chart = this,
|
|
components = chart.components,
|
|
yAxis = components.yAxis[0],
|
|
axisRange = yAxis.config.axisRange,
|
|
min = axisRange.min,
|
|
yAxisMax = axisRange.max,
|
|
config = chart.config,
|
|
maxValue = config.yMax,
|
|
limitchanged = false,
|
|
hiddenAxisLabels = chart.graphics.hiddenAxisLabels || [],
|
|
len = hiddenAxisLabels.length,
|
|
i,
|
|
label,
|
|
max;
|
|
|
|
if ((upperLimit !== undefined) && upperLimit > maxValue && upperLimit !== yAxisMax) {
|
|
max = upperLimit;
|
|
limitchanged = true;
|
|
}
|
|
else {
|
|
max = maxValue > yAxisMax ? maxValue : yAxisMax;
|
|
}
|
|
|
|
if (limitchanged) {
|
|
yAxis.setAxisConfig({
|
|
axisMaxValue : max,
|
|
axisMinValue : min,
|
|
showUpperLimit: true
|
|
});
|
|
yAxis.setDataLimit(max, min);
|
|
chart._manageSpace();
|
|
chart._postSpaceManagement();
|
|
chart._drawCanvas();
|
|
chart.chartMenuBar && chart._drawChartMenuBar();
|
|
chart._manageCaptionPosition();
|
|
chart._drawCanvas();
|
|
//iapi._drawCaption ();
|
|
components.caption && components.caption.draw();
|
|
|
|
chart.drawLegend();
|
|
|
|
chart.drawActionBar && chart.drawActionBar();
|
|
|
|
// Show hidden axis labels
|
|
for (i = 0; i < len; i++) {
|
|
label = hiddenAxisLabels[i];
|
|
label.show();
|
|
}
|
|
|
|
chart._drawAxis && chart._drawAxis();
|
|
chart._drawDataset ();
|
|
chart.drawAxisUpdateUI();
|
|
}
|
|
return limitchanged;
|
|
},
|
|
changeLowerLimits: function (lowerLimit) {
|
|
var chart = this,
|
|
components = chart.components,
|
|
yAxis = components.yAxis[0],
|
|
axisRange = yAxis.config.axisRange,
|
|
minValue = chart.config.yMin,
|
|
max = axisRange.max,
|
|
min,
|
|
limitchanged = false,
|
|
hiddenAxisLabels = chart.graphics.hiddenAxisLabels || [],
|
|
len = hiddenAxisLabels.length,
|
|
i,
|
|
label,
|
|
yMin = axisRange.min;
|
|
if ((lowerLimit !== undefined) && lowerLimit < minValue && lowerLimit !== yMin) {
|
|
min = lowerLimit;
|
|
limitchanged = true;
|
|
} else {
|
|
lowerLimit = minValue < yMin ? minValue : yMin;
|
|
}
|
|
if (limitchanged) {
|
|
yAxis.setAxisConfig({
|
|
axisMaxValue : max,
|
|
axisMinValue : lowerLimit
|
|
});
|
|
yAxis.setDataLimit(max, min);
|
|
chart._manageSpace();
|
|
chart._postSpaceManagement();
|
|
chart._drawCanvas();
|
|
chart.chartMenuBar && chart._drawChartMenuBar();
|
|
chart._manageCaptionPosition();
|
|
chart._drawCanvas();
|
|
//iapi._drawCaption ();
|
|
components.caption && components.caption.draw();
|
|
|
|
chart.drawLegend();
|
|
|
|
chart.drawActionBar && chart.drawActionBar();
|
|
|
|
// Show hidden axis labels
|
|
for (i = 0; i < len; i++) {
|
|
label = hiddenAxisLabels[i];
|
|
label.show();
|
|
}
|
|
|
|
chart._drawAxis && chart._drawAxis();
|
|
chart._drawDataset ();
|
|
chart.drawAxisUpdateUI();
|
|
}
|
|
return limitchanged;
|
|
},
|
|
eiMethods: {
|
|
getDataWithId: function () {
|
|
var vars = this.jsVars,
|
|
iapi = vars.instanceAPI,
|
|
dataObj = iapi.getJSONData(),
|
|
returnObj = [
|
|
[BLANK]
|
|
],
|
|
datasets = dataObj.dataset,
|
|
catArr = (dataObj.categories && dataObj.categories[0] &&
|
|
dataObj.categories[0].category),
|
|
i = (datasets && datasets.length) || 0,
|
|
vLinePassed = 0,
|
|
setArr,
|
|
catName,
|
|
catObj,
|
|
set,
|
|
DS,
|
|
item,
|
|
dsID,
|
|
id,
|
|
j,
|
|
ln;
|
|
|
|
while (i--) {
|
|
DS = datasets[i];
|
|
if (DS) {
|
|
returnObj[0][i + 1] = DS.id || DS.seriesname;
|
|
dsID = DS.id || (i + 1);
|
|
set = DS.data;
|
|
ln = (set && set.length) || 0;
|
|
for (j = 0; j < ln; j += 1) {
|
|
item = j + 1;
|
|
if (!returnObj[item]) {
|
|
catObj = (catArr && catArr[j + vLinePassed]) || {};
|
|
while (catObj.vline) {
|
|
vLinePassed += 1;
|
|
catObj = catArr[j + vLinePassed] || {};
|
|
}
|
|
catName = catObj.label || catObj.name || BLANK;
|
|
returnObj[item] = [catName];
|
|
}
|
|
setArr = returnObj[item];
|
|
id = set[j].id || (item + UNDERSCORE + dsID);
|
|
setArr[i + 1] = [id, Number(set[j].value)];
|
|
}
|
|
}
|
|
}
|
|
|
|
return returnObj;
|
|
},
|
|
getData: function(format) {
|
|
// create a two dimensional array as given in the docs
|
|
var vars = this.jsVars,
|
|
iapi = vars.instanceAPI,
|
|
dataObj = iapi.getJSONData(),
|
|
returnObj = [
|
|
[BLANK]
|
|
],
|
|
datasets = dataObj.dataset,
|
|
catArr = (dataObj.categories && dataObj.categories[0] &&
|
|
dataObj.categories[0].category),
|
|
i = (datasets && datasets.length) || 0,
|
|
vLinePassed = 0,
|
|
catObj,
|
|
setArr,
|
|
catName,
|
|
set,
|
|
item,
|
|
ln,
|
|
j;
|
|
|
|
// When a format is provided
|
|
if (format) {
|
|
// no transcoding needed for json
|
|
if (/^json$/ig.test(format)) {
|
|
returnObj = dataObj;
|
|
} else {
|
|
returnObj = global.core.transcodeData.call(iapi.chartInstance, dataObj,
|
|
'json', format);
|
|
}
|
|
}
|
|
// if no format has been specified, return data as 2d array.
|
|
else {
|
|
while (i--) {
|
|
set = datasets[i];
|
|
if (set) {
|
|
returnObj[0][i + 1] = datasets[i].seriesname;
|
|
|
|
set = datasets[i] && datasets[i].data;
|
|
ln = (set && set.length) || 0;
|
|
for (j = 0; j < ln; j += 1) {
|
|
item = j + 1;
|
|
if (!returnObj[item]) {
|
|
catObj = (catArr && catArr[j + vLinePassed]) || {};
|
|
while (catObj.vline) {
|
|
vLinePassed += 1;
|
|
catObj = catArr[j + vLinePassed] || {};
|
|
}
|
|
catName = catObj.label || catObj.name || BLANK;
|
|
returnObj[item] = [catName];
|
|
}
|
|
setArr = returnObj[item];
|
|
setArr[i + 1] = Number(set[j].value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return returnObj;
|
|
},
|
|
setUpperLimit: function (limit, callback) {
|
|
var iapi = this.apiInstance,
|
|
list = iapi.getJobList(),
|
|
output,
|
|
asyncRender = iapi.chartInstance.args.asyncRender;
|
|
|
|
if (callback || asyncRender) {
|
|
list.eiMethods.push(schedular.addJob(function(){
|
|
output = iapi.changeUpperLimits(limit);
|
|
if (typeof callback === 'function') {
|
|
callback(output);
|
|
}
|
|
}, iapi, [], priorityList.postRender));
|
|
}
|
|
else {
|
|
return iapi.changeUpperLimits(limit);
|
|
}
|
|
},
|
|
setLowerLimit: function (limit, callback) {
|
|
var iapi = this.apiInstance,
|
|
list = iapi.getJobList(),
|
|
output,
|
|
asyncRender = iapi.chartInstance.args.asyncRender;
|
|
|
|
if (callback || asyncRender) {
|
|
list.eiMethods.push(schedular.addJob(function(){
|
|
output = iapi.changeLowerLimits(limit);
|
|
if (typeof callback === 'function') {
|
|
callback(output);
|
|
}
|
|
}, iapi, [], priorityList.postRender));
|
|
}
|
|
else {
|
|
return iapi.changeLowerLimits(limit);
|
|
}
|
|
},
|
|
getLowerLimit: function (callback) {
|
|
var iapi = this.apiInstance,
|
|
components = iapi.components,
|
|
yAxis = components.yAxis && components.yAxis[0],
|
|
list = iapi.getJobList();
|
|
|
|
if (yAxis) {
|
|
if (callback) {
|
|
list.eiMethods.push(schedular.addJob(function () {
|
|
callback(yAxis.config.axisRange.min);
|
|
}, iapi, [], priorityList.postRender));
|
|
}
|
|
else {
|
|
return yAxis.config.axisRange.min;
|
|
}
|
|
}
|
|
|
|
},
|
|
getUpperLimit: function (callback) {
|
|
var iapi = this.apiInstance,
|
|
components = iapi.components,
|
|
yAxis = components.yAxis && components.yAxis[0],
|
|
list = iapi.getJobList();
|
|
|
|
if (yAxis) {
|
|
if (callback) {
|
|
list.eiMethods.push(schedular.addJob(function () {
|
|
callback(yAxis.config.axisRange.max);
|
|
}, iapi, [], priorityList.postRender));
|
|
}
|
|
else {
|
|
return yAxis.config.axisRange.max;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
restoreData: function () {
|
|
var chart = this,
|
|
components = chart.components,
|
|
yAxis = components.yAxis[0],
|
|
datasets = components.dataset,
|
|
legend = components.legend,
|
|
len = datasets.length,
|
|
dataset,
|
|
hiddenAxisLabels = chart.graphics.hiddenAxisLabels || [],
|
|
label,
|
|
i;
|
|
|
|
chart.config.isDataRestored = true;
|
|
for (i = 0; i < len; i++) {
|
|
dataset = datasets[i];
|
|
dataset.configure();
|
|
}
|
|
yAxis.setAxisConfig({
|
|
axisMaxValue : undefined,
|
|
axisMinValue : undefined
|
|
});
|
|
chart._setAxisLimits();
|
|
|
|
len = hiddenAxisLabels.length;
|
|
for (i = 0; i < len; i++) {
|
|
label = hiddenAxisLabels[i];
|
|
label.show();
|
|
}
|
|
chart._drawAxis();
|
|
chart._drawDataset();
|
|
legend._drawPointLegendItem();
|
|
chart.drawAxisUpdateUI();
|
|
delete chart.config.isDataRestored;
|
|
lib.raiseEvent('dataRestored', {}, chart.chartInstance, [chart.chartInstance.id]);
|
|
},
|
|
submitData: function (global) {
|
|
var chart = this,
|
|
iapi = chart.chartInstance,
|
|
ajaxObj = new global.ajax(),
|
|
chartConf = chart.config,
|
|
json = global.dataFormats.JSON,
|
|
csv = global.dataFormats.CSV,
|
|
xml = global.dataFormats.XML,
|
|
url = chartConf.formAction,
|
|
chartInstance = chart.chartInstance,
|
|
submitAsAjax = chartConf.submitFormAsAjax,
|
|
requestType,
|
|
data,
|
|
paramObj,
|
|
tempSpan,
|
|
formEle;
|
|
|
|
if (chartConf.formDataFormat === json) {
|
|
requestType = json;
|
|
data = JSON.stringify(chart.getJSONData());
|
|
} else if (chart.formDataFormat === csv) {
|
|
requestType = csv;
|
|
data = iapi.getCSVString && iapi.getCSVString();
|
|
if (data === undefined) {
|
|
data = global.core.transcodeData(chart.getJSONData(), json, csv);
|
|
}
|
|
} else {
|
|
requestType = xml;
|
|
data = global.core.transcodeData(chart.getJSONData(), json, xml);
|
|
}
|
|
|
|
// cancel data submit function added in event options
|
|
/**
|
|
* For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc., data
|
|
* points value can be selected for `Scatter Chart` and values can be changed for dragable charts by
|
|
* clicking and dragging the data points whose data point values can be sent to an URL by ajax POST.
|
|
* This is the first event raised when `Submit` button is clicked where the current chart data is
|
|
* about to be sent to the set URL.
|
|
*
|
|
* @event FusionCharts#beforeDataSubmit
|
|
* @group chart-powercharts
|
|
*
|
|
* @param {string} data - Contains the XML string with complete chart data at it's current state.
|
|
*
|
|
*/
|
|
global.raiseEvent('beforeDataSubmit', {
|
|
data: data
|
|
}, chartInstance, undefined, function() {
|
|
// After the collation is done, we have to submit the data using
|
|
// ajax or form submit method.
|
|
if (!submitAsAjax) {
|
|
// Create a hidden form with data inside it.
|
|
tempSpan = win.document.createElement('span');
|
|
tempSpan.innerHTML = '<form style="display:none" action="' +
|
|
url + '" method="' + chartConf.formMethod + '" target="' + chartConf.formTarget +
|
|
'"> <input type="hidden" name="strXML" value="' +
|
|
xssEncode(data) + '"><input type="hidden" name="dataFormat" value="' +
|
|
requestType.toUpperCase() + '" /></form>';
|
|
|
|
formEle = tempSpan.removeChild(tempSpan.firstChild);
|
|
|
|
// Append the form to body and then submit it.
|
|
win.document.body.appendChild(formEle);
|
|
formEle.submit && formEle.submit();
|
|
// cleanup
|
|
formEle.parentNode.removeChild(formEle);
|
|
tempSpan = formEle = null;
|
|
}
|
|
else {
|
|
ajaxObj.onError = function(response, wrapper, ajaxData, url) {
|
|
/**
|
|
* For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc.,
|
|
* data points value can be selected for `Scatter Chart` and values can be changed for
|
|
* dragable charts by clicking and dragging the data points whose data point values can be
|
|
* sent to an URL by ajax POST. This event is raised if there is an ajax error in sending
|
|
* the chart XML data.
|
|
*
|
|
* @event FusionCharts#dataSubmitError
|
|
* @group chart-powercharts
|
|
*
|
|
* @param {string} data - Contains the XML string with complete chart data.
|
|
* @param {number} httpStatus - Tells the status code of the ajax POST request
|
|
* @param {string} statusText - Contains the ajax error message.
|
|
* @param {string} url - URL to which the data is sent as ajax POST request.
|
|
* @param {object} xhrObject - XMLHttpRequest object which takes care of sending the XML
|
|
* chart data. In case of error, this object won't be defined.
|
|
*/
|
|
lib.raiseEvent('dataSubmitError', {
|
|
xhrObject: wrapper.xhr,
|
|
url: url,
|
|
statusText: response,
|
|
httpStatus: (wrapper.xhr && wrapper.xhr.status) ?
|
|
wrapper.xhr.status : -1,
|
|
data: data
|
|
}, chartInstance, [chartInstance.id, response, wrapper.xhr && wrapper.xhr.status]);
|
|
};
|
|
|
|
ajaxObj.onSuccess = function(response, wrapper, ajaxData, url) {
|
|
/**
|
|
* For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc.,
|
|
* data points value can be selected for `Scatter Chart` and values can be changed for
|
|
* dragable charts by clicking and dragging the data points whose data point values can be
|
|
* sent to an URL by ajax POST. This event is raised when the ajax POST request is
|
|
* successfully completed.
|
|
*
|
|
* @event FusionCharts#dataSubmitted
|
|
* @group chart-powercharts
|
|
*
|
|
* @param {string} data - Contains the XML string with complete chart data.
|
|
* @param {string} reponse - Contains the reponse returned by the web server to which the
|
|
* HTTP POST request was submitted.
|
|
* @param {string} url - URL to which the data is sent as HTTP POST request.
|
|
* @param {object} xhrObject - XMLHttpRequest object which takes care of sending the XML
|
|
* chart data
|
|
*/
|
|
lib.raiseEvent('dataSubmitted', {
|
|
xhrObject: ajaxObj,
|
|
response: response,
|
|
url: url,
|
|
data: data
|
|
}, chartInstance, [chartInstance.id, response]);
|
|
};
|
|
|
|
paramObj = {};
|
|
paramObj['str' + requestType.toUpperCase()] = data;
|
|
|
|
if (ajaxObj.open) {
|
|
ajaxObj.abort();
|
|
}
|
|
ajaxObj.post(url, paramObj);
|
|
}
|
|
}, function() {
|
|
/**
|
|
* For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc.,
|
|
* data points value can be selected for `Scatter Chart` and values can be changed for
|
|
* dragable charts by clicking and dragging the data points whose data point values can be
|
|
* sent to an URL by ajax POST. This event is raised when `preventDefault()` method is called
|
|
* from the `eventObject` of FusionCharts#beforeDataSubmit event.
|
|
*
|
|
* @event FusionCharts#dataSubmitCancelled
|
|
* @group chart-powercharts
|
|
*
|
|
* @param {string} data - Contains the XML string with complete chart data.
|
|
* @param {number} httpStatus - Tells the status code of the ajax POST request
|
|
* @param {string} statusText - Contains the ajax error message.
|
|
* @param {string} url - URL to which the data is sent as ajax POST request.
|
|
* @param {object} xhrObject - XMLHttpRequest object which takes care of sending the XML
|
|
* chart data. In case of error, this object won't be defined.
|
|
* @example
|
|
* FusionCharts.addEventListener('beforeDataSubmit', function(eventObject, parameterObject) {
|
|
* eventObject.preventDefault();
|
|
* }
|
|
*/
|
|
global.raiseEvent('dataSubmitCancelled', {
|
|
data: data
|
|
}, chartInstance);
|
|
});
|
|
},
|
|
getJSONData: function () {
|
|
var chart = this,
|
|
defaultDatasetType = chart.defaultDatasetType && chart.defaultDatasetType.toLowerCase(),
|
|
chartComponents = chart.components,
|
|
groupManager = chartComponents['datasetGroup_' + defaultDatasetType],
|
|
datasets = chartComponents.dataset,
|
|
rawDatasets = chart.jsonData.dataset,
|
|
rawDataset,
|
|
rawObj = chart.jsonData,
|
|
len = datasets.length,
|
|
datasetsArr = [],
|
|
jsonObj,
|
|
dataObj,
|
|
dataset,
|
|
i;
|
|
if (groupManager && groupManager.getJSONData) {
|
|
datasetsArr = groupManager.getJSONData();
|
|
}
|
|
else {
|
|
for (i = 0; i < len; i++) {
|
|
dataset = datasets[i];
|
|
dataObj = dataset.getJSONData();
|
|
rawDataset = rawDatasets[i] || {};
|
|
delete rawDataset.data;
|
|
datasetsArr.push(extend2(rawDataset, dataObj));
|
|
}
|
|
}
|
|
jsonObj = extend2({}, rawObj);
|
|
jsonObj.dataset = datasetsArr;
|
|
return jsonObj;
|
|
},
|
|
_setDataLimits: function () {
|
|
var chart = this,
|
|
datasets = chart.components.dataset,
|
|
config = chart.config,
|
|
yMax = -Infinity,
|
|
yMin = +Infinity,
|
|
dataset,
|
|
limits,
|
|
len,
|
|
i;
|
|
len = datasets.length;
|
|
for (i = 0; i < len; i++) {
|
|
dataset = datasets[i];
|
|
limits = dataset.getDataLimits();
|
|
yMax = mathMax(yMax, limits.max);
|
|
yMin = mathMin(yMin, limits.min);
|
|
}
|
|
config.yMax = yMax;
|
|
config.yMin = yMin;
|
|
},
|
|
_mouseEvtHandler: function (e) {
|
|
var chart = this,
|
|
data = e.data,
|
|
mouseTracker = data.mouseTracker,
|
|
oriEvent = e.originalEvent,
|
|
chartConfig = chart.config,
|
|
canvasLeft = chartConfig.canvasLeft,
|
|
canvasRight = chartConfig.canvasRight,
|
|
canvasBottom = chartConfig.canvasBottom,
|
|
canvasTop = chartConfig.canvasTop,
|
|
datasets = chartConfig.datasetOrder || chart.components.dataset,
|
|
coordinate = lib.getMouseCoordinate(chart.linkedItems.container, oriEvent, chart),
|
|
chartX = coordinate.chartX,
|
|
chartY = coordinate.chartY,
|
|
dataset,
|
|
hoveredInfo,
|
|
pointFound = false,
|
|
i = datasets.length,
|
|
j,
|
|
l,
|
|
derivedEvensInfo,
|
|
_lastDatasetIndex = mouseTracker._lastDatasetIndex,
|
|
_lastPointIndex = mouseTracker._lastPointIndex,
|
|
dragStart,
|
|
eventType,
|
|
tolerance = chartConfig.dragTolerance || 0;
|
|
|
|
(_lastPointIndex !== undefined) &&
|
|
(dragStart = datasets[_lastDatasetIndex].components.data[_lastPointIndex].config.dragStart);
|
|
|
|
// @todo we have to implement this for charts with more than one canvas like candle stick
|
|
// if inside the canvas
|
|
if (!dragStart && chartX > canvasLeft - tolerance && chartX < canvasRight + tolerance &&
|
|
chartY > canvasTop - tolerance && chartY < canvasBottom + tolerance ||
|
|
!dragStart && chart.config.plotOverFlow) {
|
|
|
|
// @todo make sure the datasets are as per their z-order
|
|
while (i-- && !pointFound) {
|
|
dataset = datasets[i];
|
|
if (dataset && dataset.visible) {
|
|
hoveredInfo = dataset._getHoveredPlot && dataset._getHoveredPlot(chartX, chartY);
|
|
if (hoveredInfo && hoveredInfo.hovered) {
|
|
pointFound = true;
|
|
hoveredInfo.datasetIndex = i;
|
|
derivedEvensInfo = mouseTracker._getMouseEvents(e, hoveredInfo.datasetIndex,
|
|
hoveredInfo.pointIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//for drag event
|
|
if(dragStart && _lastDatasetIndex !== undefined) {
|
|
eventType = (e.type === MOUSEOUT) ? MOUSEMOVE : e.type;
|
|
datasets[_lastDatasetIndex] && datasets[_lastDatasetIndex]._firePlotEvent &&
|
|
datasets[_lastDatasetIndex]._firePlotEvent(eventType, _lastPointIndex, e);
|
|
}
|
|
// @todo instead of sending event names, create a event object of that type and send it
|
|
// fire out on last hovered plot
|
|
if (!dragStart && (!pointFound || (derivedEvensInfo && derivedEvensInfo.fireOut)) &&
|
|
_lastDatasetIndex !== undefined) {
|
|
// delete stored last ds details
|
|
delete mouseTracker._lastDatasetIndex;
|
|
delete mouseTracker._lastPointIndex;
|
|
|
|
datasets[_lastDatasetIndex] && datasets[_lastDatasetIndex]._firePlotEvent &&
|
|
datasets[_lastDatasetIndex]._firePlotEvent(MOUSEOUT, _lastPointIndex, e);
|
|
|
|
// @todo scope to have sticky tracked tooltip
|
|
}
|
|
// fire remaining events
|
|
if (pointFound) {
|
|
l = derivedEvensInfo.events && derivedEvensInfo.events.length;
|
|
// store the index of the hovered DS and plot
|
|
mouseTracker._lastDatasetIndex = hoveredInfo.datasetIndex;
|
|
_lastPointIndex = mouseTracker._lastPointIndex = hoveredInfo.pointIndex;
|
|
for (j = 0; j < l; j += 1) {
|
|
dataset && dataset._firePlotEvent && dataset._firePlotEvent(derivedEvensInfo.events[j],
|
|
_lastPointIndex, e);
|
|
}
|
|
}
|
|
}
|
|
}, chartAPI.mscartesian);
|
|
}]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dragnode', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
ZEROSTRING = lib.ZEROSTRING,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
getValidValue = lib.getValidValue,
|
|
pluckNumber = lib.pluckNumber,
|
|
extend2 = lib.extend2,
|
|
COMPONENT = 'component',
|
|
componentDispose = lib.componentDispose,
|
|
math = Math,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname),
|
|
chartAPI = lib.chartAPI,
|
|
DATASET = 'dataset',
|
|
DATASET_GROUP = 'datasetGroup',
|
|
UNDEFINED;
|
|
|
|
|
|
chartAPI('dragnode', {
|
|
friendlyName: 'Dragable Node Chart',
|
|
standaloneInit: true,
|
|
fireGroupEvent: true,
|
|
hasLegend: true,
|
|
numVDivLines: 0,
|
|
numDivLines: 0,
|
|
showLimits: 0,
|
|
setadaptivexmin: 1,
|
|
showdivlinevalues: 0,
|
|
showzeroplane: 0,
|
|
showyaxisvalues: 0,
|
|
dontShowLegendByDefault: true,
|
|
creditLabel: creditLabel,
|
|
//showvlimits: 0,
|
|
defaultDatasetType: 'dragnode',
|
|
configure: function () {
|
|
var iapi = this,
|
|
jsonData = iapi.jsonData,
|
|
chartAttr = jsonData.chart,
|
|
config;
|
|
chartAPI.dragbase.configure.call(this);
|
|
config = iapi.config;
|
|
config.formAction = getValidValue(chartAttr.formaction);
|
|
|
|
if (chartAttr.submitdataasxml === ZEROSTRING && !chartAttr.formdataformat) {
|
|
chartAttr.formdataformat = global.dataFormats.CSV;
|
|
}
|
|
|
|
config.formDataFormat = pluck(chartAttr.formdataformat,
|
|
global.dataFormats.XML);
|
|
config.formTarget = pluck(chartAttr.formtarget, '_self');
|
|
config.formMethod = pluck(chartAttr.formmethod, 'POST');
|
|
config.submitFormAsAjax = pluckNumber(chartAttr.submitformusingajax, 1);
|
|
config.viewMode = pluckNumber(chartAttr.viewmode, 0);
|
|
},
|
|
_createDatasets : function () {
|
|
var iapi = this,
|
|
config = iapi.config,
|
|
components = iapi.components,
|
|
dataObj = iapi.jsonData,
|
|
dataset = dataObj.dataset,
|
|
connectorSet = dataObj.connectors,
|
|
labelSet = dataObj.labels && dataObj.labels.label || [],
|
|
datasetlen = dataset && dataset.length,
|
|
connLength = connectorSet && connectorSet.length,
|
|
labelsLength = labelSet && labelSet.length || [],
|
|
legend = components.legend,
|
|
i,
|
|
datasetStore,
|
|
datasetObj,
|
|
GroupManager,
|
|
DsGroupClass,
|
|
datasetJSON,
|
|
Dragnode,
|
|
connectorObj,
|
|
connectors,
|
|
ConnectorClass,
|
|
DragLabelClass,
|
|
labelObj,
|
|
prevDataLength,
|
|
currDataLength,
|
|
count = 0,
|
|
JSONData,
|
|
datasetMap = config.datasetMap || (config.datasetMap = {
|
|
connectors : [],
|
|
dragnode : [],
|
|
labels : []
|
|
}),
|
|
dsTypeRef,
|
|
dsRef,
|
|
tempMap = {
|
|
connectors : [],
|
|
dragnode : [],
|
|
labels : []
|
|
},
|
|
length,
|
|
j,
|
|
dsCount = {},
|
|
dsType,
|
|
groupManagerName = 'datasetGroup_dragnode';
|
|
|
|
if (!dataset) {
|
|
iapi.setChartMessage();
|
|
return;
|
|
}
|
|
|
|
iapi.config.categories = dataObj.categories && dataObj.categories[0].category;
|
|
|
|
datasetStore = components.dataset = [];
|
|
// get the ds group class
|
|
DsGroupClass = FusionCharts.register(COMPONENT, [DATASET_GROUP, 'dragnode']);
|
|
GroupManager = components[groupManagerName];
|
|
if (DsGroupClass && !GroupManager) {
|
|
GroupManager = components[groupManagerName] = new DsGroupClass();
|
|
GroupManager.chart = iapi;
|
|
GroupManager.init();
|
|
}
|
|
Dragnode = FusionCharts.get(COMPONENT, [DATASET, 'Dragnode']);
|
|
ConnectorClass = FusionCharts.get(COMPONENT, [DATASET, 'Connector']);
|
|
DragLabelClass = FusionCharts.get(COMPONENT, [DATASET, 'DragableLabels']);
|
|
for(i = 0; i < datasetlen; i++) {
|
|
dsType = 'dragnode';
|
|
dsTypeRef = datasetMap[dsType];
|
|
dsRef = dsTypeRef[0];
|
|
if (dsCount[dsType] === UNDEFINED) {
|
|
dsCount[dsType] = 0;
|
|
}
|
|
else {
|
|
dsCount[dsType]++;
|
|
}
|
|
if (!dsRef) {
|
|
datasetJSON = dataset[i];
|
|
datasetObj = new Dragnode();
|
|
datasetObj.chart = iapi;
|
|
tempMap[dsType].push(datasetObj);
|
|
datasetStore.push(datasetObj);
|
|
datasetObj.chart = iapi;
|
|
datasetObj.index = i;
|
|
datasetObj.init(datasetJSON);
|
|
GroupManager.addDataset(datasetObj, i);
|
|
}
|
|
else {
|
|
|
|
datasetJSON = dataset[i];
|
|
JSONData = (dsRef.components && dsRef.components.data) || [];
|
|
tempMap[dsType].push(dsRef);
|
|
datasetStore.push (dsRef);
|
|
prevDataLength = JSONData.length;
|
|
currDataLength = datasetJSON && datasetJSON.data && datasetJSON.data.length || 0;
|
|
// Removing data plots if the number of current data plots is more than the existing ones.
|
|
if (prevDataLength > currDataLength) {
|
|
dsRef.removeData(currDataLength - 1,
|
|
prevDataLength - currDataLength);
|
|
}
|
|
dsRef.JSONData = datasetJSON;
|
|
dsRef.configure();
|
|
dsTypeRef.shift();
|
|
}
|
|
count++;
|
|
}
|
|
for (i = 0; i < connLength; i++) {
|
|
dsType = 'connectors';
|
|
connectors = connectorSet[i];
|
|
dsTypeRef = datasetMap[dsType];
|
|
dsRef = dsTypeRef[0];
|
|
if (dsCount[dsType] === UNDEFINED) {
|
|
dsCount[dsType] = 0;
|
|
}
|
|
else {
|
|
dsCount[dsType]++;
|
|
}
|
|
if (!dsRef) {
|
|
connectorObj = new ConnectorClass();
|
|
connectorObj.chart = iapi;
|
|
connectorObj.index = i;
|
|
tempMap[dsType].push(connectorObj);
|
|
datasetStore.push(connectorObj);
|
|
connectorObj.init(connectors);
|
|
GroupManager.addConnectors(connectorObj, i);
|
|
}
|
|
else {
|
|
JSONData = (dsRef.components && dsRef.components.data) || [];
|
|
prevDataLength = JSONData.length;
|
|
currDataLength = connectors.connector && connectors.connector.length || 0;
|
|
tempMap[dsType].push(dsRef);
|
|
datasetStore.push (dsRef);
|
|
// Removing data plots if the number of current data plots is more than the existing ones.
|
|
if (prevDataLength > currDataLength) {
|
|
dsRef.removeData(currDataLength - 1,
|
|
prevDataLength - currDataLength);
|
|
}
|
|
dsRef.JSONData = connectors;
|
|
dsRef.configure();
|
|
dsTypeRef.shift();
|
|
}
|
|
count++;
|
|
}
|
|
|
|
dsType = 'labels';
|
|
dsTypeRef = datasetMap[dsType];
|
|
dsRef = dsTypeRef[0];
|
|
if (dsCount[dsType] === UNDEFINED) {
|
|
dsCount[dsType] = 0;
|
|
}
|
|
else {
|
|
dsCount[dsType]++;
|
|
}
|
|
if (!dsRef) {
|
|
labelObj = new DragLabelClass();
|
|
labelObj.chart = iapi;
|
|
tempMap[dsType].push(labelObj);
|
|
datasetStore.push(labelObj);
|
|
labelObj.init(labelSet);
|
|
GroupManager.addLabels(labelObj, 0);
|
|
}
|
|
else {
|
|
JSONData = dsRef.JSONData;
|
|
prevDataLength = JSONData.length;
|
|
currDataLength = labelsLength;
|
|
tempMap[dsType].push(dsRef);
|
|
datasetStore.push (dsRef);
|
|
// Removing data plots if the number of current data plots is more than the existing ones.
|
|
if (prevDataLength > currDataLength) {
|
|
dsRef.removeData(currDataLength - 1,
|
|
prevDataLength - currDataLength);
|
|
}
|
|
dsRef.JSONData = labelSet;
|
|
dsRef.configure();
|
|
dsTypeRef.shift();
|
|
}
|
|
|
|
iapi.config._datasetUpdated = true;
|
|
// Removing unused datasets if any
|
|
for (dataset in datasetMap) {
|
|
dsTypeRef = datasetMap[dataset];
|
|
length = dsTypeRef.length;
|
|
count = dsCount[dataset] || -1;
|
|
if (length) {
|
|
for (j = 0; j < length; j++) {
|
|
if (dataset === 'dragnode') {
|
|
|
|
GroupManager.removeNodeDataset(count);
|
|
GroupManager._clearConnectors();
|
|
legend.removeItem(dsTypeRef[j].legendItemId);
|
|
}
|
|
else if (dataset === 'connectors') {
|
|
GroupManager.removeConnectorSet(count);
|
|
}
|
|
else {
|
|
GroupManager.removeLabelSet(count);
|
|
}
|
|
componentDispose.call(dsTypeRef[j]);
|
|
count +=1;
|
|
}
|
|
}
|
|
}
|
|
config.datasetMap = tempMap;
|
|
},
|
|
addConfigureOptions: function () {
|
|
var chart = this,
|
|
chartMenuTools = chart.chartMenuTools,
|
|
components = chart.components,
|
|
actionBar = components.actionBar,
|
|
chartMenuBar =components.chartMenuBar,
|
|
manager = chart.components['datasetGroup_' + chart.defaultDatasetType],
|
|
componentGroup = (chartMenuBar || actionBar).componentGroups[0],
|
|
symbolList = componentGroup.symbolList[0],
|
|
sListRef = symbolList.getListRefernce(),
|
|
setChartTools = chartMenuTools.set,
|
|
viewMode = chart.config.viewMode,
|
|
configureTools = [
|
|
{
|
|
'Add Node' : {
|
|
handler: function () {
|
|
manager.showNodeAddUI();
|
|
},
|
|
action: 'click'
|
|
}
|
|
},
|
|
{
|
|
'Add Connector': {
|
|
handler: function () {
|
|
manager.showConnectorAddUI(manager.chart, {
|
|
|
|
});
|
|
},
|
|
action: 'click'
|
|
}
|
|
},
|
|
{
|
|
'Add Label': {
|
|
handler: function () {
|
|
manager.showLabelUpdateUI(manager.chart, {
|
|
|
|
});
|
|
},
|
|
action: 'click'
|
|
}
|
|
}
|
|
];
|
|
setChartTools(configureTools);
|
|
!viewMode && sListRef.appendAsList(configureTools);
|
|
},
|
|
// _createAxes: function () {
|
|
// var iapi = this,
|
|
// chartAttr = iapi.jsonData.chart,
|
|
// yAxis;
|
|
// chartAPI.mscartesian._createAxes.call(iapi);
|
|
// yAxis = iapi.components.yAxis[0];
|
|
// yAxis.setAxisConfig({
|
|
// showZeroPlane: pluckNumber(chartAttr.showzeroplane, 0),
|
|
// showZeroPlaneValue: pluckNumber(chartAttr.showzeroplanevalue, 1),
|
|
// showDivLineValues: pluckNumber(chartAttr.showdivlinevalues, 0)
|
|
// });
|
|
// },
|
|
_redrawDragNode: function (eventArgs, sourceEvent) {
|
|
var manager = this,
|
|
chart = manager.chart;
|
|
manager.draw();
|
|
lib.raiseEvent('chartUpdated', extend2({
|
|
sourceEvent: sourceEvent
|
|
}, eventArgs), chart.chartInstance, [chart.chartInstance.id]);
|
|
|
|
},
|
|
addNode: function (dataObj) {
|
|
var chart = this,
|
|
datasets = chart.components.dataset,
|
|
datasetId = dataObj.datasetId,
|
|
len = datasets.length,
|
|
dataset,
|
|
groupManager,
|
|
eventArgs,
|
|
index,
|
|
idFound,
|
|
id,
|
|
i,
|
|
sourceEvent = 'nodeAdded',
|
|
dataStore;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
dataset = datasets[i] || {};
|
|
id = dataset.config && dataset.config.id;
|
|
if (id !== UNDEFINED) {
|
|
id = id.toString();
|
|
}
|
|
if (id === datasetId) {
|
|
idFound = true;
|
|
break;
|
|
}
|
|
}
|
|
if (dataset && idFound) {
|
|
groupManager = dataset.groupManager,
|
|
dataStore = dataset.components.data;
|
|
dataObj.add = true;
|
|
// This is the index of the new data
|
|
index = dataStore.length;
|
|
eventArgs = {
|
|
index: index, // to be deprecated
|
|
dataIndex: index,
|
|
link: dataObj.link,
|
|
y: dataObj.y,
|
|
x: dataObj.x,
|
|
shape: dataObj.shape,
|
|
width: dataObj.width,
|
|
height: dataObj.height,
|
|
radius: dataObj.radius,
|
|
sides: dataObj.sides,
|
|
label: dataObj.name,
|
|
toolText: dataObj.tooltext,
|
|
id: dataObj.id,
|
|
datasetIndex: dataset.index,
|
|
datasetName: dataset.JSONData.seriesname,
|
|
sourceType: 'dataplot'
|
|
};
|
|
|
|
dataset._setConfigure(index, dataObj);
|
|
chart._redrawDragNode.call(groupManager, eventArgs, sourceEvent);
|
|
/**
|
|
* In `DragNode` charts, data points are represented as nodes whose
|
|
* properties like location(x,y), shape, dimensions and color can be added dynamically to
|
|
* the chart. Chart can contain any number of datasets and an index number is assigned to
|
|
* each dataset based upon order of dataset creation. This event is raised when a node is
|
|
* added by clicking on the menu button located at the left side bottom of the chart by
|
|
* default but can the menu button location can be changed.
|
|
*
|
|
* This event is only applicable to DragNode chart.
|
|
*
|
|
* @event FusionCharts#nodeAdded
|
|
* @group chart-powercharts:dragnode
|
|
*
|
|
* @param {number} datasetIndex - Index of the dataset to which the newly added
|
|
* node belongs to.
|
|
* @param {string} datasetName - Name of the dataset to which the node was added. Name of
|
|
* the dataset can be defined by the attribute `seriesName` for `dataset` tag in the chart
|
|
* data.
|
|
* @param {number} dataIndex - Index of the newly added node.
|
|
*
|
|
* @param {number} height - Height of the shape represented by the newly added node.
|
|
* @param {string} id - ID of the newly added node which can be set using `id` attribute
|
|
* for `set` tag.
|
|
*
|
|
* @param {string} label - Text displayed inside the shape of the newly added node.
|
|
* @param {string} link - URL associated with the newly added node.
|
|
* @param {number} radius - Radius of the circumcirle for the shape of the
|
|
* newly added node.
|
|
* @param {string} shape - Shape of the newly added node.
|
|
* @param {number} sides - Depending on the shape of the node it is the
|
|
* number of sides of the polygon. If it is a circle it will have 0 sides.
|
|
* @param {string} toolText - Text that is displayed over the shape of the
|
|
* newly added node.
|
|
* @param {number} width - Width of the shape of the newly added node.
|
|
* @param {number} x - X Co-ordinate of the newly added node in reference with
|
|
* the canvas / axis.
|
|
* @param {number} y - Y Co-ordinate of the newly added node in reference with
|
|
* the canvas / axis.
|
|
*/
|
|
global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
|
|
}
|
|
|
|
},
|
|
updateNode: function (updateObj) {
|
|
var chart = this,
|
|
groupManager = chart.components['datasetGroup_' + chart.defaultDatasetType],
|
|
datasets = groupManager.datasets,
|
|
len = datasets.length,
|
|
dataLen,
|
|
idFound,
|
|
dataset,
|
|
dataObj,
|
|
i,
|
|
dataStore,
|
|
eventArgs,
|
|
sourceEvent = 'nodeupdated',
|
|
j;
|
|
updateObj.update = true;
|
|
for (i = 0; i < len; i++) {
|
|
dataset = datasets[i].dataset;
|
|
dataStore = dataset.components.data || [];
|
|
dataLen = dataStore.length;
|
|
for (j = 0; j < dataLen; j++) {
|
|
dataObj = dataStore[j];
|
|
if (dataObj.config.id === updateObj.id) {
|
|
idFound = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dataset && idFound) {
|
|
eventArgs = {
|
|
index: j, // to be deprecated
|
|
dataIndex: j,
|
|
link: updateObj.link,
|
|
y: updateObj.y,
|
|
x: updateObj.x,
|
|
shape: updateObj.shape,
|
|
width: updateObj.width,
|
|
height: updateObj.height,
|
|
radius: updateObj.radius,
|
|
sides: updateObj.sides,
|
|
label: updateObj.name,
|
|
toolText: updateObj.tooltext,
|
|
id: updateObj.id,
|
|
datasetIndex: dataset.index,
|
|
datasetName: dataset.JSONData.seriesname,
|
|
sourceType: 'dataplot'
|
|
};
|
|
dataset._setConfigure(j, updateObj);
|
|
chart._redrawDragNode.call(groupManager, eventArgs, sourceEvent);
|
|
global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
|
|
}
|
|
|
|
},
|
|
|
|
deleteNode: function (id) {
|
|
var chart = this,
|
|
groupManager = chart.components['datasetGroup_' + chart.defaultDatasetType],
|
|
nodes = groupManager.nodes,
|
|
node = nodes[id],
|
|
dataset,
|
|
dataStore,
|
|
startConnectors,
|
|
endConnectors,
|
|
i,
|
|
graphics,
|
|
connector,
|
|
dataObj,
|
|
prop,
|
|
len,
|
|
eventArgs,
|
|
config,
|
|
idFound,
|
|
sourceEvent = 'nodedeleted',
|
|
removeElements = function (graphics) {
|
|
for (var i in graphics) {
|
|
graphics[i].remove();
|
|
}
|
|
};
|
|
if (node) {
|
|
dataset = node.dataset;
|
|
dataStore = dataset.components.data;
|
|
startConnectors = node.config.startConnectors;
|
|
endConnectors = node.config.endConnectors;
|
|
len = dataStore.length;
|
|
for (i = 0; i < len; i++) {
|
|
dataObj = dataStore[i];
|
|
if (dataObj.config.id === id) {
|
|
idFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (idFound === true) {
|
|
graphics = dataObj.graphics;
|
|
removeElements(graphics);
|
|
for (prop in startConnectors) {
|
|
connector = startConnectors[prop] || {};
|
|
graphics = connector.graphics;
|
|
removeElements(graphics);
|
|
delete connector.graphics;
|
|
connector.removed = true;
|
|
}
|
|
for (prop in endConnectors) {
|
|
connector = endConnectors[prop] || {};
|
|
graphics = connector.graphics;
|
|
removeElements(graphics);
|
|
delete connector.graphics;
|
|
connector.removed = true;
|
|
}
|
|
delete nodes[id];
|
|
dataObj.removed = true;
|
|
config = dataObj.config || {};
|
|
eventArgs = {
|
|
index: i,
|
|
dataIndex: i,
|
|
link: config.link,
|
|
y: config.y,
|
|
x: config.x,
|
|
shape: config.shape,
|
|
width: config.width,
|
|
height: config.height,
|
|
radius: config.radius,
|
|
sides: config.sides,
|
|
label: config.displayValue,
|
|
toolText: config.toolText,
|
|
id: config.id,
|
|
datasetIndex: i,
|
|
datasetName: dataset.JSONData.seriesname,
|
|
sourceType: 'dataplot'
|
|
};
|
|
lib.raiseEvent('chartUpdated', extend2({
|
|
sourceEvent: sourceEvent
|
|
}, eventArgs), chart.chartInstance, [chart.chartInstance.id]);
|
|
global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
|
|
}
|
|
}
|
|
|
|
},
|
|
addConnector: function (connectorObj) {
|
|
var chart = this,
|
|
groupManager = chart.components['datasetGroup_' + chart.defaultDatasetType],
|
|
connectorSets = groupManager.connectorSet,
|
|
connectors = connectorSets[0].connectors,
|
|
data = connectors.components.data,
|
|
sourceEvent = 'connectoradded',
|
|
eventArgs,
|
|
length = data.length;
|
|
connectorObj.add = true;
|
|
connectors._setConfigure(length, connectorObj);
|
|
eventArgs = {
|
|
arrowAtEnd: Boolean(connectorObj.arrowAtEnd),
|
|
arrowAtStart: Boolean(connectorObj.arrowAtStart),
|
|
fromNodeId: connectorObj.from,
|
|
id: connectorObj.id,
|
|
label: connectorObj.label,
|
|
link: connectorObj.connectorLink,
|
|
sourceType: 'connector',
|
|
toNodeId: connectorObj.to
|
|
};
|
|
chart._redrawDragNode.call(groupManager, eventArgs, sourceEvent);
|
|
global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
|
|
},
|
|
editConnector: function (connectorObj) {
|
|
var chart = this,
|
|
groupManager = chart.components['datasetGroup_' + chart.defaultDatasetType],
|
|
from = connectorObj.from,
|
|
to = connectorObj.to,
|
|
connectorSets = groupManager.connectorSet,
|
|
i,
|
|
conLen,
|
|
data,
|
|
dataObj,
|
|
fromId,
|
|
toId,
|
|
j,
|
|
idFound,
|
|
connectors,
|
|
config,
|
|
eventArgs,
|
|
sourceEvent = 'connectorupdated',
|
|
len = connectorSets.length;
|
|
for (i = 0; i < len; i++) {
|
|
connectors = connectorSets[i].connectors;
|
|
data = connectors && connectors.components.data || [];
|
|
conLen = data.length;
|
|
for (j = 0; j < conLen; j++) {
|
|
dataObj = data[j];
|
|
config = dataObj.config;
|
|
fromId = config.from;
|
|
toId = config.to;
|
|
if (fromId === from && toId === to) {
|
|
idFound = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
connectorObj.update = true;
|
|
if (idFound) {
|
|
connectors._setConfigure(j, connectorObj);
|
|
eventArgs = {
|
|
arrowAtEnd: Boolean(connectorObj.arrowatend),
|
|
arrowAtStart: Boolean(connectorObj.arrowatstart),
|
|
fromNodeId: connectorObj.from,
|
|
id: connectorObj.id,
|
|
label: connectorObj.label,
|
|
link: connectorObj.link,
|
|
sourceType: 'connector',
|
|
toNodeId: connectorObj.to
|
|
};
|
|
chart._redrawDragNode.call(groupManager, eventArgs, sourceEvent);
|
|
global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
|
|
}
|
|
|
|
|
|
},
|
|
deleteConnector: function (config) {
|
|
var chart = this,
|
|
groupManager = chart.components['datasetGroup_' + chart.defaultDatasetType],
|
|
from = config.from,
|
|
to = config.to,
|
|
connectorSets = groupManager.connectorSet,
|
|
i,
|
|
j,
|
|
dataObj,
|
|
dataStore,
|
|
dataLen,
|
|
connFound = false,
|
|
connectors,
|
|
eventArgs,
|
|
connConfig,
|
|
len = connectorSets.length,
|
|
sourceEvent = 'connectordeleted',
|
|
removeElements = function (graphics) {
|
|
var prop;
|
|
for (prop in graphics) {
|
|
graphics[prop].remove();
|
|
}
|
|
};
|
|
|
|
for (i = 0; i < len; i++) {
|
|
connectors = connectorSets[i].connectors;
|
|
dataStore = connectors.components.data;
|
|
dataLen = dataStore.length;
|
|
for (j = 0; j < dataLen; j++) {
|
|
dataObj = dataStore[j];
|
|
if (dataObj.config.from === from && dataObj.config.to === to) {
|
|
connFound = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (connFound) {
|
|
connConfig = dataObj.config || {};
|
|
eventArgs = {
|
|
arrowAtEnd: connConfig.arrowAtEnd,
|
|
arrowAtStart: connConfig.arrowAtStart,
|
|
fromNodeId: connConfig.from,
|
|
id: connConfig.id,
|
|
label: connConfig.label,
|
|
link: connConfig.connectorLink,
|
|
sourceType: 'connector',
|
|
toNodeId: connConfig.to
|
|
};
|
|
removeElements(dataObj.graphics);
|
|
delete dataObj.graphics;
|
|
// Mark data object as removed
|
|
dataObj.removed = true;
|
|
lib.raiseEvent('chartUpdated', extend2({
|
|
sourceEvent: sourceEvent
|
|
}, eventArgs), chart.chartInstance, [chart.chartInstance.id]);
|
|
global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
|
|
}
|
|
|
|
},
|
|
addLabel: function (labelObj) {
|
|
var chart = this,
|
|
manager = chart.components['datasetGroup_' + chart.defaultDatasetType],
|
|
labelSet = manager.labelSet,
|
|
DragLabelClass = FusionCharts.get(COMPONENT, [DATASET, 'DragableLabels']),
|
|
labelDS,
|
|
dataStore,
|
|
sourceEvent = 'labeladded',
|
|
eventArgs,
|
|
len;
|
|
labelObj.add = true;
|
|
if (!labelSet.length) {
|
|
labelDS = new DragLabelClass();
|
|
labelDS.chart = chart;
|
|
labelDS.init([labelObj]);
|
|
manager.addLabels(labelDS, 0);
|
|
}
|
|
else {
|
|
labelDS = manager.labelSet[0].labels,
|
|
dataStore = labelDS.components.data,
|
|
len = dataStore.length;
|
|
labelDS._setConfigure(len, labelObj);
|
|
}
|
|
|
|
eventArgs = {
|
|
text: labelObj.text,
|
|
x: labelObj.x,
|
|
y: labelObj.y,
|
|
allowdrag: labelObj.allowdrag,
|
|
sourceType: 'labelnode',
|
|
link: labelObj.link
|
|
};
|
|
|
|
chart._redrawDragNode.call(manager, eventArgs, sourceEvent);
|
|
|
|
global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
|
|
labelObj.add = true;
|
|
},
|
|
deleteLabel: function (index) {
|
|
var chart = this,
|
|
manager = chart.components['datasetGroup_' + chart.defaultDatasetType],
|
|
labels = manager.labelSet[0].labels,
|
|
dataStore = labels.components.data,
|
|
labelObj = dataStore[index],
|
|
labelElement,
|
|
eventArgs,
|
|
sourceEvent = 'labeldeleted';
|
|
|
|
labelElement = labelObj.graphics.element;
|
|
|
|
if (labelElement) {
|
|
eventArgs = labelElement.data('eventArgs');
|
|
labelElement.remove();
|
|
delete labelObj.graphics;
|
|
}
|
|
lib.raiseEvent('chartUpdated', extend2({
|
|
sourceEvent: sourceEvent
|
|
}, eventArgs), chart.chartInstance, [chart.chartInstance.id]);
|
|
|
|
global.raiseEvent(sourceEvent, eventArgs, chart.chartInstance);
|
|
labelObj.removed = true;
|
|
},
|
|
restoreData: function () {
|
|
var chart = this,
|
|
manager = chart.components['datasetGroup_' + chart.defaultDatasetType],
|
|
datasets = manager.datasets,
|
|
legend = chart.components.legend,
|
|
connectors = manager.connectorSet,
|
|
i,
|
|
dataset,
|
|
dataStore,
|
|
dataObj,
|
|
graphics,
|
|
labelObj,
|
|
labelSet = manager.labelSet,
|
|
removeElements = function (dataStore) {
|
|
var j,
|
|
ele;
|
|
for (j = 0; j < dataStore.length; j++) {
|
|
dataObj = dataStore[j];
|
|
delete dataObj.removed;
|
|
if (dataObj.config.add) {
|
|
graphics = dataStore[j].graphics;
|
|
for (ele in graphics) {
|
|
graphics[ele].remove();
|
|
}
|
|
}
|
|
|
|
}
|
|
};
|
|
for (i = 0; i < datasets.length; i++) {
|
|
dataset = datasets[i].dataset;
|
|
dataStore = dataset.components.data;
|
|
removeElements(dataStore);
|
|
dataset.drawn = false;
|
|
dataset.configure();
|
|
}
|
|
for (i = 0; i < connectors.length; i++) {
|
|
dataset = connectors[i].connectors;
|
|
dataStore = dataset.components.data;
|
|
removeElements(dataStore);
|
|
dataset.drawn = false;
|
|
dataset.configure();
|
|
}
|
|
if (labelSet.length) {
|
|
labelObj = labelSet[0].labels;
|
|
dataStore = labelObj.components.data;
|
|
removeElements(dataStore);
|
|
labelObj.configure();
|
|
}
|
|
chart._setAxisLimits();
|
|
chart._drawAxis();
|
|
chart._drawDataset();
|
|
legend._drawPointLegendItem();
|
|
lib.raiseEvent('dataRestored', {}, chart.chartInstance, [chart.chartInstance.id]);
|
|
},
|
|
getJSONData: function () {
|
|
var chart = this,
|
|
defaultDatasetType = chart.defaultDatasetType && chart.defaultDatasetType.toLowerCase(),
|
|
chartComponents = chart.components,
|
|
groupManager = chartComponents['datasetGroup_' + defaultDatasetType],
|
|
datasets = chartComponents.dataset,
|
|
rawObj = chart.jsonData,
|
|
len = datasets.length,
|
|
datasetsArr = [],
|
|
jsonObj,
|
|
dataObj,
|
|
dataset,
|
|
i;
|
|
if (groupManager) {
|
|
datasetsArr = groupManager.getJSONData();
|
|
}
|
|
else {
|
|
for (i = 0; i < len; i++) {
|
|
dataset = datasets[i];
|
|
dataObj = dataset.getJSONData();
|
|
datasetsArr.push(dataObj);
|
|
}
|
|
}
|
|
jsonObj = extend2({}, rawObj);
|
|
jsonObj.dataset = datasetsArr.dataset;
|
|
jsonObj.connectors = datasetsArr.connectors;
|
|
jsonObj.labels = datasetsArr.labels;
|
|
return jsonObj;
|
|
},
|
|
_setCategories: function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
dataObj = iapi.jsonData,
|
|
xAxis = components.xAxis,
|
|
categories = dataObj.categories && dataObj.categories[0].category || [],
|
|
catLen = categories.length,
|
|
catArr = [],
|
|
i,
|
|
catObj;
|
|
|
|
for (i = 0; i < catLen; i++) {
|
|
catObj = categories[i] || {};
|
|
if (catObj.x !== UNDEFINED) {
|
|
catArr.push(catObj);
|
|
}
|
|
}
|
|
|
|
xAxis && xAxis[0].setCategory(catArr);
|
|
},
|
|
_drawDataset : function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
defaultDatasetType = iapi.defaultDatasetType,
|
|
managerName = 'datasetGroup_' + defaultDatasetType,
|
|
groupManagerObj = components[managerName];
|
|
groupManagerObj && groupManagerObj.draw();
|
|
},
|
|
_setAxisLimits : function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
dataObj = iapi.jsonData,
|
|
categories = dataObj.categories && dataObj.categories[0].category || [],
|
|
category,
|
|
catX,
|
|
dataset = components.dataset,
|
|
yAxis = components.yAxis,
|
|
xAxis = components.xAxis,
|
|
currentDataset,
|
|
length = dataset.length,
|
|
i,
|
|
infMin = -Infinity,
|
|
infMax = +Infinity,
|
|
max = infMin,
|
|
min = infMax,
|
|
xMin = infMax,
|
|
xMax = infMin,
|
|
maxminObj,
|
|
groupManager,
|
|
xMaxValue,
|
|
xMinValue,
|
|
groupManagerObj = { },
|
|
noManager = [],
|
|
getMaxMin = function (maxminObj) {
|
|
xMaxValue = pluck(maxminObj.xMax, infMin);
|
|
xMinValue = pluck(maxminObj.xMin, infMax);
|
|
max = mathMax (max, maxminObj.max);
|
|
min = mathMin (min, maxminObj.min);
|
|
xMax = mathMax (xMax, xMaxValue);
|
|
xMin = mathMin (xMin, xMinValue);
|
|
|
|
};
|
|
|
|
for (i=0; i<length; i++) {
|
|
currentDataset = dataset[i];
|
|
groupManager = currentDataset.groupManager;
|
|
if (groupManager) {
|
|
groupManagerObj[currentDataset.type] = groupManager;
|
|
}
|
|
else {
|
|
noManager.push (currentDataset);
|
|
}
|
|
}
|
|
|
|
for (groupManager in groupManagerObj) {
|
|
maxminObj = groupManagerObj[groupManager].getDataLimits ();
|
|
getMaxMin (maxminObj);
|
|
}
|
|
|
|
length =noManager.length;
|
|
for (i=0; i<length; i++) {
|
|
maxminObj = noManager[i].getDataLimits ();
|
|
getMaxMin (maxminObj);
|
|
}
|
|
|
|
(max === -Infinity) && (max = 0);
|
|
(min === +Infinity) && (min = 0);
|
|
iapi.config.yMax = max;
|
|
iapi.config.yMin = min;
|
|
yAxis[0].setAxisConfig ( {
|
|
isPercent : iapi.isStacked ? iapi.config.stack100Percent : 0
|
|
});
|
|
yAxis[0].setDataLimit (max, min);
|
|
if ((xMax !== infMin) || (xMin !== infMax)) {
|
|
|
|
for (i = 0, length = categories.length; i < length; i++) {
|
|
category = categories[i];
|
|
if (catX = category.x) {
|
|
if (catX < xMin) {
|
|
xMin = catX;
|
|
}
|
|
if (catX > xMax) {
|
|
xMax = catX;
|
|
}
|
|
}
|
|
}
|
|
xAxis[0].setDataLimit (xMax, xMin);
|
|
}
|
|
}
|
|
}, chartAPI.dragbase);
|
|
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-dragarea', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
HUNDREDSTRING = lib.HUNDREDSTRING,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI;
|
|
|
|
/////////////// DragArea ///////////
|
|
chartAPI('dragarea', {
|
|
friendlyName: 'Dragable Area Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType: 'dragarea',
|
|
decimals: 2,
|
|
applicableDSList: {'dragarea': true}
|
|
}, chartAPI.dragbase, {
|
|
anchoralpha: HUNDREDSTRING,
|
|
enablemousetracking : true,
|
|
isDrag : true
|
|
}, chartAPI.areabase);
|
|
|
|
}]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dragline', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
chartAPI = lib.chartAPI,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);
|
|
/////////////// DragLine ///////////
|
|
chartAPI('dragline', {
|
|
friendlyName: 'Dragable Line Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
decimals: 2,
|
|
defaultDatasetType: 'dragline',
|
|
applicableDSList: {'dragline': true},
|
|
defaultPlotShadow: 1
|
|
}, chartAPI.dragbase, {
|
|
zeroplanethickness: 1,
|
|
zeroplanealpha: 40,
|
|
showzeroplaneontop: 0,
|
|
enablemousetracking : true,
|
|
isDrag : true
|
|
}, chartAPI.areabase);
|
|
|
|
}]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dragcolumn2d', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
chartAPI = lib.chartAPI,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);
|
|
|
|
/////////////// DragArea ///////////
|
|
chartAPI('dragcolumn2d', {
|
|
friendlyName: 'Dragable Column Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
decimals: 2,
|
|
defaultDatasetType: 'DragColumn',
|
|
applicableDSList: {'dragcolumn': true}
|
|
}, chartAPI.dragbase, {
|
|
enablemousetracking: true,
|
|
isDrag : true
|
|
});
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-selectscatter', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
getValidValue = lib.getValidValue,
|
|
COMMA = ',',
|
|
extend2 = lib.extend2, //old: jarendererExtend / margecolone
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
preDefStr = lib.preDefStr,
|
|
isIE = lib.isIE,
|
|
hasSVG = lib.hasSVG,
|
|
t = 't',
|
|
docMode8 = win.document.documentMode === 8,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
ROUND = preDefStr.ROUND,
|
|
POINTER = 'pointer',
|
|
math = Math,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
mathAbs = math.abs,
|
|
xssEncode = global.xssEncode,
|
|
hiddenStr = preDefStr.hiddenStr,
|
|
HIDDEN = hiddenStr,
|
|
visibleStr = preDefStr.visibleStr,
|
|
VISIBLE = docMode8 ? visibleStr : BLANKSTRING,
|
|
configStr = preDefStr.configStr,
|
|
TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
|
|
chartAPI = lib.chartAPI;
|
|
|
|
chartAPI('selectscatter', {
|
|
isXY: true,
|
|
hasLegend: true,
|
|
applicableDSList: {
|
|
'selectScatter': true
|
|
},
|
|
friendlyName: 'Dragable Scatter Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType: 'selectScatter',
|
|
defaultZeroPlaneHighlighted: false,
|
|
configure: chartAPI.dragbase.configure,
|
|
_createToolBox: chartAPI.dragbase._createToolBox,
|
|
_manageActionBarSpace: chartAPI.dragbase._manageActionBarSpace,
|
|
drawActionBar: chartAPI.dragbase.drawActionBar,
|
|
getData: function(format) {
|
|
// create a two dimensional array as given in the docs
|
|
var iapi = this,
|
|
dataObj = iapi.getCollatedData(),
|
|
returnObj = [],
|
|
datasets = dataObj.dataset,
|
|
length = (datasets && datasets.length) || 0,
|
|
index = 0,
|
|
NULLSTR = 'null',
|
|
dsInd = 0,
|
|
setLen,
|
|
set,
|
|
j;
|
|
|
|
|
|
// When a format is provided
|
|
if (format) {
|
|
// no transcoding needed for json
|
|
if (/^json$/ig.test(format)) {
|
|
returnObj = dataObj;
|
|
} else if (/^csv$/ig.test(format)) {
|
|
returnObj = iapi.getCSVString();
|
|
} else {
|
|
returnObj = global.core.transcodeData(dataObj,
|
|
'json', format);
|
|
}
|
|
}
|
|
// if no format has been specified, return data as 2d array.
|
|
else {
|
|
//while (length--) {
|
|
for (; index < length; index += 1) {
|
|
set = datasets[index];
|
|
if (set) {
|
|
set = datasets[index] && datasets[index].data;
|
|
j = setLen = (set && set.length) || 0;
|
|
j && (returnObj[dsInd] || (returnObj[dsInd] = [getValidValue(datasets[index].id,
|
|
NULLSTR)]));
|
|
while (j--) {
|
|
returnObj[dsInd][j + 1] = getValidValue(set[j].id, NULLSTR);
|
|
}
|
|
|
|
setLen && (dsInd += 1);
|
|
}
|
|
}
|
|
}
|
|
return returnObj;
|
|
},
|
|
|
|
getCSVString: function() {
|
|
var chart = this,
|
|
dataObj = chart.getData(),
|
|
i = dataObj.length;
|
|
|
|
while (i--) {
|
|
dataObj[i] = dataObj[i].join(COMMA);
|
|
}
|
|
|
|
return dataObj.join('|');
|
|
},
|
|
getCollatedData: function() {
|
|
var api = this,
|
|
chartInstance = api.chartInstance,
|
|
dataset = api.components.dataset,
|
|
selectedArr = api.config._selectEleArr,
|
|
len = selectedArr && selectedArr.length,
|
|
origChartData = extend2({}, chartInstance.getChartData(global.dataFormats.JSON)),
|
|
origDataSets = origChartData.dataset,
|
|
xPos,
|
|
yPos,
|
|
oriDataArr,
|
|
selectionBoxObj,
|
|
lenDS,
|
|
setObj,
|
|
dataLen,
|
|
startX,
|
|
endX,
|
|
startY,
|
|
endY,
|
|
selectedData = [];
|
|
|
|
while (len--) {
|
|
selectionBoxObj = selectedArr[len];
|
|
if (!selectionBoxObj) {
|
|
continue;
|
|
}
|
|
startX = selectionBoxObj.startX;
|
|
endX = selectionBoxObj.endX;
|
|
startY = selectionBoxObj.startY;
|
|
endY = selectionBoxObj.endY;
|
|
lenDS = origDataSets.length;
|
|
|
|
while (lenDS--) {
|
|
if (!dataset[lenDS].visible) {
|
|
continue;
|
|
}
|
|
selectedData[lenDS] || (selectedData[lenDS] = {
|
|
data: []
|
|
});
|
|
oriDataArr = origDataSets[lenDS].data;
|
|
dataLen = oriDataArr && oriDataArr.length;
|
|
while (dataLen--) {
|
|
setObj = oriDataArr[dataLen];
|
|
xPos = setObj.x;
|
|
yPos = setObj.y;
|
|
if (xPos > startX && xPos < endX &&
|
|
yPos < startY && yPos > endY) {
|
|
selectedData[lenDS].data[dataLen] = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
lenDS = origDataSets.length;
|
|
while (lenDS--) {
|
|
oriDataArr = origDataSets[lenDS].data;
|
|
dataLen = oriDataArr && oriDataArr.length;
|
|
while (dataLen--) {
|
|
if (!(selectedData[lenDS] && selectedData[lenDS].data[dataLen])) {
|
|
oriDataArr.splice(dataLen, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
//state.hasStaleData = false;
|
|
return (api.updatedDataObj = origChartData);
|
|
},
|
|
|
|
createSelectionBox: function(event) {
|
|
var chart = event.chart,
|
|
chartComponents = chart.components,
|
|
paper = chartComponents.paper,
|
|
chartConfig = chart.config,
|
|
yAxis = chartComponents.yAxis && chartComponents.yAxis[0],
|
|
xAxis = chartComponents.xAxis && chartComponents.xAxis[0],
|
|
x = event.selectionLeft,
|
|
y = event.selectionTop,
|
|
width = event.selectionWidth,
|
|
height = event.selectionHeight,
|
|
x2 = x + width,
|
|
y2 = y + height,
|
|
TRACKER_WIDTH = 12,
|
|
TRACKER_HALF_WIDTH = TRACKER_WIDTH * 0.5,
|
|
trackerRadius = 12,
|
|
resizeInnerSymbolColor = '#999999',
|
|
resizeOuterSymbolColor = '#777777',
|
|
closeButtonRadius = 6,
|
|
cornerSymbolRadius = 15,
|
|
isSmall = width > cornerSymbolRadius &&
|
|
height > cornerSymbolRadius,
|
|
selectEleObj = {
|
|
resizeEleRadius: cornerSymbolRadius,
|
|
canvasTop: chartConfig.canvasTop,
|
|
canvasRight: chartConfig.canvasLeft + chartConfig.canvasWidth,
|
|
canvasLeft: chartConfig.canvasLeft,
|
|
canvasBottom: chartConfig.canvasTop + chartConfig.canvasHeight
|
|
},
|
|
trackerG = chart.graphics.trackerGroup,
|
|
selectEleArr = chartConfig._selectEleArr || (chartConfig._selectEleArr = []),
|
|
selectBoxG;
|
|
|
|
//var TRACKER_FILL = 'rgba(255,0,0,0.3)';
|
|
|
|
selectEleObj.index = selectEleArr.length;
|
|
selectEleObj.id = 'SELECT_' + selectEleObj.index;
|
|
|
|
selectEleObj.selectBoxG = selectBoxG = paper.group('selection-box',
|
|
trackerG).toFront();
|
|
|
|
// Drawing the main box element
|
|
selectEleObj.selectBoxTracker = paper.rect(x, y, width, height, selectBoxG)
|
|
.attr({
|
|
'stroke-width': 1,
|
|
stroke: toRaphaelColor(chartConfig.selectBorderColor),
|
|
ishot: true,
|
|
fill: chartConfig.selectFillColor
|
|
})
|
|
.css({
|
|
cursor: 'move'
|
|
});
|
|
selectEleObj.selectBoxTracker.data(configStr, {
|
|
position: 6, // MOVE
|
|
selectEleObj: selectEleObj,
|
|
xChange: true,
|
|
yChange: true
|
|
});
|
|
|
|
// Draw top tracker element
|
|
selectEleObj.topTracker = paper.rect(x, y -
|
|
TRACKER_HALF_WIDTH, width, TRACKER_WIDTH, selectBoxG)
|
|
.attr({
|
|
'stroke-width': 0,
|
|
ishot: true,
|
|
fill: TRACKER_FILL
|
|
})
|
|
.css('cursor', hasSVG && 'ns-resize' || 'n-resize');
|
|
selectEleObj.topTracker.data(configStr, {
|
|
position: 1, // TOP
|
|
selectEleObj: selectEleObj,
|
|
yChange: true
|
|
});
|
|
|
|
// Draw right tracker element
|
|
selectEleObj.rightTracker = paper.rect(x + width -
|
|
TRACKER_HALF_WIDTH, y, TRACKER_WIDTH, height, selectBoxG)
|
|
.attr({
|
|
'stroke-width': 0,
|
|
ishot: true,
|
|
fill: TRACKER_FILL
|
|
})
|
|
.css('cursor', hasSVG && 'ew-resize' || 'w-resize');
|
|
selectEleObj.rightTracker.data(configStr, {
|
|
position: 2, // RIGHT
|
|
selectEleObj: selectEleObj,
|
|
xChange: true
|
|
});
|
|
|
|
// Draw bottom tracker element
|
|
selectEleObj.bottomTracker = paper.rect(x, y + height -
|
|
TRACKER_HALF_WIDTH, width, TRACKER_WIDTH, selectBoxG)
|
|
.attr({
|
|
'stroke-width': 0,
|
|
ishot: true,
|
|
fill: TRACKER_FILL
|
|
})
|
|
.css('cursor', hasSVG && 'ns-resize' || 'n-resize');
|
|
selectEleObj.bottomTracker.data(configStr, {
|
|
position: 3, // BOTTOM
|
|
selectEleObj: selectEleObj,
|
|
yChange: true
|
|
});
|
|
|
|
// Draw left tracker element
|
|
selectEleObj.leftTracker = paper.rect(x - TRACKER_HALF_WIDTH, y,
|
|
TRACKER_WIDTH, height, selectBoxG)
|
|
.attr({
|
|
'stroke-width': 0,
|
|
ishot: true,
|
|
fill: TRACKER_FILL
|
|
})
|
|
.css('cursor', hasSVG && 'ew-resize' || 'e-resize');
|
|
selectEleObj.leftTracker.data(configStr, {
|
|
position: 4, // LEFT
|
|
selectEleObj: selectEleObj,
|
|
xChange: true
|
|
});
|
|
|
|
selectEleObj.cornerInnerSymbol = paper.symbol('resizeIcon', 0, 0,
|
|
cornerSymbolRadius, selectBoxG)
|
|
.attr({
|
|
transform: t + x2 + COMMA + y2,
|
|
'stroke-width': 1,
|
|
visibility: isSmall ? VISIBLE : HIDDEN,
|
|
ishot: true,
|
|
stroke: resizeInnerSymbolColor
|
|
});
|
|
|
|
selectEleObj.cornerOuterSymbol = paper.symbol('resizeIcon', 0, 0, -cornerSymbolRadius * 0.8, selectBoxG)
|
|
.attr({
|
|
transform: t + x2 + COMMA + y2,
|
|
strokeWidth: 1,
|
|
visibility: !isSmall ? VISIBLE : HIDDEN,
|
|
ishot: true,
|
|
stroke: resizeOuterSymbolColor
|
|
});
|
|
|
|
selectEleObj.resizeTracker = paper.circle(x2, y2, trackerRadius, selectBoxG)
|
|
.attr({
|
|
'stroke-width': 1,
|
|
stroke: TRACKER_FILL,
|
|
ishot: true,
|
|
fill: TRACKER_FILL
|
|
})
|
|
.css('cursor', hasSVG && 'nwse-resize' || 'nw-resize');
|
|
selectEleObj.resizeTracker.data(configStr, {
|
|
position: 5, // Corner
|
|
selectEleObj: selectEleObj,
|
|
yChange: true,
|
|
xChange: true
|
|
});
|
|
|
|
selectEleObj.closeButton = paper.symbol('closeIcon', 0, 0, closeButtonRadius, selectBoxG)
|
|
.attr({
|
|
transform: 't' + x2 + COMMA + y,
|
|
'stroke-width': 2,
|
|
stroke: chartConfig.selectionCancelButtonBorderColor,
|
|
fill: chartConfig.selectionCancelButtonFillColor,
|
|
'stroke-linecap': ROUND,
|
|
ishot: true,
|
|
'stroke-linejoin': ROUND
|
|
})
|
|
.css({
|
|
cursor: POINTER,
|
|
_cursor: 'hand'
|
|
})
|
|
.click(function() { // Delete the selection
|
|
chart.deleteSelection(this, chart);
|
|
});
|
|
selectEleObj.closeButton.data(configStr, {
|
|
index: selectEleObj.index
|
|
});
|
|
|
|
selectEleObj.chart = chart;
|
|
selectEleObj.startX = xAxis.getValue(x - chartConfig.canvasLeft);
|
|
selectEleObj.startY = yAxis.getValue(y - chartConfig.canvasTop);
|
|
selectEleObj.endX = xAxis.getValue(x2 - chartConfig.canvasLeft);
|
|
selectEleObj.endY = yAxis.getValue(y2 - chartConfig.canvasTop);
|
|
selectEleObj.isVisible = true;
|
|
|
|
selectEleArr.push(selectEleObj);
|
|
chart.bindDragEvent(selectEleObj);
|
|
},
|
|
|
|
_deleteAllSelection : function () {
|
|
var chart = this,
|
|
selectEleArr = chart.config._selectEleArr,
|
|
selectEleObj,
|
|
selectEleItem,
|
|
items,
|
|
items1;
|
|
|
|
for (items in selectEleArr) {
|
|
if (selectEleArr.hasOwnProperty(items)) {
|
|
selectEleObj = selectEleArr[items];
|
|
for (items1 in selectEleObj) {
|
|
if (selectEleObj.hasOwnProperty(items1)) {
|
|
selectEleItem = selectEleObj[items1];
|
|
selectEleItem.remove && selectEleItem.remove();
|
|
delete selectEleObj[items1];
|
|
}
|
|
}
|
|
delete selectEleArr[items];
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
deleteSelection: function(ele, chart) {
|
|
var index = ele.data(configStr).index,
|
|
chartComponents = chart.components,
|
|
selectEleArr = chart.config._selectEleArr,
|
|
selectEleObj = selectEleArr[index],
|
|
selectT = selectEleObj.selectBoxTracker,
|
|
selectEleItem,
|
|
items,
|
|
bBox,
|
|
eventArgs;
|
|
bBox = selectT.getBBox();
|
|
eventArgs = {
|
|
selectionLeft: bBox.x,
|
|
selectionTop: bBox.y,
|
|
selectionWidth: bBox.width,
|
|
selectionHeight: bBox.height,
|
|
startXValue: chartComponents.xAxis[0].getAxisPosition(bBox.x, 1),
|
|
startYValue: chartComponents.yAxis[0].getAxisPosition(bBox.y, 1),
|
|
endXValue: chartComponents.xAxis[0].getAxisPosition(bBox.x + bBox.width, 1),
|
|
endYValue: chartComponents.yAxis[0].getAxisPosition(bBox.y + bBox.height, 1),
|
|
data: chart.getCollatedData(),
|
|
id: selectEleObj.id
|
|
};
|
|
|
|
for (items in selectEleObj) {
|
|
if (selectEleObj.hasOwnProperty(items)) {
|
|
selectEleItem = selectEleObj[items];
|
|
selectEleItem.remove && selectEleItem.remove();
|
|
delete selectEleObj[items];
|
|
}
|
|
}
|
|
delete selectEleArr[index];
|
|
/**
|
|
* This event is raised when the selection of a SelectScatter chart is removed. This happens when one
|
|
* clicks the close button on a selection that one has made on the chart.
|
|
*
|
|
* @event FusionCharts#selectionRemoved
|
|
* @group chart-powercharts:selectscatter
|
|
*
|
|
* @param {object} data - This returns the subset of data that was selected.
|
|
*/
|
|
global.raiseEvent('selectionRemoved', eventArgs, chart.chartInstance);
|
|
},
|
|
|
|
bindDragEvent: function(selectEleObj) {
|
|
var chart = this,
|
|
//logic = chart.logic,
|
|
item;
|
|
for (item in selectEleObj) {
|
|
/Tracker/.test(item) && selectEleObj[item].drag(chart.move,
|
|
chart.start, chart.up);
|
|
}
|
|
},
|
|
|
|
start: function() {
|
|
var ele = this,
|
|
data = ele.data(configStr),
|
|
selectEleObj = data.selectEleObj,
|
|
|
|
topT = selectEleObj.topTracker,
|
|
rightT = selectEleObj.rightTracker,
|
|
bottomT = selectEleObj.bottomTracker,
|
|
leftT = selectEleObj.leftTracker,
|
|
resizeT = selectEleObj.resizeTracker,
|
|
|
|
topTData = topT.data(configStr),
|
|
rightTData = rightT.data(configStr),
|
|
bottomTData = bottomT.data(configStr),
|
|
leftTData = leftT.data(configStr),
|
|
resizeTData = resizeT.data(configStr),
|
|
selectTData = selectEleObj.selectBoxTracker.data(configStr),
|
|
bBox = selectEleObj.selectBoxTracker.getBBox();
|
|
|
|
topTData.ox = bBox.x;
|
|
topTData.oy = bBox.y;
|
|
|
|
rightTData.ox = bBox.x2;
|
|
rightTData.oy = bBox.y;
|
|
|
|
bottomTData.ox = bBox.x;
|
|
bottomTData.oy = bBox.y2;
|
|
|
|
leftTData.ox = bBox.x;
|
|
leftTData.oy = bBox.y;
|
|
|
|
topTData.ox = bBox.x;
|
|
topTData.oy = bBox.y;
|
|
|
|
resizeTData.ox = bBox.x2;
|
|
resizeTData.oy = bBox.y2;
|
|
|
|
selectTData.ox = bBox.x;
|
|
selectTData.oy = bBox.y;
|
|
selectTData.ow = bBox.width;
|
|
selectTData.oh = bBox.height;
|
|
selectTData.ox2 = bBox.x2;
|
|
selectTData.oy2 = bBox.y2;
|
|
// on click take the selection box on top.
|
|
selectEleObj.selectBoxG.toFront();
|
|
|
|
topT.hide();
|
|
rightT.hide();
|
|
bottomT.hide();
|
|
leftT.hide();
|
|
resizeT.hide();
|
|
ele.show();
|
|
},
|
|
|
|
move: function(dx, dy) {
|
|
var ele = this,
|
|
data = ele.data(configStr),
|
|
selectEleObj = data.selectEleObj,
|
|
chart = selectEleObj.chart,
|
|
chartConfig = chart.config,
|
|
chartComponents = chart.components,
|
|
topT = selectEleObj.topTracker,
|
|
rightT = selectEleObj.rightTracker,
|
|
bottomT = selectEleObj.bottomTracker,
|
|
leftT = selectEleObj.leftTracker,
|
|
resizeT = selectEleObj.resizeTracker,
|
|
selectT = selectEleObj.selectBoxTracker,
|
|
canvasLeft = selectEleObj.canvasLeft,
|
|
canvasRight = selectEleObj.canvasRight,
|
|
canvasTop = selectEleObj.canvasTop,
|
|
canvasBottom = selectEleObj.canvasBottom,
|
|
HALF_T_WID = -6,
|
|
selectTData = selectT.data(configStr),
|
|
attrib = {},
|
|
bBox,
|
|
eventArgs,
|
|
x,
|
|
y;
|
|
|
|
dx = data.xChange ? dx : 0;
|
|
dy = data.yChange ? dy : 0;
|
|
|
|
x = dx + data.ox;
|
|
y = dy + data.oy;
|
|
|
|
x = mathMin(canvasRight - (data.ow || 0), mathMax(x, canvasLeft));
|
|
y = mathMin(canvasBottom - (data.oh || 0), mathMax(y, canvasTop));
|
|
|
|
|
|
switch (data.position) {
|
|
case 1: // TOP
|
|
attrib.y = mathMin(selectTData.oy2, y);
|
|
attrib.height = mathAbs(selectTData.oy2 - y) || 1;
|
|
topT.attr({
|
|
y: y + HALF_T_WID
|
|
});
|
|
break;
|
|
case 2: // Right
|
|
attrib.x = mathMin(selectTData.ox, x);
|
|
attrib.width = mathAbs(selectTData.ox - x) || 1;
|
|
rightT.attr({
|
|
x: x + HALF_T_WID
|
|
});
|
|
break;
|
|
case 3: // Bottom
|
|
attrib.y = mathMin(selectTData.oy, y);
|
|
attrib.height = mathAbs(selectTData.oy - y) || 1;
|
|
bottomT.attr({
|
|
y: y + HALF_T_WID
|
|
});
|
|
break;
|
|
case 4: // Left
|
|
attrib.x = mathMin(selectTData.ox2, x);
|
|
attrib.width = mathAbs(selectTData.ox2 - x) || 1;
|
|
leftT.attr({
|
|
x: x + HALF_T_WID
|
|
});
|
|
break;
|
|
case 5: // Corner
|
|
attrib.x = mathMin(selectTData.ox, x);
|
|
attrib.width = mathAbs(selectTData.ox - x) || 1;
|
|
attrib.y = mathMin(selectTData.oy, y);
|
|
attrib.height = mathAbs(selectTData.oy - y) || 1;
|
|
resizeT.attr({
|
|
cx: x,
|
|
cy: y
|
|
});
|
|
break;
|
|
default:
|
|
attrib.x = x;
|
|
attrib.y = y;
|
|
break;
|
|
}
|
|
|
|
if (!ele.data('dragStarted')) {
|
|
bBox = selectT.getBBox();
|
|
|
|
eventArgs = {
|
|
selectionLeft: bBox.x,
|
|
selectionTop: bBox.y,
|
|
selectionWidth: bBox.width,
|
|
selectionHeight: bBox.height,
|
|
startXValue: chartComponents.xAxis[0].getValue(bBox.x - chartConfig.canvasLeft),
|
|
startYValue: chartComponents.yAxis[0].getValue(bBox.y - chartConfig.canvasTop),
|
|
endXValue: chartComponents.xAxis[0].getValue(bBox.x + bBox.width - chartConfig.canvasLeft),
|
|
endYValue: chartComponents.yAxis[0].getValue(bBox.y + bBox.height - chartConfig.canvasTop),
|
|
id: selectEleObj.id
|
|
};
|
|
|
|
global.raiseEvent('BeforeSelectionUpdate', eventArgs, chart.chartInstance);
|
|
ele.data('dragStarted', 1);
|
|
}
|
|
|
|
selectT.animate(attrib);
|
|
|
|
if (selectEleObj.isVisible) {
|
|
selectEleObj.closeButton.hide();
|
|
selectEleObj.cornerInnerSymbol.hide();
|
|
selectEleObj.cornerOuterSymbol.hide();
|
|
selectEleObj.isVisible = false;
|
|
}
|
|
},
|
|
|
|
up: function() {
|
|
var ele = this,
|
|
data = ele.data(configStr),
|
|
selectEleObj = data.selectEleObj,
|
|
chart = selectEleObj.chart,
|
|
chartComponents = chart.components,
|
|
chartConfig = chart.config,
|
|
xAxis = chartComponents.xAxis && chartComponents.xAxis[0],
|
|
yAxis = chartComponents.yAxis && chartComponents.yAxis[0],
|
|
topT = selectEleObj.topTracker,
|
|
rightT = selectEleObj.rightTracker,
|
|
bottomT = selectEleObj.bottomTracker,
|
|
leftT = selectEleObj.leftTracker,
|
|
resizeT = selectEleObj.resizeTracker,
|
|
selectT = selectEleObj.selectBoxTracker,
|
|
RESIZE_T_RADIUS = 15,
|
|
HALF_T_WID = -6,
|
|
bBox,
|
|
eventArgs;
|
|
|
|
// using setTimeout to fix for the issue #RED-476.
|
|
setTimeout(function() {
|
|
bBox = selectT.getBBox(),
|
|
|
|
selectEleObj.startX = xAxis.getValue(bBox.x - chartConfig.canvasLeft);
|
|
selectEleObj.startY = yAxis.getValue(bBox.y - chartConfig.canvasTop);
|
|
selectEleObj.endX = xAxis.getValue(bBox.x2 - chartConfig.canvasLeft);
|
|
selectEleObj.endY = yAxis.getValue(bBox.y2 - chartConfig.canvasTop);
|
|
|
|
topT.attr({
|
|
x: bBox.x,
|
|
y: bBox.y + HALF_T_WID,
|
|
width: bBox.width
|
|
});
|
|
rightT.attr({
|
|
x: bBox.x2 + HALF_T_WID,
|
|
y: bBox.y,
|
|
height: bBox.height
|
|
});
|
|
bottomT.attr({
|
|
x: bBox.x,
|
|
y: bBox.y2 + HALF_T_WID,
|
|
width: bBox.width
|
|
});
|
|
leftT.attr({
|
|
x: bBox.x + HALF_T_WID,
|
|
y: bBox.y,
|
|
height: bBox.height
|
|
});
|
|
resizeT.attr({
|
|
cx: bBox.x2,
|
|
cy: bBox.y2
|
|
});
|
|
|
|
selectEleObj.closeButton.transform(t + bBox.x2 + COMMA + bBox.y);
|
|
selectEleObj.cornerInnerSymbol.transform(t + bBox.x2 + COMMA + bBox.y2);
|
|
selectEleObj.cornerOuterSymbol.transform(t + bBox.x2 + COMMA + bBox.y2);
|
|
selectEleObj.closeButton.show();
|
|
if (bBox.width < RESIZE_T_RADIUS || bBox.height < RESIZE_T_RADIUS) {
|
|
selectEleObj.cornerInnerSymbol.hide();
|
|
selectEleObj.cornerOuterSymbol.show();
|
|
} else {
|
|
selectEleObj.cornerInnerSymbol.show();
|
|
selectEleObj.cornerOuterSymbol.hide();
|
|
}
|
|
selectEleObj.isVisible = true;
|
|
|
|
topT.show();
|
|
rightT.show();
|
|
bottomT.show();
|
|
leftT.show();
|
|
resizeT.show();
|
|
|
|
if (ele.data('dragStarted')) {
|
|
eventArgs = {
|
|
selectionLeft: bBox.x,
|
|
selectionTop: bBox.y,
|
|
selectionWidth: bBox.width,
|
|
selectionHeight: bBox.height,
|
|
startXValue: chartComponents.xAxis[0].getValue(bBox.x - chartConfig.canvasLeft),
|
|
startYValue: chartComponents.yAxis[0].getValue(bBox.y - chartConfig.canvasTop),
|
|
endXValue: chartComponents.xAxis[0].getValue(bBox.x + bBox.width - chartConfig.canvasLeft),
|
|
endYValue: chartComponents.yAxis[0].getValue(bBox.y + bBox.height - chartConfig.canvasTop),
|
|
data: chart.getCollatedData(),
|
|
id: selectEleObj.id
|
|
};
|
|
global.raiseEvent('SelectionUpdated', eventArgs, chart.chartInstance);
|
|
ele.data('dragStarted', 0);
|
|
}
|
|
|
|
}, 100);
|
|
},
|
|
|
|
restoreData: function () {
|
|
var chart = this,
|
|
datasets = chart.components.dataset,
|
|
i;
|
|
|
|
chart._deleteAllSelection();
|
|
for (i = 0; i < datasets.length; i++) {
|
|
datasets[i].draw();
|
|
|
|
}
|
|
lib.raiseEvent('dataRestored', {}, chart.chartInstance, [chart.chartInstance.id]);
|
|
return true;
|
|
},
|
|
|
|
submitData: function () {
|
|
var chart = this,
|
|
iapi = chart.chartInstance,
|
|
ajaxObj = new global.ajax(),
|
|
chartConf = chart.config,
|
|
json = global.dataFormats.JSON,
|
|
csv = global.dataFormats.CSV,
|
|
xml = global.dataFormats.XML,
|
|
url = chartConf.formAction || '',
|
|
submitAsAjax = chartConf.submitFormAsAjax,
|
|
requestType,
|
|
data,
|
|
paramObj,
|
|
tempSpan,
|
|
formEle;
|
|
|
|
if (chartConf.formDataFormat === json) {
|
|
requestType = json;
|
|
data = JSON.stringify(chart.getCollatedData());
|
|
} else if (chart.formDataFormat === csv) {
|
|
requestType = csv;
|
|
data = iapi.getCSVString && iapi.getCSVString();
|
|
if (data === undefined) {
|
|
data = global.core.transcodeData(chart.getCollatedData(), json, csv);
|
|
}
|
|
} else {
|
|
requestType = xml;
|
|
data = global.core.transcodeData(chart.getCollatedData(), json, xml);
|
|
}
|
|
|
|
// cancel data submit function added in event options
|
|
/**
|
|
* For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc., data
|
|
* points value can be selected for `Scatter Chart` and values can be changed for dragable charts by
|
|
* clicking and dragging the data points whose data point values can be sent to an URL by ajax POST.
|
|
* This is the first event raised when `Submit` button is clicked where the current chart data is
|
|
* about to be sent to the set URL.
|
|
*
|
|
* @event FusionCharts#beforeDataSubmit
|
|
* @group chart-powercharts
|
|
*
|
|
* @param {string} data - Contains the XML string with complete chart data at it's current state.
|
|
*
|
|
*/
|
|
global.raiseEvent('beforeDataSubmit', {
|
|
data: data
|
|
}, iapi, undefined, function() {
|
|
// After the collation is done, we have to submit the data using
|
|
// ajax or form submit method.
|
|
if (!submitAsAjax) {
|
|
// Create a hidden form with data inside it.
|
|
tempSpan = win.document.createElement('span');
|
|
tempSpan.innerHTML = '<form style="display:none" action="' +
|
|
url + '" method="' + chartConf.formMethod + '" target="' + chartConf.formTarget +
|
|
'"> <input type="hidden" name="strXML" value="' +
|
|
xssEncode(data) + '"><input type="hidden" name="dataFormat" value="' +
|
|
requestType.toUpperCase() + '" /></form>';
|
|
|
|
formEle = tempSpan.removeChild(tempSpan.firstChild);
|
|
|
|
// Append the form to body and then submit it.
|
|
win.document.body.appendChild(formEle);
|
|
formEle.submit && formEle.submit();
|
|
// cleanup
|
|
formEle.parentNode.removeChild(formEle);
|
|
tempSpan = formEle = null;
|
|
}
|
|
else {
|
|
ajaxObj.onError = function(response, wrapper, ajaxData, url) {
|
|
/**
|
|
* For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc.,
|
|
* data points value can be selected for `Scatter Chart` and values can be changed for
|
|
* dragable charts by clicking and dragging the data points whose data point values can be
|
|
* sent to an URL by ajax POST. This event is raised if there is an ajax error in sending
|
|
* the chart XML data.
|
|
*
|
|
* @event FusionCharts#dataSubmitError
|
|
* @group chart-powercharts
|
|
*
|
|
* @param {string} data - Contains the XML string with complete chart data.
|
|
* @param {number} httpStatus - Tells the status code of the ajax POST request
|
|
* @param {string} statusText - Contains the ajax error message.
|
|
* @param {string} url - URL to which the data is sent as ajax POST request.
|
|
* @param {object} xhrObject - XMLHttpRequest object which takes care of sending the XML
|
|
* chart data. In case of error, this object won't be defined.
|
|
*/
|
|
lib.raiseEvent('dataSubmitError', {
|
|
xhrObject: wrapper.xhr,
|
|
url: url,
|
|
statusText: response,
|
|
httpStatus: (wrapper.xhr && wrapper.xhr.status) ?
|
|
wrapper.xhr.status : -1,
|
|
data: data
|
|
}, iapi, [iapi.id, response, wrapper.xhr && wrapper.xhr.status]);
|
|
};
|
|
|
|
ajaxObj.onSuccess = function(response, wrapper, ajaxData, url) {
|
|
/**
|
|
* For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc.,
|
|
* data points value can be selected for `Scatter Chart` and values can be changed for
|
|
* dragable charts by clicking and dragging the data points whose data point values can be
|
|
* sent to an URL by ajax POST. This event is raised when the ajax POST request is
|
|
* successfully completed.
|
|
*
|
|
* @event FusionCharts#dataSubmitted
|
|
* @group chart-powercharts
|
|
*
|
|
* @param {string} data - Contains the XML string with complete chart data.
|
|
* @param {string} reponse - Contains the reponse returned by the web server to which the
|
|
* HTTP POST request was submitted.
|
|
* @param {string} url - URL to which the data is sent as HTTP POST request.
|
|
* @param {object} xhrObject - XMLHttpRequest object which takes care of sending the XML
|
|
* chart data
|
|
*/
|
|
lib.raiseEvent('dataSubmitted', {
|
|
xhrObject: ajaxObj,
|
|
response: response,
|
|
url: url,
|
|
data: data
|
|
}, iapi, [iapi.id, response]);
|
|
};
|
|
|
|
paramObj = {};
|
|
paramObj['str' + requestType.toUpperCase()] = data;
|
|
|
|
if (ajaxObj.open) {
|
|
ajaxObj.abort();
|
|
}
|
|
ajaxObj.post(url, paramObj);
|
|
}
|
|
}, function() {
|
|
/**
|
|
* For interative charts like `Select Scatter`, `DragNode`, `Dragable Column2D ` and etc.,
|
|
* data points value can be selected for `Scatter Chart` and values can be changed for
|
|
* dragable charts by clicking and dragging the data points whose data point values can be
|
|
* sent to an URL by ajax POST. This event is raised when `preventDefault()` method is called
|
|
* from the `eventObject` of FusionCharts#beforeDataSubmit event.
|
|
*
|
|
* @event FusionCharts#dataSubmitCancelled
|
|
* @group chart-powercharts
|
|
*
|
|
* @param {string} data - Contains the XML string with complete chart data.
|
|
* @param {number} httpStatus - Tells the status code of the ajax POST request
|
|
* @param {string} statusText - Contains the ajax error message.
|
|
* @param {string} url - URL to which the data is sent as ajax POST request.
|
|
* @param {object} xhrObject - XMLHttpRequest object which takes care of sending the XML
|
|
* chart data. In case of error, this object won't be defined.
|
|
* @example
|
|
* FusionCharts.addEventListener('beforeDataSubmit', function(eventObject, parameterObject) {
|
|
* eventObject.preventDefault();
|
|
* }
|
|
*/
|
|
global.raiseEvent('dataSubmitCancelled', {
|
|
data: data
|
|
}, iapi);
|
|
});
|
|
},
|
|
|
|
_postSpaceManagement: function () {
|
|
var iapi = this;
|
|
|
|
chartAPI('mscartesian')._postSpaceManagement.call(iapi);
|
|
iapi._deleteAllSelection();
|
|
},
|
|
|
|
eiMethods : {
|
|
getData: function(format) {
|
|
var apiInstance = this.apiInstance;
|
|
return apiInstance && apiInstance.getData(format);
|
|
},
|
|
restoreData: function() {
|
|
var apiInstance = this.apiInstance;
|
|
return apiInstance && apiInstance.restoreData();
|
|
},
|
|
submitData: function() {
|
|
var apiInstance = this.apiInstance;
|
|
return apiInstance && apiInstance.submitData();
|
|
}
|
|
}
|
|
|
|
}, chartAPI.scatterBase, {
|
|
enablemousetracking: true,
|
|
allowreversexaxis: true
|
|
});
|
|
|
|
}]);
|
|
|
|
FusionCharts.register ('module', ['private', 'modules.renderer.js-candlestick', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
|
|
chartAPI = lib.chartAPI,
|
|
pluck = lib.pluck,
|
|
convertColor = lib.graphics.convertColor,
|
|
preDefStr = lib.preDefStr,
|
|
altHGridColorStr = preDefStr.altHGridColorStr,
|
|
altHGridAlphaStr = preDefStr.altHGridAlphaStr,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
COLUMN = preDefStr.column,
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
UNDEFINED,
|
|
componentDispose = lib.componentDispose,
|
|
VOLUME = preDefStr.volume,
|
|
POSITION_RIGHT = lib.POSITION_RIGHT,
|
|
math = Math,
|
|
mathMax = math.max,
|
|
mathRound = math.round,
|
|
POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
MAX_MITER_LINEJOIN = 2,
|
|
ROUND = preDefStr.ROUND,
|
|
miterStr = preDefStr.miterStr,
|
|
NONE = 'none',
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
AXIS = 'axis',
|
|
divLineAlpha3DStr = preDefStr.divLineAlpha3DStr,
|
|
defaultFontStr = preDefStr.defaultFontStr,
|
|
pluckFontSize = lib.pluckFontSize, // To get the valid font size (filters negative values)
|
|
divLineAlphaStr = preDefStr.divLineAlphaStr,
|
|
altVGridColorStr = preDefStr.altVGridColorStr,
|
|
altVGridAlphaStr = preDefStr.altVGridAlphaStr,
|
|
colorStrings = preDefStr.colors,
|
|
mathMin = math.min,
|
|
COLOR_000000 = colorStrings.c000000,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
chartPaletteStr = lib.chartPaletteStr = {
|
|
chart2D: {
|
|
bgColor : 'bgColor',
|
|
bgAlpha : 'bgAlpha',
|
|
bgAngle : 'bgAngle',
|
|
bgRatio : 'bgRatio',
|
|
canvasBgColor : 'canvasBgColor',
|
|
canvasBaseColor : 'canvasBaseColor',
|
|
divLineColor : 'divLineColor',
|
|
legendBgColor : 'legendBgColor',
|
|
legendBorderColor : 'legendBorderColor',
|
|
toolTipbgColor : 'toolTipbgColor',
|
|
toolTipBorderColor : 'toolTipBorderColor',
|
|
baseFontColor : 'baseFontColor',
|
|
anchorBgColor : 'anchorBgColor'
|
|
},
|
|
chart3D : {
|
|
bgColor : 'bgColor3D',
|
|
bgAlpha : 'bgAlpha3D',
|
|
bgAngle : 'bgAngle3D',
|
|
bgRatio : 'bgRatio3D',
|
|
canvasBgColor : 'canvasBgColor3D',
|
|
canvasBaseColor : 'canvasBaseColor3D',
|
|
divLineColor : 'divLineColor3D',
|
|
divLineAlpha : divLineAlpha3DStr,
|
|
legendBgColor : 'legendBgColor3D',
|
|
legendBorderColor : 'legendBorderColor3D',
|
|
toolTipbgColor : 'toolTipbgColor3D',
|
|
toolTipBorderColor : 'toolTipBorderColor3D',
|
|
baseFontColor : 'baseFontColor3D',
|
|
anchorBgColor : 'anchorBgColor3D'
|
|
}
|
|
},
|
|
extend2 = lib.extend2, //old: jarendererExtend / margecolone
|
|
pluckNumber = lib.pluckNumber;
|
|
|
|
chartAPI('candlestick', {
|
|
friendlyName: 'Candlestick Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
paletteIndex: 3,
|
|
defaultDatasetType: 'candlestick',
|
|
hasLegend: true,
|
|
applicableDSList: {'candlestick': true},
|
|
canvasborderthickness: 1,
|
|
hasInteractiveLegend: false,
|
|
init: function (container, dataObj, chartobj, callBack) {
|
|
var iapi = this,
|
|
components;
|
|
|
|
// chartAttrs = dataObj.chart = (dataObj.chart || dataObj.graph ||
|
|
// // dataObj.map || { });
|
|
iapi.jsonData = dataObj;
|
|
components = iapi.components = iapi.components || (iapi.components = {});
|
|
|
|
components.canvasVolume = components.canvasVolume || (components.canvasVolume = {
|
|
graphics: {},
|
|
config: {}
|
|
});
|
|
|
|
chartAPI.mscartesian.init.call(iapi, container, dataObj, chartobj, callBack);
|
|
|
|
},
|
|
configure: function () {
|
|
var iapi = this,
|
|
config,
|
|
volumeHeightPercent,
|
|
canvasConfig,
|
|
colorM = iapi.components.colorManager,
|
|
vCanvasConf,
|
|
chartAttrs = iapi.jsonData.chart,
|
|
components = iapi.components;
|
|
iapi.base.configure.call(this);
|
|
config = iapi.config;
|
|
canvasConfig = components.canvas.config;
|
|
config.showVolumeChart = pluckNumber(chartAttrs.showvolumechart, 1);
|
|
volumeHeightPercent = pluckNumber(chartAttrs.volumeheightpercent, 40);
|
|
config.volumeHeightPercent = volumeHeightPercent < 20 ? 20 : (volumeHeightPercent > 80 ? 80 :
|
|
volumeHeightPercent);
|
|
config.canvasBorderWidth = pluckNumber(chartAttrs.canvasborderthickness, 1);
|
|
config.rollOverBandColor = convertColor(
|
|
pluck(chartAttrs.rolloverbandcolor, colorM.getColor(altHGridColorStr)),
|
|
pluck(chartAttrs.rolloverbandalpha, colorM.getColor(altHGridAlphaStr)));
|
|
vCanvasConf = components.canvasVolume.config;
|
|
extend2(vCanvasConf, canvasConfig);
|
|
},
|
|
_createDatasets : function () {
|
|
var iapi = this,
|
|
config = iapi.config,
|
|
components = iapi.components,
|
|
//graphics = iapi.graphics,
|
|
//datasetGroup = graphics.datasetGroup,
|
|
dataObj = iapi.jsonData,
|
|
chartAttr = dataObj.chart,
|
|
dataset = dataObj.dataset,
|
|
trendset = dataObj.trendset || [],
|
|
showVolumeChart = iapi.config.showVolumeChart,
|
|
length = dataset && dataset.length,
|
|
i,
|
|
datasetStore,
|
|
datasetObj,
|
|
defaultSeriesType = iapi.defaultDatasetType,
|
|
plotType = pluck(parseUnsafeString(chartAttr.plotpriceas), COLUMN),
|
|
dsType,
|
|
DsClass,
|
|
datasetJSON,
|
|
JSONData,
|
|
prevDataLength,
|
|
currDataLength,
|
|
count = 0,
|
|
// map,line,area,column, stores the index of the various dataplots in combinational charts.
|
|
datasetMap = config.datasetMap || (config.datasetMap = {
|
|
trendset : [],
|
|
candlestick : []
|
|
}),
|
|
dsTypeRef,
|
|
dsRef,
|
|
dsCount = {},
|
|
tempMap = {
|
|
trendset: [],
|
|
candlestick : []
|
|
},
|
|
datasetComp,
|
|
j,
|
|
vYAxis,
|
|
legend = components.legend,
|
|
obj;
|
|
|
|
if (!dataset) {
|
|
iapi.setChartMessage();
|
|
return;
|
|
}
|
|
|
|
iapi.config.categories = dataObj.categories && dataObj.categories[0].category;
|
|
|
|
datasetStore = components.dataset = [];
|
|
|
|
for(i = 0, length = dataset.length; i < length; i++) {
|
|
|
|
datasetJSON = dataset[i];
|
|
datasetJSON.seriesname && (datasetJSON.seriesname = parseUnsafeString(datasetJSON.seriesname));
|
|
dsType = pluck(datasetJSON.renderas, defaultSeriesType);
|
|
dsType = dsType && dsType.toLowerCase();
|
|
/// get the DsClass
|
|
DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
|
|
dsTypeRef = datasetMap[dsType];
|
|
dsRef = dsTypeRef[0];
|
|
|
|
if (DsClass) {
|
|
if (dsCount[dsType] === UNDEFINED) {
|
|
dsCount[dsType] = 0;
|
|
}
|
|
else {
|
|
dsCount[dsType]++;
|
|
}
|
|
// create the dataset Object
|
|
if (!dsRef) {
|
|
datasetObj = new DsClass();
|
|
datasetStore.push(datasetObj);
|
|
tempMap[dsType].push(datasetObj);
|
|
datasetObj.chart = iapi;
|
|
datasetObj.index = count;
|
|
datasetObj.init(datasetJSON);
|
|
}
|
|
else {
|
|
datasetComp = dsRef;
|
|
dsRef.index = i;
|
|
if (plotType !== datasetComp.config.plotType) {
|
|
componentDispose.call(datasetComp);
|
|
datasetObj = datasetStore[count] = new DsClass();
|
|
datasetObj.chart = iapi;
|
|
datasetObj.index = count;
|
|
datasetObj.init(datasetJSON);
|
|
dsRef = datasetObj;
|
|
}
|
|
else {
|
|
JSONData = dsRef.JSONData;
|
|
prevDataLength = JSONData && JSONData.data && JSONData.data.length;
|
|
currDataLength = datasetJSON.data && datasetJSON.data.length;
|
|
// Removing data plots if the number of
|
|
// current data plots is more than the existing ones.
|
|
if (prevDataLength > currDataLength) {
|
|
dsRef.removeData(currDataLength - 1,
|
|
prevDataLength - currDataLength, false);
|
|
}
|
|
dsRef.JSONData = datasetJSON;
|
|
}
|
|
dsRef.configure();
|
|
tempMap[dsType].push(dsRef);
|
|
datasetStore.push (dsRef);
|
|
dsTypeRef.shift();
|
|
}
|
|
}
|
|
count++;
|
|
|
|
vYAxis = components.yAxis && components.yAxis[1];
|
|
if (showVolumeChart && iapi.config.drawVolume) {
|
|
vYAxis && vYAxis.show();
|
|
if (DsClass) {
|
|
if (dsCount[dsType] === UNDEFINED) {
|
|
dsCount[dsType] = 0;
|
|
}
|
|
else {
|
|
dsCount[dsType]++;
|
|
}
|
|
dsTypeRef = datasetMap[dsType];
|
|
dsRef = dsTypeRef[0];
|
|
if (!dsRef) {
|
|
datasetObj = new DsClass();
|
|
datasetObj.chart = iapi;
|
|
datasetStore.push(datasetObj);
|
|
tempMap[dsType].push(datasetObj);
|
|
datasetObj.init(datasetJSON, VOLUME);
|
|
}
|
|
else {
|
|
JSONData = dsRef.JSONData;
|
|
prevDataLength = JSONData && JSONData.data && JSONData.data.length;
|
|
currDataLength = datasetJSON.data && datasetJSON.data.length;
|
|
// Removing data plots if the number of current
|
|
// data plots is more than the existing ones.
|
|
if (prevDataLength > currDataLength) {
|
|
dsRef.removeData(currDataLength - 1,
|
|
prevDataLength - currDataLength, false);
|
|
}
|
|
dsRef.JSONData = datasetJSON;
|
|
dsRef.configure();
|
|
datasetStore.push (dsRef);
|
|
tempMap[dsType].push(dsRef);
|
|
dsTypeRef.shift();
|
|
}
|
|
}
|
|
count++;
|
|
}
|
|
else {
|
|
vYAxis && vYAxis.hide();
|
|
}
|
|
if (iapi.config.drawVolume && showVolumeChart) {
|
|
showVolumeChart = iapi.config.showVolumeChart = 1;
|
|
}
|
|
else {
|
|
showVolumeChart = iapi.config.showVolumeChart = 0;
|
|
}
|
|
}
|
|
for (i = 0,length = trendset.length; i < length; i++) {
|
|
datasetJSON = trendset[i];
|
|
dsType = 'trendset';
|
|
dsTypeRef = datasetMap[dsType];
|
|
dsRef = dsTypeRef[0];
|
|
if (dsCount[dsType] === UNDEFINED) {
|
|
dsCount[dsType] = 0;
|
|
}
|
|
else {
|
|
dsCount[dsType]++;
|
|
}
|
|
if (!dsRef) {
|
|
DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
|
|
obj = new DsClass();
|
|
datasetStore.push(obj);
|
|
tempMap[dsType].push(obj);
|
|
obj.chart = iapi;
|
|
obj.index = count;
|
|
obj.init(datasetJSON);
|
|
}
|
|
else {
|
|
JSONData = dsRef.JSONData;
|
|
prevDataLength = JSONData && JSONData.data && JSONData.data.length;
|
|
currDataLength = datasetJSON.data && datasetJSON.data.length;
|
|
tempMap[dsType].push(dsRef);
|
|
datasetStore.push (dsRef);
|
|
dsRef.index = count;
|
|
// Removing data plots if the number of current data plots is more than the existing ones.
|
|
if (prevDataLength > currDataLength) {
|
|
dsRef.removeData(currDataLength - 1,
|
|
prevDataLength - currDataLength, false);
|
|
}
|
|
dsRef.JSONData = datasetJSON;
|
|
dsRef.configure();
|
|
|
|
dsTypeRef.shift();
|
|
}
|
|
count++;
|
|
}
|
|
|
|
// Removing unused datasets if any
|
|
for (dataset in datasetMap) {
|
|
dsTypeRef = datasetMap[dataset];
|
|
length = dsTypeRef.length;
|
|
count = dsCount[dataset] || -1;
|
|
if (length) {
|
|
for (j = 0; j < length; j++) {
|
|
legend.removeItem(dsTypeRef[j].legendItemId);
|
|
componentDispose.call(dsTypeRef[j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
config.datasetMap = tempMap;
|
|
|
|
},
|
|
_spaceManager: function () {
|
|
// todo marge _allocateSpace and _spacemanager
|
|
var spaceForActionBar,
|
|
actionBarSpace,
|
|
availableWidth,
|
|
availableHeight,
|
|
iapi = this,
|
|
config = iapi.config,
|
|
components = iapi.components,
|
|
legendPosition = config.legendPosition,
|
|
xAxis = components.xAxis && components.xAxis[0],
|
|
vxAxis = components.xAxis && components.xAxis[1],
|
|
yAxis = components.yAxis && components.yAxis[0],
|
|
yAxis2 = components.yAxis && components.yAxis[1],
|
|
hasLegend = iapi.hasLegend,
|
|
legend = components.legend,
|
|
canvasHeight,
|
|
xAxisDimensions,
|
|
showVolumeChart = iapi.config.showVolumeChart,
|
|
volumeHeightPercent = showVolumeChart ? config.volumeHeightPercent : 0,
|
|
canvasConfig = components.canvas.config,
|
|
vCanvasConfig = components.canvasVolume.config,
|
|
vCanvasY,
|
|
padding = 6,
|
|
canvasY,
|
|
xAxis2dimensions,
|
|
yAxisDim,
|
|
vYAxisDim,
|
|
width = config.width,
|
|
height = config.height,
|
|
actualYDim = {},
|
|
allottedSpace,
|
|
chartBorderWidth = config.chartBorderWidth,
|
|
canvasBorderWidth = components.canvas.config.canvasBorderWidth,
|
|
minCanvasHeight = config.minCanvasHeight,
|
|
minCanvasWidth = config.minCanvasWidth,
|
|
canvasMarginLeft = config.canvasMarginLeft,
|
|
canvasMarginRight = config.canvasMarginRight,
|
|
canvasMarginTop = config.canvasMarginTop,
|
|
canvasMarginBottom = config.canvasMarginBottom,
|
|
diff,
|
|
currentCanvasHeight,
|
|
currentCanvasWidth,
|
|
heightAdjust,
|
|
origCanvasTopMargin = config.origCanvasTopMargin,
|
|
origCanvasBottomMargin = config.origCanvasBottomMargin,
|
|
origCanvasLeftMargin = config.origCanvasLeftMargin,
|
|
origCanvasRightMargin = config.origCanvasRightMargin,
|
|
left,
|
|
right,
|
|
top,
|
|
bottom,
|
|
|
|
widthAdjust,
|
|
sum;
|
|
// Manage space
|
|
|
|
iapi._allocateSpace ( {
|
|
top : chartBorderWidth,
|
|
bottom : chartBorderWidth,
|
|
left : chartBorderWidth,
|
|
right : chartBorderWidth
|
|
});
|
|
|
|
// iapi._allocateSpace ( {
|
|
// left : config.canvasMarginLeft,
|
|
// right : config.canvasMarginRight
|
|
// });
|
|
|
|
spaceForActionBar = config.availableHeight * 0.225;
|
|
actionBarSpace = iapi._manageActionBarSpace && iapi._manageActionBarSpace(spaceForActionBar) ||
|
|
{};
|
|
iapi._allocateSpace(actionBarSpace);
|
|
|
|
if (legendPosition === POSITION_RIGHT) {
|
|
allottedSpace = config.canvasWidth * 0.225;
|
|
}
|
|
else {
|
|
allottedSpace = config.canvasHeight * 0.3;
|
|
}
|
|
((hasLegend !== false) && xAxis) &&
|
|
iapi._allocateSpace(legend._manageLegendPosition(allottedSpace));
|
|
availableWidth = config.canvasWidth * 0.7;
|
|
yAxisDim = yAxis.placeAxis(availableWidth);
|
|
vYAxisDim = showVolumeChart ? yAxis2.placeAxis(availableWidth) : {};
|
|
actualYDim.left = mathMax(yAxisDim.left, vYAxisDim.left || 0);
|
|
actualYDim.right = mathMax(yAxisDim.right, vYAxisDim.right || 0);
|
|
iapi._allocateSpace(actualYDim);
|
|
|
|
// Check for minimun canvas width for applying canvas left and right margin.
|
|
if (minCanvasWidth > width - canvasMarginLeft - canvasMarginRight) {
|
|
widthAdjust = true;
|
|
diff = config.canvasWidth - minCanvasWidth;
|
|
sum = canvasMarginLeft + canvasMarginRight;
|
|
canvasMarginLeft = config.canvasMarginLeft = diff * canvasMarginLeft / sum;
|
|
canvasMarginRight = config.canvasMarginRight = diff * canvasMarginRight / sum;
|
|
}
|
|
|
|
// Calculating the left and right canvas margin.
|
|
left = canvasMarginLeft > config.canvasLeft ? (canvasMarginLeft - config.canvasLeft) : 0;
|
|
right = canvasMarginRight > (width - config.canvasRight) ? (canvasMarginRight +
|
|
config.canvasRight - width) : 0;
|
|
|
|
iapi._allocateSpace ( {
|
|
left : left,
|
|
right : right
|
|
});
|
|
|
|
// Forcing canvas width to its minimum
|
|
if (widthAdjust) {
|
|
sum = origCanvasLeftMargin + origCanvasRightMargin;
|
|
currentCanvasWidth = config.canvasWidth;
|
|
if (currentCanvasWidth > minCanvasWidth) {
|
|
diff = currentCanvasWidth - minCanvasWidth;
|
|
left = diff * origCanvasLeftMargin / sum;
|
|
right = diff * origCanvasRightMargin / sum;
|
|
}
|
|
iapi._allocateSpace ( {
|
|
left : left,
|
|
right : right
|
|
});
|
|
}
|
|
|
|
availableHeight = config.canvasHeight * 0.225;
|
|
|
|
availableHeight = (legendPosition === POSITION_BOTTOM) ? config.canvasHeight * 0.6 :
|
|
config.canvasWidth * 0.6;
|
|
// a space manager that manages the space for the tools as well as the captions.
|
|
iapi._manageChartMenuBar(availableHeight);
|
|
|
|
iapi._allocateSpace ( {
|
|
top : config.canvasMarginTop,
|
|
bottom : config.canvasMarginBottom
|
|
});
|
|
|
|
availableHeight = config.canvasHeight * 0.3;
|
|
xAxisDimensions = xAxis.placeAxis(availableHeight);
|
|
xAxis && iapi._allocateSpace(xAxisDimensions);
|
|
xAxisDimensions.bottom += padding;
|
|
canvasConfig.intermediarySpace = xAxisDimensions.bottom;
|
|
if (showVolumeChart) {
|
|
xAxis2dimensions = vxAxis.placeAxis(availableHeight);
|
|
iapi._allocateSpace(xAxis2dimensions);
|
|
}
|
|
iapi._allocateSpace({
|
|
top : canvasBorderWidth,
|
|
bottom : canvasBorderWidth * 2,
|
|
left : canvasBorderWidth,
|
|
right : canvasBorderWidth
|
|
});
|
|
|
|
// Check for minimum canvas height for applying top and bottom margin.
|
|
if (minCanvasHeight > height - canvasMarginTop - canvasMarginBottom) {
|
|
heightAdjust = true;
|
|
diff = config.canvasHeight - minCanvasHeight;
|
|
sum = canvasMarginTop + canvasMarginBottom;
|
|
canvasMarginTop = config.canvasMarginTop = diff * canvasMarginTop / sum;
|
|
canvasMarginBottom = config.canvasMarginBottom = diff * canvasMarginBottom / sum;
|
|
}
|
|
|
|
// Allocate space for canvas margin only if the margin is less than the margin entered by the user.
|
|
top = canvasMarginTop > config.canvasTop ? (canvasMarginTop - config.canvasTop) : 0;
|
|
bottom = canvasMarginBottom > (height - config.canvasBottom) ? (canvasMarginBottom +
|
|
config.canvasBottom - height) : 0;
|
|
|
|
iapi._allocateSpace ( {
|
|
top : top,
|
|
bottom : bottom
|
|
});
|
|
|
|
// Forcing canvas height to its minimum
|
|
if (heightAdjust) {
|
|
sum = origCanvasTopMargin + origCanvasBottomMargin;
|
|
currentCanvasHeight = config.canvasHeight;
|
|
if (currentCanvasHeight > minCanvasHeight) {
|
|
diff = currentCanvasHeight - minCanvasHeight;
|
|
top = diff * origCanvasTopMargin / sum;
|
|
bottom = diff * origCanvasBottomMargin / sum;
|
|
}
|
|
iapi._allocateSpace ( {
|
|
top : top,
|
|
bottom : bottom
|
|
});
|
|
}
|
|
canvasHeight = config.canvasHeight;
|
|
canvasConfig.canvasHeight = mathRound((100 - volumeHeightPercent)/100 * canvasHeight);
|
|
vCanvasConfig.canvasHeight = ((volumeHeightPercent/100) * canvasHeight);
|
|
|
|
canvasConfig.canvasTop = config.canvasTop;
|
|
canvasConfig.canvasLeft = config.canvasLeft;
|
|
canvasConfig.canvasBottom = canvasConfig.canvasTop + canvasConfig.canvasHeight;
|
|
canvasConfig.canvasWidth = config.canvasWidth;
|
|
canvasConfig.canvasRight = config.canvasRight;
|
|
vCanvasConfig.canvasTop = canvasConfig.canvasBottom + xAxisDimensions.bottom +
|
|
(canvasBorderWidth * 2);
|
|
vCanvasConfig.canvasLeft = config.canvasLeft;
|
|
vCanvasConfig.canvasBottom = vCanvasConfig.canvasTop + vCanvasConfig.canvasHeight +
|
|
(canvasBorderWidth * 2);
|
|
vCanvasConfig.canvasRight = config.canvasRight;
|
|
vCanvasConfig.canvasWidth = config.canvasWidth;
|
|
|
|
canvasY = config.canvasTop + canvasConfig.canvasHeight + canvasBorderWidth;
|
|
vCanvasY = config.canvasTop + canvasConfig.canvasHeight + xAxisDimensions.bottom +
|
|
(canvasBorderWidth * 2);
|
|
canvasConfig.canvasY = canvasY;
|
|
vCanvasConfig.canvasY = vCanvasY;
|
|
},
|
|
_postSpaceManagement : function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
showVolumeChart = iapi.config.showVolumeChart,
|
|
xAxis = components.xAxis && components.xAxis[0],
|
|
yAxis = components.yAxis && components.yAxis[0],
|
|
vxAxis = components.xAxis && components.xAxis[1],
|
|
vyAxis = components.yAxis && components.yAxis[1],
|
|
canvasConfig = components.canvas.config,
|
|
legend = components.legend,
|
|
vCanvasConfig = components.canvasVolume.config,
|
|
canvasBorderWidth = canvasConfig.canvasBorderWidth;
|
|
|
|
xAxis && xAxis.setAxisDimention({
|
|
x : canvasConfig.canvasLeft,
|
|
y : canvasConfig.canvasY,
|
|
opposite : canvasConfig.canvasTop - canvasBorderWidth,
|
|
axisLength : canvasConfig.canvasWidth
|
|
});
|
|
yAxis && yAxis.setAxisDimention({
|
|
x : canvasConfig.canvasLeft - canvasBorderWidth,
|
|
y : canvasConfig.canvasTop,
|
|
opposite : canvasConfig.canvasRight + canvasBorderWidth,
|
|
axisLength : canvasConfig.canvasHeight
|
|
});
|
|
|
|
if (showVolumeChart) {
|
|
vxAxis && vxAxis.setAxisDimention({
|
|
x : canvasConfig.canvasLeft,
|
|
y : vCanvasConfig.canvasBottom,
|
|
opposite : vCanvasConfig.canvasTop - canvasBorderWidth,
|
|
axisLength : canvasConfig.canvasWidth
|
|
});
|
|
vyAxis && vyAxis.setAxisDimention({
|
|
x : canvasConfig.canvasLeft - canvasBorderWidth,
|
|
y : vCanvasConfig.canvasY,
|
|
opposite : vCanvasConfig.canvasRight + canvasBorderWidth,
|
|
axisLength : vCanvasConfig.canvasHeight
|
|
});
|
|
vxAxis && vxAxis.setCanvas(vCanvasConfig);
|
|
vyAxis && vyAxis.setCanvas(vCanvasConfig);
|
|
}
|
|
xAxis.setCanvas(canvasConfig);
|
|
yAxis.setCanvas(canvasConfig);
|
|
legend.postSpaceManager();
|
|
},
|
|
_drawCanvas: function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
chartGraphics = iapi.graphics,
|
|
paper = components.paper,
|
|
canvas = components.canvas,
|
|
topCanvas = components.canvas.config,
|
|
clip = topCanvas.clip || (topCanvas.clip = []),
|
|
volumeCanvas = components.canvasVolume.config,
|
|
graphics = canvas.graphics,
|
|
vCanvasGraphics = components.canvasVolume.graphics,
|
|
config = canvas.config,
|
|
topCanvasElement = graphics.topCanvas,
|
|
topCanvasBorderElement = graphics.topCanvasBorderElement,
|
|
volumeCanvasElement = vCanvasGraphics.volumeCanvas,
|
|
canvasLeft = topCanvas.canvasLeft,
|
|
canvasTop = topCanvas.canvasTop,
|
|
canvasWidth = topCanvas.canvasWidth,
|
|
canvasHeight = topCanvas.canvasHeight,
|
|
vCanvasTop = volumeCanvas.canvasTop,
|
|
vCanvasHeight = volumeCanvas.canvasHeight,
|
|
canvasGroup = chartGraphics.canvasGroup,
|
|
canvasBorderRadius = config.canvasBorderRadius,
|
|
canvasBorderWidth = config.canvasBorderWidth,
|
|
borderWHlf = canvasBorderWidth * 0.5,
|
|
canvasBorderColor = config.canvasBorderColor,
|
|
animationObj = iapi.get(configStr, animationObjStr),
|
|
dummyAnimElem = animationObj.dummyObj,
|
|
dummyAnimObj = animationObj.animObj,
|
|
animType = animationObj.animType,
|
|
transposeAnimDuration = animationObj.transposeAnimDuration,
|
|
canvasBgColor,
|
|
attr1,
|
|
attr2,
|
|
topBorderAttr,
|
|
showVolumeChart = iapi.config.showVolumeChart,
|
|
shadow = config.shadow,
|
|
shadowOnCanvasFill = config.shadowOnCanvasFill;
|
|
|
|
canvasBgColor = config.canBGColor;
|
|
// Upper canvas border attributes
|
|
topBorderAttr = {
|
|
x: canvasLeft - borderWHlf,
|
|
y: canvasTop - borderWHlf,
|
|
width: canvasWidth + canvasBorderWidth,
|
|
height: canvasHeight + canvasBorderWidth,
|
|
r: canvasBorderRadius,
|
|
'stroke-width': canvasBorderWidth,
|
|
stroke: canvasBorderColor,
|
|
'stroke-linejoin': canvasBorderWidth > MAX_MITER_LINEJOIN ? ROUND : miterStr
|
|
};
|
|
|
|
if (!topCanvasBorderElement) {
|
|
topCanvasBorderElement = graphics.topCanvasBorderElement = paper.rect(topBorderAttr, canvasGroup)
|
|
.shadow(shadow);
|
|
}
|
|
else {
|
|
if (transposeAnimDuration) {
|
|
topCanvasBorderElement.animateWith(dummyAnimElem, dummyAnimObj, {
|
|
x: canvasLeft - borderWHlf,
|
|
y: canvasTop - borderWHlf,
|
|
width: canvasWidth + canvasBorderWidth,
|
|
height: canvasHeight + canvasBorderWidth,
|
|
r: canvasBorderRadius
|
|
}, transposeAnimDuration, animType);
|
|
}
|
|
else {
|
|
topCanvasBorderElement.attr(topBorderAttr);
|
|
}
|
|
}
|
|
|
|
topCanvasBorderElement.attr({
|
|
'stroke-width': canvasBorderWidth,
|
|
stroke: canvasBorderColor,
|
|
'stroke-linejoin': canvasBorderWidth > MAX_MITER_LINEJOIN ? ROUND : miterStr
|
|
});
|
|
clip['clip-canvas'] = [
|
|
mathMax (0, canvasLeft),
|
|
mathMax (0, canvasTop),
|
|
mathMax (1, canvasWidth),
|
|
mathMax (1, canvasHeight)
|
|
];
|
|
clip['clip-canvas-init'] = [
|
|
mathMax (0, canvasLeft),
|
|
mathMax (0, canvasTop),
|
|
1,
|
|
mathMax (1, canvasHeight)
|
|
];
|
|
|
|
if (!topCanvasElement) {
|
|
graphics.topCanvas = topCanvasElement = paper.rect(canvasGroup);
|
|
topCanvasElement.attr({
|
|
x: canvasLeft,
|
|
y: canvasTop,
|
|
width: canvasWidth,
|
|
height: canvasHeight
|
|
})
|
|
.shadow(shadowOnCanvasFill);
|
|
}
|
|
else {
|
|
if (transposeAnimDuration) {
|
|
topCanvasElement.animate({
|
|
x: canvasLeft,
|
|
y: canvasTop,
|
|
width: canvasWidth,
|
|
height: canvasHeight
|
|
}, transposeAnimDuration, animType)
|
|
.attr({
|
|
r: canvasBorderRadius
|
|
});
|
|
}
|
|
else {
|
|
topCanvasElement.attr(attr1);
|
|
}
|
|
}
|
|
|
|
topCanvasElement.animateWith(dummyAnimElem, dummyAnimObj, {
|
|
x: canvasLeft,
|
|
y: canvasTop,
|
|
width: canvasWidth,
|
|
height: canvasHeight
|
|
}, transposeAnimDuration, animType);
|
|
|
|
topCanvasElement.attr({
|
|
r: canvasBorderRadius,
|
|
'stroke-width': 0,
|
|
'stroke': NONE,
|
|
fill: toRaphaelColor(canvasBgColor)
|
|
});
|
|
|
|
if (showVolumeChart) {
|
|
|
|
attr2 = {
|
|
x: canvasLeft - borderWHlf,
|
|
y: vCanvasTop - borderWHlf - 1,
|
|
width: canvasWidth + canvasBorderWidth,
|
|
height: vCanvasHeight + canvasBorderWidth
|
|
};
|
|
|
|
if (!volumeCanvasElement) {
|
|
vCanvasGraphics.volumeCanvas = volumeCanvasElement = paper.rect(canvasGroup)
|
|
.attr(attr2)
|
|
.shadow(shadowOnCanvasFill)
|
|
.crisp();
|
|
}
|
|
|
|
volumeCanvasElement.show().animateWith(dummyAnimElem, dummyAnimObj, attr2,
|
|
transposeAnimDuration, animType).attr({
|
|
r: canvasBorderRadius,
|
|
fill: toRaphaelColor(canvasBgColor),
|
|
'stroke-width': canvasBorderWidth,
|
|
stroke: canvasBorderColor,
|
|
'stroke-linejoin': canvasBorderWidth > 2 ?
|
|
ROUND : miterStr,
|
|
'shape-rendering': 'crisp'
|
|
});
|
|
}
|
|
else {
|
|
volumeCanvasElement && volumeCanvasElement.hide();
|
|
}
|
|
|
|
},
|
|
_createAxes: function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
yAxis1,
|
|
CartesianAxis = FusionCharts.register(COMPONENT, [AXIS, 'cartesian']),
|
|
showVolumeChart = iapi.config.showVolumeChart,
|
|
yAxis,
|
|
xAxis,
|
|
vxAxis;
|
|
|
|
components.yAxis = [];
|
|
components.xAxis = [];
|
|
components.yAxis[0] = yAxis = new CartesianAxis();
|
|
components.yAxis[1] = yAxis1 = new CartesianAxis();
|
|
|
|
components.xAxis[0] = xAxis = new CartesianAxis();
|
|
yAxis.chart = iapi;
|
|
yAxis1.chart = iapi;
|
|
xAxis.chart = iapi;
|
|
if (showVolumeChart) {
|
|
components.xAxis[1] = vxAxis = new CartesianAxis();
|
|
vxAxis.chart = iapi;
|
|
vxAxis.init();
|
|
}
|
|
|
|
yAxis.init();
|
|
yAxis1.init();
|
|
|
|
xAxis.init();
|
|
// set the chart categories
|
|
iapi._setCategories();
|
|
},
|
|
_feedAxesRawData: function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
colorM = components.colorManager,
|
|
dataObj = iapi.jsonData,
|
|
chartAttrs = dataObj.chart,
|
|
xAxisConf,
|
|
yAxis1,
|
|
yAxisConf,
|
|
vYAxisConf,
|
|
is3d = iapi.is3d,
|
|
palleteString = is3d ? chartPaletteStr.chart3D : chartPaletteStr.chart2D,
|
|
CartesianAxis = FusionCharts.register(COMPONENT, [AXIS, 'cartesian']),
|
|
yAxis,
|
|
xAxis,
|
|
showVolumeChart = iapi.config.showVolumeChart,
|
|
vxAxis,
|
|
vxAxisConf;
|
|
xAxisConf = {
|
|
outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
|
|
outCanfontSize: pluckFontSize(chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
|
|
outCancolor: pluck(chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
|
|
colorM.getColor(palleteString.baseFontColor)).replace(/^#?([a-f0-9]+)/ig, '#$1'),
|
|
axisNamePadding: chartAttrs.xaxisnamepadding,
|
|
axisValuePadding: chartAttrs.labelpadding,
|
|
axisNameFont: chartAttrs.xaxisnamefont,
|
|
axisNameFontSize: chartAttrs.xaxisnamefontsize,
|
|
axisNameFontColor: chartAttrs.xaxisnamefontcolor,
|
|
axisNameFontBold: chartAttrs.xaxisnamefontbold,
|
|
axisNameFontItalic: chartAttrs.xaxisnamefontitalic,
|
|
axisNameBgColor: chartAttrs.xaxisnamebgcolor,
|
|
axisNameBorderColor: chartAttrs.xaxisnamebordercolor,
|
|
axisNameAlpha: chartAttrs.xaxisnamealpha,
|
|
axisNameFontAlpha: chartAttrs.xaxisnamefontalpha,
|
|
axisNameBgAlpha: chartAttrs.xaxisnamebgalpha,
|
|
axisNameBorderAlpha: chartAttrs.xaxisnameborderalpha,
|
|
axisNameBorderPadding: chartAttrs.xaxisnameborderpadding,
|
|
axisNameBorderRadius: chartAttrs.xaxisnameborderradius,
|
|
axisNameBorderThickness: chartAttrs.xaxisnameborderthickness,
|
|
axisNameBorderDashed: chartAttrs.xaxisnameborderdashed,
|
|
axisNameBorderDashLen: chartAttrs.xaxisnameborderdashlen,
|
|
axisNameBorderDashGap: chartAttrs.xaxisnameborderdashgap,
|
|
useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
|
|
divLineColor: pluck (chartAttrs.vdivlinecolor, chartAttrs.divlinecolor,
|
|
colorM.getColor (palleteString.divLineColor)),
|
|
divLineAlpha: pluck (chartAttrs.vdivlinealpha, chartAttrs.divlinealpha,
|
|
is3d ? colorM.getColor(divLineAlpha3DStr) : colorM.getColor (divLineAlphaStr)),
|
|
divLineThickness: pluckNumber (chartAttrs.vdivlinethickness, chartAttrs.divlinethickness, 1),
|
|
divLineIsDashed: Boolean (pluckNumber (chartAttrs.vdivlinedashed, chartAttrs.vdivlineisdashed,
|
|
chartAttrs.divlinedashed, chartAttrs.divlineisdashed, 0)),
|
|
divLineDashLen: pluckNumber (chartAttrs.vdivlinedashlen, chartAttrs.divlinedashlen, 4),
|
|
divLineDashGap: pluckNumber (chartAttrs.vdivlinedashgap, chartAttrs.divlinedashgap, 2),
|
|
showAlternateGridColor: pluckNumber(chartAttrs.showalternatevgridcolor, 0),
|
|
alternateGridColor: pluck(chartAttrs.alternatevgridcolor, colorM.getColor(altVGridColorStr)),
|
|
alternateGridAlpha: pluck(chartAttrs.alternatevgridalpha, colorM.getColor(altVGridAlphaStr)),
|
|
numDivLines: chartAttrs.numvdivlines,
|
|
labelFont: chartAttrs.labelfont,
|
|
labelFontSize: chartAttrs.labelfontsize,
|
|
labelFontColor: chartAttrs.labelfontcolor,
|
|
labelFontAlpha: chartAttrs.labelalpha,
|
|
labelFontBold : chartAttrs.labelfontbold,
|
|
labelFontItalic : chartAttrs.labelfontitalic,
|
|
axisName: chartAttrs.xaxisname,
|
|
axisMinValue: chartAttrs.xaxisminvalue,
|
|
axisMaxValue: chartAttrs.xaxismaxvalue,
|
|
setAdaptiveMin: chartAttrs.setadaptivexmin,
|
|
adjustDiv: chartAttrs.adjustvdiv,
|
|
labelDisplay: chartAttrs.labeldisplay,
|
|
showLabels: chartAttrs.showlabels,
|
|
rotateLabels: chartAttrs.rotatelabels,
|
|
slantLabel: pluckNumber(chartAttrs.slantlabels, chartAttrs.slantlabel),
|
|
labelStep: pluckNumber(chartAttrs.labelstep, chartAttrs.xaxisvaluesstep),
|
|
showAxisValues: pluckNumber(chartAttrs.showxaxisvalues, chartAttrs.showxaxisvalue),
|
|
showLimits: chartAttrs.showvlimits,
|
|
showDivLineValues: pluckNumber(chartAttrs.showvdivlinevalues, chartAttrs.showvdivlinevalues),
|
|
showZeroPlane: chartAttrs.showvzeroplane,
|
|
zeroPlaneColor: chartAttrs.vzeroplanecolor,
|
|
zeroPlaneThickness: chartAttrs.vzeroplanethickness,
|
|
zeroPlaneAlpha: chartAttrs.vzeroplanealpha,
|
|
showZeroPlaneValue: chartAttrs.showvzeroplanevalue,
|
|
trendlineColor: chartAttrs.trendlinecolor,
|
|
trendlineToolText: chartAttrs.trendlinetooltext,
|
|
trendlineThickness: chartAttrs.trendlinethickness,
|
|
trendlineAlpha: chartAttrs.trendlinealpha,
|
|
showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
|
|
showAxisLine: pluckNumber(chartAttrs.showxaxisline, chartAttrs.showaxislines,
|
|
chartAttrs.drawAxisLines, 0),
|
|
axisLineThickness: pluckNumber(chartAttrs.xaxislinethickness, chartAttrs.axislinethickness, 1),
|
|
axisLineAlpha: pluckNumber(chartAttrs.xaxislinealpha, chartAttrs.axislinealpha, 100),
|
|
axisLineColor: pluck(chartAttrs.xaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
|
|
};
|
|
vxAxisConf = {
|
|
outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
|
|
outCanfontSize: pluckFontSize(chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
|
|
outCancolor: pluck(chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
|
|
colorM.getColor(palleteString.baseFontColor)).replace(/^#?([a-f0-9]+)/ig, '#$1'),
|
|
axisNamePadding: chartAttrs.xaxisnamepadding,
|
|
axisValuePadding: chartAttrs.labelpadding,
|
|
axisNameFont: chartAttrs.xaxisnamefont,
|
|
axisNameFontSize: chartAttrs.xaxisnamefontsize,
|
|
axisNameFontColor: chartAttrs.xaxisnamefontcolor,
|
|
axisNameFontBold: chartAttrs.xaxisnamefontbold,
|
|
axisNameFontItalic: chartAttrs.xaxisnamefontitalic,
|
|
axisNameBgColor: chartAttrs.xaxisnamebgcolor,
|
|
axisNameBorderColor: chartAttrs.xaxisnamebordercolor,
|
|
axisNameAlpha: chartAttrs.xaxisnamealpha,
|
|
axisNameFontAlpha: chartAttrs.xaxisnamefontalpha,
|
|
axisNameBgAlpha: chartAttrs.xaxisnamebgalpha,
|
|
axisNameBorderAlpha: chartAttrs.xaxisnameborderalpha,
|
|
axisNameBorderPadding: chartAttrs.xaxisnameborderpadding,
|
|
axisNameBorderRadius: chartAttrs.xaxisnameborderradius,
|
|
axisNameBorderThickness: chartAttrs.xaxisnameborderthickness,
|
|
axisNameBorderDashed: chartAttrs.xaxisnameborderdashed,
|
|
axisNameBorderDashLen: chartAttrs.xaxisnameborderdashlen,
|
|
axisNameBorderDashGap: chartAttrs.xaxisnameborderdashgap,
|
|
useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
|
|
divLineColor: pluck(chartAttrs.vdivlinecolor, colorM.getColor(palleteString.divLineColor)),
|
|
divLineAlpha: pluck(chartAttrs.vdivlinealpha, colorM.getColor(divLineAlphaStr)),
|
|
divLineThickness: pluckNumber(chartAttrs.vdivlinethickness, 1),
|
|
divLineIsDashed: Boolean(pluckNumber(chartAttrs.vdivlinedashed, chartAttrs.vdivlineisdashed, 0)),
|
|
divLineDashLen: pluckNumber(chartAttrs.vdivlinedashlen, 4),
|
|
divLineDashGap: pluckNumber(chartAttrs.vdivlinedashgap, 2),
|
|
showAlternateGridColor: pluckNumber(chartAttrs.showalternatevgridcolor, 0),
|
|
alternateGridColor: pluck(chartAttrs.alternatevgridcolor, colorM.getColor(altVGridColorStr)),
|
|
alternateGridAlpha: pluck(chartAttrs.alternatevgridalpha, colorM.getColor(altVGridAlphaStr)),
|
|
numDivLines: chartAttrs.numvdivlines,
|
|
labelFont: chartAttrs.labelfont,
|
|
labelFontSize: chartAttrs.labelfontsize,
|
|
labelFontColor: chartAttrs.labelfontcolor,
|
|
labelFontAlpha: chartAttrs.labelalpha,
|
|
labelFontBold : chartAttrs.labelfontbold,
|
|
labelFontItalic : chartAttrs.labelfontitalic,
|
|
axisName: chartAttrs.xaxisname,
|
|
axisMinValue: chartAttrs.xaxisminvalue,
|
|
axisMaxValue: chartAttrs.xaxismaxvalue,
|
|
setAdaptiveMin: chartAttrs.setadaptivexmin,
|
|
adjustDiv: chartAttrs.adjustvdiv,
|
|
labelDisplay: chartAttrs.labeldisplay,
|
|
showLabels: 1,
|
|
rotateLabels: chartAttrs.rotatelabels,
|
|
slantLabel: pluckNumber(chartAttrs.slantlabels, chartAttrs.slantlabel),
|
|
labelStep: pluckNumber(chartAttrs.labelstep, chartAttrs.xaxisvaluesstep),
|
|
showAxisValues: pluckNumber(chartAttrs.showxaxisvalues, chartAttrs.showxaxisvalue),
|
|
showLimits: chartAttrs.showvlimits,
|
|
showDivLineValues: pluckNumber(chartAttrs.showvdivlinevalues, chartAttrs.showvdivlinevalues),
|
|
showZeroPlane: chartAttrs.showvzeroplane,
|
|
zeroPlaneColor: chartAttrs.vzeroplanecolor,
|
|
zeroPlaneThickness: chartAttrs.vzeroplanethickness,
|
|
zeroPlaneAlpha: chartAttrs.vzeroplanealpha,
|
|
showZeroPlaneValue: chartAttrs.showvzeroplanevalue,
|
|
trendlineColor: chartAttrs.trendlinecolor,
|
|
trendlineToolText: chartAttrs.trendlinetooltext,
|
|
trendlineThickness: chartAttrs.trendinethickness,
|
|
trendlineAlpha: chartAttrs.trendlinealpha,
|
|
showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
|
|
showAxisLine: pluckNumber(chartAttrs.showxaxisline, chartAttrs.showaxislines,
|
|
chartAttrs.drawAxisLines, 0),
|
|
axisLineThickness: pluckNumber(chartAttrs.xaxislinethickness, chartAttrs.axislinethickness, 1),
|
|
axisLineAlpha: pluckNumber(chartAttrs.xaxislinealpha, chartAttrs.axislinealpha, 100),
|
|
axisLineColor: pluck(chartAttrs.xaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
|
|
};
|
|
yAxisConf = {
|
|
outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
|
|
outCanfontSize: pluckFontSize(chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
|
|
outCancolor: pluck(chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
|
|
colorM.getColor(palleteString.baseFontColor)).replace(/^#?([a-f0-9]+)/ig, '#$1'),
|
|
axisNamePadding: chartAttrs.yaxisnamepadding,
|
|
axisValuePadding: chartAttrs.yaxisvaluespadding,
|
|
axisNameFont: chartAttrs.pyaxisnamefont,
|
|
axisNameFontSize: chartAttrs.pyaxisnamefontsize,
|
|
axisNameFontColor: chartAttrs.pyaxisnamefontcolor,
|
|
axisNameFontBold: chartAttrs.pyaxisnamefontbold,
|
|
axisNameFontItalic: chartAttrs.pyaxisnamefontitalic,
|
|
axisNameBgColor: chartAttrs.pyaxisnamebgcolor,
|
|
axisNameBorderColor: chartAttrs.pyaxisnamebordercolor,
|
|
axisNameAlpha: chartAttrs.pyaxisnamealpha,
|
|
axisNameFontAlpha: chartAttrs.pyaxisnamefontalpha,
|
|
axisNameBgAlpha: chartAttrs.pyaxisnamebgalpha,
|
|
axisNameBorderAlpha: chartAttrs.pyaxisnameborderalpha,
|
|
axisNameBorderPadding: chartAttrs.pyaxisnameborderpadding,
|
|
axisNameBorderRadius: chartAttrs.pyaxisnameborderradius,
|
|
axisNameBorderThickness: chartAttrs.pyaxisnameborderthickness,
|
|
axisNameBorderDashed: chartAttrs.pyaxisnameborderdashed,
|
|
axisNameBorderDashLen: chartAttrs.pyaxisnameborderdashlen,
|
|
axisNameBorderDashGap: chartAttrs.pyaxisnameborderdashgap,
|
|
axisNameWidth: chartAttrs.yaxisnamewidth,
|
|
useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
|
|
rotateAxisName: pluckNumber(chartAttrs.rotateyaxisname, 1),
|
|
axisName: chartAttrs.pyaxisname,
|
|
divLineColor: pluck(chartAttrs.divlinecolor, colorM.getColor(palleteString.divLineColor)),
|
|
divLineAlpha: pluck(chartAttrs.divlinealpha, colorM.getColor(divLineAlphaStr)),
|
|
divLineThickness: pluckNumber(chartAttrs.divlinethickness, 1),
|
|
divLineIsDashed: Boolean(pluckNumber(chartAttrs.divlinedashed, chartAttrs.divlineisdashed, 1)),
|
|
divLineDashLen: pluckNumber(chartAttrs.divlinedashlen, 4),
|
|
divLineDashGap: pluckNumber(chartAttrs.divlinedashgap, 2),
|
|
showAlternateGridColor: pluckNumber(chartAttrs.showalternatehgridcolor, 1),
|
|
alternateGridColor: pluck(chartAttrs.alternatehgridcolor, colorM.getColor(altHGridColorStr)),
|
|
alternateGridAlpha: pluck(chartAttrs.alternatehgridalpha, colorM.getColor(altHGridAlphaStr)),
|
|
numDivLines: pluckNumber(chartAttrs.numpdivlines, 5),
|
|
axisMinValue: chartAttrs.pyaxisminvalue,
|
|
axisMaxValue: chartAttrs.pyaxismaxvalue,
|
|
setAdaptiveMin: pluckNumber(chartAttrs.setadaptiveymin, 1),
|
|
adjustDiv: chartAttrs.adjustdiv,
|
|
labelStep: chartAttrs.yaxisvaluesstep,
|
|
showAxisValues: pluckNumber(chartAttrs.showyaxisvalues, chartAttrs.showyaxisvalue),
|
|
showLimits: pluckNumber(chartAttrs.showyaxislimits, chartAttrs.showlimits, iapi.showLimits),
|
|
showDivLineValues: pluckNumber(chartAttrs.showdivlinevalues, chartAttrs.showdivlinevalue),
|
|
showZeroPlane: chartAttrs.showzeroplane,
|
|
zeroPlaneColor: chartAttrs.zeroplanecolor,
|
|
zeroPlaneThickness: chartAttrs.zeroplanethickness,
|
|
zeroPlaneAlpha: chartAttrs.zeroplanealpha,
|
|
showZeroPlaneValue: chartAttrs.showzeroplanevalue,
|
|
trendlineColor: chartAttrs.trendlinecolor,
|
|
trendlineToolText: chartAttrs.trendlinetooltext,
|
|
trendlineThickness: chartAttrs.trendlinethickness,
|
|
trendlineAlpha: chartAttrs.trendlinealpha,
|
|
showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
|
|
showAxisLine: pluckNumber(chartAttrs.showyaxisline, chartAttrs.showaxislines,
|
|
chartAttrs.drawAxisLines, 0),
|
|
axisLineThickness: pluckNumber(chartAttrs.yaxislinethickness, chartAttrs.axislinethickness, 1),
|
|
axisLineAlpha: pluckNumber(chartAttrs.yaxislinealpha, chartAttrs.axislinealpha, 100),
|
|
axisLineColor: pluck(chartAttrs.yaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
|
|
};
|
|
vYAxisConf = {
|
|
outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
|
|
outCanfontSize: pluckFontSize(chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
|
|
outCancolor: pluck(chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
|
|
colorM.getColor(palleteString.baseFontColor)).replace(/^#?([a-f0-9]+)/ig, '#$1'),
|
|
axisNamePadding: chartAttrs.yaxisnamepadding,
|
|
axisValuePadding: chartAttrs.yaxisvaluespadding,
|
|
axisNameFont: chartAttrs.vyaxisnamefont,
|
|
axisNameFontSize: chartAttrs.vyaxisnamefontsize,
|
|
axisNameFontColor: chartAttrs.vyaxisnamefontcolor,
|
|
axisNameFontBold: chartAttrs.vyaxisnamefontbold,
|
|
axisNameFontItalic: chartAttrs.vyaxisnamefontitalic,
|
|
axisNameBgColor: chartAttrs.vyaxisnamebgcolor,
|
|
axisNameBorderColor: chartAttrs.vyaxisnamebordercolor,
|
|
axisNameAlpha: chartAttrs.vyaxisnamealpha,
|
|
axisNameFontAlpha: chartAttrs.vyaxisnamefontalpha,
|
|
axisNameBgAlpha: chartAttrs.vyaxisnamebgalpha,
|
|
axisNameBorderAlpha: chartAttrs.vyaxisnameborderalpha,
|
|
axisNameBorderPadding: chartAttrs.vyaxisnameborderpadding,
|
|
axisNameBorderRadius: chartAttrs.vyaxisnameborderradius,
|
|
axisNameBorderThickness: chartAttrs.vyaxisnameborderthickness,
|
|
axisNameBorderDashed: chartAttrs.vyaxisnameborderdashed,
|
|
axisNameBorderDashLen: chartAttrs.vyaxisnameborderdashlen,
|
|
axisNameBorderDashGap: chartAttrs.vyaxisnameborderdashgap,
|
|
axisNameWidth: chartAttrs.yaxisnamewidth,
|
|
useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
|
|
rotateAxisName: pluckNumber(chartAttrs.rotateyaxisname, 1),
|
|
axisName: chartAttrs.vyaxisname,
|
|
divLineColor: pluck(chartAttrs.divlinecolor, colorM.getColor(palleteString.divLineColor)),
|
|
divLineAlpha: pluck(chartAttrs.divlinealpha, colorM.getColor(divLineAlphaStr)),
|
|
divLineThickness: pluckNumber(chartAttrs.divlinethickness, 1),
|
|
divLineIsDashed: Boolean(pluckNumber(chartAttrs.divlinedashed, chartAttrs.divlineisdashed, 1)),
|
|
divLineDashLen: pluckNumber(chartAttrs.divlinedashlen, 4),
|
|
divLineDashGap: pluckNumber(chartAttrs.divlinedashgap, 2),
|
|
showAlternateGridColor: pluckNumber(chartAttrs.showalternatehgridcolor, 1),
|
|
alternateGridColor: pluck(chartAttrs.alternatehgridcolor, colorM.getColor(altHGridColorStr)),
|
|
alternateGridAlpha: pluck(chartAttrs.alternatehgridalpha, colorM.getColor(altHGridAlphaStr)),
|
|
numDivLines: chartAttrs.numdivlines,
|
|
// @todo have to change the y axis max and min value afterwards when percentage axis is ready
|
|
axisMinValue: chartAttrs.vyaxisminvalue,
|
|
axisMaxValue: chartAttrs.vyaxismaxvalue,
|
|
setAdaptiveMin: chartAttrs.setadaptiveymin,
|
|
adjustDiv: chartAttrs.adjustdiv,
|
|
labelStep: chartAttrs.yaxisvaluesstep,
|
|
showAxisValues: pluckNumber(chartAttrs.showyaxisvalues, chartAttrs.showyaxisvalue),
|
|
showLimits: pluckNumber(chartAttrs.showsecondarylimits, chartAttrs.showlimits),
|
|
showDivLineValues: pluckNumber(chartAttrs.showdivlinevalues, chartAttrs.showdivlinevalue),
|
|
showZeroPlane: chartAttrs.showzeroplane,
|
|
zeroPlaneColor: chartAttrs.zeroplanecolor,
|
|
zeroPlaneThickness: chartAttrs.zeroplanethickness,
|
|
zeroPlaneAlpha: chartAttrs.zeroplanealpha,
|
|
showZeroPlaneValue: chartAttrs.showzeroplanevalue,
|
|
trendlineColor: chartAttrs.trendlinecolor,
|
|
trendlineToolText: chartAttrs.trendlinetooltext,
|
|
trendlineThickness: chartAttrs.trendlinethickness,
|
|
trendlineAlpha: chartAttrs.trendlinealpha,
|
|
showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
|
|
showAxisLine: pluckNumber(chartAttrs.showyaxisline, chartAttrs.showaxislines,
|
|
chartAttrs.drawAxisLines, 0),
|
|
axisLineThickness: pluckNumber(chartAttrs.yaxislinethickness, chartAttrs.axislinethickness, 1),
|
|
axisLineAlpha: pluckNumber(chartAttrs.yaxislinealpha, chartAttrs.axislinealpha, 100),
|
|
axisLineColor: pluck(chartAttrs.yaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
|
|
};
|
|
xAxisConf.vtrendlines = dataObj.vtrendlines;
|
|
vxAxisConf.vtrendlines = dataObj.vtrendlines;
|
|
yAxisConf.trendlines = dataObj.trendlines;
|
|
yAxis = components.yAxis[0];
|
|
yAxis1 = components.yAxis[1];
|
|
|
|
xAxis = components.xAxis[0];
|
|
|
|
|
|
yAxis.setCommonConfigArr(yAxisConf, true, false, false);
|
|
yAxis.configure();
|
|
yAxis1.setCommonConfigArr(vYAxisConf, true, false, false);
|
|
yAxis1.configure();
|
|
yAxis.setAxisConfig({
|
|
drawLabelsOpposit : 1,
|
|
axisNameAlignCanvas : 1,
|
|
relativeAxis : yAxis1
|
|
});
|
|
yAxis1.setAxisConfig({
|
|
drawLabelsOpposit : 1,
|
|
axisNameAlignCanvas : 1,
|
|
uniqueClassName : 1,
|
|
relativeAxis : yAxis
|
|
});
|
|
|
|
xAxis.setCommonConfigArr(xAxisConf, false, false, false);
|
|
xAxis.configure();
|
|
xAxis.setAxisConfig({
|
|
drawTrendLabels: showVolumeChart ? false : true
|
|
});
|
|
if (showVolumeChart) {
|
|
if (!components.xAxis[1]) {
|
|
vxAxis = components.xAxis[1] = new CartesianAxis();
|
|
vxAxis.chart = iapi;
|
|
vxAxis.init();
|
|
} else {
|
|
components.xAxis[1].show();
|
|
}
|
|
vxAxis = components.xAxis[1];
|
|
vxAxis.setCommonConfigArr(vxAxisConf, false, false, false);
|
|
vxAxis.configure();
|
|
vxAxis.setAxisConfig({
|
|
drawLabels : false,
|
|
drawPlotlines : true,
|
|
drawPlotBands : false,
|
|
drawAxisName : false,
|
|
drawTrendLines : true,
|
|
drawOnlyCategoryLine : true,
|
|
uniqueClassName : 1
|
|
});
|
|
} else {
|
|
if (components.xAxis[1]) {
|
|
components.xAxis[1].hide();
|
|
}
|
|
}
|
|
},
|
|
_setCategories: function() {
|
|
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
dataObj = iapi.jsonData,
|
|
xAxis = components.xAxis,
|
|
categories = dataObj.categories && dataObj.categories[0].category || [],
|
|
xAxisCatArr = [],
|
|
catObj,
|
|
i;
|
|
for (i = 0; i < categories.length; i++) {
|
|
catObj = extend2({}, categories[i]);
|
|
catObj.label = BLANKSTRING;
|
|
xAxisCatArr.push(catObj);
|
|
}
|
|
xAxis[0].setAxisPadding(0.5, 0.5);
|
|
xAxis[0].setCategory(categories);
|
|
xAxis[1] && xAxis[1].setAxisPadding(0.5, 0.5);
|
|
xAxis[1] && xAxis[1].setCategory(xAxisCatArr);
|
|
},
|
|
_setAxisLimits: function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
dataset = components.dataset,
|
|
yAxis = components.yAxis,
|
|
xAxis = components.xAxis,
|
|
currentDataset,
|
|
length = dataset.length,
|
|
i,
|
|
infMin = -Infinity,
|
|
infMax = +Infinity,
|
|
max = infMin,
|
|
min = infMax,
|
|
vMax = infMin,
|
|
vMin = infMax,
|
|
xMin = infMax,
|
|
xMax = infMin,
|
|
maxminObj,
|
|
groupManager,
|
|
trendMinMaxObj,
|
|
yAxisIndex = 0,
|
|
groupManagerObj = {},
|
|
getMaxMin = function (maxminObj) {
|
|
if (yAxisIndex === 1) {
|
|
vMax = mathMax(vMax, maxminObj.max);
|
|
vMin = mathMin(vMin, maxminObj.min);
|
|
}
|
|
else {
|
|
max = mathMax(max, maxminObj.max);
|
|
min = mathMin(min, maxminObj.min);
|
|
}
|
|
|
|
xMax = mathMax(xMax, maxminObj.xMax || infMin);
|
|
xMin = mathMin(xMin, maxminObj.xMin || infMax);
|
|
|
|
};
|
|
|
|
for (i=0; i<length; i++) {
|
|
currentDataset = dataset[i];
|
|
groupManager = currentDataset.groupManager;
|
|
yAxisIndex = currentDataset.config.parentYAxis;
|
|
if (groupManager) {
|
|
groupManagerObj[currentDataset.type] = groupManager;
|
|
groupManagerObj[currentDataset.type].yAxisIndex = yAxisIndex;
|
|
}
|
|
else {
|
|
maxminObj = currentDataset.getDataLimits();
|
|
getMaxMin(maxminObj);
|
|
}
|
|
}
|
|
|
|
for (groupManager in groupManagerObj) {
|
|
yAxisIndex = groupManagerObj[groupManager].yAxisIndex;
|
|
maxminObj = groupManagerObj[groupManager].getDataLimits();
|
|
max = mathMax(max, maxminObj.max);
|
|
min = mathMin(min, maxminObj.min);
|
|
}
|
|
trendMinMaxObj = iapi._getTrendLineMinMax('h');
|
|
max = mathMax (max, trendMinMaxObj.max);
|
|
min = mathMin (min, trendMinMaxObj.min);
|
|
yAxis[0].setDataLimit(max, min);
|
|
yAxis[1].setDataLimit(vMax, vMin);
|
|
if ((xMax !== infMin) || (xMin !== infMax)) {
|
|
xAxis[0].setAxisRange({
|
|
min: xMin - 0.5,
|
|
max: xMax + 0.5,
|
|
tickInterval: 1
|
|
});
|
|
xAxis[1] && xAxis[1].setAxisRange({
|
|
min: xMin - 0.5,
|
|
max: xMax + 0.5,
|
|
tickInterval: 1
|
|
});
|
|
// xAxis[0].setDataLimit(xMax, xMin);
|
|
}
|
|
},
|
|
isDual: true
|
|
}, chartAPI.mscartesian, {
|
|
enablemousetracking: true,
|
|
iscandlestick: true
|
|
});
|
|
|
|
}]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-kagi', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
chartAPI = lib.chartAPI,
|
|
win = global.window,
|
|
math = Math,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
pluck = lib.pluck,
|
|
pluckNumber = lib.pluckNumber,
|
|
toPrecision = lib.toPrecision,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);
|
|
|
|
//The chartAPI for the kagi chart.
|
|
//It is a single series chart hence ingerited from sscartesian(Single series chart).
|
|
chartAPI('kagi', {
|
|
standaloneInit: true,
|
|
friendlyName: 'Kagi Chart',
|
|
creditLabel: creditLabel,
|
|
defaultDatasetType : 'kagi',
|
|
applicableDSList: {
|
|
'kagi': true
|
|
},
|
|
singleseries: true,
|
|
hasLegend: false,
|
|
_postSpaceManagement : function () {
|
|
var iapi = this,
|
|
config = iapi.config,
|
|
components = iapi.components,
|
|
xAxis = components.xAxis && components.xAxis[0],
|
|
yAxis = components.yAxis && components.yAxis[0],
|
|
canvasConfig = components.canvas.config,
|
|
canvasBorderWidth = canvasConfig.canvasBorderWidth,
|
|
canvasPadding = canvasConfig.canvasPadding || 15,
|
|
canvasPaddingTop = canvasConfig.canvasPaddingTop,
|
|
canvasPaddingBottom = canvasConfig.canvasPaddingBottom,
|
|
chartAttrs = iapi.jsonData.chart,
|
|
dataset = components.dataset,
|
|
series = dataset[0].config,
|
|
shiftCount = series && series.shiftCount,
|
|
min = pluckNumber(xAxis.getAxisConfig('axisMinValue'), 0),
|
|
max = pluckNumber(xAxis.getAxisConfig('axisMaxValue'), shiftCount - 1),
|
|
canvasWidth = iapi.config.canvasWidth,
|
|
//plot area will not be less then 10 px
|
|
leftPixelPad = mathMin(pluckNumber(chartAttrs.canvaspadding, 0), (canvasWidth / 2) - 10),
|
|
rightPixelPad = leftPixelPad,
|
|
// The maximum horizontal shift in percentage of the
|
|
// available canvas width
|
|
maxHShiftPercent = pluckNumber(chartAttrs.maxhshiftpercent, 10),
|
|
effectiveCanvasWidth = canvasWidth - canvasPadding * 2,
|
|
xShiftLength;
|
|
|
|
yAxis && yAxis.setAxisDimention ( {
|
|
x : config.canvasLeft - canvasBorderWidth,
|
|
y : config.canvasTop + canvasPaddingTop,
|
|
opposite : config.canvasRight + canvasBorderWidth,
|
|
axisLength : config.canvasHeight - canvasPaddingTop - canvasPaddingBottom
|
|
});
|
|
|
|
iapi._setPosition();
|
|
if (series) {
|
|
// maxHShiftPercent can not be < 0
|
|
maxHShiftPercent = maxHShiftPercent <= 0 ?
|
|
10 : maxHShiftPercent;
|
|
xShiftLength = series.xShiftLength =
|
|
mathMin(effectiveCanvasWidth / shiftCount,
|
|
maxHShiftPercent * effectiveCanvasWidth / 100);
|
|
leftPixelPad = canvasPadding + xShiftLength / 2;
|
|
rightPixelPad = canvasWidth - ((xShiftLength *
|
|
// handling single value rendering issue in Kagi
|
|
mathMax((shiftCount - 1), 1)) + leftPixelPad);
|
|
// Fix for Kagi chart single value rendering issue
|
|
// If there is a single value, we use xAxis max value
|
|
// as 1 not as 0
|
|
max = mathMax(max, 1);
|
|
}
|
|
|
|
// function for adjusting value padding depending upon data and axis labels.
|
|
iapi._adjustCanvasPadding();
|
|
xAxis && xAxis.setAxisDimention ( {
|
|
x: iapi.config.canvasLeft + canvasPadding + (xShiftLength/2),
|
|
axisLength: xShiftLength * (max - min),
|
|
y : config.canvasBottom + (config.shift || 0) + canvasBorderWidth,
|
|
opposite : config.canvasTop - canvasBorderWidth
|
|
});
|
|
},
|
|
_setPosition: function () {
|
|
var i,
|
|
point,
|
|
yValue,
|
|
config,
|
|
isRally,
|
|
lastHigh,
|
|
lastLow,
|
|
isRallyInitialised,
|
|
lastPoint,
|
|
iapi = this,
|
|
components = iapi.components,
|
|
dataObj = iapi.jsonData,
|
|
dataSet = components.dataset[0],
|
|
categories = dataObj.data || (dataSet && dataSet[0] && dataSet[0].data),
|
|
setDataArr = dataSet.components.data,
|
|
dataSetLen = setDataArr && setDataArr.length,
|
|
yAxis = components.yAxis[0],
|
|
xValue = 0,
|
|
plotX = xValue,
|
|
catArr = [];
|
|
//create plot elements
|
|
for (i=0; i<dataSetLen; i++) {
|
|
|
|
point = setDataArr[i].config;
|
|
yValue = point.setValue;
|
|
|
|
dataObj = setDataArr[i];
|
|
config = dataObj.config;
|
|
|
|
// Creating the data object if not created
|
|
if (!dataObj) {
|
|
dataObj = setDataArr[i] = {
|
|
graphics : {}
|
|
};
|
|
}
|
|
if (!point.isDefined) {
|
|
yValue = point.plotValue;
|
|
}
|
|
|
|
// Getting appropiate value for the current plot point.
|
|
yValue = pluck(point.plotValue, yValue);
|
|
|
|
// Set the y position.
|
|
point.plotY = toPrecision(yAxis.getAxisPosition(point.setValue), 2);
|
|
|
|
// Store value textbox y position.
|
|
point.graphY = toPrecision(yAxis.getAxisPosition(yValue), 2);
|
|
|
|
// Abscissa of the point on the kagi line.
|
|
point.plotX = plotX;
|
|
// If there is a horizontal shift, then abscissa of the kagi
|
|
// line and as such all points on it shifts to the right by a
|
|
// slab more.
|
|
if (point.isShift) {
|
|
xValue += 1;
|
|
plotX = xValue;
|
|
categories && catArr.push(categories[i]);
|
|
}
|
|
else if (i === (dataSetLen - 1)){
|
|
categories && catArr.push(categories[i]);
|
|
}
|
|
|
|
if (i) {
|
|
lastPoint = setDataArr[i - 1].config;
|
|
|
|
// Getting the previously bundled up properties in local
|
|
// variables.
|
|
isRally = point && point.objParams && point.objParams.isRally;
|
|
lastHigh = point && point.objParams && point.objParams.lastHigh;
|
|
lastLow = point && point.objParams && point.objParams.lastLow;
|
|
isRallyInitialised = point && point.objParams &&
|
|
point.objParams.isRallyInitialised;
|
|
|
|
// To find if there is a change in trend towards the current
|
|
// plot.
|
|
if (lastPoint && isRallyInitialised &&
|
|
lastPoint.isRally !== point.isRally) {
|
|
|
|
// Setting in this.data for the plot, to be used for.
|
|
// Setting the color/thickness the graph segments.
|
|
point.isChanged = true;
|
|
|
|
// To get the pixel position of the transtion point and
|
|
// storing in data point for the plot.
|
|
point.ty = toPrecision(yAxis.getAxisPosition((isRally ?
|
|
lastHigh : lastLow)), 2);
|
|
} else {
|
|
// Setting in this.data for the plot.
|
|
point.isChanged = false;
|
|
}
|
|
}
|
|
}
|
|
//end of previous translation
|
|
},
|
|
_setAxisLimits : function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
dataset = components.dataset,
|
|
yAxis = components.yAxis,
|
|
xAxis = components.xAxis,
|
|
currentDataset,
|
|
length = dataset.length,
|
|
i,
|
|
infMin = -Infinity,
|
|
infMax = +Infinity,
|
|
max = infMin,
|
|
min = infMax,
|
|
xMin = infMax,
|
|
xMax = infMin,
|
|
maxminObj,
|
|
groupManager,
|
|
groupManagerObj = { },
|
|
noManager = [],
|
|
getMaxMin = function (maxminObj) {
|
|
max = mathMax (max, maxminObj.max);
|
|
min = mathMin (min, maxminObj.min);
|
|
xMax = mathMax (xMax, maxminObj.xMax || infMin);
|
|
xMin = mathMin (xMin, maxminObj.xMin || infMax);
|
|
|
|
};
|
|
|
|
for (i=0; i<length; i++) {
|
|
currentDataset = dataset[i];
|
|
groupManager = currentDataset.groupManager;
|
|
if (groupManager) {
|
|
groupManagerObj[currentDataset.type] = groupManager;
|
|
}
|
|
else {
|
|
noManager.push (currentDataset);
|
|
}
|
|
}
|
|
|
|
for (groupManager in groupManagerObj) {
|
|
maxminObj = groupManagerObj[groupManager].getDataLimits ();
|
|
getMaxMin (maxminObj);
|
|
}
|
|
|
|
length =noManager.length;
|
|
for (i=0; i<length; i++) {
|
|
maxminObj = noManager[i].getDataLimits ();
|
|
getMaxMin (maxminObj);
|
|
}
|
|
getMaxMin(iapi._getTrendLineMinMax('h'));
|
|
(max === -Infinity) && (max = 0);
|
|
(min === +Infinity) && (min = 0);
|
|
iapi.config.yMax = max;
|
|
iapi.config.yMin = min;
|
|
yAxis[0].setAxisConfig({
|
|
setAdaptiveMin: true
|
|
});
|
|
yAxis[0].setDataLimit (max, min);
|
|
if ((xMax !== infMin) || (xMin !== infMax)) {
|
|
xAxis[0].config.xaxisrange = {
|
|
max : xMax,
|
|
min : xMin
|
|
};
|
|
xAxis[0].setDataLimit (xMax, xMin);
|
|
}
|
|
}
|
|
}, chartAPI.waterfall2d, {
|
|
enablemousetracking: true
|
|
}, chartAPI.areabase);
|
|
}]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-boxandwhisker2d', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
chartAPI = lib.chartAPI,
|
|
win = global.window,
|
|
pluck = lib.pluck,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
BLANK = lib.BLANKSTRING,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
preDefStr = lib.preDefStr,
|
|
sStr = preDefStr.sStr,
|
|
componentDispose = lib.componentDispose,
|
|
HUNDREDSTRING = lib.HUNDREDSTRING,
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
DATASET_GROUP = 'datasetGroup',
|
|
UNDEFINED,
|
|
BoxAndWhiskerStatisticalCalc,
|
|
setAttribDefs = lib.setAttribDefs,
|
|
attrTypeNum = lib.attrTypeNum,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname),
|
|
math = Math,
|
|
mathRound = math.round,
|
|
mathAbs = math.abs,
|
|
mathCeil = math.ceil,
|
|
mathFloor = math.floor,
|
|
mathSqrt = math.sqrt,
|
|
mathPow = math.pow,
|
|
defined = function(obj) {
|
|
return obj !== UNDEFINED && obj !== null;
|
|
};
|
|
|
|
// boxAndWhisker statistical Methods
|
|
lib.BoxAndWhiskerStatisticalCalc =
|
|
BoxAndWhiskerStatisticalCalc = function(method, numberFormatter, dataSeparator) {
|
|
this.nf = numberFormatter;
|
|
this.dataSeparator = dataSeparator;
|
|
this.method = (method || BLANK).toLowerCase().replace(/\s/g, BLANKSTRING);
|
|
};
|
|
|
|
BoxAndWhiskerStatisticalCalc.prototype = {
|
|
setArray: function(value) {
|
|
var nf = this.nf,
|
|
dataSeparator = this.dataSeparator,
|
|
sum = 0,
|
|
len,
|
|
dataArr;
|
|
!value && (value = BLANK);
|
|
// First we make an arry form the comma-separated value.
|
|
// and then we sort and store the data array in dataArr
|
|
// for further calculation.
|
|
dataArr = value.replace(/\s/g, BLANK).split(dataSeparator);
|
|
// Parse the values using NumberFormatter getCleanValue
|
|
len = this.dataLength = dataArr && dataArr.length;
|
|
|
|
while (len--) {
|
|
sum += dataArr[len] = nf.getCleanValue(dataArr[len]);
|
|
}
|
|
|
|
// Now sort the data in ascending order
|
|
dataArr && dataArr.sort(function(a, b) {
|
|
return a - b;
|
|
});
|
|
|
|
this.values = dataArr;
|
|
// Calculate and store the Mean
|
|
this.mean = sum / this.dataLength;
|
|
this.getFrequencies();
|
|
},
|
|
|
|
getQuartiles: function() {
|
|
var values = this.values,
|
|
len = this.dataLength,
|
|
isOdd = len % 2,
|
|
q1Pos,
|
|
q1LowPos,
|
|
q3Pos,
|
|
q3LowPos,
|
|
q1Val,
|
|
q3Val;
|
|
|
|
switch (this.method) {
|
|
case 'tukey':
|
|
if (isOdd) {
|
|
// Q1 = n + 3 / 4 And Q3 = 3N + 1 / 4
|
|
q1Pos = (len + 3) / 4;
|
|
q3Pos = ((len * 3) + 1) / 4;
|
|
} else {
|
|
// Q1 = n + 2 / 4 And Q3 = 3N + 2 / 4
|
|
q1Pos = (len + 2) / 4;
|
|
q3Pos = ((len * 3) + 2) / 4;
|
|
}
|
|
break;
|
|
case 'mooremccabe':
|
|
if (isOdd) {
|
|
// Q1 = n + 1 / 4 And Q3 = 3N + 3 / 4
|
|
q1Pos = (len + 1) / 4;
|
|
q3Pos = q1Pos * 3;
|
|
} else {
|
|
// Q1 = n + 2 / 4 And Q3 = 3N + 2 / 4
|
|
q1Pos = (len + 2) / 4;
|
|
q3Pos = ((len * 3) + 2) / 4;
|
|
}
|
|
break;
|
|
case 'freundperles':
|
|
// Q1 = n + 3 / 4 And Q3 = 3N + 1 / 4
|
|
q1Pos = (len + 3) / 4;
|
|
q3Pos = ((len * 3) + 1) / 4;
|
|
break;
|
|
case 'mendenhallsincich':
|
|
// Q1 = [n + 1 / 4] And [Q3 = 3N + 3 / 4]
|
|
q1Pos = mathRound((len + 1) / 4);
|
|
q3Pos = mathRound(q1Pos * 3);
|
|
break;
|
|
default:
|
|
// Q1 = n + 1 / 4 And Q3 = 3N + 3 / 4
|
|
q1Pos = (len + 1) / 4;
|
|
q3Pos = q1Pos * 3;
|
|
break;
|
|
}
|
|
|
|
q1Pos -= 1;
|
|
q3Pos -= 1;
|
|
q1LowPos = mathFloor(q1Pos);
|
|
q3LowPos = mathFloor(q3Pos);
|
|
|
|
q1Val = q1Pos - q1LowPos ? values[q1LowPos] +
|
|
((values[mathCeil(q1Pos)] - values[q1LowPos]) *
|
|
(q1Pos - q1LowPos)) : values[q1Pos];
|
|
q3Val = q3Pos - q3LowPos ? values[q3LowPos] +
|
|
((values[mathCeil(q3Pos)] - values[q3LowPos]) *
|
|
(q3Pos - q3LowPos)) : values[q3Pos];
|
|
|
|
return this.quartiles = {
|
|
q1: q1Val,
|
|
q3: q3Val
|
|
};
|
|
},
|
|
|
|
// return min and max values from the data array.
|
|
getMinMax: function() {
|
|
var values = this.values;
|
|
return {
|
|
min: values[0],
|
|
max: values[this.dataLength - 1]
|
|
};
|
|
},
|
|
|
|
// calculate and returns the mean value
|
|
getMean: function() {
|
|
return this.mean;
|
|
},
|
|
|
|
// calculate the MeanDeviation
|
|
getMD: function() {
|
|
var mean = this.mean,
|
|
freq = this.frequencies,
|
|
freqLen = freq.length,
|
|
freqObj,
|
|
sum = 0;
|
|
|
|
while (freqLen--) {
|
|
freqObj = freq[freqLen];
|
|
sum += freqObj.frequency * mathAbs(freqObj.value - mean);
|
|
}
|
|
return sum / this.dataLength;
|
|
},
|
|
|
|
// calculate the standard deviation
|
|
getSD: function() {
|
|
var mean = this.mean,
|
|
values = this.values,
|
|
i = this.dataLength,
|
|
len = i,
|
|
sum = 0;
|
|
|
|
while (i--) {
|
|
sum += mathPow(values[i] - mean, 2);
|
|
}
|
|
|
|
return mathSqrt(sum) / len;
|
|
},
|
|
|
|
// calculate the quartile deviation
|
|
getQD: function() {
|
|
return (this.quartiles.q3 - this.quartiles.q1) * 0.5;
|
|
},
|
|
|
|
// calculate the frequencies and sum of the values
|
|
getFrequencies: function() {
|
|
var frequenciesArr = [],
|
|
len = this.dataLength,
|
|
values = this.values,
|
|
sum = 0,
|
|
value,
|
|
freqObj,
|
|
index;
|
|
|
|
for (index = 0; index < len; index += 1) {
|
|
sum += value = values[index];
|
|
if (defined(frequenciesArr[index])) {
|
|
frequenciesArr[index].frequency += 1;
|
|
} else {
|
|
freqObj = {};
|
|
freqObj.value = value;
|
|
freqObj.frequency = 1;
|
|
frequenciesArr[index] = freqObj;
|
|
}
|
|
}
|
|
this.sum = sum;
|
|
this.frequencies = frequenciesArr;
|
|
},
|
|
|
|
getMedian: function() {
|
|
var len = this.dataLength,
|
|
midVal = len * 0.5,
|
|
values = this.values;
|
|
|
|
return len % 2 === 0 ? (values[midVal] + values[midVal - 1]) / 2 :
|
|
values[mathFloor(midVal)];
|
|
}
|
|
};
|
|
|
|
BoxAndWhiskerStatisticalCalc.prototype.constructor = BoxAndWhiskerStatisticalCalc;
|
|
|
|
/******************************************************************************
|
|
* Raphael Renderer Extension
|
|
******************************************************************************/
|
|
|
|
setAttribDefs && setAttribDefs({
|
|
whiskerslimitswidthratio: {
|
|
type: attrTypeNum,
|
|
pAttr: 'whiskerslimitswidthratio'
|
|
},
|
|
outliersupperrangeratio: {
|
|
type: attrTypeNum,
|
|
pAttr: 'outliersupperrangeratio'
|
|
},
|
|
outlierslowerrangeratio: {
|
|
type: attrTypeNum,
|
|
pAttr: 'outlierslowerrangeratio'
|
|
},
|
|
showalloutliers: {
|
|
type: attrTypeNum,
|
|
pAttr: 'showalloutliers'
|
|
},
|
|
showmean: {
|
|
type: attrTypeNum,
|
|
pAttr: 'showmean'
|
|
},
|
|
showsd: {
|
|
type: attrTypeNum,
|
|
pAttr: 'showsd'
|
|
},
|
|
showmd: {
|
|
type: attrTypeNum,
|
|
pAttr: 'showmd'
|
|
},
|
|
showqd: {
|
|
type: attrTypeNum,
|
|
pAttr: 'showqd'
|
|
},
|
|
showminvalues: {
|
|
type: attrTypeNum,
|
|
pAttr: 'showminvalues'
|
|
},
|
|
showmaxvalues: {
|
|
type: attrTypeNum,
|
|
pAttr: 'showmaxvalues'
|
|
},
|
|
showq1values: {
|
|
type: attrTypeNum,
|
|
pAttr: 'showq1values'
|
|
},
|
|
showq3values: {
|
|
type: attrTypeNum,
|
|
pAttr: 'showq3values'
|
|
},
|
|
showmedianvalues: {
|
|
type: attrTypeNum,
|
|
pAttr: 'showmedianvalues'
|
|
}
|
|
});
|
|
|
|
chartAPI('boxandwhisker2d', {
|
|
friendlyName: 'Box and Whisker Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
chart: chartAPI.errorbar2d.chart,
|
|
drawErrorValue: chartAPI.errorbar2d.drawErrorValue,
|
|
decimals: 2,
|
|
maxColWidth: +Infinity,
|
|
useErrorAnimation: 1,
|
|
avoidCrispError: 0,
|
|
tooltipsepchar: ': ',
|
|
defaultDatasetType: 'boxandwhisker2d',
|
|
applicableDSList: {'boxandwhisker2d': true},
|
|
hasSubDataset: true,
|
|
fireGroupEvent: true,
|
|
fireInitialAnimation: true,
|
|
drawTracker: true,
|
|
_drawDataset : function () {
|
|
var iapi = this,
|
|
dataset = iapi.components.dataset,
|
|
currentDataset,
|
|
length = dataset.length,
|
|
i,
|
|
j,
|
|
len,
|
|
groupManager,
|
|
groupManagerObj = {};
|
|
|
|
for (i=0; i<length; i++) {
|
|
currentDataset = dataset[i];
|
|
groupManager = currentDataset.groupManager;
|
|
groupManagerObj[currentDataset.type] = groupManager;
|
|
}
|
|
|
|
for (groupManager in groupManagerObj) {
|
|
groupManagerObj[groupManager].draw();
|
|
}
|
|
|
|
dataset.flag = true;
|
|
|
|
for (i=0; i<length; i++) {
|
|
dataset[i].components.mean && dataset[i].components.mean.draw();
|
|
dataset[i].components.sd && dataset[i].components.sd.draw();
|
|
dataset[i].components.md && dataset[i].components.md.draw();
|
|
dataset[i].components.qd && dataset[i].components.qd.draw();
|
|
|
|
len = dataset[i].config.maxNumberOfOutliers || dataset[i].components.outliers.length;
|
|
|
|
for (j = 0; j < len; j++) {
|
|
|
|
if (!dataset[i].config.showOutliersLegend) {
|
|
dataset[i].components.outliers[j].visible = false;
|
|
}
|
|
// else {
|
|
// outliersVisible = dataset[i].components.outliers.visible;
|
|
// dataset[i].components.outliers[j].visible =
|
|
// (outliersVisible === UNDEFINED || outliersVisible) ? true : false;
|
|
// }
|
|
dataset[i].components.outliers && dataset[i].components.outliers[j].draw();
|
|
}
|
|
}
|
|
},
|
|
_createDatasets : function () {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
xAxis = components.xAxis[0],
|
|
dataObj = iapi.jsonData,
|
|
dataset = dataObj.dataset,
|
|
length = dataset && dataset.length,
|
|
i,
|
|
j,
|
|
datasetStore,
|
|
datasetStoreLen,
|
|
datasetObj,
|
|
defaultSeriesType = iapi.defaultDatasetType,
|
|
applicableDSList = iapi.applicableDSList,
|
|
legend = iapi.components.legend,
|
|
legendItems = legend.components.items || [],
|
|
GroupManager,
|
|
dsType,
|
|
DsClass,
|
|
DsGroupClass,
|
|
datasetJSON,
|
|
isStacked = iapi.isStacked,
|
|
groupManagerName,
|
|
parentyaxis,
|
|
prevData,
|
|
prevDataLength,
|
|
currDataLength,
|
|
groupManagers = [],
|
|
isRealTime = iapi.isRealTime,
|
|
diff,
|
|
catLen = iapi.config.catLen,
|
|
currCatLen,
|
|
DataDiff,
|
|
catDiff,
|
|
startIndex,
|
|
dsCount = { };
|
|
|
|
if (!dataset) {
|
|
iapi.setChartMessage();
|
|
}
|
|
|
|
iapi.config.categories = dataObj.categories && dataObj.categories[0].category;
|
|
|
|
datasetStore = components.dataset || (components.dataset = []);
|
|
datasetStoreLen = datasetStore.length;
|
|
|
|
legend.emptyItems(0, legendItems.length);
|
|
|
|
for (i=0; i<length; i++) {
|
|
datasetJSON = dataset[i];
|
|
|
|
datasetJSON.seriesname && (datasetJSON.seriesname = parseUnsafeString(datasetJSON.seriesname));
|
|
|
|
parentyaxis = datasetJSON.parentyaxis || BLANKSTRING;
|
|
if (iapi.isDual && parentyaxis.toLowerCase () === sStr) {
|
|
dsType = pluck (datasetJSON.renderas, iapi.sDefaultDatasetType);
|
|
}
|
|
else {
|
|
dsType = pluck (datasetJSON.renderas, defaultSeriesType);
|
|
}
|
|
dsType = dsType && dsType.toLowerCase ();
|
|
if (!applicableDSList[dsType]) {
|
|
dsType = defaultSeriesType;
|
|
}
|
|
|
|
/// get the DsClass
|
|
DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
|
|
if (DsClass) {
|
|
if (dsCount[dsType] === UNDEFINED) {
|
|
dsCount[dsType] = 0;
|
|
}
|
|
else {
|
|
dsCount[dsType]++;
|
|
}
|
|
groupManagerName = 'datasetGroup_' + dsType;
|
|
// get the ds group class
|
|
DsGroupClass = FusionCharts.register(COMPONENT, [DATASET_GROUP, dsType]);
|
|
GroupManager = components[groupManagerName];
|
|
GroupManager && groupManagers.push(GroupManager);
|
|
if (DsGroupClass && !GroupManager) {
|
|
GroupManager = components[groupManagerName] = new DsGroupClass ();
|
|
GroupManager.chart = iapi;
|
|
GroupManager.init ();
|
|
}
|
|
|
|
// If the dataset does not exists.
|
|
if (!(datasetObj = datasetStore[i])) {
|
|
// create the dataset Object
|
|
datasetObj = new DsClass ();
|
|
datasetStore.push (datasetObj);
|
|
datasetObj.chart = iapi;
|
|
datasetObj.index = i;
|
|
// add to group manager
|
|
GroupManager && (isStacked ? GroupManager.addDataSet (datasetObj, 0, dsCount[dsType]) :
|
|
GroupManager.addDataSet (datasetObj, dsCount[dsType], 0));
|
|
datasetObj.init (datasetJSON);
|
|
}
|
|
// If the dataset exists incase the chart is updated using setChartData() method.
|
|
else {
|
|
currCatLen = xAxis.getCategoryLen();
|
|
catDiff = catLen - currCatLen;
|
|
|
|
prevData = isRealTime ? datasetObj.components : datasetObj.JSONData;
|
|
prevDataLength = (prevData.data && prevData.data.length) || 0;
|
|
currDataLength = (datasetJSON.data && datasetJSON.data.length) || 0;
|
|
|
|
DataDiff = prevDataLength - currDataLength;
|
|
|
|
if (catDiff > DataDiff) {
|
|
diff = catDiff;
|
|
startIndex = currCatLen;
|
|
}
|
|
else {
|
|
diff = DataDiff;
|
|
startIndex = currDataLength;
|
|
}
|
|
// Removing data plots if the number of current data plots is more than the existing ones.
|
|
if (diff > 0) {
|
|
datasetObj.removeData(startIndex, diff, false);
|
|
}
|
|
datasetStore[i].JSONData = datasetJSON;
|
|
datasetStore[i].configure();
|
|
datasetStore[i]._deleteGridImages && datasetStore[i]._deleteGridImages();
|
|
}
|
|
}
|
|
}
|
|
|
|
// When the number of datasets entered vis setChartData is less than the existing dataset
|
|
// then dispose the extra datasets.
|
|
if (datasetStoreLen > length) {
|
|
diff = datasetStoreLen - length;
|
|
GroupManager && isStacked && GroupManager.removeDataSet(0, i, diff);
|
|
|
|
for (j = i, length = diff + i; j < length; j ++ ) {
|
|
GroupManager && !isStacked && GroupManager.removeDataSet(i, 0, 1);
|
|
legend.removeItem(datasetStore[j].legendItemId);
|
|
componentDispose.call(datasetStore[j]);
|
|
}
|
|
datasetStore.splice(i, diff);
|
|
}
|
|
iapi.config.catLen = xAxis.getCategoryLen();
|
|
}
|
|
|
|
}, chartAPI.mscartesian, {
|
|
showplotborder: 1,
|
|
plotborderdashlen: 5,
|
|
plotborderdashgap: 4,
|
|
plotfillalpha: HUNDREDSTRING,
|
|
useroundedges: 0,
|
|
plotborderthickness: 1,
|
|
showvalues: 1,
|
|
valuepadding: 2,
|
|
showtooltip: 1,
|
|
maxcolwidth: 50,
|
|
rotatevalues: 0,
|
|
use3dlighting: 1,
|
|
whiskerslimitswidthratio: 40,
|
|
outliersupperrangeratio: 0,
|
|
outlierslowerrangeratio: 0,
|
|
showalloutliers: 0,
|
|
showmean: 0,
|
|
showsd: 0,
|
|
showmd: 0,
|
|
showqd: 0,
|
|
showminvalues: 1,
|
|
showmaxvalues: 1,
|
|
showq1values: 0,
|
|
showq3values: 0,
|
|
showmedianvalues: 1
|
|
});
|
|
}]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-heatmap', function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
chartAPI = lib.chartAPI,
|
|
win = global.window,
|
|
COMPONENT = 'component',
|
|
AXIS = 'axis',
|
|
pluckFontSize = lib.pluckFontSize,
|
|
pluck = lib.pluck,
|
|
pluckNumber = lib.pluckNumber,
|
|
preDefStr = lib.preDefStr,
|
|
defaultFontStr = preDefStr.defaultFontStr,
|
|
divLineAlpha3DStr = preDefStr.divLineAlpha3DStr,
|
|
divLineAlphaStr = preDefStr.divLineAlphaStr,
|
|
altVGridColorStr = preDefStr.altVGridColorStr,
|
|
altVGridAlphaStr = preDefStr.altVGridAlphaStr,
|
|
altHGridColorStr = preDefStr.altHGridColorStr,
|
|
altHGridAlphaStr = preDefStr.altHGridAlphaStr,
|
|
colorStrings = preDefStr.colors,
|
|
COLOR_000000 = colorStrings.c000000,
|
|
UNDEFINED,
|
|
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);
|
|
|
|
chartAPI('heatmap', {
|
|
friendlyName: 'Heatmap Chart',
|
|
standaloneInit: true,
|
|
creditLabel: creditLabel,
|
|
//defaultSeriesType: 'heatmap',
|
|
hasLegend: true,
|
|
tooltipsepchar: ': ',
|
|
tooltipConstraint: 'chart',
|
|
defaultDatasetType : 'heatmap',
|
|
applicableDSList: {'heatmap': true},
|
|
isSingleSeries: true,
|
|
hasGradientLegend: true,
|
|
_createAxes : function() {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
CartesianAxis = FusionCharts.register(COMPONENT, [AXIS, 'cartesian']),
|
|
yAxis,
|
|
xAxis;
|
|
|
|
|
|
components.yAxis = [];
|
|
components.xAxis = [];
|
|
components.yAxis[0] = yAxis = new CartesianAxis();
|
|
components.xAxis[0] = xAxis = new CartesianAxis();
|
|
yAxis.chart = iapi;
|
|
xAxis.chart = iapi;
|
|
|
|
yAxis.init();
|
|
xAxis.init();
|
|
|
|
},
|
|
|
|
_postSpaceManagement : function () {
|
|
var iapi = this,
|
|
config = iapi.config,
|
|
placeAxisLabelsOnTop = config.placeAxisLabelsOnTop,
|
|
components = iapi.components,
|
|
xAxis = components.xAxis && components.xAxis[0],
|
|
yAxis = components.yAxis && components.yAxis[0],
|
|
legend = components.legend,
|
|
xDepth = config.xDepth,
|
|
canvasConfig = components.canvas.config,
|
|
canvasBorderWidth = canvasConfig.canvasBorderWidth;
|
|
|
|
xAxis && xAxis.setAxisDimention ( {
|
|
x : config.canvasLeft,
|
|
y : placeAxisLabelsOnTop ? (config.canvasTop + (config.shift || 0) - canvasBorderWidth) :
|
|
(config.canvasBottom + (config.shift || 0) + canvasBorderWidth),
|
|
opposite : config.canvasTop - canvasBorderWidth,
|
|
axisLength : config.canvasWidth
|
|
});
|
|
yAxis && yAxis.setAxisDimention ( {
|
|
x : config.canvasLeft - canvasBorderWidth,
|
|
y : config.canvasTop,
|
|
opposite : config.canvasRight + canvasBorderWidth,
|
|
axisLength : config.canvasHeight
|
|
});
|
|
|
|
xAxis && xAxis.shiftLabels (-xDepth, 0);
|
|
legend.postSpaceManager();
|
|
// Setting the number of columns to be displayed based on numdisplaysets.
|
|
iapi.config.realtimeEnabled && iapi._setRealTimeCategories && iapi._setRealTimeCategories ();
|
|
// function for adjusting value padding depending upon data and axis labels.
|
|
iapi._adjustCanvasPadding();
|
|
},
|
|
|
|
_adjustCanvasPadding : function () {
|
|
},
|
|
|
|
_feedAxesRawData : function() {
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
colorM = components.colorManager,
|
|
dataObj = iapi.jsonData,
|
|
chartAttrs = dataObj.chart,
|
|
xAxisConf,
|
|
yAxisConf,
|
|
is3d = iapi.is3d,
|
|
chartPaletteStr = lib.chartPaletteStr,
|
|
palleteString = is3d ? chartPaletteStr.chart3D : chartPaletteStr.chart2D,
|
|
yAxis,
|
|
xAxis;
|
|
|
|
|
|
xAxisConf = {
|
|
outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
|
|
outCanfontSize: pluckFontSize(chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
|
|
outCancolor: pluck(chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
|
|
colorM.getColor(palleteString.baseFontColor)).replace(/^#?([a-f0-9]+)/ig, '#$1'),
|
|
axisNamePadding: chartAttrs.xaxisnamepadding,
|
|
axisValuePadding: chartAttrs.labelpadding,
|
|
axisNameFont: chartAttrs.xaxisnamefont,
|
|
axisNameFontSize: chartAttrs.xaxisnamefontsize,
|
|
axisNameFontColor: chartAttrs.xaxisnamefontcolor,
|
|
axisNameFontBold: chartAttrs.xaxisnamefontbold,
|
|
axisNameFontItalic: chartAttrs.xaxisnamefontitalic,
|
|
axisNameBgColor: chartAttrs.xaxisnamebgcolor,
|
|
axisNameBorderColor: chartAttrs.xaxisnamebordercolor,
|
|
axisNameAlpha: chartAttrs.xaxisnamealpha,
|
|
axisNameFontAlpha: chartAttrs.xaxisnamefontalpha,
|
|
axisNameBgAlpha: chartAttrs.xaxisnamebgalpha,
|
|
axisNameBorderAlpha: chartAttrs.xaxisnameborderalpha,
|
|
axisNameBorderPadding: chartAttrs.xaxisnameborderpadding,
|
|
axisNameBorderRadius: chartAttrs.xaxisnameborderradius,
|
|
axisNameBorderThickness: chartAttrs.xaxisnameborderthickness,
|
|
axisNameBorderDashed: chartAttrs.xaxisnameborderdashed,
|
|
axisNameBorderDashLen: chartAttrs.xaxisnameborderdashlen,
|
|
axisNameBorderDashGap: chartAttrs.xaxisnameborderdashgap,
|
|
useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
|
|
divLineColor: pluck (chartAttrs.vdivlinecolor, chartAttrs.divlinecolor,
|
|
colorM.getColor (palleteString.divLineColor)),
|
|
divLineAlpha: pluck (chartAttrs.vdivlinealpha, chartAttrs.divlinealpha,
|
|
is3d ? colorM.getColor(divLineAlpha3DStr) : colorM.getColor (divLineAlphaStr)),
|
|
divLineThickness: pluckNumber (chartAttrs.vdivlinethickness, chartAttrs.divlinethickness, 1),
|
|
divLineIsDashed: Boolean (pluckNumber (chartAttrs.vdivlinedashed, chartAttrs.vdivlineisdashed,
|
|
chartAttrs.divlinedashed, chartAttrs.divlineisdashed, 0)),
|
|
divLineDashLen: pluckNumber (chartAttrs.vdivlinedashlen, chartAttrs.divlinedashlen, 4),
|
|
divLineDashGap: pluckNumber (chartAttrs.vdivlinedashgap, chartAttrs.divlinedashgap, 2),
|
|
showAlternateGridColor: pluckNumber(chartAttrs.showalternatevgridcolor, 0),
|
|
alternateGridColor: pluck(chartAttrs.alternatevgridcolor, colorM.getColor(altVGridColorStr)),
|
|
alternateGridAlpha: pluck(chartAttrs.alternatevgridalpha, colorM.getColor(altVGridAlphaStr)),
|
|
numDivLines: chartAttrs.numvdivlines,
|
|
labelFont: chartAttrs.labelfont,
|
|
labelFontSize: chartAttrs.labelfontsize,
|
|
labelFontColor: chartAttrs.labelfontcolor,
|
|
labelFontAlpha: chartAttrs.labelalpha,
|
|
labelFontBold : chartAttrs.labelfontbold,
|
|
labelFontItalic : chartAttrs.labelfontitalic,
|
|
axisName: chartAttrs.xaxisname,
|
|
axisMinValue: chartAttrs.xaxisminvalue,
|
|
axisMaxValue: chartAttrs.xaxismaxvalue,
|
|
setAdaptiveMin: chartAttrs.setadaptivexmin,
|
|
adjustDiv: chartAttrs.adjustvdiv,
|
|
labelDisplay: chartAttrs.labeldisplay,
|
|
showLabels: pluckNumber(chartAttrs.showxaxislabels, chartAttrs.showlabels),
|
|
rotateLabels: chartAttrs.rotatexaxislabels,
|
|
slantLabel: pluckNumber(chartAttrs.slantlabels, chartAttrs.slantlabel),
|
|
labelStep: pluckNumber(chartAttrs.labelstep, chartAttrs.xaxisvaluesstep),
|
|
showAxisValues: pluckNumber(chartAttrs.showxaxisvalues, chartAttrs.showxaxisvalue),
|
|
maxLabelHeight : chartAttrs.maxlabelheight,
|
|
// showLimits: chartAttrs.showvlimits,
|
|
// showDivLineValues: pluckNumber(chartAttrs.showvdivlinevalues, chartAttrs.showvdivlinevalues),
|
|
showZeroPlane: chartAttrs.showvzeroplane,
|
|
zeroPlaneColor: chartAttrs.vzeroplanecolor,
|
|
zeroPlaneThickness: chartAttrs.vzeroplanethickness,
|
|
zeroPlaneAlpha: chartAttrs.vzeroplanealpha,
|
|
showZeroPlaneValue: chartAttrs.showvzeroplanevalue,
|
|
trendlineColor: chartAttrs.trendlinecolor,
|
|
trendlineToolText: chartAttrs.trendlinetooltext,
|
|
trendlineThickness: chartAttrs.trendlinethickness,
|
|
trendlineAlpha: chartAttrs.trendlinealpha,
|
|
showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
|
|
showAxisLine: pluckNumber(chartAttrs.showxaxisline, chartAttrs.showaxislines,
|
|
chartAttrs.drawAxisLines, 0),
|
|
axisLineThickness: pluckNumber(chartAttrs.xaxislinethickness, chartAttrs.axislinethickness, 1),
|
|
axisLineAlpha: pluckNumber(chartAttrs.xaxislinealpha, chartAttrs.axislinealpha, 100),
|
|
axisLineColor: pluck(chartAttrs.xaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
|
|
};
|
|
yAxisConf = {
|
|
outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, defaultFontStr),
|
|
outCanfontSize: pluckFontSize(chartAttrs.outcnvbasefontsize, chartAttrs.basefontsize, 10),
|
|
outCancolor: pluck(chartAttrs.outcnvbasefontcolor, chartAttrs.basefontcolor,
|
|
colorM.getColor(palleteString.baseFontColor)).replace(/^#?([a-f0-9]+)/ig, '#$1'),
|
|
axisNamePadding: chartAttrs.yaxisnamepadding,
|
|
axisValuePadding: chartAttrs.yaxisvaluespadding,
|
|
axisNameFont: chartAttrs.yaxisnamefont,
|
|
axisNameFontSize: chartAttrs.yaxisnamefontsize,
|
|
axisNameFontColor: chartAttrs.yaxisnamefontcolor,
|
|
axisNameFontBold: chartAttrs.yaxisnamefontbold,
|
|
axisNameFontItalic: chartAttrs.yaxisnamefontitalic,
|
|
axisNameBgColor: chartAttrs.yaxisnamebgcolor,
|
|
axisNameBorderColor: chartAttrs.yaxisnamebordercolor,
|
|
axisNameAlpha: chartAttrs.yaxisnamealpha,
|
|
axisNameFontAlpha: chartAttrs.yaxisnamefontalpha,
|
|
axisNameBgAlpha: chartAttrs.yaxisnamebgalpha,
|
|
axisNameBorderAlpha: chartAttrs.yaxisnameborderalpha,
|
|
axisNameBorderPadding: chartAttrs.yaxisnameborderpadding,
|
|
axisNameBorderRadius: chartAttrs.yaxisnameborderradius,
|
|
axisNameBorderThickness: chartAttrs.yaxisnameborderthickness,
|
|
axisNameBorderDashed: chartAttrs.yaxisnameborderdashed,
|
|
axisNameBorderDashLen: chartAttrs.yaxisnameborderdashlen,
|
|
axisNameBorderDashGap: chartAttrs.yaxisnameborderdashgap,
|
|
axisNameWidth: chartAttrs.yaxisnamewidth,
|
|
useEllipsesWhenOverflow: chartAttrs.useellipseswhenoverflow,
|
|
rotateAxisName: pluckNumber(chartAttrs.rotateyaxisname, 1),
|
|
axisName: chartAttrs.yaxisname,
|
|
showAlternateGridColor: pluckNumber(chartAttrs.showalternatehgridcolor, 1),
|
|
alternateGridColor: pluck(chartAttrs.alternatehgridcolor, colorM.getColor(altHGridColorStr)),
|
|
alternateGridAlpha: pluck(chartAttrs.alternatehgridalpha, colorM.getColor(altHGridAlphaStr)),
|
|
numDivLines: chartAttrs.numdivlines,
|
|
axisMinValue: chartAttrs.yaxisminvalue,
|
|
axisMaxValue: chartAttrs.yaxismaxvalue,
|
|
setAdaptiveMin: chartAttrs.setadaptiveymin,
|
|
adjustDiv: chartAttrs.adjustdiv,
|
|
labelStep: chartAttrs.yaxisvaluesstep,
|
|
showLabels: pluckNumber(chartAttrs.showyaxislabels, chartAttrs.showlabels),
|
|
maxLabelWidthPercent : chartAttrs.maxlabelwidthpercent,
|
|
showAxisValues: pluckNumber(chartAttrs.showyaxisvalues, chartAttrs.showyaxisvalue),
|
|
divLineColor: pluck(chartAttrs.hdivlinecolor, colorM.getColor(palleteString.divLineColor)),
|
|
divLineAlpha: pluck(chartAttrs.hdivlinealpha, colorM.getColor(divLineAlphaStr)),
|
|
divLineThickness: pluckNumber(chartAttrs.hdivlinethickness, 1),
|
|
divLineIsDashed: Boolean(pluckNumber(chartAttrs.hdivlinedashed, chartAttrs.hdivlineisdashed, 0)),
|
|
divLineDashLen: pluckNumber(chartAttrs.hdivlinedashlen, 4),
|
|
divLineDashGap: pluckNumber(chartAttrs.hdivlinedashgap, 2),
|
|
// showLimits: chartAttrs.showlimits,
|
|
// showDivLineValues: pluckNumber(chartAttrs.showdivlinevalues, chartAttrs.showdivlinevalue),
|
|
showZeroPlane: chartAttrs.showzeroplane,
|
|
zeroPlaneColor: chartAttrs.zeroplanecolor,
|
|
zeroPlaneThickness: chartAttrs.zeroplanethickness,
|
|
zeroPlaneAlpha: chartAttrs.zeroplanealpha,
|
|
showZeroPlaneValue: chartAttrs.showzeroplanevalue,
|
|
trendlineColor: chartAttrs.trendlinecolor,
|
|
trendlineToolText: chartAttrs.trendlinetooltext,
|
|
trendlineThickness: chartAttrs.trendlinethickness,
|
|
trendlineAlpha: chartAttrs.trendlinealpha,
|
|
showTrendlinesOnTop: chartAttrs.showtrendlinesontop,
|
|
showAxisLine: pluckNumber(chartAttrs.showyaxisline, chartAttrs.showaxislines,
|
|
chartAttrs.drawAxisLines, 0),
|
|
axisLineThickness: pluckNumber(chartAttrs.yaxislinethickness, chartAttrs.axislinethickness, 1),
|
|
axisLineAlpha: pluckNumber(chartAttrs.yaxislinealpha, chartAttrs.axislinealpha, 100),
|
|
axisLineColor: pluck(chartAttrs.yaxislinecolor, chartAttrs.axislinecolor, COLOR_000000)
|
|
};
|
|
xAxisConf.vtrendlines = dataObj.vtrendlines;
|
|
yAxisConf.trendlines = dataObj.trendlines;
|
|
yAxis = components.yAxis[0];
|
|
xAxis = components.xAxis[0];
|
|
|
|
yAxis.setCommonConfigArr(yAxisConf, true, true, false);
|
|
xAxis.setCommonConfigArr(xAxisConf, false, false, iapi.config.placeAxisLabelsOnTop ? true : false);
|
|
yAxis.configure();
|
|
xAxis.configure();
|
|
|
|
// set the chart categories
|
|
iapi._setCategories();
|
|
|
|
},
|
|
|
|
_setAxisLimits : function () {
|
|
|
|
},
|
|
|
|
_setCategories: function() {
|
|
|
|
var iapi = this,
|
|
components = iapi.components,
|
|
dataObj = iapi.jsonData,
|
|
xAxis = components.xAxis,
|
|
yAxis = components.yAxis,
|
|
len = dataObj.dataset && dataObj.dataset[0].data && dataObj.dataset[0].data.length,
|
|
i,
|
|
columnObj,
|
|
rowObj,
|
|
columns,
|
|
rows,
|
|
columnArr = [],
|
|
rowArr = [],
|
|
columnFlag,
|
|
rowFlag,
|
|
j;
|
|
|
|
if (!dataObj.columns || !dataObj.rows) {
|
|
dataObj.columns = {};
|
|
dataObj.columns.column = columns = [];
|
|
|
|
dataObj.rows = {};
|
|
dataObj.rows.row = rows = [];
|
|
|
|
for (i = 0; i < len; i++) {
|
|
columnFlag = true;
|
|
rowFlag = true;
|
|
|
|
for (j=0; j<columns.length; j++) {
|
|
if (dataObj.dataset[0].data[i].columnid == columns[j].id) {
|
|
columnFlag = false;
|
|
}
|
|
}
|
|
if (columnFlag) {
|
|
columnObj = {
|
|
id : dataObj.dataset[0].data[i].columnid,
|
|
label: dataObj.dataset[0].data[i].columnid
|
|
};
|
|
dataObj.columns.column.push(columnObj);
|
|
}
|
|
|
|
for (j=0; j<rows.length; j++) {
|
|
if (dataObj.dataset[0].data[i].rowid == rows[j].id) {
|
|
rowFlag = false;
|
|
}
|
|
}
|
|
if (rowFlag) {
|
|
rowObj = {
|
|
id : dataObj.dataset[0].data[i].rowid,
|
|
label: dataObj.dataset[0].data[i].rowid
|
|
};
|
|
dataObj.rows.row.push(rowObj);
|
|
}
|
|
}
|
|
}
|
|
|
|
columns = dataObj.columns.column;
|
|
rows = dataObj.rows.row;
|
|
|
|
for (i = 0; i < (columns && columns.length); i++) {
|
|
columns[i].label = pluck(columns[i].label, columns[i].name, columns[i].id);
|
|
(columns[i].label !== UNDEFINED) && columnArr.push(columns[i]);
|
|
}
|
|
dataObj.columns.column = columnArr;
|
|
|
|
for (i = 0; i < (rows && rows.length); i++) {
|
|
rows[i].label = pluck(rows[i].label, rows[i].name, rows[i].id);
|
|
(rows[i].label !== UNDEFINED) && rowArr.push(rows[i]);
|
|
}
|
|
dataObj.rows.row = rowArr;
|
|
|
|
dataObj.columns && xAxis[0].setAxisPadding(0.5, 0.5);
|
|
dataObj.columns && xAxis[0].setCategory(dataObj.columns.column);
|
|
|
|
dataObj.columns && yAxis[0].setAxisPadding(0.5, 0.5);
|
|
dataObj.rows && yAxis[0].setCategory(dataObj.rows.row);
|
|
|
|
xAxis[0].setAxisConfig({
|
|
categoryNumDivLines : dataObj.columns.column.length - 1,
|
|
categoryDivLinesFromZero : 0,
|
|
showAlternateGridColor : 0
|
|
});
|
|
|
|
yAxis[0].setAxisConfig({
|
|
categoryNumDivLines : dataObj.rows.row.length - 1,
|
|
categoryDivLinesFromZero : 0,
|
|
showAlternateGridColor : 0
|
|
});
|
|
|
|
}
|
|
|
|
}, chartAPI.mscartesian, {
|
|
enablemousetracking: true
|
|
});
|
|
}]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-errorbar2d',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
//strings
|
|
preDefStr = lib.preDefStr,
|
|
colorStrings = preDefStr.colors,
|
|
COLOR_FFFFFF = colorStrings.FFFFFF,
|
|
COLOR_AAAAAA = colorStrings.AAAAAA,
|
|
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
columnStr = preDefStr.columnStr,
|
|
shadowStr = preDefStr.shadowStr,
|
|
errorBarStr = preDefStr.errorBarStr,
|
|
errorShadowStr = preDefStr.errorShadowStr,
|
|
miterStr = preDefStr.miterStr,
|
|
visibleStr = preDefStr.visibleStr,
|
|
visiblilityStr = preDefStr.visiblilityStr,
|
|
ROUND = preDefStr.ROUND,
|
|
PERCENTAGESTRING = preDefStr.PERCENTAGESTRING,
|
|
pStr = preDefStr.pStr,
|
|
sStr = preDefStr.sStr,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
parseTooltext = lib.parseTooltext,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
getValidValue = lib.getValidValue,
|
|
pluckNumber = lib.pluckNumber,
|
|
getFirstValue = lib.getFirstValue,
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
isIE = lib.isIE,
|
|
UNDEFINED,
|
|
NONE = 'none',
|
|
ROLLOVER = 'DataPlotRollOver',
|
|
ROLLOUT = 'DataPlotRollOut',
|
|
COMMASPACE = lib.COMMASPACE,
|
|
showHoverEffectStr = preDefStr.showHoverEffectStr,
|
|
SETROLLOVERATTR = preDefStr.setRolloverAttrStr,
|
|
SETROLLOUTATTR = preDefStr.setRolloutAttrStr,
|
|
DEFAULT_CURSOR = 'default',
|
|
|
|
PLOTBORDERCOLOR = 'plotBorderColor',
|
|
PLOTGRADIENTCOLOR = 'plotGradientColor',
|
|
SHOWSHADOW = 'showShadow',
|
|
POINTER = 'pointer',
|
|
EVENTARGS = 'eventArgs',
|
|
GROUPID = 'groupId',
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
|
|
TOUCH_THRESHOLD_PIXELS = lib.TOUCH_THRESHOLD_PIXELS,
|
|
CLICK_THRESHOLD_PIXELS = lib.CLICK_THRESHOLD_PIXELS,
|
|
M = 'M',
|
|
H = 'H',
|
|
V = 'V',
|
|
COMMA = ',',
|
|
math = Math,
|
|
mathRound = math.round,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
mathAbs = math.abs,
|
|
hasTouch = lib.hasTouch,
|
|
// hot/tracker threshold in pixels
|
|
HTP = hasTouch ? TOUCH_THRESHOLD_PIXELS :
|
|
CLICK_THRESHOLD_PIXELS,
|
|
// getColumnColor = lib.graphics.getColumnColor,
|
|
getFirstColor = lib.getFirstColor,
|
|
// pluckColor = lib.pluckColor,
|
|
getFirstAlpha = lib.getFirstAlpha,
|
|
getLightColor = lib.graphics.getLightColor,
|
|
convertColor = lib.graphics.convertColor,
|
|
HUNDREDSTRING = lib.HUNDREDSTRING,
|
|
// COMMASPACE = lib.COMMASPACE,
|
|
plotEventHandler = lib.plotEventHandler;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'ErrorBar2D', {
|
|
/*
|
|
* Function for parsing all the attributes and value given by the user at chart,dataset and set level.
|
|
* This function is called once from the init() function of the Column class.
|
|
*/
|
|
configure : function () {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
//logic = chart.logic,
|
|
conf = dataSet.config,
|
|
//fcJSON = dataSet.fcJSON,
|
|
JSONData = dataSet.JSONData,
|
|
setDataArr = JSONData.data,
|
|
setDataLen = setDataArr && setDataArr.length,
|
|
categories = chart.config.categories,
|
|
catLen = categories && categories.length,
|
|
len = mathMin(catLen, setDataLen),
|
|
chartAttr = chart.jsonData.chart,
|
|
colorM = chart.components.colorManager,
|
|
index = dataSet.index || dataSet.positionIndex,
|
|
showplotborder,
|
|
plotColor = colorM.getPlotColor(index),
|
|
plotBorderDash = pluckNumber(JSONData.dashed, chartAttr.plotborderdashed),
|
|
usePlotGradientColor = pluckNumber(chartAttr.useplotgradientcolor, 1),
|
|
showTooltip,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
yAxisName = parseUnsafeString(chartAttr.yaxisname),
|
|
xAxisName = parseUnsafeString(chartAttr.xaxisname),
|
|
tooltipSepChar = parseUnsafeString(pluck(chartAttr.tooltipsepchar, COMMASPACE)),
|
|
seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1),
|
|
parseTooltext = lib.parseTooltext,
|
|
formatedVal,
|
|
parserConfig,
|
|
setTooltext,
|
|
seriesname,
|
|
macroIndices,
|
|
tempPlotfillAngle,
|
|
toolText,
|
|
plotDashLen,
|
|
plotDashGap,
|
|
plotBorderThickness,
|
|
isRoundEdges,
|
|
showHoverEffect,
|
|
plotfillAngle,
|
|
plotFillAlpha,
|
|
plotRadius,
|
|
plotFillRatio,
|
|
plotgradientcolor,
|
|
plotBorderAlpha,
|
|
plotBorderColor,
|
|
plotBorderDashStyle,
|
|
initailPlotBorderDashStyle,
|
|
setData,
|
|
setValue,
|
|
dataObj,
|
|
config,
|
|
label,
|
|
colorArr,
|
|
hoverColor,
|
|
hoverAlpha,
|
|
hoverGradientColor,
|
|
hoverRatio,
|
|
hoverAngle,
|
|
hoverBorderColor,
|
|
hoverBorderAlpha,
|
|
hoverBorderThickness,
|
|
hoverBorderDashed,
|
|
hoverBorderDashGap,
|
|
hoverBorderDashLen,
|
|
hoverDashStyle,
|
|
hoverColorArr,
|
|
getDashStyle = lib.getDashStyle,
|
|
dataStore = dataSet.components.data,
|
|
numberFormatter = chart.components.numberFormatter,
|
|
toolTipValue,
|
|
setDisplayValue,
|
|
definedGroupPadding,
|
|
isBar = chart.isBar,
|
|
is3D = chart.is3D,
|
|
isStacked = chart.isStacked,
|
|
stack100Percent,
|
|
enableAnimation,
|
|
parentYAxis,
|
|
setDataDashed,
|
|
setDataPlotDashLen,
|
|
setDataPlotDashGap,
|
|
|
|
setErrorValue,
|
|
errorDataValue,
|
|
errorPercentValue,
|
|
errorInPercent,
|
|
i,
|
|
includeInLegend,
|
|
reflowData = /*logic.chartInstance.jsVars._reflowData*/ {},
|
|
reflowDataObj = reflowData.dataObj || (reflowData.dataObj = {}),
|
|
reflowChartObj = reflowDataObj.chart || (reflowDataObj.chart = {});
|
|
|
|
conf.legendSymbolColor = plotColor;
|
|
showplotborder = conf.showplotborder = pluckNumber(chartAttr.showplotborder, is3D ? 0 : 1);
|
|
conf.plotDashLen = plotDashLen = pluckNumber(chartAttr.plotborderdashlen, 5);
|
|
conf.plotDashGap = plotDashGap = pluckNumber(chartAttr.plotborderdashgap, 4);
|
|
conf.plotfillAngle = plotfillAngle = pluckNumber(360 - chartAttr.plotfillangle, (isBar ? 180 : 90));
|
|
conf.plotFillAlpha = plotFillAlpha = pluck(JSONData.alpha, chartAttr.plotfillalpha, HUNDREDSTRING);
|
|
conf.plotColor = plotColor = pluck(JSONData.color, plotColor);
|
|
conf.legendSymbolColor = conf.plotColor;
|
|
conf.isRoundEdges = isRoundEdges = pluckNumber(chartAttr.useroundedges,0);
|
|
conf.plotRadius = plotRadius = pluckNumber(chartAttr.useRoundEdges, conf.isRoundEdges ? 1 : 0);
|
|
conf.plotFillRatio = plotFillRatio = pluck(JSONData.ratio, chartAttr.plotfillratio);
|
|
conf.plotgradientcolor = plotgradientcolor = lib.getDefinedColor(chartAttr.plotgradientcolor,
|
|
colorM.getColor(PLOTGRADIENTCOLOR));
|
|
!usePlotGradientColor && (plotgradientcolor = BLANKSTRING);
|
|
conf.plotBorderAlpha = plotBorderAlpha = showplotborder ? pluck(chartAttr.plotborderalpha,
|
|
plotFillAlpha, HUNDREDSTRING): 0;
|
|
conf.plotBorderColor = plotBorderColor = pluck(chartAttr.plotbordercolor,
|
|
is3D ? COLOR_FFFFFF : colorM.getColor(PLOTBORDERCOLOR));
|
|
conf.plotBorderThickness = plotBorderThickness = pluckNumber(chartAttr.plotborderthickness, 1);
|
|
conf.plotBorderDashStyle = initailPlotBorderDashStyle = plotBorderDash ?
|
|
getDashStyle(plotDashLen, plotDashGap, plotBorderThickness) : NONE;
|
|
conf.showValues = pluckNumber(JSONData.showvalues, chartAttr.showvalues, 1);
|
|
conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
|
|
conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
|
|
chartAttr.defaultanimation, 1);
|
|
conf.animation = !enableAnimation ? false : {
|
|
duration: pluckNumber(chartAttr.animationduration, 1) * 1000
|
|
};
|
|
reflowChartObj.transposeAnimation = conf.transposeAnimation =
|
|
pluckNumber(chartAttr.transposeanimation, reflowChartObj.transposeAnimation, enableAnimation);
|
|
conf.transposeAnimDuration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;
|
|
|
|
conf.showShadow = (isRoundEdges || is3D) ? pluckNumber(chartAttr.showshadow, 1) :
|
|
pluckNumber(chartAttr.showshadow, colorM.getColor(SHOWSHADOW));
|
|
conf.showHoverEffect = showHoverEffect = pluckNumber(chartAttr.plothovereffect,
|
|
chartAttr.showhovereffect, UNDEFINED);
|
|
conf.showTooltip = showTooltip = pluckNumber(chartAttr.showtooltip, 1);
|
|
conf.stack100Percent = stack100Percent =
|
|
pluckNumber(chart.stack100percent ,chartAttr.stack100percent, 0);
|
|
conf.definedGroupPadding = definedGroupPadding = mathMax(pluckNumber(chartAttr.plotspacepercent), 0);
|
|
conf.plotSpacePercent = mathMax(pluckNumber(chartAttr.plotspacepercent, 20) % 100, 0);
|
|
conf.maxColWidth = pluckNumber(isBar ? chartAttr.maxbarheight : chartAttr.maxcolwidth, 50);
|
|
conf.showPercentValues = pluckNumber(chartAttr.showpercentvalues, (isStacked && stack100Percent) ?
|
|
1 : 0);
|
|
conf.showPercentInToolTip = pluckNumber(chartAttr.showpercentintooltip,
|
|
(isStacked && stack100Percent) ? 1 : 0);
|
|
conf.plotPaddingPercent = pluckNumber(chartAttr.plotpaddingpercent),
|
|
conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
|
|
conf.placeValuesInside = pluckNumber(chartAttr.placevaluesinside, 0);
|
|
conf.includeInLegend = pluckNumber(JSONData.includeinlegend, 1);
|
|
|
|
conf.errorInPercent = errorInPercent = pluckNumber(JSONData.errorinpercent, chartAttr.errorinpercent);
|
|
|
|
conf.cumulativeValueOnErrorBar =
|
|
pluckNumber(JSONData.cumulativevalueonerrorbar, chartAttr.cumulativevalueonerrorbar, 1);
|
|
// conf.zeroPlaneColor = chart.options.chart.zeroPlaneColor;
|
|
// conf.zeroPlaneBorderColor = chart.options.chart.zeroPlaneBorderColor;
|
|
// conf.zeroPlaneShowBorder = chart.options.chart.zeroPlaneShowBorder;
|
|
|
|
conf.use3DLighting = pluckNumber(chartAttr.use3dlighting, 1);
|
|
conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
|
|
pStr) === sStr ? 1 : 0 ;
|
|
if (!dataStore) {
|
|
dataStore = dataSet.components.data = [];
|
|
}
|
|
|
|
// Parsing the attributes and values at set level.
|
|
for (i = 0; i < len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
config = dataObj && dataObj.config;
|
|
|
|
if (!dataObj) {
|
|
dataObj = dataStore[i] = {
|
|
graphics : {}
|
|
};
|
|
}
|
|
|
|
if (!dataObj.config) {
|
|
config = dataStore[i].config = {};
|
|
|
|
}
|
|
config.showValue = pluckNumber(setData.showvalue, conf.showValues);
|
|
config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
|
|
config.setLink = pluck(setData.link);
|
|
config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
|
|
config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
|
|
config.displayValue = pluck(setDisplayValue, toolTipValue);
|
|
setDataDashed = pluckNumber(setData.dashed);
|
|
setDataPlotDashLen = pluckNumber(setData.dashlen, plotDashLen);
|
|
setDataPlotDashGap = plotDashGap = pluckNumber(setData.dashgap, plotDashGap);
|
|
|
|
config.plotBorderDashStyle = plotBorderDashStyle = setDataDashed === 1 ?
|
|
getDashStyle(setDataPlotDashLen, setDataPlotDashGap, plotBorderThickness) :
|
|
(setDataDashed === 0 ? NONE : initailPlotBorderDashStyle);
|
|
plotColor = pluck(setData.color, conf.plotColor);
|
|
plotFillAlpha = pluck(setData.alpha, conf.plotFillAlpha);
|
|
|
|
// Setting the angle for plot fill for negative data
|
|
if (setValue < 0 && !isRoundEdges) {
|
|
|
|
tempPlotfillAngle = plotfillAngle;
|
|
plotfillAngle = isBar ? 180 - plotfillAngle : 360 - plotfillAngle;
|
|
}
|
|
|
|
// Setting the color Array to be applied to the bar/column.
|
|
config.colorArr = colorArr = lib.graphics.getColumnColor (
|
|
plotColor + COMMA + plotgradientcolor,
|
|
plotFillAlpha,
|
|
plotFillRatio,
|
|
plotfillAngle,
|
|
isRoundEdges,
|
|
plotBorderColor,
|
|
plotBorderAlpha.toString(),
|
|
(isBar ? 1 : 0),
|
|
(is3D ? true : false)
|
|
);
|
|
|
|
config.label = label =
|
|
getValidValue(parseUnsafeString(pluck (categories[i].tooltext, categories[i].label)));
|
|
|
|
// Parsing the hover effects only if showhovereffect is not 0.
|
|
if (showHoverEffect !== 0) {
|
|
|
|
hoverColor = pluck(setData.hovercolor, JSONData.hovercolor, chartAttr.plotfillhovercolor,
|
|
chartAttr.columnhovercolor, plotColor);
|
|
hoverAlpha = pluck(setData.hoveralpha, JSONData.hoveralpha,
|
|
chartAttr.plotfillhoveralpha, chartAttr.columnhoveralpha, plotFillAlpha);
|
|
hoverGradientColor = pluck(setData.hovergradientcolor,
|
|
JSONData.hovergradientcolor, chartAttr.plothovergradientcolor, plotgradientcolor);
|
|
!hoverGradientColor && (hoverGradientColor = BLANKSTRING);
|
|
hoverRatio = pluck(setData.hoverratio,
|
|
JSONData.hoverratio, chartAttr.plothoverratio, plotFillRatio);
|
|
hoverAngle = pluckNumber(360 - setData.hoverangle,
|
|
360 - JSONData.hoverangle, 360 - chartAttr.plothoverangle, plotfillAngle);
|
|
hoverBorderColor = pluck(setData.borderhovercolor,
|
|
JSONData.borderhovercolor, chartAttr.plotborderhovercolor, plotBorderColor);
|
|
hoverBorderAlpha = pluck(setData.borderhoveralpha,
|
|
JSONData.borderhoveralpha, chartAttr.plotborderhoveralpha,
|
|
chartAttr.plotfillhoveralpha, plotBorderAlpha, plotFillAlpha);
|
|
hoverBorderThickness = pluckNumber(setData.borderhoverthickness,
|
|
JSONData.borderhoverthickness, chartAttr.plotborderhoverthickness, plotBorderThickness);
|
|
hoverBorderDashed = pluckNumber(setData.borderhoverdashed,
|
|
JSONData.borderhoverdashed, chartAttr.plotborderhoverdashed);
|
|
hoverBorderDashGap = pluckNumber(setData.borderhoverdashgap,
|
|
JSONData.borderhoverdashgap, chartAttr.plotborderhoverdashgap, plotDashLen);
|
|
hoverBorderDashLen = pluckNumber(setData.borderhoverdashlen,
|
|
JSONData.borderhoverdashlen, chartAttr.plotborderhoverdashlen, plotDashGap);
|
|
hoverDashStyle = hoverBorderDashed ?
|
|
getDashStyle(hoverBorderDashLen, hoverBorderDashGap, hoverBorderThickness) :
|
|
plotBorderDashStyle;
|
|
|
|
/* If no hover effects are explicitly defined and
|
|
* showHoverEffect is not 0 then hoverColor is set.
|
|
*/
|
|
if (showHoverEffect == 1 && hoverColor === plotColor) {
|
|
hoverColor = getLightColor(hoverColor, 70);
|
|
}
|
|
|
|
// setting the hover color array which is always applied except when showHoverEffect is not 0.
|
|
hoverColorArr = lib.graphics.getColumnColor (
|
|
hoverColor + COMMA + hoverGradientColor,
|
|
hoverAlpha,
|
|
hoverRatio,
|
|
hoverAngle,
|
|
isRoundEdges,
|
|
hoverBorderColor,
|
|
hoverBorderAlpha.toString(),
|
|
(isBar ? 1 : 0),
|
|
(is3D ? true : false)
|
|
),
|
|
|
|
config.setRolloutAttr = {
|
|
fill: !is3D ? toRaphaelColor(colorArr[0])
|
|
: [toRaphaelColor(colorArr[0]), !conf.use3DLighting],
|
|
stroke: showplotborder && toRaphaelColor(colorArr[1]),
|
|
'stroke-width': plotBorderThickness,
|
|
'stroke-dasharray': plotBorderDashStyle
|
|
};
|
|
config.setRolloverAttr = {
|
|
fill: !is3D ? toRaphaelColor(hoverColorArr[0])
|
|
: [toRaphaelColor(hoverColorArr[0]), !conf.use3DLighting],
|
|
stroke: showplotborder && toRaphaelColor(hoverColorArr[1]),
|
|
'stroke-width': hoverBorderThickness,
|
|
'stroke-dasharray': hoverDashStyle
|
|
};
|
|
}
|
|
|
|
formatedVal = config.toolTipValue;
|
|
|
|
// Parsing tooltext against various configurations provided by the user.
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
|
|
JSONData.plottooltext, chartAttr.plottooltext)));
|
|
|
|
config.setErrorValue = setErrorValue = numberFormatter.getCleanValue(setData.errorvalue);
|
|
config.errorInPercent = pluckNumber(setData.errorinpercent, errorInPercent, 0);
|
|
|
|
config.errorInPercent &&
|
|
(config.setErrorValue = setErrorValue = pluckNumber(((setErrorValue / 100) * setValue).toFixed(2)));
|
|
|
|
config.cumulativeValueOnErrorBar =
|
|
pluckNumber(setData.cumulativevalueonerrorbar, conf.cumulativeValueOnErrorBar, 1);
|
|
|
|
config.positiveErrorValue =
|
|
numberFormatter.getCleanValue(pluckNumber(setData.positiveerrorvalue, setData.errorvalue));
|
|
|
|
(config.errorInPercent && config.positiveErrorValue) &&
|
|
(config.positiveErrorValue = pluckNumber(((config.positiveErrorValue / 100) *
|
|
setValue).toFixed(2)));
|
|
|
|
config.positiveCumulativeErrorValue = setValue +
|
|
pluckNumber(config.positiveErrorValue, config.setErrorValue);
|
|
|
|
config.negativeErrorValue =
|
|
numberFormatter.getCleanValue(pluckNumber(setData.negativeerrorvalue, setData.errorvalue));
|
|
|
|
(config.errorInPercent && config.negativeErrorValue) &&
|
|
(config.negativeErrorValue = pluckNumber(((config.negativeErrorValue / 100) *
|
|
setValue).toFixed(2)));
|
|
|
|
config.negativeCumulativeErrorValue = setValue -
|
|
pluckNumber(config.negativeErrorValue, config.setErrorValue);
|
|
|
|
config.errorToolTipValue = errorDataValue = numberFormatter.dataLabels(setErrorValue, parentYAxis);
|
|
|
|
|
|
config.negativeErrorToolTipValue =
|
|
numberFormatter.dataLabels(config.negativeErrorValue, parentYAxis);
|
|
|
|
config.negativeCumulativeErrorTooltipValue =
|
|
numberFormatter.dataLabels(config.negativeCumulativeErrorValue, parentYAxis);
|
|
|
|
config.positiveErrorToolTipValue =
|
|
numberFormatter.dataLabels(config.positiveErrorValue, parentYAxis);
|
|
|
|
config.positiveCumulativeErrorTooltipValue =
|
|
numberFormatter.dataLabels(config.positiveCumulativeErrorValue, parentYAxis);
|
|
|
|
config.errorPercentValue = errorPercentValue =
|
|
(mathRound(((setErrorValue / setValue) * HUNDREDSTRING) * HUNDREDSTRING) /
|
|
HUNDREDSTRING) + PERCENTAGESTRING;
|
|
|
|
if (!showTooltip) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
if (formatedVal === null) {
|
|
toolText = false;
|
|
}
|
|
else if (setTooltext !== undefined) {
|
|
macroIndices = [1,2,3,4,5,6,7,99,100,101,102,120,121];
|
|
parserConfig = {
|
|
yaxisName: yAxisName,
|
|
xaxisName: xAxisName ,
|
|
formattedValue : formatedVal,
|
|
errorValue: setErrorValue,
|
|
errorDataValue: errorDataValue,
|
|
errorPercentValue: errorPercentValue,
|
|
errorPercentDataValue: errorPercentValue,
|
|
positiveErrorValue: config.positiveErrorToolTipValue,
|
|
negativeErrorValue: config.negativeErrorToolTipValue,
|
|
label : label
|
|
};
|
|
toolText = parseTooltext(setTooltext, macroIndices,
|
|
parserConfig, setData, chartAttr, JSONData);
|
|
}
|
|
else {
|
|
if (seriesNameInTooltip) {
|
|
seriesname = getFirstValue(JSONData && JSONData.seriesname);
|
|
}
|
|
toolText = seriesname ? seriesname + tooltipSepChar : BLANKSTRING;
|
|
toolText += label ? label + tooltipSepChar : BLANKSTRING;
|
|
}
|
|
}
|
|
config.toolText = toolText;
|
|
config.setTooltext = toolText;
|
|
tempPlotfillAngle && (plotfillAngle = tempPlotfillAngle);
|
|
}
|
|
includeInLegend = dataSet.config.includeInLegend;
|
|
(chart.hasLegend !== false) && includeInLegend && dataSet._addLegend();
|
|
dataSet.ErrorValueConfigure();
|
|
},
|
|
|
|
ErrorValueConfigure: function() {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
conf = dataSet.config,
|
|
//fcJSON = dataSet.fcJSON,
|
|
JSONData = dataSet.JSONData,
|
|
setDataArr = JSONData.data,
|
|
setDataLen = setDataArr && setDataArr.length,
|
|
categories = chart.config.categories,
|
|
catLen = categories && categories.length,
|
|
len = mathMin(catLen, setDataLen),
|
|
chartAttr = chart.jsonData.chart,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
setData,
|
|
dataObj,
|
|
config,
|
|
dataStore = dataSet.components.data,
|
|
yAxisName = parseUnsafeString(chartAttr.yaxisname),
|
|
xAxisName = parseUnsafeString(chartAttr.xaxisname),
|
|
toolText,
|
|
seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1),
|
|
seriesname,
|
|
tooltipSepChar = parseUnsafeString(pluck(chartAttr.tooltipsepchar, COMMASPACE)),
|
|
macroIndices,
|
|
parserConfig,
|
|
toolTipValue,
|
|
errorBarAlpha,
|
|
setErrorValue,
|
|
formatedVal,
|
|
setTooltext,
|
|
errorBarShadow,
|
|
maxValue = -Infinity,
|
|
minValue = Infinity,
|
|
setValue,
|
|
errorValue,
|
|
notHalfErrorBar,
|
|
maxErrorValue,
|
|
minErrorValue,
|
|
halfErrorBar,
|
|
positiveErrorValue,
|
|
negativeErrorValue,
|
|
cumulativeValueOnErrorBar,
|
|
positiveCumulativeErrorTooltext,
|
|
negativeCumulativeErrorTooltext,
|
|
getTooltext = function(setTooltext) {
|
|
var toolText;
|
|
|
|
if (!conf.showTooltip) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
if (formatedVal === null) {
|
|
toolText = false;
|
|
}
|
|
else if (setTooltext !== undefined) {
|
|
macroIndices = [1,2,3,4,5,6,7,99,100,101,102,120,121];
|
|
parserConfig = {
|
|
yaxisName: yAxisName,
|
|
xaxisName: xAxisName ,
|
|
formattedValue : config.toolTipValue,
|
|
errorValue: setErrorValue,
|
|
errorDataValue: config.errorToolTipValue,
|
|
errorPercentValue: config.errorPercentValue,
|
|
errorPercentDataValue: config.errorPercentValue,
|
|
positiveErrorValue: config.positiveErrorToolTipValue,
|
|
negativeErrorValue: config.negativeErrorToolTipValue,
|
|
label : config.label
|
|
};
|
|
toolText = parseTooltext(setTooltext, macroIndices,
|
|
parserConfig, setData, chartAttr, JSONData);
|
|
}
|
|
else {
|
|
if (seriesNameInTooltip) {
|
|
seriesname = getFirstValue(JSONData && JSONData.seriesname);
|
|
}
|
|
toolText = seriesname ? seriesname + tooltipSepChar : BLANKSTRING;
|
|
toolText += config.label ? config.label + tooltipSepChar : BLANKSTRING;
|
|
}
|
|
}
|
|
return toolText;
|
|
},
|
|
positiveErrorToolText,
|
|
negativeErrorToolText,
|
|
i;
|
|
|
|
conf.showValues = pluckNumber(JSONData.showvalues, chartAttr.showvalues, 0);
|
|
conf.errorBarShadow = errorBarShadow = pluckNumber(chartAttr.errorbarshadow, chartAttr.showshadow, 1);
|
|
conf.ignoreEmptyDatasets = pluckNumber(JSONData.ignoreemptydatasets, 0);
|
|
halfErrorBar = pluckNumber(chartAttr.halferrorbar, 1);
|
|
conf.notHalfErrorBar = notHalfErrorBar = !pluckNumber(chartAttr.halferrorbar, 1);
|
|
|
|
errorBarAlpha = getFirstAlpha(pluck(
|
|
JSONData.errorbaralpha, chartAttr.errorbaralpha, conf.plotFillAlpha));
|
|
conf.errorBarWidthPercent = pluckNumber(
|
|
JSONData.errorbarwidthpercent, chartAttr.errorbarwidthpercent, 70);
|
|
conf.errorBarColor = convertColor(getFirstColor(
|
|
pluck(JSONData.errorbarcolor, chartAttr.errorbarcolor,
|
|
COLOR_AAAAAA)), errorBarAlpha);
|
|
conf.errorBarThickness = pluckNumber(
|
|
JSONData.errorbarthickness, chartAttr.errorbarthickness, 1);
|
|
conf.shadowOpacity = errorBarShadow ? (errorBarAlpha / 250) : 0;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
config = dataObj && dataObj.config;
|
|
positiveErrorToolText = UNDEFINED;
|
|
negativeErrorToolText = UNDEFINED;
|
|
|
|
if (pluckNumber(setData.value) === UNDEFINED) {
|
|
continue;
|
|
}
|
|
|
|
if (!dataObj) {
|
|
dataObj = dataStore[i] = {
|
|
graphics : {}
|
|
};
|
|
}
|
|
|
|
if (!dataObj.config) {
|
|
config = dataStore[i].config = {};
|
|
|
|
}
|
|
|
|
cumulativeValueOnErrorBar = config.cumulativeValueOnErrorBar;
|
|
|
|
config.notHalfErrorBar = conf.notHalfErrorBar;
|
|
config.halfErrorBar = halfErrorBar;
|
|
|
|
setValue = config.setValue;
|
|
config.showValue = pluckNumber(setData.showvalue, conf.showValues);
|
|
config.hasErrorValue = pluckNumber(setData.errorvalue) !== UNDEFINED ? 1 : 0;
|
|
setErrorValue = config.setErrorValue;
|
|
|
|
errorValue = config.errorValue = setErrorValue;
|
|
|
|
toolTipValue = config.errorToolTipValue;
|
|
|
|
formatedVal = toolTipValue;
|
|
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext,
|
|
formatedVal)));
|
|
|
|
toolText = getTooltext(setTooltext);
|
|
|
|
positiveErrorToolText = negativeErrorToolText = undefined;
|
|
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext,
|
|
config.positiveErrorToolTipValue)));
|
|
|
|
(setTooltext && config.positiveErrorToolTipValue) &&
|
|
(positiveErrorToolText = getTooltext(setTooltext));
|
|
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext,
|
|
config.negativeErrorToolTipValue)));
|
|
|
|
(setTooltext && config.negativeErrorToolTipValue) &&
|
|
(negativeErrorToolText = getTooltext(setTooltext));
|
|
|
|
if (cumulativeValueOnErrorBar) {
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext,
|
|
config.positiveCumulativeErrorTooltipValue)));
|
|
|
|
(setTooltext && config.positiveCumulativeErrorTooltipValue) &&
|
|
(positiveCumulativeErrorTooltext = getTooltext(setTooltext));
|
|
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext,
|
|
config.negativeCumulativeErrorTooltipValue)));
|
|
|
|
(setTooltext && config.negativeCumulativeErrorTooltipValue) &&
|
|
(negativeCumulativeErrorTooltext = getTooltext(setTooltext));
|
|
}
|
|
|
|
positiveErrorValue = config.positiveErrorValue;
|
|
|
|
negativeErrorValue = config.negativeErrorValue;
|
|
|
|
if (setData.positiveerrorvalue || setData.negativeerrorvalue) {
|
|
config.halfErrorBar = 0;
|
|
config.notHalfErrorBar = true;
|
|
}
|
|
|
|
maxErrorValue = setValue + (positiveErrorValue !== null ? positiveErrorValue : setErrorValue);
|
|
minErrorValue = setValue - (config.halfErrorBar ? 0 :
|
|
((negativeErrorValue < 0 && setValue < 0) ? 0 :
|
|
(negativeErrorValue != null ? negativeErrorValue : setErrorValue)));
|
|
|
|
maxValue = mathMax(maxValue, maxErrorValue, minErrorValue);
|
|
minValue = mathMin(minValue, maxErrorValue, minErrorValue);
|
|
|
|
config.errorValueArr = [];
|
|
|
|
(config.positiveErrorValue === null) && (config.positiveErrorValue = undefined);
|
|
errorValue = -config.positiveErrorValue;
|
|
config.errorValueArr.push({
|
|
errorValue: errorValue,
|
|
tooltext: cumulativeValueOnErrorBar ? positiveCumulativeErrorTooltext :
|
|
(positiveErrorToolText || toolText),
|
|
errorEdgeBar : true
|
|
});
|
|
|
|
config.errorValueArr.push({
|
|
errorValue: errorValue,
|
|
tooltext: positiveErrorToolText || toolText
|
|
});
|
|
|
|
if (config.notHalfErrorBar) {
|
|
errorValue = config.negativeErrorValue;
|
|
config.errorValueArr.push({
|
|
errorValue: errorValue,
|
|
tooltext: cumulativeValueOnErrorBar ? negativeCumulativeErrorTooltext :
|
|
(negativeErrorToolText || toolText),
|
|
errorEdgeBar : true
|
|
});
|
|
config.errorValueArr.push({
|
|
errorValue: errorValue,
|
|
tooltext: negativeErrorToolText || toolText
|
|
});
|
|
}
|
|
}
|
|
conf.maxValue = maxValue;
|
|
conf.minValue = minValue;
|
|
},
|
|
/*
|
|
* Function for initializing the column class object.
|
|
* This function is called once.
|
|
* @param {object} chart - The default FutionCharts chart object.
|
|
* @param {number} datasetIndex - The postion index of a dataset.
|
|
* @param {number} stackIndex - The stack index of a dataset.
|
|
*/
|
|
init : function(datasetJSON) {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
components = chart.components,
|
|
visible,
|
|
isDual = chart.isDual,
|
|
//todo
|
|
yAxis = isDual ? components.yAxis[dataSet.yAxis || 0] : components.yAxis[0];
|
|
|
|
|
|
|
|
if (!datasetJSON) {
|
|
return false;
|
|
}
|
|
dataSet.JSONData = datasetJSON;
|
|
dataSet.yAxis = yAxis;
|
|
dataSet.chartGraphics = chart.chartGraphics;
|
|
dataSet.components = {
|
|
};
|
|
|
|
dataSet.graphics = {
|
|
};
|
|
|
|
// defined(stackIndex) ? (dataSet.JSONData = dataJSONarr[datasetIndex].dataset[stackIndex]):
|
|
// (dataSet.JSONData = dataJSONarr[datasetIndex]);
|
|
dataSet.visible = visible = pluckNumber(dataSet.JSONData.visible,
|
|
!Number(dataSet.JSONData.initiallyhidden), 1) === 1;
|
|
dataSet.configure();
|
|
},
|
|
|
|
/*
|
|
* Function for drawing 2D columns.
|
|
* This function is called every time for each dataset when they are initially drawn or shown/hidden from
|
|
* the drawGraph() function.
|
|
*/
|
|
draw: function () {
|
|
var dataSet = this,
|
|
JSONData = dataSet.JSONData,
|
|
chartAttr = dataSet.chart.jsonData.chart,
|
|
conf = dataSet.config,
|
|
groupManager = dataSet.groupManager,
|
|
datasetIndex = dataSet.index,
|
|
categories = dataSet.chart.config.categories,
|
|
setDataArr = JSONData.data,
|
|
len,
|
|
setData,
|
|
attr,
|
|
i,
|
|
visible = dataSet.visible,
|
|
chart = dataSet.chart,
|
|
//jobList = chart.getJobList(),
|
|
paper = chart.components.paper,
|
|
xAxis = chart.components.xAxis[0],
|
|
yAxis = chart.components.yAxis[0],
|
|
parentContainer = chart.graphics.columnGroup,
|
|
isStacked = false,
|
|
xPos,
|
|
yPos,
|
|
crispBox,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
getValidValue = lib.getValidValue,
|
|
R = lib.Raphael,
|
|
showTooltip = conf.showTooltip,
|
|
xAxisZeroPos = xAxis.getAxisPosition(0),
|
|
xAxisFirstPos = xAxis.getAxisPosition(1),
|
|
groupMaxWidth = conf.groupMaxWidth = xAxisFirstPos - xAxisZeroPos,
|
|
definedGroupPadding = conf.definedGroupPadding,
|
|
plotSpacePercent = conf.plotSpacePercent,
|
|
groupPadding = plotSpacePercent / 200,
|
|
numOfColumns = 1,
|
|
positionValue = groupManager.getDataSetPosition(dataSet),
|
|
stackSumValue = groupManager.stackSumValue[dataSet.positionIndex],
|
|
manageClip = groupManager.manageClip,
|
|
maxColWidth = conf.maxColWidth,
|
|
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animType = animationObj.animType,
|
|
animObj = animationObj.animObj,
|
|
dummyObj = animationObj.dummyObj,
|
|
animationDuration = animationObj.duration,
|
|
|
|
// Calculating the net width occupied by bars for each category
|
|
groupNetWidth = (1 - definedGroupPadding * 0.01) * groupMaxWidth || mathMin(
|
|
groupMaxWidth * (1 - groupPadding * 2),
|
|
maxColWidth * numOfColumns
|
|
),
|
|
initialColumnWidth = pluckNumber(positionValue.columnWidth, (groupNetWidth / numOfColumns)),
|
|
columnWidth,
|
|
xPosOffset = positionValue.xPosOffset || 0,
|
|
hiddenDatasetHeight = positionValue.height,
|
|
height,
|
|
toolText,
|
|
dataStore = dataSet.components.data,
|
|
dataObj,
|
|
setTooltext,
|
|
setElement,
|
|
// hotElement,
|
|
setLink,
|
|
setValue,
|
|
// eventArgs,
|
|
displayValue,
|
|
groupId,
|
|
config,
|
|
setRolloutAttr = {},
|
|
setRolloverAttr = {},
|
|
|
|
yAxisMaxmin = yAxis.getLimit(),
|
|
yMax = yAxisMaxmin.max,
|
|
yMin = yAxisMaxmin.min,
|
|
|
|
isPositiveNegative = yMax > 0 && yMin < 0,
|
|
isPositive,
|
|
yBase = yAxis.getAxisBase(),
|
|
yBasePos = yAxis.yBasePos = yAxis.getAxisPosition(yBase),
|
|
previousY,
|
|
previousYPos,
|
|
heightBase = 0,
|
|
showShadow = conf.showShadow,
|
|
plotBorderThickness = conf.plotBorderThickness,
|
|
plotRadius = conf.plotRadius,
|
|
container = dataSet.graphics.container,
|
|
dataLabelContainer = dataSet.graphics.dataLabelContainer,
|
|
shadowContainer = dataSet.graphics.shadowContainer,
|
|
errorGroupContainer = dataSet.graphics.errorGroupContainer,
|
|
errorShadowContainer = dataSet.graphics.errorShadowContainer,
|
|
colorArr,
|
|
plotBorderDashStyle,
|
|
animFlag = true,
|
|
drawDataLabel = false,
|
|
drawSumLabel = false,
|
|
drawErrorBar = false,
|
|
isNewElement,
|
|
removeDataArr = dataSet.components.removeDataArr || [],
|
|
removeDataArrLen = removeDataArr.length,
|
|
pool = dataSet.components.pool || [],
|
|
//showHoverEffect = conf.showHoverEffect,
|
|
chartConfig = chart.config,
|
|
showHoverEffect = chartConfig.plothovereffect,
|
|
trackerConfig,
|
|
//Fired at the end of transpose animation.
|
|
animCallBack = function() {
|
|
/*
|
|
* It enters the if condition if the dataset is not visible that is the legend is clicked to
|
|
* hide the dataset. Also it is executed only once for each dataset though it is called by
|
|
* every plot of each dataset but the _conatinerHidden flag restricts multiple execution of the
|
|
* if condition.
|
|
*/
|
|
if (dataSet.visible === false && (dataSet._conatinerHidden === false ||
|
|
dataSet._conatinerHidden=== undefined)) {
|
|
container.hide();
|
|
shadowContainer.hide();
|
|
dataLabelContainer && dataLabelContainer.hide();
|
|
errorGroupContainer && errorGroupContainer.hide();
|
|
errorShadowContainer && errorShadowContainer.hide();
|
|
dataSet._conatinerHidden = true;
|
|
}
|
|
},
|
|
//animCompleteFn = chart.getAnimationCompleteFn(),
|
|
|
|
//Fired initially after the chart is rendered.
|
|
initAnimCallBack = function() {
|
|
dataSet.drawLabel();
|
|
dataSet.drawErrorValue();
|
|
//groupManager.drawSumValueFlag && groupManager.drawSumValue();
|
|
//animCompleteFn();
|
|
};
|
|
|
|
/*
|
|
* Creating a container group for the graphic element of column plots if
|
|
* not present and attaching it to its parent group.
|
|
*/
|
|
if (!container) {
|
|
container = dataSet.graphics.container =
|
|
paper.group(columnStr, parentContainer).trackTooltip(true);
|
|
|
|
// Clipping the group so that the plots do not come out of the canvas area when given thick border.
|
|
// if (!container.attrs['clip-rect'] && !isScroll) {
|
|
// container.attr({
|
|
// 'clip-rect': elements['clip-canvas']
|
|
// });
|
|
// }
|
|
if (visible) {
|
|
container.show();
|
|
}
|
|
else {
|
|
container.hide();
|
|
}
|
|
}
|
|
|
|
//chart.addCSSDefinition('.fusioncharts-datalabels .fusioncharts-label', labelCSS);
|
|
|
|
/*
|
|
* Creating the shadow element container group for each plots if not present
|
|
* and attaching it its parent group.
|
|
*/
|
|
if (!shadowContainer) {
|
|
// Always sending the shadow group to the back of the plots group.
|
|
shadowContainer = dataSet.graphics.shadowContainer =
|
|
paper.group(shadowStr, parentContainer).toBack();
|
|
// Clipping the group so that the shadow do not come out of the canvas area when given thick border.
|
|
// if (!shadowContainer.attrs['clip-rect'] && !isScroll) {
|
|
// shadowContainer.attr({
|
|
// 'clip-rect': elements['clip-canvas']
|
|
// });
|
|
// }
|
|
if (!visible) {
|
|
shadowContainer.hide();
|
|
}
|
|
|
|
}
|
|
|
|
len = xAxis.getCategoryLen();
|
|
|
|
// Create plot elements.
|
|
for (i = 0; i < len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
if (!dataObj) {
|
|
continue;
|
|
}
|
|
trackerConfig = dataObj.trackerConfig = {};
|
|
config = dataObj && dataObj.config;
|
|
setValue = config && config.setValue;
|
|
isNewElement = false;
|
|
|
|
// If plot value is found "null", continue the loop to next iteration.
|
|
if (dataObj === undefined || setValue === undefined || setValue === null) {
|
|
continue;
|
|
}
|
|
|
|
isPositive = setValue >= 0;
|
|
setLink = config.setLink;
|
|
colorArr = config.colorArr;
|
|
|
|
// Creating the data structure if not present for storing the graphics elements.
|
|
if (!dataObj.graphics) {
|
|
dataStore[i].graphics = {};
|
|
|
|
}
|
|
|
|
displayValue = config.displayValue;
|
|
|
|
previousY = isPositive ? config.previousPositiveY : config.previousNegativeY;
|
|
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
|
|
JSONData.plottooltext, chartAttr.plottooltext)));
|
|
|
|
/*
|
|
* If it is a stacked chart then the display value, tooltext value and data plots
|
|
* (if stack 100percent is active) is recalculated.
|
|
*/
|
|
if (isStacked) {
|
|
previousY = dataSet._parseValues(i, previousY, stackSumValue[i], setTooltext);
|
|
setValue = config.value;
|
|
}
|
|
|
|
// Getting the previous yposition of the plot and calculating the current yposition of the plot.
|
|
previousYPos = yAxis.getAxisPosition( previousY|| yBase);
|
|
xPos = xAxis.getAxisPosition(i) + xPosOffset;
|
|
|
|
/*
|
|
* Check for setting the height of the datasets which are hidden. If the datasets are hidden then
|
|
* the height is set to 0 and ypos is set to the ypos of the previous plot.
|
|
*/
|
|
if (hiddenDatasetHeight !== 0) {
|
|
yPos = yAxis.getAxisPosition(setValue + ( previousY || 0));
|
|
height = mathAbs(previousYPos - yPos);
|
|
}
|
|
else {
|
|
height = 0;
|
|
yPos = previousYPos;
|
|
}
|
|
yPos = mathMin(yPos,previousYPos);
|
|
|
|
// Fix for making the bottom border invisible for the plots.
|
|
if (!isPositiveNegative && manageClip && visible && plotBorderThickness > 0) {
|
|
height += plotBorderThickness;
|
|
groupManager.manageClip = false;
|
|
}
|
|
|
|
//todo- remove _ to make it public
|
|
dataObj._oriXPos = xPos;
|
|
dataObj._oriYPos = yPos;
|
|
dataObj._oriHeight = height;
|
|
dataObj._oriWidth = initialColumnWidth;
|
|
|
|
// Crisping the dataplots based on some condition determined by the column group manager.
|
|
if (groupManager.isCrisp) {
|
|
crispBox = R.crispBound(xPos, yPos, initialColumnWidth, height, plotBorderThickness);
|
|
xPos = crispBox.x;
|
|
yPos = crispBox.y;
|
|
columnWidth = crispBox.width;
|
|
height = crispBox.height;
|
|
}
|
|
else {
|
|
columnWidth = initialColumnWidth;
|
|
}
|
|
|
|
// Setting the final tooltext.
|
|
toolText = config.finalTooltext = (config.toolText !== false) && (config.toolText +
|
|
(setTooltext ? '' : config.toolTipValue));
|
|
plotBorderDashStyle = config.plotBorderDashStyle;
|
|
|
|
// Setting the event arguments.
|
|
trackerConfig.eventArgs = {
|
|
index: i,
|
|
link: setLink,
|
|
value: setValue,
|
|
cursor: setLink ? POINTER : BLANKSTRING,
|
|
displayValue: displayValue,
|
|
categoryLabel: categories[i].label,
|
|
toolText: !toolText ? '' : toolText,
|
|
id: BLANKSTRING,
|
|
datasetIndex: datasetIndex,
|
|
datasetName: JSONData.seriesname,
|
|
visible: visible
|
|
};
|
|
|
|
setRolloutAttr = config.setRolloutAttr;
|
|
setRolloverAttr = config.setRolloverAttr;
|
|
|
|
/*
|
|
* If animation is inactive then ybase position and heightBase of the plots is set to the final
|
|
* values.
|
|
*/
|
|
if (!animationDuration) {
|
|
yBasePos = yPos;
|
|
heightBase = height;
|
|
}
|
|
|
|
// Setting the attributes for plot drawing.
|
|
attr = {
|
|
x: xPos,
|
|
y: yBasePos,
|
|
width: columnWidth,
|
|
height: heightBase || 1,
|
|
r: plotRadius,
|
|
ishot: !showTooltip,
|
|
fill: toRaphaelColor(colorArr[0]),
|
|
stroke: toRaphaelColor(colorArr[1]),
|
|
'stroke-width': plotBorderThickness,
|
|
'stroke-dasharray': plotBorderDashStyle,
|
|
'stroke-linejoin': miterStr,
|
|
'visibility': visible
|
|
};
|
|
|
|
//todo- remove _ to make it public
|
|
dataObj._xPos = xPos;
|
|
dataObj._yPos = yPos;
|
|
dataObj._height = height;
|
|
dataObj._width = columnWidth;
|
|
|
|
/*
|
|
* If the data plots are not present then they are created, else only attributes are set for the
|
|
* existing plots.
|
|
*/
|
|
if (!dataObj.graphics.element) {
|
|
|
|
if(pool.element && pool.element.length) {
|
|
setElement = dataObj.graphics.element = pool.element.shift();
|
|
setElement.show();
|
|
}
|
|
// If there is no element in cachestore then create it freshly
|
|
else {
|
|
setElement = dataObj.graphics.element = paper.rect(attr, container);
|
|
isNewElement = true;
|
|
}
|
|
setElement.attr(attr);
|
|
|
|
setElement.animateWith(dummyObj, animObj, {
|
|
y: yPos,
|
|
height: height || 1
|
|
}, animationDuration, animType, (animFlag && initAnimCallBack));
|
|
|
|
animFlag = false;
|
|
config.elemCreated = true;
|
|
}
|
|
|
|
else {
|
|
drawSumLabel = drawDataLabel = drawErrorBar = true;
|
|
|
|
setElement = dataObj.graphics.element;
|
|
|
|
attr = {
|
|
x: xPos,
|
|
y: yPos,
|
|
width: columnWidth,
|
|
height: height || 1
|
|
};
|
|
|
|
setElement.animateWith(dummyObj, animObj, attr,
|
|
animationDuration, animType, (animFlag && animCallBack));
|
|
|
|
setElement.attr({
|
|
r: plotRadius,
|
|
ishot: !showTooltip,
|
|
fill: toRaphaelColor(colorArr[0]),
|
|
stroke: toRaphaelColor(colorArr[1]),
|
|
'stroke-width': plotBorderThickness,
|
|
'stroke-dasharray': plotBorderDashStyle,
|
|
'stroke-linejoin': miterStr,
|
|
'visibility': visible
|
|
});
|
|
config.elemCreated = false;
|
|
}
|
|
|
|
// The shadow element is set for the dataplots.
|
|
setElement
|
|
.shadow({opacity : showShadow}, shadowContainer)
|
|
.data('BBox', crispBox);
|
|
|
|
if (setLink || showTooltip) {
|
|
// Fix for touch devices.
|
|
if (height < HTP) {
|
|
yPos -= (HTP - height) / 2;
|
|
height = HTP;
|
|
}
|
|
|
|
// Setting attributes for the tooltip.
|
|
trackerConfig.attr = {
|
|
x: xPos,
|
|
y: yPos,
|
|
width: columnWidth,
|
|
height: height,
|
|
r: plotRadius,
|
|
stroke: TRACKER_FILL,
|
|
'stroke-width': plotBorderThickness,
|
|
fill: TRACKER_FILL,
|
|
ishot: true,
|
|
visibility: visible
|
|
};
|
|
}
|
|
|
|
groupId = datasetIndex + '_' + i;
|
|
|
|
// If algorithmic mouseTracking is enabled then attach these data to setElement
|
|
// because tracker element will not be drawn
|
|
chart.config.enablemousetracking && setElement
|
|
.data(GROUPID, groupId)
|
|
.data(EVENTARGS, trackerConfig.eventArgs)
|
|
.data(showHoverEffectStr, showHoverEffect)
|
|
.data(SETROLLOVERATTR, config.setRolloverAttr || {})
|
|
.data(SETROLLOUTATTR, config.setRolloutAttr || {});
|
|
}
|
|
|
|
removeDataArrLen && dataSet.remove();
|
|
// The dataLabels are drawn if the drawDataLabel flag is set.
|
|
drawDataLabel && dataSet.drawLabel();
|
|
|
|
drawErrorBar && dataSet.drawErrorValue();
|
|
},
|
|
|
|
show : function() {
|
|
var dataSet = this,
|
|
container = dataSet.graphics && dataSet.graphics.container,
|
|
dataLabelContainer = dataSet.graphics && dataSet.graphics.dataLabelContainer,
|
|
shadowContainer = dataSet.graphics && dataSet.graphics.shadowContainer,
|
|
errorGroupContainer = dataSet.graphics && dataSet.graphics.errorGroupContainer,
|
|
errorShadowContainer = dataSet.graphics && dataSet.graphics.errorShadowContainer,
|
|
is3D = dataSet.chart.is3D,
|
|
i,
|
|
data = dataSet.components.data,
|
|
dataSetLen = dataSet.JSONData.data && dataSet.JSONData.data.length,
|
|
categories = dataSet.chart.config.categories,
|
|
catLen = categories && categories.length,
|
|
yAxis = dataSet.yAxis,
|
|
chart = dataSet.chart,
|
|
len = mathMin(dataSetLen, catLen);
|
|
|
|
chart._chartAnimation();
|
|
dataSet.visible = true;
|
|
dataSet._conatinerHidden = false;
|
|
|
|
if (is3D) {
|
|
for (i = 0; i < len; i++) {
|
|
data[i].graphics.element && data[i].graphics.element.attr(visiblilityStr, visibleStr);
|
|
}
|
|
}
|
|
else {
|
|
container.show();
|
|
}
|
|
|
|
shadowContainer.show();
|
|
dataLabelContainer && dataLabelContainer.show();
|
|
errorGroupContainer && errorGroupContainer.show();
|
|
errorShadowContainer && errorShadowContainer.show();
|
|
|
|
chart._setAxisLimits();
|
|
yAxis.draw();
|
|
chart._drawDataset();
|
|
},
|
|
|
|
/*
|
|
* This function is used to make a dataset hidden when clicked on its respective legend.
|
|
* This fucntion is fired from drawGraph() every time an activated legend is clicked.
|
|
*/
|
|
hide : function() {
|
|
var dataSet = this,
|
|
yAxis = dataSet.yAxis,
|
|
chart = dataSet.chart;
|
|
|
|
chart._chartAnimation();
|
|
dataSet.visible = false;
|
|
chart._setAxisLimits();
|
|
yAxis.draw();
|
|
chart._drawDataset();
|
|
},
|
|
|
|
drawErrorValue: function() {
|
|
var dataSet = this,
|
|
JSONData = dataSet.JSONData,
|
|
//fcJSON = dataSet.fcJSON,
|
|
datasetIndex = dataSet.index,
|
|
conf = dataSet.config,
|
|
setDataArr = JSONData.data,
|
|
dataSetLen = setDataArr && setDataArr.length,
|
|
len,
|
|
setData,
|
|
attr,
|
|
i,
|
|
k,
|
|
visible = dataSet.visible,
|
|
chart = dataSet.chart,
|
|
catLen = chart.components.xAxis[0].getCategoryLen(),
|
|
parentContainer = chart.graphics.columnGroup,
|
|
paper = chart.components.paper,
|
|
//elements = chart.elements,
|
|
yAxis = chart.components.yAxis[0],
|
|
dataStore = dataSet.components.data,
|
|
|
|
groupManager = dataSet.groupManager,
|
|
positionValue = groupManager.getDataSetPosition(dataSet),
|
|
hiddenDatasetHeight = positionValue.height,
|
|
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animType = animationObj.animType,
|
|
animObj = animationObj.animObj,
|
|
dummyObj = animationObj.dummyObj,
|
|
animationDuration = animationObj.duration,
|
|
|
|
errorBarThickness = conf.errorBarThickness,
|
|
errorBarWidthPercent = conf.errorBarWidthPercent,
|
|
errorBarColor = conf.errorBarColor,
|
|
showTooltip = conf.showTooltip,
|
|
shadowOpacity = conf.shadowOpacity,
|
|
|
|
errorGroupContainer = dataSet.graphics.errorGroupContainer,
|
|
errorShadowContainer = dataSet.graphics.errorShadowContainer,
|
|
setLink,
|
|
tooltext,
|
|
xPos,
|
|
yPos,
|
|
|
|
useCrispErrorPath = 1,
|
|
dataObj,
|
|
setValue,
|
|
// groupId,
|
|
config,
|
|
// eventArgs,
|
|
crispY,
|
|
crispX,
|
|
errorPath,
|
|
errorValPos,
|
|
errorValuePosFactor,
|
|
errorValueArr,
|
|
errorValueObj,
|
|
errorValue,
|
|
errorStartPos,
|
|
errorLen,
|
|
errorBarWidth,
|
|
halfErrorBarW,
|
|
groupId,
|
|
errorLineElem,
|
|
errorTrackerElem,
|
|
errorValueElem,
|
|
isNegative,
|
|
barXpos,
|
|
barYpos,
|
|
barWidth,
|
|
barHeight,
|
|
trackerConfig,
|
|
trackerTolerance = errorBarThickness > 5 ? (errorBarThickness / 2) : 2.5,
|
|
errorTrackerConfig;
|
|
// errorElemClick = function(e) {
|
|
// var ele = this;
|
|
// plotEventHandler.call(ele, chart, e);
|
|
// },
|
|
// erroElemHoverFN = function(e) {
|
|
// var ele = this;
|
|
// plotEventHandler.call(ele, chart, e, ROLLOVER);
|
|
// }, erroElemOutFN = function(e) {
|
|
// var ele = this;
|
|
// plotEventHandler.call(ele, chart, e, ROLLOUT);
|
|
// },
|
|
// getErrLinkClickFN = function(link) {
|
|
// return function() {
|
|
// (link !== undefined) &&
|
|
// chart.linkClickFN.call({
|
|
// link: link
|
|
// }, chart);
|
|
// };
|
|
// };
|
|
|
|
if (!errorGroupContainer) {
|
|
errorGroupContainer = dataSet.graphics.errorGroupContainer =
|
|
paper.group(errorBarStr, parentContainer);
|
|
/*if (!errorGroupContainer.attrs['clip-rect']) {
|
|
errorGroupContainer.attr({
|
|
'clip-rect': elements['clip-canvas']
|
|
});
|
|
}*/
|
|
if (!visible) {
|
|
errorGroupContainer.hide();
|
|
}
|
|
}
|
|
|
|
if (!errorShadowContainer) {
|
|
// Always sending the shadow group to the back of the plots group.
|
|
errorShadowContainer = dataSet.graphics.errorShadowContainer =
|
|
paper.group(errorShadowStr, parentContainer).toBack();
|
|
/*if (!errorShadowContainer.attrs['clip-rect']) {
|
|
errorShadowContainer.attr({
|
|
'clip-rect': elements['clip-canvas']
|
|
});
|
|
}*/
|
|
if (!visible) {
|
|
errorShadowContainer.hide();
|
|
}
|
|
}
|
|
|
|
len = mathMin(catLen, dataSetLen);
|
|
|
|
// Loop through each data points
|
|
for (i = 0; i < len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
trackerConfig = dataObj.trackerConfig;
|
|
errorTrackerConfig = dataObj.errorTrackerConfig = {};
|
|
errorTrackerConfig.errorTrackerArr = [];
|
|
config = dataObj && dataObj.config;
|
|
setValue = config && config.setValue;
|
|
|
|
if (dataObj && (setValue === undefined || setValue === null)) {
|
|
if (dataObj.graphics.element) {
|
|
dataObj.graphics.element.hide();
|
|
dataObj.graphics.element.shadow(false);
|
|
}
|
|
dataObj.graphics.hotElement && dataObj.graphics.hotElement.hide();
|
|
errorLen = dataObj.graphics.error && dataObj.graphics.error.length;
|
|
for (k = 0; k < errorLen; k++) {
|
|
if (dataObj.graphics.error && dataObj.graphics.error[k]) {
|
|
dataObj.graphics.error[k].hide();
|
|
dataObj.graphics.error[k].shadow({opacity: 0});
|
|
}
|
|
}
|
|
}
|
|
|
|
// If plot value is found "null", continue the loop to next iteration.
|
|
if (dataObj === undefined || setValue === undefined || setValue === null) {
|
|
continue;
|
|
}
|
|
|
|
dataObj.errorBar && (delete dataObj.errorBar);
|
|
|
|
errorValueArr = config.errorValueArr;
|
|
errorTrackerConfig.errorLen = errorLen = errorValueArr.length;
|
|
|
|
!dataObj.graphics.error && (dataObj.graphics.error = []);
|
|
!dataObj.graphics.errorTracker && (dataObj.graphics.errorTracker = []);
|
|
|
|
if ((config.errorValue === BLANKSTRING || config.errorValue === undefined ||
|
|
(config.errorValue === null && config.positiveErrorValue === null &&
|
|
config.negativeErrorValue === null))) {
|
|
|
|
for (k = 0; k < errorLen; k++) {
|
|
if (dataObj.graphics.error && dataObj.graphics.error[k]) {
|
|
dataObj.graphics.error[k].hide();
|
|
dataObj.graphics.error[k].shadow({opacity: 0});
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
|
|
groupId = datasetIndex + '_' + i;
|
|
|
|
setLink = config.setLink;
|
|
|
|
isNegative = (setValue < 0);
|
|
|
|
barXpos = dataObj._oriXPos;
|
|
barYpos = dataObj._oriYPos;
|
|
barWidth = dataObj._oriWidth;
|
|
barHeight = dataObj._oriHeight;
|
|
|
|
yPos = isNegative ? (barYpos + barHeight) : barYpos;
|
|
xPos = barXpos + (barWidth / 2);
|
|
|
|
dataObj.errorBar || (dataObj.errorBar = []);
|
|
|
|
//Loop through errorValue array
|
|
while (errorLen--) {
|
|
errorTrackerElem = errorLineElem = errorValueElem =
|
|
null;
|
|
|
|
errorTrackerConfig.errorTrackerArr[errorLen] = {};
|
|
|
|
errorValueObj = errorValueArr[errorLen];
|
|
errorTrackerConfig.errorTrackerArr[errorLen].tooltext = tooltext = errorValueObj.tooltext;
|
|
errorStartPos = yPos;
|
|
errorValue = errorValueObj.errorValue;
|
|
|
|
if (errorValue === null || isNaN(errorValue)) {
|
|
if (dataObj.graphics.error && dataObj.graphics.error[errorLen]) {
|
|
dataObj.graphics.error[errorLen].hide();
|
|
dataObj.graphics.error[errorLen].shadow({opacity: 0});
|
|
}
|
|
|
|
continue;
|
|
}
|
|
errorBarWidth = barWidth * (errorBarWidthPercent / 100);
|
|
halfErrorBarW = errorBarWidth / 2;
|
|
|
|
errorValuePosFactor = (hiddenDatasetHeight === 0) ? 0 : 1;
|
|
// Vertical Error drawing
|
|
errorValPos = barYpos +
|
|
((yAxis.getAxisPosition(0) - yAxis.getAxisPosition(1)) * errorValue * errorValuePosFactor);
|
|
(isNegative) && (errorValPos = errorValPos + barHeight);
|
|
crispY = errorValPos;
|
|
crispX = xPos;
|
|
if (useCrispErrorPath) {
|
|
crispY = mathRound(errorValPos) +
|
|
(errorBarThickness % 2 / 2);
|
|
crispX = mathRound(xPos) +
|
|
(errorBarThickness % 2 / 2);
|
|
}
|
|
dataObj.errorBar[errorLen] || (dataObj.errorBar[errorLen] = []);
|
|
if (errorValueObj.errorEdgeBar) {
|
|
errorPath = [
|
|
M, crispX - halfErrorBarW, crispY,
|
|
H, (crispX + halfErrorBarW)
|
|
];
|
|
dataObj.errorBar[errorLen][1] = {
|
|
_xPos: crispX - halfErrorBarW - trackerTolerance,
|
|
_yPos: crispY - trackerTolerance,
|
|
_height: 2 * trackerTolerance,
|
|
_width: 2 * (halfErrorBarW + trackerTolerance),
|
|
_toolText : errorValueObj.tooltext
|
|
};
|
|
} else {
|
|
errorPath = [
|
|
M, crispX, errorStartPos,
|
|
V, crispY
|
|
];
|
|
dataObj.errorBar[errorLen][0] = {
|
|
_xPos: crispX - trackerTolerance,
|
|
_yPos: crispY < errorStartPos ? crispY : errorStartPos,
|
|
_height: mathAbs(errorStartPos - crispY),
|
|
_width: 2 * trackerTolerance,
|
|
_toolText : errorValueObj.tooltext
|
|
};
|
|
}
|
|
|
|
|
|
if (!dataObj.graphics.error[errorLen]) {
|
|
errorLineElem = dataObj.graphics.error[errorLen] =
|
|
paper.path(errorPath, errorGroupContainer)
|
|
.attr({
|
|
stroke: errorBarColor,
|
|
// In case of tooltip disabled this element should act as the hot element.
|
|
ishot: !showTooltip,
|
|
'stroke-width': errorBarThickness,
|
|
'cursor': setLink ? POINTER : BLANKSTRING,
|
|
'stroke-linecap': ROUND
|
|
});
|
|
}
|
|
else {
|
|
attr = {
|
|
path: errorPath
|
|
};
|
|
|
|
errorLineElem = dataObj.graphics.error[errorLen];
|
|
|
|
errorLineElem.animateWith(dummyObj, animObj, attr, animationDuration, animType);
|
|
|
|
errorLineElem.attr({
|
|
stroke: errorBarColor,
|
|
// In case of tooltip disabled this element should act as the hot element.
|
|
ishot: !showTooltip,
|
|
'stroke-width': errorBarThickness,
|
|
'cursor': setLink ? POINTER : BLANKSTRING,
|
|
'stroke-linecap': ROUND
|
|
});
|
|
}
|
|
|
|
errorLineElem.show();
|
|
|
|
errorLineElem
|
|
.shadow({opacity : shadowOpacity}, errorShadowContainer);
|
|
|
|
errorTrackerConfig.errorTrackerArr[errorLen].attr = {
|
|
path: errorPath,
|
|
stroke: TRACKER_FILL,
|
|
'stroke-width': (errorBarThickness < HTP) ? HTP : errorBarThickness,
|
|
'cursor': setLink ? POINTER : BLANKSTRING,
|
|
'ishot': !! setLink
|
|
};
|
|
chart.config.enablemousetracking && errorLineElem
|
|
.data(GROUPID, groupId)
|
|
.data(EVENTARGS, trackerConfig.eventArgs);
|
|
|
|
}
|
|
|
|
if (!config.notHalfErrorBar) {
|
|
for (k = 2; k < 4; k++) {
|
|
dataObj.graphics.error && dataObj.graphics.error[k] && dataObj.graphics.error[k].hide() &&
|
|
dataObj.graphics.error[k].shadow({opacity: 0});
|
|
}
|
|
}
|
|
}
|
|
},
|
|
_rolloverResponseSetter : function (chart, data, event) {
|
|
var dataGraphics = data.graphics,
|
|
errorBarHovered = data.errorBarHovered,
|
|
elem = dataGraphics && dataGraphics.element,
|
|
elData = elem && elem.getData();
|
|
|
|
!errorBarHovered && elem &&
|
|
elData.showHoverEffect !== 0 && elem.attr(elem.getData().setRolloverAttr);
|
|
elem && plotEventHandler.call(elem, chart, event, ROLLOVER);
|
|
},
|
|
_rolloutResponseSetter : function (chart, data, event) {
|
|
var dataGraphics = data.graphics,
|
|
errorBarHovered = data.errorBarHovered,
|
|
elem = dataGraphics && dataGraphics.element,
|
|
elData = elem && elem.getData();
|
|
|
|
!errorBarHovered && elem &&
|
|
elData.showHoverEffect !== 0 && elem.attr(elem.getData().setRolloutAttr);
|
|
elem && plotEventHandler.call(elem, chart, event, ROLLOUT);
|
|
},
|
|
/**
|
|
* This method handles all mouse events of an dataset.
|
|
* @param {String} eventType name of the event
|
|
* @param {number} plotIndex index of the plot where this event has been occured
|
|
* @param {Event} originalEvent reference of the original mouse event
|
|
*/
|
|
_firePlotEvent: function (eventType, plotIndex, e, datasetIndex) {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
data = dataset.components.data[plotIndex],
|
|
setElement = data.graphics.element,
|
|
errorBarHovered = data.errorBarHovered,
|
|
tip = lib.toolTip,
|
|
originalEvent = e.originalEvent,
|
|
style = chart.components.paper.canvas.style,
|
|
config = data.config,
|
|
setLink = config.setLink;
|
|
|
|
if (setElement) {
|
|
switch (eventType) {
|
|
case 'mouseover' :
|
|
dataset._decideTooltipType(plotIndex, datasetIndex, e);
|
|
dataset._rolloverResponseSetter(chart, data, originalEvent);
|
|
setLink && (style.cursor = POINTER);
|
|
break;
|
|
case 'mouseout' :
|
|
tip.hide(chart.chartInstance.id);
|
|
dataset._rolloutResponseSetter(chart, data, originalEvent);
|
|
setLink && (style.cursor = DEFAULT_CURSOR);
|
|
break;
|
|
case 'click' :
|
|
plotEventHandler.call(setElement, chart, originalEvent);
|
|
break;
|
|
case 'mousemove' :
|
|
dataset._decideTooltipType(plotIndex, datasetIndex, e);
|
|
if (errorBarHovered && !data._isRollover) {
|
|
setElement.showHoverEffect !== 0 &&
|
|
setElement.attr(setElement.getData().setRolloutAttr);
|
|
data._isRollover = true;
|
|
data._isRollout = false;
|
|
}
|
|
else if (!errorBarHovered && !data._isRollout) {
|
|
setElement.showHoverEffect !== 0 &&
|
|
setElement.attr(setElement.getData().setRolloverAttr);
|
|
data._isRollover = false;
|
|
data._isRollout = true;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
// Helper function of _checkPointerOverPlot().
|
|
_checkPointerOverErrorBar : function (pX, chartX, chartY) {
|
|
var dataset = this,
|
|
dataStore = dataset.components.data,
|
|
pointObj = dataStore[pX],
|
|
hovered,
|
|
errorBarArr,
|
|
errorBarCompArr,
|
|
len,
|
|
errorBarCompLen,
|
|
toolText,
|
|
xPos,
|
|
yPos,
|
|
height,
|
|
width;
|
|
|
|
if (!pointObj) {
|
|
return;
|
|
}
|
|
|
|
errorBarArr = pointObj.errorBar;
|
|
|
|
if (!errorBarArr) {
|
|
return;
|
|
}
|
|
|
|
len = errorBarArr && errorBarArr.length;
|
|
while (len--) {
|
|
errorBarCompArr = errorBarArr[len];
|
|
errorBarCompLen = errorBarCompArr && errorBarCompArr.length;
|
|
while (errorBarCompLen--) {
|
|
if (!(errorBarCompArr[errorBarCompLen] && errorBarCompArr[errorBarCompLen]._xPos)) {
|
|
continue;
|
|
}
|
|
xPos = errorBarCompArr[errorBarCompLen]._xPos;
|
|
yPos = errorBarCompArr[errorBarCompLen]._yPos;
|
|
height = errorBarCompArr[errorBarCompLen]._height;
|
|
width = errorBarCompArr[errorBarCompLen]._width;
|
|
toolText = errorBarCompArr[errorBarCompLen]._toolText;
|
|
|
|
hovered = chartX >= xPos && chartX <= xPos + width &&
|
|
chartY >= yPos && chartY <= yPos + height;
|
|
|
|
if (hovered) {
|
|
return {
|
|
pointIndex: pX,
|
|
hovered: hovered,
|
|
pointObj: dataStore[pX],
|
|
toolText : toolText
|
|
};
|
|
}
|
|
|
|
}
|
|
}
|
|
},
|
|
//Helper function of _getHoverPlot()
|
|
_checkPointerOverPlot : function (pX, chartX, chartY) {
|
|
var dataSet = this,
|
|
dataStore = dataSet.components.data,
|
|
data = dataStore[pX],
|
|
config = data && data.config,
|
|
hoverInfo;
|
|
|
|
if (!data) {
|
|
return;
|
|
}
|
|
|
|
hoverInfo = dataSet._checkPointerOverErrorBar(pX, chartX, chartY);
|
|
if (hoverInfo) {
|
|
data.errorBarHovered = true;
|
|
config.finalTooltext = hoverInfo.toolText;
|
|
} else {
|
|
hoverInfo = dataSet._checkPointerOverColumn(pX, chartX, chartY);
|
|
data.errorBarHovered = false;
|
|
|
|
hoverInfo && (config.finalTooltext = (config.toolText !== false) &&
|
|
(config.toolText + config.toolTipValue));
|
|
}
|
|
|
|
return hoverInfo;
|
|
},
|
|
/**
|
|
* Function that retunr the nearest plot details
|
|
* @param {number} x x-axis position of the mouse cordinate
|
|
* @param {number} y y-axis position of the mouse cordinate
|
|
* @returns {object} return an object with details of nearest polt and whether it is hovered or not
|
|
*/
|
|
_getHoveredPlot: function (chartX, chartY) {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
chartConfig = chart.config,
|
|
xAxis = chart.components.xAxis[0],
|
|
x,
|
|
canvas = chart.components.canvas,
|
|
canvasConfig = canvas.config,
|
|
canvasPadding = Math.max(canvasConfig.canvasPaddingLeft, canvasConfig.canvasPadding),
|
|
canvasLeft = chartConfig.canvasLeft,
|
|
pX;
|
|
|
|
x = xAxis.getValue(chartX - canvasLeft - canvasPadding);
|
|
pX = Math.round(x);
|
|
|
|
// Checking for overlap between two cosecutive column plots along x-axis
|
|
return (pX - x > 0 ? dataset._checkPointerOverPlot(pX, chartX, chartY) ||
|
|
dataset._checkPointerOverPlot(pX - 1, chartX, chartY) :
|
|
dataset._checkPointerOverPlot(pX + 1, chartX, chartY) ||
|
|
dataset._checkPointerOverPlot(pX, chartX, chartY));
|
|
},
|
|
// Function to remove a data from a dataset during real time update.
|
|
remove : function () {
|
|
var dataSet = this,
|
|
components = dataSet.components,
|
|
removeDataArr = components.removeDataArr,
|
|
pool = components.pool || (components.pool = {
|
|
element :[],
|
|
hotElement : [],
|
|
label : []
|
|
}),
|
|
len = removeDataArr.length,
|
|
removeData,
|
|
maxminFlag = dataSet.maxminFlag,
|
|
graphics,
|
|
i,
|
|
k;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
removeData = removeDataArr[0];
|
|
removeDataArr.splice(0,1);
|
|
// In case of non existing data plot continue;
|
|
if (!removeData || !removeData.graphics) {
|
|
continue;
|
|
}
|
|
|
|
graphics = removeData.graphics;
|
|
|
|
graphics.element && graphics.element.hide() && graphics.element.shadow({opacity: 0});
|
|
for (k = 0; k < 4; k++) {
|
|
graphics.error && graphics.error[k] && graphics.error[k].hide() &&
|
|
graphics.error[k].shadow({opacity: 0});
|
|
}
|
|
graphics.hotElement && graphics.hotElement.hide() && graphics.hotElement.attr({width : 0});
|
|
|
|
// Storing the graphic elements for reuse.
|
|
removeData.graphics.element && (pool.element = pool.element.concat(removeData.graphics.element));
|
|
removeData.graphics.hotElement && (pool.hotElement = pool.hotElement.concat(removeData.graphics.
|
|
hotElement));
|
|
removeData.graphics.label && (pool.label = pool.label.concat(removeData.graphics.label));
|
|
}
|
|
components.pool = pool;
|
|
maxminFlag && dataSet.setMaxMin();
|
|
}
|
|
|
|
},'Column']);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-errorline',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
//strings
|
|
preDefStr = lib.preDefStr,
|
|
colorStrings = preDefStr.colors,
|
|
COLOR_AAAAAA = colorStrings.AAAAAA,
|
|
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
errorBarStr = preDefStr.errorBarStr,
|
|
errorShadowStr = preDefStr.errorShadowStr,
|
|
ROUND = preDefStr.ROUND,
|
|
PERCENTAGESTRING = preDefStr.PERCENTAGESTRING,
|
|
|
|
LINE = preDefStr.line,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
parseTooltext = lib.parseTooltext,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
getValidValue = lib.getValidValue,
|
|
pluckNumber = lib.pluckNumber,
|
|
getFirstValue = lib.getFirstValue,
|
|
// getDefinedColor = lib.getDefinedColor,
|
|
isIE = lib.isIE,
|
|
UNDEFINED,
|
|
COMMASPACE = lib.COMMASPACE,
|
|
POINTER = 'pointer',
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
|
|
TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
|
|
TOUCH_THRESHOLD_PIXELS = lib.TOUCH_THRESHOLD_PIXELS,
|
|
CLICK_THRESHOLD_PIXELS = lib.CLICK_THRESHOLD_PIXELS,
|
|
M = 'M',
|
|
H = 'H',
|
|
V = 'V',
|
|
math = Math,
|
|
mathRound = math.round,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
mathAbs = math.abs,
|
|
hasTouch = lib.hasTouch,
|
|
// hot/tracker threshold in pixels
|
|
HTP = hasTouch ? TOUCH_THRESHOLD_PIXELS :
|
|
CLICK_THRESHOLD_PIXELS,
|
|
// getColumnColor = lib.graphics.getColumnColor,
|
|
getFirstColor = lib.getFirstColor,
|
|
// pluckColor = lib.pluckColor,
|
|
getFirstAlpha = lib.getFirstAlpha,
|
|
convertColor = lib.graphics.convertColor,
|
|
// POSITION_CENTER = lib.POSITION_CENTER,
|
|
// INT_ZERO = 0,
|
|
// renderer = chartAPI,
|
|
HUNDREDSTRING = lib.HUNDREDSTRING;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'ErrorLine', {
|
|
type: LINE,
|
|
|
|
/*
|
|
* Parses all the attributes for dataset level and set level
|
|
* Called from init function of area class and line class
|
|
* Both line and area attributes configuration is done here
|
|
*/
|
|
|
|
ErrorValueConfigure: function() {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
conf = dataSet.config,
|
|
chartConfig = chart.config,
|
|
parentYAxis = conf.parentYAxis,
|
|
JSONData = dataSet.JSONData,
|
|
setDataArr = JSONData.data,
|
|
chartAttr = chart.jsonData.chart,
|
|
xAxis = chart.components.xAxis[0],
|
|
len = xAxis.getCategoryLen(),
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
setData,
|
|
dataObj,
|
|
config,
|
|
dataStore = dataSet.components.data,
|
|
numberFormatter = chart.components.numberFormatter,
|
|
toolTipValue,
|
|
errorBarAlpha,
|
|
errorBarThickness,
|
|
setErrorValue,
|
|
formatedVal,
|
|
setTooltext,
|
|
positiveCumulativeErrorTooltext,
|
|
negativeCumulativeErrorTooltext,
|
|
positiveErrorToolText,
|
|
negativeErrorToolText,
|
|
errorBarShadow,
|
|
lineThickness = conf.linethickness,
|
|
maxValue = -Infinity,
|
|
minValue = Infinity,
|
|
halfErrorBar,
|
|
maxErrorValue,
|
|
minErrorValue,
|
|
setValue,
|
|
errorValue,
|
|
notHalfErrorBar,
|
|
yAxisName = parseUnsafeString(chartAttr.yaxisname),
|
|
xAxisName = parseUnsafeString(chartAttr.xaxisname),
|
|
cumulativeValueOnErrorBar,
|
|
tooltipSepChar = pluck(chartAttr.tooltipsepchar, COMMASPACE),
|
|
macroIndices,
|
|
parserConfig,
|
|
seriesname,
|
|
errorInPercent,
|
|
errorDataValue,
|
|
errorPercentValue,
|
|
errorToolText,
|
|
seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1),
|
|
getTooltext = function(setTooltext) {
|
|
var toolText;
|
|
|
|
if (!chartConfig.showtooltip) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
if (formatedVal === null) {
|
|
toolText = false;
|
|
}
|
|
else if (setTooltext !== undefined) {
|
|
macroIndices = [1,2,3,4,5,6,7,99,100,101,102];
|
|
parserConfig = {
|
|
yaxisName: yAxisName,
|
|
xaxisName: xAxisName ,
|
|
formattedValue : config.toolTipValue,
|
|
errorValue: setErrorValue,
|
|
errorDataValue: config.errorToolTipValue,
|
|
errorPercentValue: config.errorPercentValue,
|
|
errorPercentDataValue: config.errorPercentValue,
|
|
label : config.label
|
|
};
|
|
toolText = parseTooltext(setTooltext, macroIndices,
|
|
parserConfig, setData, chartAttr, JSONData);
|
|
}
|
|
else {
|
|
if (seriesNameInTooltip) {
|
|
seriesname = getFirstValue(JSONData && JSONData.seriesname);
|
|
}
|
|
toolText = seriesname ? seriesname + tooltipSepChar : BLANKSTRING;
|
|
toolText += config.label ? config.label + tooltipSepChar : BLANKSTRING;
|
|
}
|
|
}
|
|
return toolText;
|
|
},
|
|
i;
|
|
|
|
conf.errorBarShadow = errorBarShadow = pluckNumber(chartAttr.errorbarshadow, chartAttr.showshadow, 1);
|
|
conf.ignoreEmptyDatasets = pluckNumber(JSONData.ignoreemptydatasets, 0);
|
|
halfErrorBar = pluckNumber(chartAttr.halferrorbar, 1);
|
|
conf.notHalfErrorBar = notHalfErrorBar = !pluckNumber(chartAttr.halferrorbar, 1);
|
|
|
|
errorBarAlpha = getFirstAlpha(pluck(
|
|
JSONData.errorbaralpha, chartAttr.errorbaralpha, conf.alpha));
|
|
conf.errorBarWidth = pluckNumber(JSONData.errorbarwidth,
|
|
chartAttr.errorbarwidth, 5);
|
|
conf.errorBarColor = convertColor(getFirstColor(
|
|
pluck(JSONData.errorbarcolor, chartAttr.errorbarcolor,
|
|
COLOR_AAAAAA)), errorBarAlpha);
|
|
errorBarThickness = pluckNumber(
|
|
JSONData.errorbarthickness, chartAttr.errorbarthickness, 1);
|
|
conf.errorBarThickness = errorBarThickness > lineThickness ? lineThickness
|
|
: errorBarThickness;
|
|
conf.shadowOpacity = errorBarShadow ? (errorBarAlpha / 250) : 0;
|
|
|
|
conf.errorInPercent = errorInPercent = pluckNumber(JSONData.errorinpercent, chartAttr.errorinpercent);
|
|
|
|
conf.cumulativeValueOnErrorBar =
|
|
pluckNumber(JSONData.cumulativevalueonerrorbar, chartAttr.cumulativevalueonerrorbar, 1);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
setData = setDataArr && setDataArr[i];
|
|
|
|
if (!setDataArr || !setData) {
|
|
continue;
|
|
}
|
|
|
|
dataObj = dataStore[i];
|
|
config = dataObj && dataObj.config;
|
|
|
|
if (!dataObj) {
|
|
dataObj = dataStore[i] = {
|
|
graphics : {}
|
|
};
|
|
}
|
|
|
|
if (!dataObj.config) {
|
|
config = dataStore[i].config = {};
|
|
|
|
}
|
|
|
|
setValue = config.setValue;
|
|
|
|
config.notHalfErrorBar = conf.notHalfErrorBar;
|
|
setErrorValue = numberFormatter.getCleanValue(setData.errorvalue);
|
|
config.errorToolTipValue = errorDataValue = numberFormatter.dataLabels(setErrorValue, parentYAxis);
|
|
errorPercentValue = (mathRound(((setErrorValue / setValue) * HUNDREDSTRING) * HUNDREDSTRING) /
|
|
HUNDREDSTRING) + PERCENTAGESTRING;
|
|
config.setErrorValue = config.errorValue = errorValue = setErrorValue;
|
|
config.hasErrorValue = pluckNumber(setData.errorvalue) !== UNDEFINED ? 1 : 0;
|
|
|
|
toolTipValue = config.errorToolTipValue;
|
|
|
|
formatedVal = toolTipValue;
|
|
|
|
// Parsing tooltext against various configurations provided by the user.
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext, formatedVal)));
|
|
|
|
errorToolText = getTooltext(setTooltext);
|
|
|
|
config.errorInPercent = pluckNumber(setData.errorinpercent, errorInPercent, 0);
|
|
|
|
config.errorInPercent &&
|
|
(config.setErrorValue = setErrorValue = pluckNumber(((setErrorValue / 100) * setValue).toFixed(2)));
|
|
|
|
|
|
config.cumulativeValueOnErrorBar = cumulativeValueOnErrorBar =
|
|
pluckNumber(setData.cumulativevalueonerrorbar, conf.cumulativeValueOnErrorBar, 1);
|
|
|
|
config.positiveErrorValue =
|
|
numberFormatter.getCleanValue(pluckNumber(setData.positiveerrorvalue, setData.errorvalue));
|
|
|
|
(config.errorInPercent && config.positiveErrorValue) &&
|
|
(config.positiveErrorValue = pluckNumber(((config.positiveErrorValue / 100) *
|
|
setValue).toFixed(2)));
|
|
|
|
config.positiveCumulativeErrorValue = setValue +
|
|
pluckNumber(config.positiveErrorValue, config.setErrorValue);
|
|
|
|
config.negativeErrorValue =
|
|
numberFormatter.getCleanValue(pluckNumber(setData.negativeerrorvalue, setData.errorvalue));
|
|
|
|
(config.errorInPercent && config.negativeErrorValue) &&
|
|
(config.negativeErrorValue = pluckNumber(((config.negativeErrorValue / 100) *
|
|
setValue).toFixed(2)));
|
|
|
|
config.negativeCumulativeErrorValue = setValue -
|
|
pluckNumber(config.negativeErrorValue, config.setErrorValue);
|
|
|
|
config.errorToolTipValue = errorDataValue = numberFormatter.dataLabels(setErrorValue, parentYAxis);
|
|
|
|
config.negativeErrorToolTipValue =
|
|
numberFormatter.dataLabels(config.negativeErrorValue, parentYAxis);
|
|
|
|
config.negativeCumulativeErrorTooltipValue =
|
|
numberFormatter.dataLabels(config.negativeCumulativeErrorValue, parentYAxis);
|
|
|
|
config.positiveErrorToolTipValue =
|
|
numberFormatter.dataLabels(config.positiveErrorValue, parentYAxis);
|
|
|
|
config.positiveCumulativeErrorTooltipValue =
|
|
numberFormatter.dataLabels(config.positiveCumulativeErrorValue, parentYAxis);
|
|
|
|
config.errorPercentValue = errorPercentValue =
|
|
(mathRound(((setErrorValue / setValue) * HUNDREDSTRING) * HUNDREDSTRING) /
|
|
HUNDREDSTRING) + PERCENTAGESTRING;
|
|
|
|
positiveErrorToolText = negativeErrorToolText = undefined;
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext,
|
|
config.positiveErrorToolTipValue)));
|
|
|
|
(setTooltext && config.positiveErrorToolTipValue) &&
|
|
(positiveErrorToolText = getTooltext(setTooltext));
|
|
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext,
|
|
config.negativeErrorToolTipValue)));
|
|
|
|
(setTooltext && config.negativeErrorToolTipValue) &&
|
|
(negativeErrorToolText = getTooltext(setTooltext));
|
|
|
|
if (setData.positiveerrorvalue || setData.negativeerrorvalue) {
|
|
config.halfErrorBar = 0;
|
|
config.notHalfErrorBar = true;
|
|
}
|
|
|
|
if (cumulativeValueOnErrorBar) {
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext,
|
|
config.positiveCumulativeErrorTooltipValue)));
|
|
|
|
(setTooltext && config.positiveCumulativeErrorTooltipValue) &&
|
|
(positiveCumulativeErrorTooltext = getTooltext(setTooltext));
|
|
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext,
|
|
config.negativeCumulativeErrorTooltipValue)));
|
|
|
|
(setTooltext && config.negativeCumulativeErrorTooltipValue) &&
|
|
(negativeCumulativeErrorTooltext = getTooltext(setTooltext));
|
|
}
|
|
maxErrorValue = setValue + (config.positiveErrorValue !== null ?
|
|
config.positiveErrorValue : setErrorValue);
|
|
minErrorValue = setValue - (config.halfErrorBar ? 0 :
|
|
((config.negativeErrorValue < 0 && setValue < 0) ? 0 :
|
|
(config.negativeErrorValue != null ? config.negativeErrorValue : setErrorValue)));
|
|
|
|
maxValue = mathMax(maxValue, maxErrorValue, minErrorValue);
|
|
minValue = mathMin(minValue, maxErrorValue, minErrorValue);
|
|
|
|
(setErrorValue == null) && (setErrorValue = undefined);
|
|
|
|
config.errorValueArr = [];
|
|
(config.positiveErrorValue === null) && (config.positiveErrorValue = undefined);
|
|
errorValue = -config.positiveErrorValue;
|
|
config.errorValueArr.push({
|
|
errorValue: errorValue,
|
|
tooltext: cumulativeValueOnErrorBar ? positiveCumulativeErrorTooltext :
|
|
positiveErrorToolText || errorToolText,
|
|
errorEdgeBar : true
|
|
});
|
|
|
|
config.errorValueArr.push({
|
|
errorValue: errorValue,
|
|
tooltext: positiveErrorToolText || errorToolText
|
|
});
|
|
|
|
if (config.notHalfErrorBar) {
|
|
errorValue = config.negativeErrorValue;
|
|
config.errorValueArr.push({
|
|
errorValue: errorValue,
|
|
tooltext: cumulativeValueOnErrorBar ? negativeCumulativeErrorTooltext :
|
|
negativeErrorToolText || errorToolText,
|
|
errorEdgeBar : true
|
|
});
|
|
config.errorValueArr.push({
|
|
errorValue: errorValue,
|
|
tooltext: negativeErrorToolText || errorToolText
|
|
});
|
|
}
|
|
|
|
config.toolText = getTooltext(config.setTooltext); //toolText;
|
|
}
|
|
conf.maxValue = maxValue;
|
|
conf.minValue = minValue;
|
|
},
|
|
/*
|
|
* Initialization of line dataset
|
|
* @param {object} chart - chart object of fusioncharts
|
|
* @param {number} datasetIndex - index of line dataset
|
|
* @param {boolean} isLineSet - Whether it is a lineset or a dataset
|
|
* Called from draw graph of line
|
|
*/
|
|
init: function (datasetJSON) {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
components = chart.components,
|
|
isDual = chart.isDual,
|
|
yAxis;
|
|
dataSet.chart = chart;
|
|
yAxis = isDual ? components.yAxis[dataSet.yAxis || 0] : components.yAxis[0];
|
|
dataSet.yAxis = yAxis;
|
|
dataSet.components = {
|
|
|
|
};
|
|
|
|
dataSet.graphics = {
|
|
|
|
};
|
|
dataSet.JSONData = datasetJSON;
|
|
dataSet.visible = pluckNumber(dataSet.JSONData.visible,
|
|
!Number(dataSet.JSONData.initiallyhidden), 1) === 1;
|
|
dataSet.configure();
|
|
|
|
},
|
|
|
|
/*
|
|
* Makes a dataset visible when clicked on its respective legend
|
|
* Fired every time a deactivated legend is clicked
|
|
*/
|
|
show : function() {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
yAxis = dataSet.yAxis,
|
|
container = dataSet.graphics && dataSet.graphics.container,
|
|
dataLabelContainer = dataSet.graphics && dataSet.graphics.dataLabelContainer,
|
|
errorGroupContainer = dataSet.graphics && dataSet.graphics.errorGroupContainer,
|
|
errorShadowContainer = dataSet.graphics && dataSet.graphics.errorShadowContainer;
|
|
|
|
chart._chartAnimation();
|
|
container.lineGroup.show();
|
|
container.anchorGroup.show();
|
|
container.anchorShadowGroup.show();
|
|
container.lineShadowGroup.show();
|
|
dataLabelContainer.show();
|
|
dataSet.visible = true;
|
|
errorGroupContainer && errorGroupContainer.show();
|
|
errorShadowContainer && errorShadowContainer.show();
|
|
dataSet._conatinerHidden = false;
|
|
|
|
chart._setAxisLimits();
|
|
yAxis.draw();
|
|
// Calling the draw function for redrawing the dataset
|
|
chart._drawDataset();
|
|
},
|
|
|
|
/*
|
|
* Hides when clicked on its respective legend
|
|
* Fired every time an activated legend is clicked
|
|
*/
|
|
hide : function() {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
yAxis = dataSet.yAxis;
|
|
|
|
chart._chartAnimation();
|
|
dataSet.visible = false;
|
|
|
|
chart._setAxisLimits();
|
|
yAxis.draw();
|
|
chart._drawDataset();
|
|
},
|
|
|
|
drawErrorValue: function() {
|
|
var dataSet = this,
|
|
JSONData = dataSet.JSONData,
|
|
// fcJSON = dataSet.fcJSON,
|
|
conf = dataSet.config,
|
|
chart = dataSet.chart,
|
|
parentContainer = chart.graphics.datasetGroup,
|
|
chartComponents = chart.components,
|
|
setDataArr = JSONData.data,
|
|
xAxis = chartComponents.xAxis[0],
|
|
len = xAxis.getCategoryLen(),
|
|
setData,
|
|
attr,
|
|
i,
|
|
j,
|
|
k,
|
|
visible = dataSet.visible,
|
|
paper = chartComponents.paper,
|
|
yAxis = dataSet.yAxis,
|
|
dataStore = dataSet.components.data,
|
|
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animType = animationObj.animType,
|
|
animObj = animationObj.animObj,
|
|
dummyObj = animationObj.dummyObj,
|
|
animationDuration = animationObj.duration,
|
|
|
|
errorBarThickness = conf.errorBarThickness,
|
|
errorBarWidth = conf.errorBarWidth,
|
|
errorBarColor = conf.errorBarColor,
|
|
showTooltip = chart.config.showtooltip,
|
|
shadowOpacity = conf.shadowOpacity,
|
|
|
|
lineGroup = dataSet.graphics.container.lineGroup,
|
|
errorGroupContainer = dataSet.graphics.errorGroupContainer,
|
|
errorShadowContainer = dataSet.graphics.errorShadowContainer,
|
|
setLink,
|
|
tooltext,
|
|
xPos,
|
|
yPos,
|
|
useCrispErrorPath = /*!chartLogic.avoidCrispError*/1,
|
|
dataObj,
|
|
setValue,
|
|
// groupId,
|
|
config,
|
|
// eventArgs,
|
|
crispY,
|
|
crispX,
|
|
errorPath,
|
|
errorValPos,
|
|
errorValuePosFactor,
|
|
errorValueArr,
|
|
errorValueObj,
|
|
errorValue,
|
|
errorStartPos,
|
|
errorLen,
|
|
halfErrorBarW,
|
|
errorLineElem,
|
|
errorTrackerElem,
|
|
errorValueElem,
|
|
plotXpos,
|
|
trackerTolerance = errorBarThickness > 5 ? (errorBarThickness / 2) : 2.5,
|
|
plotYpos,
|
|
errorTrackerConfig;
|
|
|
|
if (!errorGroupContainer) {
|
|
errorGroupContainer = dataSet.graphics.errorGroupContainer =
|
|
paper.group(errorBarStr, parentContainer).insertAfter(lineGroup);
|
|
/*if (!errorGroupContainer.attrs['clip-rect']) {
|
|
errorGroupContainer.attr({
|
|
'clip-rect': elements['clip-canvas']
|
|
});
|
|
}*/
|
|
if (!visible) {
|
|
errorGroupContainer.hide();
|
|
}
|
|
}
|
|
|
|
if (!errorShadowContainer) {
|
|
// Always sending the shadow group to the back of the plots group.
|
|
errorShadowContainer = dataSet.graphics.errorShadowContainer =
|
|
paper.group(errorShadowStr, parentContainer).insertBefore(errorGroupContainer);
|
|
/*if (!errorShadowContainer.attrs['clip-rect']) {
|
|
errorShadowContainer.attr({
|
|
'clip-rect': elements['clip-canvas']
|
|
});
|
|
}*/
|
|
if (!visible) {
|
|
errorShadowContainer.hide();
|
|
}
|
|
}
|
|
|
|
// Loop through each data points
|
|
for (i = 0; i < len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
errorTrackerConfig = dataObj.errorTrackerConfig = {};
|
|
errorTrackerConfig.errorTrackerArr = [];
|
|
config = dataObj && dataObj.config;
|
|
setValue = config && config.setValue;
|
|
|
|
// If plot value is found "null", continue the loop to next iteration.
|
|
if (dataObj === undefined || setValue === undefined || setValue === null) {
|
|
|
|
if (dataObj.graphics.error) {
|
|
for (j = 0; j < dataObj.graphics.error.length; j++) {
|
|
dataObj.graphics.error[j].hide();
|
|
dataObj.graphics.errorTracker[j].hide();
|
|
dataObj.graphics.error[j].shadow(false);
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
|
|
errorValueArr = config.errorValueArr;
|
|
errorTrackerConfig.errorLen = errorLen = errorValueArr.length;
|
|
|
|
!dataObj.graphics.error && (dataObj.graphics.error = []);
|
|
!dataObj.graphics.errorTracker && (dataObj.graphics.errorTracker = []);
|
|
|
|
if ((config.errorValue === BLANKSTRING || config.errorValue === undefined ||
|
|
(config.errorValue === null && config.positiveErrorValue === null &&
|
|
config.negativeErrorValue === null))) {
|
|
|
|
for (k = 0; k < errorLen; k++) {
|
|
if (dataObj.graphics.error && dataObj.graphics.error[k]) {
|
|
dataObj.graphics.error[k].hide();
|
|
dataObj.graphics.error[k].shadow({opacity: 0});
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
setLink = config.setLink;
|
|
|
|
plotXpos = dataObj._xPos;
|
|
plotYpos = dataObj._yPos;
|
|
|
|
yPos = plotYpos;
|
|
xPos = plotXpos;
|
|
|
|
dataObj.errorBar && (delete dataObj.errorBar);
|
|
dataObj.errorBar = [];
|
|
//Loop through errorValue array
|
|
while (errorLen--) {
|
|
errorTrackerElem = errorLineElem = errorValueElem =
|
|
null;
|
|
errorTrackerConfig.errorTrackerArr[errorLen] = {};
|
|
errorValueObj = errorValueArr[errorLen];
|
|
errorTrackerConfig.errorTrackerArr[errorLen].tooltext = tooltext = errorValueObj.tooltext;
|
|
errorStartPos = yPos;
|
|
errorValue = errorValueObj.errorValue;
|
|
if (errorValue === null || isNaN(errorValue)) {
|
|
if (dataObj.graphics.error && dataObj.graphics.error[errorLen]) {
|
|
dataObj.graphics.error[errorLen].hide();
|
|
dataObj.graphics.error[errorLen].shadow({opacity: 0});
|
|
}
|
|
continue;
|
|
}
|
|
halfErrorBarW = errorBarWidth / 2;
|
|
|
|
errorValuePosFactor = (!visible) ? 0 : 1;
|
|
// Vertical Error drawing
|
|
errorValPos = plotYpos +
|
|
((yAxis.getAxisPosition(0) - yAxis.getAxisPosition(1)) * errorValue * errorValuePosFactor);
|
|
crispY = errorValPos;
|
|
crispX = xPos;
|
|
if (useCrispErrorPath) {
|
|
crispY = mathRound(errorValPos) +
|
|
(errorBarThickness % 2 / 2);
|
|
crispX = mathRound(xPos) +
|
|
(errorBarThickness % 2 / 2);
|
|
}
|
|
|
|
dataObj.errorBar[errorLen] || (dataObj.errorBar[errorLen] = []);
|
|
if (!errorValueObj.errorEdgeBar) {
|
|
errorPath = [
|
|
M, crispX, errorStartPos,
|
|
V, crispY
|
|
];
|
|
dataObj.errorBar[errorLen][0] = {
|
|
_xPos: crispX - trackerTolerance,
|
|
_yPos: crispY < errorStartPos ? crispY : errorStartPos,
|
|
_height: mathAbs(errorStartPos - crispY),
|
|
_width: 2 * trackerTolerance,
|
|
_toolText : errorValueObj.tooltext
|
|
};
|
|
} else {
|
|
errorPath = [
|
|
M, crispX - halfErrorBarW, crispY,
|
|
H, (crispX + halfErrorBarW)
|
|
];
|
|
dataObj.errorBar[errorLen][1] = {
|
|
_xPos: crispX - halfErrorBarW - trackerTolerance,
|
|
_yPos: crispY - trackerTolerance,
|
|
_height: 2 * trackerTolerance,
|
|
_width: 2 * (halfErrorBarW + trackerTolerance),
|
|
_toolText : errorValueObj.tooltext
|
|
};
|
|
}
|
|
|
|
if (!dataObj.graphics.error[errorLen]) {
|
|
errorLineElem = dataObj.graphics.error[errorLen] =
|
|
paper.path(errorPath, errorGroupContainer)
|
|
.attr({
|
|
stroke: errorBarColor,
|
|
// In case of tooltip disabled this element should act as the hot element.
|
|
ishot: !showTooltip,
|
|
'stroke-width': errorBarThickness,
|
|
'cursor': setLink ? POINTER : BLANKSTRING,
|
|
'stroke-linecap': ROUND
|
|
});
|
|
}
|
|
else {
|
|
attr = {
|
|
path: errorPath
|
|
};
|
|
|
|
errorLineElem = dataObj.graphics.error[errorLen];
|
|
|
|
errorLineElem.animateWith(dummyObj, animObj, attr, animationDuration, animType);
|
|
|
|
errorLineElem.attr({
|
|
stroke: errorBarColor,
|
|
// In case of tooltip disabled this element should act as the hot element.
|
|
ishot: !showTooltip,
|
|
'stroke-width': errorBarThickness,
|
|
'cursor': setLink ? POINTER : BLANKSTRING,
|
|
'stroke-linecap': ROUND
|
|
});
|
|
}
|
|
|
|
errorLineElem.show();
|
|
|
|
errorLineElem
|
|
.shadow({opacity : shadowOpacity}, errorShadowContainer);
|
|
|
|
errorTrackerConfig.errorTrackerArr[errorLen].attr = {
|
|
path: errorPath,
|
|
stroke: TRACKER_FILL,
|
|
'stroke-width': (errorBarThickness < HTP) ? HTP : errorBarThickness,
|
|
'cursor': setLink ? POINTER : BLANKSTRING,
|
|
'ishot': !! setLink
|
|
};
|
|
|
|
}
|
|
if (!config.notHalfErrorBar) {
|
|
for (k = 2; k < 4; k++) {
|
|
dataObj.graphics.error && dataObj.graphics.error[k] && dataObj.graphics.error[k].hide() &&
|
|
dataObj.graphics.error[k].shadow({opacity: 0});
|
|
}
|
|
}
|
|
}
|
|
},
|
|
_rolloverResponseSetter : FusionCharts.get(COMPONENT, [DATASET, 'ErrorBar2D'])
|
|
.prototype._rolloverResponseSetter,
|
|
_rolloutResponseSetter : FusionCharts.get(COMPONENT, [DATASET, 'ErrorBar2D'])
|
|
.prototype._rolloutResponseSetter,
|
|
_firePlotEvent : FusionCharts.get(COMPONENT, [DATASET, 'ErrorBar2D'])
|
|
.prototype._firePlotEvent,
|
|
_checkPointerOverErrorBar : FusionCharts.get(COMPONENT, [DATASET, 'ErrorBar2D'])
|
|
.prototype._checkPointerOverErrorBar,
|
|
|
|
//Helper function of _getHoverPlot()
|
|
_checkPointerOverPlot : function (pX, chartX, chartY) {
|
|
var dataSet = this,
|
|
dataStore = dataSet.components.data,
|
|
data = dataStore[pX],
|
|
config = data && data.config,
|
|
hoverInfo;
|
|
if (!data) {
|
|
return;
|
|
}
|
|
|
|
|
|
hoverInfo = dataSet.isWithinShape(data, pX, chartX, chartY);
|
|
|
|
if (hoverInfo) {
|
|
data.errorBarHovered = false;
|
|
config.finalTooltext = (config.toolText !== false) &&
|
|
(config.toolText + config.toolTipValue);
|
|
} else {
|
|
hoverInfo = dataSet._checkPointerOverErrorBar(pX, chartX, chartY);
|
|
if(hoverInfo) {
|
|
data.errorBarHovered = true;
|
|
config.finalTooltext = hoverInfo.toolText;
|
|
}
|
|
}
|
|
|
|
return hoverInfo;
|
|
},
|
|
_getHoveredPlot : FusionCharts.get(COMPONENT, [DATASET, 'ErrorBar2D'])
|
|
.prototype._getHoveredPlot,
|
|
/*
|
|
* This functions calculate the space required for a dataset and return that to the chart
|
|
*
|
|
*/
|
|
manageSpace: function () {
|
|
var dataset = this,
|
|
conf = dataset.config,
|
|
halfErrorBarW = conf.errorBarWidth * 0.5,
|
|
components = dataset.components || {},
|
|
chart = dataset.chart,
|
|
dataLabelStyle = chart.config.dataLabelStyle,
|
|
data = components.data || [],
|
|
firstData = data[0],
|
|
lastData = data[data.length - 1],
|
|
dataConf,
|
|
label,
|
|
dataAnchorConf,
|
|
labelDim = {},
|
|
padding,
|
|
labelSpace,
|
|
showValue,
|
|
SmartLabel = chart.linkedItems.smartLabel,
|
|
retrunDimension = {
|
|
paddingLeft: 0,
|
|
paddingRight: 0
|
|
};
|
|
|
|
|
|
// @todo also calculate the space for the labels
|
|
|
|
if (firstData) {
|
|
dataConf = firstData.config;
|
|
showValue = dataConf.showValue;
|
|
dataAnchorConf = dataConf && dataConf.anchorProps || {};
|
|
if (showValue) {
|
|
label = dataConf.displayValue;
|
|
SmartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
|
|
SmartLabel.setStyle(dataLabelStyle);
|
|
labelDim = SmartLabel.getOriSize(label);
|
|
}
|
|
if (dataConf.setValue) {
|
|
padding = mathMax(pluckNumber(dataAnchorConf.radius, 0), halfErrorBarW) +
|
|
pluckNumber(dataAnchorConf.borderThickness, 0);
|
|
labelSpace = (labelDim.width || 0)/2;
|
|
}
|
|
|
|
retrunDimension.paddingLeft = mathMax(padding, labelSpace);
|
|
}
|
|
|
|
if (lastData) {
|
|
dataConf = lastData.config;
|
|
showValue = dataConf.showValue;
|
|
dataAnchorConf = dataConf && dataConf.anchorProps || {};
|
|
if (showValue) {
|
|
label = dataConf.displayValue;
|
|
SmartLabel.setStyle(dataLabelStyle);
|
|
labelDim = SmartLabel.getOriSize(label);
|
|
}
|
|
if (dataConf.setValue) {
|
|
padding = mathMax(pluckNumber(dataAnchorConf.radius, 0), halfErrorBarW) +
|
|
pluckNumber(dataAnchorConf.borderThickness, 0);
|
|
labelSpace = (labelDim.width || 0)/2;
|
|
}
|
|
|
|
retrunDimension.paddingRight = mathMax(padding, labelSpace);
|
|
}
|
|
|
|
return retrunDimension;
|
|
},
|
|
|
|
_removeDataVisuals : function (dataObj) {
|
|
var graphics,
|
|
k;
|
|
if (!dataObj) {
|
|
return;
|
|
}
|
|
graphics = dataObj.graphics;
|
|
graphics.element && graphics.element.hide() && graphics.element.shadow({opacity: 0});
|
|
|
|
for (k = 0; k < 4; k++) {
|
|
dataObj.graphics.error && dataObj.graphics.error[k] && dataObj.graphics.error[k].hide() &&
|
|
dataObj.graphics.error[k].shadow({opacity: 0});
|
|
}
|
|
graphics.hotElement && graphics.hotElement.hide() && graphics.hotElement.attr({width : 0});
|
|
}
|
|
|
|
},LINE]);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-errorscatter',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
|
|
//strings
|
|
preDefStr = lib.preDefStr,
|
|
colorStrings = preDefStr.colors,
|
|
COLOR_AAAAAA = colorStrings.AAAAAA,
|
|
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
errorBarStr = preDefStr.errorBarStr,
|
|
errorShadowStr = preDefStr.errorShadowStr,
|
|
ROUND = preDefStr.ROUND,
|
|
PERCENTAGESTRING = preDefStr.PERCENTAGESTRING,
|
|
BLANK = lib.BLANKSTRING,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
parseTooltext = lib.parseTooltext,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
getValidValue = lib.getValidValue,
|
|
pluckNumber = lib.pluckNumber,
|
|
isIE = lib.isIE,
|
|
UNDEFINED,
|
|
COMMASPACE = lib.COMMASPACE,
|
|
POINTER = 'pointer',
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
|
|
TOUCH_THRESHOLD_PIXELS = lib.TOUCH_THRESHOLD_PIXELS,
|
|
CLICK_THRESHOLD_PIXELS = lib.CLICK_THRESHOLD_PIXELS,
|
|
M = 'M',
|
|
H = 'H',
|
|
V = 'V',
|
|
math = Math,
|
|
mathRound = math.round,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
mathAbs = math.abs,
|
|
hasTouch = lib.hasTouch,
|
|
// hot/tracker threshold in pixels
|
|
HTP = hasTouch ? TOUCH_THRESHOLD_PIXELS :
|
|
CLICK_THRESHOLD_PIXELS,
|
|
// getColumnColor = lib.graphics.getColumnColor,
|
|
getFirstColor = lib.getFirstColor,
|
|
// pluckColor = lib.pluckColor,
|
|
getFirstAlpha = lib.getFirstAlpha,
|
|
convertColor = lib.graphics.convertColor,
|
|
HUNDREDSTRING = lib.HUNDREDSTRING;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'ErrorScatter', {
|
|
|
|
ErrorValueConfigure: function() {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
chartComponents = chart.components,
|
|
conf = dataSet.config,
|
|
JSONData = dataSet.JSONData,
|
|
categories = chart.config.categories,
|
|
chartAttr = chart.jsonData.chart,
|
|
setDataArr = JSONData.data,
|
|
xAxis = chartComponents.xAxis[0],
|
|
catLen = xAxis.getCategoryLen(),
|
|
setDataLen = (setDataArr && setDataArr.length) || catLen,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
setData,
|
|
dataObj,
|
|
config,
|
|
dataStore = dataSet.components.data,
|
|
numberFormatter = chartComponents.numberFormatter,
|
|
errorBarAlpha,
|
|
errorBarThickness,
|
|
setErrorValue,
|
|
errorBarShadow,
|
|
errorBarWidth,
|
|
errorBarColor,
|
|
halfHorizontalErrorBar,
|
|
halfVerticalErrorBar,
|
|
horizontalErrorBarAlpha,
|
|
verticalErrorBarAlpha,
|
|
horizontalErrorBarColor,
|
|
verticalErrorBarColor,
|
|
horizontalErrorBarThickness,
|
|
verticalErrorBarThickness,
|
|
hErrorValue,
|
|
vErrorValue,
|
|
hErrorToolTipValue,
|
|
vErrorToolTipValue,
|
|
useHorizontalErrorBar,
|
|
useVerticalErrorBar,
|
|
tooltipSepChar = pluck(chartAttr.tooltipsepchar, COMMASPACE),
|
|
yAxisName = parseUnsafeString(chartAttr.yaxisname),
|
|
xAxisName = parseUnsafeString(chartAttr.xaxisname),
|
|
|
|
parentYAxis = conf.parentYAxis,
|
|
setValue,
|
|
errorPercentValue,
|
|
formatedVal,
|
|
toolText,
|
|
horizontalErrorPercent,
|
|
verticalErrorPercent,
|
|
macroIndices,
|
|
parserConfig,
|
|
seriesname,
|
|
infMin = -Infinity,
|
|
infMax = +Infinity,
|
|
maxErrorValue,
|
|
minErrorValue,
|
|
vPositiveErrorValue,
|
|
hNegativeErrorValue,
|
|
hPositiveErrorValue,
|
|
hPositiveSetTooltext,
|
|
hPositiveErrorToolTipValue,
|
|
hCPErrorToolText,
|
|
hCPErrorToolTipValue,
|
|
hNegativeErrorToolTipValue,
|
|
hCNErrorToolTipValue,
|
|
vPositiveErrorToolTipValue,
|
|
hNegativeSetTooltext,
|
|
vCPErrorToolTipValue,
|
|
vNegativeErrorValue,
|
|
vCNErrorToolText,
|
|
vCNErrorToolTipValue,
|
|
vPositiveSetTooltext,
|
|
hCNErrorToolText,
|
|
vCPErrorToolText,
|
|
cumulativeValueOnErrorBar,
|
|
vNegativeSetTooltext,
|
|
vNegativeErrorToolTipValue,
|
|
yMax = infMin,
|
|
yMin = infMax,
|
|
xMin = infMax,
|
|
xMax = infMin,
|
|
errorValue,
|
|
getTooltext = function(setTooltext, errorValue) {
|
|
var toolText;
|
|
|
|
if (!conf.showTooltip) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
if (formatedVal === null) {
|
|
toolText = false;
|
|
}
|
|
else if (setTooltext !== undefined) {
|
|
macroIndices = [1,2,3,4,5,6,7,8,9,10,11,99,100,101,102,103,104,105,106,107,109];
|
|
parserConfig = {
|
|
yaxisName: yAxisName,
|
|
xaxisName: xAxisName,
|
|
yDataValue: formatedVal,
|
|
xDataValue: config.label,
|
|
formattedValue : config.toolTipValue,
|
|
horizontalErrorValue: hErrorValue,
|
|
horizontalErrorDataValue: hErrorToolTipValue,
|
|
verticalErrorValue: vErrorValue,
|
|
verticalErrorDataValue: vErrorToolTipValue,
|
|
horizontalErrorPercent: horizontalErrorPercent,
|
|
verticalErrorPercent: verticalErrorPercent,
|
|
label : config.label,
|
|
errorValue: errorValue,
|
|
errorDataValue: errorValue,
|
|
errorPercentValue: config.errorPercentValue,
|
|
errorPercentDataValue: config.errorPercentValue
|
|
};
|
|
toolText = parseTooltext(setTooltext, macroIndices,
|
|
parserConfig, setData, chartAttr, JSONData);
|
|
}
|
|
else {
|
|
if (formatedVal === null) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
if (conf.seriesNameInTooltip) {
|
|
seriesname = lib.getFirstValue(JSONData && JSONData.seriesname);
|
|
}
|
|
toolText = seriesname ? seriesname + tooltipSepChar : BLANK;
|
|
toolText += setValue.x ? numberFormatter.xAxis(setValue.x) + tooltipSepChar : BLANK;
|
|
toolText += config.toolTipValue;
|
|
}
|
|
}
|
|
}
|
|
return toolText;
|
|
},
|
|
i;
|
|
|
|
conf.errorBarShadow = errorBarShadow = pluckNumber(chartAttr.errorbarshadow, chartAttr.showshadow, 0);
|
|
conf.ignoreEmptyDatasets = pluckNumber(JSONData.ignoreemptydatasets, 0);
|
|
conf.notHalfErrorBar = !pluckNumber(chartAttr.halferrorbar, 1);
|
|
|
|
conf.errorBarAlpha = getFirstAlpha(pluck(
|
|
JSONData.errorbaralpha, chartAttr.errorbaralpha));
|
|
conf.errorBarWidth = errorBarWidth = pluckNumber(JSONData.errorbarwidth,
|
|
chartAttr.errorbarwidth, 5);
|
|
conf.errorBarColor = errorBarColor = convertColor(getFirstColor(
|
|
pluck(JSONData.errorbarcolor, chartAttr.errorbarcolor,
|
|
COLOR_AAAAAA)), errorBarAlpha);
|
|
conf.errorBarThickness = errorBarThickness = pluckNumber(
|
|
JSONData.errorbarthickness, chartAttr.errorbarthickness, 1);
|
|
conf.shadowOpacity = errorBarShadow ? (errorBarAlpha / 250) : 0;
|
|
|
|
conf.halfHorizontalErrorBar = halfHorizontalErrorBar =
|
|
pluckNumber(chartAttr.halfhorizontalerrorbar, 1);
|
|
conf.halfVerticalErrorBar = halfVerticalErrorBar =
|
|
pluckNumber(chartAttr.halfverticalerrorbar, 1);
|
|
|
|
(conf.initAnimation === UNDEFINED) && (conf.initAnimation = chart.initAnimation);
|
|
|
|
horizontalErrorBarAlpha =
|
|
pluck(JSONData.horizontalerrorbaralpha,
|
|
JSONData.errorbaralpha,
|
|
chartAttr.horizontalerrorbaralpha, errorBarAlpha);
|
|
|
|
verticalErrorBarAlpha = pluckNumber(
|
|
JSONData.verticalerrorbaralpha, JSONData.errorbaralpha,
|
|
chartAttr.verticalerrorbaralpha, errorBarAlpha);
|
|
|
|
horizontalErrorBarColor = convertColor(pluck(
|
|
JSONData.horizontalerrorbarcolor, JSONData.errorbarcolor,
|
|
chartAttr.horizontalerrorbarcolor, errorBarColor),
|
|
horizontalErrorBarAlpha
|
|
);
|
|
|
|
verticalErrorBarColor = convertColor(pluck(
|
|
JSONData.verticalerrorbarcolor, JSONData.errorbarcolor,
|
|
chartAttr.verticalerrorbarcolor, errorBarColor),
|
|
verticalErrorBarAlpha
|
|
);
|
|
|
|
horizontalErrorBarThickness = pluckNumber(
|
|
JSONData.horizontalerrorbarthickness,
|
|
JSONData.errorbarthickness,
|
|
chartAttr.horizontalerrorbarthickness,
|
|
errorBarThickness);
|
|
|
|
verticalErrorBarThickness = pluckNumber(
|
|
JSONData.verticalerrorbarthickness,
|
|
JSONData.errorbarthickness,
|
|
chartAttr.verticalerrorbarthickness,
|
|
errorBarThickness);
|
|
|
|
conf.horizontalErrorBarWidth = pluckNumber(
|
|
JSONData.horizontalerrorbarwidth,
|
|
chartAttr.horizontalerrorbarwidth,
|
|
errorBarWidth);
|
|
|
|
conf.verticalErrorBarWidth = pluckNumber(
|
|
JSONData.verticalerrorbarwidth,
|
|
chartAttr.verticalerrorbarwidth,
|
|
errorBarWidth);
|
|
|
|
conf.cumulativeValueOnErrorBar =
|
|
pluckNumber(JSONData.cumulativevalueonerrorbar, chartAttr.cumulativevalueonerrorbar, 1);
|
|
|
|
for (i = 0; i < setDataLen; i++) {
|
|
|
|
if (!setDataArr) {
|
|
continue;
|
|
}
|
|
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
config = dataObj && dataObj.config;
|
|
|
|
if (!dataObj) {
|
|
dataObj = dataStore[i] = {
|
|
graphics : {}
|
|
};
|
|
}
|
|
|
|
if (!dataObj.config) {
|
|
config = dataStore[i].config = {};
|
|
|
|
}
|
|
|
|
setErrorValue = numberFormatter.getCleanValue(setData.errorvalue);
|
|
|
|
setValue = config.setValue;
|
|
config.errorValue = errorValue = setData.errorvalue;
|
|
|
|
config.cumulativeValueOnErrorBar = cumulativeValueOnErrorBar =
|
|
pluckNumber(setData.cumulativevalueonerrorbar, conf.cumulativeValueOnErrorBar, 1);
|
|
|
|
config.hErrorValue = hErrorValue = numberFormatter.getCleanValue(
|
|
pluck(setData.horizontalerrorvalue, setData.errorvalue));
|
|
|
|
config.vErrorValue = vErrorValue = numberFormatter.getCleanValue(
|
|
pluck(setData.verticalerrorvalue, setData.errorvalue));
|
|
|
|
config.hPositiveErrorValue = hPositiveErrorValue = numberFormatter.getCleanValue(
|
|
pluck(setData.horizontalpositiveerrorvalue, setData.positiveerrorvalue, hErrorValue));
|
|
config.hNegativeErrorValue = hNegativeErrorValue = numberFormatter.getCleanValue(
|
|
pluck(setData.horizontalnegativeerrorvalue, setData.negativeerrorvalue, hErrorValue));
|
|
|
|
|
|
config.vPositiveErrorValue = vPositiveErrorValue = numberFormatter.getCleanValue(
|
|
pluck(setData.verticalpositiveerrorvalue, setData.positiveerrorvalue, vErrorValue));
|
|
config.vNegativeErrorValue = vNegativeErrorValue = numberFormatter.getCleanValue(
|
|
pluck(setData.verticalnegativeerrorvalue, setData.negativeerrorvalue, vErrorValue));
|
|
|
|
hPositiveErrorToolTipValue =
|
|
numberFormatter.dataLabels(hPositiveErrorValue, parentYAxis);
|
|
|
|
hPositiveSetTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext, hPositiveErrorToolTipValue)));
|
|
|
|
hNegativeErrorToolTipValue =
|
|
numberFormatter.dataLabels(hNegativeErrorValue, parentYAxis);
|
|
|
|
hNegativeSetTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext, hNegativeErrorToolTipValue)));
|
|
|
|
vPositiveErrorToolTipValue =
|
|
numberFormatter.dataLabels(vPositiveErrorValue, parentYAxis);
|
|
|
|
vPositiveSetTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext, vPositiveErrorToolTipValue)));
|
|
|
|
vNegativeErrorToolTipValue =
|
|
numberFormatter.dataLabels(vNegativeErrorValue, parentYAxis);
|
|
|
|
vNegativeSetTooltext = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext, vNegativeErrorToolTipValue)));
|
|
hCPErrorToolText = hCNErrorToolText = vCPErrorToolText = vCNErrorToolText = undefined;
|
|
if (cumulativeValueOnErrorBar) {
|
|
hCPErrorToolTipValue =
|
|
numberFormatter.dataLabels(setValue.x + hPositiveErrorValue, parentYAxis);
|
|
hCPErrorToolText = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext, hCPErrorToolTipValue)));
|
|
|
|
hCNErrorToolTipValue =
|
|
numberFormatter.dataLabels(setValue.x - hNegativeErrorValue, parentYAxis);
|
|
hCNErrorToolText = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext, hCNErrorToolTipValue)));
|
|
|
|
vCPErrorToolTipValue =
|
|
numberFormatter.dataLabels(setValue.y + vPositiveErrorValue, parentYAxis);
|
|
vCPErrorToolText = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext, vCPErrorToolTipValue)));
|
|
|
|
vCNErrorToolTipValue =
|
|
numberFormatter.dataLabels(setValue.y - vNegativeErrorValue, parentYAxis);
|
|
vCNErrorToolText = getValidValue(parseUnsafeString(pluck(setData.errorplottooltext,
|
|
JSONData.errorplottooltext, chartAttr.errorplottooltext, vCNErrorToolTipValue)));
|
|
}
|
|
|
|
categories && categories[i] && (config.label =
|
|
getValidValue(parseUnsafeString(pluck (categories[i].tooltext, categories[i].label))));
|
|
|
|
if (setData.horizontalpositiveerrorvalue || setData.positiveerrorvalue ||
|
|
setData.horizontalnegativeerrorvalue || setData.negativeerrorvalue) {
|
|
config.halfHorizontalErrorBar = halfHorizontalErrorBar = 0;
|
|
} else {
|
|
config.halfHorizontalErrorBar = halfHorizontalErrorBar = conf.halfHorizontalErrorBar;
|
|
}
|
|
|
|
if (setData.verticalpositiveerrorvalue || setData.positiveerrorvalue ||
|
|
setData.verticalnegativeerrorvalue || setData.negativeerrorvalue) {
|
|
config.halfVerticalErrorBar = halfVerticalErrorBar = 0;
|
|
} else {
|
|
config.halfVerticalErrorBar = halfVerticalErrorBar = conf.halfVerticalErrorBar;
|
|
}
|
|
|
|
if (setValue.x !== null) {
|
|
maxErrorValue = setValue.x + Number(hPositiveErrorValue);
|
|
minErrorValue = setValue.x - (halfHorizontalErrorBar ? 0 : Number(hNegativeErrorValue));
|
|
|
|
xMax = mathMax(xMax, maxErrorValue, minErrorValue);
|
|
xMin = mathMin(xMin, maxErrorValue, minErrorValue);
|
|
}
|
|
|
|
if (setValue.y !== null) {
|
|
maxErrorValue = setValue.y + Number(vPositiveErrorValue);
|
|
minErrorValue = setValue.y - (halfVerticalErrorBar ? 0 : Number(vNegativeErrorValue));
|
|
|
|
yMax = mathMax(yMax, maxErrorValue, minErrorValue);
|
|
yMin = mathMin(yMin, maxErrorValue, minErrorValue);
|
|
}
|
|
|
|
|
|
|
|
useHorizontalErrorBar = config.useHorizontalErrorBar = pluckNumber(setData.usehorizontalerrorbar,
|
|
JSONData.usehorizontalerrorbar, chartAttr.usehorizontalerrorbar, 0);
|
|
|
|
useVerticalErrorBar = config.useVerticalErrorBar = pluckNumber(setData.useverticalerrorbar,
|
|
JSONData.useverticalerrorbar, chartAttr.useverticalerrorbar, 1);
|
|
|
|
config.errorValueArr = [];
|
|
|
|
config.errorValueArr.push({
|
|
errorValue: -(hPositiveErrorValue === null ? undefined : hPositiveErrorValue),
|
|
tooltext: getTooltext(hPositiveSetTooltext, hPositiveErrorToolTipValue),
|
|
errorBarColor: horizontalErrorBarColor,
|
|
isHorizontal: 1,
|
|
errorBarThickness: horizontalErrorBarThickness,
|
|
shadowOpacity : errorBarShadow ? (horizontalErrorBarAlpha / 250) : 0
|
|
});
|
|
|
|
config.errorValueArr.push({
|
|
errorValue: -(hPositiveErrorValue === null ? undefined : hPositiveErrorValue),
|
|
tooltext: cumulativeValueOnErrorBar ? getTooltext(hCPErrorToolText, hCPErrorToolTipValue) :
|
|
getTooltext(hPositiveSetTooltext, hPositiveErrorToolTipValue),
|
|
errorBarColor: horizontalErrorBarColor,
|
|
isHorizontal: 1,
|
|
errorBarThickness: horizontalErrorBarThickness,
|
|
shadowOpacity : errorBarShadow ? (horizontalErrorBarAlpha / 250) : 0,
|
|
errorEdgeBar : true
|
|
});
|
|
|
|
config.errorValueArr.push({
|
|
errorValue: hNegativeErrorValue,
|
|
tooltext: getTooltext(hNegativeSetTooltext, hNegativeErrorToolTipValue),
|
|
errorBarColor: horizontalErrorBarColor,
|
|
isHorizontal: 1,
|
|
errorBarThickness: horizontalErrorBarThickness,
|
|
shadowOpacity : errorBarShadow ? (horizontalErrorBarAlpha / 250) : 0
|
|
});
|
|
|
|
config.errorValueArr.push({
|
|
errorValue: hNegativeErrorValue,
|
|
tooltext: cumulativeValueOnErrorBar ? getTooltext(hCNErrorToolText, hCNErrorToolTipValue) :
|
|
getTooltext(hNegativeSetTooltext, hNegativeErrorToolTipValue),
|
|
errorBarColor: horizontalErrorBarColor,
|
|
isHorizontal: 1,
|
|
errorBarThickness: horizontalErrorBarThickness,
|
|
shadowOpacity : errorBarShadow ? (horizontalErrorBarAlpha / 250) : 0,
|
|
errorEdgeBar : true
|
|
});
|
|
|
|
config.errorValueArr.push({
|
|
errorValue: -(vPositiveErrorValue === null ? undefined : vPositiveErrorValue),
|
|
tooltext: getTooltext(vPositiveSetTooltext, vPositiveErrorToolTipValue),
|
|
errorBarColor: verticalErrorBarColor,
|
|
errorBarThickness: verticalErrorBarThickness,
|
|
shadowOpacity : errorBarShadow ? (verticalErrorBarAlpha / 250) : 0
|
|
});
|
|
|
|
config.errorValueArr.push({
|
|
errorValue: -(vPositiveErrorValue === null ? undefined : vPositiveErrorValue),
|
|
tooltext: cumulativeValueOnErrorBar ? getTooltext(vCPErrorToolText, vCPErrorToolTipValue) :
|
|
getTooltext(vPositiveSetTooltext, vPositiveErrorToolTipValue),
|
|
errorBarColor: verticalErrorBarColor,
|
|
errorBarThickness: verticalErrorBarThickness,
|
|
shadowOpacity : errorBarShadow ? (verticalErrorBarAlpha / 250) : 0,
|
|
errorEdgeBar : true
|
|
});
|
|
|
|
config.errorValueArr.push({
|
|
errorValue: vNegativeErrorValue,
|
|
tooltext: getTooltext(vNegativeSetTooltext, vNegativeErrorToolTipValue),
|
|
errorBarColor: verticalErrorBarColor,
|
|
errorBarThickness: verticalErrorBarThickness,
|
|
shadowOpacity : errorBarShadow ? (verticalErrorBarAlpha / 250) : 0
|
|
});
|
|
|
|
config.errorValueArr.push({
|
|
errorValue: vNegativeErrorValue,
|
|
tooltext: cumulativeValueOnErrorBar ? getTooltext(vCNErrorToolText, vCNErrorToolTipValue) :
|
|
getTooltext(vNegativeSetTooltext, vNegativeErrorToolTipValue),
|
|
errorBarColor: verticalErrorBarColor,
|
|
errorBarThickness: verticalErrorBarThickness,
|
|
shadowOpacity : errorBarShadow ? (verticalErrorBarAlpha / 250) : 0,
|
|
errorEdgeBar : true
|
|
});
|
|
|
|
setValue = config.setValue;
|
|
|
|
errorPercentValue = (mathRound(((setErrorValue / setValue) * HUNDREDSTRING) * HUNDREDSTRING) /
|
|
HUNDREDSTRING) + PERCENTAGESTRING;
|
|
|
|
horizontalErrorPercent = (mathRound(((hErrorValue / setValue) * HUNDREDSTRING) * HUNDREDSTRING) /
|
|
HUNDREDSTRING) + PERCENTAGESTRING;
|
|
|
|
verticalErrorPercent = (mathRound(((vErrorValue / setValue) * HUNDREDSTRING) * HUNDREDSTRING) /
|
|
HUNDREDSTRING) + PERCENTAGESTRING;
|
|
|
|
formatedVal = config.formatedVal;
|
|
|
|
// Initial tooltext parsing
|
|
if (!conf.showTooltip) {
|
|
toolText = false;
|
|
}
|
|
else if (config.setTooltext !== undefined) {
|
|
macroIndices = [1,2,3,4,5,6,7,8,9,10,11,99,100,101,102,103,104,105,106,107,109];
|
|
parserConfig = {
|
|
yaxisName: yAxisName,
|
|
xaxisName: xAxisName,
|
|
yDataValue: formatedVal,
|
|
xDataValue: config.label,
|
|
formattedValue : config.toolTipValue,
|
|
horizontalErrorValue: hErrorValue,
|
|
horizontalErrorDataValue: hErrorToolTipValue,
|
|
verticalErrorValue: vErrorValue,
|
|
verticalErrorDataValue: vErrorToolTipValue,
|
|
horizontalErrorPercent: horizontalErrorPercent,
|
|
verticalErrorPercent: verticalErrorPercent,
|
|
label : config.label
|
|
};
|
|
toolText = parseTooltext(config.setTooltext, macroIndices, parserConfig, setData, chartAttr,
|
|
JSONData);
|
|
}
|
|
//determine the default tooltext then.
|
|
else {
|
|
if (formatedVal === null) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
if (conf.seriesNameInTooltip) {
|
|
seriesname = lib.getFirstValue(JSONData && JSONData.seriesname);
|
|
}
|
|
toolText = seriesname ? seriesname + tooltipSepChar : BLANK;
|
|
toolText += setValue.x ? numberFormatter.xAxis(setValue.x) + tooltipSepChar : BLANK;
|
|
toolText += config.toolTipValue;
|
|
}
|
|
}
|
|
config.toolText = toolText;
|
|
}
|
|
|
|
conf.xMax = xMax;
|
|
conf.xMin = xMin;
|
|
conf.yMin = yMin;
|
|
conf.yMax = yMax;
|
|
},
|
|
|
|
drawErrorValue: function() {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
chartComponents = chart.components,
|
|
parentContainer = dataSet.parentContainer,
|
|
JSONData = dataSet.JSONData,
|
|
conf = dataSet.config,
|
|
setDataArr = JSONData.data,
|
|
dataSetLen = setDataArr && setDataArr.length,
|
|
setData,
|
|
attr,
|
|
i,
|
|
visible = dataSet.visible,
|
|
paper = chartComponents.paper,
|
|
xAxis = chartComponents.xAxis[0],
|
|
yAxis = dataSet.yAxis,
|
|
dataStore = dataSet.components.data,
|
|
|
|
isHorizontal,
|
|
errorBarThickness,
|
|
errorBarWidth,
|
|
errorBarColor,
|
|
showTooltip = conf.showTooltip,
|
|
shadowOpacity = conf.shadowOpacity,
|
|
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animType = animationObj.animType,
|
|
animObj = animationObj.animObj,
|
|
dummyObj = animationObj.dummyObj,
|
|
animationDuration = animationObj.duration,
|
|
|
|
lineGroup = dataSet.graphics.container.lineGroup,
|
|
errorGroupContainer = dataSet.graphics.errorGroupContainer,
|
|
errorShadowContainer = dataSet.graphics.errorShadowContainer,
|
|
setLink,
|
|
tooltext,
|
|
xPos,
|
|
yPos,
|
|
useCrispErrorPath = 1,
|
|
dataObj,
|
|
setValue,
|
|
// groupId,
|
|
config,
|
|
// eventArgs,
|
|
crispY,
|
|
crispX,
|
|
errorPath,
|
|
errorValPos,
|
|
errorValuePosFactor,
|
|
errorValueArr,
|
|
errorValueObj,
|
|
errorValue,
|
|
errorStartPos,
|
|
errorLen,
|
|
halfErrorBarW,
|
|
errorLineElem,
|
|
errorTrackerElem,
|
|
errorValueElem,
|
|
plotXpos,
|
|
plotYpos,
|
|
errorBarSegmentLen,
|
|
errorBarSegmentStartPos,
|
|
l,
|
|
j,
|
|
k,
|
|
trackerTolerance,
|
|
searchDataArr = [],
|
|
errorTrackerConfig;
|
|
|
|
if (!errorGroupContainer) {
|
|
errorGroupContainer = dataSet.graphics.errorGroupContainer =
|
|
paper.group(errorBarStr, parentContainer).insertAfter(lineGroup);
|
|
if (!visible) {
|
|
errorGroupContainer.hide();
|
|
}
|
|
}
|
|
|
|
if (!errorShadowContainer) {
|
|
// Always sending the shadow group to the back of the plots group.
|
|
errorShadowContainer = dataSet.graphics.errorShadowContainer =
|
|
paper.group(errorShadowStr, parentContainer).insertBefore(errorGroupContainer);
|
|
if (!visible) {
|
|
errorShadowContainer.hide();
|
|
}
|
|
}
|
|
|
|
// Loop through each data points
|
|
for (i = 0; i < dataSetLen; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
errorTrackerConfig = dataObj.errorTrackerConfig = {};
|
|
errorTrackerConfig.errorTrackerArr = [];
|
|
config = dataObj && dataObj.config;
|
|
setValue = config && config.setValue;
|
|
|
|
errorValueArr = config.errorValueArr;
|
|
|
|
// If plot value is found "null", continue the loop to next iteration.
|
|
if (dataObj === undefined || setValue === undefined || setValue === null || !errorValueArr) {
|
|
continue;
|
|
}
|
|
|
|
errorValueArr = config.errorValueArr;
|
|
errorTrackerConfig.errorLen = errorLen = errorValueArr.length;
|
|
|
|
!dataObj.graphics.error && (dataObj.graphics.error = []);
|
|
!dataObj.graphics.errorTracker && (dataObj.graphics.errorTracker = []);
|
|
|
|
if (config.vErrorValue === null &&
|
|
config.vPositiveErrorValue === null && config.vNegativeErrorValue === null) {
|
|
for (k = 0; k < 4; k++) {
|
|
if (dataObj.graphics.error && dataObj.graphics.error[k]) {
|
|
dataObj.graphics.error[k].hide();
|
|
dataObj.graphics.error[k].shadow({opacity: 0});
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (config.hErrorValue === null &&
|
|
config.hPositiveErrorValue === null && config.vPositiveErrorValue === null) {
|
|
for (k = 4; k < 8; k++) {
|
|
if (dataObj.graphics.error && dataObj.graphics.error[k]) {
|
|
dataObj.graphics.error[k].hide();
|
|
dataObj.graphics.error[k].shadow({opacity: 0});
|
|
}
|
|
}
|
|
}
|
|
|
|
if (config.hErrorValue === null && config.vErrorValue === null && config.hPositiveErrorValue &&
|
|
config.hNegativeErrorValue && config.vPositiveErrorValue && config.vNegativeErrorValue) {
|
|
continue;
|
|
}
|
|
|
|
setLink = config.setLink;
|
|
|
|
plotXpos = dataObj._xPos;
|
|
plotYpos = dataObj._yPos;
|
|
|
|
yPos = plotYpos;
|
|
xPos = plotXpos;
|
|
|
|
//Loop through errorValue array
|
|
for (j = 0; j < errorLen; j++) {
|
|
|
|
if (((!config.useHorizontalErrorBar) && (j === 0 || j === 1 || j === 2 || j === 3)) ||
|
|
((!config.useVerticalErrorBar) && (j === 4 || j === 5 || j === 6 || j === 7) ) ||
|
|
((j === 2 || j === 3) && config.halfHorizontalErrorBar) ||
|
|
((j === 6 || j === 7) && config.halfVerticalErrorBar)) {
|
|
|
|
dataObj.graphics.error && dataObj.graphics.error[j] && dataObj.graphics.error[j].hide() &&
|
|
dataObj.graphics.error[j].shadow({opacity: 0});
|
|
|
|
dataObj.graphics.errorTracker && dataObj.graphics.errorTracker[j] &&
|
|
dataObj.graphics.errorTracker[j].hide() &&
|
|
dataObj.graphics.errorTracker[j].shadow({opacity: 0});
|
|
continue;
|
|
}
|
|
|
|
errorTrackerConfig.errorTrackerArr[j] = {};
|
|
|
|
errorTrackerElem = errorLineElem = errorValueElem =
|
|
null;
|
|
errorValueObj = errorValueArr[j];
|
|
errorTrackerConfig.errorTrackerArr[j].tooltext = tooltext = errorValueObj.tooltext;
|
|
errorStartPos = yPos;
|
|
errorValue = errorValueObj.errorValue;
|
|
if (errorValue === null || errorValue === undefined || isNaN(errorValue)) {
|
|
if (dataObj.graphics.error && dataObj.graphics.error[j]) {
|
|
dataObj.graphics.error[j].hide();
|
|
dataObj.graphics.error[j].shadow({opacity: j});
|
|
}
|
|
|
|
if (dataObj.graphics.errorTracker && dataObj.graphics.errorTracker[j]) {
|
|
dataObj.graphics.errorTracker[j].hide();
|
|
dataObj.graphics.errorTracker[j].shadow({opacity: 0});
|
|
}
|
|
continue;
|
|
}
|
|
errorBarColor = errorValueObj.errorBarColor;
|
|
isHorizontal =
|
|
pluckNumber(errorValueObj.isHorizontal, 0);
|
|
errorBarThickness =
|
|
pluckNumber(errorValueObj.errorBarThickness,
|
|
conf.errorBarThickness, 1);
|
|
|
|
errorBarWidth = isHorizontal ? conf.horizontalErrorBarWidth
|
|
: conf.verticalErrorBarWidth;
|
|
|
|
halfErrorBarW = (!visible) ? 0 : (errorBarWidth / 2);
|
|
|
|
errorValuePosFactor = (!visible) ? 0 : 1;
|
|
|
|
trackerTolerance = errorBarThickness > 5 ? (errorBarThickness) / 2 + 0.5 : 5.5 / 2;
|
|
|
|
if (isHorizontal) {
|
|
errorValPos = plotXpos +
|
|
((xAxis.getAxisPosition(0) - xAxis.getAxisPosition(1)) *
|
|
errorValue * errorValuePosFactor);
|
|
crispY = errorValPos;
|
|
crispX = xPos;
|
|
|
|
if (useCrispErrorPath) {
|
|
crispY = mathRound(errorStartPos) +
|
|
(errorBarThickness % 2 / 2);
|
|
crispX = mathRound(errorValPos) +
|
|
(errorBarThickness % 2 / 2);
|
|
}
|
|
|
|
if(errorValueObj.errorEdgeBar) {
|
|
errorPath = [
|
|
M, crispX, crispY - halfErrorBarW,
|
|
V, (crispY + halfErrorBarW)
|
|
];
|
|
|
|
errorBarSegmentLen = 2 * halfErrorBarW;
|
|
errorBarSegmentStartPos = crispY - halfErrorBarW;
|
|
for (l = trackerTolerance; l < errorBarSegmentLen; l += (2 * trackerTolerance)) {
|
|
searchDataArr.push({
|
|
x: crispX,
|
|
y: errorBarSegmentStartPos + l,
|
|
r: trackerTolerance,
|
|
index: i,
|
|
data: dataObj,
|
|
toolText: errorValueObj.tooltext,
|
|
barType: 'h'
|
|
});
|
|
}
|
|
} else {
|
|
errorPath = [
|
|
M, xPos, crispY,
|
|
H, crispX
|
|
];
|
|
|
|
errorBarSegmentLen = mathAbs(xPos - crispX);
|
|
errorBarSegmentStartPos = xPos > crispX ? crispX : xPos;
|
|
for (l = trackerTolerance; l < errorBarSegmentLen; l += (2 * trackerTolerance)) {
|
|
searchDataArr.push({
|
|
x: errorBarSegmentStartPos + l,
|
|
y: crispY,
|
|
r: trackerTolerance,
|
|
index: i,
|
|
data: dataObj,
|
|
toolText: errorValueObj.tooltext,
|
|
barType: 'h'
|
|
});
|
|
}
|
|
}
|
|
}
|
|
// Vertical Error drawing
|
|
else {
|
|
// Vertical Error drawing
|
|
errorValPos = plotYpos +
|
|
((yAxis.getAxisPosition(0) - yAxis.getAxisPosition(1)) *
|
|
errorValue * errorValuePosFactor);
|
|
crispY = errorValPos;
|
|
crispX = xPos;
|
|
if (useCrispErrorPath) {
|
|
crispY = mathRound(errorValPos) +
|
|
(errorBarThickness % 2 / 2);
|
|
crispX = mathRound(xPos) +
|
|
(errorBarThickness % 2 / 2);
|
|
}
|
|
|
|
if(errorValueObj.errorEdgeBar) {
|
|
errorPath = [
|
|
M, crispX - halfErrorBarW, crispY,
|
|
H, (crispX + halfErrorBarW)
|
|
];
|
|
|
|
errorBarSegmentLen = 2 * halfErrorBarW;
|
|
errorBarSegmentStartPos = crispX - halfErrorBarW;
|
|
for (l = trackerTolerance; l <= errorBarSegmentLen; l += (2 * trackerTolerance)) {
|
|
searchDataArr.push({
|
|
x: errorBarSegmentStartPos + l,
|
|
y: crispY,
|
|
r: trackerTolerance,
|
|
index: i,
|
|
data: dataObj,
|
|
toolText: errorValueObj.tooltext,
|
|
barType: 'v'
|
|
});
|
|
}
|
|
} else {
|
|
errorPath = [
|
|
M, crispX, errorStartPos,
|
|
V, crispY
|
|
];
|
|
|
|
errorBarSegmentLen = mathAbs(errorStartPos - crispY);
|
|
errorBarSegmentStartPos = errorStartPos > crispY ? crispY : errorStartPos;
|
|
for (l = trackerTolerance; l <= errorBarSegmentLen; l += (2 * trackerTolerance)) {
|
|
searchDataArr.push({
|
|
x: crispX,
|
|
y: errorBarSegmentStartPos + l,
|
|
r: trackerTolerance,
|
|
index: i,
|
|
data: dataObj,
|
|
toolText: errorValueObj.tooltext,
|
|
barType: 'v'
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!dataObj.graphics.error[j]) {
|
|
errorLineElem = dataObj.graphics.error[j] =
|
|
paper.path(errorPath, errorGroupContainer)
|
|
.attr({
|
|
stroke: errorBarColor,
|
|
// In case of tooltip disabled this element should act as the hot element.
|
|
ishot: !showTooltip,
|
|
'stroke-width': errorBarThickness,
|
|
'cursor': setLink ? POINTER : BLANKSTRING,
|
|
'stroke-linecap': ROUND
|
|
});
|
|
|
|
if (conf.initAnimation) {
|
|
errorLineElem
|
|
.attr({
|
|
opacity: 0
|
|
})
|
|
.animateWith(dummyObj, animObj, {
|
|
opacity: 1
|
|
}, animationDuration, animType);
|
|
}
|
|
}
|
|
else {
|
|
errorLineElem = dataObj.graphics.error[j];
|
|
|
|
attr = {
|
|
path: errorPath,
|
|
'stroke-width': visible ? errorBarThickness : 0
|
|
};
|
|
|
|
errorLineElem.animateWith(dummyObj, animObj, attr, animationDuration, animType);
|
|
|
|
errorLineElem.attr({
|
|
stroke: errorBarColor,
|
|
// In case of tooltip disabled this element should act as the hot element.
|
|
ishot: !showTooltip,
|
|
'cursor': setLink ? POINTER : BLANKSTRING,
|
|
'stroke-linecap': ROUND
|
|
});
|
|
|
|
}
|
|
errorLineElem.show();
|
|
errorLineElem
|
|
.shadow({opacity : shadowOpacity}, errorShadowContainer);
|
|
|
|
errorTrackerConfig.errorTrackerArr[j].attr = {
|
|
path: errorPath,
|
|
stroke: TRACKER_FILL,
|
|
'stroke-width': visible ? (errorBarThickness < HTP ? HTP : errorBarThickness) : 0,
|
|
'cursor': setLink ? POINTER : BLANKSTRING,
|
|
'ishot': !! setLink
|
|
};
|
|
}
|
|
}
|
|
searchDataArr.length && (this.dataTreeB = new lib.KdTree().buildKdTree(searchDataArr));
|
|
conf.initAnimation = false;
|
|
},
|
|
|
|
/*
|
|
* Using kdtree algo for searching
|
|
*/
|
|
_getHoveredPlot: function (x, y) {
|
|
var res,
|
|
res1,
|
|
tooltext,
|
|
errorBarToolText,
|
|
hoverEffects,
|
|
element;
|
|
|
|
res = this.dataTree.getNeighbour({
|
|
x: x,
|
|
y: y
|
|
}, true);
|
|
|
|
// searching neighbour from Kdtree with basic search flag on
|
|
if (res) {
|
|
tooltext = res.data.config.toolText;
|
|
res.data.config.finalTooltext = tooltext;
|
|
hoverEffects = res.data.config.hoverEffects;
|
|
element = res.data.graphics.element;
|
|
element.data('hoverEnabled', hoverEffects.enabled);
|
|
hoverEffects.enabled && element.attr(element.getData().setRolloverAttr);
|
|
return {
|
|
pointIndex: res.index,
|
|
hovered: true,
|
|
pointObj: res.data
|
|
};
|
|
} else {
|
|
res1 = this.dataTreeB && this.dataTreeB.getNeighbour({
|
|
x: x,
|
|
y: y
|
|
}, true);
|
|
if (res1) {
|
|
if (res1.barType === 'h') {
|
|
errorBarToolText = res1.toolText;
|
|
} else if (res1.barType === 'v') {
|
|
errorBarToolText = res1.toolText;
|
|
}
|
|
res1.data.config.finalTooltext = errorBarToolText;
|
|
element = res1.data.graphics.element;
|
|
element.data('hoverEnabled', false);
|
|
element.attr(element.getData().setRolloutAttr);
|
|
return {
|
|
pointIndex: res1.index,
|
|
hovered: true,
|
|
pointObj: res1.data
|
|
};
|
|
}
|
|
}
|
|
},
|
|
/*
|
|
* Makes a dataset visible when clicked on its respective legend
|
|
* Fired every time a deactivated legend is clicked
|
|
*/
|
|
show : function() {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
yAxis = dataSet.yAxis,
|
|
errorGroupContainer = dataSet.graphics && dataSet.graphics.errorGroupContainer,
|
|
errorShadowContainer = dataSet.graphics && dataSet.graphics.errorShadowContainer;
|
|
|
|
chart._chartAnimation();
|
|
dataSet.visible = true;
|
|
dataSet._conatinerHidden = false;
|
|
|
|
errorGroupContainer && errorGroupContainer.show();
|
|
errorShadowContainer && errorShadowContainer.show();
|
|
|
|
chart._setAxisLimits();
|
|
yAxis.draw();
|
|
// Calling the draw function for redrawing the dataset
|
|
dataSet.draw();
|
|
},
|
|
|
|
// Function to remove a data from a dataset during real time update.
|
|
remove : function () {
|
|
var dataSet = this,
|
|
components = dataSet.components,
|
|
removeDataArr = components.removeDataArr,
|
|
pool = components.pool || (components.pool = {
|
|
element :[],
|
|
hotElement : [],
|
|
label : []
|
|
}),
|
|
len = removeDataArr.length,
|
|
removeData,
|
|
maxminFlag = dataSet.maxminFlag,
|
|
graphics,
|
|
i,
|
|
j;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
removeData = removeDataArr[0];
|
|
removeDataArr.splice(0,1);
|
|
// In case of non existing data plot continue;
|
|
if (!removeData || !removeData.graphics) {
|
|
continue;
|
|
}
|
|
|
|
graphics = removeData.graphics;
|
|
|
|
graphics.element && graphics.element.hide() && graphics.element.shadow({opacity: 0});
|
|
|
|
for (j = 0; j < 8; j++) {
|
|
graphics.error && graphics.error[j] && graphics.error[j].hide() &&
|
|
graphics.error[j].shadow({opacity: 0});
|
|
}
|
|
|
|
// Storing the graphic elements for reuse.
|
|
removeData.graphics.element && (pool.element = pool.element.concat(removeData.graphics.element));
|
|
removeData.graphics.label && (pool.label = pool.label.concat(removeData.graphics.label));
|
|
}
|
|
components.pool = pool;
|
|
maxminFlag && dataSet.setMaxMin();
|
|
}
|
|
|
|
},'Scatter']);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-multiaxisline',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
pluckNumber = lib.pluckNumber,
|
|
//strings
|
|
preDefStr = lib.preDefStr,
|
|
LINE = preDefStr.line,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
HUNDREDSTRING = lib.HUNDREDSTRING;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'multiaxisline', {
|
|
type : 'multiaxisline',
|
|
|
|
pIndex : 2,
|
|
|
|
customConfigFn : '_createDatasets',
|
|
|
|
configure: function () {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
datasetJSON = dataSet.JSONData,
|
|
dataSetConfig = dataSet.config,
|
|
conf = chart.config,
|
|
components = chart.components,
|
|
chartJSON = chart.jsonData,
|
|
axes = chartJSON.axis,
|
|
chartAttr = chartJSON.chart,
|
|
axis = axes[dataSet.axisIndex],
|
|
singleSeries = chart.singleseries,
|
|
Line = FusionCharts.get(COMPONENT, [DATASET, LINE]).prototype,
|
|
yAxis,
|
|
lineDashStyle,
|
|
lineDashed;
|
|
|
|
Line.configure.call(this);
|
|
yAxis = components.yAxis[dataSet.axisIndex];
|
|
dataSet.yAxis = yAxis;
|
|
conf.axesPadding = 5;
|
|
conf.allowAxisShift = pluckNumber(chartAttr.allowaxisshift, 1);
|
|
conf.allowSelection = pluckNumber(chartAttr.allowselection, 1);
|
|
conf.checkBoxColor = pluck(chartAttr.checkboxcolor, '#2196f3');
|
|
conf.axisConfigured = true;
|
|
|
|
dataSetConfig.linethickness = pluckNumber(datasetJSON.linethickness, axis.linethickness,
|
|
chartAttr.linethickness, singleSeries ? 4 : 2);
|
|
dataSetConfig.lineDashLen = pluckNumber(datasetJSON.linedashlen, axis.linedashlen,
|
|
chartAttr.linedashlen, 5);
|
|
dataSetConfig.lineDashGap = pluckNumber(datasetJSON.linedashgap, axis.linedashgap,
|
|
chartAttr.linedashgap, 4);
|
|
dataSetConfig.alpha = pluckNumber(datasetJSON.alpha, axis.linealpha,
|
|
chartAttr.linealpha, HUNDREDSTRING);
|
|
dataSetConfig.linecolor = pluck(datasetJSON.color, axis.linecolor, axis.color, chartAttr.linecolor,
|
|
dataSetConfig.plotColor);
|
|
|
|
|
|
dataSetConfig.legendSymbolColor = dataSet.type === LINE ? dataSetConfig.lineColor :
|
|
dataSetConfig.plotFillColor;
|
|
lineDashed = pluckNumber(datasetJSON.dashed, axis.linedashed, chartAttr.linedashed);
|
|
lineDashStyle = lib.getDashStyle(dataSetConfig.lineDashLen, dataSetConfig.lineDashGap,
|
|
dataSetConfig.linethickness);
|
|
dataSetConfig.anchorBorderColor = pluck(datasetJSON.anchorbordercolor,
|
|
chartAttr.anchorbordercolor, dataSetConfig.lineColor, dataSetConfig.plotColor);
|
|
dataSetConfig.lineDashStyle = lineDashed ?
|
|
lineDashStyle : 'none';
|
|
Line._setConfigure.call(this);
|
|
(chart.hasLegend !== false) && dataSet._addLegend();
|
|
},
|
|
init: function (datasetJSON) {
|
|
var dataSet = this,
|
|
chart = dataSet.chart;
|
|
|
|
dataSet.chart = chart;
|
|
dataSet.components = {
|
|
|
|
};
|
|
|
|
dataSet.conf ={
|
|
|
|
};
|
|
|
|
dataSet.graphics = {
|
|
|
|
};
|
|
dataSet.JSONData = datasetJSON;
|
|
dataSet.visible = pluckNumber(dataSet.JSONData.visible,
|
|
!Number(dataSet.JSONData.initiallyhidden), 1) === 1;
|
|
dataSet.configure();
|
|
},
|
|
// Fuction to be fired on legend click
|
|
legendInteractivity : function (dataSet, legendItem) {
|
|
var legend = this,
|
|
chart = dataSet.chart,
|
|
dataSets = chart.components.dataset,
|
|
axesArr = chart.config.axesArr,
|
|
legendConfig = legend.config,
|
|
visible = dataSet.visible,
|
|
config = legendItem.config,
|
|
legendGraphics = legendItem.graphics,
|
|
itemHiddenStyle = legendConfig.itemHiddenStyle,
|
|
hiddenColor = itemHiddenStyle.color,
|
|
itemStyle = legendConfig.itemStyle,
|
|
itemTextColor = itemStyle.color,
|
|
color = config.fillColor,
|
|
stroke = config.strokeColor,
|
|
checkboxes,
|
|
axisIndex = dataSet.axisIndex,
|
|
checkboxUncheck = true,
|
|
i;
|
|
|
|
checkboxes = axesArr.checkBox;
|
|
visible ? dataSet.hide() : dataSet.show();
|
|
if (visible) {
|
|
for (i in dataSets) {
|
|
if(dataSets.hasOwnProperty(i)) {
|
|
if (dataSets[i].visible && dataSets[i].axisIndex === axisIndex) {
|
|
checkboxUncheck = false;
|
|
}
|
|
}
|
|
}
|
|
if (checkboxUncheck) {
|
|
checkboxes[axisIndex] && checkboxes[axisIndex].checkbox.uncheck();
|
|
}
|
|
} else {
|
|
checkboxes[axisIndex] && checkboxes[axisIndex].checkbox.check();
|
|
}
|
|
if (!visible) {
|
|
legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
|
|
fill: color,
|
|
'stroke': stroke
|
|
});
|
|
legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
|
|
fill: itemTextColor
|
|
});
|
|
legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
|
|
'stroke': color
|
|
});
|
|
} else {
|
|
legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
|
|
fill: hiddenColor,
|
|
'stroke': hiddenColor
|
|
});
|
|
legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
|
|
fill: hiddenColor
|
|
});
|
|
legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
|
|
'stroke': hiddenColor
|
|
});
|
|
}
|
|
}
|
|
}, LINE]);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-multilevelpie',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
convertColor = lib.graphics.convertColor,
|
|
plotEventHandler = lib.plotEventHandler,
|
|
//strings
|
|
preDefStr = lib.preDefStr,
|
|
colorStrings = preDefStr.colors,
|
|
COLOR_FFFFFF = colorStrings.FFFFFF,
|
|
COLOR_000000 = colorStrings.c000000,
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
ZEROSTRING = lib.ZEROSTRING,
|
|
BLANK = lib.BLANKSTRING,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
parseTooltext = lib.parseTooltext,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
getValidValue = lib.getValidValue,
|
|
pluckNumber = lib.pluckNumber,
|
|
getFirstValue = lib.getFirstValue,
|
|
// getDefinedColor = lib.getDefinedColor,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
getDashStyle = lib.getDashStyle, // returns dashed style of a line series
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
UNDEFINED,
|
|
NONE = 'none',
|
|
// The default value for stroke-dash attribute.
|
|
DASH_DEF = NONE,
|
|
ROLLOVER = 'DataPlotRollOver',
|
|
ROLLOUT = 'DataPlotRollOut',
|
|
PXSTRING = 'px',
|
|
pInt = function (s, mag) {
|
|
return parseInt(s, mag || 10);
|
|
},
|
|
COMMASPACE = lib.COMMASPACE,
|
|
POINTER = 'pointer',
|
|
NORMALSTRING = 'normal',
|
|
EVENTARGS = 'eventArgs',
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
schedular = lib.schedular,
|
|
// CRISP = 'crisp',
|
|
PX = PXSTRING,
|
|
math = Math,
|
|
mathSin = math.sin,
|
|
mathCos = math.cos,
|
|
mathPI = math.PI,
|
|
mathRound = math.round,
|
|
mathMin = math.min,
|
|
mathMax = math.max;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'multiLevelPie', {
|
|
init: function (datasetJSON) {
|
|
var dataSet = this;
|
|
|
|
!dataSet.components && (dataSet.components = {
|
|
data: []
|
|
});
|
|
|
|
dataSet.conf ={
|
|
|
|
};
|
|
|
|
dataSet.graphics = {
|
|
|
|
};
|
|
dataSet.JSONData = datasetJSON;
|
|
dataSet.configure();
|
|
},
|
|
configure: function () {
|
|
var maxLevel,
|
|
useHoverColor,
|
|
hoverFillColor,
|
|
fontBdrColor,
|
|
pierad,
|
|
dataSet = this,
|
|
chart = dataSet.chart,
|
|
chartConfig = chart.config,
|
|
dataSetConfig = dataSet.conf || (dataSet.conf = {}),
|
|
dataLabels = dataSetConfig.dataLabelOptions || (dataSetConfig.dataLabelOptions = {}),
|
|
piePlotOptions = dataSetConfig.piePlotOptions,
|
|
style = chart.config.style,
|
|
jsonData = dataSet.JSONData,
|
|
chartAttrs = chart.jsonData.chart,
|
|
enableAnimation = dataSetConfig.enableAnimation = pluckNumber(chartAttrs.animation,
|
|
chartAttrs.defaultanimation, 1),
|
|
centerAngle = pluckNumber(-chartAttrs.centerangle, 180),
|
|
totalAngle = pluckNumber(chartAttrs.totalangle, 360);
|
|
dataSetConfig.animation = !enableAnimation ? false : {
|
|
duration: pluckNumber(chartAttrs.animationduration, chartAttrs.moveduration, 1) * 1000
|
|
};
|
|
dataSetConfig.showShadow = pluckNumber(chartAttrs.showshadow, 0);
|
|
useHoverColor = (dataSetConfig.useHoverColor = Boolean(pluckNumber(chartAttrs.usehovercolor, 1)));
|
|
hoverFillColor = (dataSetConfig.hoverFillColor = convertColor(pluck(chartAttrs.hoverfillcolor,
|
|
'FF5904'), pluckNumber(chartAttrs.hoverfillalpha, 100)));
|
|
pierad = (dataSetConfig.pierad = parseInt(chartAttrs.pieradius, 10));
|
|
|
|
fontBdrColor = getFirstValue(chartAttrs.valuebordercolor, BLANK);
|
|
fontBdrColor = fontBdrColor ? convertColor(
|
|
fontBdrColor, pluckNumber(chartAttrs.valueborderalpha, chartAttrs.valuebgalpha,
|
|
chartAttrs.valuealpha, 100)) : BLANK;
|
|
//create the style object if required.
|
|
//fix for multilevel pie datavalue cosmetics issue RED-1594
|
|
!dataLabels.style && (dataLabels.style = {
|
|
fontFamily: pluck(chartAttrs.valuefont, style.fontFamily),
|
|
fontSize: pluckNumber(chartAttrs.valuefontsize,
|
|
pInt(style.fontSize, 10)) + PX,
|
|
color: convertColor(pluck(chartAttrs.valuefontcolor, style.color),
|
|
pluckNumber(chartAttrs.valuefontalpha,
|
|
chartAttrs.valuealpha, 100)),
|
|
fontWeight: pluckNumber(chartAttrs.valuefontbold) ? 'bold' : NORMALSTRING,
|
|
fontStyle: pluckNumber(chartAttrs.valuefontitalic) ? 'italic' : NORMALSTRING,
|
|
backgroundColor: chartAttrs.valuebgcolor ?
|
|
convertColor(chartAttrs.valuebgcolor,
|
|
pluckNumber(chartAttrs.valuebgalpha, chartAttrs.valuealpha, 100)) : BLANK,
|
|
border: fontBdrColor || chartAttrs.valuebgcolor ?
|
|
(pluckNumber(chartAttrs.valueborderthickness, 1) + 'px solid') : BLANK,
|
|
borderPadding: pluckNumber(chartAttrs.valueborderpadding, 2),
|
|
borderThickness: pluckNumber(chartAttrs.valueborderthickness, style.borderThickness, 1),
|
|
borderRadius: pluckNumber(chartAttrs.valueborderradius, style.borderRadius, 0),
|
|
borderColor: fontBdrColor,
|
|
borderDash: pluckNumber(chartAttrs.valueborderdashed, 0) ?
|
|
getDashStyle(pluckNumber(chartAttrs.valueborderdashlen, 4),
|
|
pluckNumber(chartAttrs.valueborderdashgap, 2),
|
|
pluckNumber(chartAttrs.valueborderthickness, 1)) : DASH_DEF
|
|
});
|
|
|
|
//stop point slicing
|
|
!piePlotOptions && (piePlotOptions = (dataSetConfig.piePlotOptions = {}));
|
|
piePlotOptions.allowPointSelect = false;
|
|
|
|
dataSetConfig.borderColor = convertColor(pluck(chartAttrs.plotbordercolor,
|
|
chartAttrs.piebordercolor, COLOR_FFFFFF), chartAttrs.showplotborder != ZEROSTRING ?
|
|
pluck(chartAttrs.plotborderalpha, chartAttrs.pieborderalpha, 100) : 0);
|
|
dataSetConfig.showTooltip = pluckNumber(chartAttrs.showtooltip, 1);
|
|
|
|
dataSetConfig.borderWidth = pluckNumber(chartAttrs.pieborderthickness,
|
|
chartAttrs.plotborderthickness, 1);
|
|
|
|
piePlotOptions.startingAngle = 0; //set the chart's startingAngle as 0 [alwase]
|
|
piePlotOptions.size = '100%';
|
|
|
|
dataSetConfig.showLabels = pluckNumber(chartAttrs.showlabels, 1);
|
|
dataSetConfig.showValues = pluckNumber(chartAttrs.showvalues, 0);
|
|
dataSetConfig.showValuesInTooltip = pluckNumber(chartAttrs.showvaluesintooltip,
|
|
chartAttrs.showvalues, 0);
|
|
dataSetConfig.showPercentValues = pluckNumber(chartAttrs.showpercentvalues,
|
|
chartAttrs.showpercentagevalues, 0);
|
|
dataSetConfig.showPercentInTooltip = pluckNumber(chartAttrs.showpercentintooltip, 0);
|
|
dataSetConfig.toolTipSepChar = pluck(chartAttrs.tooltipsepchar, chartAttrs.hovercapsepchar, COMMASPACE);
|
|
dataSetConfig.labelSepChar = pluck(chartAttrs.labelsepchar, dataSetConfig.toolTipSepChar);
|
|
dataSetConfig.tooltext = chartAttrs.plottooltext;
|
|
dataSetConfig.alpha = pluck(chartAttrs.plotfillalpha, chartAttrs.piefillalpha, 100);
|
|
dataSetConfig.startAngle = (centerAngle - (totalAngle / 2)) * (mathPI / 180);
|
|
dataSetConfig.endtAngle = (centerAngle + (totalAngle / 2)) * (mathPI / 180);
|
|
dataSetConfig.initialAngle = dataSetConfig.endtAngle;
|
|
dataSetConfig.originX = pluckNumber(chartAttrs.originx);
|
|
dataSetConfig.originY = pluckNumber(chartAttrs.originy);
|
|
|
|
if (useHoverColor) {
|
|
dataSetConfig.events = {
|
|
mouseOver: function() {
|
|
var point = this.data('plotItem'),
|
|
selfRef = point.selfRef,
|
|
conf = dataSet.conf;
|
|
while (selfRef.graphics.element) {
|
|
(selfRef.graphics.element).attr({
|
|
fill: conf.hoverFillColor
|
|
});
|
|
selfRef = selfRef.linkedItems.parent;
|
|
}
|
|
},
|
|
mouseOut: function() {
|
|
var point = this.data('plotItem'),
|
|
selfRef = point.selfRef;
|
|
while (selfRef.graphics.element) {
|
|
(selfRef.graphics.element).attr({
|
|
fill: (selfRef.config || point).color
|
|
});
|
|
selfRef = selfRef.linkedItems.parent;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
//remove the plotboder
|
|
chartConfig.plotBorderWidth = 0;
|
|
|
|
//remove the plotboder
|
|
chartConfig.plotBorderWidth = 0;
|
|
maxLevel = dataSetConfig.maxLevel = dataSet.addMSPieCat(jsonData, 1, dataSet, dataSetConfig.startAngle,
|
|
dataSetConfig.endtAngle);
|
|
/*dataSet._addMSPieCat(jsonData, 0, 0, 100, pluck(chartAttrs.plotfillalpha,
|
|
chartAttrs.piefillalpha, 100), dataSetConfig, null);*/
|
|
/*pierad = parseInt(chartAttrs.pieradius, 10);
|
|
inner = 0;
|
|
isPercent = true;
|
|
if (pierad) {
|
|
serieswidth = (2 * pierad) / maxLevel;
|
|
isPercent = false;
|
|
} else {
|
|
serieswidth = smallerDimension * parseInt(100 / maxLevel, 10);
|
|
}*/
|
|
dataSetConfig.pieRadius = parseInt(chartAttrs.pieradius, 10);
|
|
dataLabels.distance = 0;
|
|
dataLabels.placeLabelsInside = true;
|
|
//chart.options.plotOptions.series.dataLabels.placeLabelsInside
|
|
//iterate through all data series
|
|
/*for (y = 0; y < series.length; y += 1) {
|
|
|
|
//set the size and iner radious
|
|
series[y].config.innerSize = inner + (isPercent ? '%' : BLANKSTRING);
|
|
series[y].config.size = (inner += serieswidth) + (isPercent ? '%' : BLANKSTRING);
|
|
if (series[y].components.data[series[y].components.data.length - 1].config.y === 0) {
|
|
series[y].components.data.pop();
|
|
}
|
|
}*/
|
|
|
|
},
|
|
// doHide is a Boolean Flag to hide the element or not.
|
|
// All the graphical elements in excess are pushed to the graphics pool. They are hidden only after the
|
|
// entire draw is complete.
|
|
removalFn: function(ele, doHide, prop) {
|
|
var dataSet = this,
|
|
centerAngle,
|
|
ringpath,
|
|
pool = dataSet.pool || (dataSet.pool = {}),
|
|
chart = dataSet.chart,
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animationDuration = animationObj.duration,
|
|
mainElm = animationObj.dummyObj,
|
|
animObj = animationObj.animObj,
|
|
animType = animationObj.animType,
|
|
hideFN = function (ele) {
|
|
(ele || this).hide();
|
|
};
|
|
|
|
!pool[prop] && (pool[prop] = []);
|
|
|
|
if (prop === 'element') {
|
|
ringpath = ele.attr('ringpath');
|
|
centerAngle = (ringpath[4] + ringpath[5]) / 2;
|
|
doHide ? ele.animateWith(mainElm, animObj, {
|
|
ringpath: [ringpath[0], ringpath[1], ringpath[2], ringpath[3], centerAngle, centerAngle]
|
|
}, animationDuration, animType, hideFN) : pool[prop].push(ele);
|
|
}
|
|
else {
|
|
doHide ? hideFN(ele) : pool[prop].push(ele);
|
|
}
|
|
},
|
|
removeGraphics: function (obj, doHide) {
|
|
var i,
|
|
prop,
|
|
dataSet = this,
|
|
childData = obj.components && obj.components.data,
|
|
len,
|
|
graphics = obj.graphics;
|
|
if (childData) {
|
|
len = childData.length;
|
|
for (i = 0; i < len; i += 1) {
|
|
dataSet.removeGraphics(childData[i]);
|
|
}
|
|
}
|
|
|
|
if (obj.graphics) {
|
|
for (prop in graphics) {
|
|
if (graphics.hasOwnProperty(prop)) {
|
|
dataSet.removalFn(obj.graphics[prop], doHide, prop);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
removeChild: function (removalStore, doHide, type) {
|
|
var i,
|
|
elemObj,
|
|
dataSet = this;
|
|
if (removalStore.length) {
|
|
for (i = 0; i < removalStore.length; i += 1) {
|
|
elemObj = removalStore[i];
|
|
if (type) {
|
|
dataSet.removalFn(elemObj, doHide, type);
|
|
}
|
|
else {
|
|
dataSet.removeGraphics(elemObj, doHide);
|
|
}
|
|
}
|
|
}
|
|
// if the removalStore is in the Object structure.
|
|
else {
|
|
for (i in removalStore) {
|
|
dataSet.removeChild(removalStore[i], doHide, i);
|
|
}
|
|
}
|
|
},
|
|
addMSPieCat: function(cat, level, parentObj, startAngle, endAngle) {
|
|
var dataObj,
|
|
dataObjLen,
|
|
catObjLen,
|
|
catLen = cat.length,
|
|
dataSet = this,
|
|
data = parentObj.components.data,
|
|
chart = dataSet.chart,
|
|
chartComponents = chart.components,
|
|
dataSetConfig = dataSet.conf,
|
|
plotBorderThickness = dataSetConfig.borderWidth,
|
|
plotBorderColor = dataSetConfig.borderColor,
|
|
numberFormatter = chartComponents.numberFormatter,
|
|
colorM = chartComponents.colorManager,
|
|
sharePercent,
|
|
totalValue = 0,
|
|
catObj,
|
|
catVal,
|
|
i,
|
|
label,
|
|
labelSepChar = dataSetConfig.labelSepChar,
|
|
fillalpha,
|
|
valueStr,
|
|
pValueStr,
|
|
toolText,
|
|
displayValue,
|
|
maxLevel = level,
|
|
dataLength = data.length,
|
|
removalFn = function () {
|
|
dataSet.removeChild.apply(dataSet, arguments);
|
|
},
|
|
catLength = cat.length,
|
|
totAngle = endAngle - startAngle,
|
|
tempAngle,
|
|
cumilative = 0,
|
|
preDataOldEndAngle;
|
|
|
|
for (i = 0; i < catLen; i += 1) {
|
|
//store for letter use
|
|
catObj = cat[i];
|
|
catObj._userValue = numberFormatter.getCleanValue(catObj.value, true);
|
|
catObj._value = pluckNumber(catObj._userValue, 1);
|
|
totalValue += catObj._value;
|
|
}
|
|
// Total value can't be zero, since its used in denominator to find ratio.
|
|
totalValue = totalValue || 1;
|
|
|
|
//add the category
|
|
sharePercent = totAngle / totalValue;
|
|
for (i = catLen - 1; i >= 0; i -= 1) {
|
|
catObj = cat[i];
|
|
catVal = sharePercent * catObj._value;
|
|
label = parseUnsafeString(pluck(catObj.label, catObj.name));
|
|
valueStr = catObj._userValue !== null ?
|
|
numberFormatter.dataLabels(catObj._userValue) : BLANK;
|
|
pValueStr = numberFormatter.percentValue((catObj._value /
|
|
totalValue) * 100);
|
|
// pointIndex = sLevel.length - 1;
|
|
fillalpha = pluckNumber(catObj.alpha, dataSetConfig.alpha);
|
|
displayValue = dataSetConfig.showLabels ? label : BLANK;
|
|
if (dataSetConfig.showValues) {
|
|
if (dataSetConfig.showPercentValues) {
|
|
displayValue += displayValue !== BLANK ? (labelSepChar + pValueStr) : pValueStr;
|
|
} else if (valueStr !== UNDEFINED && valueStr !== BLANK) {
|
|
displayValue += displayValue !== BLANK ? (labelSepChar + valueStr) : valueStr;
|
|
}
|
|
}
|
|
toolText = dataSetConfig.showTooltip ? parseUnsafeString(pluck(catObj.tooltext, catObj.hovertext,
|
|
dataSetConfig.tooltext)) : UNDEFINED;
|
|
if (toolText === BLANK) {
|
|
toolText = label;
|
|
if (dataSetConfig.showValuesInTooltip) {
|
|
if (dataSetConfig.showPercentInTooltip) {
|
|
toolText += toolText !== BLANK ? (labelSepChar + pValueStr) : pValueStr;
|
|
} else if (valueStr !== undefined && valueStr !== BLANK) {
|
|
toolText += toolText !== BLANK ? (labelSepChar + valueStr) : valueStr;
|
|
}
|
|
}
|
|
} else {
|
|
toolText = parseTooltext(toolText, [1, 2, 3, 14], {
|
|
percentValue: pValueStr,
|
|
label: label,
|
|
formattedValue: valueStr
|
|
}, catObj);
|
|
}
|
|
|
|
dataObj = data[i];
|
|
tempAngle = startAngle + cumilative;
|
|
cumilative += catVal;
|
|
if (!dataObj) {
|
|
dataObj = data[i] = {
|
|
components: {
|
|
data: []
|
|
},
|
|
linkedItems: {},
|
|
config: {},
|
|
graphics: {}
|
|
};
|
|
}
|
|
// store old end angle for newly added element's aimation position
|
|
if (dataObj.graphics.element) {
|
|
preDataOldEndAngle = dataObj.config.startAngle + dataObj.config.angleStrech;
|
|
}
|
|
dataObj.config = {
|
|
initialAngle: preDataOldEndAngle || (parentObj.conf || parentObj.config).initialAngle,
|
|
startAngle: tempAngle,
|
|
angleStrech: catVal,
|
|
level: level,
|
|
displayValue: displayValue,
|
|
toolText: toolText,
|
|
link: getValidValue(catObj.link),
|
|
doNotSlice: true, //added to stop slicing
|
|
color: convertColor(catObj.color || colorM.getPlotColor(), fillalpha),
|
|
borderWidth: pluckNumber(catObj.borderwidth, plotBorderThickness),
|
|
borderColor: pluck(catObj.bordercolor, plotBorderColor),
|
|
dashStyle: pluckNumber(catObj.valueborderdashed, 0) ?
|
|
getDashStyle(pluckNumber(catObj.borderdashlen, 4),
|
|
pluckNumber(catObj.borderdashgap, 2),
|
|
pluckNumber(catObj.borderthickness, 1)) : DASH_DEF,
|
|
shadow: {
|
|
opacity: mathRound(fillalpha > 50 ? fillalpha * fillalpha * fillalpha * 0.0001 :
|
|
fillalpha * fillalpha * 0.01) * 0.01
|
|
},
|
|
isSingleTon: (catLen > 1) ? false : true
|
|
};
|
|
dataObj.linkedItems.parent = parentObj;
|
|
|
|
if (catObj.category) {
|
|
maxLevel = mathMax(maxLevel, dataSet.addMSPieCat(catObj.category, level + 1,
|
|
dataObj, tempAngle, (catVal + tempAngle)));
|
|
if ((dataObjLen = dataObj.components.data.length) > (catObjLen = catObj.category.length)) {
|
|
removalFn(dataObj.components.data.splice(dataObjLen - 1, catObjLen));
|
|
}
|
|
}
|
|
else if (dataObjLen = dataObj.components.data.length){
|
|
// no child category, recursively remove existing childs (dataObj.components.data)
|
|
removalFn(dataObj.components.data.splice(0, dataObjLen));
|
|
}
|
|
}
|
|
// remove estra data
|
|
if (dataLength > catLength) {
|
|
// recursively remove elements with child
|
|
removalFn(data.splice(catLength, dataLength - 1));
|
|
}
|
|
return maxLevel;
|
|
},
|
|
draw: function (parentObj) {
|
|
var angle,
|
|
_textAttr,
|
|
_textAttrs,
|
|
centerDistance,
|
|
level,
|
|
dataSet = this,
|
|
dataSetConfig = dataSet.conf || {},
|
|
chart = dataSet.chart,
|
|
jobList = chart.getJobList(),
|
|
chartComponents = chart.components,
|
|
chartConfig = chart.config,
|
|
chartGraphics = chart.graphics,
|
|
dataSetComponents = dataSet.components,
|
|
data = dataSetComponents.data,
|
|
len = data.length,
|
|
seriesDataLabelsStyle = chartConfig.dataLabelStyle,
|
|
seriesShadow = dataSetConfig.showShadow,
|
|
paper = chartComponents.paper,
|
|
textDirection = chartConfig.textDirection,
|
|
tooltipOptions = chartConfig.tooltip || {},
|
|
isTooltip = tooltipOptions && tooltipOptions.enabled !== false,
|
|
toolText,
|
|
canvasWidth = chartConfig.canvasWidth,
|
|
canvasHeight = chartConfig.canvasHeight,
|
|
cx = pluckNumber(dataSetConfig.originX, chartConfig.canvasLeft + canvasWidth * 0.5),
|
|
cy = pluckNumber(dataSetConfig.originY, chartConfig.canvasTop + canvasHeight * 0.5),
|
|
r,
|
|
r2,
|
|
plotItem,
|
|
color,
|
|
val,
|
|
displayValue,
|
|
setLink,
|
|
angle1,
|
|
angle2,
|
|
i,
|
|
datasetLayer = (chartGraphics.datasetGroup.trackTooltip(true)),
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animationDuration = animationObj.duration || 0,
|
|
primaryItemAnimating = animationObj.dummyObj,
|
|
animObj = animationObj.animObj,
|
|
animType = animationObj.animType,
|
|
eventArgs,
|
|
setGraphics,
|
|
setConfig,
|
|
element,
|
|
label,
|
|
initialAngle,
|
|
dataLabelsLayer = chartGraphics.datalabels || (chartGraphics.datalabels = paper.group('datalabels')
|
|
.insertAfter(datasetLayer)),
|
|
events = dataSetConfig.events || {},
|
|
plotHoverFN = function(e) {
|
|
var o = this,
|
|
mouseOver = events.mouseOver;
|
|
plotEventHandler.call(o, chart, e, ROLLOVER);
|
|
mouseOver && mouseOver.call(o);
|
|
},
|
|
plotMouseOut = function(e) {
|
|
var o = this,
|
|
mouseOut = events.mouseOut;
|
|
plotEventHandler.call(o, chart, e, ROLLOUT);
|
|
mouseOut && mouseOut.call(o);
|
|
},
|
|
//Fired when clicked over the hot elements.
|
|
clickFunc = function (setDataArr) {
|
|
var ele = this;
|
|
plotEventHandler.call(ele, chart, setDataArr);
|
|
},
|
|
animStartFN = function () {
|
|
if (!dataSetConfig._drawn) {
|
|
dataSetConfig._drawn = true;
|
|
dataLabelsLayer.show();
|
|
jobList.labelDrawID.push(schedular.addJob(dataSet.drawLabel,
|
|
dataSet, [], lib.priorityList.label));
|
|
chart._animCallBack();
|
|
}
|
|
},
|
|
pool = dataSet.pool || (dataSet.pool = {}),
|
|
removeDataArr = dataSetComponents.removeDataArr,
|
|
removeDataArrLen = removeDataArr && removeDataArr.length,
|
|
// either the user-specified size is chosen or the minimum aspect dimension is choosen
|
|
pieSize = pluckNumber(dataSetConfig.pieRadius * 2, mathMin(canvasWidth, canvasHeight)),
|
|
seriesHalfWidth = pieSize / (2 * dataSetConfig.maxLevel);
|
|
removeDataArrLen && dataSet.remove();
|
|
animationDuration && dataLabelsLayer.hide();
|
|
if (!parentObj) {
|
|
parentObj = dataSet;
|
|
dataLabelsLayer.css(seriesDataLabelsStyle);
|
|
}
|
|
len = parentObj.components.data.length;
|
|
for (i = 0; i < len; i += 1) {
|
|
dataSet.draw(parentObj.components.data[i]);
|
|
}
|
|
setConfig = parentObj.config;
|
|
level = setConfig.level;
|
|
if (level) {
|
|
r = (level * seriesHalfWidth);
|
|
r2 = ((level - 1) * seriesHalfWidth);
|
|
|
|
setGraphics = parentObj.graphics;
|
|
val = setConfig.angleStrech;
|
|
displayValue = setConfig.displayValue;
|
|
toolText = setConfig.toolText;
|
|
setLink = !! setConfig.link;
|
|
color = setConfig.color;
|
|
|
|
angle1 = setConfig.startAngle;
|
|
angle2 = angle1 + setConfig.angleStrech;
|
|
initialAngle = setConfig.initialAngle;
|
|
|
|
element = setGraphics.element;
|
|
if (!element) {
|
|
// Reuse the cache element
|
|
if(pool.element && pool.element.length) {
|
|
element = setGraphics.element = pool.element.shift();
|
|
element.show();
|
|
}
|
|
// If there is no element in cachestore then create it freshly
|
|
else {
|
|
element = setGraphics.element = paper.ringpath(datasetLayer)
|
|
.mouseover(plotHoverFN)
|
|
.mouseout(plotMouseOut)
|
|
.mouseup(clickFunc);
|
|
}
|
|
element.attr({
|
|
ringpath: [cx, cy, r, r2, initialAngle, initialAngle]
|
|
});
|
|
}
|
|
setConfig.plotItem = plotItem = {
|
|
chart: chart,
|
|
link: setConfig.link,
|
|
value: val,
|
|
color: color,
|
|
labelText: displayValue,
|
|
graphics: {
|
|
element: element
|
|
},
|
|
selfRef: parentObj
|
|
};
|
|
|
|
setConfig.eventArgs = eventArgs = {
|
|
link: setConfig.link,
|
|
label: setConfig.displayValue,
|
|
toolText: setConfig.toolText
|
|
};
|
|
element.attr({
|
|
'stroke-width': setConfig.borderWidth,
|
|
'stroke': setConfig.borderColor,
|
|
fill: toRaphaelColor(setConfig.color),
|
|
'stroke-dasharray': setConfig.dashStyle,
|
|
// In case of tooltip disabled this element should act as the hot element.
|
|
ishot: !isTooltip,
|
|
cursor: setLink ? POINTER : BLANKSTRING
|
|
})
|
|
.tooltip(setConfig.toolText)
|
|
.shadow(seriesShadow && !! setConfig.shadow)
|
|
.data('plotItem', plotItem)
|
|
.data(EVENTARGS, eventArgs);
|
|
label = setGraphics.label;
|
|
if ((displayValue !== undefined) && (displayValue !== BLANKSTRING)) {
|
|
angle = (angle1 + angle2) / 2;
|
|
if (!(_textAttr = setConfig._textAttr)) {
|
|
_textAttr = setConfig._textAttr = {};
|
|
}
|
|
// for the innermost Concentric circle the center distance is presumed to be zero
|
|
centerDistance = ((r2 === 0) && setConfig.isSingleTon) ? 0 : r2 + ((r - r2) / 2);
|
|
label = setGraphics.label;
|
|
|
|
if (!(_textAttrs = setConfig._textAttrs)) {
|
|
_textAttrs = setConfig._textAttrs = {};
|
|
}
|
|
|
|
_textAttrs.text = displayValue;
|
|
_textAttrs.fill = seriesDataLabelsStyle.color || COLOR_000000;
|
|
_textAttrs.direction = textDirection;
|
|
_textAttrs.ishot = setLink;
|
|
_textAttrs.cursor = setLink ? POINTER : BLANKSTRING;
|
|
_textAttrs.x = cx + (centerDistance * mathCos(angle));
|
|
_textAttrs.y = cy + (centerDistance * mathSin(angle));
|
|
_textAttrs['text-bound'] = [seriesDataLabelsStyle.backgroundColor,
|
|
seriesDataLabelsStyle.borderColor,
|
|
seriesDataLabelsStyle.borderThickness,
|
|
seriesDataLabelsStyle.borderPadding,
|
|
seriesDataLabelsStyle.borderRadius,
|
|
seriesDataLabelsStyle.borderDash];
|
|
|
|
}
|
|
element.animateWith(primaryItemAnimating, animObj, {
|
|
ringpath: [cx, cy, r, r2, angle1, angle2]
|
|
}, animationDuration, animType, !i && animStartFN);
|
|
}
|
|
else {
|
|
// If the chart is already drawn, then instead of sheduling the label drawing, directly draw the
|
|
// labels.
|
|
dataSetConfig._drawn && dataSet.drawLabel();
|
|
// at the end of all the tree structure, hide all the pool elements.
|
|
dataSet.removeChild(dataSet.pool, true);
|
|
}
|
|
},
|
|
/*
|
|
* Draws the label in a ML pie chart.
|
|
*/
|
|
drawLabel: function (parentObj) {
|
|
var _textAttrs,
|
|
level,
|
|
dataSet = this,
|
|
dataSetConfig = dataSet.conf || {},
|
|
chart = dataSet.chart,
|
|
chartComponents = chart.components,
|
|
chartConfig = chart.config,
|
|
chartGraphics = chart.graphics,
|
|
dataSetComponents = dataSet.components,
|
|
data = dataSetComponents.data,
|
|
len = data.length,
|
|
seriesDataLabelsStyle = chartConfig.dataLabelStyle,
|
|
paper = chartComponents.paper,
|
|
tooltipOptions = chartConfig.tooltip || {},
|
|
isTooltip = tooltipOptions && tooltipOptions.enabled !== false,
|
|
toolText,
|
|
plotItem,
|
|
displayValue,
|
|
i,
|
|
setGraphics,
|
|
setConfig,
|
|
label,
|
|
events = dataSetConfig.events || {},
|
|
labelHoverFN = function(e) {
|
|
var o = this,
|
|
mouseOver = events.mouseOver;
|
|
plotEventHandler.call(o, chart, e, ROLLOVER);
|
|
mouseOver && mouseOver.call(o);
|
|
},
|
|
labelOutFN = function(e) {
|
|
var o = this,
|
|
mouseOut = events.mouseOut;
|
|
plotEventHandler.call(o, chart, e, ROLLOUT);
|
|
mouseOut && mouseOut.call(o);
|
|
},
|
|
//Fired when clicked over the hot elements.
|
|
clickFunc = function (setDataArr) {
|
|
var ele = this;
|
|
plotEventHandler.call(ele, chart, setDataArr);
|
|
},
|
|
pool = dataSet.pool || (dataSet.pool = {}),
|
|
dataLabelsLayer = chartGraphics.datalabels;
|
|
!parentObj && (parentObj = dataSet);
|
|
len = parentObj.components.data.length;
|
|
for (i = 0; i < len; i += 1) {
|
|
dataSet.drawLabel(parentObj.components.data[i]);
|
|
}
|
|
setConfig = parentObj.config;
|
|
plotItem = setConfig.plotItem;
|
|
displayValue = setConfig.displayValue;
|
|
_textAttrs = setConfig._textAttrs;
|
|
level = setConfig.level;
|
|
if (level) {
|
|
setGraphics = parentObj.graphics;
|
|
label = setGraphics.label;
|
|
if ((displayValue !== undefined) && (displayValue !== BLANKSTRING)) {
|
|
label = setGraphics.label;
|
|
if (!label) {
|
|
// Reuse the cache element
|
|
if(pool.label && pool.label.length) {
|
|
label = setGraphics.label = pool.label.shift();
|
|
label
|
|
.attr(_textAttrs)
|
|
.css(seriesDataLabelsStyle);
|
|
}
|
|
// If there is no element in cachestore then create it freshly
|
|
else {
|
|
label = setGraphics.label = paper.text(_textAttrs, seriesDataLabelsStyle,
|
|
dataLabelsLayer)
|
|
.mouseover(labelHoverFN)
|
|
.mouseout(labelOutFN)
|
|
.mouseup(clickFunc);
|
|
}
|
|
}
|
|
else {
|
|
label
|
|
.attr(_textAttrs)
|
|
.css(seriesDataLabelsStyle);
|
|
}
|
|
plotItem.label = label
|
|
.show()
|
|
.data('plotItem', plotItem)
|
|
.data(EVENTARGS, setConfig.eventArgs);
|
|
isTooltip && label.tooltip(toolText);
|
|
}
|
|
else {
|
|
label && label.hide();
|
|
}
|
|
}
|
|
else {
|
|
// at the end of all the tree structure, hide all the pool elements.
|
|
dataSet.removeChild(dataSet.pool, true);
|
|
}
|
|
}
|
|
}, 'Pie2D']);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-dragnode',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
R = lib.Raphael,
|
|
isVML = (R.type === 'VML'),
|
|
|
|
//strings
|
|
preDefStr = lib.preDefStr,
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
visibleStr = preDefStr.visibleStr,
|
|
ZEROSTRING = lib.ZEROSTRING,
|
|
POSITION_TOP = preDefStr.POSITION_TOP,
|
|
POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
|
|
UNDERSCORE = preDefStr.UNDERSCORE,
|
|
BLANK = lib.BLANKSTRING,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
parseTooltext = lib.parseTooltext,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
getValidValue = lib.getValidValue,
|
|
pluckNumber = lib.pluckNumber,
|
|
getFirstValue = lib.getFirstValue,
|
|
// getDefinedColor = lib.getDefinedColor,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
extend2 = lib.extend2, //old: jarendererExtend / margecolone
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
UNDEFINED,
|
|
// The default value for stroke-dash attribute.
|
|
ROLLOVER = 'DataPlotRollOver',
|
|
ROLLOUT = 'DataPlotRollOut',
|
|
POLYGON = 'polygon',
|
|
CIRCLE = 'circle',
|
|
RECTANGLE = 'rectangle',
|
|
POINTER = 'pointer',
|
|
EVENTARGS = 'eventArgs',
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
GROUPID = 'groupId',
|
|
|
|
schedular = lib.schedular,
|
|
getTouchEvent = lib.getTouchEvent,
|
|
defined = function(obj) {
|
|
return obj !== UNDEFINED && obj !== null;
|
|
},
|
|
|
|
OBJECTBOUNDINGBOX = 'objectBoundingBox', // gradient unit
|
|
COMMA = ',',
|
|
POSITION_MIDDLE = 'middle',
|
|
BGRATIOSTRING = lib.BGRATIOSTRING,
|
|
math = Math,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
hasTouch = lib.hasTouch,
|
|
// getColumnColor = lib.graphics.getColumnColor,
|
|
getFirstColor = lib.getFirstColor,
|
|
// pluckColor = lib.pluckColor,
|
|
getFirstAlpha = lib.getFirstAlpha,
|
|
getDarkColor = lib.graphics.getDarkColor,
|
|
getLightColor = lib.graphics.getLightColor,
|
|
convertColor = lib.graphics.convertColor,
|
|
// renderer = chartAPI,
|
|
mapSymbolName = lib.graphics.mapSymbolName,
|
|
COMMASTRING = lib.COMMASTRING,
|
|
HUNDREDSTRING = lib.HUNDREDSTRING,
|
|
// COMMASPACE = lib.COMMASPACE,
|
|
getMouseCoordinate = lib.getMouseCoordinate,
|
|
plotEventHandler = lib.plotEventHandler,
|
|
|
|
//strings
|
|
BLANKSPACE = ' ',
|
|
|
|
//add the tools thats are requared
|
|
SHAPE_RECT = lib.SHAPE_RECT,
|
|
stubEvent = {
|
|
pageX: 0,
|
|
pageY: 0
|
|
},
|
|
CLEAR_TIME_1000 = 1000,
|
|
clearLongPress = function() {
|
|
var ele = this;
|
|
ele.data('move', false);
|
|
clearTimeout(ele._longpressactive);
|
|
delete ele._longpressactive;
|
|
};
|
|
|
|
// Drag node class
|
|
FusionCharts.register(COMPONENT, [DATASET, 'Dragnode', {
|
|
type: 'dragnode',
|
|
// Configure
|
|
configure: function () {
|
|
var dataSet = this,
|
|
dIndex = dataSet.index,
|
|
chartObj = dataSet.chart,
|
|
chartComp = chartObj.components,
|
|
JSONData = dataSet.JSONData,
|
|
data = JSONData.data || [],
|
|
chartAttr = chartObj.jsonData.chart,
|
|
dataLength = data.length,
|
|
conf = dataSet.config,
|
|
showValues,
|
|
ZERO = ZEROSTRING,
|
|
colorM = chartComp.colorManager,
|
|
index,
|
|
plotFillAlpha,
|
|
showPlotBorder,
|
|
plotBorderColor,
|
|
plotBorderThickness,
|
|
plotBorderAlpha,
|
|
datasetId,
|
|
datasetPlotBorderThickness,
|
|
dataStore,
|
|
dataStoreLen,
|
|
useRoundEdges,
|
|
HUNDRED = HUNDREDSTRING;
|
|
showValues = conf.showValues = pluckNumber(JSONData.showvalues, chartAttr.showvalues, 1);
|
|
useRoundEdges = conf.useRoundEdges = pluckNumber(chartAttr.useroundedges);
|
|
conf.zIndex = 1;
|
|
conf.name = getValidValue(JSONData.seriesname);
|
|
conf.viewMode = pluckNumber(chartAttr.viewmode, 0);
|
|
datasetId = conf.id = pluck(JSONData.id, dataSet.index);
|
|
if (pluckNumber(JSONData.includeinlegend) === 0 ||
|
|
conf.name === undefined) {
|
|
conf.showInLegend = false;
|
|
}
|
|
conf.includeInLegend = pluckNumber(JSONData.includeinlegend, 1);
|
|
|
|
conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
|
|
conf.seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1);
|
|
conf.tooltipSepChar = pluck(chartAttr.tooltipsepchar, ' - ');
|
|
//Plot Properties
|
|
plotFillAlpha = conf.plotFillAlpha = pluck(chartAttr.plotfillalpha, HUNDRED);
|
|
showPlotBorder = conf.showPlotBorder = pluckNumber(chartAttr.showplotborder, 1);
|
|
plotBorderColor = conf.plotBorderColor = getFirstColor(pluck(chartAttr.plotbordercolor, '666666'));
|
|
plotBorderThickness = conf.plotBorderThickness = pluckNumber(chartAttr.plotborderthickness,
|
|
useRoundEdges ? 2 : 1);
|
|
plotBorderAlpha = conf.plotBorderAlpha = pluck(chartAttr.plotborderalpha, chartAttr.plotfillalpha,
|
|
useRoundEdges ? '35' : '95');
|
|
|
|
//Node Properties
|
|
conf.use3DLighting = Boolean(pluckNumber(chartAttr.use3dlighting,
|
|
chartAttr.is3d, useRoundEdges ? 1 : 0));
|
|
//Store attributeshc
|
|
conf.color = getFirstColor(pluck(JSONData.color, colorM.getPlotColor(dIndex)));
|
|
conf.alpha = pluck(JSONData.plotfillalpha, JSONData.nodeFillAlpha,
|
|
JSONData.alpha, plotFillAlpha);
|
|
//Data set plot properties
|
|
conf.datasetShowPlotBorder = Boolean(pluckNumber(JSONData.showplotborder, showPlotBorder));
|
|
conf.datasetPlotBorderColor = getFirstColor(pluck(JSONData.plotbordercolor, JSONData.nodebordercolor,
|
|
plotBorderColor));
|
|
conf.datasetPlotBorderThickness = pluckNumber(JSONData.plotborderthickness,
|
|
JSONData.nodeborderthickness, plotBorderThickness);
|
|
conf.datasetPlotBorderAlpha = (conf.datasetShowPlotBorder) ? pluck(JSONData.plotborderalpha,
|
|
JSONData.nodeborderalpha, JSONData.alpha, plotBorderAlpha) : ZERO;
|
|
conf.seriesname = parseUnsafeString(JSONData.seriesname);
|
|
//Drag Border properties
|
|
conf.datasetAllowDrag = Boolean(pluckNumber(JSONData.allowdrag, 1));
|
|
|
|
conf.colorObj = {
|
|
fillColor: convertColor(conf.color, conf.alpha),
|
|
lineColor: {
|
|
FCcolor: {
|
|
color: conf.datasetPlotBorderColor,
|
|
alpha: conf.datasetPlotBorderAlpha
|
|
}
|
|
}
|
|
};
|
|
conf.lineWidth = datasetPlotBorderThickness;
|
|
conf.symbol = 'poly_4';
|
|
dataStore = dataSet.components.data = dataSet.components.data || (dataSet.components.data = []);
|
|
dataStoreLen = dataStore.length;
|
|
if (dataStoreLen > dataLength) {
|
|
dataStore.splice(dataLength, dataStoreLen - dataLength);
|
|
|
|
}
|
|
|
|
dataSet.visible = pluckNumber(JSONData.visible,
|
|
!Number(JSONData.initiallyhidden), 1) === 1;
|
|
conf.yMin = conf.yMax = conf.xMax = conf.xMin = 0;
|
|
// This flag is true when data update is fired
|
|
dataSet._refreshData = true;
|
|
// Iterate through all level data
|
|
for (index = 0; index < dataLength; index += 1) {
|
|
this._setConfigure(index);
|
|
}
|
|
dataSet._refreshData = false;
|
|
dataSet._addLegend();
|
|
},
|
|
_setConfigure: function (index, updateObj) {
|
|
var dataset = this,
|
|
JSONData = dataset.JSONData,
|
|
data = JSONData.data,
|
|
setData = updateObj ? updateObj : data[index],
|
|
dataStore = dataset.components.data,
|
|
conf = dataset.config,
|
|
dataObj = dataStore[index] = dataStore[index] || (dataStore[index] = {}),
|
|
config = dataObj.config = dataObj.config || (dataObj.config = {}),
|
|
datasetId = conf.id,
|
|
shape,
|
|
yMin = conf.yMin || +Infinity,
|
|
yMax = conf.yMax || -Infinity,
|
|
xMax = conf.xMax || -Infinity,
|
|
xMin = conf.xMin || +Infinity,
|
|
itemValueY,
|
|
itemValueX,
|
|
label,
|
|
safeLabel,
|
|
shapeType,
|
|
use3DLighting = conf.use3DLighting,
|
|
datasetPlotBorderThickness = conf.datasetPlotBorderThickness,
|
|
datasetPlotBorderColor = conf.datasetPlotBorderColor,
|
|
datasetPlotBorderAlpha = conf.datasetPlotBorderAlpha,
|
|
chart = dataset.chart,
|
|
chartAttr = chart.jsonData.chart,
|
|
datasetColor = conf.color,
|
|
datasetAlpha = conf.alpha,
|
|
fillColor,
|
|
datasetAllowDrag = conf.datasetAllowDrag,
|
|
numberFormatter = dataset.chart.components.numberFormatter;
|
|
!dataObj.graphics && (dataObj.graphics = {});
|
|
config._options = extend2({}, setData);
|
|
if (setData || updateObj) {
|
|
itemValueY = config.y = numberFormatter.getCleanValue(pluck(setData.y));
|
|
itemValueX = config.x = numberFormatter.getCleanValue(pluck(setData.x));
|
|
config.index = index;
|
|
if (!config.dragStart) {
|
|
config.dragStart = {};
|
|
}
|
|
yMax = mathMax(yMax, config.y);
|
|
yMin = mathMin(yMin, config.y);
|
|
xMax = mathMax(xMax, config.x);
|
|
xMin = mathMin(xMin, config.x);
|
|
if (itemValueY === null) {
|
|
config.value = null;
|
|
}
|
|
else {
|
|
label = numberFormatter.xAxis(itemValueX);
|
|
//push the point object
|
|
config.formatedVal = (itemValueY === null ?
|
|
itemValueY : numberFormatter.dataLabels(itemValueY)),
|
|
config.setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
|
|
JSONData.plottooltext, chartAttr.plottooltext)));
|
|
config.pointLabel = pluck(setData.label, setData.name);
|
|
safeLabel = parseUnsafeString(config.pointLabel);
|
|
config.label = safeLabel;
|
|
config.name = safeLabel;
|
|
config.displayValue = safeLabel;
|
|
config.xValue = label;
|
|
|
|
config.startConnectors = {};
|
|
config.endConnectors = {};
|
|
//create the tooltext
|
|
if (!conf.showTooltip) {
|
|
config.toolText = false;
|
|
}
|
|
else {
|
|
config.toolText = dataset._configureTooltext(config, conf, chartAttr);
|
|
}
|
|
config.link = setData.link;
|
|
// Shape and cosmetics related attributes
|
|
config.id = pluck(setData.id, (datasetId + UNDERSCORE + index));
|
|
config.allowDrag = Boolean(pluckNumber(setData.allowdrag, datasetAllowDrag));
|
|
shape = config.shape = getValidValue(pluck(setData.shape), RECTANGLE).toLowerCase(),
|
|
config.height = getValidValue(pluck(setData.height), 10),
|
|
config.width = getValidValue(pluck(setData.width), 10),
|
|
config.radius = getValidValue(pluck(setData.radius), 10),
|
|
config.numSides = getValidValue(pluck(setData.numsides), 4),
|
|
config.color = getFirstColor(pluck(setData.color, datasetColor));
|
|
config.borderColor = getFirstColor(pluck(setData.bordercolor, datasetPlotBorderColor));
|
|
config.alpha = pluck(setData.alpha, datasetAlpha),
|
|
config.imageURL = getValidValue(setData.imageurl),
|
|
config.imageNode = Boolean(pluckNumber(setData.imagenode));
|
|
config.imageWidth = setData.imagewidth;
|
|
config.imageHeight = setData.imageheight;
|
|
config.imageAlign = getValidValue(setData.imagealign, BLANK).toLowerCase();
|
|
config.labelAlign = pluck(setData.labelalign, config.imageNode &&
|
|
defined(config.imageURL) ? POSITION_TOP : POSITION_MIDDLE);
|
|
//If not required shape then set it to rectangle
|
|
switch (config.shape) {
|
|
case CIRCLE:
|
|
shapeType = 0;
|
|
break;
|
|
case POLYGON:
|
|
shapeType = 2;
|
|
shape = mapSymbolName(config.numSides);
|
|
break;
|
|
default:
|
|
shapeType = 1;
|
|
break;
|
|
}
|
|
config.symbol = shape;
|
|
if (use3DLighting) {
|
|
fillColor = config.fillColor = this.getPointColor(config.color,
|
|
config.alpha, shapeType);
|
|
config.cloneFillColor = this.getPointColor(config.color, 50, shapeType);
|
|
} else {
|
|
fillColor = config.fillColor = {
|
|
color: config.color,
|
|
alpha: config.alpha
|
|
};
|
|
config.cloneFillColor = convertColor(config.color, 50);
|
|
}
|
|
|
|
config.rollOverProperties = dataset.pointHoverOptions(dataObj, chartAttr, {
|
|
shapeType: shapeType,
|
|
use3D: use3DLighting,
|
|
height: config.height,
|
|
width: config.width,
|
|
radius: config.radius,
|
|
color: config.color,
|
|
alpha: config.alpha,
|
|
borderColor: config.borderColor,
|
|
borderAlpha: datasetPlotBorderAlpha,
|
|
borderThickness: datasetPlotBorderThickness
|
|
});
|
|
}
|
|
!config.update && updateObj && (config.update = updateObj.update);
|
|
!config.add && updateObj && (config.add = updateObj.add);
|
|
if (dataset._refreshData === true) {
|
|
delete dataObj.removed;
|
|
}
|
|
}
|
|
dataObj.dataset = dataset;
|
|
conf.xMax = xMax;
|
|
conf.xMin = xMin;
|
|
conf.yMin = yMin;
|
|
conf.yMax = yMax;
|
|
},
|
|
_configureTooltext: function (config, datasetConf, chartAttr) {
|
|
var setTooltext = config.setTooltext,
|
|
formatedVal = config.formatedVal,
|
|
seriesname = datasetConf.seriesname,
|
|
label = config.label,
|
|
xValue = config.xValue,
|
|
pointLabel = config.pointLabel,
|
|
tooltipSepChar = datasetConf.tooltipSepChar,
|
|
toolText;
|
|
if (setTooltext !== undefined) {
|
|
toolText = parseTooltext(setTooltext, [3, 4, 5, 6, 8, 9, 10, 11], {
|
|
yaxisName: parseUnsafeString(chartAttr.yaxisname),
|
|
xaxisName: parseUnsafeString(chartAttr.xaxisname),
|
|
yDataValue: formatedVal,
|
|
xDataValue: xValue,
|
|
label: label
|
|
}, config, chartAttr, datasetConf);
|
|
} else if (pointLabel !== undefined) {
|
|
toolText = label;
|
|
} else { //determine the tooltext then
|
|
if (formatedVal === null) {
|
|
toolText = false;
|
|
} else {
|
|
if (datasetConf.seriesNameInToolTip) {
|
|
seriesname = getFirstValue(datasetConf.seriesname);
|
|
}
|
|
toolText = seriesname ? seriesname + tooltipSepChar : BLANK;
|
|
toolText += xValue ? xValue + tooltipSepChar : BLANK;
|
|
toolText += formatedVal;
|
|
}
|
|
}
|
|
return toolText;
|
|
},
|
|
updatePointConfig: function (updateConf, index) {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
dataStore = dataset.components.data,
|
|
conf = dataset.config,
|
|
dataObj = dataStore[index] || {},
|
|
config = dataObj.config,
|
|
numberFormatter = chart.components.numberFormatter,
|
|
chartAttr = chart.jsonData.chart,
|
|
yMin = conf.yMin || +Infinity,
|
|
yMax = conf.yMax || -Infinity,
|
|
xMax = conf.xMax || -Infinity,
|
|
xMin = conf.xMin || +Infinity,
|
|
xValue;
|
|
if (config === UNDEFINED) {
|
|
return;
|
|
}
|
|
config.y = numberFormatter.getCleanValue(pluck(updateConf.y));
|
|
config.x = numberFormatter.getCleanValue(pluck(updateConf.x));
|
|
config._options.x = config.x;
|
|
config._options.y = config.y;
|
|
yMax = mathMax(yMax, config.y);
|
|
yMin = mathMin(yMin, config.y);
|
|
xMax = mathMax(xMax, config.x);
|
|
xMin = mathMin(xMin, config.x);
|
|
xValue = numberFormatter.xAxis(config.x);
|
|
//push the point object
|
|
config.formatedVal = (config.y === null ?
|
|
config.y : numberFormatter.dataLabels(config.y));
|
|
config.xValue = xValue;
|
|
if (!conf.showTooltip) {
|
|
config.toolText = false;
|
|
}
|
|
else {
|
|
config.toolText = dataset._configureTooltext(config, conf, chartAttr);
|
|
}
|
|
config.update = updateConf.update;
|
|
},
|
|
pointHoverOptions: function(dataObj, chartAttr, defaults) {
|
|
var dataset = this,
|
|
hoverEffect = pluckNumber(dataObj.showhovereffect, dataset.showhovereffect,
|
|
chartAttr.plothovereffect, chartAttr.showhovereffect),
|
|
rolloverProperties = {},
|
|
hoverAttr = !!pluck(dataObj.hovercolor, dataset.hovercolor, chartAttr.plotfillhovercolor,
|
|
dataObj.hoveralpha, dataset.hoveralpha, chartAttr.plotfillhoveralpha,
|
|
dataObj.borderhovercolor, dataset.borderhovercolor, chartAttr.plotborderhovercolor,
|
|
dataObj.borderhoveralpha, dataset.borderhoveralpha, chartAttr.plotborderhoveralpha,
|
|
dataObj.borderhoverthickness, dataset.borderhoverthickness, chartAttr.plotborderhoverthickness,
|
|
dataObj.hoverheight, dataset.hoverheight, chartAttr.plothoverheight,
|
|
dataObj.hoverwidth, dataset.hoverwidth, chartAttr.plothoverwidth,
|
|
dataObj.hoverradius, dataset.hoverradius, chartAttr.plothoverradius, hoverEffect),
|
|
enabled = false,
|
|
color,
|
|
alpha,
|
|
fillColor;
|
|
|
|
if ((hoverEffect === UNDEFINED && hoverAttr) || hoverEffect) {
|
|
enabled = true;
|
|
color = pluck(dataObj.hovercolor, dataset.hovercolor,
|
|
chartAttr.plotfillhovercolor, getLightColor(defaults.color, 70));
|
|
alpha = pluck(dataObj.hoveralpha, dataset.hoveralpha,
|
|
chartAttr.plotfillhoveralpha, defaults.alpha);
|
|
|
|
rolloverProperties = {
|
|
stroke: convertColor(pluck(dataObj.borderhovercolor, dataset.borderhovercolor,
|
|
chartAttr.plotborderhovercolor, defaults.borderColor),
|
|
pluckNumber(dataObj.borderhoveralpha, dataset.borderhoveralpha,
|
|
chartAttr.plotborderhoveralpha, alpha, defaults.borderAlpha)),
|
|
'stroke-width': pluckNumber(dataObj.borderhoverthickness, dataset.borderhoverthickness,
|
|
chartAttr.plotborderhoverthickness, defaults.borderThickness),
|
|
height: pluckNumber(dataObj.hoverheight, dataset.hoverheight,
|
|
chartAttr.plothoverheight, defaults.height),
|
|
width: pluckNumber(dataObj.hoverwidth, dataset.hoverwidth,
|
|
chartAttr.plothoverwidth, defaults.width),
|
|
r: pluckNumber(dataObj.hoverradius, dataset.hoverradius,
|
|
chartAttr.plothoverradius, defaults.radius)
|
|
};
|
|
|
|
if (defaults.use3D) {
|
|
fillColor = this.getPointColor(getFirstColor(pluck(dataObj.hovercolor,
|
|
dataset.hovercolor, chartAttr.plotfillhovercolor,
|
|
getLightColor(defaults.color, 70))),
|
|
pluck(dataObj.hoveralpha, dataset.hoveralpha,
|
|
chartAttr.plotfillhoveralpha, defaults.alpha),
|
|
defaults.shapeType);
|
|
} else {
|
|
fillColor = convertColor(color, alpha);
|
|
}
|
|
|
|
rolloverProperties.fill = toRaphaelColor(fillColor);
|
|
}
|
|
|
|
return {
|
|
enabled: enabled,
|
|
rollOverAttrs: rolloverProperties
|
|
};
|
|
},
|
|
// Get json data of dragnode dataset
|
|
getJSONData: function () {
|
|
var dataset = this,
|
|
dataStore = dataset.components.data,
|
|
len = dataStore.length,
|
|
jsonData = [],
|
|
dataObj,
|
|
i;
|
|
for (i = 0; i < len; i++) {
|
|
dataObj = dataStore[i];
|
|
if (!dataObj.removed) {
|
|
if (dataObj.config._options) {
|
|
delete dataObj.config._options.update;
|
|
delete dataObj.config._options.add;
|
|
jsonData.push(dataObj.config._options);
|
|
}
|
|
}
|
|
}
|
|
return jsonData;
|
|
},
|
|
// Function that produce the point color
|
|
getPointColor: function(color, alpha, shapeType) {
|
|
var colorObj, innerColor, outerColor;
|
|
color = getFirstColor(color);
|
|
alpha = getFirstAlpha(alpha);
|
|
innerColor = getLightColor(color, 80);
|
|
outerColor = getDarkColor(color, 65);
|
|
colorObj = {
|
|
FCcolor: {
|
|
gradientUnits: OBJECTBOUNDINGBOX,
|
|
color: innerColor + COMMA + outerColor,
|
|
alpha: alpha + COMMA + alpha,
|
|
ratio: BGRATIOSTRING
|
|
}
|
|
};
|
|
|
|
if (shapeType) {
|
|
if (shapeType === 1) {
|
|
colorObj.FCcolor.angle = 0;
|
|
} else {
|
|
colorObj.FCcolor.angle = 180;
|
|
}
|
|
} else {
|
|
colorObj.FCcolor.cx = 0.4;
|
|
colorObj.FCcolor.cy = 0.4;
|
|
colorObj.FCcolor.r = '50%';
|
|
colorObj.FCcolor.radialGradient = true;
|
|
}
|
|
|
|
return colorObj;
|
|
},
|
|
init: function (jsonData) {
|
|
var dataSet = this,
|
|
chart = dataSet.chart;
|
|
dataSet.yAxis = chart.components.yAxis[0];
|
|
dataSet.components = {
|
|
|
|
};
|
|
dataSet.graphics = {
|
|
|
|
};
|
|
|
|
dataSet.JSONData = jsonData;
|
|
dataSet.plotType = 'dragnode';
|
|
dataSet.configure();
|
|
|
|
},
|
|
_addLegend: function () {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
conf = dataset.config,
|
|
legend = chart.components.legend,
|
|
config = {
|
|
enabled: conf.includeInLegend,
|
|
type : dataset.type,
|
|
fillColor : toRaphaelColor({
|
|
color: conf.color,
|
|
alpha: conf.alpha
|
|
}),
|
|
strokeColor: toRaphaelColor({
|
|
color: conf.plotBorderColor,
|
|
alpha: HUNDREDSTRING
|
|
}),
|
|
anchorSide: 4,
|
|
strokeWidth: conf.anchorBorderThickness,
|
|
label : getFirstValue(dataset.JSONData.seriesname)
|
|
};
|
|
dataset.legendItemId = legend.addItems(dataset, dataset.legendInteractivity, config);
|
|
},
|
|
draw: function () {
|
|
var dataset = this,
|
|
components = dataset.components,
|
|
datasetGraphics = dataset.graphics,
|
|
chart = dataset.chart,
|
|
jobList = chart.getJobList(),
|
|
smartLabel = chart.linkedItems.smartLabel,
|
|
data = components.data,
|
|
removeDataArr = dataset.components.removeDataArr || [],
|
|
removeDataArrLen = removeDataArr.length,
|
|
i,
|
|
paper = chart.components.paper,
|
|
ln,
|
|
group,
|
|
config,
|
|
style = chart.config.dataLabelStyle,
|
|
css = {
|
|
fontFamily: style.fontFamily,
|
|
fontSize: style.fontSize,
|
|
lineHeight: style.lineHeight,
|
|
fontWeight: style.fontWeight,
|
|
fontStyle: style.fontStyle
|
|
},
|
|
dragLabelGroup,
|
|
removed,
|
|
layers = chart.graphics,//requird for series drawing
|
|
gDataset = layers.datasetGroup;
|
|
group = datasetGraphics.group = (datasetGraphics.group || paper.group(gDataset));
|
|
dragLabelGroup = datasetGraphics.dragLabelGroup = (datasetGraphics.dragLabelGroup ||
|
|
paper.group('dragLabelGroup', gDataset));
|
|
group.trackTooltip(true);
|
|
smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
|
|
smartLabel.setStyle(style);
|
|
group.css(css);
|
|
//draw data
|
|
for (i = 0, ln = data.length; i < ln; i += 1) {
|
|
config = data[i].config;
|
|
removed = data[i].removed;
|
|
!removed && this._drawNode(i);
|
|
}
|
|
// jobList.trackerDrawID.push(schedular.addJob(dataset.drawTracker, dataset, [],
|
|
// lib.priorityList.tracker));
|
|
!dataset.drawn && jobList.labelDrawID.push(schedular.addJob(dataset.drawLabel, dataset, [],
|
|
lib.priorityList.label));
|
|
dataset.drawn = true;
|
|
|
|
if (dataset.visible) {
|
|
group.show();
|
|
dragLabelGroup.show();
|
|
}
|
|
// Remove the extra elements
|
|
for (i = 0; i < removeDataArrLen; i++) {
|
|
dataset._removeDataVisuals(removeDataArr.shift());
|
|
}
|
|
|
|
},
|
|
rolloverResponseSetter: function (elem, enabled) {
|
|
return function (data) {
|
|
var ele = this,
|
|
_data = ele.data('drag-options'),
|
|
chart = _data.chart,
|
|
dataObj = _data.dataObj,
|
|
config = dataObj.config,
|
|
dragStart = config.dragStart,
|
|
keysNo = dragStart && Object.keys(dragStart).length,
|
|
hoverAttr = ele.data('hoverAttr');
|
|
if (!keysNo) {
|
|
enabled && elem.graphics.element.attr(hoverAttr);
|
|
plotEventHandler.call(ele, chart, data, ROLLOVER);
|
|
}
|
|
};
|
|
},
|
|
rolloutResponseSetter: function (elem, enabled) {
|
|
return function (data) {
|
|
var ele = this,
|
|
_data = ele.data('drag-options'),
|
|
dataObj = _data.dataObj,
|
|
chart = _data.chart,
|
|
config = dataObj.config,
|
|
dragStart = config.dragStart,
|
|
keysNo = dragStart && Object.keys(dragStart).length,
|
|
unHoverAttr = ele.data('unHoverAttr');
|
|
if (!keysNo) {
|
|
enabled && elem.graphics.element.attr(unHoverAttr);
|
|
plotEventHandler.call(ele, chart, data, ROLLOUT);
|
|
}
|
|
};
|
|
},
|
|
dragUp: function (event) {
|
|
var ele = this,
|
|
data = ele.data('drag-options'),
|
|
dataset = data.dataset;
|
|
dataset._dragUp.call(ele, event);
|
|
},
|
|
dragMove: function (dx, dy, px, py) {
|
|
var ele = this,
|
|
data = ele.data('drag-options'),
|
|
dataset = data.dataset,
|
|
chart = data.chart;
|
|
dataset._dragMove.call(ele, dx, dy, px, py, chart);
|
|
},
|
|
dragStart: function (x, y, event) {
|
|
var ele = this,
|
|
data = ele.data('drag-options'),
|
|
dataset = data.dataset,
|
|
chart = data.chart;
|
|
dataset._dragStart.call(ele, event, chart);
|
|
},
|
|
_drawNode: function (i) {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
datasetIndex = dataset.index,
|
|
chartComp = chart.components,
|
|
manager = dataset.groupManager,
|
|
nodes = manager.nodes,
|
|
paper = chartComp.paper,
|
|
xAxis = dataset.xAxis = chartComp.xAxis[0],
|
|
yAxis = dataset.yAxis = chartComp.yAxis[0],
|
|
data = dataset.components.data,
|
|
set = data[i],
|
|
config = set.config,
|
|
conf = dataset.config,
|
|
animationObj = chart.get(configStr, animationObjStr) || {},
|
|
animation = animationObj.duration,
|
|
dummyAnimElem = animationObj.dummyObj,
|
|
dummyAnimObj = animationObj.animObj,
|
|
xPos,
|
|
yPos,
|
|
setGraphics = set.graphics || (set.graphics = {}),
|
|
symbol = config.symbol,
|
|
width,
|
|
height,
|
|
radius,
|
|
id,
|
|
groupId,
|
|
imageNode,
|
|
confShapeArg,
|
|
imageURL,
|
|
imageAlign,
|
|
labelAlign,
|
|
lineColor = conf.colorObj.lineColor,
|
|
lineWidth = conf.datasetPlotBorderThickness,
|
|
plotWidth,
|
|
plotHeight,
|
|
isRectangle,
|
|
layers = chart.graphics,
|
|
datasetGraphics = dataset.graphics,
|
|
gDataset = layers.datasetGroup,
|
|
group = datasetGraphics.group,
|
|
rollOverProperties = set.config.rollOverProperties,
|
|
imageWidth,
|
|
imageHeight,
|
|
imageY,
|
|
graphic,
|
|
pointAttr,
|
|
pointOptions,
|
|
rolloverResponseSetter = dataset.rolloverResponseSetter,
|
|
rolloutResponseSetter = dataset.rolloutResponseSetter,
|
|
dragUp = dataset.dragUp,
|
|
dragMove = dataset.dragMove,
|
|
dragStart = dataset.dragStart,
|
|
fill,
|
|
link,
|
|
eventArgs,
|
|
shapeType = config.shapeType,
|
|
cursor = config.link ? POINTER : config.allowDrag ? 'move' : BLANKSTRING,
|
|
rollOverAttrs,
|
|
pool = dataset.components.pool || {},
|
|
poolElemType,
|
|
type,
|
|
polypath,
|
|
setElement = setGraphics.graphic,
|
|
cloneText = setGraphics.cloneText,
|
|
cloneGraphic = setGraphics.cloneGraphic,
|
|
cloneImage = setGraphics.cloneImage,
|
|
imageElement = setGraphics.image,
|
|
attr,
|
|
elemType,
|
|
labelElement = setGraphics.label;
|
|
|
|
datasetGraphics.cloneGraphicGroup = datasetGraphics.cloneGraphicGroup ||
|
|
paper.group('clone', gDataset);
|
|
|
|
datasetGraphics.cloneGraphicGroup.attr({
|
|
opacity: 0.3
|
|
});
|
|
|
|
config._yPos = yPos = yAxis.getAxisPosition(config.y);
|
|
config._xPos = xPos = xAxis.getAxisPosition(config.x);
|
|
// only draw the point if y is defined
|
|
if (yPos !== UNDEFINED && !isNaN(yPos)) {
|
|
config.shapeArg = {};
|
|
confShapeArg = config.shapeArg;
|
|
pointOptions = set._options;
|
|
graphic = set.graphic;
|
|
height = pluckNumber(config.height);
|
|
width = pluckNumber(config.width);
|
|
radius = pluckNumber(config.radius);
|
|
isRectangle = symbol === RECTANGLE;
|
|
id = config.id;
|
|
imageNode = config.imageNode;
|
|
imageURL = config.imageURL;
|
|
imageAlign = config.imageAlign; //TOP, MIDDLE or BOTTOM
|
|
labelAlign = config.labelAlign;
|
|
plotWidth = isRectangle ? width : radius * 1.4;
|
|
imageWidth = pluckNumber(config.imageWidth, plotWidth);
|
|
plotHeight = isRectangle ? height : radius * 1.4;
|
|
imageHeight = pluckNumber(config.imageHeight, plotHeight),
|
|
link = config.link;
|
|
fill = toRaphaelColor(config.fillColor);
|
|
config._plotWidth = plotWidth;
|
|
config._plotHeight = plotHeight;
|
|
pointAttr = {
|
|
fill: fill,
|
|
'stroke-width': lineWidth,
|
|
stroke: toRaphaelColor(lineColor)
|
|
};
|
|
symbol = confShapeArg.symbol = pluck(config.symbol,
|
|
conf.symbol, BLANK);
|
|
symbol = symbol.split(UNDERSCORE);
|
|
|
|
polypath = [symbol[1], xPos, yPos, config.radius, config.startAngle, 0];
|
|
|
|
if (symbol[0] === 'poly' || symbol[0] === CIRCLE) {
|
|
config.shapeType = symbol[0];
|
|
elemType = 'polypath';
|
|
poolElemType = 'path';
|
|
attr = {
|
|
polypath: polypath
|
|
};
|
|
confShapeArg.x = xPos;
|
|
confShapeArg.y = yPos;
|
|
confShapeArg.radius = config.radius;
|
|
confShapeArg.sides = symbol[1];
|
|
}
|
|
else {
|
|
config.shapeType = SHAPE_RECT;
|
|
elemType = 'rect';
|
|
poolElemType = 'rect';
|
|
confShapeArg.x = xPos - (width / 2);
|
|
confShapeArg.y = yPos - (height / 2);
|
|
confShapeArg.r = 0;
|
|
confShapeArg.width = width;
|
|
confShapeArg.height = height;
|
|
attr = {
|
|
x: confShapeArg.x,
|
|
y: confShapeArg.y,
|
|
width: width,
|
|
height: height,
|
|
r: 0
|
|
};
|
|
pointAttr.width = width;
|
|
pointAttr.height = height;
|
|
pointAttr.x = xPos - (width / 2);
|
|
pointAttr.y = yPos - (height / 2);
|
|
// Readjust x and y of the rectangle if hover width or height is
|
|
// changed
|
|
if (rollOverProperties && rollOverProperties.enabled) {
|
|
rollOverAttrs = rollOverProperties.rollOverAttrs;
|
|
rollOverAttrs.x = xPos - (rollOverAttrs.width / 2);
|
|
rollOverAttrs.y = yPos - (rollOverAttrs.height / 2);
|
|
delete rollOverAttrs.r;
|
|
}
|
|
}
|
|
|
|
setElement = setGraphics.element;
|
|
type = setElement && setElement.type;
|
|
if (elemType.indexOf(type) === -1 && setElement) {
|
|
setElement.remove();
|
|
setElement = setGraphics.element = null;
|
|
labelElement && labelElement.remove();
|
|
imageElement && imageElement.remove();
|
|
delete setGraphics.label;
|
|
delete setGraphics.image;
|
|
imageElement = null;
|
|
labelElement = null;
|
|
}
|
|
|
|
// Create a new element
|
|
if (!setElement) {
|
|
// Reuse element from pool if any
|
|
if (pool.element && pool.element[poolElemType] &&
|
|
pool.element[poolElemType].length) {
|
|
setElement = setGraphics.element = pool.element[poolElemType].shift();
|
|
setElement.toFront();
|
|
}
|
|
else {
|
|
setElement = setGraphics.element = paper[elemType](group);
|
|
setElement.attr(attr);
|
|
}
|
|
|
|
setElement.hover(rolloverResponseSetter(set,
|
|
rollOverProperties && rollOverProperties.enabled),
|
|
rolloutResponseSetter(set, rollOverProperties && rollOverProperties.enabled));
|
|
|
|
// If dragging is allowed for that node then only we bind drag functions to the setElement
|
|
setElement.drag(dragMove, dragStart, dragUp);
|
|
}
|
|
|
|
|
|
setElement.show().animateWith(dummyAnimElem, dummyAnimObj, attr, animation);
|
|
|
|
setElement.attr({
|
|
fill: fill,
|
|
'stroke-width': lineWidth,
|
|
stroke: toRaphaelColor(lineColor)
|
|
});
|
|
|
|
manager.animationDone = true;
|
|
|
|
eventArgs = {
|
|
index: i,
|
|
link: config.link,
|
|
y: config.y,
|
|
x: config.x,
|
|
shape: pluck(shapeType, 'rect'),
|
|
width: width,
|
|
height: height,
|
|
radius: radius,
|
|
sides: config.numSides,
|
|
label: config.displayValue,
|
|
toolText: config.toolText,
|
|
id: config.id,
|
|
datasetIndex: dataset.index,
|
|
datasetName: dataset.JSONData.seriesname,
|
|
sourceType: 'dataplot'
|
|
};
|
|
groupId = datasetIndex + '_' + i;
|
|
|
|
if (cloneGraphic) {
|
|
if (cloneGraphic.type === setElement.type) {
|
|
attr.fill = fill;
|
|
attr['stroke-width'] = lineWidth;
|
|
attr.stroke = toRaphaelColor(lineColor);
|
|
cloneGraphic.transform(BLANKSTRING);
|
|
cloneGraphic.attr(attr);
|
|
}
|
|
else {
|
|
cloneGraphic.remove();
|
|
delete set.graphics.cloneGraphic;
|
|
/*if (cloneImage) {
|
|
cloneImage.remove();
|
|
delete set.graphics.cloneImage;
|
|
}*/
|
|
if (cloneText) {
|
|
cloneText.remove();
|
|
delete set.graphics.cloneText;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Draw the imageNode if available
|
|
if (imageNode && imageURL) {
|
|
if (imageHeight > plotHeight) {
|
|
imageHeight = plotHeight;
|
|
}
|
|
if (imageWidth > plotWidth) {
|
|
imageWidth = plotWidth;
|
|
}
|
|
switch (imageAlign) {
|
|
case POSITION_MIDDLE:
|
|
imageY = yPos - (imageHeight / 2);
|
|
break;
|
|
case POSITION_BOTTOM:
|
|
imageY = plotHeight > imageHeight ? yPos +
|
|
(plotHeight / 2) - imageHeight :
|
|
yPos - imageHeight / 2;
|
|
break;
|
|
default:
|
|
imageY = plotHeight > imageHeight ?
|
|
yPos - (plotHeight * 0.5) :
|
|
yPos - imageHeight / 2;
|
|
break;
|
|
}
|
|
config.imageX = xPos - (imageWidth / 2);
|
|
config.imageY = imageY;
|
|
config.imageWidth = imageWidth;
|
|
config.imageHeight = imageHeight;
|
|
poolElemType = 'image';
|
|
if (!imageElement) {
|
|
if (pool.image && pool.image[poolElemType] && pool.image[poolElemType].length) {
|
|
imageElement = setGraphics.image = pool.image[poolElemType].shift();
|
|
imageElement.toFront();
|
|
}
|
|
else {
|
|
imageElement = setGraphics.image = paper.image(group);
|
|
imageElement.tooltip(config.toolText);
|
|
imageElement.hover(rolloverResponseSetter(set,
|
|
rollOverProperties && rollOverProperties.enabled),
|
|
rolloutResponseSetter(set, rollOverProperties && rollOverProperties.enabled));
|
|
|
|
// If dragging is allowed for that node then only
|
|
//we bind drag functions to the imageElement
|
|
imageElement.drag(dragMove, dragStart, dragUp);
|
|
}
|
|
}
|
|
|
|
imageElement.show().attr({
|
|
src: imageURL,
|
|
x: config.imageX,
|
|
y: imageY,
|
|
width: imageWidth,
|
|
height: imageHeight
|
|
});
|
|
|
|
imageElement.attr({
|
|
cursor : cursor
|
|
});
|
|
imageElement.tooltip(config.toolText);
|
|
|
|
imageElement.data('drag-options',{
|
|
dataObj: set,
|
|
dataset: dataset,
|
|
datasetIndex: dataset.index,
|
|
pointIndex: set.config.index,
|
|
cursor: cursor,
|
|
chart: chart,
|
|
link: set.link
|
|
});
|
|
|
|
imageElement.data(GROUPID, groupId);
|
|
imageElement.data(EVENTARGS, eventArgs);
|
|
imageElement.data('hoverAttr', rollOverProperties && rollOverProperties.rollOverAttrs);
|
|
imageElement.data('unHoverAttr', pointAttr);
|
|
|
|
if (cloneImage) {
|
|
cloneImage.transform(BLANKSTRING);
|
|
cloneImage.attr({
|
|
src: imageURL,
|
|
x: config.imageX,
|
|
y: imageY,
|
|
width: imageWidth,
|
|
height: imageHeight
|
|
});
|
|
}
|
|
}
|
|
config.pointAttr = pointAttr;
|
|
dataset.drawn && dataset.drawLabel(i);
|
|
nodes[id] = set;
|
|
|
|
|
|
|
|
setElement.attr({
|
|
cursor : cursor
|
|
});
|
|
setElement.tooltip(config.toolText);
|
|
|
|
setElement.data('drag-options',{
|
|
dataObj: set,
|
|
dataset: dataset,
|
|
datasetIndex: dataset.index,
|
|
pointIndex: set.config.index,
|
|
cursor: cursor,
|
|
chart: chart,
|
|
link: set.link
|
|
});
|
|
|
|
|
|
|
|
setElement.data(GROUPID, groupId);
|
|
setElement.data(EVENTARGS, eventArgs);
|
|
setElement.data('hoverAttr', rollOverProperties && rollOverProperties.rollOverAttrs);
|
|
setElement.data('unHoverAttr', pointAttr);
|
|
}
|
|
},
|
|
drawLabel: function (index) {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
datasetIndex = dataset.index,
|
|
paper = chart.components.paper,
|
|
dataStore = dataset.components.data,
|
|
i,
|
|
len = dataStore.length,
|
|
labelAttrs,
|
|
labelElement,
|
|
group = dataset.graphics.group,
|
|
style = chart.config.dataLabelStyle,
|
|
animationObj = chart.get('config', 'animationObj'),
|
|
dummyAnimElem = animationObj.dummyObj,
|
|
dummyAnimObj = animationObj.animObj,
|
|
animationDuration = animationObj.duration,
|
|
pool = dataset.components.pool || {},
|
|
config,
|
|
valueString,
|
|
chartConfig = chart.config,
|
|
poolElemType,
|
|
cursor,
|
|
smartTextObj,
|
|
labelDisplacement,
|
|
eventArgs,
|
|
set,
|
|
yAdjustment,
|
|
animType = animationObj.animType,
|
|
xPos,
|
|
labelY,
|
|
groupId,
|
|
cloneText,
|
|
plotWidth,
|
|
plotHeight,
|
|
labelAlign,
|
|
setGraphics,
|
|
rolloverResponseSetter = dataset.rolloverResponseSetter,
|
|
rolloutResponseSetter = dataset.rolloutResponseSetter,
|
|
dragUp = dataset.dragUp,
|
|
dragMove = dataset.dragMove,
|
|
dragStart = dataset.dragStart,
|
|
rollOverProperties,
|
|
shapeType,
|
|
yPos,
|
|
smartLabel = chart.linkedItems.smartLabel,
|
|
setElement;
|
|
|
|
|
|
if (index !== UNDEFINED) {
|
|
i = index;
|
|
len = i + 1;
|
|
}
|
|
else {
|
|
i = 0;
|
|
}
|
|
|
|
for (; i < len; i++) {
|
|
set = dataStore[i];
|
|
config = set.config;
|
|
plotWidth = config._plotWidth;
|
|
plotHeight = config._plotHeight;
|
|
valueString = config.displayValue;
|
|
labelAlign = config.labelAlign;
|
|
setGraphics = set.graphics;
|
|
cloneText = setGraphics.cloneText;
|
|
rollOverProperties = set.config.rollOverProperties;
|
|
shapeType = config.shapeType;
|
|
|
|
if (defined(valueString) || valueString !== BLANK) {
|
|
poolElemType = 'text';
|
|
// Get the displayValue text according to the canvas width.
|
|
smartLabel.useEllipsesOnOverflow(chartConfig.useEllipsesWhenOverflow);
|
|
smartTextObj = smartLabel.getSmartText(valueString,
|
|
plotWidth, plotHeight);
|
|
|
|
// label displacement for top or bottom
|
|
labelDisplacement = plotHeight * 0.5 -
|
|
(smartTextObj.height * 0.5);
|
|
// label at TOP
|
|
switch (labelAlign) {
|
|
case POSITION_TOP:
|
|
labelDisplacement = -labelDisplacement;
|
|
break;
|
|
case POSITION_BOTTOM:
|
|
labelDisplacement = labelDisplacement;
|
|
break;
|
|
default:
|
|
labelDisplacement = 0;
|
|
break;
|
|
}
|
|
xPos = config._xPos;
|
|
yPos = config._yPos;
|
|
set._yAdjustment = yAdjustment = labelDisplacement;
|
|
labelY = yPos + yAdjustment;
|
|
|
|
labelAttrs = {
|
|
text: smartTextObj.text,
|
|
title: (smartTextObj.tooltext || BLANKSTRING),
|
|
fill: style.color,
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
};
|
|
|
|
labelElement = setGraphics.label =
|
|
setGraphics.label || (pool.label && pool.label[poolElemType] &&
|
|
pool.label[poolElemType].shift());
|
|
|
|
if (!labelElement) {
|
|
labelAttrs.x = xPos;
|
|
labelAttrs.y = labelY;
|
|
labelElement = setGraphics.label = paper.text(labelAttrs, group);
|
|
|
|
labelElement.hover(rolloverResponseSetter(set,
|
|
rollOverProperties && rollOverProperties.enabled),
|
|
rolloutResponseSetter(set, rollOverProperties && rollOverProperties.enabled));
|
|
|
|
// If dragging is allowed for that node then only we bind drag functions to the labelElement
|
|
labelElement.drag(dragMove, dragStart, dragUp);
|
|
}
|
|
else {
|
|
labelElement.attr(labelAttrs);
|
|
labelElement.show().animateWith(dummyAnimElem, dummyAnimObj, {
|
|
x: xPos,
|
|
y: labelY
|
|
}, animationDuration, animType);
|
|
}
|
|
|
|
setElement = setGraphics && (setGraphics.image || setGraphics.element);
|
|
|
|
setElement && labelElement.insertAfter(setElement);
|
|
|
|
if (cloneText) {
|
|
cloneText.transform(BLANKSTRING);
|
|
cloneText.attr({
|
|
x: xPos,
|
|
y: labelY,
|
|
text: smartTextObj.text,
|
|
title: (smartTextObj.tooltext || BLANKSTRING),
|
|
fill: style.color,
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
});
|
|
}
|
|
cursor = config.link ? POINTER : config.allowDrag ? 'move' : BLANKSTRING;
|
|
labelElement.attr({
|
|
cursor : cursor
|
|
});
|
|
labelElement.tooltip(config.toolText);
|
|
|
|
labelElement.data('drag-options',{
|
|
dataObj: set,
|
|
dataset: dataset,
|
|
datasetIndex: dataset.index,
|
|
pointIndex: set.config.index,
|
|
cursor: cursor,
|
|
chart: chart,
|
|
link: set.link
|
|
});
|
|
|
|
eventArgs = {
|
|
index: i,
|
|
link: config.link,
|
|
y: config.y,
|
|
x: config.x,
|
|
shape: pluck(shapeType, 'rect'),
|
|
width: config.width,
|
|
height: config.height,
|
|
radius: config.radius,
|
|
sides: config.numSides,
|
|
label: config.displayValue,
|
|
toolText: config.toolText,
|
|
id: config.id,
|
|
datasetIndex: dataset.index,
|
|
datasetName: dataset.JSONData.seriesname,
|
|
sourceType: 'dataplot'
|
|
};
|
|
|
|
groupId = datasetIndex + '_' + i;
|
|
labelElement.data(GROUPID, groupId);
|
|
labelElement.data(EVENTARGS, eventArgs);
|
|
labelElement.data('hoverAttr', rollOverProperties && rollOverProperties.rollOverAttrs);
|
|
labelElement.data('unHoverAttr', setElement.data('unHoverAttr'));
|
|
}
|
|
else {
|
|
setGraphics.label && setGraphics.label.hide();
|
|
}
|
|
}
|
|
|
|
},
|
|
_removeDataVisuals : function (dataObj) {
|
|
var dataSet = this,
|
|
pool = dataSet.components.pool || (dataSet.components.pool = {}),
|
|
elementPool,
|
|
ele,
|
|
graphics,
|
|
elemSpecificPool,
|
|
type,
|
|
graphicsObj;
|
|
if (!dataObj) {
|
|
return;
|
|
}
|
|
graphics = dataObj.graphics;
|
|
for (ele in graphics) {
|
|
elementPool = pool[ele] || (pool[ele] = {});
|
|
|
|
graphicsObj = graphics[ele];
|
|
type = graphicsObj && graphicsObj.type;
|
|
elemSpecificPool = elementPool[type] || (elementPool[type] = []);
|
|
|
|
if (graphicsObj.hide && typeof graphicsObj.hide === 'function') {
|
|
graphicsObj.attr({
|
|
'text-bound': []
|
|
});
|
|
graphicsObj.hide();
|
|
graphicsObj.transform && graphicsObj.transform(BLANKSTRING);
|
|
}
|
|
elemSpecificPool.push(graphics[ele]);
|
|
}
|
|
},
|
|
show: function () {
|
|
var dataset = this,
|
|
graphics = dataset.graphics,
|
|
group = graphics.group,
|
|
dragLabelGroup = graphics.dragLabelGroup;
|
|
|
|
group.show();
|
|
dragLabelGroup.show();
|
|
dataset.visible = true;
|
|
|
|
},
|
|
hide: function () {
|
|
var dataset = this,
|
|
graphics = dataset.graphics,
|
|
group = graphics.group,
|
|
dragLabelGroup = graphics.dragLabelGroup;
|
|
group.hide();
|
|
dragLabelGroup.hide();
|
|
dataset.visible = false;
|
|
},
|
|
_dragStart: function (e, chart) {
|
|
var element = this,
|
|
data = element.data('drag-options'),
|
|
dataObj = data.dataObj,
|
|
dataGraphics = dataObj.graphics,
|
|
ele = dataGraphics.element,
|
|
bBox = ele.getBBox(),
|
|
config = dataObj.config,
|
|
dataset = data.dataset,
|
|
groupManager = dataset.groupManager,
|
|
graphics = groupManager.graphics,
|
|
waitElement = graphics.waitElement,
|
|
conf = data.dataset.config,
|
|
viewMode = conf.viewMode,
|
|
touchEvent = (hasTouch && getTouchEvent(e)) || stubEvent,
|
|
layerX = e.layerX || touchEvent.layerX,
|
|
layerY = e.layerY || touchEvent.layerY,
|
|
paper = chart.components.paper,
|
|
trackerGroup = dataset.graphics.group,
|
|
dragStart = config.dragStart || (config.dragStart = {}),
|
|
cloneGraphic = dataObj.graphics.cloneGraphic,
|
|
cloneGraphicGroup = dataset.graphics.cloneGraphicGroup,
|
|
cloneText = dataObj.graphics.cloneText,
|
|
image = dataObj.graphics.image,
|
|
displayValue = config.displayValue,
|
|
cloneImage = dataObj.graphics.cloneImage,
|
|
style = chart.config.dataLabelStyle,
|
|
labelAttr,
|
|
label = dataObj.graphics.label,
|
|
shapesInfo = {
|
|
circle: 'circ',
|
|
rectangle: 'rect',
|
|
polygon: 'poly'
|
|
},
|
|
attr;
|
|
// Set dirty flag to 1 so that bbox is recalculated again
|
|
if (isVML) {
|
|
ele._.dirty = 1;
|
|
}
|
|
|
|
attr = [config.symbol.split(UNDERSCORE)[1], config._xPos,
|
|
config._yPos, config.radius, config.startAngle, 0];
|
|
labelAttr = {
|
|
text: displayValue,
|
|
'class': 'fusioncharts-label',
|
|
x: config._xPos,
|
|
y: config._yPos,
|
|
fill: 'rgba(96,99,78,.4)',
|
|
'font-size': style.fontSize,
|
|
'font-weight': style.fontWeight,
|
|
'font-style': style.fontStyle,
|
|
'font-family': style.fontFamily,
|
|
visibility: visibleStr
|
|
};
|
|
if (config.allowDrag) {
|
|
if (!cloneGraphic && dataObj.graphics.element) {
|
|
cloneGraphic = dataObj.graphics.cloneGraphic = dataObj.graphics.element.clone();
|
|
cloneGraphicGroup.appendChild(cloneGraphic);
|
|
}
|
|
if (label && !cloneText) {
|
|
cloneText = dataObj.graphics.cloneText = dataObj.graphics.label.clone();
|
|
if (cloneText.followers[0] && cloneText.followers[0].el) {
|
|
cloneGraphicGroup.appendChild(cloneText.followers[0].el);
|
|
}
|
|
cloneGraphicGroup.appendChild(cloneText);
|
|
}
|
|
if (image && !cloneImage) {
|
|
cloneImage = dataObj.graphics.cloneImage =
|
|
dataObj.graphics.image.clone();
|
|
cloneGraphicGroup.appendChild(cloneImage);
|
|
}
|
|
cloneText && cloneText.show();
|
|
cloneImage && cloneImage.show();
|
|
cloneGraphic && cloneGraphic.show();
|
|
}
|
|
dragStart.xPos = config._xPos;
|
|
dragStart.yPos = config._yPos;
|
|
dragStart.x = config.x;
|
|
dragStart.y = config.y;
|
|
dragStart.bBox = bBox;
|
|
// store original x, y positions
|
|
dragStart.origX = dragStart.lastDx || (dragStart.lastDx = 0);
|
|
dragStart.origY = dragStart.lastDy || (dragStart.lastDy = 0);
|
|
|
|
// Whether to fire the click event ot not
|
|
ele.data('fire_click_event', 1);
|
|
ele.data('mousedown', 1);
|
|
clearTimeout(ele._longpressactive);
|
|
// DragNode mouse progress cursor added.
|
|
ele.data('move', true);
|
|
// If view mode is enabled, don't open the node edit UI.
|
|
if (!viewMode) {
|
|
waitElement || (waitElement = graphics.waitElement = paper
|
|
.ringpath(config._xPos, config._yPos, 8, 11, 0, 0, trackerGroup)
|
|
.attr({
|
|
fill: toRaphaelColor({
|
|
alpha: '100,100',
|
|
angle: 120,
|
|
color: 'CCCCCC,FFFFFF',
|
|
ratio: '30,50'
|
|
}),
|
|
'stroke-width': 0
|
|
}));
|
|
layerX += 11;
|
|
layerY -= 21;
|
|
waitElement.attr({
|
|
ringpath: [config._xPos, config._yPos, 8, 11, 0, 0]
|
|
})
|
|
.show()
|
|
.animate({
|
|
ringpath: [config._xPos, config._yPos, 8, 11, 0, 6.28]
|
|
}, CLEAR_TIME_1000);
|
|
|
|
ele._longpressactive = setTimeout(function() {
|
|
var seriesName = (conf.name !== BLANK &&
|
|
conf.name !== UNDEFINED) ?
|
|
conf.name + COMMASTRING +
|
|
BLANKSPACE : BLANK,
|
|
seriesId = conf.id;
|
|
graphics.waitElement && graphics.waitElement.hide();
|
|
// Whether to fire the click event ot not
|
|
ele.data('fire_click_event', 0);
|
|
groupManager.showNodeUpdateUI(chart, {
|
|
x: {
|
|
value: config.x
|
|
},
|
|
y: {
|
|
value: config.y
|
|
},
|
|
draggable: {
|
|
value: getFirstValue(config.allowdrag, 1)
|
|
},
|
|
color: {
|
|
value: config.color
|
|
},
|
|
alpha: {
|
|
value: config.alpha
|
|
},
|
|
label: {
|
|
value: getFirstValue(config.label,
|
|
config.name)
|
|
},
|
|
tooltip: {
|
|
value: config.toolText
|
|
},
|
|
shape: {
|
|
value: shapesInfo[config.shape]
|
|
},
|
|
rectWidth: {
|
|
value: config.width
|
|
},
|
|
rectHeight: {
|
|
value: config.height
|
|
},
|
|
circPolyRadius: {
|
|
value: config.radius
|
|
},
|
|
polySides: {
|
|
value: config.numsides
|
|
},
|
|
image: {
|
|
value: config.imageNode
|
|
},
|
|
imgWidth: {
|
|
value: config.imageWidth
|
|
},
|
|
imgHeight: {
|
|
value: config.imageHeight
|
|
},
|
|
imgAlign: {
|
|
value: config.imageAlign
|
|
},
|
|
imgUrl: {
|
|
value: config.imageURL
|
|
},
|
|
id: {
|
|
value: config.id,
|
|
disabled: true
|
|
},
|
|
link: {
|
|
value: config.link
|
|
},
|
|
dataset: {
|
|
innerHTML: '<option value="' +
|
|
seriesId + '">' + seriesName +
|
|
seriesId + '</option>',
|
|
disabled: true
|
|
},
|
|
datasetIndex: dataset.index
|
|
}, true);
|
|
}, CLEAR_TIME_1000);
|
|
}
|
|
cloneGraphic && cloneGraphic.show();
|
|
cloneText && cloneText.show();
|
|
cloneImage && cloneImage.show();
|
|
},
|
|
_dragMove: function (dx, dy, px, py, chart) {
|
|
var element = this,
|
|
data = element.data('drag-options'),
|
|
dataObj = data.dataObj,
|
|
ele = dataObj.graphics.element,
|
|
cloneGraphic = dataObj.graphics.cloneGraphic,
|
|
cloneImage = dataObj.graphics.cloneImage,
|
|
cloneText = dataObj.graphics.cloneText,
|
|
config = dataObj.config,
|
|
dragStart = config.dragStart,
|
|
startX = dragStart.bBox.x + dx,
|
|
endX = dragStart.bBox.x2 + dx,
|
|
startY = dragStart.bBox.y + dy,
|
|
endY = dragStart.bBox.y2 + dy,
|
|
graphics = data.dataset.groupManager.graphics,
|
|
canvasLeft = chart.config.canvasLeft,
|
|
canvasRight = chart.config.canvasRight,
|
|
transform,
|
|
canvasTop = chart.config.canvasTop,
|
|
canvasBottom = chart.config.canvasBottom;
|
|
|
|
// Bound limits
|
|
if (startX < canvasLeft) {
|
|
dx += (canvasLeft - startX);
|
|
}
|
|
if (endX > canvasRight) {
|
|
dx -= (endX - canvasRight);
|
|
}
|
|
if (startY < canvasTop) {
|
|
dy += (canvasTop - startY);
|
|
}
|
|
if (endY > canvasBottom) {
|
|
dy -= (endY - canvasBottom);
|
|
}
|
|
if (dx || dy) {
|
|
graphics.waitElement && graphics.waitElement.hide();
|
|
// Whether to fire the click event or not
|
|
ele.data('fire_click_event', 0);
|
|
clearLongPress.call(ele);
|
|
}
|
|
if (config.allowDrag) {
|
|
dragStart.draged = true;
|
|
dragStart.lastDx = dx;
|
|
dragStart.lastDy = dy;
|
|
|
|
transform = data._transformObj = {
|
|
transform: 't' + (dragStart.origX + dx) + COMMA +
|
|
(dragStart.origY + dy)
|
|
};
|
|
if (cloneGraphic) {
|
|
cloneGraphic.attr(transform);
|
|
}
|
|
if (cloneImage) {
|
|
cloneImage.attr(transform);
|
|
}
|
|
if (cloneText) {
|
|
cloneText.attr({
|
|
x: config._xPos + dx,
|
|
y: config._yPos + dy
|
|
});
|
|
|
|
}
|
|
}
|
|
|
|
},
|
|
removeData: function (index, stretch) {
|
|
var dataSet = this,
|
|
components = dataSet.components,
|
|
manager = dataSet.groupManager,
|
|
dataStore = components.data,
|
|
removeDataArr = components.removeDataArr || (components.removeDataArr = []);
|
|
|
|
stretch = stretch || 1;
|
|
index = index || 0;
|
|
|
|
if (index < 0) {
|
|
index = 0;
|
|
}
|
|
components.removeDataArr = removeDataArr = removeDataArr.concat(dataStore.splice(index, stretch));
|
|
manager._clearConnectors();
|
|
},
|
|
_dragUp: function (event) {
|
|
var element = this,
|
|
data = element.data('drag-options'),
|
|
dataset = data.dataset,
|
|
chart = dataset.chart,
|
|
dataStore = dataset.components.data,
|
|
dataObj = data.dataObj,
|
|
ele = dataObj.graphics.element,
|
|
groupManager = data.dataset.groupManager,
|
|
startConnectors,
|
|
endConnectors,
|
|
sourceEvent = 'dataplotdragend',
|
|
fireClick = ele.data('fire_click_event'),
|
|
config = dataObj.config,
|
|
canvasTop = chart.config.canvasTop,
|
|
canvasLeft = chart.config.canvasLeft,
|
|
dragStart = dataObj.config.dragStart || {},
|
|
yAxis = dataset.yAxis,
|
|
i,
|
|
setObj,
|
|
len,
|
|
eventCord,
|
|
eventArgs,
|
|
cloneText = dataObj.graphics.cloneText,
|
|
graphics = dataset.groupManager.graphics,
|
|
xAxis = chart.components.xAxis[0],
|
|
updateObj = {},
|
|
fromObj,
|
|
toObj,
|
|
datasetIndex,
|
|
connectorSet,
|
|
connector,
|
|
cloneGraphic = dataObj.graphics.cloneGraphic,
|
|
cloneImage = dataObj.graphics.cloneImage,
|
|
drawNodeConnectors = function (connectorsObj) {
|
|
var i;
|
|
if (!connectorsObj) {
|
|
return;
|
|
}
|
|
for (i in connectorsObj) {
|
|
connector = connectorsObj[i];
|
|
if (connector) {
|
|
datasetIndex = connector.config.datasetIndex;
|
|
fromObj = connector.config.fromPointObj;
|
|
toObj = connector.config.toPointObj;
|
|
connectorSet = groupManager.connectorSet[datasetIndex];
|
|
|
|
if (connectorSet) {
|
|
connectorSet && connectorSet.connectors.drawConnector(connector, fromObj, toObj);
|
|
}
|
|
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
graphics.waitElement && graphics.waitElement.hide();
|
|
clearLongPress.call(this);
|
|
ele.data('mousedown', 0);
|
|
fireClick && plotEventHandler.call(ele, chart, event);
|
|
if (dragStart.draged) {
|
|
dragStart.origX += dragStart.lastDx;
|
|
dragStart.origY += dragStart.lastDy;
|
|
dataObj.config._xPos = dragStart.xPos + dragStart.lastDx;
|
|
dataObj.config._yPos = dragStart.yPos + dragStart.lastDy;
|
|
updateObj.x = xAxis.getValue(dataObj.config._xPos - canvasLeft);
|
|
updateObj.y = yAxis.getValue(dataObj.config._yPos - canvasTop);
|
|
updateObj.update = true;
|
|
for (i = 0, len = dataStore.length; i < len; i++) {
|
|
setObj = dataStore[i];
|
|
if (dataObj.config.id === setObj.config.id) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
dataset.updatePointConfig(updateObj, i);
|
|
eventArgs = ele.data(EVENTARGS);
|
|
eventArgs.x = updateObj.x;
|
|
eventArgs.y = updateObj.y;
|
|
dataset._drawNode(i);
|
|
// dataset.drawTracker(i, i + 1);
|
|
startConnectors = dataObj.config.startConnectors;
|
|
endConnectors = dataObj.config.endConnectors;
|
|
drawNodeConnectors(startConnectors);
|
|
drawNodeConnectors(endConnectors);
|
|
eventCord = getMouseCoordinate(chart.linkedItems.container, event);
|
|
eventCord.sourceEvent = sourceEvent;
|
|
// Fire the ChartUpdated event
|
|
lib.raiseEvent('chartupdated', extend2(eventCord, eventArgs),
|
|
chart.chartInstance);
|
|
|
|
// groupManager.draw();
|
|
dragStart.draged = false;
|
|
}
|
|
cloneText && cloneText.hide();
|
|
cloneGraphic && cloneGraphic.hide();
|
|
cloneImage && cloneImage.hide();
|
|
delete config.dragStart;
|
|
|
|
},
|
|
getDataLimits: function () {
|
|
var conf = this.config;
|
|
return {
|
|
max : conf.yMax,
|
|
min : conf.yMin,
|
|
xMax : conf.xMax,
|
|
xMin : conf.xMin
|
|
};
|
|
}
|
|
}, 'Area']);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-connector',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
|
|
//strings
|
|
preDefStr = lib.preDefStr,
|
|
|
|
configStr = preDefStr.configStr,
|
|
BLANK = lib.BLANKSTRING,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
parseTooltext = lib.parseTooltext,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
getValidValue = lib.getValidValue,
|
|
pluckNumber = lib.pluckNumber,
|
|
// getDefinedColor = lib.getDefinedColor,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
getDashStyle = lib.getDashStyle, // returns dashed style of a line series
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
NONE = 'none',
|
|
// The default value for stroke-dash attribute.
|
|
DASH_DEF = NONE,
|
|
POINTER = 'pointer',
|
|
EVENTARGS = 'eventArgs',
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
schedular = lib.schedular,
|
|
// CRISP = 'crisp',
|
|
M = 'M',
|
|
L = 'L',
|
|
math = Math,
|
|
mathSin = math.sin,
|
|
mathCos = math.cos,
|
|
mathAbs = math.abs,
|
|
// getColumnColor = lib.graphics.getColumnColor,
|
|
getFirstColor = lib.getFirstColor,
|
|
HUNDREDSTRING = lib.HUNDREDSTRING,
|
|
plotEventHandler = lib.plotEventHandler,
|
|
|
|
//add the tools thats are requared
|
|
SHAPE_RECT = lib.SHAPE_RECT,
|
|
OPTIONSTR = '<option>',
|
|
OPTIONCLOSESTR = '</option>',
|
|
CLEAR_TIME_1000 = 1000,
|
|
clearLongPress = function() {
|
|
var ele = this;
|
|
ele.data('move', false);
|
|
clearTimeout(ele._longpressactive);
|
|
delete ele._longpressactive;
|
|
};
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'Connector', {
|
|
type: 'connector',
|
|
configure: function () {
|
|
var connectors = this,
|
|
chartObj = connectors.chart,
|
|
rawData = chartObj.jsonData,
|
|
chartAttr = rawData.chart,
|
|
conf = connectors.config,
|
|
dataStore = connectors.components.data || (connectors.components.data = []),
|
|
dataStoreLen,
|
|
connectorsObj = connectors.JSONData,
|
|
connectorsArr = connectorsObj.connector,
|
|
length = connectorsArr && connectorsArr.length,
|
|
index,
|
|
seriesConnector,
|
|
HUNDRED = HUNDREDSTRING,
|
|
parseUnsafeString = lib.parseUnsafeString;
|
|
|
|
conf.connectorsTooltext = getValidValue(parseUnsafeString(pluck(
|
|
connectorsObj.connectortooltext, chartAttr.connectortooltext)));
|
|
|
|
//Extract attributes of this node.
|
|
conf.stdThickness = pluckNumber(connectorsObj.stdthickness, 1);
|
|
conf.conColor = getFirstColor(pluck(connectorsObj.color, 'FF5904'));
|
|
conf.conAlpha = pluck(connectorsObj.alpha, HUNDRED);
|
|
conf.conDashGap = pluckNumber(connectorsObj.dashgap, 5);
|
|
conf.conDashLen = pluckNumber(connectorsObj.dashlen, 5);
|
|
conf.conDashed = Boolean(pluckNumber(connectorsObj.dashed, 0));
|
|
conf.arrowAtStart = Boolean(pluckNumber(connectorsObj.arrowatstart, 1));
|
|
conf.arrowAtEnd = Boolean(pluckNumber(connectorsObj.arrowatend, 1));
|
|
conf.conStrength = pluckNumber(connectorsObj.strength, 1);
|
|
conf.toolTipSepChar = pluck(chartAttr.tooltipsepchar, ' - ');
|
|
seriesConnector = connectors.connector;
|
|
conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
|
|
conf.viewMode = pluckNumber(chartAttr.viewmode, 1);
|
|
|
|
dataStoreLen = dataStore.length;
|
|
|
|
if (dataStoreLen > length) {
|
|
dataStore.splice(length, dataStoreLen - length);
|
|
}
|
|
conf._refreshData = true;
|
|
for (index = 0; index < length; index += 1) {
|
|
this._setConfigure(index, connectorsArr[index]);
|
|
}
|
|
conf._refreshData = true;
|
|
},
|
|
_setConfigure: function (index, connectorObj) {
|
|
//connector label.
|
|
var dataset = this,
|
|
connectorStore = dataset.components.data,
|
|
connObj = connectorStore[index] || (connectorStore[index] = connectorStore[index] = {}),
|
|
conf = dataset.config,
|
|
chartObj = dataset.chart,
|
|
connectorLabel = parseUnsafeString(pluck(connectorObj.label, connectorObj.name)),
|
|
setConAlpha = pluck(connectorObj.alpha, conf.conAlpha),
|
|
smartLabel = chartObj.linkedItems.smartLabel,
|
|
tooltipSepChar = conf.toolTipSepChar,
|
|
defToolTextMacro = '$fromLabel' + tooltipSepChar + '$toLabel',
|
|
setConColor = {
|
|
FCcolor: {
|
|
color: getFirstColor(pluck(connectorObj.color, conf.conColor)),
|
|
alpha: setConAlpha
|
|
}
|
|
},
|
|
toolText,
|
|
config,
|
|
labelTextObj,
|
|
connectorsTooltext = conf.connectorsTooltext,
|
|
connectorToolText = getValidValue(parseUnsafeString(pluck(connectorObj.tooltext,
|
|
connectorsTooltext)));
|
|
|
|
smartLabel.useEllipsesOnOverflow(chartObj.config.useEllipsesWhenOverflow);
|
|
labelTextObj = smartLabel.getOriSize(connectorLabel);
|
|
config = connObj.config = connObj.config || (connObj.config = {});
|
|
!connObj.graphics && (connObj.graphics = {});
|
|
//create the tooltext
|
|
if (!conf.showTooltip) {
|
|
toolText = false;
|
|
} else { //determine the tooltext then
|
|
toolText = pluck(connectorToolText, connectorLabel ?
|
|
'$label' : defToolTextMacro);
|
|
}
|
|
config = connObj.config = {
|
|
_options: connectorObj,
|
|
id: pluck(connectorObj.id, index).toString(),
|
|
from: pluck(connectorObj.from, BLANK),
|
|
to: pluck(connectorObj.to, BLANK),
|
|
label: connectorLabel,
|
|
toolText: toolText,
|
|
customToolText: connectorToolText,
|
|
color: setConColor,
|
|
index: index,
|
|
dashStyle: Boolean(pluckNumber(connectorObj.dashed, conf.conDashed)) ?
|
|
getDashStyle(pluckNumber(connectorObj.dashlen, conf.conDashLen),
|
|
pluckNumber(connectorObj.dashgap, conf.conDashGap), conf.stdThickness) : DASH_DEF,
|
|
dashed: connectorObj.dashed,
|
|
dashlen: connectorObj.dashlen,
|
|
dashgap: connectorObj.dashgap,
|
|
arrowAtStart: Boolean(pluckNumber(connectorObj.arrowatstart, conf.arrowAtStart)),
|
|
arrowAtEnd: Boolean(pluckNumber(connectorObj.arrowatend, conf.arrowAtEnd)),
|
|
conStrength: pluckNumber(connectorObj.strength, conf.conStrength),
|
|
link: connectorObj.link,
|
|
stdThickness: conf.stdThickness,
|
|
labelWidth: labelTextObj.widht,
|
|
labelHeight: labelTextObj.height
|
|
};
|
|
config.datasetIndex = dataset.index;
|
|
config.add = connectorObj.add;
|
|
config.update = connectorObj.update;
|
|
if (conf._refreshData) {
|
|
delete connObj.removed;
|
|
}
|
|
},
|
|
init: function (jsonData) {
|
|
var dataSet = this,
|
|
chart = dataSet.chart;
|
|
dataSet.yAxis = chart.components.yAxis[0];
|
|
dataSet.components = {
|
|
|
|
};
|
|
|
|
dataSet.graphics = {
|
|
|
|
};
|
|
|
|
dataSet.JSONData = jsonData;
|
|
dataSet.configure();
|
|
},
|
|
draw: function () {
|
|
var connectors = this,
|
|
chart = connectors.chart,
|
|
manager = connectors.groupManager,
|
|
conf = connectors.config,
|
|
chartObj = connectors.chart,
|
|
chartComp = chartObj.components,
|
|
chartGraphics = chart.graphics,
|
|
nodes = manager.nodes,
|
|
connectorStore = connectors.components.data,
|
|
connector,
|
|
fromId,
|
|
toId,
|
|
paper = chartComp.paper,
|
|
jobList = chart.getJobList(),
|
|
datasetGroup = chartGraphics.datasetGroup,
|
|
fromPointObj,
|
|
toPointObj,
|
|
style = chart.config.dataLabelStyle,
|
|
graphics,
|
|
i,
|
|
length = connectorStore.length,
|
|
removeDataArr = connectors.components.removeDataArr || [],
|
|
removeDataArrLen = removeDataArr.length,
|
|
connectorsGroup,
|
|
config;
|
|
|
|
if (!connectorsGroup) {
|
|
connectorsGroup = connectors.graphics.connectorGroup =
|
|
connectors.graphics.connectorGroup || paper.group('connectorGroup').insertBefore(datasetGroup);
|
|
}
|
|
|
|
if (conf.showTooltip) {
|
|
connectorsGroup.trackTooltip(true);
|
|
}
|
|
conf.cleared = false;
|
|
connectorsGroup.css(style);
|
|
for (i = 0; i < length; i++) {
|
|
connector = connectorStore[i];
|
|
config = connector.config;
|
|
graphics = connector.graphics || (connector.graphics = {});
|
|
fromId = config.from;
|
|
toId = config.to;
|
|
fromPointObj = nodes[fromId];
|
|
toPointObj = nodes[toId];
|
|
if (fromPointObj && toPointObj && config.deleted !== true) {
|
|
connectors.drawConnector(connector, fromPointObj, toPointObj, i);
|
|
}
|
|
}
|
|
// For first time render label is drawn in a separate thread
|
|
connectors.drawn !== true && jobList.labelDrawID.push(schedular.addJob(connectors.drawLabel, connectors,
|
|
[], lib.priorityList.label));
|
|
connectors.drawn = true;
|
|
|
|
for (i = 0; i < removeDataArrLen; i++) {
|
|
connectors._removeDataVisuals(removeDataArr.shift());
|
|
}
|
|
},
|
|
mouseDown: function () {
|
|
var ele = this,
|
|
config = ele.data(configStr),
|
|
dataset = ele.data('dataset'),
|
|
manager = dataset.groupManager,
|
|
chart = dataset.chart,
|
|
conf = dataset.config,
|
|
options = config || {};
|
|
|
|
ele._longpressactive = clearTimeout(ele._longpressactive);
|
|
|
|
// Whether to fire the click event ot not
|
|
ele.data('fire_click_event', 1);
|
|
|
|
ele._longpressactive = setTimeout(function() {
|
|
|
|
// Whether to fire the click event ot not
|
|
ele.data('fire_click_event', 0);
|
|
|
|
if (!ele.data('viewMode')) {
|
|
//add a selection method for start and end
|
|
manager.showConnectorUpdateUI(chart, {
|
|
fromid: {
|
|
val: options.from,
|
|
innerHTML: OPTIONSTR + options.from + OPTIONCLOSESTR,
|
|
disabled: true
|
|
},
|
|
toid: {
|
|
val: options.to,
|
|
innerHTML: OPTIONSTR + options.to + OPTIONCLOSESTR,
|
|
disabled: true
|
|
},
|
|
datasetIndex: dataset.index,
|
|
index: config.index,
|
|
arratstart: {
|
|
val: Boolean(pluckNumber(options.arrowatstart, 1))
|
|
},
|
|
arratend: {
|
|
val: Boolean(pluckNumber(options.arrowatend, 1))
|
|
},
|
|
dashed: {
|
|
val: pluckNumber(options.dashed)
|
|
},
|
|
dashgap: {
|
|
val: options.dashgap
|
|
},
|
|
dashlen: {
|
|
val: options.dashlen
|
|
},
|
|
label: {
|
|
val: options.label
|
|
},
|
|
tooltext: {
|
|
val: options.tooltext
|
|
},
|
|
id: {
|
|
val: conf.id,
|
|
disabled: true
|
|
},
|
|
strength: {
|
|
val: options.conStrength
|
|
},
|
|
alpha: {
|
|
val: options.alpha
|
|
},
|
|
color: {
|
|
val: options.color.FCcolor.color
|
|
}
|
|
}, true);
|
|
}
|
|
}, CLEAR_TIME_1000);
|
|
},
|
|
mousemove: function() {
|
|
// Whether to fire the click event ot not
|
|
this.data('fire_click_event', 0);
|
|
clearLongPress.call(this);
|
|
},
|
|
mouseup: function(data) {
|
|
var ele = this,
|
|
dataset = ele.data('dataset'),
|
|
chart = dataset.chart;
|
|
|
|
clearLongPress.call(ele);
|
|
plotEventHandler.call(ele, chart, data, 'ConnectorClick');
|
|
},
|
|
hoverIn: function(data) {
|
|
var ele = this,
|
|
dataset = ele.data('dataset'),
|
|
chart = dataset.chart;
|
|
plotEventHandler.call(ele, chart, data, 'ConnectorRollover');
|
|
},
|
|
hoverOut: function(data) {
|
|
var ele = this,
|
|
dataset = ele.data('dataset'),
|
|
chart = dataset.chart;
|
|
plotEventHandler.call(ele, chart, data, 'ConnectorRollout');
|
|
},
|
|
drawConnector: function (connector, fromPointObj, toPointObj) {
|
|
if (connector.removed) {
|
|
return;
|
|
}
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
fromX,
|
|
toX,
|
|
fromY,
|
|
toY,
|
|
strokeWidth,
|
|
textBgColor,
|
|
paper = chart.components.paper,
|
|
NumberFormatter = chart.components.numberFormatter,
|
|
pathArr,
|
|
graphics = connector.graphics,
|
|
startConnectors,
|
|
endConnectors,
|
|
element,
|
|
animationObj = chart.get('config', 'animationObj'),
|
|
connectorsGroup = dataset.graphics.connectorGroup,
|
|
dummyAnimObj = animationObj.animObj,
|
|
dummyAnimElem = animationObj.dummyObj,
|
|
animType = animationObj.animType,
|
|
animationDuration = animationObj.duration,
|
|
config = connector.config,
|
|
label,
|
|
tooltext = config.toolText,
|
|
fromConf,
|
|
toConf,
|
|
eventArgs = config.eventArgs || (config.eventArgs = {}),
|
|
color,
|
|
conf = dataset.config,
|
|
pool = dataset.components.pool || {},
|
|
id;
|
|
|
|
config.fromPointObj = fromPointObj;
|
|
config.toPointObj = toPointObj;
|
|
fromConf = fromPointObj.config;
|
|
toConf = toPointObj.config;
|
|
config.fromX = fromX = fromConf._xPos;
|
|
config.fromY = fromY = fromConf._yPos;
|
|
config.toX = toX = toConf._xPos;
|
|
config.toY = toY = toConf._yPos;
|
|
config._labelX = (fromX + toX) / 2;
|
|
config._labelY = (fromY + toY) / 2;
|
|
config.strokeWidth = strokeWidth = (config.conStrength * config.stdThickness);
|
|
color = config.color;
|
|
config.textBgColor = textBgColor = color && color.FCcolor &&
|
|
color.FCcolor.color;
|
|
label = eventArgs.label = config.label;
|
|
eventArgs.arrowAtStart = config.arrowAtStart;
|
|
eventArgs.arrowAtEnd = config.arrowAtEnd;
|
|
eventArgs.link = config.link;
|
|
eventArgs.id = config.id;
|
|
eventArgs.fromNodeId = fromConf.id;
|
|
eventArgs.toNodeId = toConf.id;
|
|
tooltext = config.toolText = parseTooltext(config.toolText, [3, 83,
|
|
84, 85, 86, 87, 88, 89, 90, 91, 92
|
|
], {
|
|
label: config.label,
|
|
fromXValue: NumberFormatter.dataLabels(fromPointObj.config.x),
|
|
fromYValue: NumberFormatter.dataLabels(fromPointObj.config.y),
|
|
fromXDataValue: fromPointObj.config.x,
|
|
fromYDataValue: fromPointObj.config.y,
|
|
fromLabel: pluck(fromPointObj.config.displayValue, fromPointObj.config.id),
|
|
toXValue: NumberFormatter.dataLabels(toPointObj.config.x),
|
|
toYValue: NumberFormatter.dataLabels(toPointObj.config.y),
|
|
toXDataValue: toPointObj.config.x,
|
|
toYDataValue: toPointObj.config.y,
|
|
toLabel: pluck(toPointObj.config.displayValue, toPointObj.config.id)
|
|
});
|
|
|
|
|
|
fromConf = fromPointObj.config;
|
|
toConf = toPointObj.config;
|
|
|
|
startConnectors = fromConf.startConnectors;
|
|
endConnectors = toConf.endConnectors;
|
|
|
|
id = connector.config.id + '-' + fromConf.id + '-' + toConf.id;
|
|
|
|
startConnectors[id] = connector;
|
|
endConnectors[id] = connector;
|
|
|
|
pathArr = this._getlinePath(connector);
|
|
element = graphics.graphic;
|
|
//draw the line
|
|
if (!graphics.graphic) {
|
|
if (pool.graphic && pool.graphic.path && pool.graphic.path.length) {
|
|
element = graphics.graphic = pool.graphic.path.shift();
|
|
}
|
|
else {
|
|
element = graphics.graphic = paper.path(connectorsGroup)
|
|
.mousedown(dataset.mouseDown)
|
|
.mousemove(dataset.mousemove)
|
|
.mouseup(dataset.mouseup)
|
|
.hover(dataset.hoverIn, dataset.hoverOut);
|
|
element.attr({
|
|
path: pathArr
|
|
});
|
|
}
|
|
}
|
|
|
|
element.show().animateWith(dummyAnimElem, dummyAnimObj, {
|
|
path: pathArr
|
|
}, animationDuration, animType);
|
|
element.attr({
|
|
'stroke-width': strokeWidth,
|
|
ishot: true,
|
|
'stroke-dasharray': config.dashStyle,
|
|
cursor: config.link ? POINTER : BLANKSTRING,
|
|
stroke: toRaphaelColor(color)
|
|
})
|
|
.data(EVENTARGS, eventArgs)
|
|
.data('viewMode', conf.viewMode)
|
|
.data(configStr, config)
|
|
.data('dataset', dataset)
|
|
.tooltip(tooltext);
|
|
// If this is not the first render then label is drawn instantly otherwise it is drawn in
|
|
// another thread for performance optimization
|
|
dataset.drawn && dataset.drawLabel(connector);
|
|
},
|
|
drawLabel: function (connector) {
|
|
var dataset = this,
|
|
groupManager = dataset.groupManager,
|
|
nodes = groupManager.nodes,
|
|
conf = dataset.config,
|
|
chart = dataset.chart,
|
|
paper = chart.components.paper,
|
|
animationObj = chart.get('config', 'animationObj'),
|
|
connectorsGroup = dataset.graphics.connectorGroup,
|
|
dummyAnimObj = animationObj.animObj,
|
|
dummyAnimElem = animationObj.dummyObj,
|
|
animType = animationObj.animType,
|
|
animationDuration = animationObj.duration,
|
|
config,
|
|
label,
|
|
tooltext,
|
|
labelAttrs,
|
|
style = chart.config.dataLabelStyle,
|
|
labelElement,
|
|
graphics,
|
|
connectorObj,
|
|
i,
|
|
labelX,
|
|
labelY,
|
|
textBgColor,
|
|
dataStore = dataset.components.data,
|
|
pool = dataset.components.pool || {},
|
|
len = dataStore.length,
|
|
fromPointObj,
|
|
toPointObj,
|
|
fromId,
|
|
toId,
|
|
drawIndividualLabel = function (connector) {
|
|
config = connector.config;
|
|
tooltext = config.toolText;
|
|
graphics = connector.graphics;
|
|
label = config.label;
|
|
labelX = config._labelX;
|
|
labelY = config._labelY;
|
|
fromId = config.from;
|
|
toId = config.to;
|
|
fromPointObj = nodes[fromId];
|
|
toPointObj = nodes[toId];
|
|
textBgColor = config.textBgColor;
|
|
// if (label && fromPointObj && toPointObj) {
|
|
// labelElement = graphics.text = graphics.text || (pool.text && pool.text.shift());
|
|
// =======
|
|
// textBgColor = config.textBgColor;
|
|
if (label) {
|
|
labelElement = graphics.text = graphics.text || (pool.element && pool.element.text &&
|
|
pool.element.text.shift());
|
|
labelAttrs = {
|
|
text: label,
|
|
fill: style.color,
|
|
ishot: true,
|
|
direction: BLANKSTRING,
|
|
cursor: config.link ? POINTER : BLANKSTRING,
|
|
'text-bound': [pluck(style.backgroundColor, textBgColor),
|
|
pluck(style.borderColor, textBgColor), 1, '2'
|
|
]
|
|
};
|
|
|
|
// Drawing the connector Label
|
|
if (!graphics.text) {
|
|
labelAttrs.x = labelX;
|
|
labelAttrs.y = labelY;
|
|
graphics.text = labelElement = paper.text(labelAttrs, connectorsGroup)
|
|
.mousedown(dataset.mouseDown)
|
|
.mousemove(dataset.mousemove)
|
|
.mouseup(dataset.mouseup)
|
|
.hover(dataset.hoverIn, dataset.hoverOut);
|
|
}
|
|
else {
|
|
labelElement.show().animateWith(dummyAnimElem, dummyAnimObj, {
|
|
x: labelX,
|
|
y: labelY
|
|
}, animationDuration, animType);
|
|
labelElement.attr(labelAttrs);
|
|
}
|
|
labelElement.data(EVENTARGS, config.eventArgs)
|
|
.data('viewMode', conf.viewMode)
|
|
.data(configStr, config)
|
|
.data('dataset', dataset)
|
|
.tooltip(tooltext);
|
|
}
|
|
else {
|
|
graphics.text && graphics.text.hide();
|
|
}
|
|
};
|
|
|
|
if (connector) {
|
|
drawIndividualLabel(connector);
|
|
}
|
|
else {
|
|
for (i = 0; i < len; i++) {
|
|
connectorObj = dataStore[i];
|
|
drawIndividualLabel(connectorObj);
|
|
}
|
|
}
|
|
},
|
|
// Get jsondata of connector dataset
|
|
getJSONData: function () {
|
|
var dataset = this,
|
|
dataStore = dataset.components.data,
|
|
len = dataStore.length,
|
|
jsonData = [],
|
|
dataObj,
|
|
i;
|
|
for (i = 0; i < len; i++) {
|
|
dataObj = dataStore[i];
|
|
if (!dataObj.removed) {
|
|
if (dataObj.config._options) {
|
|
delete dataObj.config._options.update;
|
|
delete dataObj.config._options.add;
|
|
}
|
|
jsonData.push(dataObj.config._options);
|
|
}
|
|
}
|
|
return jsonData;
|
|
},
|
|
|
|
_updateFromPos: function (x, y) {
|
|
var connector = this;
|
|
connector.fromX = x;
|
|
connector.fromY = y;
|
|
connector.graphic && connector.graphic.animate({
|
|
path: connector.getlinePath()
|
|
});
|
|
|
|
connector.text && connector.text.animate({
|
|
x: (connector.fromX + connector.toX) / 2,
|
|
y: (connector.fromY + connector.toY) / 2
|
|
});
|
|
},
|
|
|
|
_updateToPos: function (x, y) {
|
|
var connector = this;
|
|
connector.toX = x;
|
|
connector.toY = y;
|
|
connector.graphic && connector.graphic.animate({
|
|
path: connector.getlinePath()
|
|
});
|
|
|
|
connector.text && connector.text.animate({
|
|
x: (connector.fromX + connector.toX) / 2,
|
|
y: (connector.fromY + connector.toY) / 2
|
|
});
|
|
},
|
|
|
|
_getlinePath: function (connector) {
|
|
var config = connector.config,
|
|
fromPointObj = config.fromPointObj,
|
|
toPointObj = config.toPointObj,
|
|
fromX = config.fromX,
|
|
fromY = config.fromY,
|
|
toX = config.toX,
|
|
toY = config.toY,
|
|
path = [M, fromX, fromY],
|
|
pointConfig;
|
|
|
|
if (config.arrowAtStart) {
|
|
pointConfig = fromPointObj.config;
|
|
if (pointConfig.shapeType === SHAPE_RECT) {
|
|
path = path.concat(this._drawArrow(fromX, fromY, toX, toY,
|
|
pointConfig.shapeArg.width, pointConfig.shapeArg.height));
|
|
} else {
|
|
path = path.concat(this._drawArrow(fromX, fromY, toX, toY,
|
|
pointConfig.shapeArg.radius));
|
|
}
|
|
}
|
|
|
|
// Calculating path for connector Arrow
|
|
if (config.arrowAtEnd) {
|
|
pointConfig = toPointObj.config;
|
|
if (pointConfig.shapeType === SHAPE_RECT) {
|
|
path = path.concat(this._drawArrow(toX, toY, fromX, fromY,
|
|
pointConfig.shapeArg.width, pointConfig.shapeArg.height));
|
|
} else {
|
|
path = path.concat(this._drawArrow(toX, toY, fromX, fromY,
|
|
pointConfig.shapeArg.radius));
|
|
}
|
|
}
|
|
path.push(L, toX, toY);
|
|
return path;
|
|
},
|
|
|
|
_drawArrow: function (X1, Y1, X2, Y2, R, H) {
|
|
var tanganent = (Y1 - Y2) / (X1 - X2),
|
|
angle = math.atan(tanganent),
|
|
PX, PY, RHlf, HHlf,
|
|
arr = [];
|
|
|
|
|
|
//make all angle as positive
|
|
if (angle < 0) {
|
|
angle = (2 * math.PI) + angle;
|
|
}
|
|
if (Y2 > Y1) { ///PI >angle > 0
|
|
if ((X2 >= X1 && angle > math.PI) || (X2 < X1 && angle > math.PI)) {
|
|
angle = angle - math.PI;
|
|
}
|
|
} else { /// PI <= angle < 360 || angle == 0
|
|
//angle may not be 360 in that case it will be 0 as atan work
|
|
if ((X2 >= X1 && angle < math.PI && angle !== 0) || (X2 < X1 && angle < math.PI)) {
|
|
angle = angle + math.PI;
|
|
}
|
|
}
|
|
|
|
if (typeof H == 'undefined') {
|
|
///arrow start point
|
|
PX = X1 + (R * mathCos(angle));
|
|
PY = Y1 + (R * mathSin(angle));
|
|
} else { ///rectangle
|
|
RHlf = mathAbs(R) / 2;
|
|
HHlf = mathAbs(H) / 2;
|
|
|
|
//asume it will intersect a vertical side
|
|
PX = X1 + (RHlf = X1 < X2 ? RHlf : -RHlf);
|
|
PY = Y1 + (RHlf * math.tan(angle));
|
|
//validate PY
|
|
//if not validate then it will cross the horizontal axis
|
|
if (mathAbs(Y1 - PY) > mathAbs(HHlf)) {
|
|
PY = Y1 + (HHlf = Y1 < Y2 ? HHlf : -HHlf);
|
|
PX = X1 + (HHlf / math.tan(angle));
|
|
}
|
|
}
|
|
|
|
arr.push(L, PX, PY,
|
|
///arrowone half
|
|
PX + (10 * mathCos(angle + 0.79)),
|
|
PY + (10 * mathSin(angle + 0.79)),
|
|
///arrowone half
|
|
M, PX + (10 * mathCos(angle - 0.79)),
|
|
PY + (10 * mathSin(angle - 0.79)),
|
|
//return to th eedege
|
|
L, PX, PY);
|
|
|
|
return arr;
|
|
},
|
|
|
|
removeData: function (index, stretch) {
|
|
var dataset = this,
|
|
components = dataset.components,
|
|
dataStore = components.data,
|
|
removeDataArr;
|
|
|
|
if (index < 0) {
|
|
index = 0;
|
|
}
|
|
components.removeDataArr = removeDataArr = dataStore.splice(index, stretch);
|
|
|
|
}
|
|
},'Dragnode']);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-dragablelabels',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
|
|
//strings
|
|
preDefStr = lib.preDefStr,
|
|
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
visibleStr = preDefStr.visibleStr,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
pluckNumber = lib.pluckNumber,
|
|
// getDefinedColor = lib.getDefinedColor,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
extend2 = lib.extend2, //old: jarendererExtend / margecolone
|
|
getDashStyle = lib.getDashStyle, // returns dashed style of a line series
|
|
isIE = lib.isIE,
|
|
dropHash = lib.regex.dropHash,
|
|
HASHSTRING = lib.HASHSTRING,
|
|
UNDEFINED,
|
|
NONE = 'none',
|
|
// The default value for stroke-dash attribute.
|
|
DASH_DEF = NONE,
|
|
// getLinkAction = lib.getLinkAction,
|
|
POSITION_CENTER = 'center',
|
|
// NumberFormatter = lib.NumberFormatter,
|
|
hashify = lib.hashify,
|
|
PXSTRING = 'px',
|
|
EVENTARGS = 'eventArgs',
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
schedular = lib.schedular,
|
|
TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
|
|
PX = PXSTRING,
|
|
setLineHeight = lib.setLineHeight,
|
|
// renderer = chartAPI,
|
|
// COMMASPACE = lib.COMMASPACE,
|
|
getMouseCoordinate = lib.getMouseCoordinate,
|
|
plotEventHandler = lib.plotEventHandler,
|
|
CLEAR_TIME_1000 = 1000;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'DragableLabels', {
|
|
configure: function () {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
jsonData = chart.jsonData,
|
|
chartAttr = jsonData.chart,
|
|
conf = dataset.config,
|
|
setDataArr = dataset.JSONData || [],
|
|
len = setDataArr.length,
|
|
dataStoreLen,
|
|
dataStore = dataset.components.data,
|
|
i;
|
|
conf.viewMode = pluckNumber(chartAttr.viewmode, 0);
|
|
if (!dataStore) {
|
|
dataStore = dataset.components.data = [];
|
|
}
|
|
dataStoreLen = dataStore.length;
|
|
|
|
if (dataStoreLen > len) {
|
|
dataStore.splice(len, dataStoreLen - len);
|
|
}
|
|
|
|
for (i = 0; i < len; i++) {
|
|
dataset._setConfigure(i);
|
|
}
|
|
|
|
},
|
|
_setConfigure: function (index, updateObj) {
|
|
var dataset = this,
|
|
setDataArr = dataset.JSONData,
|
|
chart = dataset.chart,
|
|
setData = updateObj ? updateObj : setDataArr[index],
|
|
dataStore = dataset.components.data,
|
|
dataObj,
|
|
text,
|
|
style = chart.config.style,
|
|
inCanvasStyle = style.inCanvasStyle,
|
|
inCanFontSize = inCanvasStyle.fontSize,
|
|
labelColor,
|
|
labelBGColor,
|
|
config,
|
|
labelBDColor,
|
|
alpha,
|
|
labelFontSize;
|
|
dataObj = dataStore[index];
|
|
!dataObj && (dataObj = dataStore[index] = {});
|
|
!dataObj.graphics && (dataObj.graphics = {});
|
|
|
|
config = dataObj.config = dataObj.config || (dataObj.config = {});
|
|
text = parseUnsafeString(pluck(setData.text, setData.label));
|
|
config._options = setData;
|
|
config.add = setData.add;
|
|
if (text) {
|
|
config.text = text;
|
|
config.x = setData.x || 0;
|
|
config.y = setData.y || 0;
|
|
config.labelFontSize = labelFontSize = pluckNumber(setData.fontsize, inCanFontSize);
|
|
|
|
config.labelColor = labelColor = hashify(pluck(setData.color,
|
|
inCanvasStyle.color));
|
|
config.alpha = alpha = (pluckNumber(setData.alpha, 100)) / 100;
|
|
config.allowdrag = pluckNumber(setData.allowdrag, 1);
|
|
config.padding = pluckNumber(setData.padding, 5);
|
|
|
|
// config.labelColor = labelColor = convertColor(pluck(setData.color, inCanvasStyle.color),
|
|
// pluckNumber(setData.alpha, 100));
|
|
|
|
if (setData.fontsize) {
|
|
config.labelCSS = {
|
|
fontSize: labelFontSize + PX
|
|
};
|
|
}
|
|
else {
|
|
config.labelCSS = UNDEFINED;
|
|
}
|
|
|
|
config.labelBGColor = labelBGColor = pluck(setData.bgcolor &&
|
|
setData.bgcolor.replace(dropHash, HASHSTRING));
|
|
config.labelBDColor = labelBDColor = pluck(setData.bordercolor &&
|
|
setData.bordercolor.replace(dropHash, HASHSTRING));
|
|
config.link = setData.link;
|
|
config.allowDrag = pluckNumber(setData.allowdrag, 1);
|
|
config.borderThickness = setData.borderthickness;
|
|
config.dashLen = setData.dashlen;
|
|
config.dashGap = setData.dashgap;
|
|
config.dashed = setData.dashed;
|
|
config.radius = setData.radius;
|
|
}
|
|
},
|
|
init: function (jsonData) {
|
|
var dataSet = this,
|
|
chart = dataSet.chart;
|
|
dataSet.yAxis = chart.components.yAxis[0];
|
|
dataSet.components = {
|
|
|
|
};
|
|
|
|
dataSet.graphics = {
|
|
|
|
};
|
|
|
|
dataSet.JSONData = jsonData;
|
|
dataSet.configure();
|
|
},
|
|
// Get jsondata of dragable label dataset
|
|
getJSONData: function () {
|
|
var dataset = this,
|
|
dataStore = dataset.components.data,
|
|
len = dataStore.length,
|
|
jsonData = [],
|
|
dataObj,
|
|
i;
|
|
for (i = 0; i < len; i++) {
|
|
dataObj = dataStore[i];
|
|
if (!dataObj.removed) {
|
|
if (dataObj.config._options) {
|
|
jsonData.push(dataObj.config._options);
|
|
}
|
|
}
|
|
}
|
|
return jsonData;
|
|
},
|
|
draw: function () {
|
|
var dataset = this,
|
|
dataStore = dataset.components.data,
|
|
chart = dataset.chart,
|
|
jobList = chart.getJobList(),
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animationDuration = animationObj.duration,
|
|
animType = animationObj.animType,
|
|
dummyAnimElem = animationObj.dummyObj,
|
|
dummyAnimObj = animationObj.animObj,
|
|
paper = chart.components.paper,
|
|
yAxis = chart.components.yAxis[0],
|
|
xAxis = chart.components.xAxis[0],
|
|
SmartLabel = chart.linkedItems.smartLabel,
|
|
dataLabelsLayer = chart.graphics.datalabelsGroup,
|
|
trackerGroup = chart.graphics.trackerGroup,
|
|
style = chart.config.dataLabelStyle,
|
|
dashLen,
|
|
dashGap,
|
|
dashed,
|
|
x,
|
|
y,
|
|
color,
|
|
text,
|
|
bgColor,
|
|
borderColor,
|
|
padding,
|
|
config,
|
|
attr,
|
|
alpha,
|
|
dataObj,
|
|
allowDrag,
|
|
fontSize,
|
|
eventArgs,
|
|
radius,
|
|
element,
|
|
dim,
|
|
borderThickness,
|
|
len = dataStore.length,
|
|
lStyle,
|
|
removeDataArr = dataset.components.removeDataArr || [],
|
|
removeDataArrLen = removeDataArr.length,
|
|
pool = dataset.components.pool || {},
|
|
i,
|
|
trackerContainer,
|
|
dataLabelContainer,
|
|
labelCSS;
|
|
|
|
dataLabelContainer = dataset.graphics.dataLabelContainer = dataset.graphics.dataLabelContainer ||
|
|
paper.group('datalabels', dataLabelsLayer);
|
|
trackerContainer = dataset.graphics.trackerContainer = dataset.graphics.trackerContainer ||
|
|
paper.group('tracker', trackerGroup);
|
|
|
|
dataLabelContainer.css({
|
|
'font-weight': style.fontWeight,
|
|
'font-style': style.fontStyle,
|
|
'font-size': style.fontSize,
|
|
'font-family': style.fontFamily
|
|
});
|
|
|
|
for (i = 0; i < len; i++) {
|
|
dataObj = dataStore[i];
|
|
if (dataObj.removed) {
|
|
continue;
|
|
}
|
|
config = dataObj.config;
|
|
!dataObj.graphics && (dataObj.graphics = {});
|
|
config.index = i;
|
|
x = xAxis.getPixel(config.x);
|
|
y = yAxis.getPixel(config.y);
|
|
text = config.text;
|
|
bgColor = config.labelBGColor;
|
|
borderColor = config.labelBDColor;
|
|
padding = config.padding;
|
|
allowDrag = config.allowDrag;
|
|
fontSize = config.labelFontSize;
|
|
color = config.labelColor;
|
|
alpha = config.alpha;
|
|
radius = config.radius;
|
|
dashed = config.dashed;
|
|
borderThickness = config.borderThickness;
|
|
dashLen = config.dashLen;
|
|
dashGap = config.dashGap;
|
|
borderThickness = config.borderThickness;
|
|
labelCSS = config.labelCSS;
|
|
|
|
attr = {
|
|
x: x,
|
|
y: y,
|
|
text: text,
|
|
align: POSITION_CENTER,
|
|
fill: color,
|
|
'text-bound': [(bgColor || BLANKSTRING), (borderColor || BLANKSTRING),
|
|
pluckNumber(borderThickness, 1),
|
|
padding,
|
|
pluckNumber(radius, 0),
|
|
pluckNumber(dashed, 0) ?
|
|
getDashStyle(pluckNumber(dashLen, 5),
|
|
pluckNumber(dashGap, 4),
|
|
pluckNumber(borderThickness, 1)) :
|
|
DASH_DEF
|
|
],
|
|
visibility: visibleStr
|
|
};
|
|
|
|
lStyle = {
|
|
backgroundColor: bgColor,
|
|
borderColor: borderColor,
|
|
borderPadding: padding,
|
|
fontSize: fontSize + PXSTRING,
|
|
fontStyle: style.fontStyle,
|
|
fontWeight: style.fontWeight,
|
|
borderRadius: 0,
|
|
borderDash: DASH_DEF,
|
|
fontFamily: style.fontFamily
|
|
};
|
|
setLineHeight(lStyle);
|
|
SmartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
|
|
SmartLabel.setStyle(lStyle);
|
|
eventArgs = {
|
|
link: config.link,
|
|
text: text,
|
|
x: x,
|
|
y: y,
|
|
allowdrag: allowDrag,
|
|
sourceType: 'labelnode'
|
|
};
|
|
|
|
element = dataObj.graphics.element = dataObj.graphics.element ||
|
|
(pool.element && pool.element.text && pool.element.text.shift());
|
|
|
|
if (!element) {
|
|
element = dataObj.graphics.element = paper.text(attr, labelCSS, dataLabelContainer);
|
|
}
|
|
else {
|
|
// If label css was applied on this element and now label css is not given then remove css
|
|
if (config.labelCSSApplied && !labelCSS) {
|
|
element.removeCSS();
|
|
}
|
|
|
|
element.show()
|
|
.animateWith(dummyAnimElem, dummyAnimObj, attr, animationDuration, animType)
|
|
.css(labelCSS);
|
|
}
|
|
|
|
config.labelCSSApplied = labelCSS;
|
|
|
|
element.data('eventArgs', eventArgs);
|
|
dim = SmartLabel.getOriSize(text);
|
|
config.width = dim.width;
|
|
config.height = dim.height;
|
|
config.xPos = x;
|
|
config.yPos = y;
|
|
}
|
|
jobList.trackerDrawID.push(schedular.addJob(dataset.drawTracker, dataset, [],
|
|
lib.priorityList.tracker));
|
|
for (i = 0; i < removeDataArrLen; i++) {
|
|
dataset._removeDataVisuals(removeDataArr.shift());
|
|
}
|
|
|
|
},
|
|
removeData: function (index, stretch) {
|
|
var dataset = this,
|
|
components = dataset.components,
|
|
dataStore = components.data;
|
|
components.removeDataArr = dataStore.splice(index, stretch);
|
|
},
|
|
drawTracker: function () {
|
|
var dataset = this,
|
|
dataStore = dataset.components.data,
|
|
chart = dataset.chart,
|
|
paper = chart.components.paper,
|
|
manager = dataset.groupManager,
|
|
conf = dataset.config,
|
|
trackerGroup = dataset.graphics.trackerContainer,
|
|
len = dataStore.length,
|
|
dataObj,
|
|
config,
|
|
padding,
|
|
elemMouseDownFN = function(labelObj) { // Long press eve
|
|
var ele = this;
|
|
ele.data('fire_click_event', 1);
|
|
clearTimeout(ele._longpressactive);
|
|
ele._longpressactive = setTimeout(function() {
|
|
ele.data('fire_click_event', 0);
|
|
if (!ele.data('viewMode')) {
|
|
manager.showLabelDeleteUI(labelObj);
|
|
}
|
|
}, CLEAR_TIME_1000);
|
|
},
|
|
elemMouseMoveFN = function() {
|
|
// Whether to fire the click event ot not
|
|
var ele = this;
|
|
if (ele.data('fire_click_event')) {
|
|
ele.data('fire_click_event', 0);
|
|
manager.clearLongPress.call(this);
|
|
}
|
|
},
|
|
elemMouseUPFN = function(data) {
|
|
var ele = this,
|
|
fireClick = ele.data('fire_click_event');
|
|
manager.clearLongPress.call(ele);
|
|
if (fireClick) {
|
|
/**
|
|
*
|
|
* > Applicable to `dragnode` chart only.
|
|
*
|
|
* @event FusionCharts#labelClick
|
|
* @group chart-powercharts:dragnode
|
|
*
|
|
* @param {number} chartX - x-coordinate of the pointer relative to the chart.
|
|
* @param {number} chartY - y-coordinate of the pointer relative to the chart.
|
|
* @param {number} pageX - x-coordinate of the pointer relative to the page.
|
|
* @param {number} pageY - y-coordinate of the pointer relative to the page.
|
|
*
|
|
* @param {number} x - The x-value of the label node scaled as per the axis of the chart.
|
|
* @param {number} y - The y-value of the label node scaled as per the axis of the chart.
|
|
*
|
|
* @param {string} text - The text value of the label.
|
|
*/
|
|
plotEventHandler.call(ele, chart, data, 'LabelClick');
|
|
}
|
|
},
|
|
elemHoverFN = function(data) {
|
|
var ele = this;
|
|
/**
|
|
*
|
|
* > Applicable to `dragnode` chart only.
|
|
*
|
|
* @event FusionCharts#labelRollOver
|
|
* @group chart-powercharts:dragnode
|
|
*
|
|
* @param {number} chartX - x-coordinate of the pointer relative to the chart.
|
|
* @param {number} chartY - y-coordinate of the pointer relative to the chart.
|
|
* @param {number} pageX - x-coordinate of the pointer relative to the page.
|
|
* @param {number} pageY - y-coordinate of the pointer relative to the page.
|
|
*
|
|
* @param {number} x - The x-value of the label node scaled as per the axis of the chart.
|
|
* @param {number} y - The y-value of the label node scaled as per the axis of the chart.
|
|
*
|
|
* @param {string} text - The text value of the label.
|
|
*/
|
|
plotEventHandler.call(ele, chart, data, 'LabelRollover');
|
|
},
|
|
elemOutFN = function(data) {
|
|
var ele = this;
|
|
/**
|
|
*
|
|
* > Applicable to `dragnode` chart only.
|
|
*
|
|
* @event FusionCharts#labelRollOut
|
|
* @group chart-powercharts:dragnode
|
|
*
|
|
* @param {number} chartX - x-coordinate of the pointer relative to the chart.
|
|
* @param {number} chartY - y-coordinate of the pointer relative to the chart.
|
|
* @param {number} pageX - x-coordinate of the pointer relative to the page.
|
|
* @param {number} pageY - y-coordinate of the pointer relative to the page.
|
|
*
|
|
* @param {number} x - The x-value of the label node scaled as per the axis of the chart.
|
|
* @param {number} y - The y-value of the label node scaled as per the axis of the chart.
|
|
*
|
|
* @param {string} text - The text value of the label.
|
|
*/
|
|
plotEventHandler.call(ele, chart, data, 'LabelRollout');
|
|
},
|
|
eventArgs,
|
|
attr,
|
|
allowDrag,
|
|
text,
|
|
trackerElement,
|
|
x,
|
|
y,
|
|
width,
|
|
height,
|
|
dragMove = function(dx, dy, px, py, event) {
|
|
var ele = this;
|
|
dataset._labelDragMove.call(ele, dx, dy, px, py, chart, event);
|
|
},
|
|
dragStart = function(event) {
|
|
var ele = this;
|
|
dataset._labelDragStart.call(ele, event, chart);
|
|
},
|
|
dragUp = function(event) {
|
|
var ele = this;
|
|
dataset._labelDragUp.call(ele, event);
|
|
},
|
|
i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
dataObj = dataStore[i];
|
|
if (dataObj.removed) {
|
|
continue;
|
|
}
|
|
config = dataObj.config;
|
|
padding = config.padding || 0;
|
|
width = config.width;
|
|
height = config.height;
|
|
x = config.xPos - width / 2;
|
|
y = config.yPos - height / 2;
|
|
allowDrag = config.allowDrag;
|
|
text = config.text;
|
|
trackerElement = dataObj.graphics.trackerElement;
|
|
attr = {
|
|
x: x - padding,
|
|
y: y - padding,
|
|
width: width + padding * 2,
|
|
height: height + padding * 2,
|
|
cursor: config.allowDrag ? 'move' : BLANKSTRING,
|
|
fill: TRACKER_FILL,
|
|
stroke: TRACKER_FILL,
|
|
ishot: true
|
|
};
|
|
eventArgs = {
|
|
link: config.link,
|
|
text: text,
|
|
x: x,
|
|
y: y,
|
|
allowdrag: allowDrag,
|
|
sourceType: 'labelnode'
|
|
};
|
|
if (!trackerElement) {
|
|
trackerElement = dataObj.graphics.trackerElement = paper.rect(trackerGroup)
|
|
.mousedown(elemMouseDownFN)
|
|
.mousemove(elemMouseMoveFN)
|
|
.mouseup(elemMouseUPFN)
|
|
.data('viewMode', conf.viewMode)
|
|
.data(EVENTARGS, eventArgs)
|
|
.hover(elemHoverFN, elemOutFN)
|
|
.drag(dragMove, dragStart, dragUp);
|
|
}
|
|
trackerElement.attr(attr);
|
|
trackerElement.data('drag-options', {
|
|
index: i,
|
|
dataset: dataset
|
|
});
|
|
}
|
|
},
|
|
_labelDragStart: function () {
|
|
var ele = this,
|
|
bBox = ele.getBBox(),
|
|
data = ele.data('drag-options'),
|
|
dataset = data.dataset,
|
|
manager = dataset.groupManager,
|
|
index = data.index,
|
|
labelObj = dataset.components.data[index],
|
|
labelElement = labelObj.graphics.element,
|
|
dragStart = labelObj.dragStart = labelObj.dragStart || (labelObj.dragStart = {});
|
|
data.ox = labelElement.attr('x');
|
|
data.oy = labelElement.attr('y');
|
|
data.bBox = bBox;
|
|
dragStart.xPos = labelObj.config.xPos;
|
|
dragStart.yPos = labelObj.config.yPos;
|
|
dragStart.bBox = bBox;
|
|
ele.data('fire_click_event', 1);
|
|
ele.data('fire_dragend', 0);
|
|
clearTimeout(ele._longpressactive);
|
|
ele._longpressactive = setTimeout(function() {
|
|
ele.data('fire_click_event', 0);
|
|
if (!ele.data('viewMode')) {
|
|
manager.showLabelDeleteUI(labelObj);
|
|
}
|
|
}, CLEAR_TIME_1000);
|
|
},
|
|
_labelDragMove: function (dx, dy, px, py, chart, event) {
|
|
var ele = this,
|
|
chartConfig = chart.config,
|
|
canvasLeft = chartConfig.canvasLeft,
|
|
canvasRight = chartConfig.canvasRight,
|
|
canvasBottom = chartConfig.canvasBottom,
|
|
canvasTop = chartConfig.canvasTop,
|
|
data = ele.data('drag-options'),
|
|
index = data.index,
|
|
dataset = data.dataset,
|
|
manager = dataset.groupManager,
|
|
labelObj = dataset.components.data[index],
|
|
labelElement = labelObj.graphics.element,
|
|
dragStart = labelObj.dragStart,
|
|
bBox = dragStart.bBox,
|
|
startX = dragStart.bBox.x + dx,
|
|
endX = dragStart.bBox.x2 + dx,
|
|
startY = dragStart.bBox.y + dy,
|
|
endY = dragStart.bBox.y2 + dy,
|
|
yAxis = chart.components.yAxis[0],
|
|
xAxis = chart.components.xAxis[0],
|
|
xPos,
|
|
yPos;
|
|
// Bound limits
|
|
if (startX < canvasLeft) {
|
|
dx += (canvasLeft - startX);
|
|
}
|
|
if (endX > canvasRight) {
|
|
dx -= (endX - canvasRight);
|
|
}
|
|
if (startY < canvasTop) {
|
|
dy += (canvasTop - startY);
|
|
}
|
|
if (endY > canvasBottom) {
|
|
dy -= (endY - canvasBottom);
|
|
}
|
|
dragStart.draged = true;
|
|
ele.attr({
|
|
x: bBox.x + dx,
|
|
y: bBox.y + dy
|
|
});
|
|
|
|
xPos = data.ox + dx;
|
|
yPos = data.oy + dy;
|
|
labelElement.attr({
|
|
x: data.ox + dx,
|
|
y: data.oy + dy
|
|
});
|
|
labelObj.config.x = xAxis.getValue(xPos - canvasLeft);
|
|
labelObj.config.y = yAxis.getValue(yPos - canvasTop);
|
|
if (!ele.data('fire_dragend')) {
|
|
/**
|
|
*
|
|
* > Applicable to `dragnode` chart only.
|
|
*
|
|
* @event FusionCharts#labelDragStart
|
|
* @group chart-powercharts:dragnode
|
|
*
|
|
* @param {number} chartX - x-coordinate of the pointer relative to the chart.
|
|
* @param {number} chartY - y-coordinate of the pointer relative to the chart.
|
|
* @param {number} pageX - x-coordinate of the pointer relative to the page.
|
|
* @param {number} pageY - y-coordinate of the pointer relative to the page.
|
|
*
|
|
* @param {number} x - The x-value of the label node scaled as per the axis of the chart.
|
|
* @param {number} y - The y-value of the label node scaled as per the axis of the chart.
|
|
*
|
|
* @param {string} text - The text value of the label.
|
|
*/
|
|
plotEventHandler.call(ele, chart, event, 'LabelDragStart');
|
|
ele.data('fire_dragend', 1);
|
|
}
|
|
if (ele.data('fire_click_event')) {
|
|
ele.data('fire_click_event', 0);
|
|
manager.clearLongPress.call(ele);
|
|
}
|
|
},
|
|
_labelDragUp: function (event) {
|
|
var ele = this,
|
|
data = ele.data('drag-options'),
|
|
index = data.index,
|
|
dataset = data.dataset,
|
|
chart = dataset.chart,
|
|
manager = dataset.groupManager,
|
|
sourceEvent = 'labeldragend',
|
|
labelObj = dataset.components.data[index],
|
|
dragStart = labelObj.dragStart,
|
|
eventArgs = ele.data(EVENTARGS),
|
|
xAxis = chart.components.xAxis[0],
|
|
yAxis = dataset.yAxis,
|
|
eventCord;
|
|
eventArgs.x = xAxis.getValue(ele.attr('x')),
|
|
eventArgs.y = yAxis.getValue(ele.attr('y')),
|
|
|
|
dragStart.draged = false;
|
|
if (ele.data('fire_dragend')) {
|
|
eventCord = getMouseCoordinate(chart.linkedItems.container, event);
|
|
eventCord.sourceEvent = sourceEvent;
|
|
|
|
// Fire the ChartUpdated event
|
|
lib.raiseEvent('chartupdated',
|
|
extend2(eventCord, eventArgs),
|
|
chart.chartInstance);
|
|
/**
|
|
*
|
|
* > Applicable to `dragnode` chart only.
|
|
*
|
|
* @event FusionCharts#labelDragEnd
|
|
* @group chart-powercharts:dragnode
|
|
*
|
|
* @param {number} chartX - x-coordinate of the pointer relative to the chart.
|
|
* @param {number} chartY - y-coordinate of the pointer relative to the chart.
|
|
* @param {number} pageX - x-coordinate of the pointer relative to the page.
|
|
* @param {number} pageY - y-coordinate of the pointer relative to the page.
|
|
*
|
|
* @param {number} x - The x-value of the label node scaled as per the axis of the chart.
|
|
* @param {number} y - The y-value of the label node scaled as per the axis of the chart.
|
|
*
|
|
* @param {string} text - The text value of the label.
|
|
*/
|
|
plotEventHandler.call(ele, chart, event, sourceEvent);
|
|
}
|
|
manager.clearLongPress.call(ele);
|
|
}
|
|
}, 'Dragnode']);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-dragcolumn',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
pluckNumber = lib.pluckNumber,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
getValidValue = lib.getValidValue,
|
|
// getDefinedColor = lib.getDefinedColor,
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
hasSVG = lib.hasSVG,
|
|
SETROLLOVERATTR = 'setRolloverAttr',
|
|
SETROLLOUTATTR = 'setRolloutAttr',
|
|
ROLLOVER = 'DataPlotRollOver',
|
|
ROLLOUT = 'DataPlotRollOut',
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
math = Math,
|
|
mathRound = math.round,
|
|
mathAbs = math.abs,
|
|
plotEventHandler = lib.plotEventHandler;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'DragColumn',{
|
|
/*
|
|
* Function for drawing 2D columns.
|
|
* This function is called every time for each dataset when they are initially drawn or shown/hidden from
|
|
* the drawGraph() function.
|
|
*/
|
|
configure: function () {
|
|
var dataset = this,
|
|
conf,
|
|
chartAttr = dataset.chart.jsonData.chart,
|
|
data,
|
|
i,
|
|
config,
|
|
JSONData = dataset.JSONData,
|
|
setDataArr = dataset.JSONData.data || [],
|
|
length,
|
|
setData;
|
|
this.__base__.configure.call(dataset);
|
|
conf = dataset.config;
|
|
data = dataset.components.data;
|
|
conf.allowDrag = pluckNumber(JSONData.allowdrag, 1);
|
|
conf.allowNegDrag = pluckNumber(JSONData.allownegativedrag, 1);
|
|
conf.allowAxisChange = pluckNumber(chartAttr.allowaxischange, 1);
|
|
conf.snapToDivOnly = pluckNumber(chartAttr.snaptodivonly, 0);
|
|
conf.snapToDiv = conf.snapToDivOnly ? 1 : pluckNumber(chartAttr.snaptodiv, 1);
|
|
conf.doNotSnap = pluckNumber(chartAttr.donotsnap, 0);
|
|
conf.snapToDivRelaxation = pluckNumber(chartAttr.snaptodivrelaxation, 10);
|
|
if (conf.doNotSnap) {
|
|
conf.snapToDiv = conf.snapToDivOnly = 0;
|
|
}
|
|
length = data.length;
|
|
for (i = 0; i < length; i++) {
|
|
setData = setDataArr[i] || {};
|
|
config = data[i].config;
|
|
config.allowDrag = pluckNumber(setData.allowdrag, conf.allowDrag);
|
|
config.allowNegDrag = pluckNumber(setData.allownegativedrag, conf.allowNegDrag);
|
|
}
|
|
|
|
},
|
|
/**
|
|
* This method handles all mouse events of an dataset.
|
|
* @param {String} eventType name of the event
|
|
* @param {number} plotIndex index of the plot where this event has been occured
|
|
* @param {Event} originalEvent reference of the original mouse event
|
|
*/
|
|
_firePlotEvent: function (eventType, plotIndex, e) {
|
|
var dataset = this,
|
|
JSONData = dataset.JSONData,
|
|
chartAttr = dataset.chart.jsonData.chart,
|
|
chart = dataset.chart,
|
|
dataSetConf = dataset.config,
|
|
chartConfig = chart.config,
|
|
useplotgradientcolor = chartConfig.useplotgradientcolor,
|
|
useroundedges = chartConfig.useroundedges,
|
|
chartComp = chart.components,
|
|
paper = chartComp.paper,
|
|
canvas = paper.canvas,
|
|
style = canvas.style,
|
|
NumberFormatter = chartComp.numberFormatter,
|
|
data = dataset.components.data[plotIndex],
|
|
config = data.config,
|
|
setElement = data.graphics.element,
|
|
setTooltext,
|
|
toolText = config.finalTooltext,
|
|
tip = lib.toolTip,
|
|
originalEvent = e.originalEvent,
|
|
dragMouseAttr = hasSVG && 'ns-resize' || 'n-resize',
|
|
pointerMouseAttr = 'default',
|
|
tolerance,
|
|
oriEvent = e.originalEvent,
|
|
coordinate = lib.getMouseCoordinate(chart.linkedItems.container, oriEvent),
|
|
chartY = coordinate.chartY,
|
|
yPos = data._yPos,
|
|
height = data._height,
|
|
formattedVal,
|
|
yAxis = chartComp.yAxis[0],
|
|
yBasePos = yAxis.getPixel(yAxis.getAxisBase()),
|
|
value,
|
|
yActual,
|
|
canvasTop = chartConfig.canvasTop,
|
|
canvasBottom = chartConfig.canvasBottom,
|
|
allowDrag = config.allowDrag,
|
|
allowNegDrag = config.allowNegDrag,
|
|
lowerDragBoundary = allowNegDrag ? canvasBottom : yBasePos,
|
|
eventArgsArr,
|
|
eventArgs,
|
|
rolloverdata,
|
|
rolloutedata,
|
|
fill,
|
|
angle,
|
|
colTop = yPos,
|
|
colBottom = yPos + height;
|
|
|
|
tolerance = chartConfig.dragTolerance + 1;
|
|
|
|
value = config.setValue;
|
|
|
|
yActual = (yPos >= yBasePos) ? (yPos + height) : yPos;
|
|
|
|
if (setElement) {
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(config.origToolText,
|
|
JSONData.plottooltext, chartAttr.plottooltext)));
|
|
switch (eventType) {
|
|
case 'mouseover' :
|
|
//set flag on mouse over
|
|
dataSetConf.mouseIn = true;
|
|
toolText && tip.setStyle(paper);
|
|
if (chartY <= colBottom - tolerance && chartY >= colTop + tolerance) {
|
|
tip.setPosition(originalEvent);
|
|
tip.draw(toolText, paper);
|
|
}
|
|
|
|
//fire _rollOverResponseSetter if its not already fired and
|
|
//cursor position is on column body
|
|
if(!config._rollOverResponseSetterFire && chartY <= colBottom && chartY >= colTop) {
|
|
dataset._rolloverResponseSetter(chart, setElement, originalEvent);
|
|
//set flag true as _rollOverResponseSetter is fired
|
|
config._rollOverResponseSetterFire = true;
|
|
}
|
|
break;
|
|
|
|
case 'mouseout' :
|
|
//set flag on mouse out
|
|
dataSetConf.mouseIn = false;
|
|
style.cursor = pointerMouseAttr;
|
|
//fire _rolloutResponseSetter if _rolloverResponseSetter is fired
|
|
config._rollOverResponseSetterFire &&
|
|
dataset._rolloutResponseSetter(chart, setElement, originalEvent);
|
|
//set flag false as _rolloutResponseSetter is fired
|
|
config._rollOverResponseSetterFire = false;
|
|
tip.hide();
|
|
break;
|
|
|
|
case 'click' :
|
|
plotEventHandler.call(setElement, chart, originalEvent);
|
|
break;
|
|
|
|
case 'touchmove' :
|
|
case 'mousemove' :
|
|
if (config.dragStart) {
|
|
(oriEvent.preventDefault) ? oriEvent.preventDefault() : oriEvent.returnValue = false;
|
|
config._rollOverResponseSetterFire = false;
|
|
style.cursor = dragMouseAttr;
|
|
//counter on drag move
|
|
config._pointerDy++;
|
|
//calculate chartY with _dragBuffer
|
|
chartY += config._dragBuffer;
|
|
//update chartY on canvas edge crossing
|
|
if(chartY < canvasTop) {
|
|
chartY = canvasTop;
|
|
} else if(chartY > lowerDragBoundary) {
|
|
chartY = lowerDragBoundary;
|
|
}
|
|
//calculate yPos
|
|
yPos = yBasePos < chartY ? yBasePos : chartY;
|
|
//calculate height
|
|
height = mathAbs(yBasePos - chartY);
|
|
data._yPos = yPos;
|
|
data._height = height;
|
|
yActual = (yPos >= yBasePos) ? (yPos + height) : yPos;
|
|
value = config.setValue = mathRound(yAxis.getValue(yActual - canvasTop));
|
|
formattedVal = NumberFormatter.dataLabels(value);
|
|
config.toolTipValue = formattedVal;
|
|
config.displayValue = pluck(config.setDisplayValue, formattedVal);
|
|
if (useplotgradientcolor && !useroundedges) {
|
|
config.colorArr[0].FCcolor.angle = angle = yPos < yBasePos ? 90 : 270;
|
|
}
|
|
setElement.attr({
|
|
y : data._yPos,
|
|
height : data._height,
|
|
fill : toRaphaelColor(config.colorArr[0])
|
|
});
|
|
|
|
dataset.drawLabel(plotIndex, plotIndex + 1);
|
|
data.graphics.element = setElement;
|
|
tip.hide();
|
|
|
|
//fire dataplotDragStart event
|
|
if (config._pointerDy == 1) {
|
|
eventArgs = {
|
|
dataIndex: plotIndex,
|
|
datasetIndex: data.datasetIndex,
|
|
startValue: data.startValue,
|
|
datasetName: data.name
|
|
};
|
|
global.raiseEvent('dataplotDragStart', eventArgs, chart.chartInstance);
|
|
}
|
|
}
|
|
else {
|
|
yActual = (yPos >= yBasePos) ? (yPos + height) : yPos;
|
|
|
|
if (allowDrag && chartY >= yActual - tolerance && chartY <= yActual + tolerance) {
|
|
style.cursor = dragMouseAttr;
|
|
tip.hide();
|
|
}
|
|
else {
|
|
style.cursor = pointerMouseAttr;
|
|
if (config._rollOverResponseSetterFire) {
|
|
tip.setPosition(originalEvent);
|
|
tip.draw(toolText, paper);
|
|
}
|
|
}
|
|
//fire _rollOverResponseSetter if its not already fired and
|
|
//cursor position is on column body
|
|
if (!config._rollOverResponseSetterFire && chartY <= colBottom && chartY >= colTop) {
|
|
dataset._rolloverResponseSetter(chart, setElement, originalEvent);
|
|
config._rollOverResponseSetterFire = true;
|
|
}
|
|
else if (config._rollOverResponseSetterFire &&
|
|
!(chartY <= colBottom && chartY >= colTop)) {
|
|
tip.hide();
|
|
config._rollOverResponseSetterFire = false;
|
|
dataset._rolloutResponseSetter(chart, setElement, originalEvent);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'touchend':
|
|
case 'mouseup' :
|
|
dataSetConf.mousedown = false;
|
|
if (config.dragStart) {
|
|
dataset.setMaxMin();
|
|
chart._setDataLimits();
|
|
eventArgs = {
|
|
dataIndex: plotIndex,
|
|
datasetIndex: data.datasetIndex,
|
|
startValue: data.startValue,
|
|
endValue: config.setValue,
|
|
datasetName: data.name
|
|
};
|
|
eventArgsArr = [
|
|
chart.chartInstance.id,
|
|
eventArgs.dataIndex,
|
|
eventArgs.datasetIndex,
|
|
eventArgs.datasetName,
|
|
eventArgs.startValue,
|
|
eventArgs.endValue
|
|
];
|
|
|
|
if (config._pointerDy) {
|
|
global.raiseEvent('dataplotDragEnd', eventArgs, chart.chartInstance);
|
|
|
|
// Fire the ChartUpdated event
|
|
lib.raiseEvent('chartupdated', eventArgs, chart.chartInstance, eventArgsArr);
|
|
}
|
|
if (useplotgradientcolor && !useroundedges) {
|
|
angle = yPos >= yBasePos ? 90 : 270;
|
|
if ((rolloverdata = setElement.data(SETROLLOVERATTR)) && rolloverdata.fill) {
|
|
fill = rolloverdata.fill;
|
|
fill = fill.split('-');
|
|
fill[0] = angle;
|
|
rolloverdata.fill = fill.join('-');
|
|
}
|
|
if ((rolloutedata = setElement.data(SETROLLOUTATTR)) && rolloutedata.fill) {
|
|
fill = rolloutedata.fill;
|
|
fill = fill.split('-');
|
|
fill[0] = angle;
|
|
rolloutedata.fill = fill.join('-');
|
|
}
|
|
}
|
|
}
|
|
//difference on actualY and chartY
|
|
config._dragBuffer = 0;
|
|
//counter on drag move
|
|
config._pointerDy = 0;
|
|
config.dragStart = false;
|
|
config.dragStart = false;
|
|
toolText = config.finalTooltext = config.toolText !== false ? (config.toolText +
|
|
(setTooltext ? '' : config.toolTipValue)) : '';
|
|
if (!(chartY >= yActual - tolerance &&
|
|
chartY <= yActual + tolerance)) {
|
|
style.cursor = pointerMouseAttr;
|
|
}
|
|
break;
|
|
|
|
case 'touchstart' :
|
|
case 'mousedown' :
|
|
if (dataSetConf.mouseIn) {
|
|
dataSetConf.mousedown = true;
|
|
yActual = (yPos >= yBasePos) ? (yPos + height) : yPos;
|
|
if (allowDrag && chartY >= yActual - tolerance &&
|
|
chartY <= yActual + tolerance) {
|
|
//set drag flag
|
|
config.dragStart = true;
|
|
config._pointerDy = 0;
|
|
config._dragStartY = chartY;
|
|
//difference on actualY and chartY
|
|
config._dragBuffer = yActual - chartY;
|
|
|
|
data.startValue = config.setValue;
|
|
data.name = dataSetConf.seriesname;
|
|
data.datasetIndex = dataset.positionIndex;
|
|
|
|
data.dragged = true;
|
|
}
|
|
else {
|
|
config.dragStart = false;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
},
|
|
_rolloverResponseSetter : function (chart, elem, event) {
|
|
var elData = elem.getData();
|
|
// Check whether the plot is in dragged state or not if
|
|
// drag then dont fire rolloverevent
|
|
if (elData.showHoverEffect !== 0 && elData.draged !== true) {
|
|
elem.attr(elem.getData().setRolloverAttr);
|
|
plotEventHandler.call(elem, chart, event, ROLLOVER);
|
|
}
|
|
},
|
|
|
|
_rolloutResponseSetter : function (chart, elem, event) {
|
|
var elData = elem.getData();
|
|
// Check whether the plot is in draggedstate or not if drag then dont fire rolloutevent
|
|
if (elData.showHoverEffect !== 0 && elData.draged !== true) {
|
|
elem.attr(elem.getData().setRolloutAttr);
|
|
plotEventHandler.call(elem, chart, event, ROLLOUT);
|
|
}
|
|
},
|
|
getJSONData: function () {
|
|
var dataset = this,
|
|
JSONData = dataset.JSONData.data,
|
|
dataStore = dataset.components.data,
|
|
dataArr = [],
|
|
obj = {},
|
|
updatedDataObj,
|
|
dataObj,
|
|
prop,
|
|
len,
|
|
i;
|
|
|
|
for (i = 0, len = JSONData.length; i < len; i++) {
|
|
dataObj = JSONData[i];
|
|
updatedDataObj = dataStore[i];
|
|
obj = {};
|
|
for (prop in dataObj) {
|
|
if (prop === 'value') {
|
|
obj[prop] = updatedDataObj.config.setValue;
|
|
}
|
|
else {
|
|
obj[prop] = dataObj[prop];
|
|
}
|
|
}
|
|
dataArr.push(obj);
|
|
}
|
|
return {
|
|
data: dataArr
|
|
};
|
|
}
|
|
}, 'Column']);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-dragarea',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
R = lib.Raphael,
|
|
isVML = (R.type === 'VML'),
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
preDefStr = lib.preDefStr,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
getValidValue = lib.getValidValue,
|
|
DRAGLINE = 'dragline',
|
|
hiddenStr = preDefStr.hiddenStr,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
pluckNumber = lib.pluckNumber,
|
|
hasSVG = lib.hasSVG,
|
|
SETROLLOVERATTR = 'setRolloverAttr',
|
|
SETROLLOUTATTR = 'setRolloutAttr',
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
math = Math,
|
|
mathRound = math.round,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
ROLLOVER = 'DataPlotRollOver',
|
|
ROLLOUT = 'DataPlotRollOut',
|
|
DATAPLOTCLICK = 'dataplotclick',
|
|
plotEventHandler = lib.plotEventHandler;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'DragArea',{
|
|
configure: function () {
|
|
var dataset = this,
|
|
conf,
|
|
chart = dataset.chart,
|
|
chartAttr = chart.jsonData.chart,
|
|
Area = FusionCharts.get(COMPONENT, [DATASET, 'area']),
|
|
data,
|
|
i,
|
|
config,
|
|
setData,
|
|
JSONData = dataset.JSONData,
|
|
setDataArr = JSONData.data || [],
|
|
length;
|
|
Area.prototype.configure.call(dataset);
|
|
conf = dataset.config;
|
|
data = dataset.components.data;
|
|
conf.allowDrag = pluckNumber(JSONData.allowdrag, 1);
|
|
conf.allowNegDrag = pluckNumber(JSONData.allownegativedrag, 1);
|
|
conf.allowAxisChange = pluckNumber(chartAttr.allowaxischange, 1);
|
|
conf.snapToDivOnly = pluckNumber(chartAttr.snaptodivonly, 0);
|
|
conf.doNotSnap = pluckNumber(chartAttr.donotsnap, 0);
|
|
conf.snapToDiv = pluckNumber(chartAttr.snaptodiv, 1);
|
|
conf.snapToDivRelaxation = pluckNumber(chartAttr.snaptodivrelaxation, 10);
|
|
if (conf.doNotSnap) {
|
|
conf.snapToDiv = conf.snapToDivOnly = 0;
|
|
}
|
|
length = data.length;
|
|
for (i = 0; i < length; i++) {
|
|
setData = setDataArr[i] || {};
|
|
config = data[i].config;
|
|
config.allowDrag = pluckNumber(setData.allowdrag, conf.allowDrag);
|
|
config.allowNegDrag = pluckNumber(setData.allownegativedrag, conf.allowNegDrag);
|
|
}
|
|
|
|
},
|
|
updateImage: function (dataObj) {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
graphics = dataObj.graphics,
|
|
image = graphics.image || graphics.element,
|
|
config = dataObj.config,
|
|
anchorProps = config.anchorProps,
|
|
hoverEffects = config.hoverEffects,
|
|
imgRef = image && image.data('imgRef'),
|
|
getPathString = function (data) {
|
|
var PathArrLength = data.length,
|
|
pathString = BLANKSTRING,
|
|
ittr;
|
|
for (ittr = 0; ittr < PathArrLength; ittr += 1) {
|
|
pathString += ' '+data[ittr];
|
|
}
|
|
return pathString;
|
|
},
|
|
scale = anchorProps.imageScale,
|
|
paper = chart.components.paper,
|
|
imgH = imgRef.height * scale * 0.01,
|
|
imgW = imgRef.width * scale * 0.01,
|
|
x = dataObj._xPos,
|
|
y = dataObj._yPos,
|
|
hoverScale = hoverEffects.imageHoverScale,
|
|
hotW = (imgRef.width * hoverScale * 0.01),
|
|
hotH = (imgRef.height * hoverScale * 0.01),
|
|
isAnchorRadius = anchorProps.isAnchorRadius,
|
|
markerRadius = anchorProps.radius = isAnchorRadius ?
|
|
anchorProps.radius : mathMin(imgW, imgH)/2,
|
|
imagePadding = anchorProps.imagePadding,
|
|
rolloutClipRadius = markerRadius - imagePadding - anchorProps.borderThickness * 0.5,
|
|
rolloverClipRadius = hoverEffects.radius -
|
|
imagePadding - hoverEffects.anchorBorderThickness * 0.5,
|
|
symbol = anchorProps.symbol[1],
|
|
imageRollOverPath,
|
|
setRolloverAttr,
|
|
tempPath = paper.polypath(symbol || 2, x, y,
|
|
rolloutClipRadius > 0 ? rolloutClipRadius : 0,
|
|
anchorProps.startAngle,
|
|
0)
|
|
.attr({visibility : hiddenStr}),
|
|
imageRolloutPath = getPathString(tempPath.attrs.path),
|
|
setRolloutAttr = {
|
|
x: x - imgRef.width * scale * 0.005,
|
|
y: y - imgRef.height * scale * 0.005,
|
|
width: imgW,
|
|
height: imgH,
|
|
alpha: 100
|
|
};
|
|
|
|
if (!isVML) {
|
|
setRolloutAttr['clip-path'] = imageRolloutPath;
|
|
}
|
|
tempPath.remove();
|
|
|
|
tempPath = paper.polypath(symbol || 2, x, y,
|
|
rolloverClipRadius > 0 ? rolloverClipRadius : 0,
|
|
hoverEffects.startAngle,
|
|
hoverEffects.dip);
|
|
|
|
imageRollOverPath = getPathString(tempPath.attrs.path);
|
|
|
|
tempPath.remove();
|
|
setRolloverAttr = {
|
|
x: x - imgRef.width * hoverScale * 0.005,
|
|
y: y - imgRef.height * hoverScale * 0.005,
|
|
width: hotW,
|
|
height: hotH,
|
|
alpha: 100
|
|
};
|
|
|
|
if (!isVML) {
|
|
setRolloverAttr['clip-path'] = imageRollOverPath;
|
|
}
|
|
image.attr(setRolloutAttr);
|
|
image.data(SETROLLOVERATTR, setRolloverAttr);
|
|
image.data(SETROLLOUTATTR, setRolloutAttr);
|
|
},
|
|
/**
|
|
* This method handles all mouse events of an dataset.
|
|
* @param {String} eventType name of the event
|
|
* @param {number} plotIndex index of the plot where this event has been occured
|
|
* @param {Event} originalEvent reference of the original mouse event
|
|
*/
|
|
_firePlotEvent: function (eventType, plotIndex, eventObj) {
|
|
var dataset = this,
|
|
JSONData = dataset.JSONData,
|
|
chartAttr = dataset.chart.jsonData.chart,
|
|
chart = dataset.chart,
|
|
chartConfig = chart.config,
|
|
chartComp = chart.components,
|
|
paper = chartComp.paper,
|
|
tip = lib.toolTip,
|
|
canvas = paper.canvas,
|
|
style = canvas.style,
|
|
NumberFormatter = chartComp.numberFormatter,
|
|
datasetComp = dataset.components,
|
|
plotItem = datasetComp.data[plotIndex],
|
|
length = datasetComp.data.length,
|
|
dataArr,
|
|
DragArea = FusionCharts.get(COMPONENT, [DATASET, 'DragArea']),
|
|
dataSetConf = dataset.config,
|
|
datasetIndex = dataset.index,
|
|
originalEvent = eventObj.originalEvent,
|
|
dragMouseAttr = hasSVG && 'ns-resize' || 'n-resize',
|
|
pointerMouseAttr = 'default',
|
|
tolerance,
|
|
coordinate,
|
|
chartY,
|
|
chartX,
|
|
yPos,
|
|
xPos,
|
|
i,
|
|
setObj,
|
|
pathArr,
|
|
startIndex,
|
|
endIndex,
|
|
connector,
|
|
element,
|
|
hoverEnabled,
|
|
setTooltext,
|
|
toolText,
|
|
link,
|
|
eventArgs,
|
|
eventArgsArr,
|
|
config,
|
|
formattedVal,
|
|
changedTouch,
|
|
yBasePos = plotItem && plotItem._yBasePos,
|
|
value,
|
|
yAxis = chartComp.yAxis[0],
|
|
canvasTop = chartConfig.canvasTop,
|
|
canvasBottom = chartConfig.canvasBottom,
|
|
allowDrag,
|
|
allowNegDrag,
|
|
datasetGraphics = dataset.graphics,
|
|
mainLineElement = datasetGraphics.lineElement,
|
|
anchorProps,
|
|
anchorImageUrl,
|
|
anchorElement,
|
|
image,
|
|
path,
|
|
lowerDragBoundary = allowNegDrag ? canvasBottom : yBasePos,
|
|
radius,
|
|
hoverRadius,
|
|
hoverAnchorSides,
|
|
hoverAnchorAngle,
|
|
anchorStartAngle,
|
|
rolloverData,
|
|
rolloverdata,
|
|
rolloutdata,
|
|
isHoverEnabled,
|
|
isDragLine = dataset.type === DRAGLINE ? true : false;
|
|
|
|
if (eventType === 'touchend') {
|
|
changedTouch = originalEvent.changedTouches[0];
|
|
originalEvent.pageX = changedTouch && changedTouch.pageX;
|
|
originalEvent.pageY = changedTouch && changedTouch.pageY;
|
|
}
|
|
coordinate = lib.getMouseCoordinate(chart.linkedItems.container, originalEvent);
|
|
chartY = coordinate.chartY;
|
|
chartX = coordinate.chartX;
|
|
|
|
if (plotItem) {
|
|
element = plotItem.graphics.element;
|
|
config = plotItem.config;
|
|
anchorProps = config.anchorProps;
|
|
anchorImageUrl = anchorProps.imageUrl;
|
|
image = plotItem.graphics.image;
|
|
anchorElement = element;
|
|
rolloverData = anchorElement && anchorElement.data(SETROLLOVERATTR);
|
|
isHoverEnabled = config.hoverEffects && config.hoverEffects.enabled;
|
|
hoverRadius = isHoverEnabled && rolloverData.polypath[3];
|
|
hoverAnchorSides = isHoverEnabled && rolloverData.polypath[0];
|
|
hoverAnchorAngle = isHoverEnabled && rolloverData.polypath[4];
|
|
anchorStartAngle = anchorProps.startAngle || 90;
|
|
link = config.setLink;
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(config.origToolText,
|
|
JSONData.plottooltext, chartAttr.plottooltext)));
|
|
toolText = config.finalTooltext;
|
|
hoverEnabled = config.hoverEffects.enabled;
|
|
eventArgs = config.eventArgs;
|
|
yPos = plotItem._yPos;
|
|
xPos = plotItem._xPos;
|
|
allowDrag = config.allowDrag;
|
|
allowNegDrag = config.allowNegDrag;
|
|
lowerDragBoundary = allowNegDrag ? canvasBottom : yBasePos;
|
|
radius = anchorProps.radius;
|
|
config.dragTolerance = config.dragTolerance < anchorProps.markerRadius ?
|
|
anchorProps.markerRadius + 0.5 : config.dragTolerance;
|
|
tolerance = mathMax(config.dragTolerance, config.hoverEffects.anchorRadius || 0) + 1;
|
|
|
|
switch (eventType) {
|
|
case 'mouseover':
|
|
dataSetConf.mouseIn = true;
|
|
if (config.allowDrag) {
|
|
style.cursor = dragMouseAttr;
|
|
}
|
|
if (!config.dragStart && toolText && !config.dragStart) {
|
|
tip.setStyle(paper);
|
|
tip.setPosition(originalEvent);
|
|
tip.draw(toolText, paper);
|
|
}
|
|
if (!config.dragStart) {
|
|
hoverEnabled && dataset._hoverPlotAnchor(plotItem, ROLLOVER);
|
|
element && plotEventHandler.call(element, chart, originalEvent, ROLLOVER, eventArgs);
|
|
}
|
|
break;
|
|
|
|
case 'mouseout':
|
|
dataSetConf.mouseIn = false;
|
|
style.cursor = pointerMouseAttr;
|
|
|
|
hoverEnabled && dataset._hoverPlotAnchor(plotItem, ROLLOUT);
|
|
element && plotEventHandler.call(element, chart, originalEvent, ROLLOUT, eventArgs);
|
|
tip.hide();
|
|
break;
|
|
|
|
case 'touchmove':
|
|
case 'mousemove':
|
|
if (config.dragStart) {
|
|
(originalEvent.preventDefault) ? originalEvent.preventDefault() :
|
|
originalEvent.returnValue = false;
|
|
config.allowDrag && (style.cursor = dragMouseAttr);
|
|
config._pointerDy++;
|
|
chartY += config._dragBuffer;
|
|
if(chartY < canvasTop) {
|
|
chartY = canvasTop;
|
|
} else if(chartY > lowerDragBoundary) {
|
|
chartY = lowerDragBoundary;
|
|
}
|
|
plotItem._yPos = chartY;
|
|
value = config.setValue = mathRound(yAxis.getValue(yPos - canvasTop));
|
|
formattedVal = NumberFormatter.dataLabels(value);
|
|
config.toolTipValue = formattedVal;
|
|
config.displayValue = formattedVal;
|
|
|
|
dataset.drawLabel(plotIndex, plotIndex + 1);
|
|
plotItem.graphics.element = element;
|
|
|
|
if (isVML && anchorImageUrl) {
|
|
image = anchorElement;
|
|
}
|
|
else {
|
|
|
|
if (isHoverEnabled && (rolloverdata = anchorElement.data(SETROLLOVERATTR))) {
|
|
rolloverdata.polypath[2] = plotItem._yPos;
|
|
}
|
|
if (isHoverEnabled && (rolloutdata = anchorElement.data(SETROLLOUTATTR))) {
|
|
rolloutdata.polypath[2] = plotItem._yPos;
|
|
}
|
|
|
|
anchorElement && anchorElement.attr(rolloutdata || {
|
|
polypath: [anchorProps.symbol[1] || 2, xPos, plotItem._yPos,
|
|
anchorProps.radius, anchorStartAngle, 0]
|
|
});
|
|
}
|
|
|
|
if (image) {
|
|
DragArea.prototype.updateImage.call(dataset, plotItem);
|
|
}
|
|
|
|
dataArr = datasetComp.data;
|
|
path = dataset.getLinePath(dataArr, {});
|
|
|
|
if (isDragLine) {
|
|
for (i = 0; i < length; i++) {
|
|
connector = dataArr[i].graphics && dataArr[i].graphics.connector;
|
|
|
|
if (connector) {
|
|
|
|
setObj = dataArr[i];
|
|
startIndex = setObj.config.connStartIndex;
|
|
endIndex = setObj.config.connEndIndex;
|
|
|
|
pathArr = dataset.getLinePath(dataArr, {}, {
|
|
begin: startIndex,
|
|
end: endIndex + 1
|
|
});
|
|
|
|
connector.attr({
|
|
path: pathArr.getPathArr()
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mainLineElement) {
|
|
dataSetConf = dataset.config;
|
|
startIndex = config.pathStartIndex;
|
|
endIndex = config.pathEndIndex;
|
|
pathArr = config.lastPath;
|
|
pathArr = dataset.getLinePath(dataArr, {}, {
|
|
begin: startIndex,
|
|
end: endIndex
|
|
});
|
|
mainLineElement.attr({
|
|
path: pathArr.getPathArr()
|
|
});
|
|
}
|
|
|
|
if (config._pointerDy == 1) {
|
|
eventArgs = {
|
|
dataIndex: plotIndex,
|
|
datasetIndex: datasetIndex,
|
|
startValue: plotItem.startValue,
|
|
endValue: config.setValue,
|
|
datasetName: plotItem.name
|
|
};
|
|
global.raiseEvent('dataplotDragStart', eventArgs, chart.chartInstance);
|
|
}
|
|
}
|
|
if (!config.dragStart && toolText &&
|
|
chartY >= yPos - tolerance && chartY <= yPos + tolerance &&
|
|
chartX <= xPos + tolerance && chartX >= xPos - tolerance) {
|
|
tip.setPosition(originalEvent);
|
|
tip.draw(toolText, paper);
|
|
} else {
|
|
tip.hide();
|
|
}
|
|
|
|
break;
|
|
|
|
case 'click':
|
|
element && plotEventHandler.call(element, chart, originalEvent, DATAPLOTCLICK, eventArgs);
|
|
break;
|
|
|
|
case 'touchend':
|
|
case 'mouseup' :
|
|
dataSetConf.mousedown = false;
|
|
if (config.dragStart) {
|
|
dataset.setMaxMin();
|
|
chart._setDataLimits();
|
|
|
|
eventArgs = {
|
|
dataIndex: plotIndex,
|
|
datasetIndex: datasetIndex,
|
|
startValue: plotItem.startValue,
|
|
endValue: config.setValue,
|
|
datasetName: plotItem.name
|
|
};
|
|
eventArgsArr = [
|
|
chart.chartInstance.id,
|
|
eventArgs.dataIndex,
|
|
eventArgs.datasetIndex,
|
|
eventArgs.datasetName,
|
|
eventArgs.startValue,
|
|
eventArgs.endValue
|
|
];
|
|
/**
|
|
* The four dragable charts: `dragnode`, `dragcolumn2d`, `dragline` and `dragarea`
|
|
* fires this event when their data plots are stopped being dragged.
|
|
*
|
|
* @event FusionCharts#dataplotDragEnd
|
|
* @group chart-powercharts:drag
|
|
*/
|
|
if (config._pointerDy) {
|
|
hoverEnabled && dataset._hoverPlotAnchor(plotItem, ROLLOUT);
|
|
global.raiseEvent('dataplotDragEnd', eventArgs, chart.chartInstance);
|
|
// Fire the ChartUpdated event
|
|
lib.raiseEvent('chartupdated', eventArgs, chart.chartInstance, eventArgsArr);
|
|
}
|
|
}
|
|
toolText = config.finalTooltext = config.toolText !== false ? (config.toolText +
|
|
(setTooltext ? '' : config.toolTipValue)) : '';
|
|
|
|
if (!(chartY >= yPos - tolerance && chartY <= yPos + tolerance &&
|
|
chartX <= xPos + tolerance && chartX >= xPos - tolerance)) {
|
|
|
|
style.cursor = pointerMouseAttr;
|
|
}
|
|
if (dataSetConf.mouseIn && !config.dragStart) {
|
|
tip.setPosition(originalEvent);
|
|
tip.draw(toolText, paper);
|
|
}
|
|
config._dragBuffer = 0;
|
|
config._pointerDy = 0;
|
|
config.dragStart = false;
|
|
break;
|
|
|
|
case 'touchstart':
|
|
case 'mousedown' :
|
|
if (dataSetConf.mouseIn) {
|
|
dataSetConf.mousedown = true;
|
|
if (allowDrag &&
|
|
chartY >= yPos - tolerance && chartY <= yPos + tolerance &&
|
|
chartX <= xPos + tolerance && chartX >= xPos - tolerance) {
|
|
config.dragStart = true;
|
|
config._pointerDy = 0;
|
|
config._dragStartY = chartY;
|
|
config._dragBuffer = yPos - chartY;
|
|
|
|
plotItem.dragged = true;
|
|
|
|
plotItem.startValue = config.setValue;
|
|
plotItem.name = dataSetConf.seriesname;
|
|
plotItem.datasetIndex = dataset.positionIndex;
|
|
eventArgs = {
|
|
dataIndex: plotIndex + 1,
|
|
datasetIndex: plotItem.datasetIndex,
|
|
startValue: plotItem.startValue,
|
|
datasetName: plotItem.name
|
|
};
|
|
} else {
|
|
config.dragStart = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
getJSONData: function () {
|
|
var dataset = this,
|
|
JSONData = dataset.JSONData.data,
|
|
dataStore = dataset.components.data,
|
|
dataArr = [],
|
|
obj = {},
|
|
dataObj,
|
|
updatedDataObj,
|
|
prop,
|
|
len,
|
|
i;
|
|
for (i = 0, len = JSONData.length; i < len; i++) {
|
|
dataObj = JSONData[i];
|
|
updatedDataObj = dataStore[i];
|
|
obj = {};
|
|
for (prop in dataObj) {
|
|
if (prop === 'value') {
|
|
obj[prop] = updatedDataObj.config.setValue;
|
|
}
|
|
else {
|
|
obj[prop] = dataObj[prop];
|
|
}
|
|
}
|
|
dataArr.push(obj);
|
|
}
|
|
return {
|
|
data: dataArr
|
|
};
|
|
}
|
|
}, 'Area']);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-dragline',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
preDefStr = lib.preDefStr,
|
|
LINE = preDefStr.line,
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset';
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'DragLine', {
|
|
type : 'dragline',
|
|
configure: FusionCharts.get(COMPONENT, [DATASET, 'DragArea']).prototype.configure,
|
|
/**
|
|
* This method handles all mouse events of an dataset.
|
|
* @param {String} eventType name of the event
|
|
* @param {number} plotIndex index of the plot where this event has been occured
|
|
* @param {Event} originalEvent reference of the original mouse event
|
|
*/
|
|
_firePlotEvent: FusionCharts.get(COMPONENT, [DATASET, 'DragArea']).prototype._firePlotEvent,
|
|
getJSONData: function () {
|
|
var dataset = this,
|
|
JSONData = dataset.JSONData.data,
|
|
dataStore = dataset.components.data,
|
|
dataArr = [],
|
|
obj = {},
|
|
dataObj,
|
|
prop,
|
|
updatedDataObj,
|
|
len,
|
|
i;
|
|
for (i = 0, len = JSONData.length; i < len; i++) {
|
|
dataObj = JSONData[i];
|
|
updatedDataObj = dataStore[i];
|
|
obj = {};
|
|
for (prop in dataObj) {
|
|
if (prop === 'value') {
|
|
obj[prop] = updatedDataObj.config.setValue;
|
|
}
|
|
else {
|
|
obj[prop] = dataObj[prop];
|
|
}
|
|
}
|
|
dataArr.push(obj);
|
|
}
|
|
return {
|
|
data: dataArr
|
|
};
|
|
}
|
|
}, LINE]);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-selectscatter',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
convertColor = lib.graphics.convertColor,
|
|
preDefStr = lib.preDefStr,
|
|
altHGridColorStr = preDefStr.altHGridColorStr,
|
|
altHGridAlphaStr = preDefStr.altHGridAlphaStr,
|
|
colorStrings = preDefStr.colors,
|
|
COLOR_FFFFFF = colorStrings.FFFFFF,
|
|
getValidValue = lib.getValidValue,
|
|
ZEROSTRING = lib.ZEROSTRING,
|
|
bindSelectionEvent = lib.bindSelectionEvent,
|
|
getMouseCoordinate = lib.getMouseCoordinate,
|
|
extend2 = lib.extend2,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
pluckNumber = lib.pluckNumber,
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset';
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'selectScatter', {
|
|
configure : function () {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
chartConfig = chart.config,
|
|
chartComponents = chart.components,
|
|
chartAttr = chart.jsonData.chart,
|
|
colorM = chartComponents.colorManager,
|
|
borderColor = pluck(chartAttr.selectbordercolor,
|
|
colorM.getColor('canvasBorderColor')),
|
|
borderAlpha = pluckNumber(chartAttr.selectborderalpha,
|
|
colorM.getColor('canvasBorderAlpha'));
|
|
|
|
FusionCharts.get(COMPONENT, [DATASET, 'scatter']).prototype.configure.call(dataSet);
|
|
|
|
chartConfig.selectBorderColor = //convertColor(borderColor, borderAlpha);
|
|
{
|
|
FCcolor: {
|
|
color: borderColor,
|
|
alpha: borderAlpha
|
|
}
|
|
};
|
|
chartConfig.selectFillColor = convertColor(
|
|
pluck(chartAttr.selectfillcolor,
|
|
colorM.getColor(altHGridColorStr)),
|
|
pluckNumber(chartAttr.selectfillalpha,
|
|
colorM.getColor(altHGridAlphaStr)));
|
|
|
|
chartConfig.selectionCancelButtonBorderColor = convertColor(pluck(
|
|
chartAttr.selectioncancelbuttonbordercolor, borderColor),
|
|
pluckNumber(chartAttr.selectioncancelbuttonborderalpha, borderAlpha));
|
|
chartConfig.selectionCancelButtonFillColor = convertColor(pluck(
|
|
chartAttr.selectioncancelbuttonfillcolor, COLOR_FFFFFF),
|
|
pluckNumber(chartAttr.selectioncancelbuttonfillalpha, 100));
|
|
chartConfig.connativeZoom = false;
|
|
chartConfig.zoomType = 'xy';
|
|
|
|
chartConfig.formAction = getValidValue(chartAttr.formaction);
|
|
|
|
if (chartAttr.submitdataasxml === ZEROSTRING && !chartAttr.formdataformat) {
|
|
chartAttr.formdataformat = global.dataFormats.CSV;
|
|
}
|
|
|
|
chartConfig.formDataFormat = pluck(chartAttr.formdataformat,
|
|
global.dataFormats.XML);
|
|
chartConfig.formTarget = pluck(chartAttr.formtarget, '_self');
|
|
chartConfig.formMethod = pluck(chartAttr.formmethod, 'POST');
|
|
chartConfig.submitFormAsAjax = pluckNumber(chartAttr.submitformusingajax, 1);
|
|
},
|
|
|
|
draw : function() {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
container = chart.linkedItems.container;
|
|
|
|
FusionCharts.get(COMPONENT, [DATASET, 'scatter']).prototype.draw.call(dataSet);
|
|
|
|
bindSelectionEvent(chart, {
|
|
selectionStart: function(data) {
|
|
var pos = getMouseCoordinate(container, data.originalEvent),
|
|
eventArgs = extend2({
|
|
selectionLeft: data.selectionLeft,
|
|
selectionTop: data.selectionTop,
|
|
selectionWidth: data.selectionWidth,
|
|
selectionHeight: data.selectionHeight,
|
|
startXValue: data.chart.components.xAxis[0].getAxisPosition(data.selectionLeft, 1),
|
|
startYValue: data.chart.components.yAxis[0].getAxisPosition(data.selectionTop, 1)
|
|
}, pos);
|
|
/**
|
|
* Raised when user starts to draw a selection box on a `selectScatter` chart.
|
|
* @event FusionCharts#selectionStart
|
|
*
|
|
* @param {number} chartX - The x-coordinate of the mouse with respect to the chart.
|
|
* @param {number} chartY - The y-coordinate of the mouse with respect to the chart.
|
|
* @param {number} pageX - The x-coordinate of the mouse with respect to the page.
|
|
* @param {number} pageY - The y-coordinate of the mouse with respect to the page.
|
|
* @param {number} startXValue - The value on the canvas x-axis where the selection started.
|
|
* @param {number} startYValue - The value on the canvas y-axis where the selection started.
|
|
*/
|
|
global.raiseEvent('selectionStart', eventArgs, data.chart.chartInstance);
|
|
},
|
|
selectionEnd: function(data) {
|
|
var pos = getMouseCoordinate(container, data.originalEvent),
|
|
xAxis = data.chart.components.xAxis[0],
|
|
yAxis = data.chart.components.yAxis[0],
|
|
eventArgs = extend2({
|
|
selectionLeft: data.selectionLeft,
|
|
selectionTop: data.selectionTop,
|
|
selectionWidth: data.selectionWidth,
|
|
selectionHeight: data.selectionHeight,
|
|
startXValue: xAxis.getAxisPosition(data.selectionLeft, 1),
|
|
startYValue: yAxis.getAxisPosition(data.selectionTop, 1),
|
|
endXValue: xAxis.getAxisPosition(data.selectionLeft + data.selectionWidth, 1),
|
|
endYValue: yAxis.getAxisPosition(data.selectionTop + data.selectionHeight, 1)
|
|
}, pos);
|
|
|
|
/**
|
|
* Raised when user completes a selection box on a `selectScatter` chart.
|
|
* @event FusionCharts#selectionEnd
|
|
*
|
|
* @param {number} chartX - The x-coordinate of the mouse with respect to the chart.
|
|
* @param {number} chartY - The y-coordinate of the mouse with respect to the chart.
|
|
* @param {number} pageX - The x-coordinate of the mouse with respect to the page.
|
|
* @param {number} pageY - The y-coordinate of the mouse with respect to the page.
|
|
* @param {number} startXValue - The value on the canvas x-axis where the selection started.
|
|
* @param {number} startYValue - The value on the canvas y-axis where the selection started.
|
|
* @param {number} endXValue - The value on the canvas x-axis where the selection ended.
|
|
* @param {number} endYValue - The value on the canvas y-axis where the selection ended.
|
|
* @param {number} selectionLeft - The x-coordinate from where selection started with
|
|
* respect to the chart.
|
|
* @param {number} selectionTop - The y-coordinate from where selection started with
|
|
* respect to the chart.
|
|
* @param {number} selectionWidth - The width of the selection in pixels.
|
|
* @param {number} selectionHeight - The height of the selection box in pixels.
|
|
*/
|
|
global.raiseEvent('selectionEnd', eventArgs, data.chart.chartInstance);
|
|
data.chart.createSelectionBox(data);
|
|
}
|
|
});
|
|
}
|
|
},'scatter']);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-candlestick',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
preDefStr = lib.preDefStr,
|
|
LINE = preDefStr.line,
|
|
VOLUME = preDefStr.volume,
|
|
BAR = preDefStr.bar,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
getValidValue = lib.getValidValue,
|
|
getFirstValue = lib.getFirstValue,
|
|
getFirstColor = lib.getFirstColor,
|
|
SETROLLOVERATTR = preDefStr.setRolloverAttrStr,
|
|
SETROLLOUTATTR = preDefStr.setRolloutAttrStr,
|
|
ZEROSTRING = lib.ZEROSTRING,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
COLUMN = preDefStr.column,
|
|
HUNDRED = '100',
|
|
getDashStyle = lib.getDashStyle,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
UNDEFINED,
|
|
columnStr = preDefStr.columnStr,
|
|
shadowStr = preDefStr.shadowStr,
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
miterStr = preDefStr.miterStr,
|
|
schedular = lib.schedular,
|
|
t = 't',
|
|
COMMA = ',',
|
|
showHoverEffectStr = preDefStr.showHoverEffectStr,
|
|
M = 'M',
|
|
L = 'L',
|
|
H = 'H',
|
|
V = 'V',
|
|
EVENTARGS = 'eventArgs',
|
|
POINTER = 'pointer',
|
|
DEFAULT = 'default',
|
|
ROUND = preDefStr.ROUND,
|
|
visibleStr = preDefStr.visibleStr,
|
|
errorBarStr = preDefStr.errorBarStr,
|
|
errorHotStr = preDefStr.errorHotStr,
|
|
defined = function(obj) {
|
|
return obj !== UNDEFINED && obj !== null;
|
|
},
|
|
NONE = 'none',
|
|
// The default value for stroke-dash attribute.
|
|
DASH_DEF = NONE,
|
|
UNDERSCORE = preDefStr.UNDERSCORE,
|
|
parseTooltext = lib.parseTooltext,
|
|
BOLDSTARTTAG = '<b>',
|
|
BOLDENDTAG = '</b>',
|
|
BLANKSPACE = ' ',
|
|
BREAKSTRING = '<br />',
|
|
colorStrings = preDefStr.colors,
|
|
extend2 = lib.extend2,
|
|
configStr = preDefStr.configStr,
|
|
COLOR_B90000 = colorStrings.B90000,
|
|
COLOR_FFFFFF = colorStrings.FFFFFF,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
pluckNumber = lib.pluckNumber,
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
math = Math,
|
|
mathRound = math.round,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
mathAbs = math.abs,
|
|
ROLLOVER = 'DataPlotRollOver',
|
|
ROLLOUT = 'DataPlotRollOut',
|
|
plotEventHandler = lib.plotEventHandler;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'Candlestick', {
|
|
type: 'Candlestick',
|
|
configure: function () {
|
|
if (this.plotType === VOLUME) {
|
|
this._configureVolume();
|
|
return;
|
|
}
|
|
var dataset = this,
|
|
conf = dataset.config,
|
|
chart = dataset.chart,
|
|
chartComponents = chart.components,
|
|
rawDataObj = chart.jsonData,
|
|
JSONData = dataset.JSONData,
|
|
dataArr = JSONData.data || [],
|
|
chartAttr = rawDataObj.chart,
|
|
BLANK = BLANKSTRING,
|
|
dataLength = dataArr.length,
|
|
plotPriceAs = conf.plotPriceAs = getValidValue(chartAttr.plotpriceas, BLANK).toLowerCase(),
|
|
numberFormatter = chartComponents.numberFormatter,
|
|
colorM = chartComponents.colorManager,
|
|
valueText,
|
|
setColor,
|
|
setBorderColor,
|
|
setAlpha,
|
|
dashStyle,
|
|
//Candle stick properties.
|
|
//Bear fill and border color - (Close lower than open)
|
|
bearBorderColor = conf.bearBorderColor =
|
|
getFirstColor(pluck(chartAttr.bearbordercolor, COLOR_B90000)),
|
|
bearFillColor = conf.bearFillColor =
|
|
getFirstColor(pluck(chartAttr.bearfillcolor, COLOR_B90000)),
|
|
//Bull fill and border color - Close higher than open
|
|
bullBorderColor = conf.bullBorderColor =
|
|
getFirstColor(pluck(chartAttr.bullbordercolor,
|
|
colorM.getColor('canvasBorderColor'))),
|
|
bullFillColor = conf.bullFillColor =
|
|
getFirstColor(pluck(chartAttr.bullfillcolor,
|
|
COLOR_FFFFFF)),
|
|
//Line Properties - Serves as line for bar & line and border for candle stick
|
|
plotLineThickness = conf.linethickness = conf.plotBorderThickness =
|
|
pluckNumber(chartAttr.plotlinethickness, (plotPriceAs == LINE ||
|
|
plotPriceAs == BAR) ? 2 : 1),
|
|
plotLineDashLen = conf.plotLineDashLen = pluckNumber(chartAttr.plotlinedashlen, 5),
|
|
plotLineDashGap = conf.plotLineDashGap = pluckNumber(chartAttr.plotlinedashgap, 4),
|
|
// Anchor cosmetics in data points
|
|
// Getting anchor cosmetics for the data points or its default values
|
|
// The default value is different from flash in order to render a
|
|
// perfect circle when no anchorside is provided.
|
|
drawAnchors = !! pluckNumber(chartAttr.drawanchors, 1),
|
|
setAnchorAngle = pluckNumber(chartAttr.anchorstartangle, 90),
|
|
setAnchorRadius = pluckNumber(chartAttr.anchorradius,
|
|
this.anchorRadius, 3),
|
|
setAnchorBorderColor = getFirstColor(pluck(chartAttr.anchorbordercolor,
|
|
bullBorderColor)),
|
|
setAnchorBorderThickness = pluckNumber(chartAttr.anchorborderthickness,
|
|
this.anchorBorderThickness, 1),
|
|
setAnchorBgColor = getFirstColor(pluck(chartAttr.anchorbgcolor,
|
|
colorM.getColor('anchorBgColor'))),
|
|
setAnchorAlpha = pluck(chartAttr.anchoralpha, ZEROSTRING),
|
|
setAnchorBgAlpha = pluck(chartAttr.anchorbgalpha, setAnchorAlpha),
|
|
pointShadow,
|
|
index,
|
|
dataObj,
|
|
toolText,
|
|
open,
|
|
close,
|
|
high,
|
|
low,
|
|
volume,
|
|
minValue,
|
|
maxValue,
|
|
x,
|
|
closeVal,
|
|
borderColor,
|
|
yVal,
|
|
isLine,
|
|
openVal,
|
|
dataStore,
|
|
setData,
|
|
config,
|
|
isCandleStick = false,
|
|
displayValue,
|
|
plotSpacePercent,
|
|
yMax = -Infinity,
|
|
yMin = +Infinity,
|
|
xMax = -Infinity,
|
|
xMin = +Infinity,
|
|
userMaxColWidth,
|
|
enableAnimation,
|
|
mapSymbolName = lib.graphics.mapSymbolName;
|
|
conf.parentYAxis = 0;
|
|
conf.toolText = getValidValue(parseUnsafeString(pluck(JSONData.tooltext, chartAttr.plottooltext)));
|
|
// Dataset seriesname
|
|
conf.name = getValidValue(JSONData.seriesname);
|
|
conf.showTooltip = pluck(chartAttr.showtooltip, 1);
|
|
switch (plotPriceAs) {
|
|
case LINE:
|
|
conf.plotType = LINE;
|
|
break;
|
|
case BAR:
|
|
conf.plotType = BAR;
|
|
break;
|
|
default:
|
|
conf.plotType = COLUMN;
|
|
conf.showErrorValue = true;
|
|
conf.errorBarWidthPercent = 0;
|
|
isCandleStick = true;
|
|
break;
|
|
}
|
|
conf.animation = {
|
|
duration : 200
|
|
};
|
|
userMaxColWidth = pluck(chartAttr.maxcolwidth);
|
|
conf.maxColWidth = mathAbs(pluckNumber(
|
|
userMaxColWidth, 50)) || 1;
|
|
// Animation related attributes configuration
|
|
conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
|
|
chartAttr.defaultanimation, 1);
|
|
conf.animation = !enableAnimation ? false : {
|
|
duration: pluckNumber(chartAttr.animationduration, 1) * 1000
|
|
};
|
|
conf.lineAlpha = pluck(chartAttr.plotlinealpha, HUNDRED);
|
|
plotSpacePercent = mathMax(pluckNumber(chartAttr.plotspacepercent, 20) % 100, 0);
|
|
conf.plotSpacePercent = conf.groupPadding = plotSpacePercent / 200;
|
|
dataStore = dataset.components.data = dataset.components.data || (dataset.components.data = []);
|
|
conf.valuePadding = pluckNumber(JSONData.valuepadding, chartAttr.valuepadding, 2);
|
|
conf.plotBorderThickness = plotLineThickness;
|
|
// Iterate through all level data
|
|
for (index = 0; index < dataLength; index += 1) {
|
|
// Individual data obj
|
|
// for further manipulation
|
|
setData = dataArr[index];
|
|
dataObj = dataStore[index];
|
|
if (!dataObj) {
|
|
dataObj = dataStore[index] = {};
|
|
}
|
|
!dataObj.config && (dataObj.config = {});
|
|
!dataObj.graphics && (dataObj.graphics = {});
|
|
config = dataObj.config;
|
|
if (setData && !setData.vline) {
|
|
config.setLink = pluck(setData.link);
|
|
open = config.open = numberFormatter.getCleanValue(setData.open);
|
|
close = config.close = numberFormatter.getCleanValue(setData.close);
|
|
high = config.high = numberFormatter.getCleanValue(setData.high);
|
|
low = config.low = numberFormatter.getCleanValue(setData.low);
|
|
volume = config.volume = numberFormatter.getCleanValue(setData.volume, true);
|
|
if (volume !== null) {
|
|
chart.config.drawVolume = true;
|
|
}
|
|
x = config.x = numberFormatter.getCleanValue(setData.x);
|
|
openVal = config.openVal = isCandleStick ? mathAbs(close - open) : open;
|
|
closeVal = config.closeVal = mathMin(open, close);
|
|
yVal = config.yVal = mathMax(open, close);
|
|
isLine = plotPriceAs === LINE ? 1 : 0;
|
|
minValue = mathMin(open, close, high, low);
|
|
maxValue = mathMax(open, close, high, low);
|
|
|
|
valueText = parseUnsafeString(getValidValue(setData.valuetext, BLANK));
|
|
|
|
setBorderColor = getFirstColor(pluck(setData.bordercolor, close < open ? bearBorderColor :
|
|
bullBorderColor));
|
|
setAlpha = pluck(setData.alpha, isLine ? conf.lineAlpha : HUNDRED);
|
|
setColor = getFirstColor(pluck(setData.color, close < open ? bearFillColor :
|
|
bullFillColor));
|
|
dashStyle = Boolean(pluckNumber(setData.dashed)) ? getDashStyle(plotLineDashLen,
|
|
plotLineDashGap) : DASH_DEF;
|
|
config.dashStyle = dashStyle;
|
|
// Set alpha of the shadow
|
|
pointShadow = {
|
|
opacity: setAlpha / 100
|
|
};
|
|
config.color = isCandleStick ? setColor : setBorderColor,
|
|
config.alpha = setAlpha;
|
|
/*
|
|
* Storing the set level color and set level alpha which is required in drawing of line
|
|
* In line we are checking setColor and setAlpha of current line segment is same as the previous
|
|
* line segment's setColor and setAlpha by accesing config.setColor and config.setAlpha
|
|
*/
|
|
config.setColor = config.color;
|
|
config.setAlpha = config.alpha;
|
|
config.anchorImageUrl = pluck(setData.anchorimageurl, JSONData.anchorimageurl,
|
|
chartAttr.anchorimageurl);
|
|
// Finally add the data
|
|
// we call getPointStub function that manage displayValue, toolText and link
|
|
borderColor = config.borderColor = setBorderColor;
|
|
config.borderAlpha = config.plotLineAlpha;
|
|
config.colorArr = [{
|
|
color: config.color,
|
|
alpha: config.alpha
|
|
},
|
|
{
|
|
color: config.borderColor,
|
|
alpha: config.borderAlpha
|
|
}];
|
|
config.anchorSides = pluckNumber(setData.anchorsides, JSONData.anchorsides,
|
|
chartAttr.anchorsides);
|
|
config.symbol = mapSymbolName(config.anchorSides).split(UNDERSCORE);
|
|
config.anchorProps = {
|
|
enabled: drawAnchors,
|
|
bgColor: setAnchorBgColor,
|
|
symbol: config.symbol,
|
|
bgAlpha: ((setAnchorBgAlpha * setAnchorAlpha) / 100) + BLANK,
|
|
borderColor: setAnchorBorderColor,
|
|
borderAlpha: setAnchorAlpha,
|
|
anchorAlpha: setAnchorAlpha,
|
|
borderThickness: setAnchorBorderThickness,
|
|
imageUrl: config.anchorImageUrl,
|
|
radius: setAnchorRadius,
|
|
imageScale: pluckNumber(setData.imagescale, JSONData.imagescale, chartAttr.imagescale, 100),
|
|
imagePadding: pluckNumber(setData.anchorimagepadding, JSONData.anchorimagepadding,
|
|
chartAttr.anchorimagepadding, 1),
|
|
imageAlpha: pluckNumber(JSONData.anchorimagealpha, chartAttr.anchorimagealpha, 100),
|
|
startAngle: setAnchorAngle
|
|
};
|
|
config.showValue = 1;
|
|
config.hoverEffects = {};
|
|
switch (conf.plotType) {
|
|
case LINE:
|
|
config.y = close;
|
|
config.link = pluck(setData.link);
|
|
break;
|
|
case COLUMN:
|
|
config.y = mathAbs(close - open);
|
|
config.previousY = closeVal;
|
|
config.link = pluck(setData.link);
|
|
config.errorValue = [];
|
|
if (high - yVal > 0) {
|
|
config.errorValue.push({
|
|
errorValue: high - yVal,
|
|
errorStartValue: yVal,
|
|
errorBarColor: borderColor,
|
|
errorBarThickness: plotLineThickness,
|
|
opacity: 1
|
|
});
|
|
}
|
|
if (low - closeVal < 0) {
|
|
config.errorValue.push({
|
|
errorValue: low - closeVal,
|
|
errorStartValue: closeVal,
|
|
errorBarColor: borderColor,
|
|
errorBarThickness: plotLineThickness,
|
|
opacity: 1
|
|
});
|
|
}
|
|
break;
|
|
default:
|
|
config.y = open;
|
|
config.previousY = close;
|
|
config.link = pluck(setData.link);
|
|
break;
|
|
}
|
|
config.setValue = config.y;
|
|
|
|
if (minValue !== null) {
|
|
(!yMax && yMax !== 0) && (yMax = minValue);
|
|
(!yMin && yMin !== 0) && (yMin = minValue);
|
|
yMax = mathMax(yMax, minValue);
|
|
yMin = mathMin(yMin, minValue);
|
|
}
|
|
if (maxValue !== null) {
|
|
(!yMax && yMax !== 0) && (yMax = maxValue);
|
|
(!yMin && yMin !== 0) && (yMin = maxValue);
|
|
yMax = mathMax(yMax, maxValue);
|
|
yMin = mathMin(yMin, maxValue);
|
|
}
|
|
if (x !== null) {
|
|
xMax = mathMax(xMax, x);
|
|
xMin = mathMin(xMin, x);
|
|
}
|
|
|
|
toolText = this._parseToolText(index);
|
|
config.toolText = toolText;
|
|
config.toolTipValue = BLANKSTRING;
|
|
x = x ? x : index + 1;
|
|
config.x = x;
|
|
|
|
displayValue = config.displayValue = parseUnsafeString(pluck(setData.displayvalue,
|
|
setData.valuetext, BLANK));
|
|
config.high = mathMax(open, close, high, low);
|
|
config.low = mathMin(open, close, high, low);
|
|
config.shadow = pointShadow;
|
|
}
|
|
}
|
|
conf.yMax = yMax;
|
|
conf.yMin = yMin;
|
|
conf.xMax = xMax;
|
|
conf.xMin = xMin;
|
|
|
|
},
|
|
_parseToolText: function (i) {
|
|
var dataset = this,
|
|
conf = dataset.config,
|
|
setDataArr = dataset.JSONData.data,
|
|
data = dataset.components.data,
|
|
chart = dataset.chart,
|
|
xAxis = chart.components.xAxis[0],
|
|
chartAttr = chart.jsonData.chart,
|
|
isLine = conf.plotType === LINE ? 1 : 0,
|
|
toolText,
|
|
BLANK = BLANKSTRING,
|
|
setData = setDataArr[i],
|
|
config = data[i].config,
|
|
label = xAxis.getLabel(config.x).label,
|
|
open = config.open,
|
|
close = config.close,
|
|
yAxis = dataset.yAxis,
|
|
high = config.high,
|
|
low = config.low,
|
|
volume = config.volume,
|
|
volumeToolText = volume !== undefined ? setData.volumetooltext : undefined;
|
|
|
|
//create the tooltext
|
|
if (!conf.showTooltip) {
|
|
toolText = BLANK;
|
|
} else {
|
|
toolText = getValidValue(parseUnsafeString(pluck(volumeToolText,
|
|
setData.tooltext, conf.volumeToolText, conf.toolText)));
|
|
|
|
if (toolText !== undefined) {
|
|
toolText = parseTooltext(toolText, [3, 5, 6, 10, 54, 55, 56, 57,
|
|
58, 59, 60, 61, 81, 82
|
|
], {
|
|
label: label,
|
|
yaxisName: parseUnsafeString(chartAttr.yaxisname),
|
|
xaxisName: parseUnsafeString(chartAttr.xaxisname),
|
|
openValue: setData.open,
|
|
openDataValue:yAxis.dataLabels(open),
|
|
closeValue: setData.close,
|
|
closeDataValue:yAxis.dataLabels(close),
|
|
highValue: setData.high,
|
|
highDataValue:yAxis.dataLabels(high),
|
|
lowValue: setData.low,
|
|
lowDataValue:yAxis.dataLabels(low),
|
|
volumeValue: setData.volume,
|
|
volumeDataValue:yAxis.dataLabels(volume)
|
|
}, setData, chartAttr);
|
|
} else {
|
|
toolText = (open !== null && !isLine) ? BOLDSTARTTAG + 'Open:' + BOLDENDTAG + BLANKSPACE +
|
|
yAxis.dataLabels(open) +
|
|
BREAKSTRING : BLANK;
|
|
toolText += close !== null ? BOLDSTARTTAG + 'Close:' + BOLDENDTAG + BLANKSPACE +
|
|
yAxis.dataLabels(close) + BREAKSTRING :
|
|
BLANK;
|
|
toolText += (high !== null && !isLine) ? BOLDSTARTTAG + 'High:' + BOLDENDTAG + BLANKSPACE +
|
|
yAxis.dataLabels(high) +
|
|
BREAKSTRING : BLANK;
|
|
toolText += (low !== null && !isLine) ? BOLDSTARTTAG + 'Low:' + BOLDENDTAG + BLANKSPACE +
|
|
yAxis.dataLabels(low) +
|
|
BREAKSTRING : BLANK;
|
|
toolText += volume !== null ? BOLDSTARTTAG + 'Volume:' + BOLDENDTAG + BLANKSPACE +
|
|
yAxis.dataLabels(volume) : BLANK;
|
|
}
|
|
}
|
|
return toolText;
|
|
},
|
|
// Initialization of dataset of candlestick chart
|
|
init: function (datasetJSON, type) {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
yAxis;
|
|
if (type === VOLUME) {
|
|
yAxis = chart.components.yAxis[1];
|
|
}
|
|
else {
|
|
yAxis = chart.components.yAxis[0];
|
|
}
|
|
|
|
dataset.yAxis = yAxis;
|
|
dataset.components = {
|
|
|
|
};
|
|
|
|
dataset.graphics = {
|
|
|
|
};
|
|
dataset.JSONData = datasetJSON;
|
|
dataset.visible = 1;
|
|
dataset.plotType = type;
|
|
dataset.configure();
|
|
|
|
},
|
|
_configureVolume: function () {
|
|
var dataset = this,
|
|
conf = dataset.config,
|
|
chart = dataset.chart,
|
|
chartComponents = chart.components,
|
|
rawDataObj = chart.jsonData,
|
|
JSONData = dataset.JSONData,
|
|
dataArr = JSONData.data || [],
|
|
chartAttr = rawDataObj.chart,
|
|
BLANK = BLANKSTRING,
|
|
dataLength = dataArr.length,
|
|
colorM = chartComponents.colorManager,
|
|
valueText,
|
|
setColor,
|
|
setBorderColor,
|
|
setAlpha,
|
|
dashStyle,
|
|
pointShadow,
|
|
index,
|
|
dataObj,
|
|
toolText,
|
|
open,
|
|
close,
|
|
high,
|
|
low,
|
|
volume,
|
|
x,
|
|
closeVal,
|
|
borderColor,
|
|
numberFormatterAttrs,
|
|
//Candle stick properties.
|
|
//Bear fill and border color - (Close lower than open)
|
|
bearBorderColor = conf.bearBorderColor =
|
|
getFirstColor(pluck(chartAttr.bearbordercolor, COLOR_B90000)),
|
|
bearFillColor = conf.bearFillColor =
|
|
getFirstColor(pluck(chartAttr.bearfillcolor, COLOR_B90000)),
|
|
//Bull fill and border color - Close higher than open
|
|
bullBorderColor = conf.bullBorderColor =
|
|
getFirstColor(pluck(chartAttr.bullbordercolor,
|
|
colorM.getColor('canvasBorderColor'))),
|
|
bullFillColor = conf.bullFillColor =
|
|
getFirstColor(pluck(chartAttr.bullfillcolor,
|
|
COLOR_FFFFFF)),
|
|
showVPlotBorder = pluckNumber(chartAttr.showvplotborder, 1),
|
|
//VPlotBorder is border properties for the volume chart.
|
|
vPlotBorderThickness = showVPlotBorder ? pluckNumber(chartAttr.vplotborderthickness, 1) : 0,
|
|
plotLineDashLen = conf.plotLineDashLen = pluckNumber(chartAttr.plotlinedashlen, 5),
|
|
plotLineDashGap = conf.plotLineDashGap = pluckNumber(chartAttr.plotlinedashgap, 4),
|
|
openVal,
|
|
dataStore,
|
|
setData,
|
|
config,
|
|
enableAnimation,
|
|
isCandleStick = true,
|
|
plotSpacePercent,
|
|
yAxis = dataset.yAxis,
|
|
yMax = -Infinity,
|
|
yMin = +Infinity,
|
|
xMax = -Infinity,
|
|
xMin = +Infinity,
|
|
userMaxColWidth,
|
|
vNumberFormatter = chart.components.vNumberFormatter;
|
|
conf.plotType = COLUMN;
|
|
conf.parentYAxis = 1;
|
|
conf.volumeToolText = getValidValue(parseUnsafeString(pluck(JSONData.volumetooltext,
|
|
chartAttr.volumetooltext, chartAttr.plottooltext)));
|
|
// Dataset seriesname
|
|
conf.name = getValidValue(JSONData.seriesname);
|
|
conf.showTooltip = pluck(chartAttr.showtooltip, 1);
|
|
// Animation related attributes configuration
|
|
conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
|
|
chartAttr.defaultanimation, 1);
|
|
conf.animation = !enableAnimation ? false : {
|
|
duration: pluckNumber(chartAttr.animationduration, 1) * 1000
|
|
};
|
|
userMaxColWidth = pluck(chartAttr.maxcolwidth);
|
|
conf.maxColWidth = mathAbs(pluckNumber(
|
|
userMaxColWidth, 50)) || 1;
|
|
plotSpacePercent = mathMax(pluckNumber(chartAttr.plotspacepercent, 20) % 100, 0);
|
|
conf.plotSpacePercent = conf.groupPadding = plotSpacePercent / 200;
|
|
conf.plotBorderThickness = vPlotBorderThickness;
|
|
dataStore = dataset.components.data = dataset.components.data || (dataset.components.data = []);
|
|
numberFormatterAttrs = extend2(extend2({}, chartAttr), {
|
|
forcedecimals: getFirstValue(chartAttr.forcevdecimals,
|
|
chartAttr.forcedecimals),
|
|
forceyaxisvaluedecimals: getFirstValue(
|
|
chartAttr.forcevyaxisvaluedecimals,
|
|
chartAttr.forceyaxisvaluedecimals),
|
|
yaxisvaluedecimals: getFirstValue(
|
|
chartAttr.vyaxisvaluedecimals,
|
|
chartAttr.yaxisvaluedecimals),
|
|
formatnumber: getFirstValue(chartAttr.vformatnumber,
|
|
chartAttr.formatnumber),
|
|
formatnumberscale: getFirstValue(
|
|
chartAttr.vformatnumberscale,
|
|
chartAttr.formatnumberscale),
|
|
defaultnumberscale: getFirstValue(
|
|
chartAttr.vdefaultnumberscale,
|
|
chartAttr.defaultnumberscale),
|
|
numberscaleunit: getFirstValue(
|
|
chartAttr.vnumberscaleunit, chartAttr.numberscaleunit),
|
|
vnumberscalevalue: getFirstValue(
|
|
chartAttr.vnumberscalevalue,
|
|
chartAttr.numberscalevalue),
|
|
scalerecursively: getFirstValue(
|
|
chartAttr.vscalerecursively,
|
|
chartAttr.scalerecursively),
|
|
maxscalerecursion: getFirstValue(
|
|
chartAttr.vmaxscalerecursion,
|
|
chartAttr.maxscalerecursion),
|
|
scaleseparator: getFirstValue(chartAttr.vscaleseparator,
|
|
chartAttr.scaleseparator),
|
|
numberprefix: getFirstValue(chartAttr.vnumberprefix,
|
|
chartAttr.numberprefix),
|
|
numbersuffix: getFirstValue(chartAttr.vnumbersuffix,
|
|
chartAttr.numbersuffix),
|
|
decimals: getFirstValue(chartAttr.vdecimals,
|
|
chartAttr.decimals)
|
|
});
|
|
if (!vNumberFormatter) {
|
|
vNumberFormatter = chart.components.vNumberFormatter = new lib.NumberFormatter(chart,
|
|
numberFormatterAttrs);
|
|
}
|
|
else {
|
|
vNumberFormatter.configure(numberFormatterAttrs);
|
|
}
|
|
|
|
|
|
|
|
yAxis.setNumberFormatter(vNumberFormatter);
|
|
// Iterate through all level data
|
|
for (index = 0; index < dataLength; index += 1) {
|
|
// Individual data obj
|
|
// for further manipulation
|
|
setData = dataArr[index];
|
|
dataObj = dataStore[index];
|
|
if (!dataObj) {
|
|
dataObj = dataStore[index] = {};
|
|
}
|
|
!dataObj.config && (dataObj.config = {});
|
|
!dataObj.graphics && (dataObj.graphics = {});
|
|
config = dataObj.config;
|
|
if (setData && !setData.vline) {
|
|
open = config.open = yAxis.getCleanValue(setData.open);
|
|
close = config.close = yAxis.getCleanValue(setData.close);
|
|
high = config.high = yAxis.getCleanValue(setData.high);
|
|
low = config.low = yAxis.getCleanValue(setData.low);
|
|
volume = config.volume = yAxis.getCleanValue(setData.volume, true);
|
|
x = config.x = yAxis.getCleanValue(setData.x);
|
|
openVal = config.openVal = isCandleStick ? mathAbs(close - open) : open;
|
|
closeVal = config.closeVal = mathMin(open, close);
|
|
|
|
yMax = mathMax(yMax, volume);
|
|
yMin = mathMin(yMin, volume);
|
|
xMax = mathMax(xMax, x);
|
|
xMin = mathMin(xMin, x);
|
|
valueText = parseUnsafeString(getValidValue(setData.valuetext, BLANK));
|
|
|
|
setBorderColor = getFirstColor(pluck(setData.bordercolor, close < open ? bearBorderColor :
|
|
bullBorderColor));
|
|
setAlpha = pluck(setData.alpha, HUNDRED);
|
|
setColor = getFirstColor(pluck(setData.color, close < open ? bearFillColor :
|
|
bullFillColor));
|
|
dashStyle = config.dashStyle = Boolean(pluckNumber(setData.dashed)) ?
|
|
getDashStyle(plotLineDashLen, plotLineDashGap) : DASH_DEF;
|
|
// Set alpha of the shadow
|
|
pointShadow = {
|
|
opacity: setAlpha / 100
|
|
};
|
|
config.color = isCandleStick ? setColor : setBorderColor,
|
|
config.alpha = setAlpha;
|
|
config.setLink = setData.link;
|
|
config.borderWidth = vPlotBorderThickness;
|
|
borderColor = config.borderColor = setBorderColor;
|
|
config.borderAlpha = pluck(config.plotLineAlpha, setAlpha);
|
|
config.y = volume;
|
|
config.colorArr = [{
|
|
color: config.color,
|
|
alpha: config.alpha
|
|
},
|
|
{
|
|
color: config.borderColor,
|
|
alpha: config.borderAlpha
|
|
}];
|
|
config.setValue = config.y;
|
|
|
|
//create the tooltext
|
|
toolText = this._parseToolText(index);
|
|
config.toolText = toolText;
|
|
config.toolTipValue = BLANKSTRING;
|
|
x = x ? x : index + 1;
|
|
config.x = x;
|
|
config.shadow = pointShadow;
|
|
}
|
|
}
|
|
conf.yMax = yMax;
|
|
conf.yMin = yMin;
|
|
conf.xMax = xMax;
|
|
conf.xMin = xMin;
|
|
|
|
},
|
|
draw: function () {
|
|
var dataset = this,
|
|
conf = dataset.config,
|
|
plotType = conf.plotType,
|
|
sortedData = dataset.JSONData && dataset.JSONData.data.slice();
|
|
sortedData.sort(function (a, b) {
|
|
return a.x - b.x;
|
|
});
|
|
dataset.JSONData.sortedData = sortedData;
|
|
if (plotType === LINE) {
|
|
this.__base__.draw.call(dataset);
|
|
}
|
|
else if (plotType === COLUMN) {
|
|
this._drawColumn();
|
|
if (conf.showErrorValue) {
|
|
this._drawErrorValue();
|
|
}
|
|
}
|
|
else {
|
|
this._drawCandlestickBar();
|
|
}
|
|
|
|
dataset.drawn = true;
|
|
},
|
|
_drawColumn: function () {
|
|
var dataSet = this,
|
|
JSONData = dataSet.JSONData,
|
|
chart = dataSet.chart,
|
|
jobList = chart.getJobList(),
|
|
chartAttr = dataSet.chart.jsonData.chart,
|
|
conf = dataSet.config,
|
|
datasetIndex = dataSet.index,
|
|
setDataArr = JSONData.data,
|
|
dataSetLen = setDataArr && setDataArr.length,
|
|
len,
|
|
setData,
|
|
attr,
|
|
i,
|
|
visible = dataSet.visible,
|
|
paper = chart.components.paper,
|
|
xAxis = chart.components.xAxis[0],
|
|
yAxis = dataSet.yAxis,
|
|
xPos,
|
|
yPos,
|
|
crispBox,
|
|
layers = chart.graphics,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
getValidValue = lib.getValidValue,
|
|
R = lib.Raphael,
|
|
trackerConfig,
|
|
showTooltip = conf.showTooltip,
|
|
animObj = chart.get(configStr, animationObjStr),
|
|
animationDuration = animObj.duration,
|
|
dummyAnimElem = animObj.dummyObj,
|
|
dummyAnimObj = animObj.animObj,
|
|
groupMaxWidth = xAxis.getPVR(),
|
|
definedGroupPadding = conf.definedGroupPadding,
|
|
plotSpacePercent = conf.plotSpacePercent,
|
|
plotPaddingPercent = conf.plotPaddingPercent,
|
|
groupPadding = plotSpacePercent,
|
|
numOfColumns = 1,
|
|
columnPosition = 0,
|
|
maxColWidth = conf.maxColWidth,
|
|
overlapColumns = 0,
|
|
// Calculating the net width occupied by bars for each category
|
|
groupNetWidth = (1 - definedGroupPadding * 0.01) * groupMaxWidth || mathMin(
|
|
groupMaxWidth * (1 - groupPadding * 2),
|
|
maxColWidth * numOfColumns
|
|
),
|
|
groupNetHalfWidth = groupNetWidth / 2,
|
|
columnWidth = groupNetWidth / numOfColumns,
|
|
plotPadding = numOfColumns > 1 ? !overlapColumns && plotPaddingPercent === UNDEFINED ?
|
|
4 :
|
|
plotPaddingPercent > 0 ? (columnWidth * plotPaddingPercent / 100) : 0 : 0,
|
|
plotEffectivePadding = mathMin(columnWidth - 1, plotPadding),
|
|
xPosOffset = (columnPosition * columnWidth) - groupNetHalfWidth + plotEffectivePadding / 2,
|
|
height,
|
|
toolText,
|
|
dataStore = dataSet.components.data,
|
|
dataObj,
|
|
setTooltext,
|
|
setElement,
|
|
setLink,
|
|
setValue,
|
|
eventArgs,
|
|
displayValue,
|
|
groupId,
|
|
x,
|
|
config,
|
|
isPositive,
|
|
yBase = yAxis.getAxisBase(),
|
|
yBasePos = yAxis.yBasePos = yAxis.getAxisPosition(yBase),
|
|
previousY,
|
|
previousYPos,
|
|
heightBase = 0,
|
|
plotBorderThickness = conf.plotBorderThickness,
|
|
plotRadius = conf.plotRadius || 0,
|
|
container = dataSet.graphics.container,
|
|
shadowContainer = dataSet.graphics.shadowContainer,
|
|
colorArr,
|
|
plotBorderDashStyle,
|
|
isCrisp = true,
|
|
width,
|
|
borderWidth,
|
|
shadow,
|
|
isNewElem,
|
|
animFlag = !chart.config.plotAnimDone,
|
|
removeDataArr = dataSet.components.removeDataArr || [],
|
|
removeDataArrLen = removeDataArr.length,
|
|
Column = FusionCharts.get(COMPONENT, [DATASET, COLUMN]),
|
|
drawLabel = Column.prototype.drawLabel,
|
|
initAnimCallBack = function () {
|
|
var graphics = dataSet.graphics,
|
|
errorGroupContainer = graphics.errorGroupContainer;
|
|
errorGroupContainer && errorGroupContainer.show();
|
|
},
|
|
datasetLayer = layers.datasetGroup,
|
|
pool = dataSet.components.pool || [],
|
|
components = chart.components,
|
|
canvas = components.canvas,
|
|
canvasConfig = canvas.config,
|
|
volumeCanvas = components.canvasVolume,
|
|
vCanvasConfig = volumeCanvas.config,
|
|
rollOverBandColor = chart.config.rollOverBandColor,
|
|
rollOverBandPath,
|
|
rollOverBand,
|
|
sortedData;
|
|
// clickFunc = function (setDataArr) {
|
|
// var ele = this;
|
|
// plotEventHandler.call(ele, chart, setDataArr);
|
|
// };
|
|
/*
|
|
* Creating a container group for the graphic element of column plots if
|
|
* not present and attaching it to its parent group.
|
|
*/
|
|
if (!container) {
|
|
container = dataSet.graphics.container = paper.group(columnStr, datasetLayer);
|
|
if (!visible) {
|
|
container.hide();
|
|
}
|
|
}
|
|
|
|
|
|
//chart.addCSSDefinition('.fusioncharts-datalabels .fusioncharts-label', labelCSS);
|
|
|
|
/*
|
|
* Creating the shadow element container group for each plots if not present
|
|
* and attaching it its parent group.
|
|
*/
|
|
if (!shadowContainer) {
|
|
// Always sending the shadow group to the back of the plots group.
|
|
shadowContainer = dataSet.graphics.shadowContainer =
|
|
paper.group(shadowStr, datasetLayer).toBack();
|
|
if (!visible) {
|
|
shadowContainer.hide();
|
|
}
|
|
|
|
}
|
|
|
|
if (!rollOverBand) {
|
|
rollOverBandPath = [M, 0, canvasConfig.canvasTop, L, 0, canvasConfig.canvasBottom, M, 0,
|
|
vCanvasConfig.canvasTop - vCanvasConfig.canvasBorderWidth,
|
|
L, 0, vCanvasConfig.canvasTop + vCanvasConfig.canvasHeight +
|
|
vCanvasConfig.canvasBorderWidth / 2];
|
|
|
|
if (!rollOverBand) {
|
|
rollOverBand = chart.graphics.rollOverBand = paper.path(datasetLayer);
|
|
}
|
|
rollOverBand.transform(BLANKSTRING);
|
|
rollOverBand.attr({
|
|
path: rollOverBandPath,
|
|
'stroke-width': columnWidth,
|
|
ishot: true,
|
|
stroke: rollOverBandColor,
|
|
'stroke-linecap': 'butt'
|
|
});
|
|
rollOverBand.data('width', columnWidth);
|
|
rollOverBand.toBack();
|
|
rollOverBand.hide();
|
|
}
|
|
|
|
len = dataSetLen;
|
|
width = columnWidth;
|
|
conf.columnWidth = columnWidth;
|
|
// Create plot elements.
|
|
for (i = 0; i < len; i++) {
|
|
setData = setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
setData.originalIndex = i;
|
|
config = dataObj && dataObj.config;
|
|
setLink = config.setLink;
|
|
setValue = config.y;
|
|
x = pluckNumber(config.x, i);
|
|
borderWidth = config.borderWidth;
|
|
colorArr = config.colorArr;
|
|
shadow = config.shadow;
|
|
isPositive = setValue >= 0;
|
|
// Skipping the remaining calculations if data entered by the user is null for a plot.
|
|
if (setValue === null) {
|
|
continue;
|
|
}
|
|
setLink = config.setLink;
|
|
|
|
// Creating the data structure if not present for storing the graphics elements.
|
|
if (!dataObj.graphics) {
|
|
dataStore[i].graphics = {};
|
|
|
|
}
|
|
groupId = dataSet.index + UNDERSCORE + i;
|
|
config.groupId = groupId;
|
|
displayValue = config.displayValue;
|
|
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
|
|
JSONData.plottooltext, chartAttr.plottooltext)));
|
|
previousY = config.previousY;
|
|
// Getting the previous yposition of the plot and calculating the current yposition of the plot.
|
|
previousYPos = yAxis.getAxisPosition(previousY || yBase);
|
|
yPos = yAxis.getAxisPosition(setValue + (previousY || 0));
|
|
xPos = xAxis.getAxisPosition(x) + xPosOffset;
|
|
height = mathAbs(yPos - previousYPos);
|
|
// crisp column
|
|
crispBox = R.crispBound(xPos, yPos, width, height,
|
|
plotBorderThickness);
|
|
if (isCrisp) {
|
|
xPos = crispBox.x;
|
|
yPos = crispBox.y;
|
|
width = crispBox.width;
|
|
height = crispBox.height || 1;
|
|
}
|
|
|
|
// Setting the final tooltext.
|
|
toolText = config.toolText;
|
|
plotBorderDashStyle = config.dashStyle;
|
|
dataObj.trackerConfig = {};
|
|
trackerConfig = dataObj.trackerConfig;
|
|
eventArgs = trackerConfig.eventArgs = trackerConfig.eventArgs || {};
|
|
|
|
// Setting the event arguments.
|
|
eventArgs.index = i;
|
|
eventArgs.link = setLink;
|
|
eventArgs.value = setValue;
|
|
eventArgs.displayValue = displayValue;
|
|
eventArgs.categoryLabel = xAxis.getLabel(i).label;
|
|
eventArgs.toolText = toolText;
|
|
eventArgs.id = BLANKSTRING;
|
|
eventArgs.datasetIndex = datasetIndex;
|
|
eventArgs.datasetName = JSONData.seriesname;
|
|
eventArgs.visible = visible;
|
|
// eventArgs = {
|
|
// index: i,
|
|
// link: setLink,
|
|
// value: setValue,
|
|
// displayValue: displayValue,
|
|
// categoryLabel: xAxis.getLabel(i).label,
|
|
// toolText: toolText,
|
|
// id: BLANKSTRING,
|
|
// datasetIndex: datasetIndex,
|
|
// datasetName: JSONData.seriesname,
|
|
// visible: visible
|
|
// };
|
|
|
|
//todo- remove _ to make it public
|
|
dataObj._xPos = xPos;
|
|
dataObj._yPos = yPos;
|
|
dataObj._height = height;
|
|
dataObj._width = columnWidth;
|
|
setElement = dataObj.graphics.element;
|
|
isNewElem = false;
|
|
/*
|
|
* If the data plots are not present then they are created, else only attributes are set for the
|
|
* existing plots.
|
|
*/
|
|
if (!setElement) {
|
|
if (pool.element && pool.element.length) {
|
|
setElement = dataObj.graphics.element = pool.element.shift();
|
|
}
|
|
else {
|
|
setElement = dataObj.graphics.element = paper.rect(container);
|
|
isNewElem = true;
|
|
if (animationDuration) {
|
|
setElement.attr({
|
|
x: xPos,
|
|
y: yBasePos,
|
|
width: width,
|
|
height: heightBase
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
attr = config._elemPositions;
|
|
|
|
if (!attr) {
|
|
attr = config._elemPositions = {};
|
|
}
|
|
|
|
attr.x = xPos;
|
|
attr.y = yPos;
|
|
attr.width = width;
|
|
attr.height = height;
|
|
|
|
// Animate column plot for candlestick chart
|
|
setElement.show().animateWith(dummyAnimElem, dummyAnimObj, attr,
|
|
animationDuration, animObj.animType, animFlag && initAnimCallBack);
|
|
|
|
attr = config._elemCosmetics;
|
|
|
|
if (!attr) {
|
|
attr = config._elemCosmetics = {};
|
|
}
|
|
|
|
attr.r = plotRadius;
|
|
attr.ishot = !showTooltip;
|
|
attr.fill = toRaphaelColor(colorArr[0]);
|
|
attr.stroke = toRaphaelColor(colorArr[1]);
|
|
attr['stroke-width'] = plotBorderThickness;
|
|
attr['stroke-dasharray'] = plotBorderDashStyle;
|
|
attr['stroke-linejoin'] = miterStr;
|
|
attr.visibility = visible;
|
|
attr.cursor = setLink ? POINTER : DEFAULT;
|
|
|
|
setElement.attr(attr).shadow(config.shadow, shadowContainer).data('dataObj', dataObj);
|
|
|
|
chart.config.plotAnimDone = true;
|
|
|
|
// If algorithmic mouseTracking is enabled then attach these data to setElement
|
|
// because tracker element will not be drawn
|
|
chart.config.enablemousetracking && setElement
|
|
.data(EVENTARGS, eventArgs)
|
|
.data(showHoverEffectStr, true/*showHoverEffect*/)
|
|
.data(SETROLLOVERATTR, config.setRolloverAttr || {})
|
|
.data(SETROLLOUTATTR, config.setRolloutAttr || {});
|
|
}
|
|
|
|
dataSet.drawn ? drawLabel.call(dataSet, 0, dataStore.length) :
|
|
jobList.labelDrawID.push(schedular.addJob(drawLabel, dataSet, [0, dataStore.length],
|
|
lib.priorityList.label));
|
|
// dataSet.drawTracker();
|
|
// drawLabel.call(dataSet, 0, dataStore.length);
|
|
for (i = 0; i < removeDataArrLen; i++) {
|
|
dataObj = removeDataArr[0];
|
|
if (!dataObj) {
|
|
continue;
|
|
}
|
|
dataSet._removeDataVisuals(dataObj.graphics);
|
|
removeDataArr.shift();
|
|
}
|
|
dataSet.drawn = true;
|
|
|
|
sortedData = dataSet.JSONData.data;
|
|
for (i = sortedData.length;i--;) {
|
|
dataSet.JSONData.data[i].originalIndex = i;
|
|
}
|
|
chart.config.toleranceBottom = canvasConfig.intermediarySpace +
|
|
(chart.config.canvasBorderWidth * 2);
|
|
},
|
|
|
|
_getHoveredPlot: function (chartX, chartY) {
|
|
var dataset = this,
|
|
conf = dataset.config,
|
|
plotType = conf.plotType;
|
|
if (plotType === LINE) {
|
|
return dataset._getHoveredPlotCandleLine(chartX, chartY);
|
|
}
|
|
else if (plotType === COLUMN) {
|
|
return dataset._getHoveredPlotCandleColumn(chartX, chartY);
|
|
}
|
|
},
|
|
|
|
_getHoveredPlotCandleLine: function (chartX, chartY) {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
chartConfig = chart.config,
|
|
canvas = chart.components.canvas,
|
|
canvasConf = canvas.config,
|
|
xAxis = chart.components.xAxis[0],
|
|
dataStore = dataset.components.data,
|
|
pointObj,
|
|
xMin,
|
|
xMax,
|
|
len = dataStore.length,
|
|
returnValue,
|
|
conf = dataset.config,
|
|
canvasLeft = chartConfig.canvasLeft,
|
|
canvasPaddingLeft = canvasConf.canvasPaddingLeft,
|
|
canvasPadding = canvasConf.canvasPadding,
|
|
axisX = chartX - canvasLeft - Math.max(canvasPaddingLeft, canvasPadding),
|
|
i,
|
|
maxRadius = conf && conf.radius || 0;
|
|
|
|
xMin = Math.floor(Math.max(xAxis.getValue(axisX - maxRadius), 0));
|
|
xMin = dataset.getPlotIndices(xMin);
|
|
|
|
xMax = Math.ceil(Math.min(xAxis.getValue(axisX + maxRadius), len - 1));
|
|
xMax = dataset.getPlotIndices(xMax);
|
|
|
|
for (i = xMin.length; i--;) {
|
|
pointObj = dataStore[xMin[i].originalIndex];
|
|
if (pointObj) {
|
|
returnValue = dataset.isWithinShape(pointObj, xMin[i].originalIndex, chartX, chartY);
|
|
if (returnValue) {
|
|
return returnValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = xMax.length; i--;) {
|
|
pointObj = dataStore[xMax[i].originalIndex];
|
|
if (pointObj) {
|
|
returnValue = dataset.isWithinShape(pointObj, xMax[i].originalIndex, chartX, chartY);
|
|
if (returnValue) {
|
|
return returnValue;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
_getHoveredPlotCandleColumn: function (chartX, chartY) {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
chartConfig = chart.config,
|
|
xAxis = chart.components.xAxis[0],
|
|
x,
|
|
canvas = chart.components.canvas,
|
|
canvasConfig = canvas.config,
|
|
canvasPadding = Math.max(canvasConfig.canvasPaddingLeft, canvasConfig.canvasPadding),
|
|
canvasLeft = chartConfig.canvasLeft,
|
|
pX,
|
|
i,
|
|
returnValue;
|
|
|
|
x = xAxis.getValue(chartX - canvasLeft - canvasPadding);
|
|
pX = dataset.getPlotIndices(x);
|
|
|
|
// Checking for overlap between two cosecutive column plots along x-axis
|
|
for (i = pX.length; i--;) {
|
|
if (dataset._checkPointerOverErrorBar(pX[i].originalIndex, chartX, chartY)) {
|
|
returnValue = dataset._checkPointerOverErrorBar(pX[i].originalIndex, chartX, chartY);
|
|
}
|
|
if (dataset._checkPointerOverColumn(pX[i].originalIndex, chartX, chartY)) {
|
|
returnValue = dataset._checkPointerOverColumn(pX[i].originalIndex, chartX, chartY);
|
|
}
|
|
}
|
|
return returnValue;
|
|
},
|
|
|
|
getPlotIndices: function (x) {
|
|
var dataset = this,
|
|
i,
|
|
minX = Math.floor(x),
|
|
maxX = Math.ceil(x),
|
|
data,
|
|
returnIndices = [],
|
|
sortedData = dataset.JSONData && dataset.JSONData.sortedData;
|
|
|
|
for (i = sortedData.length; i--;) {
|
|
data = dataset.JSONData.sortedData[i];
|
|
if (data.x >= minX && data.x <= maxX) {
|
|
returnIndices.push(data);
|
|
}
|
|
}
|
|
return returnIndices;
|
|
},
|
|
|
|
// Helper function of _checkPointerOverPlot().
|
|
_checkPointerOverErrorBar : function (pX, chartX, chartY) {
|
|
var dataset = this,
|
|
dataStore = dataset.components.data,
|
|
pointObj = dataStore[pX],
|
|
hovered,
|
|
errorBarArr,
|
|
errorBarCompArr,
|
|
len,
|
|
errorBarCompLen,
|
|
xPos,
|
|
yPos,
|
|
height,
|
|
width;
|
|
|
|
if (!pointObj) {
|
|
return;
|
|
}
|
|
|
|
errorBarArr = pointObj.errorBar;
|
|
|
|
if (!errorBarArr) {
|
|
return;
|
|
}
|
|
|
|
len = errorBarArr && errorBarArr.length;
|
|
while (len--) {
|
|
errorBarCompArr = errorBarArr[len];
|
|
errorBarCompLen = errorBarCompArr && errorBarCompArr.length;
|
|
while (errorBarCompLen--) {
|
|
if (!(errorBarCompArr[errorBarCompLen] && errorBarCompArr[errorBarCompLen]._xPos)) {
|
|
continue;
|
|
}
|
|
xPos = errorBarCompArr[errorBarCompLen]._xPos;
|
|
yPos = errorBarCompArr[errorBarCompLen]._yPos;
|
|
height = errorBarCompArr[errorBarCompLen]._height;
|
|
width = errorBarCompArr[errorBarCompLen]._width;
|
|
|
|
hovered = chartX >= xPos && chartX <= xPos + width &&
|
|
chartY >= yPos && chartY <= yPos + height;
|
|
|
|
if (hovered) {
|
|
return {
|
|
pointIndex: pX,
|
|
hovered: hovered,
|
|
pointObj: dataStore[pX]
|
|
};
|
|
}
|
|
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
_checkPointerOverColumn : function (pX, chartX, chartY) {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
chartConfig = chart.config,
|
|
plotBorderThickness = chartConfig.plotborderthickness,
|
|
showPlotBorder = chartConfig.showplotborder,
|
|
dataStore = dataset.components.data,
|
|
pointObj = dataStore[pX],
|
|
pY,
|
|
dx,
|
|
dy,
|
|
hovered,
|
|
halfPlotBorderThickness,
|
|
viewPortConfig = chartConfig.viewPortConfig,
|
|
x = viewPortConfig.x,
|
|
scaleX = viewPortConfig.scaleX,
|
|
dragTolerance = chartConfig.dragTolerance || 0;
|
|
|
|
if (!pointObj) {
|
|
return;
|
|
}
|
|
|
|
pY = pointObj.config.setValue;
|
|
|
|
plotBorderThickness = showPlotBorder ? plotBorderThickness : 0;
|
|
halfPlotBorderThickness = plotBorderThickness / 2;
|
|
|
|
halfPlotBorderThickness = halfPlotBorderThickness % 2 === 0 ? halfPlotBorderThickness + 1 :
|
|
Math.round(halfPlotBorderThickness);
|
|
|
|
if (pY !== null) {
|
|
|
|
dx = chartX - (pointObj._xPos - x * scaleX) + halfPlotBorderThickness;
|
|
dy = chartY - pointObj._yPos + halfPlotBorderThickness + (pY > 0 ? dragTolerance : 0);
|
|
|
|
hovered = dx >= 0 && dx <= pointObj._width + plotBorderThickness && dy >= 0 &&
|
|
dy <= pointObj._height + plotBorderThickness + (pY > 0 ? 0 : dragTolerance);
|
|
|
|
//hovered && console.log(dy, pointObj._height + plotBorderThickness + dragTolerance)
|
|
|
|
|
|
if (hovered) {
|
|
return {
|
|
pointIndex: pX,
|
|
hovered: hovered,
|
|
pointObj: dataStore[pX]
|
|
};
|
|
}
|
|
}
|
|
},
|
|
|
|
_firePlotEvent: function (eventType, plotIndex, e) {
|
|
var dataset = this,
|
|
conf = dataset.config,
|
|
plotType = conf.plotType;
|
|
if (plotType === LINE) {
|
|
return dataset.__base__._firePlotEvent.call(dataset, eventType, plotIndex, e);
|
|
}
|
|
else if (plotType === COLUMN) {
|
|
return FusionCharts.get('component',['dataset', 'column'])
|
|
.prototype._firePlotEvent.call(dataset, eventType, plotIndex, e);
|
|
}
|
|
},
|
|
|
|
_rolloverResponseSetter: function (chart, setElement, event) {
|
|
var dataset = this,
|
|
sharedAnchor = dataset.graphics.sharedAnchor,
|
|
elements = chart.graphics,
|
|
dataObj = setElement,//setElement.data && setElement.data('dataObj'),
|
|
xPos = dataObj._xPos,
|
|
rollOverBand = elements.rollOverBand,
|
|
width = dataObj._width || 0,
|
|
elem = setElement.graphics.element || sharedAnchor.element;
|
|
|
|
rollOverBand.transform(t + (xPos + width / 2) + COMMA + 0)
|
|
.show();
|
|
plotEventHandler.call(elem, chart, event, ROLLOVER);
|
|
},
|
|
_rolloutResponseSetter: function (chart, setElement, event) {
|
|
var dataset = this,
|
|
sharedAnchor = dataset.graphics.sharedAnchor,
|
|
elements = chart.graphics,
|
|
rollOverBand = elements.rollOverBand,
|
|
elem = setElement.graphics.element || sharedAnchor.element;
|
|
rollOverBand.hide();
|
|
plotEventHandler.call(elem, chart, event, ROLLOUT);
|
|
},
|
|
|
|
_removeDataVisuals : function (graphics) {
|
|
var dataSet = this,
|
|
pool = dataSet.components.pool || (dataSet.components.pool = {}),
|
|
elementPool,
|
|
ele,
|
|
graphicsObj,
|
|
j,
|
|
len;
|
|
if (graphics.graphics) {
|
|
graphics = graphics.graphics;
|
|
}
|
|
for (ele in graphics) {
|
|
elementPool = pool[ele] || (pool[ele] = []);
|
|
graphicsObj = graphics[ele];
|
|
if (graphicsObj instanceof Array) {
|
|
for (j = 0, len = graphicsObj.length; j < len; j++) {
|
|
dataSet._removeDataVisuals(graphicsObj[j]);
|
|
}
|
|
}
|
|
else {
|
|
if (graphicsObj.hide && typeof graphicsObj.hide === 'function') {
|
|
graphicsObj.hide();
|
|
}
|
|
}
|
|
elementPool.push(graphics[ele]);
|
|
|
|
}
|
|
|
|
},
|
|
// Function for drawing candlestick bars
|
|
_drawCandlestickBar: function () {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
chartComponents = chart.components,
|
|
config,
|
|
conf = dataset.config,
|
|
components = dataset.components,
|
|
data = components.data,
|
|
length = data.length,
|
|
xAxis = chartComponents.xAxis[0],
|
|
yAxis = dataset.yAxis,
|
|
layers = chart.graphics,
|
|
paper = chartComponents.paper,
|
|
numColumns = conf.numColumns || 1,
|
|
columnPosition = conf.columnPosition || 0,
|
|
groupMaxWidth = xAxis.getPVR(),
|
|
definedGroupPadding = conf.plotspacepercent,
|
|
groupPadding = conf.groupPadding,
|
|
maxColWidth = conf.maxColWidth,
|
|
groupNetWidth = (1 - definedGroupPadding * 0.01) * groupMaxWidth ||
|
|
mathMin(
|
|
groupMaxWidth * (1 - groupPadding * 2),
|
|
maxColWidth * numColumns
|
|
),
|
|
groupNetHalfWidth = groupNetWidth / 2,
|
|
columnWidth = groupNetWidth / numColumns,
|
|
xPosOffset = (columnPosition * columnWidth) - groupNetHalfWidth,
|
|
|
|
datasetLayer = layers.datasetGroup,
|
|
i,
|
|
set,
|
|
setLink,
|
|
x,
|
|
y,
|
|
previousY,
|
|
xPos,
|
|
yPos,
|
|
previousYPos,
|
|
height,
|
|
width,
|
|
animationObj = chart.get(configStr, animationObjStr) || {},
|
|
animationDuration = animationObj.duration,
|
|
dummyAnimElem = animationObj.dummyObj,
|
|
dummyAnimObj = animationObj.animObj,
|
|
group = datasetLayer,
|
|
container = dataset.graphics.container,
|
|
// marimekko variables
|
|
fixedWidth,
|
|
setElem,
|
|
hotElem,
|
|
pool = dataset.components.pool || {},
|
|
visible = dataset.visible,
|
|
targetGroup,
|
|
highPos,
|
|
lowPos,
|
|
halfW,
|
|
path,
|
|
removeDataArr = dataset.components.removeDataArr || [],
|
|
removeDataArrLen = removeDataArr.lengt ,
|
|
graphics;
|
|
if (!container) {
|
|
container = dataset.graphics.container = paper.group(columnStr, group);
|
|
if (!visible) {
|
|
container.hide();
|
|
}
|
|
}
|
|
|
|
targetGroup = container;
|
|
|
|
//draw plots
|
|
for (i = 0; i < length; i += 1) {
|
|
set = data[i];
|
|
config = set.config;
|
|
graphics = set.graphics;
|
|
y = config.y;
|
|
setElem = hotElem = null;
|
|
|
|
if (y === null) {
|
|
setElem = graphics.element;
|
|
}
|
|
// when valid value
|
|
else {
|
|
x = pluckNumber(config.x, i);
|
|
setLink = config.link;
|
|
config.setLink = config.link;
|
|
fixedWidth = config._FCW * groupMaxWidth;
|
|
|
|
xPos = xAxis.getAxisPosition(x);
|
|
previousY = config.previousY;
|
|
previousYPos = yAxis.getAxisPosition(previousY);
|
|
yPos = yAxis.getAxisPosition(y);
|
|
highPos = yAxis.getAxisPosition(config.high);
|
|
lowPos = yAxis.getAxisPosition(config.low);
|
|
|
|
height = mathAbs(yPos - previousYPos);
|
|
width = fixedWidth || columnWidth;
|
|
|
|
halfW = yPos < previousYPos ? xPosOffset : xPosOffset;
|
|
|
|
path = [M, xPos, lowPos, L, xPos, highPos,
|
|
M, xPos, yPos, L, (xPos + halfW), yPos,
|
|
M, xPos, previousYPos, L, (xPos - halfW), previousYPos
|
|
];
|
|
setElem = graphics.element;
|
|
if (!setElem) {
|
|
if (pool.element && pool.element.length) {
|
|
graphics.element = paper.path(group);
|
|
}
|
|
else {
|
|
setElem = graphics.element = paper.path(path, container);
|
|
}
|
|
}
|
|
|
|
// Animate candlestick bar element
|
|
setElem.show().animateWith(dummyAnimElem, dummyAnimObj, {
|
|
path: path
|
|
}, animationDuration, animationObj.animType);
|
|
|
|
chart.config.plotAnimDone = true;
|
|
|
|
setElem.attr({
|
|
fill: toRaphaelColor(config.color),
|
|
stroke: toRaphaelColor(config.borderColor),
|
|
'stroke-width': conf.linethickness,
|
|
'stroke-dasharray': config.dashStyle,
|
|
'stroke-linecap': ROUND,
|
|
'stroke-linejoin': ROUND,
|
|
'shape-rendering': 'crisp',
|
|
'cursor': setLink ? POINTER : BLANKSTRING,
|
|
'visibility': visibleStr
|
|
})
|
|
.shadow(config.shadow);
|
|
}
|
|
}
|
|
for (i = 0; i < removeDataArrLen; i++) {
|
|
dataset._removeDataVisuals(removeDataArr.shift());
|
|
}
|
|
},
|
|
_drawErrorValue: function () {
|
|
var dataSet = this,
|
|
JSONData = dataSet.JSONData,
|
|
trackerTolerance = 2,
|
|
conf = dataSet.config,
|
|
setDataArr = JSONData.data,
|
|
dataSetLen = setDataArr && setDataArr.length,
|
|
len,
|
|
setData,
|
|
i,
|
|
visible = dataSet.visible,
|
|
chart = dataSet.chart,
|
|
paper = chart.components.paper,
|
|
//elements = chart.elements,
|
|
yAxis = chart.components.yAxis[0],
|
|
dataStore = dataSet.components.data,
|
|
errorBarThickness,
|
|
errorBarWidthPercent = conf.errorBarWidthPercent,
|
|
errorBarColor,
|
|
layers = chart.graphics,
|
|
datasetLayer = layers.datasetGroup,
|
|
showTooltip = conf.showTooltip,
|
|
errorGroupContainer = dataSet.graphics.errorGroupContainer,
|
|
errorTrackerContainer = dataSet.graphics.errorTrackerContainer,
|
|
trackerLayer = layers.trackerGroup,
|
|
setLink,
|
|
xPos,
|
|
yPos,
|
|
//chartLogic = chart.logic,
|
|
useCrispErrorPath = 1,
|
|
dataObj,
|
|
setValue,
|
|
config,
|
|
crispY,
|
|
crispX,
|
|
errorPath,
|
|
errorValPos,
|
|
errorValuePosFactor,
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animationDuration = animationObj.duration,
|
|
dummyAnimElem = animationObj.dummyObj,
|
|
dummyAnimObj = animationObj.animObj,
|
|
errorValueArr,
|
|
errorValueObj,
|
|
errorValue,
|
|
errorStartPos,
|
|
errorLen,
|
|
errorStartValue,
|
|
errorBarWidth,
|
|
halfErrorBarW,
|
|
errorLineElem,
|
|
errorTrackerElem,
|
|
isNegative,
|
|
barXpos,
|
|
y,
|
|
barYpos,
|
|
barWidth,
|
|
drawn = dataSet.drawn,
|
|
toolText,
|
|
errorGraphics,
|
|
isNewElem,
|
|
// errorElemClick = function(e) {
|
|
// var ele = this;
|
|
// plotEventHandler.call(ele, chart, e);
|
|
// },
|
|
// getErrLinkClickFN = function(link) {
|
|
// return function() {
|
|
// (link !== undefined) &&
|
|
// linkedItems.linkClickFN.call({
|
|
// link: link
|
|
// }, chart);
|
|
// };
|
|
// },
|
|
pool = dataSet.components.pool || [],
|
|
errorElements,
|
|
errorElemLen,
|
|
removeErrorElem,
|
|
groupId,
|
|
graphicEle,
|
|
ii,
|
|
barHeight;
|
|
|
|
if (!errorGroupContainer) {
|
|
errorGroupContainer = dataSet.graphics.errorGroupContainer =
|
|
paper.group(errorBarStr, datasetLayer);
|
|
if (!visible) {
|
|
errorGroupContainer.hide();
|
|
}
|
|
}
|
|
|
|
if (!errorTrackerContainer) {
|
|
errorTrackerContainer = dataSet.graphics.errorTrackerContainer =
|
|
paper.group(errorHotStr, trackerLayer).toBack();
|
|
if (!visible) {
|
|
errorTrackerContainer.hide();
|
|
}
|
|
}
|
|
|
|
if (visible) {
|
|
errorGroupContainer.show();
|
|
errorTrackerContainer.show();
|
|
}
|
|
|
|
len = dataSetLen;
|
|
if (animationDuration && !drawn) {
|
|
errorGroupContainer.hide();
|
|
}
|
|
// Loop through each data points
|
|
for (i = 0; i < len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
config = dataObj && dataObj.config;
|
|
setValue = config.y;
|
|
setLink = config.setLink;
|
|
errorValueArr = config.errorValue;
|
|
errorLen = errorValueArr.length;
|
|
toolText = config.toolText;
|
|
!dataObj.graphics.error && (dataObj.graphics.error = []);
|
|
|
|
// Skipping the remaining calculations if data entered by the user is null for a plot.
|
|
if (setValue === null) {
|
|
continue;
|
|
}
|
|
setLink = config.setLink;
|
|
|
|
isNegative = (setValue < 0);
|
|
|
|
barXpos = dataObj._xPos;
|
|
barYpos = dataObj._yPos;
|
|
barWidth = dataObj._width;
|
|
barHeight = dataObj._height;
|
|
|
|
yPos = isNegative ? (barYpos +barHeight) : barYpos + barHeight;
|
|
xPos = barXpos + (barWidth / 2);
|
|
|
|
errorElements = dataObj.graphics.error;
|
|
errorElemLen = errorElements.length;
|
|
isNewElem = false;
|
|
if (errorElemLen > errorLen) {
|
|
|
|
for (ii = errorLen; ii < errorElemLen; ii++) {
|
|
removeErrorElem = errorElements.pop();
|
|
dataSet._removeDataVisuals(removeErrorElem);
|
|
}
|
|
}
|
|
dataObj.errorBar || (dataObj.errorBar = []);
|
|
//Loop through errorValue array
|
|
while (errorLen--) {
|
|
errorGraphics = dataObj.graphics.error[errorLen];
|
|
if (!errorGraphics) {
|
|
errorGraphics = dataObj.graphics.error[errorLen] = {};
|
|
}
|
|
errorTrackerElem = errorGraphics.errorTrackerElem;
|
|
errorLineElem = errorGraphics.errorLineElem;
|
|
errorValueObj = errorValueArr[errorLen];
|
|
errorValue = errorValueObj.errorValue;
|
|
errorStartValue = errorValueObj.errorStartValue;
|
|
errorBarColor = errorValueObj.errorBarColor;
|
|
errorBarThickness = errorValueObj.errorBarThickness;
|
|
errorStartPos = !isNaN(errorStartValue) ?
|
|
yAxis.getAxisPosition(errorStartValue) : yPos;
|
|
errorBarWidth = barWidth * (errorBarWidthPercent / 100);
|
|
halfErrorBarW = errorBarWidth / 2;
|
|
|
|
errorValuePosFactor = 1;
|
|
// Vertical Error drawing
|
|
errorValPos = yAxis.getAxisPosition(
|
|
(defined(errorStartValue) ? errorStartValue : y) + errorValue);
|
|
isNegative && (errorValPos = errorValPos + barHeight);
|
|
crispY = errorValPos;
|
|
crispX = xPos;
|
|
if (useCrispErrorPath) {
|
|
crispY = mathRound(errorValPos) +
|
|
(errorBarThickness % 2 / 2);
|
|
crispX = mathRound(xPos) +
|
|
(errorBarThickness % 2 / 2);
|
|
}
|
|
|
|
errorPath = [
|
|
M, crispX, errorStartPos,
|
|
V, crispY,
|
|
M, crispX - halfErrorBarW, crispY,
|
|
H, (crispX + halfErrorBarW)
|
|
];
|
|
errorValueObj.errorPath = errorPath;
|
|
graphicEle = dataObj.graphics.hotElement || dataObj.graphics.element;
|
|
groupId = graphicEle.data('groupId');
|
|
dataObj.errorBar[errorLen] || (dataObj.errorBar[errorLen] = []);
|
|
dataObj.errorBar[errorLen][0] = {
|
|
_xPos: crispX - trackerTolerance,
|
|
_yPos: crispY < errorStartPos ? crispY : errorStartPos,
|
|
_height: mathAbs(errorStartPos - crispY),
|
|
_width: 2 * trackerTolerance
|
|
};
|
|
// dataObj.errorBar[errorLen][0] = {
|
|
// _xPos: crispX - halfErrorBarW - trackerTolerance,
|
|
// _yPos: crispY - trackerTolerance,
|
|
// _height: 2 * trackerTolerance,
|
|
// _width: 2 * (halfErrorBarW + trackerTolerance)
|
|
// };
|
|
if (!errorLineElem) {
|
|
if (pool.errorLineElem && pool.errorLineElem.length) {
|
|
errorLineElem = errorGraphics.errorLineElem = pool.errorLineElem.shift();
|
|
}
|
|
else {
|
|
errorLineElem = errorGraphics.errorLineElem = paper.path(errorGroupContainer);
|
|
isNewElem = true;
|
|
}
|
|
}
|
|
|
|
// Animate the error Line Element
|
|
errorLineElem.show().animateWith(dummyAnimElem, dummyAnimObj, {
|
|
path: errorPath
|
|
}, animationDuration, animationObj.animType);
|
|
|
|
errorLineElem.attr({
|
|
stroke: errorBarColor,
|
|
// In case of tooltip disabled this element should act as the hot element.
|
|
ishot: !showTooltip,
|
|
'stroke-width': errorBarThickness,
|
|
'cursor': setLink ? POINTER : BLANKSTRING,
|
|
'stroke-linecap': ROUND
|
|
});
|
|
|
|
// if ((setLink || showTooltip) && errorBarThickness < HTP) {
|
|
// errorTrackerElem = errorGraphics.errorTrackerElem;
|
|
// if (!errorTrackerElem) {
|
|
// if (pool.errorTrackerElem && pool.errorTrackerElem.length) {
|
|
// errorTrackerElem = errorGraphics.errorTrackerElem =
|
|
// pool.errorTrackerElem.shift();
|
|
// }
|
|
// else {
|
|
// errorTrackerElem = errorGraphics.errorTrackerElem =
|
|
// paper.path(errorTrackerContainer);
|
|
// isNewElem = true;
|
|
// }
|
|
// }
|
|
// errorTrackerElem.attr({
|
|
// path: errorPath,
|
|
// stroke: TRACKER_FILL,
|
|
// 'stroke-width': HTP,
|
|
// 'cursor': setLink ? POINTER : BLANKSTRING,
|
|
// 'ishot': !! setLink,
|
|
// 'visibility': visible
|
|
// })
|
|
// .data('groupId', groupId)
|
|
// .tooltip(toolText);
|
|
// errorTrackerElem.data('eventArgs', graphicEle && graphicEle.data('eventArgs') || {});
|
|
// }
|
|
|
|
// if (isNewElem) {
|
|
// (errorTrackerElem || errorLineElem).click(errorElemClick)
|
|
// .hover(erroElemHoverFN, erroElemOutFN);
|
|
// (setLink || showTooltip) &&
|
|
// errorTrackerElem.click(getErrLinkClickFN(setLink));
|
|
// }
|
|
}
|
|
}
|
|
dataSet.components.data = dataStore;
|
|
},
|
|
// Function for returning the data limits of candlestick dataset
|
|
getDataLimits: function () {
|
|
var conf = this.config;
|
|
return {
|
|
max: conf.yMax,
|
|
min: conf.yMin,
|
|
xMax: conf.xMax,
|
|
xMin: conf.xMin
|
|
};
|
|
},
|
|
// Function to remove a data with a given index.
|
|
removeData : function (index, stretch) {
|
|
var dataSet = this,
|
|
components = dataSet.components,
|
|
dataStore = components.data,
|
|
removeDataArr = components.removeDataArr || (components.removeDataArr = []);
|
|
|
|
stretch = stretch || 1;
|
|
index = index || 0;
|
|
|
|
components.removeDataArr = removeDataArr = removeDataArr.concat(dataStore.splice(index, stretch));
|
|
}
|
|
}, LINE]);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-trendset',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
|
|
//strings
|
|
preDefStr = lib.preDefStr,
|
|
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
miterStr = preDefStr.miterStr,
|
|
ROUND = preDefStr.ROUND,
|
|
LINE = preDefStr.line,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
getValidValue = lib.getValidValue,
|
|
pluckNumber = lib.pluckNumber,
|
|
getFirstValue = lib.getFirstValue,
|
|
// getDefinedColor = lib.getDefinedColor,
|
|
getDashStyle = lib.getDashStyle, // returns dashed style of a line series
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
MAX_MITER_LINEJOIN = 2,
|
|
NONE = 'none',
|
|
// The default value for stroke-dash attribute.
|
|
DASH_DEF = NONE,
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
// CRISP = 'crisp',
|
|
HUNDRED = '100',
|
|
math = Math,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
// getColumnColor = lib.graphics.getColumnColor,
|
|
getFirstColor = lib.getFirstColor,
|
|
// pluckColor = lib.pluckColor,
|
|
HUNDREDSTRING = lib.HUNDREDSTRING;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'Trendset', {
|
|
configure: function () {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
rawDataObj = chart.jsonData,
|
|
chartAttr = rawDataObj.chart,
|
|
trendset = dataset.JSONData,
|
|
index = dataset.index,
|
|
setDataArr = trendset.data || trendset.set || [],
|
|
conf = dataset.config,
|
|
dataObj,
|
|
itemValue,
|
|
dataStore = dataset.components.data,
|
|
dataStoreObj,
|
|
config,
|
|
maxValue = -Infinity,
|
|
minValue = +Infinity,
|
|
x,
|
|
length,
|
|
xMax = -Infinity,
|
|
xMin = +Infinity,
|
|
NumberFormatter = chart.components.numberFormatter,
|
|
//Trend-sets default properties
|
|
trendSetColor = getFirstColor(pluck(trendset.color, chartAttr.trendsetcolor, '666666')),
|
|
trendSetAlpha = pluck(trendset.alpha, chartAttr.trendsetalpha, HUNDRED),
|
|
trendSetThickness = pluckNumber(trendset.thickness, chartAttr.trendsetthickness, 2),
|
|
trendSetDashed = Boolean(pluckNumber(trendset.dashed, chartAttr.trendsetdashed, 0)),
|
|
trendSetDashLen = pluckNumber(trendset.dashlen, chartAttr.trendsetdashlen, 4),
|
|
trendSetDashGap = pluckNumber(trendset.dashgap, chartAttr.trendsetdashgap, 4);
|
|
conf.includeInLegend = pluckNumber(trendset.includeinlegend, 1);
|
|
conf.lineColor = trendSetColor;
|
|
conf.lineAlpha = trendSetAlpha;
|
|
conf.connectNullData = pluckNumber(chartAttr.connectnulldata, 0);
|
|
conf.lineThickness = trendSetThickness;
|
|
conf.lineDashStyle = trendSetDashed ? getDashStyle(trendSetDashLen, trendSetDashGap) : DASH_DEF;
|
|
conf.name = getValidValue(trendset.name);
|
|
|
|
conf.includeInLegend = pluckNumber(trendset.includeinlegend, 1);
|
|
if (!dataStore) {
|
|
dataStore = dataset.components.data = [];
|
|
}
|
|
for (index = 0, length = setDataArr.length; index < length; index += 1) {
|
|
dataObj = setDataArr[index];
|
|
if (dataObj && !dataObj.vline) {
|
|
dataStoreObj = dataStore[index] = dataStore[index] || (dataStore[index]= {});
|
|
config = dataStoreObj.config = dataStoreObj.config || (dataStoreObj.config = {});
|
|
itemValue = config.setValue = NumberFormatter.getCleanValue(dataObj.value);
|
|
x = NumberFormatter.getCleanValue(dataObj.x);
|
|
x = config.x = x !== null ? x : index + 1;
|
|
maxValue = mathMax(maxValue, itemValue);
|
|
minValue = mathMin(minValue, itemValue);
|
|
xMin = mathMin(xMin, x);
|
|
xMax = mathMax(xMax, x);
|
|
if (!dataStoreObj.graphics) {
|
|
dataStoreObj.graphics = {};
|
|
}
|
|
}
|
|
}
|
|
conf.max = maxValue;
|
|
conf.min = minValue;
|
|
conf.xMax = xMax;
|
|
conf.xMin = xMin;
|
|
dataset.yAxis = chart.components.yAxis[0];
|
|
dataset.visible = true;
|
|
dataset._addLegend();
|
|
},
|
|
_addLegend: function () {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
JSONData = dataset.JSONData,
|
|
conf = dataset.config,
|
|
legend = chart.components.legend,
|
|
config = {
|
|
enabled: conf.includeInLegend,
|
|
interactiveLegend: false,
|
|
type : dataset.type,
|
|
drawLine: true,
|
|
strokeColor: toRaphaelColor({
|
|
color: conf.lineColor,
|
|
alpha: HUNDREDSTRING
|
|
}),
|
|
label : getFirstValue(JSONData.name)
|
|
};
|
|
dataset.legendItemId = legend.addItems(dataset, dataset.legendInteractivity, config);
|
|
},
|
|
legendInteractivity: function () {
|
|
|
|
},
|
|
draw: function () {// retrive requitrd objects
|
|
var dataSet = this,
|
|
JSONData = dataSet.JSONData,
|
|
chart = dataSet.chart,
|
|
chartComponents = chart.components,
|
|
conf = dataSet.config,
|
|
setDataArr = JSONData.data,
|
|
dataSetLen = dataSet.components.data.length,
|
|
clip = chartComponents.canvas.config.clip,
|
|
len = dataSetLen,
|
|
setData,
|
|
i,
|
|
paper = chartComponents.paper,
|
|
xAxis = chartComponents.xAxis[0],
|
|
yAxis = dataSet.yAxis,
|
|
xPos,
|
|
yPos,
|
|
layers = chart.graphics,
|
|
setLink,
|
|
setValue,
|
|
animObj = chart.get(configStr, animationObjStr),
|
|
animationDuration = animObj.duration,
|
|
dummyAnimElem = animObj.dummyObj,
|
|
dummyAnimObj = animObj.animObj,
|
|
animType = animObj.animType,
|
|
dataStore = dataSet.components.data,
|
|
dataObj,
|
|
lineThickness = conf.lineThickness,
|
|
container = dataSet.graphics.container,
|
|
group = layers.datasetGroup,
|
|
shadow = conf.shadow,
|
|
config,
|
|
initAnimCallBack = function () {
|
|
group.line.attr({
|
|
'clip-rect': null
|
|
});
|
|
//group.line.removeCSS('clip-path');
|
|
container.lineShadowGroup.show();
|
|
},
|
|
clipCanvas = clip['clip-canvas'].slice(0),
|
|
clipCanvasInit = clip['clip-canvas-init'].slice(0),
|
|
lineDashStyle = conf.lineDashStyle,
|
|
lineColorObj = {
|
|
color: conf.lineColor,
|
|
alpha: conf.lineAlpha
|
|
},
|
|
linePath,
|
|
linePathArr,
|
|
initialAnimation = false,
|
|
lineElement = dataSet.graphics.lineElement,
|
|
visible = dataSet.visible,
|
|
x;
|
|
|
|
// Creating the line group and appending it to dataset layer if not created
|
|
group.line = group.line ||
|
|
paper.group(LINE, group);
|
|
/*
|
|
* Creating lineConnector group and appending it to dataset layer if not created
|
|
* Lineconnector group has the anchorgroups of all datasets
|
|
*/
|
|
group.lineConnector = group.lineConnector ||
|
|
paper.group('line-connector', group);
|
|
// Create dataset container if not created
|
|
if (!container) {
|
|
container = dataSet.graphics.container = {
|
|
lineShadowGroup: paper.group('connector-shadow', group.line),
|
|
lineGroup: paper.group(LINE, group.line)
|
|
};
|
|
if (!visible) {
|
|
container.lineShadowGroup.hide();
|
|
container.lineGroup.hide();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//create plot elements
|
|
for (i = 0; i < len; i++) {
|
|
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
config = dataObj.config;
|
|
setValue = config.setValue;
|
|
x = config.x;
|
|
setLink = config.setLink;
|
|
xPos = xAxis.getAxisPosition(x);
|
|
yPos = yAxis.getAxisPosition(setValue);
|
|
/*Storing the x position and y position in dataObject for future reference
|
|
For example - when drawing labels we need this xPos and yPos
|
|
*/
|
|
dataObj._xPos = xPos;
|
|
dataObj._yPos = yPos;
|
|
}
|
|
linePath = dataSet.getLinePath(dataStore, {});
|
|
linePathArr = linePath.getPathArr();
|
|
|
|
if (!lineElement) {
|
|
lineElement = dataSet.graphics.lineElement = paper.path(container.lineGroup);
|
|
initialAnimation = true;
|
|
}
|
|
|
|
lineElement.show().animateWith(dummyAnimElem, dummyAnimObj, {
|
|
path: linePathArr
|
|
}, animationDuration, animType);
|
|
|
|
lineElement.attr({
|
|
'stroke-dasharray': lineDashStyle,
|
|
'stroke-width': lineThickness,
|
|
'stroke': toRaphaelColor(lineColorObj),
|
|
'stroke-linecap': ROUND,
|
|
/* for lines even with thickness as 2 we need to have round line join
|
|
otherwise the line join may look like exceeding the correct position
|
|
*/
|
|
'stroke-linejoin': lineThickness >= MAX_MITER_LINEJOIN ? ROUND : miterStr
|
|
})
|
|
.shadow(shadow, container.lineShadowGroup);
|
|
|
|
if (animationDuration && visible && initialAnimation) {
|
|
container.lineShadowGroup.hide();
|
|
group.line.attr({
|
|
'clip-rect': clipCanvasInit
|
|
})
|
|
.animateWith(dummyAnimElem, dummyAnimObj, {
|
|
'clip-rect': clipCanvas
|
|
}, animationDuration, animType, initAnimCallBack);
|
|
}
|
|
|
|
},
|
|
getDataLimits: function () {
|
|
var conf = this.config;
|
|
return {
|
|
max: conf.max,
|
|
min: conf.min,
|
|
xMax: conf.xMax,
|
|
xMin: conf.xMin
|
|
};
|
|
}
|
|
}, LINE]);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-boxandwhisker2d',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
|
|
//strings
|
|
preDefStr = lib.preDefStr,
|
|
colorStrings = preDefStr.colors,
|
|
COLOR_000000 = colorStrings.c000000,
|
|
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
showHoverEffectStr = preDefStr.showHoverEffectStr,
|
|
shadowStr = preDefStr.shadowStr,
|
|
dataLabelStr = preDefStr.dataLabelStr,
|
|
visibleStr = preDefStr.visibleStr,
|
|
ROUND = preDefStr.ROUND,
|
|
ZEROSTRING = lib.ZEROSTRING,
|
|
pStr = preDefStr.pStr,
|
|
sStr = preDefStr.sStr,
|
|
POSITION_START = preDefStr.POSITION_START,
|
|
POSITION_TOP = preDefStr.POSITION_TOP,
|
|
POSITION_END = preDefStr.POSITION_END,
|
|
POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
|
|
PLOTFILLCOLOR_STR = preDefStr.PLOTFILLCOLOR_STR,
|
|
UNDERSCORE = preDefStr.UNDERSCORE,
|
|
MAXIMUM_STR = 'Maximum',
|
|
Q3_STR = 'Q3',
|
|
MEDIAN_STR = 'Median',
|
|
Q1_STR = 'Q1',
|
|
MINIMUM_STR = 'Minimum',
|
|
MEAN_STR = 'Mean',
|
|
SD_STR = 'SD',
|
|
MD_STR = 'MD',
|
|
QD_STR = 'QD',
|
|
OUTLIERS_STR = 'Outliers',
|
|
OUTLIER_STR = 'Outlier',
|
|
|
|
meanStr = 'mean',
|
|
sdStr = 'sd',
|
|
mdStr = 'md',
|
|
qdStr = 'qd',
|
|
outlierStr = 'outlier',
|
|
|
|
iconradiusStr = 'iconradius',
|
|
iconcolorStr = 'iconcolor',
|
|
iconalphaStr = 'iconalpha',
|
|
iconsidesStr = 'iconsides',
|
|
|
|
LINE = preDefStr.line,
|
|
BLANK = lib.BLANKSTRING,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
getValidValue = lib.getValidValue,
|
|
pluckNumber = lib.pluckNumber,
|
|
getFirstValue = lib.getFirstValue,
|
|
// getDefinedColor = lib.getDefinedColor,
|
|
extend2 = lib.extend2, //old: jarendererExtend / margecolone
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
UNDEFINED,
|
|
defined = function(obj) {
|
|
return obj !== UNDEFINED && obj !== null;
|
|
},
|
|
NONE = 'none',
|
|
ROLLOVER = 'DataPlotRollOver',
|
|
ROLLOUT = 'DataPlotRollOut',
|
|
parseConfiguration = lib.parseConfiguration,
|
|
|
|
PLOTBORDERCOLOR = 'plotBorderColor',
|
|
PLOTGRADIENTCOLOR = 'plotGradientColor',
|
|
SHOWSHADOW = 'showShadow',
|
|
BOLDSTARTTAG = '<b>',
|
|
BOLDENDTAG = '</b>',
|
|
BREAKSTRING = '<br />',
|
|
POLYGON = 'polygon',
|
|
SPOKE = 'spoke',
|
|
POINTER = 'pointer',
|
|
SETROLLOVERATTR = 'setRolloverAttr',
|
|
SETROLLOUTATTR = 'setRolloutAttr',
|
|
EVENTARGS = 'eventArgs',
|
|
GROUPID = 'groupId',
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
// CRISP = 'crisp',
|
|
M = 'M',
|
|
H = 'H',
|
|
V = 'V',
|
|
COMMA = ',',
|
|
POSITION_MIDDLE = 'middle',
|
|
math = Math,
|
|
mathRound = math.round,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
// getColumnColor = lib.graphics.getColumnColor,
|
|
getFirstColor = lib.getFirstColor,
|
|
// pluckColor = lib.pluckColor,
|
|
getFirstAlpha = lib.getFirstAlpha,
|
|
getLightColor = lib.graphics.getLightColor,
|
|
convertColor = lib.graphics.convertColor,
|
|
// POSITION_CENTER = lib.POSITION_CENTER,
|
|
POSITION_LEFT = lib.POSITION_LEFT,
|
|
COMMASTRING = lib.COMMASTRING,
|
|
HUNDREDSTRING = lib.HUNDREDSTRING,
|
|
// COMMASPACE = lib.COMMASPACE,
|
|
plotEventHandler = lib.plotEventHandler,
|
|
LABEL = 'label';
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'boxandwhisker2d', {
|
|
|
|
type: 'boxandwhisker2d',
|
|
configure : function () {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
conf = dataSet.config,
|
|
JSONData = dataSet.JSONData,
|
|
setDataArr = JSONData.data,
|
|
setDataLen = setDataArr && setDataArr.length,
|
|
categories = chart.config.categories,
|
|
singleSeries = chart.singleseries,
|
|
chartConfig = chart.config,
|
|
catLen = categories && categories.length,
|
|
len = mathMin(catLen, setDataLen),
|
|
chartAttr = chart.jsonData.chart,
|
|
colorM = chart.components.colorManager,
|
|
index = dataSet.index || dataSet.positionIndex,
|
|
showplotborder,
|
|
plotColor = conf.plotColor = colorM.getPlotColor(index),
|
|
plotBorderDash = pluckNumber(JSONData.dashed, chartAttr.plotborderdashed),
|
|
usePlotGradientColor = pluckNumber(chartAttr.useplotgradientcolor, 1),
|
|
showTooltip,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
yAxisName = parseUnsafeString(chartAttr.yaxisname),
|
|
xAxisName = parseUnsafeString(chartAttr.xaxisname),
|
|
tooltipSepChar = parseUnsafeString(pluck(chartAttr.tooltipsepchar, ': ')),
|
|
parseTooltext = lib.parseTooltext,
|
|
formatedVal,
|
|
parserConfig,
|
|
setTooltext,
|
|
macroIndices,
|
|
tempPlotfillAngle,
|
|
toolText,
|
|
plotDashLen,
|
|
plotDashGap,
|
|
plotBorderThickness,
|
|
isRoundEdges,
|
|
showHoverEffect,
|
|
plotfillAngle,
|
|
plotFillAlpha,
|
|
plotRadius,
|
|
plotFillRatio,
|
|
plotgradientcolor,
|
|
plotBorderAlpha,
|
|
plotBorderColor,
|
|
plotBorderDashStyle,
|
|
initailPlotBorderDashStyle,
|
|
setData,
|
|
setValue,
|
|
dataObj,
|
|
config,
|
|
label,
|
|
colorArr,
|
|
upperBoxHoverColor,
|
|
upperBoxHoverAlpha,
|
|
upperBoxBorderHoverColor,
|
|
upperBoxBorderHoverAlpha,
|
|
upperBoxBorderHoverThickness,
|
|
lowerBoxHoverColor,
|
|
lowerBoxHoverAlpha,
|
|
lowerBoxBorderHoverColor,
|
|
lowerBoxBorderHoverAlpha,
|
|
lowerBoxBorderHoverThickness,
|
|
upperQuartileHoverColor,
|
|
upperQuartileHoverAlpha,
|
|
upperQuartileHoverThickness,
|
|
lowerQuartileHoverColor,
|
|
lowerQuartileHoverAlpha,
|
|
lowerQuartileHoverThickness,
|
|
medianHoverColor,
|
|
medianHoverAlpha,
|
|
medianHoverThickness,
|
|
getDashStyle = lib.getDashStyle,
|
|
dataStore = dataSet.components.data,
|
|
numberFormatter = chart.components.numberFormatter,
|
|
toolTipValue,
|
|
setDisplayValue,
|
|
definedGroupPadding,
|
|
|
|
use3DLighting,
|
|
parentYAxis,
|
|
setDataDashed,
|
|
setDataPlotDashLen,
|
|
setDataPlotDashGap,
|
|
i,
|
|
maxValue = 0,
|
|
minValue = 0,
|
|
|
|
BoxAndWhiskerStatisticalCalc = lib.BoxAndWhiskerStatisticalCalc,
|
|
bwCalc,
|
|
quartile,
|
|
q1,
|
|
q3,
|
|
limits,
|
|
min,
|
|
max,
|
|
medianValue,
|
|
mean,
|
|
md,
|
|
sd,
|
|
qd,
|
|
highValue,
|
|
lowValue,
|
|
itemValue,
|
|
upperBoxColor,
|
|
upperBoxAlpha,
|
|
lowerBoxColor,
|
|
lowerBoxAlpha,
|
|
upperWhiskerAlpha,
|
|
showValues,
|
|
showAllOutliers,
|
|
difference,
|
|
lowerWhiskerAlpha,
|
|
showMean,
|
|
showSD,
|
|
showMD,
|
|
showQD,
|
|
|
|
outlierDS,
|
|
OutliersLength,
|
|
maxNumberOfOutliers = 0,
|
|
j;
|
|
|
|
dataSet.visible = pluckNumber(dataSet.JSONData.visible,
|
|
!Number(dataSet.JSONData.initiallyhidden), 1) === 1;
|
|
|
|
// set the default configurations
|
|
dataSet.__setDefaultConfig();
|
|
parseConfiguration(JSONData, conf, chartConfig, {data: true});
|
|
|
|
conf.includeInLegend = pluckNumber(JSONData.includeinlegend, 1);
|
|
conf.legendSymbolColor = conf.plotColor;
|
|
showplotborder = conf.showplotborder;
|
|
plotDashLen = conf.plotborderdashlen;
|
|
plotDashGap = conf.plotborderdashgap;
|
|
plotFillAlpha = conf.plotfillalpha;
|
|
isRoundEdges = conf.useroundedges;
|
|
plotFillRatio = conf.ratio;
|
|
plotBorderThickness = conf.plotborderthickness;
|
|
showValues = conf.showvalues;
|
|
showTooltip = conf.showtooltip;
|
|
conf.rotatevalues && (conf.rotatevalues = 270);
|
|
use3DLighting = conf.use3dlighting;
|
|
showAllOutliers = conf.showalloutliers;
|
|
|
|
conf.plotfillAngle = plotfillAngle = pluckNumber(360 - chartAttr.plotfillangle, 90);
|
|
conf.plotColor = plotColor = pluck(JSONData.color, plotColor);
|
|
conf.plotRadius = plotRadius = pluckNumber(chartAttr.useroundedges, isRoundEdges ? 1 : 0);
|
|
conf.plotgradientcolor = plotgradientcolor = lib.getDefinedColor(chartAttr.plotgradientcolor,
|
|
colorM.getColor(PLOTGRADIENTCOLOR));
|
|
!usePlotGradientColor && (plotgradientcolor = BLANKSTRING);
|
|
conf.plotBorderAlpha = plotBorderAlpha = showplotborder ? pluck(chartAttr.plotborderalpha,
|
|
plotFillAlpha, HUNDREDSTRING): 0;
|
|
conf.plotBorderColor = plotBorderColor = pluck(chartAttr.plotbordercolor,
|
|
colorM.getColor(PLOTBORDERCOLOR));
|
|
conf.plotBorderDashStyle = initailPlotBorderDashStyle = plotBorderDash ?
|
|
getDashStyle(plotDashLen, plotDashGap, plotBorderThickness) : NONE;
|
|
|
|
conf.showShadow = isRoundEdges ? pluckNumber(chartAttr.showshadow, 1) :
|
|
pluckNumber(chartAttr.showshadow, colorM.getColor(SHOWSHADOW));
|
|
conf.showHoverEffect = showHoverEffect = pluckNumber(chartAttr.plothovereffect,
|
|
chartAttr.showhovereffect, UNDEFINED);
|
|
|
|
conf.definedGroupPadding = definedGroupPadding = mathMax(pluckNumber(chartAttr.plotspacepercent), 0);
|
|
conf.plotSpacePercent = mathMax(pluckNumber(chartAttr.plotspacepercent, 20) % 100, 0);
|
|
|
|
conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
|
|
pStr) === sStr ? 1 : 0 ;
|
|
|
|
conf.dataSeparator = COMMASTRING;
|
|
conf.bwCalc = bwCalc = new BoxAndWhiskerStatisticalCalc(
|
|
UNDEFINED, numberFormatter,
|
|
conf.dataSeparator);
|
|
|
|
conf.textDirection = chartAttr.hasrtltext === '1' ? 'rtl' : BLANKSTRING;
|
|
|
|
conf.showMeanLegend = conf.showSDLegend = conf.showMDLegend = conf.showQDLegend =
|
|
conf.showOutliersLegend = 0;
|
|
|
|
!dataSet.components.data && (dataSet.components.data = []);
|
|
dataStore = dataSet.components.data;
|
|
|
|
// Parsing the attributes and values at set level.
|
|
for (i = 0; i < len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
config = dataObj && dataObj.config;
|
|
|
|
if (!dataObj) {
|
|
dataObj = dataStore[i] = {
|
|
graphics : {}
|
|
};
|
|
}
|
|
|
|
if (!dataObj.config) {
|
|
config = dataStore[i].config = {};
|
|
|
|
}
|
|
|
|
if (!setData.value) {
|
|
continue;
|
|
}
|
|
|
|
if (setData.value) {
|
|
bwCalc.setArray(setData.value);
|
|
quartile = bwCalc.getQuartiles();
|
|
q1 = quartile.q1;
|
|
q3 = quartile.q3;
|
|
|
|
limits = bwCalc.getMinMax();
|
|
config.min = min = lowValue = limits.min;
|
|
config.max = max = limits.max;
|
|
medianValue = bwCalc.getMedian();
|
|
config.mean = mean = bwCalc.getMean();
|
|
config.md = md = bwCalc.getMD();
|
|
config.sd = sd = bwCalc.getSD();
|
|
config.qd = qd = bwCalc.getQD();
|
|
|
|
// get the valid value
|
|
highValue = itemValue = max;
|
|
}
|
|
|
|
if (setData.outliers) {
|
|
config.outliers = setData.outliers.split(COMMA);
|
|
maxNumberOfOutliers = mathMax(maxNumberOfOutliers, config.outliers.length);
|
|
}
|
|
|
|
config.showMean = showMean = pluckNumber(setData.showmean, conf.showmean);
|
|
config.showSD = showSD = pluckNumber(setData.showsd, conf.showsd);
|
|
config.showMD = showMD = pluckNumber(setData.showmd, conf.showmd);
|
|
config.showQD = showQD = pluckNumber(setData.showqd, conf.showqd);
|
|
setData.outliers && (conf.showOutliersLegend = 1);
|
|
|
|
showMean && (conf.showMeanLegend = 1);
|
|
showSD && (conf.showSDLegend = 1);
|
|
showMD && (conf.showMDLegend = 1);
|
|
showQD && (conf.showQDLegend = 1);
|
|
|
|
config.upperQuartile = {
|
|
value: q3,
|
|
color: convertColor(pluck(
|
|
setData.upperquartilecolor, JSONData.upperquartilecolor, chartAttr.upperquartilecolor,
|
|
chartAttr.plotbordercolor, colorM.getColor (PLOTBORDERCOLOR)),
|
|
pluckNumber(setData.upperquartilealpha, JSONData.upperquartilealpha,
|
|
chartAttr.upperquartilealpha, chartAttr.plotborderalpha,
|
|
100)),
|
|
borderWidth: pluckNumber(
|
|
setData.upperquartilethickness, JSONData.upperquartilethickness,
|
|
chartAttr.upperquartilethickness, chartAttr.plotborderthickness,
|
|
!isRoundEdges ? 1 : 0),
|
|
|
|
displayValue: numberFormatter.dataLabels(q3)
|
|
};
|
|
|
|
config.lowerQuartile = {
|
|
value: q1,
|
|
color: convertColor(pluck(
|
|
setData.lowerquartilecolor, JSONData.lowerquartilecolor, chartAttr.lowerquartilecolor,
|
|
chartAttr.plotbordercolor, colorM.getColor (PLOTBORDERCOLOR)),
|
|
pluckNumber(setData.lowerquartilealpha, JSONData.lowerquartilealpha,
|
|
chartAttr.lowerquartilealpha, chartAttr.plotborderalpha,
|
|
100)),
|
|
borderWidth: pluckNumber(
|
|
setData.lowerquartilethickness, JSONData.lowerquartilethickness,
|
|
chartAttr.lowerquartilethickness, chartAttr.plotborderthickness,
|
|
!isRoundEdges ? 1 : 0),
|
|
|
|
displayValue: numberFormatter.dataLabels(q1)
|
|
};
|
|
|
|
config.upperBoxBorder = {
|
|
color: convertColor(pluck(
|
|
setData.upperboxbordercolor, JSONData.upperboxbordercolor,
|
|
chartAttr.upperboxbordercolor, chartAttr.plotbordercolor,
|
|
colorM.getColor (PLOTBORDERCOLOR)),
|
|
pluckNumber(setData.upperboxborderalpha, JSONData.upperboxborderalpha,
|
|
chartAttr.upperboxborderalpha, chartAttr.plotborderalpha,
|
|
100)),
|
|
borderWidth: pluckNumber(
|
|
setData.upperboxborderthickness, JSONData.upperboxborderthickness,
|
|
chartAttr.upperboxborderthickness, !isRoundEdges && chartAttr.plotborderthickness,
|
|
!isRoundEdges ? 1 : 0)
|
|
};
|
|
|
|
config.lowerBoxBorder = {
|
|
color: convertColor(pluck(
|
|
setData.lowerboxbordercolor, JSONData.lowerboxbordercolor,
|
|
chartAttr.lowerboxbordercolor, chartAttr.plotbordercolor,
|
|
colorM.getColor (PLOTBORDERCOLOR)),
|
|
pluckNumber(setData.lowerboxborderalpha, JSONData.lowerboxborderalpha,
|
|
chartAttr.lowerboxborderalpha, chartAttr.plotborderalpha,
|
|
100)),
|
|
borderWidth: pluckNumber(
|
|
setData.lowerboxborderthickness, JSONData.lowerboxborderthickness,
|
|
chartAttr.lowerboxborderthickness, !isRoundEdges && chartAttr.plotborderthickness,
|
|
!isRoundEdges ? 1 : 0)
|
|
};
|
|
|
|
config.median = {
|
|
value: medianValue,
|
|
color: convertColor(pluck(
|
|
setData.mediancolor, JSONData.mediancolor,
|
|
chartAttr.mediancolor, chartAttr.plotbordercolor,
|
|
colorM.getColor (PLOTBORDERCOLOR)),
|
|
pluckNumber(setData.medianalpha, JSONData.medianalpha,
|
|
chartAttr.medianalpha, chartAttr.plotborderalpha,
|
|
100)),
|
|
borderWidth: pluckNumber(
|
|
setData.medianthickness, JSONData.medianthickness,
|
|
chartAttr.medianthickness, chartAttr.plotborderthickness,
|
|
1),
|
|
|
|
displayValue: numberFormatter.dataLabels(medianValue)
|
|
};
|
|
|
|
conf.upperBoxColor = upperBoxColor = pluck(setData.upperboxcolor, JSONData.upperboxcolor,
|
|
chartAttr.upperboxcolor, colorM.getPlotColor(index * 2));
|
|
|
|
upperBoxAlpha = conf.upperBoxAlpha = pluck(setData.upperboxalpha, JSONData.upperboxalpha,
|
|
chartAttr.upperboxalpha, plotFillAlpha, HUNDREDSTRING);
|
|
|
|
conf.lowerBoxColor = lowerBoxColor = pluck(setData.lowerboxcolor, JSONData.lowerboxcolor,
|
|
chartAttr.lowerboxcolor, colorM.getPlotColor((index * 2) + 1));
|
|
|
|
lowerBoxAlpha = conf.lowerBoxAlpha = pluck(setData.lowerboxalpha, JSONData.lowerboxalpha,
|
|
chartAttr.lowerboxalpha, plotFillAlpha, HUNDREDSTRING);
|
|
|
|
config.upperColorArr = lib.graphics.getColumnColor (
|
|
upperBoxColor,
|
|
upperBoxAlpha,
|
|
UNDEFINED,
|
|
UNDEFINED,
|
|
isRoundEdges,
|
|
plotBorderColor,
|
|
plotBorderAlpha.toString(),
|
|
0,
|
|
false
|
|
);
|
|
|
|
config.lowerColorArr = lib.graphics.getColumnColor (
|
|
lowerBoxColor,
|
|
lowerBoxAlpha,
|
|
UNDEFINED,
|
|
UNDEFINED,
|
|
isRoundEdges,
|
|
plotBorderColor,
|
|
plotBorderAlpha.toString(),
|
|
0,
|
|
false
|
|
);
|
|
|
|
config.showMinValues = showValues ? pluckNumber(setData.showminvalues, conf.showminvalues) : 0;
|
|
|
|
config.showMaxValues = showValues ? pluckNumber(setData.showmaxvalues, conf.showmaxvalues) : 0;
|
|
|
|
config.showQ1Values = showValues ? pluckNumber(setData.showq1values, conf.showq1values) : 0;
|
|
|
|
config.showQ3Values = showValues ? pluckNumber(setData.showq3values, conf.showq3values) : 0;
|
|
|
|
config.showMedianValues = showValues ? pluckNumber(setData.showmedianvalues,
|
|
conf.showmedianvalues) : 0;
|
|
|
|
config.upperWhiskerAlpha = upperWhiskerAlpha = getFirstAlpha(pluck(setData.upperwhiskeralpha,
|
|
JSONData.upperwhiskeralpha, chartAttr.upperwhiskeralpha, chartAttr.plotborderalpha, 100));
|
|
|
|
config.upperWhiskerColor = convertColor(getFirstColor(pluck(setData.upperwhiskercolor,
|
|
JSONData.upperwhiskercolor,
|
|
chartAttr.upperwhiskercolor,
|
|
chartAttr.plotbordercolor, colorM.getColor (PLOTBORDERCOLOR))), upperWhiskerAlpha);
|
|
|
|
config.upperWhiskerThickness = pluckNumber(setData.upperwhiskerthickness,
|
|
JSONData.upperwhiskerthickness, chartAttr.upperwhiskerthickness, chartAttr.plotborderthickness,
|
|
1);
|
|
|
|
config.upperWhiskerShadowOpacity = conf.showShadow ? (upperWhiskerAlpha / 250) : 0;
|
|
|
|
config.lowerWhiskerAlpha = lowerWhiskerAlpha = getFirstAlpha(pluck(setData.lowerwhiskeralpha,
|
|
JSONData.lowerwhiskeralpha, chartAttr.lowerwhiskeralpha, chartAttr.plotborderalpha, 100));
|
|
|
|
config.lowerWhiskerColor = convertColor(getFirstColor(pluck(setData.lowerwhiskercolor,
|
|
JSONData.lowerwhiskercolor,
|
|
chartAttr.lowerwhiskercolor, chartAttr.plotbordercolor,
|
|
colorM.getColor (PLOTBORDERCOLOR))), lowerWhiskerAlpha);
|
|
|
|
config.lowerWhiskerThickness = pluckNumber(setData.lowerwhiskerthickness,
|
|
JSONData.lowerwhiskerthickness, chartAttr.lowerwhiskerthickness, chartAttr.plotborderthickness,
|
|
1);
|
|
|
|
config.lowerWhiskerShadowOpacity = conf.showShadow ? (lowerWhiskerAlpha / 250) : 0;
|
|
|
|
config.showValue = pluckNumber(setData.showvalue, conf.showvalues);
|
|
config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
|
|
config.setLink = pluck(setData.link);
|
|
config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
|
|
config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
|
|
config.displayValue = pluck(setDisplayValue, toolTipValue);
|
|
setDataDashed = pluckNumber(setData.dashed);
|
|
setDataPlotDashLen = pluckNumber(setData.dashlen, plotDashLen);
|
|
setDataPlotDashGap = plotDashGap = pluckNumber(setData.dashgap, plotDashGap);
|
|
|
|
maxValue = mathMax(maxValue, max);
|
|
minValue = mathMin(minValue, min);
|
|
|
|
if (showAllOutliers && setData.outliers) {
|
|
for (j = 0; j < config.outliers.length; j++) {
|
|
maxValue = mathMax(maxValue, config.outliers[j]);
|
|
minValue = mathMin(minValue, config.outliers[j]);
|
|
}
|
|
}
|
|
|
|
config.plotBorderDashStyle = plotBorderDashStyle = setDataDashed === 1 ?
|
|
getDashStyle(setDataPlotDashLen, setDataPlotDashGap, plotBorderThickness) :
|
|
(setDataDashed === 0 ? NONE : initailPlotBorderDashStyle);
|
|
if (singleSeries) {
|
|
plotColor = colorM.getPlotColor(i);
|
|
plotColor = pluck(setData.color, plotColor);
|
|
plotFillRatio = pluck(setData.ratio, conf.ratio);
|
|
}
|
|
else {
|
|
plotColor = pluck(setData.color, conf.plotColor);
|
|
}
|
|
plotFillAlpha = pluck(setData.alpha, conf.plotfillalpha);
|
|
|
|
// Setting the angle for plot fill for negative data
|
|
if (setValue < 0 && !isRoundEdges) {
|
|
|
|
tempPlotfillAngle = plotfillAngle;
|
|
plotfillAngle = 360 - plotfillAngle;
|
|
}
|
|
|
|
// Setting the color Array to be applied to the bar/column.
|
|
config.colorArr = colorArr = lib.graphics.getColumnColor (
|
|
plotColor + COMMA + plotgradientcolor,
|
|
plotFillAlpha,
|
|
plotFillRatio,
|
|
plotfillAngle,
|
|
isRoundEdges,
|
|
plotBorderColor,
|
|
plotBorderAlpha.toString(),
|
|
0,
|
|
false
|
|
);
|
|
|
|
config.label = label=
|
|
getValidValue(parseUnsafeString(pluck (categories[i].tooltext, categories[i].label)));
|
|
|
|
// Parsing the hover effects only if showhovereffect is not 0.
|
|
if (showHoverEffect !== 0) {
|
|
|
|
upperBoxHoverColor = pluck(setData.upperboxhovercolor, JSONData.upperboxhovercolor,
|
|
chartAttr.upperboxhovercolor, upperBoxColor);
|
|
|
|
upperBoxHoverAlpha = pluck(setData.upperboxhoveralpha, JSONData.upperboxhoveralpha,
|
|
chartAttr.upperboxhoveralpha, upperBoxAlpha);
|
|
|
|
upperBoxBorderHoverColor = pluck(setData.upperboxborderhovercolor,
|
|
JSONData.upperboxborderhovercolor,
|
|
chartAttr.upperboxborderhovercolor, setData.upperboxbordercolor,
|
|
JSONData.upperboxbordercolor,
|
|
chartAttr.upperboxbordercolor, chartAttr.plotbordercolor,
|
|
colorM.getColor (PLOTBORDERCOLOR));
|
|
|
|
upperBoxBorderHoverAlpha = pluck(setData.upperboxborderhoveralpha,
|
|
JSONData.upperboxborderhoveralpha,
|
|
chartAttr.upperboxborderhoveralpha, setData.upperboxborderalpha,
|
|
JSONData.upperboxborderalpha,
|
|
chartAttr.upperboxborderalpha, chartAttr.plotborderalpha,
|
|
100);
|
|
|
|
upperBoxBorderHoverThickness = !isRoundEdges ? pluck(setData.upperboxborderhoverthickness,
|
|
JSONData.upperboxborderhoverthickness,
|
|
chartAttr.upperboxborderhoverthickness, config.upperBoxBorder.borderWidth) : 0;
|
|
|
|
lowerBoxHoverColor = pluck(setData.lowerboxhovercolor, JSONData.lowerboxhovercolor,
|
|
chartAttr.lowerboxhovercolor, lowerBoxColor);
|
|
|
|
lowerBoxHoverAlpha = pluck(setData.lowerboxhoveralpha, JSONData.lowerboxhoveralpha,
|
|
chartAttr.lowerboxhoveralpha, lowerBoxAlpha);
|
|
|
|
lowerBoxBorderHoverColor = pluck(setData.lowerboxborderhovercolor,
|
|
JSONData.lowerboxborderhovercolor,
|
|
chartAttr.lowerboxborderhovercolor, setData.lowerboxbordercolor,
|
|
JSONData.lowerboxbordercolor,
|
|
chartAttr.lowerboxbordercolor, chartAttr.plotbordercolor,
|
|
colorM.getColor (PLOTBORDERCOLOR));
|
|
|
|
lowerBoxBorderHoverAlpha = pluck(setData.lowerboxborderhoveralpha,
|
|
JSONData.lowerboxborderhoveralpha,
|
|
chartAttr.lowerboxborderhoveralpha, setData.lowerboxborderalpha,
|
|
JSONData.lowerboxborderalpha,
|
|
chartAttr.lowerboxborderalpha, chartAttr.plotborderalpha,
|
|
100);
|
|
|
|
lowerBoxBorderHoverThickness = !isRoundEdges ? pluck(setData.lowerboxborderhoverthickness,
|
|
JSONData.lowerboxborderhoverthickness,
|
|
chartAttr.lowerboxborderhoverthickness, config.lowerBoxBorder.borderWidth) : 0;
|
|
|
|
upperQuartileHoverColor = pluck(setData.upperquartilehovercolor,
|
|
JSONData.upperquartilehovercolor,
|
|
chartAttr.upperquartilehovercolor, setData.upperquartilecolor,
|
|
JSONData.upperquartilecolor,
|
|
chartAttr.upperquartilecolor, chartAttr.plotbordercolor,
|
|
colorM.getColor (PLOTBORDERCOLOR));
|
|
|
|
upperQuartileHoverAlpha = pluck(setData.upperquartilehoveralpha,
|
|
JSONData.upperquartilehoveralpha,
|
|
chartAttr.upperquartilehoveralpha, setData.upperquartilealpha,
|
|
JSONData.upperquartilealpha,
|
|
chartAttr.upperquartilealpha, chartAttr.plotborderalpha,
|
|
100);
|
|
|
|
upperQuartileHoverThickness = pluck(setData.upperquartilehoverthickness,
|
|
JSONData.upperquartilehoverthickness,
|
|
chartAttr.upperquartilehoverthickness, config.upperQuartile.borderWidth);
|
|
|
|
lowerQuartileHoverColor = pluck(setData.lowerquartilehovercolor,
|
|
JSONData.lowerquartilehovercolor,
|
|
chartAttr.lowerquartilehovercolor, setData.lowerquartilecolor,
|
|
JSONData.lowerquartilecolor,
|
|
chartAttr.lowerquartilecolor, chartAttr.plotbordercolor,
|
|
colorM.getColor (PLOTBORDERCOLOR));
|
|
|
|
lowerQuartileHoverAlpha = pluck(setData.lowerquartilehoveralpha,
|
|
JSONData.lowerquartilehoveralpha,
|
|
chartAttr.lowerquartilehoveralpha, setData.lowerquartilealpha,
|
|
JSONData.lowerquartilealpha,
|
|
chartAttr.lowerquartilealpha, chartAttr.plotborderalpha,
|
|
100);
|
|
|
|
lowerQuartileHoverThickness = pluck(setData.lowerquartilehoverthickness,
|
|
JSONData.lowerquartilehoverthickness,
|
|
chartAttr.lowerquartilehoverthickness, config.lowerQuartile.borderWidth);
|
|
|
|
medianHoverColor = pluck(setData.medianhovercolor,
|
|
JSONData.medianhovercolor,
|
|
chartAttr.medianhovercolor, setData.mediancolor,
|
|
JSONData.mediancolor,
|
|
chartAttr.mediancolor, chartAttr.plotbordercolor,
|
|
colorM.getColor (PLOTBORDERCOLOR));
|
|
|
|
medianHoverAlpha = pluck(setData.medianhoveralpha,
|
|
JSONData.medianhoveralpha,
|
|
chartAttr.medianhoveralpha, setData.medianalpha,
|
|
JSONData.medianalpha,
|
|
chartAttr.medianalpha, chartAttr.plotborderalpha,
|
|
100);
|
|
|
|
medianHoverThickness = pluck(setData.medianhoverthickness,
|
|
JSONData.medianhoverthickness,
|
|
chartAttr.medianhoverthickness, config.median.borderWidth);
|
|
|
|
/* If no hover effects are explicitly defined and
|
|
* showHoverEffect is not 0 then hoverColor is set.
|
|
*/
|
|
if (showHoverEffect == 1) {
|
|
upperBoxColor === upperBoxHoverColor &&
|
|
(upperBoxHoverColor = getLightColor(upperBoxHoverColor, 70));
|
|
lowerBoxColor === lowerBoxHoverColor &&
|
|
(lowerBoxHoverColor = getLightColor(lowerBoxHoverColor, 70));
|
|
|
|
}
|
|
|
|
config.upperBoxHoverColorArr = lib.graphics.getColumnColor (
|
|
upperBoxHoverColor,
|
|
upperBoxHoverAlpha,
|
|
UNDEFINED,
|
|
UNDEFINED,
|
|
isRoundEdges,
|
|
plotBorderColor,
|
|
plotBorderAlpha.toString(),
|
|
0,
|
|
false
|
|
);
|
|
|
|
config.lowerBoxHoverColorArr = lib.graphics.getColumnColor (
|
|
lowerBoxHoverColor,
|
|
lowerBoxHoverAlpha,
|
|
UNDEFINED,
|
|
UNDEFINED,
|
|
isRoundEdges,
|
|
plotBorderColor,
|
|
plotBorderAlpha.toString(),
|
|
0,
|
|
false
|
|
);
|
|
|
|
config.setUpperBoxRolloutAttr = {
|
|
fill: toRaphaelColor(config.upperColorArr[0])
|
|
};
|
|
config.setUpperBoxRolloverAttr = {
|
|
fill: toRaphaelColor(config.upperBoxHoverColorArr[0])
|
|
};
|
|
|
|
config.setLowerBoxRolloutAttr = {
|
|
fill: toRaphaelColor(config.lowerColorArr[0])
|
|
};
|
|
config.setLowerBoxRolloverAttr = {
|
|
fill: toRaphaelColor(config.lowerBoxHoverColorArr[0])
|
|
};
|
|
|
|
config.setUpperBoxBorderRolloverAttr = {
|
|
stroke: convertColor(upperBoxBorderHoverColor, upperBoxBorderHoverAlpha),
|
|
'stroke-width': upperBoxBorderHoverThickness
|
|
};
|
|
config.setUpperBoxBorderRolloutAttr = {
|
|
stroke: config.upperBoxBorder.color,
|
|
'stroke-width': config.upperBoxBorder.borderWidth
|
|
};
|
|
|
|
config.setLowerBoxBorderRolloverAttr = {
|
|
stroke: convertColor(lowerBoxBorderHoverColor, lowerBoxBorderHoverAlpha),
|
|
'stroke-width': lowerBoxBorderHoverThickness
|
|
};
|
|
config.setLowerBoxBorderRolloutAttr = {
|
|
stroke: config.lowerBoxBorder.color,
|
|
'stroke-width': config.lowerBoxBorder.borderWidth
|
|
};
|
|
|
|
config.setUpperQuartileRolloverAttr = {
|
|
stroke: convertColor(upperQuartileHoverColor, upperQuartileHoverAlpha),
|
|
'stroke-width': upperQuartileHoverThickness
|
|
};
|
|
config.setUpperQuartileRolloutAttr = {
|
|
stroke: config.upperQuartile.color,
|
|
'stroke-width': config.upperQuartile.borderWidth
|
|
};
|
|
|
|
config.setLowerQuartileRolloverAttr = {
|
|
stroke: convertColor(lowerQuartileHoverColor, lowerQuartileHoverAlpha),
|
|
'stroke-width': lowerQuartileHoverThickness
|
|
};
|
|
config.setLowerQuartileRolloutAttr = {
|
|
stroke: config.lowerQuartile.color,
|
|
'stroke-width': config.lowerQuartile.borderWidth
|
|
};
|
|
|
|
config.setMedianRolloverAttr = {
|
|
stroke: convertColor(medianHoverColor, medianHoverAlpha),
|
|
'stroke-width': medianHoverThickness
|
|
};
|
|
config.setMedianRolloutAttr = {
|
|
stroke: config.median.color,
|
|
'stroke-width': config.median.borderWidth
|
|
};
|
|
}
|
|
|
|
formatedVal = config.toolTipValue;
|
|
|
|
// Parsing tooltext against various configurations provided by the user.
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
|
|
JSONData.plottooltext, chartAttr.plottooltext)));
|
|
if (!showTooltip) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
if (formatedVal === null) {
|
|
toolText = false;
|
|
}
|
|
else if (setTooltext !== UNDEFINED) {
|
|
macroIndices = [1, 2, 3, 4, 5, 6, 62, 63, 64, 65,
|
|
66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80
|
|
];
|
|
parserConfig = {
|
|
maxValue: max,
|
|
maxDataValue: numberFormatter.dataLabels(max),
|
|
minValue: min,
|
|
minDataValue: numberFormatter.dataLabels(min),
|
|
Q1: numberFormatter.dataLabels(q1),
|
|
unformattedQ1: q1,
|
|
Q3: numberFormatter.dataLabels(q3),
|
|
unformattedQ3: q3,
|
|
median: numberFormatter.dataLabels(medianValue),
|
|
unformattedMedian: medianValue,
|
|
|
|
SD: numberFormatter.dataLabels(sd),
|
|
unformattedsd: sd,
|
|
QD: numberFormatter.dataLabels(qd),
|
|
unformattedQD: qd,
|
|
MD: numberFormatter.dataLabels(md),
|
|
unformattedMD: md,
|
|
mean: numberFormatter.dataLabels(mean),
|
|
unformattedMean: mean,
|
|
label: label,
|
|
yaxisName: yAxisName,
|
|
xaxisName: xAxisName,
|
|
formattedValue: formatedVal,
|
|
value: label
|
|
};
|
|
toolText = parseTooltext(setTooltext, macroIndices,
|
|
parserConfig, setData, chartAttr, JSONData);
|
|
}
|
|
else {
|
|
toolText = BOLDSTARTTAG + MAXIMUM_STR + tooltipSepChar + BOLDENDTAG +
|
|
numberFormatter.dataLabels(max) + BREAKSTRING +
|
|
BOLDSTARTTAG + Q3_STR + tooltipSepChar + BOLDENDTAG +
|
|
numberFormatter.dataLabels(q3) + BREAKSTRING +
|
|
BOLDSTARTTAG + MEDIAN_STR + tooltipSepChar + BOLDENDTAG +
|
|
numberFormatter.dataLabels(medianValue) + BREAKSTRING +
|
|
BOLDSTARTTAG + Q1_STR + tooltipSepChar + BOLDENDTAG +
|
|
numberFormatter.dataLabels(q1) + BREAKSTRING +
|
|
BOLDSTARTTAG + MINIMUM_STR + tooltipSepChar + BOLDENDTAG +
|
|
numberFormatter.dataLabels(min);
|
|
}
|
|
}
|
|
config.toolText = toolText;
|
|
config.setTooltext = toolText;
|
|
tempPlotfillAngle && (plotfillAngle = tempPlotfillAngle);
|
|
}
|
|
|
|
conf.maxNumberOfOutliers = maxNumberOfOutliers;
|
|
|
|
conf.maxValue = maxValue;
|
|
conf.minValue = minValue;
|
|
|
|
if (!showAllOutliers) {
|
|
difference = maxValue - minValue;
|
|
conf.maxValue += (conf.outliersupperrangeratio * difference);
|
|
conf.minValue -= (conf.outlierslowerrangeratio * difference);
|
|
}
|
|
|
|
(chart.hasLegend !== false) && dataSet._addLegend();
|
|
|
|
dataSet.subDS = 0;
|
|
|
|
(dataSet.components.mean = dataSet._createSubDS(0, MEAN_STR));
|
|
|
|
conf.showMeanLegend && (dataSet._addLegendSubDS(dataSet.components.mean));
|
|
conf.showMeanLegend && (dataSet.subDS += 1);
|
|
|
|
(dataSet.components.sd = dataSet._createSubDS(1, SD_STR));
|
|
conf.showSDLegend && (dataSet._addLegendSubDS(dataSet.components.sd));
|
|
conf.showSDLegend && (dataSet.subDS += 1);
|
|
|
|
(dataSet.components.md = dataSet._createSubDS(2, MD_STR));
|
|
conf.showMDLegend && (dataSet._addLegendSubDS(dataSet.components.md));
|
|
conf.showMDLegend && (dataSet.subDS += 1);
|
|
|
|
(dataSet.components.qd = dataSet._createSubDS(3, QD_STR));
|
|
conf.showQDLegend && (dataSet._addLegendSubDS(dataSet.components.qd));
|
|
conf.showQDLegend && (dataSet.subDS += 1);
|
|
|
|
!dataSet.components.outliers && (dataSet.components.outliers = []);
|
|
|
|
OutliersLength = dataSet.config.maxNumberOfOutliers || dataSet.components.outliers.length;
|
|
|
|
for (i = 0; i < OutliersLength; i++) {
|
|
outlierDS = (dataSet._createSubDS(4 + i, OUTLIERS_STR, i));
|
|
dataSet.components.outliers[i] = outlierDS;
|
|
}
|
|
conf.showOutliersLegend && (dataSet._addLegendOutliers(dataSet.components.outliers));
|
|
conf.showOutliersLegend && (dataSet.subDS += 1);
|
|
},
|
|
|
|
_createSubDS : function (index, name, outlierIndex) {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
|
|
dataObj = chart.jsonData,
|
|
dataset = dataObj.dataset,
|
|
length = dataset && dataset.length,
|
|
|
|
subDSIndex,
|
|
dsType = 'subDS',
|
|
components = dataSet.components,
|
|
datasetStore,
|
|
DsClass,
|
|
datasetObj,
|
|
JSONData,
|
|
legend = chart.components.legend,
|
|
dsCount = {};
|
|
|
|
datasetStore = components.dataset || (components.dataset = []);
|
|
|
|
subDSIndex = (length * (index + 1)) + dataSet.index;
|
|
|
|
if (!datasetStore[index]) {
|
|
DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
|
|
if (DsClass) {
|
|
if (dsCount[dsType] === UNDEFINED) {
|
|
dsCount[dsType] = 0;
|
|
}
|
|
else {
|
|
dsCount[dsType]++;
|
|
}
|
|
|
|
// create the dataset Object
|
|
datasetObj = new DsClass();
|
|
datasetObj.chart = chart;
|
|
datasetObj.index = subDSIndex;
|
|
datasetStore.push(datasetObj);
|
|
JSONData = extend2({}, dataSet.JSONData);
|
|
dataSet.initSubDataset(JSONData, datasetObj);
|
|
datasetObj.name = name;
|
|
}
|
|
}
|
|
else {
|
|
datasetObj = datasetStore[index];
|
|
datasetObj.index = subDSIndex;
|
|
JSONData = extend2({}, dataSet.JSONData);
|
|
datasetObj.JSONData = JSONData;
|
|
}
|
|
|
|
// JSONData = extend2({}, dataSet.JSONData);
|
|
// dataSet.initSubDataset(JSONData, datasetObj);
|
|
|
|
switch(index) {
|
|
case 0:
|
|
dataSet.configureMean(datasetObj);
|
|
// if (!dataSet.config.showMeanLegend) {
|
|
// legendItems.pop();
|
|
// }
|
|
!dataSet.config.showMeanLegend && legend.removeItem(datasetObj.legendItemId);
|
|
break;
|
|
case 1:
|
|
dataSet.configureSD(datasetObj);
|
|
!dataSet.config.showQDLegend && legend.removeItem(datasetObj.legendItemId);
|
|
break;
|
|
case 2:
|
|
dataSet.configureMD(datasetObj);
|
|
!dataSet.config.showMDLegend && legend.removeItem(datasetObj.legendItemId);
|
|
break;
|
|
case 3:
|
|
dataSet.configureQD(datasetObj);
|
|
!dataSet.config.showQDLegend && legend.removeItem(datasetObj.legendItemId);
|
|
break;
|
|
default:
|
|
dataSet.configureOutliers(datasetObj, outlierIndex);
|
|
!dataSet.config.showOutliersLegend &&
|
|
legend.removeItem(dataSet.components.outliers.legendItemId);
|
|
break;
|
|
}
|
|
|
|
return datasetObj;
|
|
},
|
|
|
|
configureMean: function (dataSet) {
|
|
var chart = dataSet.chart,
|
|
chartComponents = chart.components,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
conf = dataSet.config,
|
|
JSONData = dataSet.JSONData,
|
|
chartAttr = chart.jsonData.chart,
|
|
singleSeries = chart.singleseries,
|
|
colorM = chartComponents.colorManager,
|
|
index = dataSet.index || dataSet.stackIndex,
|
|
plotType = dataSet.type,
|
|
// showplotborder = pluckNumber(JSONData.showplotborder, chartAttr.showplotborder || 1),
|
|
plotFillColor = !singleSeries || getValidValue(chartAttr.palettecolors) ?
|
|
colorM.getPlotColor(index) : colorM.getColor(PLOTFILLCOLOR_STR).split(/\s*\,\s*/)[0],
|
|
// plotBorderDash,
|
|
// usePlotGradientColor,
|
|
setDataArr = JSONData.data,
|
|
setData,
|
|
dataObj,
|
|
dataSetLen = setDataArr && setDataArr.length,
|
|
categories = chart.config.categories,
|
|
catLen = categories && categories.length,
|
|
len = mathMin(catLen, dataSetLen),
|
|
dataStore,
|
|
// areaAlpha = chart.areaAlpha,
|
|
numberFormatter = chartComponents.numberFormatter,
|
|
config,
|
|
i,
|
|
toolText,
|
|
use3dlineshift = chart.use3dlineshift,
|
|
toolTipValue,
|
|
setValue,
|
|
setDisplayValue,
|
|
formatedVal,
|
|
maxValue = -Infinity,
|
|
minValue = +Infinity,
|
|
parentYAxis,
|
|
enableAnimation,
|
|
lineDashStyle,
|
|
stack100Percent,
|
|
defaultShadow,
|
|
tooltipSepChar = pluck(chartAttr.tooltipsepchar, ': '),
|
|
lineDashed = pluckNumber(JSONData.dashed, chartAttr.linedashed),
|
|
isStacked = chart.isStacked,
|
|
hasLineSet = chart.hasLineSet,
|
|
catObj,
|
|
xAxis = chartComponents.xAxis[0],
|
|
meanIconShape,
|
|
thisConfig;
|
|
|
|
dataSet.visible = pluckNumber(dataSet.JSONData.visible,
|
|
!Number(dataSet.JSONData.initiallyhidden), 1) === 1;
|
|
|
|
if (use3dlineshift !== UNDEFINED) {
|
|
conf.use3dlineshift = pluckNumber(chartAttr.use3dlineshift, use3dlineshift);
|
|
}
|
|
else {
|
|
conf.use3dlineshift = 1;
|
|
}
|
|
conf.plotColor = plotFillColor;
|
|
conf.legendSymbolColor = conf.plotColor;
|
|
defaultShadow = pluckNumber(chart.defaultPlotShadow, colorM.getColor(SHOWSHADOW));
|
|
|
|
// Functional attributes configuration
|
|
|
|
conf.drawFullAreaBorder = pluckNumber(chartAttr.drawfullareaborder, 1);
|
|
// ParentYAxis is always 1 for lineset
|
|
if (hasLineSet) {
|
|
conf.parentYAxis = parentYAxis = 1;
|
|
}
|
|
else {
|
|
conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
|
|
pStr) === sStr ? 1 : 0 ;
|
|
}
|
|
conf.connectNullData = pluckNumber(chartAttr.connectnulldata, 0);
|
|
|
|
// Animation related attributes configuration
|
|
conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
|
|
chartAttr.defaultanimation, 1);
|
|
conf.animation = !enableAnimation ? false : {
|
|
duration: pluckNumber(chartAttr.animationduration, 1) * 1000
|
|
};
|
|
conf.transposeanimation = pluckNumber(chartAttr.transposeanimation, enableAnimation);
|
|
conf.transposeanimduration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;
|
|
|
|
// Value related configurations
|
|
conf.showValues = 0;
|
|
conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
|
|
conf.valuePosition = pluck(JSONData.valueposition, chartAttr.valueposition, 'auto');
|
|
conf.stack100Percent = stack100Percent = pluckNumber(chartAttr.stack100percent, 0),
|
|
conf.showPercentValues = pluckNumber(chartAttr.showpercentvalues, (isStacked && stack100Percent) ?
|
|
1 : 0);
|
|
conf.showPercentInToolTip = pluckNumber(chartAttr.showpercentintooltip,
|
|
(isStacked && stack100Percent) ? 1 : 0);
|
|
|
|
// Tooltip related attributes
|
|
conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
|
|
conf.seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1);
|
|
|
|
conf.showHoverEffect = pluckNumber(chartAttr.plothovereffect, chartAttr.anchorhovereffect,
|
|
chartAttr.showhovereffect, UNDEFINED);
|
|
|
|
conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
|
|
// Line configuration attributes parsing
|
|
conf.linethickness = pluckNumber(JSONData.linethickness,
|
|
chartAttr.linethickness, 1);
|
|
conf.lineDashLen = pluckNumber(JSONData.linedashlen, chartAttr.linedashlen, 5);
|
|
conf.lineDashGap = pluckNumber(JSONData.linedashgap, chartAttr.linedashgap, 4);
|
|
conf.drawLine = conf.alpha =
|
|
pluckNumber(chartAttr.drawmeanconnector, JSONData.drawmeanconnector, 0) && 100;
|
|
|
|
lineDashStyle = lib.getDashStyle(conf.lineDashLen, conf.lineDashGap, conf.linethickness);
|
|
conf.lineDashStyle = lineDashed ?
|
|
lineDashStyle : NONE;
|
|
|
|
conf.shadow = {
|
|
opacity: pluckNumber(chartAttr.showshadow, defaultShadow) ?
|
|
(plotType === LINE ? conf.alpha/100 :
|
|
conf.plotBorderAlpha/100) : 0
|
|
};
|
|
// Anchor cosmetics attributes in dataset level
|
|
conf.drawAnchors = pluckNumber(JSONData.drawanchors, JSONData.showanchors, chartAttr.drawanchors,
|
|
chartAttr.showanchors);
|
|
|
|
conf.anchorBgColor = pluck(JSONData.meaniconcolor,
|
|
chartAttr.meaniconcolor, COLOR_000000);
|
|
conf.anchorBorderColor = COLOR_000000;
|
|
conf.anchorRadius = pluckNumber(JSONData.meaniconradius, chartAttr.meaniconradius, 5);
|
|
conf.anchorAlpha = pluck(JSONData.alpha,
|
|
JSONData.meaniconalpha, chartAttr.meaniconalpha);
|
|
conf.anchorBgAlpha = pluck(JSONData.meaniconalpha, chartAttr.meaniconalpha, 100);
|
|
conf.anchorBorderThickness = pluck(JSONData.anchorborderthickness,
|
|
chartAttr.anchorborderthickness, 1);
|
|
conf.anchorSides = pluck(JSONData.meaniconsides, chartAttr.meaniconsides, 3);
|
|
|
|
conf.linecolor = conf.anchorBgColor;
|
|
|
|
// Spline attributes
|
|
conf.minimizeTendency = pluckNumber(chartAttr.minimizetendency,chartAttr.minimisetendency,0);
|
|
|
|
// Anchor image cosmetics attributes
|
|
conf.anchorImageUrl = pluck(JSONData.anchorimageurl, chartAttr.anchorimageurl);
|
|
conf.anchorImageAlpha = pluckNumber(JSONData.anchorimagealpha, chartAttr.anchorimagealpha, 100);
|
|
conf.anchorImageScale = pluckNumber(JSONData.anchorimagescale, chartAttr.anchorimagescale, 100);
|
|
conf.anchorImagePadding = pluckNumber(JSONData.anchorimagepadding, chartAttr.anchorimagepadding, 1);
|
|
conf.anchorStartAngle = pluckNumber(JSONData.anchorstartangle, chartAttr.anchorstartangle, 90);
|
|
conf.anchorShadow = pluckNumber(JSONData.anchorshadow, chartAttr.anchorshadow, 0);
|
|
|
|
!dataSet.components.data && (dataSet.components.data = []);
|
|
dataStore = dataSet.components.data;
|
|
|
|
for (i=0; i<len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i] = dataStore[i] || {};
|
|
dataObj.config = dataObj.config || {};
|
|
config = dataObj.config;
|
|
thisConfig = this.components.data[i].config;
|
|
|
|
if (thisConfig.showMean) {
|
|
setData.value = thisConfig.mean;
|
|
}
|
|
else {
|
|
setData.value = null;
|
|
}
|
|
|
|
config.x = this.components.data[i]._xPos;
|
|
|
|
config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
|
|
config.setLink = pluck(setData.link);
|
|
// Parsing the anchor properties for set level
|
|
config.anchorProps = this._parseAnchorProperties(i, dataSet, meanStr);
|
|
catObj = xAxis.getLabel(i);
|
|
config.label = lib.getValidValue(parseUnsafeString(pluck(catObj.tooltext,
|
|
catObj.label, catObj.name)));
|
|
config.showValue = 0;
|
|
|
|
// Dashed, color and alpha configuration in set level is only for line chart
|
|
config.dashed = pluckNumber(setData.dashed, lineDashed);
|
|
config.color = pluck(setData.color, conf.lineColor);
|
|
config.alpha = pluck(setData.alpha, setData.alpha, conf.alpha);
|
|
maxValue = mathMax(maxValue, setValue);
|
|
minValue = mathMin(minValue, setValue);
|
|
config.dashStyle = config.dashed ? lineDashStyle : NONE;
|
|
config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
|
|
config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
|
|
config.displayValue = pluck(setDisplayValue, toolTipValue);
|
|
config.formatedVal = formatedVal = config.toolTipValue;
|
|
config.setTooltext = lib.getValidValue(parseUnsafeString(pluck(setData.tooltext,
|
|
JSONData.plottooltext, chartAttr.plottooltext)));
|
|
|
|
meanIconShape = pluck(setData.meaniconshape, JSONData.meaniconshape,
|
|
chartAttr.meaniconshape, POLYGON);
|
|
conf.dip = config.dip = (meanIconShape === POLYGON) ? 0 : (meanIconShape === SPOKE) ? 1 : 0;
|
|
// Initial tooltext parsing
|
|
|
|
if (!conf.showTooltip) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
toolText = BOLDSTARTTAG + MEAN_STR + tooltipSepChar + BOLDENDTAG;
|
|
}
|
|
config.toolText = toolText;
|
|
// Storing the initial parsed tooltext which will be later used in stack100percent calculations
|
|
// on legend click
|
|
config.setTooltext = toolText;
|
|
if (!dataObj) {
|
|
dataObj = dataStore[i] = {
|
|
graphics : {}
|
|
};
|
|
}
|
|
else if (!dataObj.graphics) {
|
|
dataStore[i].graphics = {};
|
|
|
|
}
|
|
config.hoverEffects = {
|
|
enabled: false
|
|
};
|
|
}
|
|
conf.maxValue = maxValue;
|
|
conf.minValue = minValue;
|
|
},
|
|
|
|
configureSD: function (dataSet) {
|
|
var chart = dataSet.chart,
|
|
chartComponents = chart.components,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
conf = dataSet.config,
|
|
JSONData = dataSet.JSONData,
|
|
chartAttr = chart.jsonData.chart,
|
|
singleSeries = chart.singleseries,
|
|
colorM = chartComponents.colorManager,
|
|
index = dataSet.index || dataSet.stackIndex,
|
|
plotType = dataSet.type,
|
|
plotFillColor = !singleSeries || getValidValue(chartAttr.palettecolors) ?
|
|
colorM.getPlotColor(index) : colorM.getColor(PLOTFILLCOLOR_STR).split(/\s*\,\s*/)[0],
|
|
setDataArr = JSONData.data,
|
|
setData,
|
|
dataObj,
|
|
dataSetLen = setDataArr && setDataArr.length,
|
|
categories = chart.config.categories,
|
|
catLen = categories && categories.length,
|
|
len = mathMin(catLen, dataSetLen),
|
|
dataStore,
|
|
numberFormatter = chartComponents.numberFormatter,
|
|
config,
|
|
i,
|
|
toolText,
|
|
use3dlineshift = chart.use3dlineshift,
|
|
toolTipValue,
|
|
setValue,
|
|
setDisplayValue,
|
|
formatedVal,
|
|
maxValue = -Infinity,
|
|
minValue = +Infinity,
|
|
parentYAxis,
|
|
enableAnimation,
|
|
lineDashStyle,
|
|
stack100Percent,
|
|
defaultShadow,
|
|
tooltipSepChar = pluck(chartAttr.tooltipsepchar, ': '),
|
|
lineDashed = pluckNumber(JSONData.dashed, chartAttr.linedashed),
|
|
isStacked = chart.isStacked,
|
|
hasLineSet = chart.hasLineSet,
|
|
catObj,
|
|
xAxis = chartComponents.xAxis[0],
|
|
SDIconShape,
|
|
thisConfig;
|
|
|
|
dataSet.visible = pluckNumber(dataSet.JSONData.visible,
|
|
!Number(dataSet.JSONData.initiallyhidden), 1) === 1;
|
|
|
|
if (use3dlineshift !== UNDEFINED) {
|
|
conf.use3dlineshift = pluckNumber(chartAttr.use3dlineshift, use3dlineshift);
|
|
}
|
|
else {
|
|
conf.use3dlineshift = 1;
|
|
}
|
|
conf.plotColor = plotFillColor;
|
|
conf.legendSymbolColor = conf.plotColor;
|
|
defaultShadow = pluckNumber(chart.defaultPlotShadow, colorM.getColor(SHOWSHADOW));
|
|
|
|
// Functional attributes configuration
|
|
|
|
conf.drawFullAreaBorder = pluckNumber(chartAttr.drawfullareaborder, 1);
|
|
// ParentYAxis is always 1 for lineset
|
|
if (hasLineSet) {
|
|
conf.parentYAxis = parentYAxis = 1;
|
|
}
|
|
else {
|
|
conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
|
|
pStr) === sStr ? 1 : 0 ;
|
|
}
|
|
conf.connectNullData = pluckNumber(chartAttr.connectnulldata, 0);
|
|
|
|
// Animation related attributes configuration
|
|
conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
|
|
chartAttr.defaultanimation, 1);
|
|
conf.animation = !enableAnimation ? false : {
|
|
duration: pluckNumber(chartAttr.animationduration, 1) * 1000
|
|
};
|
|
conf.transposeanimation = pluckNumber(chartAttr.transposeanimation, enableAnimation);
|
|
conf.transposeanimduration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;
|
|
|
|
// Value related configurations
|
|
conf.showValues = 0;
|
|
conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
|
|
conf.valuePosition = pluck(JSONData.valueposition, chartAttr.valueposition, 'auto');
|
|
conf.stack100Percent = stack100Percent = pluckNumber(chartAttr.stack100percent, 0),
|
|
conf.showPercentValues = pluckNumber(chartAttr.showpercentvalues, (isStacked && stack100Percent) ?
|
|
1 : 0);
|
|
conf.showPercentInToolTip = pluckNumber(chartAttr.showpercentintooltip,
|
|
(isStacked && stack100Percent) ? 1 : 0);
|
|
|
|
// Tooltip related attributes
|
|
conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
|
|
conf.seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1);
|
|
|
|
conf.showHoverEffect = pluckNumber(chartAttr.plothovereffect, chartAttr.anchorhovereffect,
|
|
chartAttr.showhovereffect, UNDEFINED);
|
|
|
|
conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
|
|
// Line configuration attributes parsing
|
|
conf.linethickness = pluckNumber(JSONData.linethickness,
|
|
chartAttr.linethickness, 1);
|
|
conf.lineDashLen = pluckNumber(JSONData.linedashlen, chartAttr.linedashlen, 5);
|
|
conf.lineDashGap = pluckNumber(JSONData.linedashgap, chartAttr.linedashgap, 4);
|
|
conf.drawLine = conf.alpha =
|
|
pluckNumber(chartAttr.drawsdconnector, JSONData.drawsdconnector, 0) && 100;
|
|
|
|
lineDashStyle = lib.getDashStyle(conf.lineDashLen, conf.lineDashGap, conf.linethickness);
|
|
conf.lineDashStyle = lineDashed ?
|
|
lineDashStyle : NONE;
|
|
|
|
conf.shadow = {
|
|
opacity: pluckNumber(chartAttr.showshadow, defaultShadow) ?
|
|
(plotType === LINE ? conf.alpha/100 :
|
|
conf.plotBorderAlpha/100) : 0
|
|
};
|
|
// Anchor cosmetics attributes in dataset level
|
|
conf.drawAnchors = pluckNumber(JSONData.drawanchors, JSONData.showanchors, chartAttr.drawanchors,
|
|
chartAttr.showanchors);
|
|
|
|
conf.anchorBgColor = pluck(JSONData.sdiconcolor,
|
|
chartAttr.sdiconcolor, COLOR_000000);
|
|
conf.anchorBorderColor = COLOR_000000;
|
|
conf.anchorRadius = pluckNumber(JSONData.sdiconradius, chartAttr.sdiconradius, 5);
|
|
conf.anchorAlpha = pluck(JSONData.alpha,
|
|
JSONData.sdiconalpha, chartAttr.sdiconalpha);
|
|
conf.anchorBgAlpha = pluck(JSONData.sdiconalpha, chartAttr.sdiconalpha, 100);
|
|
conf.anchorBorderThickness = pluck(JSONData.anchorborderthickness,
|
|
chartAttr.anchorborderthickness, 1);
|
|
conf.anchorSides = pluck(JSONData.sdiconsides, chartAttr.sdiconsides, 3);
|
|
|
|
conf.linecolor = conf.anchorBgColor;
|
|
|
|
// Spline attributes
|
|
conf.minimizeTendency = pluckNumber(chartAttr.minimizetendency,chartAttr.minimisetendency,0);
|
|
|
|
// Anchor image cosmetics attributes
|
|
conf.anchorImageUrl = pluck(JSONData.anchorimageurl, chartAttr.anchorimageurl);
|
|
conf.anchorImageAlpha = pluckNumber(JSONData.anchorimagealpha, chartAttr.anchorimagealpha, 100);
|
|
conf.anchorImageScale = pluckNumber(JSONData.anchorimagescale, chartAttr.anchorimagescale, 100);
|
|
conf.anchorImagePadding = pluckNumber(JSONData.anchorimagepadding, chartAttr.anchorimagepadding, 1);
|
|
conf.anchorStartAngle = pluckNumber(JSONData.anchorstartangle, chartAttr.anchorstartangle, 90);
|
|
conf.anchorShadow = pluckNumber(JSONData.anchorshadow, chartAttr.anchorshadow, 0);
|
|
!dataSet.components.data && (dataSet.components.data = []);
|
|
dataStore = dataSet.components.data;
|
|
|
|
for (i=0; i<len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i] = dataStore[i] || {};
|
|
dataObj.config = dataObj.config || {};
|
|
config = dataObj.config;
|
|
thisConfig = this.components.data[i].config;
|
|
|
|
if (thisConfig.showSD) {
|
|
setData.value = thisConfig.sd;
|
|
}
|
|
else {
|
|
setData.value = null;
|
|
}
|
|
|
|
config.x = this.components.data[i]._xPos;
|
|
|
|
config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
|
|
config.setLink = pluck(setData.link);
|
|
// Parsing the anchor properties for set level
|
|
config.anchorProps = this._parseAnchorProperties(i, dataSet, sdStr);
|
|
catObj = xAxis.getLabel(i);
|
|
config.label = lib.getValidValue(parseUnsafeString(pluck(catObj.tooltext,
|
|
catObj.label, catObj.name)));
|
|
config.showValue = 0;
|
|
|
|
// Dashed, color and alpha configuration in set level is only for line chart
|
|
config.dashed = pluckNumber(setData.dashed, lineDashed);
|
|
config.color = pluck(setData.color, conf.lineColor);
|
|
config.alpha = pluck(setData.alpha, setData.alpha, conf.alpha);
|
|
maxValue = mathMax(maxValue, setValue);
|
|
minValue = mathMin(minValue, setValue);
|
|
config.dashStyle = config.dashed ? lineDashStyle : NONE;
|
|
config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
|
|
config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
|
|
config.displayValue = pluck(setDisplayValue, toolTipValue);
|
|
config.formatedVal = formatedVal = config.toolTipValue;
|
|
config.setTooltext = lib.getValidValue(parseUnsafeString(pluck(setData.tooltext,
|
|
JSONData.plottooltext, chartAttr.plottooltext)));
|
|
SDIconShape = pluck(setData.sdiconshape, JSONData.sdiconshape,
|
|
chartAttr.sdiconshape, POLYGON);
|
|
conf.dip = config.dip = (SDIconShape === POLYGON) ? 0 : (SDIconShape === SPOKE) ? 1 : 0;
|
|
// Initial tooltext parsing
|
|
|
|
if (!conf.showTooltip) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
if (formatedVal === null) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
toolText = BOLDSTARTTAG + SD_STR + tooltipSepChar + BOLDENDTAG;
|
|
}
|
|
}
|
|
config.toolText = toolText;
|
|
// Storing the initial parsed tooltext which will be later used in stack100percent calculations
|
|
// on legend click
|
|
config.setTooltext = toolText;
|
|
if (!dataObj) {
|
|
dataObj = dataStore[i] = {
|
|
graphics : {}
|
|
};
|
|
}
|
|
else if (!dataObj.graphics) {
|
|
dataStore[i].graphics = {};
|
|
|
|
}
|
|
config.hoverEffects = {
|
|
enabled: false
|
|
};
|
|
}
|
|
conf.maxValue = maxValue;
|
|
conf.minValue = minValue;
|
|
},
|
|
|
|
configureMD: function (dataSet) {
|
|
var chart = dataSet.chart,
|
|
chartComponents = chart.components,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
conf = dataSet.config,
|
|
JSONData = dataSet.JSONData,
|
|
chartAttr = chart.jsonData.chart,
|
|
singleSeries = chart.singleseries,
|
|
colorM = chartComponents.colorManager,
|
|
index = dataSet.index || dataSet.stackIndex,
|
|
plotType = dataSet.type,
|
|
plotFillColor = !singleSeries || getValidValue(chartAttr.palettecolors) ?
|
|
colorM.getPlotColor(index) : colorM.getColor(PLOTFILLCOLOR_STR).split(/\s*\,\s*/)[0],
|
|
setDataArr = JSONData.data,
|
|
setData,
|
|
dataObj,
|
|
dataSetLen = setDataArr && setDataArr.length,
|
|
categories = chart.config.categories,
|
|
catLen = categories && categories.length,
|
|
len = mathMin(catLen, dataSetLen),
|
|
dataStore,
|
|
numberFormatter = chartComponents.numberFormatter,
|
|
config,
|
|
i,
|
|
toolText,
|
|
use3dlineshift = chart.use3dlineshift,
|
|
toolTipValue,
|
|
setValue,
|
|
setDisplayValue,
|
|
formatedVal,
|
|
maxValue = -Infinity,
|
|
minValue = +Infinity,
|
|
parentYAxis,
|
|
enableAnimation,
|
|
lineDashStyle,
|
|
stack100Percent,
|
|
defaultShadow,
|
|
tooltipSepChar = pluck(chartAttr.tooltipsepchar, ': '),
|
|
lineDashed = pluckNumber(JSONData.dashed, chartAttr.linedashed),
|
|
isStacked = chart.isStacked,
|
|
hasLineSet = chart.hasLineSet,
|
|
catObj,
|
|
xAxis = chartComponents.xAxis[0],
|
|
MDIconShape,
|
|
thisConfig;
|
|
|
|
dataSet.visible = pluckNumber(dataSet.JSONData.visible,
|
|
!Number(dataSet.JSONData.initiallyhidden), 1) === 1;
|
|
|
|
if (use3dlineshift !== UNDEFINED) {
|
|
conf.use3dlineshift = pluckNumber(chartAttr.use3dlineshift, use3dlineshift);
|
|
}
|
|
else {
|
|
conf.use3dlineshift = 1;
|
|
}
|
|
conf.plotColor = plotFillColor;
|
|
conf.legendSymbolColor = conf.plotColor;
|
|
defaultShadow = pluckNumber(chart.defaultPlotShadow, colorM.getColor(SHOWSHADOW));
|
|
|
|
// Functional attributes configuration
|
|
|
|
conf.drawFullAreaBorder = pluckNumber(chartAttr.drawfullareaborder, 1);
|
|
// ParentYAxis is always 1 for lineset
|
|
if (hasLineSet) {
|
|
conf.parentYAxis = parentYAxis = 1;
|
|
}
|
|
else {
|
|
conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
|
|
pStr) === sStr ? 1 : 0 ;
|
|
}
|
|
conf.connectNullData = pluckNumber(chartAttr.connectnulldata, 0);
|
|
|
|
// Animation related attributes configuration
|
|
conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
|
|
chartAttr.defaultanimation, 1);
|
|
conf.animation = !enableAnimation ? false : {
|
|
duration: pluckNumber(chartAttr.animationduration, 1) * 1000
|
|
};
|
|
conf.transposeanimation = pluckNumber(chartAttr.transposeanimation, enableAnimation);
|
|
conf.transposeanimduration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;
|
|
|
|
// Value related configurations
|
|
conf.showValues = 0;
|
|
conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
|
|
conf.valuePosition = pluck(JSONData.valueposition, chartAttr.valueposition, 'auto');
|
|
conf.stack100Percent = stack100Percent = pluckNumber(chartAttr.stack100percent, 0),
|
|
conf.showPercentValues = pluckNumber(chartAttr.showpercentvalues, (isStacked && stack100Percent) ?
|
|
1 : 0);
|
|
conf.showPercentInToolTip = pluckNumber(chartAttr.showpercentintooltip,
|
|
(isStacked && stack100Percent) ? 1 : 0);
|
|
|
|
// Tooltip related attributes
|
|
conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
|
|
conf.seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1);
|
|
|
|
conf.showHoverEffect = pluckNumber(chartAttr.plothovereffect, chartAttr.anchorhovereffect,
|
|
chartAttr.showhovereffect, UNDEFINED);
|
|
|
|
conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
|
|
// Line configuration attributes parsing
|
|
conf.linethickness = pluckNumber(JSONData.linethickness,
|
|
chartAttr.linethickness, 1);
|
|
conf.lineDashLen = pluckNumber(JSONData.linedashlen, chartAttr.linedashlen, 5);
|
|
conf.lineDashGap = pluckNumber(JSONData.linedashgap, chartAttr.linedashgap, 4);
|
|
conf.drawLine = conf.alpha =
|
|
pluckNumber(chartAttr.drawmdconnector, JSONData.drawmdconnector, 0) && 100;
|
|
|
|
lineDashStyle = lib.getDashStyle(conf.lineDashLen, conf.lineDashGap, conf.linethickness);
|
|
conf.lineDashStyle = lineDashed ?
|
|
lineDashStyle : NONE;
|
|
|
|
conf.shadow = {
|
|
opacity: pluckNumber(chartAttr.showshadow, defaultShadow) ?
|
|
(plotType === LINE ? conf.alpha/100 :
|
|
conf.plotBorderAlpha/100) : 0
|
|
};
|
|
// Anchor cosmetics attributes in dataset level
|
|
conf.drawAnchors = pluckNumber(JSONData.drawanchors, JSONData.showanchors, chartAttr.drawanchors,
|
|
chartAttr.showanchors);
|
|
|
|
conf.anchorBgColor = pluck(JSONData.mdiconcolor,
|
|
chartAttr.mdiconcolor, COLOR_000000);
|
|
conf.anchorBorderColor = COLOR_000000;
|
|
conf.anchorRadius = pluckNumber(JSONData.mdiconradius, chartAttr.mdiconradius, 5);
|
|
conf.anchorAlpha = pluck(JSONData.alpha,
|
|
JSONData.mdiconalpha, chartAttr.mdiconalpha);
|
|
conf.anchorBgAlpha = pluck(JSONData.mdiconalpha, chartAttr.mdiconalpha, 100);
|
|
conf.anchorBorderThickness = pluck(JSONData.anchorborderthickness,
|
|
chartAttr.anchorborderthickness, 1);
|
|
conf.anchorSides = pluck(JSONData.mdiconsides, chartAttr.mdiconsides, 3);
|
|
|
|
conf.linecolor = conf.anchorBgColor;
|
|
|
|
// Spline attributes
|
|
conf.minimizeTendency = pluckNumber(chartAttr.minimizetendency,chartAttr.minimisetendency,0);
|
|
|
|
// Anchor image cosmetics attributes
|
|
conf.anchorImageUrl = pluck(JSONData.anchorimageurl, chartAttr.anchorimageurl);
|
|
conf.anchorImageAlpha = pluckNumber(JSONData.anchorimagealpha, chartAttr.anchorimagealpha, 100);
|
|
conf.anchorImageScale = pluckNumber(JSONData.anchorimagescale, chartAttr.anchorimagescale, 100);
|
|
conf.anchorImagePadding = pluckNumber(JSONData.anchorimagepadding, chartAttr.anchorimagepadding, 1);
|
|
conf.anchorStartAngle = pluckNumber(JSONData.anchorstartangle, chartAttr.anchorstartangle, 90);
|
|
conf.anchorShadow = pluckNumber(JSONData.anchorshadow, chartAttr.anchorshadow, 0);
|
|
!dataSet.components.data && (dataSet.components.data = []);
|
|
dataStore = dataSet.components.data;
|
|
|
|
for (i=0; i<len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i] = dataStore[i] || {};
|
|
dataObj.config = dataObj.config || {};
|
|
config = dataObj.config;
|
|
thisConfig = this.components.data[i].config;
|
|
|
|
if (thisConfig.showMD) {
|
|
setData.value = thisConfig.md;
|
|
}
|
|
else {
|
|
setData.value = null;
|
|
}
|
|
|
|
config.x = this.components.data[i]._xPos;
|
|
|
|
config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
|
|
config.setLink = pluck(setData.link);
|
|
// Parsing the anchor properties for set level
|
|
config.anchorProps = this._parseAnchorProperties(i, dataSet, mdStr);
|
|
catObj = xAxis.getLabel(i);
|
|
config.label = lib.getValidValue(parseUnsafeString(pluck(catObj.tooltext,
|
|
catObj.label, catObj.name)));
|
|
config.showValue = 0;
|
|
|
|
// Dashed, color and alpha configuration in set level is only for line chart
|
|
config.dashed = pluckNumber(setData.dashed, lineDashed);
|
|
config.color = pluck(setData.color, conf.lineColor);
|
|
config.alpha = pluck(setData.alpha, setData.alpha, conf.alpha);
|
|
maxValue = mathMax(maxValue, setValue);
|
|
minValue = mathMin(minValue, setValue);
|
|
config.dashStyle = config.dashed ? lineDashStyle : NONE;
|
|
config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
|
|
config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
|
|
config.displayValue = pluck(setDisplayValue, toolTipValue);
|
|
config.formatedVal = formatedVal = config.toolTipValue;
|
|
config.setTooltext = lib.getValidValue(parseUnsafeString(pluck(setData.tooltext,
|
|
JSONData.plottooltext, chartAttr.plottooltext)));
|
|
MDIconShape = pluck(setData.mdiconshape, JSONData.mdiconshape,
|
|
chartAttr.mdiconshape, POLYGON);
|
|
conf.dip = config.dip = (MDIconShape === POLYGON) ? 0 : (MDIconShape === SPOKE) ? 1 : 0;
|
|
// Initial tooltext parsing
|
|
|
|
if (!conf.showTooltip) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
toolText = BOLDSTARTTAG + MD_STR + tooltipSepChar + BOLDENDTAG;
|
|
}
|
|
config.toolText = toolText;
|
|
// Storing the initial parsed tooltext which will be later used in stack100percent calculations
|
|
// on legend click
|
|
config.setTooltext = toolText;
|
|
if (!dataObj) {
|
|
dataObj = dataStore[i] = {
|
|
graphics : {}
|
|
};
|
|
}
|
|
else if (!dataObj.graphics) {
|
|
dataStore[i].graphics = {};
|
|
|
|
}
|
|
config.hoverEffects = {
|
|
enabled: false
|
|
};
|
|
}
|
|
conf.maxValue = maxValue;
|
|
conf.minValue = minValue;
|
|
},
|
|
|
|
configureQD: function (dataSet) {
|
|
var chart = dataSet.chart,
|
|
chartComponents = chart.components,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
conf = dataSet.config,
|
|
JSONData = dataSet.JSONData,
|
|
chartAttr = chart.jsonData.chart,
|
|
singleSeries = chart.singleseries,
|
|
colorM = chartComponents.colorManager,
|
|
index = dataSet.index || dataSet.stackIndex,
|
|
plotType = dataSet.type,
|
|
plotFillColor = !singleSeries || getValidValue(chartAttr.palettecolors) ?
|
|
colorM.getPlotColor(index) : colorM.getColor(PLOTFILLCOLOR_STR).split(/\s*\,\s*/)[0],
|
|
setDataArr = JSONData.data,
|
|
setData,
|
|
dataObj,
|
|
dataSetLen = setDataArr && setDataArr.length,
|
|
categories = chart.config.categories,
|
|
catLen = categories && categories.length,
|
|
len = mathMin(catLen, dataSetLen),
|
|
dataStore,
|
|
numberFormatter = chartComponents.numberFormatter,
|
|
config,
|
|
i,
|
|
toolText,
|
|
use3dlineshift = chart.use3dlineshift,
|
|
toolTipValue,
|
|
setValue,
|
|
setDisplayValue,
|
|
formatedVal,
|
|
maxValue = -Infinity,
|
|
minValue = +Infinity,
|
|
parentYAxis,
|
|
enableAnimation,
|
|
lineDashStyle,
|
|
stack100Percent,
|
|
defaultShadow,
|
|
tooltipSepChar = pluck(chartAttr.tooltipsepchar, ': '),
|
|
lineDashed = pluckNumber(JSONData.dashed, chartAttr.linedashed),
|
|
isStacked = chart.isStacked,
|
|
hasLineSet = chart.hasLineSet,
|
|
catObj,
|
|
xAxis = chartComponents.xAxis[0],
|
|
QDIconShape,
|
|
thisConfig;
|
|
|
|
dataSet.visible = pluckNumber(dataSet.JSONData.visible,
|
|
!Number(dataSet.JSONData.initiallyhidden), 1) === 1;
|
|
|
|
if (use3dlineshift !== UNDEFINED) {
|
|
conf.use3dlineshift = pluckNumber(chartAttr.use3dlineshift, use3dlineshift);
|
|
}
|
|
else {
|
|
conf.use3dlineshift = 1;
|
|
}
|
|
conf.plotColor = plotFillColor;
|
|
conf.legendSymbolColor = conf.plotColor;
|
|
defaultShadow = pluckNumber(chart.defaultPlotShadow, colorM.getColor(SHOWSHADOW));
|
|
|
|
// Functional attributes configuration
|
|
|
|
conf.drawFullAreaBorder = pluckNumber(chartAttr.drawfullareaborder, 1);
|
|
// ParentYAxis is always 1 for lineset
|
|
if (hasLineSet) {
|
|
conf.parentYAxis = parentYAxis = 1;
|
|
}
|
|
else {
|
|
conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
|
|
pStr) === sStr ? 1 : 0 ;
|
|
}
|
|
conf.connectNullData = pluckNumber(chartAttr.connectnulldata, 0);
|
|
|
|
// Animation related attributes configuration
|
|
conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
|
|
chartAttr.defaultanimation, 1);
|
|
conf.animation = !enableAnimation ? false : {
|
|
duration: pluckNumber(chartAttr.animationduration, 1) * 1000
|
|
};
|
|
conf.transposeanimation = pluckNumber(chartAttr.transposeanimation, enableAnimation);
|
|
conf.transposeanimduration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;
|
|
|
|
// Value related configurations
|
|
conf.showValues = 0;
|
|
conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
|
|
conf.valuePosition = pluck(JSONData.valueposition, chartAttr.valueposition, 'auto');
|
|
conf.stack100Percent = stack100Percent = pluckNumber(chartAttr.stack100percent, 0),
|
|
conf.showPercentValues = pluckNumber(chartAttr.showpercentvalues, (isStacked && stack100Percent) ?
|
|
1 : 0);
|
|
conf.showPercentInToolTip = pluckNumber(chartAttr.showpercentintooltip,
|
|
(isStacked && stack100Percent) ? 1 : 0);
|
|
|
|
// Tooltip related attributes
|
|
conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
|
|
conf.seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1);
|
|
|
|
conf.showHoverEffect = pluckNumber(chartAttr.plothovereffect, chartAttr.anchorhovereffect,
|
|
chartAttr.showhovereffect, UNDEFINED);
|
|
|
|
conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
|
|
// Line configuration attributes parsing
|
|
conf.linethickness = pluckNumber(JSONData.linethickness,
|
|
chartAttr.linethickness, 1);
|
|
conf.lineDashLen = pluckNumber(JSONData.linedashlen, chartAttr.linedashlen, 5);
|
|
conf.lineDashGap = pluckNumber(JSONData.linedashgap, chartAttr.linedashgap, 4);
|
|
conf.drawLine = conf.alpha =
|
|
pluckNumber(chartAttr.drawqdconnector, JSONData.drawqdconnector, 0) && 100;
|
|
|
|
lineDashStyle = lib.getDashStyle(conf.lineDashLen, conf.lineDashGap, conf.linethickness);
|
|
conf.lineDashStyle = lineDashed ?
|
|
lineDashStyle : NONE;
|
|
|
|
conf.shadow = {
|
|
opacity: pluckNumber(chartAttr.showshadow, defaultShadow) ?
|
|
(plotType === LINE ? conf.alpha/100 :
|
|
conf.plotBorderAlpha/100) : 0
|
|
};
|
|
// Anchor cosmetics attributes in dataset level
|
|
conf.drawAnchors = pluckNumber(JSONData.drawanchors, JSONData.showanchors, chartAttr.drawanchors,
|
|
chartAttr.showanchors);
|
|
|
|
conf.anchorBgColor = pluck(JSONData.qdiconcolor,
|
|
chartAttr.qdiconcolor, COLOR_000000);
|
|
conf.anchorBorderColor = COLOR_000000;
|
|
conf.anchorRadius = pluckNumber(JSONData.qdiconradius, chartAttr.qdiconradius, 5);
|
|
conf.anchorAlpha = pluck(JSONData.alpha,
|
|
JSONData.qdiconalpha, chartAttr.qdiconalpha);
|
|
conf.anchorBgAlpha = pluck(JSONData.qdiconalpha, chartAttr.qdiconalpha, 100);
|
|
conf.anchorBorderThickness = pluck(JSONData.anchorborderthickness,
|
|
chartAttr.anchorborderthickness, 1);
|
|
conf.anchorSides = pluck(JSONData.qdiconsides, chartAttr.qdiconsides, 3);
|
|
|
|
conf.linecolor = conf.anchorBgColor;
|
|
|
|
// Spline attributes
|
|
conf.minimizeTendency = pluckNumber(chartAttr.minimizetendency,chartAttr.minimisetendency,0);
|
|
|
|
// Anchor image cosmetics attributes
|
|
conf.anchorImageUrl = pluck(JSONData.anchorimageurl, chartAttr.anchorimageurl);
|
|
conf.anchorImageAlpha = pluckNumber(JSONData.anchorimagealpha, chartAttr.anchorimagealpha, 100);
|
|
conf.anchorImageScale = pluckNumber(JSONData.anchorimagescale, chartAttr.anchorimagescale, 100);
|
|
conf.anchorImagePadding = pluckNumber(JSONData.anchorimagepadding, chartAttr.anchorimagepadding, 1);
|
|
conf.anchorStartAngle = pluckNumber(JSONData.anchorstartangle, chartAttr.anchorstartangle, 90);
|
|
conf.anchorShadow = pluckNumber(JSONData.anchorshadow, chartAttr.anchorshadow, 0);
|
|
!dataSet.components.data && (dataSet.components.data = []);
|
|
dataStore = dataSet.components.data;
|
|
|
|
for (i=0; i<len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i] = dataStore[i] || {};
|
|
dataObj.config = dataObj.config || {};
|
|
config = dataObj.config;
|
|
thisConfig = this.components.data[i].config;
|
|
|
|
if (thisConfig.showQD) {
|
|
setData.value = thisConfig.qd;
|
|
}
|
|
else {
|
|
setData.value = null;
|
|
}
|
|
|
|
config.x = this.components.data[i]._xPos;
|
|
|
|
config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
|
|
config.setLink = pluck(setData.link);
|
|
// Parsing the anchor properties for set level
|
|
config.anchorProps = this._parseAnchorProperties(i, dataSet, qdStr);
|
|
catObj = xAxis.getLabel(i);
|
|
config.label = lib.getValidValue(parseUnsafeString(pluck(catObj.tooltext,
|
|
catObj.label, catObj.name)));
|
|
config.showValue = 0;
|
|
|
|
// Dashed, color and alpha configuration in set level is only for line chart
|
|
config.dashed = pluckNumber(setData.dashed, lineDashed);
|
|
config.color = pluck(setData.color, conf.lineColor);
|
|
config.alpha = pluck(setData.alpha, setData.alpha, conf.alpha);
|
|
maxValue = mathMax(maxValue, setValue);
|
|
minValue = mathMin(minValue, setValue);
|
|
config.dashStyle = config.dashed ? lineDashStyle : NONE;
|
|
config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
|
|
config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
|
|
config.displayValue = pluck(setDisplayValue, toolTipValue);
|
|
config.formatedVal = formatedVal = config.toolTipValue;
|
|
config.setTooltext = lib.getValidValue(parseUnsafeString(pluck(setData.tooltext,
|
|
JSONData.plottooltext, chartAttr.plottooltext)));
|
|
QDIconShape = pluck(setData.qdiconshape, JSONData.qdiconshape,
|
|
chartAttr.qdiconshape, POLYGON);
|
|
conf.dip = config.dip = (QDIconShape === POLYGON) ? 0 : (QDIconShape === SPOKE) ? 1 : 0;
|
|
// Initial tooltext parsing
|
|
|
|
if (!conf.showTooltip) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
if (formatedVal === null) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
toolText = BOLDSTARTTAG + QD_STR + tooltipSepChar + BOLDENDTAG;
|
|
}
|
|
}
|
|
config.toolText = toolText;
|
|
// Storing the initial parsed tooltext which will be later used in stack100percent calculations
|
|
// on legend click
|
|
config.setTooltext = toolText;
|
|
if (!dataObj) {
|
|
dataObj = dataStore[i] = {
|
|
graphics : {}
|
|
};
|
|
}
|
|
else if (!dataObj.graphics) {
|
|
dataStore[i].graphics = {};
|
|
|
|
}
|
|
config.hoverEffects = {
|
|
enabled: false
|
|
};
|
|
}
|
|
conf.maxValue = maxValue;
|
|
conf.minValue = minValue;
|
|
},
|
|
|
|
configureOutliers: function (dataSet, outlierIndex) {
|
|
var chart = dataSet.chart,
|
|
chartComponents = chart.components,
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
conf = dataSet.config,
|
|
JSONData = dataSet.JSONData,
|
|
chartAttr = chart.jsonData.chart,
|
|
singleSeries = chart.singleseries,
|
|
colorM = chartComponents.colorManager,
|
|
index = dataSet.index || dataSet.stackIndex,
|
|
plotType = dataSet.type,
|
|
plotFillColor = !singleSeries || getValidValue(chartAttr.palettecolors) ?
|
|
colorM.getPlotColor(index) : colorM.getColor(PLOTFILLCOLOR_STR).split(/\s*\,\s*/)[0],
|
|
setDataArr = JSONData.data,
|
|
setData,
|
|
dataObj,
|
|
dataSetLen = setDataArr && setDataArr.length,
|
|
categories = chart.config.categories,
|
|
catLen = categories && categories.length,
|
|
len = mathMin(catLen, dataSetLen),
|
|
dataStore,
|
|
numberFormatter = chartComponents.numberFormatter,
|
|
config,
|
|
i,
|
|
toolText,
|
|
use3dlineshift = chart.use3dlineshift,
|
|
toolTipValue,
|
|
setValue,
|
|
setDisplayValue,
|
|
formatedVal,
|
|
maxValue = -Infinity,
|
|
minValue = +Infinity,
|
|
parentYAxis,
|
|
enableAnimation,
|
|
lineDashStyle,
|
|
stack100Percent,
|
|
defaultShadow,
|
|
tooltipSepChar = pluck(chartAttr.tooltipsepchar, ': '),
|
|
lineDashed = pluckNumber(JSONData.dashed, chartAttr.linedashed),
|
|
isStacked = chart.isStacked,
|
|
hasLineSet = chart.hasLineSet,
|
|
catObj,
|
|
xAxis = chartComponents.xAxis[0],
|
|
outlierIconShape,
|
|
thisConfig;
|
|
|
|
dataSet.visible = pluckNumber(dataSet.JSONData.visible,
|
|
!Number(dataSet.JSONData.initiallyhidden), 1) === 1;
|
|
|
|
if (use3dlineshift !== UNDEFINED) {
|
|
conf.use3dlineshift = pluckNumber(chartAttr.use3dlineshift, use3dlineshift);
|
|
}
|
|
else {
|
|
conf.use3dlineshift = 1;
|
|
}
|
|
conf.plotColor = plotFillColor;
|
|
conf.legendSymbolColor = conf.plotColor;
|
|
defaultShadow = pluckNumber(chart.defaultPlotShadow, colorM.getColor(SHOWSHADOW));
|
|
|
|
// Functional attributes configuration
|
|
|
|
conf.drawFullAreaBorder = pluckNumber(chartAttr.drawfullareaborder, 1);
|
|
// ParentYAxis is always 1 for lineset
|
|
if (hasLineSet) {
|
|
conf.parentYAxis = parentYAxis = 1;
|
|
}
|
|
else {
|
|
conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
|
|
pStr) === sStr ? 1 : 0 ;
|
|
}
|
|
conf.connectNullData = pluckNumber(chartAttr.connectnulldata, 0);
|
|
|
|
// Animation related attributes configuration
|
|
conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
|
|
chartAttr.defaultanimation, 1);
|
|
conf.animation = !enableAnimation ? false : {
|
|
duration: pluckNumber(chartAttr.animationduration, 1) * 1000
|
|
};
|
|
conf.transposeanimation = pluckNumber(chartAttr.transposeanimation, enableAnimation);
|
|
conf.transposeanimduration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;
|
|
|
|
// Value related configurations
|
|
conf.showValues = 0;
|
|
conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
|
|
conf.valuePosition = pluck(JSONData.valueposition, chartAttr.valueposition, 'auto');
|
|
conf.stack100Percent = stack100Percent = pluckNumber(chartAttr.stack100percent, 0),
|
|
conf.showPercentValues = pluckNumber(chartAttr.showpercentvalues, (isStacked && stack100Percent) ?
|
|
1 : 0);
|
|
conf.showPercentInToolTip = pluckNumber(chartAttr.showpercentintooltip,
|
|
(isStacked && stack100Percent) ? 1 : 0);
|
|
|
|
// Tooltip related attributes
|
|
conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
|
|
conf.seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1);
|
|
|
|
conf.showHoverEffect = pluckNumber(chartAttr.plothovereffect, chartAttr.anchorhovereffect,
|
|
chartAttr.showhovereffect, UNDEFINED);
|
|
|
|
conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
|
|
// Line configuration attributes parsing
|
|
conf.linethickness = pluckNumber(JSONData.linethickness,
|
|
chartAttr.linethickness, 1);
|
|
conf.lineDashLen = pluckNumber(JSONData.linedashlen, chartAttr.linedashlen, 5);
|
|
conf.lineDashGap = pluckNumber(JSONData.linedashgap, chartAttr.linedashgap, 4);
|
|
conf.alpha = 0;
|
|
|
|
lineDashStyle = lib.getDashStyle(conf.lineDashLen, conf.lineDashGap, conf.linethickness);
|
|
conf.lineDashStyle = lineDashed ?
|
|
lineDashStyle : NONE;
|
|
|
|
conf.shadow = {
|
|
opacity: pluckNumber(chartAttr.showshadow, defaultShadow) ?
|
|
(plotType === LINE ? conf.alpha/100 :
|
|
conf.plotBorderAlpha/100) : 0
|
|
};
|
|
// Anchor cosmetics attributes in dataset level
|
|
conf.drawAnchors = pluckNumber(JSONData.drawanchors, JSONData.showanchors, chartAttr.drawanchors,
|
|
chartAttr.showanchors);
|
|
|
|
conf.anchorBgColor = pluck(JSONData.outliericoncolor,
|
|
chartAttr.outliericoncolor, COLOR_000000);
|
|
conf.anchorBorderColor = COLOR_000000;
|
|
conf.anchorRadius = pluckNumber(JSONData.outliericonradius, chartAttr.outliericonradius, 5);
|
|
conf.anchorAlpha = pluck(JSONData.alpha,
|
|
JSONData.outliericonalpha, chartAttr.outliericonalpha);
|
|
conf.anchorBgAlpha = pluck(JSONData.outliericonalpha, chartAttr.outliericonalpha, 100);
|
|
conf.anchorBorderThickness = pluck(JSONData.anchorborderthickness,
|
|
chartAttr.anchorborderthickness, 1);
|
|
conf.anchorSides = pluck(JSONData.outliericonsides, chartAttr.outliericonsides, 3);
|
|
|
|
conf.linecolor = conf.anchorBgColor;
|
|
|
|
// Spline attributes
|
|
conf.minimizeTendency = pluckNumber(chartAttr.minimizetendency,chartAttr.minimisetendency,0);
|
|
|
|
// Anchor image cosmetics attributes
|
|
conf.anchorImageUrl = pluck(JSONData.anchorimageurl, chartAttr.anchorimageurl);
|
|
conf.anchorImageAlpha = pluckNumber(JSONData.anchorimagealpha, chartAttr.anchorimagealpha, 100);
|
|
conf.anchorImageScale = pluckNumber(JSONData.anchorimagescale, chartAttr.anchorimagescale, 100);
|
|
conf.anchorImagePadding = pluckNumber(JSONData.anchorimagepadding, chartAttr.anchorimagepadding, 1);
|
|
conf.anchorStartAngle = pluckNumber(JSONData.anchorstartangle, chartAttr.anchorstartangle, 90);
|
|
conf.anchorShadow = pluckNumber(JSONData.anchorshadow, chartAttr.anchorshadow, 0);
|
|
!dataSet.components.data && (dataSet.components.data = []);
|
|
dataStore = dataSet.components.data;
|
|
|
|
for (i=0; i<len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i] = dataStore[i] || {};
|
|
dataObj.config = dataObj.config || {};
|
|
config = dataObj.config;
|
|
thisConfig = this.components.data[i].config;
|
|
|
|
if (thisConfig.outliers) {
|
|
setData.value = thisConfig.outliers[outlierIndex];
|
|
}
|
|
else {
|
|
setData.value = null;
|
|
}
|
|
|
|
config.x = this.components.data[i]._xPos;
|
|
|
|
config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
|
|
|
|
if ((setValue >= thisConfig.min) && (setValue <= thisConfig.max)) {
|
|
config.setValue = setData.value = null;
|
|
}
|
|
|
|
config.setLink = pluck(setData.link);
|
|
// Parsing the anchor properties for set level
|
|
config.anchorProps = this._parseAnchorProperties(i, dataSet, outlierStr);
|
|
catObj = xAxis.getLabel(i);
|
|
config.label = lib.getValidValue(parseUnsafeString(pluck(catObj.tooltext,
|
|
catObj.label, catObj.name)));
|
|
config.showValue = 0;
|
|
|
|
// Dashed, color and alpha configuration in set level is only for line chart
|
|
config.dashed = pluckNumber(setData.dashed, lineDashed);
|
|
config.color = pluck(setData.color, conf.lineColor);
|
|
config.alpha = pluck(setData.alpha, setData.alpha, conf.alpha);
|
|
maxValue = mathMax(maxValue, setValue);
|
|
minValue = mathMin(minValue, setValue);
|
|
config.dashStyle = config.dashed ? lineDashStyle : NONE;
|
|
config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
|
|
config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
|
|
config.displayValue = pluck(setDisplayValue, toolTipValue);
|
|
config.formatedVal = formatedVal = config.toolTipValue;
|
|
config.setTooltext = lib.getValidValue(parseUnsafeString(pluck(setData.tooltext,
|
|
JSONData.plottooltext, chartAttr.plottooltext)));
|
|
outlierIconShape = pluck(setData.outliericonshape, JSONData.outliericonshape,
|
|
chartAttr.outliericonshape, POLYGON);
|
|
conf.dip = config.dip = (outlierIconShape === POLYGON) ? 0 : (outlierIconShape === SPOKE) ? 1 : 0;
|
|
// Initial tooltext parsing
|
|
|
|
if (!conf.showTooltip) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
if (formatedVal === null) {
|
|
toolText = false;
|
|
}
|
|
else {
|
|
toolText = BOLDSTARTTAG + OUTLIER_STR + tooltipSepChar + BOLDENDTAG;
|
|
}
|
|
}
|
|
config.toolText = toolText;
|
|
// Storing the initial parsed tooltext which will be later used in stack100percent calculations
|
|
// on legend click
|
|
config.setTooltext = toolText;
|
|
if (!dataObj) {
|
|
dataObj = dataStore[i] = {
|
|
graphics : {}
|
|
};
|
|
}
|
|
else if (!dataObj.graphics) {
|
|
dataStore[i].graphics = {};
|
|
|
|
}
|
|
config.hoverEffects = {
|
|
enabled: false
|
|
};
|
|
}
|
|
conf.maxValue = maxValue;
|
|
conf.minValue = minValue;
|
|
},
|
|
|
|
initSubDataset: function (datasetJSON, dataSet) {
|
|
var chart = dataSet.chart,
|
|
components = chart.components,
|
|
hasLineSet = chart.hasLineSet,
|
|
parentYAxis = ((datasetJSON.parentyaxis && datasetJSON.parentyaxis.toLowerCase() === sStr) ||
|
|
hasLineSet) ? 1 : 0,
|
|
yAxis;
|
|
dataSet.chart = chart;
|
|
yAxis = components.yAxis[parentYAxis];
|
|
dataSet.yAxis = yAxis;
|
|
dataSet.components = {
|
|
|
|
};
|
|
|
|
dataSet.graphics = {
|
|
|
|
};
|
|
dataSet.JSONData = datasetJSON;
|
|
// dataSet.visible = pluckNumber(dataSet.JSONData.visible,
|
|
// !Number(dataSet.JSONData.initiallyhidden), 1) === 1;
|
|
},
|
|
|
|
_parseAnchorProperties : function (i, dataSet, type) {
|
|
var conf = dataSet.config,
|
|
plotType = dataSet.type,
|
|
defaultAnchorVisibility = plotType === 'area' ? 0 : 1,
|
|
JSONData = dataSet.JSONData,
|
|
chartAttr = dataSet.chart.jsonData.chart,
|
|
setDataArr = JSONData.data,
|
|
setData = setDataArr[i],
|
|
anchorProps = {},
|
|
mapSymbolName = lib.graphics.mapSymbolName,
|
|
anchorAlpha,
|
|
anchorAttrsDefined,
|
|
drawAnchors;
|
|
// Check if anchor attributes are defined
|
|
anchorAttrsDefined = pluck(setData.anchorstartangle, JSONData.anchorstartangle,
|
|
chartAttr.anchorstartangle,
|
|
setData.anchorimagealpha, JSONData.anchorimagealpha, chartAttr.anchorimagealpha,
|
|
setData.anchorimagescale, JSONData.anchorimagescale, chartAttr.anchorimagescale,
|
|
setData.anchorimagepadding, JSONData.anchorimagepadding, chartAttr.anchorimagepadding,
|
|
setData.anchorimageurl, JSONData.anchorimageurl, chartAttr.anchorimageurl,
|
|
setData.meaniconradius, JSONData.meaniconradius, chartAttr.meaniconradius,
|
|
setData.meaniconcolor, JSONData.meaniconcolor, chartAttr.meaniconcolor,
|
|
setData.anchorbordercolor, JSONData.anchorbordercolor, chartAttr.anchorbordercolor,
|
|
setData.anchoralpha, JSONData.anchoralpha, chartAttr.anchoralpha,
|
|
setData.meaniconsides, JSONData.meaniconsides, chartAttr.meaniconsides,
|
|
setData.anchorborderthickness, JSONData.anchorborderthickness,
|
|
chartAttr.anchorborderthickness, UNDEFINED
|
|
) !== UNDEFINED;
|
|
drawAnchors = pluckNumber(setData.drawanchors, conf.drawAnchors);
|
|
/*
|
|
If any anchor attribute is defined then we choose between draw anchors attribute
|
|
and whether any anchor attributes are defined
|
|
Otherwise we choose between default anchor visibility which is false for area
|
|
and true for line and drawanchors attribute
|
|
*/
|
|
if (anchorAttrsDefined) {
|
|
anchorProps.enabled = pluckNumber(drawAnchors, anchorAttrsDefined);
|
|
}
|
|
else {
|
|
anchorProps.enabled = pluckNumber(drawAnchors, defaultAnchorVisibility);
|
|
}
|
|
anchorProps.startAngle = pluckNumber(setData.anchorstartangle, conf.anchorStartAngle);
|
|
anchorProps.imageAlpha = pluckNumber(setData.anchorimagealpha, conf.anchorImageAlpha);
|
|
anchorProps.imageScale = pluckNumber(setData.anchorimagescale, conf.anchorImageScale);
|
|
anchorProps.imagePadding = pluckNumber(setData.anchorimagepadding, conf.anchorImagePadding);
|
|
if (anchorProps.imagePadding < 0) {
|
|
anchorProps.imagePadding = 0;
|
|
}
|
|
anchorProps.imageUrl = pluck(setData.anchorimageurl, conf.anchorImageUrl);
|
|
anchorProps.radius = pluckNumber(setData[type + iconradiusStr], conf.anchorRadius);
|
|
anchorProps.isAnchorRadius = anchorProps.radius;
|
|
anchorProps.bgColor = pluck(setData[type + iconcolorStr], conf.anchorBgColor);
|
|
if (!anchorProps.enabled) {
|
|
anchorAlpha = 0;
|
|
}
|
|
else {
|
|
anchorAlpha = getFirstAlpha(pluck(setData.anchoralpha, conf.anchorAlpha,
|
|
anchorProps.enabled ? HUNDREDSTRING : ZEROSTRING));
|
|
}
|
|
|
|
anchorProps.bgAlpha = getFirstAlpha(pluck(setData[type + iconalphaStr],
|
|
conf.meaniconalpha, anchorAlpha));
|
|
|
|
anchorProps.borderColor = pluck(setData.anchorbordercolor, conf.anchorBorderColor);
|
|
anchorProps.borderAlpha = anchorAlpha;
|
|
anchorProps.anchorAlpha = anchorAlpha;
|
|
anchorProps.sides = pluck(setData[type + iconsidesStr], conf.anchorSides);
|
|
anchorProps.borderThickness = pluck(setData.anchorborderthickness, conf.anchorBorderThickness);
|
|
anchorProps.symbol = mapSymbolName(anchorProps.sides).split(UNDERSCORE);
|
|
anchorProps.shadow = (pluckNumber(setData.anchorshadow, conf.anchorShadow) &&
|
|
anchorProps.radius >= 1) ? {
|
|
opacity: anchorAlpha / 100
|
|
} : false;
|
|
conf.attachEvents = true;
|
|
return anchorProps;
|
|
},
|
|
|
|
init : function(datasetJSON) {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
components = chart.components,
|
|
parentYAxis = datasetJSON.parentyaxis && datasetJSON.parentyaxis.toLowerCase() === sStr ? 1 : 0,
|
|
yAxis = components.yAxis[parentYAxis];
|
|
|
|
if (!datasetJSON) {
|
|
return false;
|
|
}
|
|
dataSet.JSONData = datasetJSON;
|
|
dataSet.yAxis = yAxis;
|
|
dataSet.chartGraphics = chart.chartGraphics;
|
|
dataSet.components = {
|
|
};
|
|
|
|
dataSet.graphics = {
|
|
};
|
|
|
|
dataSet.configure();
|
|
},
|
|
|
|
draw: function () {
|
|
var dataSet = this,
|
|
JSONData = dataSet.JSONData,
|
|
conf = dataSet.config,
|
|
groupManager = dataSet.groupManager,
|
|
datasetIndex = dataSet.index,
|
|
categories = dataSet.chart.config.categories,
|
|
setDataArr = JSONData.data,
|
|
catLen = categories && categories.length,
|
|
dataSetLen = setDataArr && setDataArr.length,
|
|
len,
|
|
setData,
|
|
attr,
|
|
i,
|
|
visible = dataSet.visible,
|
|
chart = dataSet.chart,
|
|
chartConfig = chart.config,
|
|
paper = chart.components.paper,
|
|
xAxis = chart.components.xAxis[0],
|
|
yAxis = dataSet.yAxis,
|
|
parentContainer = chart.graphics.columnGroup,
|
|
xPos,
|
|
yPos,
|
|
layers = chart.graphics,
|
|
showTooltip = conf.showtooltip,
|
|
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animType = animationObj.animType,
|
|
animObj = animationObj.animObj,
|
|
dummyObj = animationObj.dummyObj,
|
|
animationDuration = animationObj.duration,
|
|
|
|
xAxisZeroPos = xAxis.getAxisPosition(0),
|
|
xAxisFirstPos = xAxis.getAxisPosition(1),
|
|
groupMaxWidth = xAxisFirstPos - xAxisZeroPos,
|
|
definedGroupPadding = conf.definedGroupPadding,
|
|
plotSpacePercent = conf.plotSpacePercent,
|
|
groupPadding = plotSpacePercent / 200,
|
|
numOfColumns = 1,
|
|
positionValue = groupManager.getDataSetPosition(dataSet),
|
|
maxColWidth = conf.maxcolwidth,
|
|
// Calculating the net width occupied by bars for each category
|
|
groupNetWidth = (1 - definedGroupPadding * 0.01) * groupMaxWidth || mathMin(
|
|
groupMaxWidth * (1 - groupPadding * 2),
|
|
maxColWidth * numOfColumns
|
|
),
|
|
initialColumnWidth = pluckNumber(positionValue.columnWidth, (groupNetWidth / numOfColumns)),
|
|
columnWidth,
|
|
xPosOffset = positionValue.xPosOffset || 0,
|
|
hiddenDatasetHeight = positionValue.height,
|
|
toolText,
|
|
dataStore = dataSet.components.data,
|
|
dataObj,
|
|
setLink,
|
|
setValue,
|
|
eventArgs,
|
|
displayValue,
|
|
config,
|
|
isPositive,
|
|
yBase = yAxis.getAxisBase(),
|
|
previousY,
|
|
previousYPos,
|
|
showShadow = conf.showShadow,
|
|
|
|
upperBoxContainer = dataSet.graphics.upperBoxContainer,
|
|
lowerBoxContainer = dataSet.graphics.lowerBoxContainer,
|
|
medianContainer = dataSet.graphics.medianContainer,
|
|
|
|
upperWhiskerContainer = dataSet.graphics.upperWhiskerContainer,
|
|
lowerWhiskerContainer = dataSet.graphics.lowerWhiskerContainer,
|
|
|
|
dataLabelContainer = dataSet.graphics.dataLabelContainer,
|
|
shadowContainer = dataSet.graphics.shadowContainer,
|
|
|
|
colorArr,
|
|
upperQuartile,
|
|
yTop,
|
|
yTopPos,
|
|
lowerQuartile,
|
|
yBottom,
|
|
yBottomPos,
|
|
median,
|
|
yMed,
|
|
yMedPos,
|
|
upperBoxH,
|
|
lowerBoxH,
|
|
upperBoxBorder,
|
|
lowerBoxBorder,
|
|
upperBoxElem,
|
|
upperBoxBorderEle,
|
|
upperQuartileEle,
|
|
lowerBoxElem,
|
|
lowerBoxBorderEle,
|
|
lowerQuartileEle,
|
|
midLineElem,
|
|
crispX,
|
|
crispX2,
|
|
crispY,
|
|
style = chart.config.dataLabelStyle,
|
|
dataLabelsLayer = layers.datalabelsGroup,
|
|
hoverOutEffects,
|
|
rotateValues = conf.rotatevalues,
|
|
valuePadding = conf.valuepadding,
|
|
|
|
numberFormatter = chart.components.numberFormatter,
|
|
textAlign = rotateValues ? POSITION_LEFT : POSITION_MIDDLE,
|
|
smartLabel = chart.linkedItems.smartLabel,
|
|
graphic,
|
|
groupId,
|
|
errorStartPos,
|
|
errorBarWidth,
|
|
halfErrorBarW,
|
|
errorValPos,
|
|
crispyX,
|
|
crispyY,
|
|
upperWhiskerEle,
|
|
errorPath,
|
|
lowerWhiskerEle,
|
|
smartText,
|
|
lineHeight,
|
|
labelBottomY,
|
|
labelTopY,
|
|
lastDataSetHeight = +Infinity,
|
|
lastDataSetYpos,
|
|
j,
|
|
animFlag = true,
|
|
removeDataArr = dataSet.components.removeDataArr || [],
|
|
removeDataArrLen = removeDataArr.length,
|
|
newupperBoxElem,
|
|
newlowerBoxElem,
|
|
newupperBoxBorderEle,
|
|
newlowerBoxBorderEle,
|
|
newupperQuartileEle,
|
|
newlowerQuartileEle,
|
|
newmidLineElem,
|
|
newupperWhiskerEle,
|
|
newlowerWhiskerEle,
|
|
hoverInAttr,
|
|
hoverOutAttr,
|
|
showHoverEffect = conf.showHoverEffect,
|
|
x,
|
|
y,
|
|
upperBoxStartPos,
|
|
lowerBoxYPos,
|
|
lowerBoxHeight,
|
|
lowerBoxEndPos,
|
|
|
|
// Fired when clicked over the hot elements.
|
|
clickFunc = function (setDataArr) {
|
|
var ele = this;
|
|
plotEventHandler.call(ele, chart, setDataArr);
|
|
},
|
|
|
|
//Fired on mouse-in over the hot elements.
|
|
rolloverResponseSetter = function (obj) {
|
|
return function (data) {
|
|
var ele = this,
|
|
elem;
|
|
|
|
if (ele.data(showHoverEffectStr) !== 0) {
|
|
for (elem in obj) {
|
|
if (elem !== LABEL) {
|
|
obj[elem].attr(ele.data(SETROLLOVERATTR)[elem]);
|
|
plotEventHandler.call(ele, chart, data, ROLLOVER);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
},
|
|
|
|
//Fired on mouse-out over the hot elements.
|
|
rolloutResponseSetter = function (obj) {
|
|
return function (data) {
|
|
var ele = this,
|
|
elem;
|
|
|
|
if (ele.data(showHoverEffectStr) !== 0) {
|
|
for (elem in obj) {
|
|
if (elem !== LABEL) {
|
|
obj[elem].attr(ele.data(SETROLLOUTATTR)[elem]);
|
|
plotEventHandler.call(ele, chart, data, ROLLOUT);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
},
|
|
animCallBack = function () {
|
|
if (dataSet.visible === false && (dataSet._conatinerHidden === false ||
|
|
dataSet._conatinerHidden=== UNDEFINED)) {
|
|
upperBoxContainer.hide();
|
|
lowerBoxContainer.hide();
|
|
upperWhiskerContainer.hide();
|
|
lowerWhiskerContainer.hide();
|
|
medianContainer.hide();
|
|
shadowContainer.hide();
|
|
dataLabelContainer && dataLabelContainer.hide();
|
|
dataSet._conatinerHidden = true;
|
|
}
|
|
};
|
|
|
|
if (!dataLabelContainer) {
|
|
dataLabelContainer = dataSet.graphics.dataLabelContainer =
|
|
paper.group(dataLabelStr, dataLabelsLayer);
|
|
if (!visible) {
|
|
dataLabelContainer.hide();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Creating a container group for the graphic element of column plots if
|
|
* not present and attaching it to its parent group.
|
|
*/
|
|
if (!upperBoxContainer) {
|
|
upperBoxContainer = dataSet.graphics.upperBoxContainer =
|
|
paper.group('upperBox', parentContainer).trackTooltip(true).toBack();
|
|
if (!visible) {
|
|
upperBoxContainer.hide();
|
|
}
|
|
}
|
|
|
|
if (!upperWhiskerContainer) {
|
|
upperWhiskerContainer = dataSet.graphics.upperWhiskerContainer =
|
|
paper.group('upperWhisker', parentContainer).trackTooltip(true);
|
|
if (!visible) {
|
|
upperWhiskerContainer.hide();
|
|
}
|
|
}
|
|
|
|
if (!lowerBoxContainer) {
|
|
lowerBoxContainer = dataSet.graphics.lowerBoxContainer = paper.group('lowerBox', parentContainer)
|
|
.trackTooltip(true).toBack();
|
|
if (!visible) {
|
|
lowerBoxContainer.hide();
|
|
}
|
|
}
|
|
|
|
if (!lowerWhiskerContainer) {
|
|
lowerWhiskerContainer = dataSet.graphics.lowerWhiskerContainer =
|
|
paper.group('lowerWhisker', parentContainer).trackTooltip(true);
|
|
if (!visible) {
|
|
lowerWhiskerContainer.hide();
|
|
}
|
|
}
|
|
|
|
if (!medianContainer) {
|
|
medianContainer = dataSet.graphics.medianContainer = paper.group('median', parentContainer)
|
|
.trackTooltip(true);
|
|
if (!visible) {
|
|
medianContainer.hide();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Creating the shadow element container group for each plots if not present
|
|
* and attaching it its parent group.
|
|
*/
|
|
if (!shadowContainer) {
|
|
// Always sending the shadow group to the back of the plots group.
|
|
shadowContainer = dataSet.graphics.shadowContainer =
|
|
paper.group(shadowStr, parentContainer).toBack();
|
|
if (!visible) {
|
|
shadowContainer.hide();
|
|
}
|
|
|
|
}
|
|
|
|
if (visible) {
|
|
// Showing the groups when visible set to true
|
|
upperBoxContainer.show();
|
|
lowerBoxContainer.show();
|
|
upperWhiskerContainer.show();
|
|
lowerWhiskerContainer.show();
|
|
medianContainer.show();
|
|
shadowContainer.show();
|
|
dataLabelContainer && dataLabelContainer.show();
|
|
dataSet._conatinerHidden = false;
|
|
|
|
dataSet.components.mean.visible && dataSet.components.mean.show();
|
|
dataSet.components.sd.visible && dataSet.components.sd.show();
|
|
dataSet.components.qd.visible && dataSet.components.qd.show();
|
|
dataSet.components.md.visible && dataSet.components.md.show();
|
|
}
|
|
|
|
len = mathMin(catLen, dataSetLen);
|
|
|
|
// Create plot elements.
|
|
for (i = 0; i < len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
config = dataObj && dataObj.config;
|
|
setValue = config && config.setValue;
|
|
|
|
newupperBoxElem = false;
|
|
newlowerBoxElem = false;
|
|
newupperBoxBorderEle = false;
|
|
newlowerBoxBorderEle = false;
|
|
newupperQuartileEle = false;
|
|
newlowerQuartileEle = false;
|
|
newmidLineElem = false;
|
|
newupperWhiskerEle = false;
|
|
newlowerWhiskerEle = false;
|
|
|
|
// If plot value is found "null", continue the loop to next iteration.
|
|
if (dataObj === UNDEFINED || setValue === UNDEFINED || setValue === null) {
|
|
continue;
|
|
}
|
|
|
|
graphic = dataObj.graphics;
|
|
|
|
isPositive = setValue >= 0;
|
|
|
|
setLink = config.setLink;
|
|
colorArr = config.colorArr;
|
|
|
|
// Creating the data structure if not present for storing the graphics elements.
|
|
if (!dataObj.graphics) {
|
|
dataStore[i].graphics = {};
|
|
|
|
}
|
|
if (!graphic.label) {
|
|
dataStore[i].graphics.label = [];
|
|
|
|
}
|
|
|
|
displayValue = config.displayValue;
|
|
|
|
previousY = isPositive ? config.previousPositiveY : config.previousNegativeY;
|
|
|
|
// Getting the previous yposition of the plot and calculating the current yposition of the plot.
|
|
previousYPos = yAxis.getAxisPosition( previousY|| yBase);
|
|
xPos = xAxis.getAxisPosition(i) + xPosOffset;
|
|
|
|
/*
|
|
* Check for setting the height of the datasets which are hidden. If the datasets are hidden then
|
|
* the height is set to 0 and ypos is set to the ypos of the previous plot.
|
|
*/
|
|
if (hiddenDatasetHeight === 0) {
|
|
lastDataSetHeight = 0;
|
|
lastDataSetYpos = previousYPos;
|
|
}
|
|
yPos = mathMin(yPos,previousYPos);
|
|
|
|
columnWidth = initialColumnWidth;
|
|
|
|
upperQuartile = config.upperQuartile || {};
|
|
yTop = upperQuartile && upperQuartile.value;
|
|
yTopPos = (yTop || yTop === 0)&& yAxis.getAxisPosition(yTop);
|
|
|
|
lowerQuartile = config.lowerQuartile || {};
|
|
yBottom = lowerQuartile && lowerQuartile.value;
|
|
yBottomPos = (yBottom || yBottom === 0) && yAxis.getAxisPosition(yBottom);
|
|
|
|
median = config.median;
|
|
yMed = median && median.value; // || yBottom;
|
|
yMedPos = (yMed || yMed === 0) && yAxis.getAxisPosition(yMed);
|
|
|
|
upperBoxH = yMedPos - yTopPos;
|
|
lowerBoxH = yBottomPos - yMedPos;
|
|
|
|
upperBoxBorder = config.upperBoxBorder || {};
|
|
lowerBoxBorder = config.lowerBoxBorder || {};
|
|
|
|
toolText = config.toolText;
|
|
groupId = dataSet.index + UNDERSCORE + i;
|
|
|
|
eventArgs = {
|
|
index: i,
|
|
link: setLink,
|
|
maximum: config.max,
|
|
minimum: config.min,
|
|
median: yMed,
|
|
q3: upperQuartile.value,
|
|
q1: lowerQuartile.value,
|
|
maxDisplayValue: config.showMaxValues ? numberFormatter.dataLabels(config.max) : BLANKSTRING,
|
|
minDisplayValue: config.showMinValues ? numberFormatter.dataLabels(config.min) : BLANKSTRING,
|
|
medianDisplayValue: config.showMedianValues ? numberFormatter.dataLabels(yMed) : BLANKSTRING,
|
|
q1DisplayValue: config.showQ1Values ? numberFormatter.dataLabels(lowerQuartile.value) :
|
|
BLANKSTRING,
|
|
q3DisplayValue: config.showQ3Values ? numberFormatter.dataLabels(upperQuartile.value) :
|
|
BLANKSTRING,
|
|
categoryLabel: config.label,
|
|
toolText: toolText,
|
|
datasetIndex: datasetIndex,
|
|
datasetName: JSONData.seriesname,
|
|
visible: visible
|
|
};
|
|
|
|
// upperBox
|
|
crispX = mathRound(xPos) + upperBoxBorder.borderWidth % 2 *
|
|
0.5;
|
|
crispX2 = mathRound(xPos + columnWidth) +
|
|
upperBoxBorder.borderWidth % 2 * 0.5;
|
|
crispY = mathRound(yTopPos) + upperQuartile.borderWidth %
|
|
2 * 0.5;
|
|
columnWidth = crispX2 - crispX;
|
|
|
|
hoverOutEffects = {
|
|
upperBox: {
|
|
fill: toRaphaelColor(config.upperColorArr[0]), //upperQuartile.color
|
|
'stroke-width': 0,
|
|
'stroke-dasharray': NONE,
|
|
cursor: setLink ? POINTER : BLANKSTRING,
|
|
ishot: true,
|
|
visibility: visible
|
|
},
|
|
lowerBox: {
|
|
fill: toRaphaelColor(config.lowerColorArr[0]),
|
|
'stroke-width': 0,
|
|
'stroke-dasharray': NONE,
|
|
cursor: setLink ? POINTER : BLANK,
|
|
ishot: true,
|
|
visibility: visible
|
|
},
|
|
upperBoxBorder: {
|
|
stroke: upperBoxBorder.color,
|
|
'stroke-width': upperBoxBorder.borderWidth,
|
|
'stroke-linecap': ROUND,
|
|
dashstyle: upperBoxBorder.dashStyle,
|
|
ishot: true,
|
|
visibility: visible
|
|
},
|
|
lowerBoxBorder: {
|
|
stroke: lowerBoxBorder.color,
|
|
'stroke-width': lowerBoxBorder.borderWidth,
|
|
dashstyle: lowerBoxBorder.dashStyle,
|
|
'stroke-linecap': ROUND,
|
|
ishot: true,
|
|
visibility: visible
|
|
},
|
|
upperQuartile: {
|
|
stroke: toRaphaelColor(upperQuartile.color),
|
|
'stroke-width': upperQuartile.borderWidth,
|
|
'stroke-dasharray': upperQuartile.dashSyle,
|
|
'stroke-linecap': ROUND,
|
|
cursor: setLink ? POINTER : BLANK,
|
|
ishot: true,
|
|
visibility: visible
|
|
},
|
|
lowerQuartile: {
|
|
stroke: toRaphaelColor(lowerQuartile.color),
|
|
'stroke-width': lowerQuartile.borderWidth,
|
|
'stroke-dasharray': lowerQuartile.dashSyle,
|
|
cursor: setLink ? POINTER : BLANKSTRING,
|
|
'stroke-linecap': ROUND,
|
|
ishot: true,
|
|
visibility: visible
|
|
},
|
|
median: {
|
|
stroke: toRaphaelColor(median.color),
|
|
'stroke-width': median.borderWidth,
|
|
'stroke-dasharray': median.dashSyle,
|
|
cursor: setLink ? POINTER : BLANKSTRING,
|
|
'stroke-linecap': ROUND,
|
|
ishot: true,
|
|
visibility: visible
|
|
}
|
|
};
|
|
|
|
upperBoxStartPos = lastDataSetYpos || crispY;
|
|
|
|
// draw upperbox element
|
|
attr = {
|
|
x: crispX,
|
|
y: lastDataSetYpos || crispY,
|
|
width: mathMax(columnWidth, 0),
|
|
height: mathMax(mathMin(lastDataSetHeight, upperBoxH), 0),
|
|
r: 0
|
|
};
|
|
|
|
upperBoxElem = dataObj.graphics.upperBoxElem;
|
|
|
|
if (!upperBoxElem) {
|
|
upperBoxElem = dataObj.graphics.upperBoxElem = paper.rect(attr, upperBoxContainer);
|
|
newupperBoxElem = true;
|
|
}
|
|
else
|
|
{
|
|
upperBoxElem.animateWith(dummyObj, animObj, attr, animationDuration,
|
|
animType, (animFlag && animCallBack));
|
|
animFlag = false;
|
|
}
|
|
|
|
upperBoxElem.attr(hoverOutEffects.upperBox)
|
|
.shadow({opacity : showShadow ? conf.upperBoxAlpha / 100 : 0}, shadowContainer);
|
|
|
|
// draw upperBoxBorder element
|
|
attr = {
|
|
path: [M, crispX, lastDataSetYpos || crispY, V, lastDataSetYpos || crispY + upperBoxH,
|
|
M, crispX2, lastDataSetYpos || crispY, V, lastDataSetYpos || crispY + upperBoxH]
|
|
};
|
|
|
|
upperBoxBorderEle = dataObj.graphics.upperBoxBorderEle;
|
|
|
|
if (!upperBoxBorderEle) {
|
|
upperBoxBorderEle = dataObj.graphics.upperBoxBorderEle = paper.path(attr, upperBoxContainer);
|
|
newupperBoxBorderEle = true;
|
|
}
|
|
else
|
|
{
|
|
upperBoxBorderEle.animateWith(dummyObj, animObj, attr, animationDuration,
|
|
animType, (animFlag && animCallBack));
|
|
}
|
|
|
|
upperBoxBorderEle.attr(hoverOutEffects.upperBoxBorder);
|
|
|
|
// draw upperQuartileBorder element
|
|
attr = {
|
|
path: [M, crispX, (lastDataSetYpos || crispY), H, (crispX + columnWidth)]
|
|
};
|
|
|
|
upperQuartileEle = dataObj.graphics.upperQuartileEle;
|
|
|
|
if (!upperQuartileEle) {
|
|
upperQuartileEle = dataObj.graphics.upperQuartileEle = paper.path(attr, upperBoxContainer);
|
|
newupperQuartileEle = true;
|
|
}
|
|
else
|
|
{
|
|
upperQuartileEle.animateWith(dummyObj, animObj, attr, animationDuration,
|
|
animType, (animFlag && animCallBack));
|
|
}
|
|
|
|
upperQuartileEle.attr(hoverOutEffects.upperQuartile);
|
|
|
|
errorStartPos = crispY;
|
|
errorBarWidth = columnWidth * (conf.whiskerslimitswidthratio / 100);
|
|
halfErrorBarW = errorBarWidth / 2;
|
|
|
|
// Vertical Error drawing
|
|
errorValPos = yAxis.getAxisPosition(config.max);
|
|
crispyY = errorValPos;
|
|
crispyX = crispX;
|
|
|
|
crispyY = mathRound(errorValPos) +
|
|
(config.upperWhiskerThickness % 2 / 2);
|
|
crispX = mathRound(crispX + (columnWidth / 2)) +
|
|
(config.upperWhiskerThickness % 2 / 2);
|
|
|
|
errorPath = [
|
|
M, crispX, lastDataSetYpos || errorStartPos,
|
|
V, mathMin(lastDataSetYpos || crispyY, upperBoxStartPos),
|
|
M, crispX - halfErrorBarW, mathMin(lastDataSetYpos || crispyY, upperBoxStartPos),
|
|
H, (crispX + halfErrorBarW)
|
|
];
|
|
|
|
upperWhiskerEle = dataObj.graphics.upperWhiskerEle;
|
|
|
|
attr = {
|
|
path: errorPath,
|
|
// In case of tooltip disabled this element should act as the hot element.
|
|
ishot: !showTooltip,
|
|
'stroke-width': config.upperWhiskerThickness,
|
|
'cursor': setLink ? POINTER : BLANKSTRING,
|
|
'stroke-linecap': ROUND
|
|
};
|
|
|
|
if (!upperWhiskerEle) {
|
|
upperWhiskerEle = dataObj.graphics.upperWhiskerEle =
|
|
paper.path(attr, upperWhiskerContainer);
|
|
newupperWhiskerEle = true;
|
|
}
|
|
else
|
|
{
|
|
upperWhiskerEle.animateWith(dummyObj, animObj, attr, animationDuration,
|
|
animType, (animFlag && animCallBack));
|
|
}
|
|
|
|
upperWhiskerEle.attr({
|
|
stroke: config.upperWhiskerColor
|
|
});
|
|
|
|
upperWhiskerEle.shadow({opacity : config.upperWhiskerShadowOpacity}, shadowContainer);
|
|
smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
|
|
smartLabel.setStyle(style);
|
|
smartText = smartLabel.getOriSize(numberFormatter.dataLabels(config.max));
|
|
lineHeight = (rotateValues ? smartText.width :
|
|
smartText.height);
|
|
labelTopY = errorValPos - config.upperWhiskerThickness *
|
|
0.5 - valuePadding - lineHeight * (rotateValues ? 0.5 : 1);
|
|
|
|
if ((labelTopY - (rotateValues ? (lineHeight / 2) : 0)) < chartConfig.canvasTop) {
|
|
labelTopY = chartConfig.canvasTop + (rotateValues ? (lineHeight / 2) : 0);
|
|
}
|
|
|
|
attr = {
|
|
text: numberFormatter.dataLabels(config.max),
|
|
x: crispyX + columnWidth / 2,
|
|
title: (upperQuartile.originalText || BLANKSTRING),
|
|
y: labelTopY,
|
|
'text-anchor': rotateValues ? POSITION_MIDDLE : textAlign,
|
|
'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_TOP,
|
|
'visibility': visibleStr,
|
|
direction: conf.textDirection,
|
|
fill: style.color,
|
|
transform: paper.getSuggestiveRotation(rotateValues, crispyX + columnWidth / 2, labelTopY),
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
};
|
|
|
|
if (config.showMaxValues) {
|
|
if (!graphic.label[3]) {
|
|
graphic.label[3] =
|
|
paper.text(attr, dataLabelContainer);
|
|
// .hover(rolloverResponseSetter(plotItem, set.hoverEffects),
|
|
// rolloutResponseSetter(plotItem, hoverOutEffects))
|
|
}
|
|
else {
|
|
graphic.label[3].show();
|
|
x = crispyX + columnWidth / 2;
|
|
y = lastDataSetYpos || labelTopY;
|
|
|
|
graphic.label[3].attr({
|
|
text: numberFormatter.dataLabels(config.max),
|
|
title: (upperQuartile.originalText || BLANKSTRING),
|
|
'text-anchor': rotateValues ? POSITION_MIDDLE : textAlign,
|
|
'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_TOP,
|
|
'visibility': visibleStr,
|
|
direction: conf.textDirection,
|
|
fill: style.color,
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
});
|
|
|
|
graphic.label[3].animateWith(dummyObj, animObj, {
|
|
x: x,
|
|
y: y,
|
|
transform: paper.getSuggestiveRotation(rotateValues, x, y)
|
|
}, animationDuration, animType, (animFlag && animCallBack));
|
|
}
|
|
graphic.label[3]
|
|
.data(GROUPID, groupId);
|
|
}
|
|
else {
|
|
graphic.label[3] && graphic.label[3].hide() && graphic.label[3].attr({'text-bound': []});
|
|
}
|
|
|
|
crispX = mathRound(xPos) + lowerBoxBorder.borderWidth % 2 *
|
|
0.5;
|
|
crispX2 = mathRound(xPos + columnWidth) +
|
|
lowerBoxBorder.borderWidth % 2 * 0.5;
|
|
crispY = mathRound(yMedPos + lowerBoxH) +
|
|
lowerQuartile.borderWidth % 2 * 0.5;
|
|
|
|
lowerBoxYPos = lastDataSetYpos || yMedPos;
|
|
lowerBoxHeight = mathMax(mathMin(lastDataSetHeight, (crispY - yMedPos)), 0);
|
|
|
|
lowerBoxEndPos = (lowerBoxYPos + lowerBoxHeight);
|
|
|
|
// draw lower element
|
|
attr = {
|
|
x: crispX,
|
|
y: lowerBoxYPos,
|
|
width: mathMax(columnWidth, 0),
|
|
height: lowerBoxHeight,
|
|
r: 0
|
|
};
|
|
|
|
lowerBoxElem = dataObj.graphics.lowerBoxElem;
|
|
|
|
if (!lowerBoxElem) {
|
|
lowerBoxElem = dataObj.graphics.lowerBoxElem = paper.rect(attr, lowerBoxContainer);
|
|
newlowerBoxElem = true;
|
|
}
|
|
else
|
|
{
|
|
lowerBoxElem.animateWith(dummyObj, animObj, attr, animationDuration,
|
|
animType, (animFlag && animCallBack));
|
|
}
|
|
|
|
lowerBoxElem.attr(hoverOutEffects.lowerBox)
|
|
.shadow({opacity : showShadow ? conf.lowerBoxAlpha / 100 : 0}, shadowContainer);
|
|
|
|
// draw lowerBoxBorder element
|
|
attr = {
|
|
path: [M, crispX, lastDataSetYpos || yMedPos, V, lastDataSetYpos || yMedPos +
|
|
lowerBoxH, M, crispX2, lastDataSetYpos || yMedPos, V,
|
|
lastDataSetYpos || yMedPos + lowerBoxH]
|
|
};
|
|
|
|
lowerBoxBorderEle = dataObj.graphics.lowerBoxBorderEle;
|
|
|
|
if (!lowerBoxBorderEle) {
|
|
lowerBoxBorderEle = dataObj.graphics.lowerBoxBorderEle = paper.path(attr, lowerBoxContainer);
|
|
newlowerBoxBorderEle = true;
|
|
}
|
|
else
|
|
{
|
|
lowerBoxBorderEle.animateWith(dummyObj, animObj, attr, animationDuration,
|
|
animType, (animFlag && animCallBack));
|
|
}
|
|
|
|
lowerBoxBorderEle.attr(hoverOutEffects.lowerBoxBorder);
|
|
|
|
// draw lowerQuartileBorder element
|
|
crispY = mathRound(yMedPos + lowerBoxH) +
|
|
lowerQuartile.borderWidth % 2 * 0.5;
|
|
|
|
attr = {
|
|
path: [M, crispX, lastDataSetYpos || crispY, H, (crispX + columnWidth)]
|
|
};
|
|
|
|
lowerQuartileEle = dataObj.graphics.lowerQuartileEle;
|
|
|
|
if (!lowerQuartileEle) {
|
|
lowerQuartileEle = dataObj.graphics.lowerQuartileEle = paper.path(attr, lowerBoxContainer);
|
|
newlowerQuartileEle = true;
|
|
}
|
|
else
|
|
{
|
|
lowerQuartileEle.animateWith(dummyObj, animObj, attr, animationDuration,
|
|
animType, (animFlag && animCallBack));
|
|
}
|
|
|
|
lowerQuartileEle.attr(hoverOutEffects.lowerQuartile);
|
|
|
|
errorStartPos = crispY;
|
|
errorBarWidth = columnWidth * (conf.whiskerslimitswidthratio / 100);
|
|
halfErrorBarW = errorBarWidth / 2;
|
|
|
|
// Vertical Error drawing
|
|
errorValPos = yAxis.getAxisPosition(config.min);
|
|
crispyY = errorValPos;
|
|
crispyX = crispX;
|
|
|
|
crispyY = mathRound(errorValPos) +
|
|
(config.lowerWhiskerThickness % 2 / 2);
|
|
crispyX = mathRound(crispyX + (columnWidth / 2)) +
|
|
(config.lowerWhiskerThickness % 2 / 2);
|
|
|
|
errorPath = [
|
|
M, crispyX, lastDataSetYpos || errorStartPos,
|
|
V, mathMax(lastDataSetYpos || crispyY, lowerBoxEndPos),
|
|
M, crispyX - halfErrorBarW, mathMax(lastDataSetYpos || crispyY, lowerBoxEndPos),
|
|
H, (crispyX + halfErrorBarW)
|
|
];
|
|
|
|
lowerWhiskerEle = dataObj.graphics.lowerWhiskerEle;
|
|
|
|
smartLabel.setStyle(style);
|
|
smartText = smartLabel.getOriSize(numberFormatter.dataLabels(config.min));
|
|
lineHeight = (rotateValues ? smartText.width :
|
|
smartText.height);
|
|
|
|
labelBottomY = errorValPos + (config.lowerWhiskerThickness * 0.5) + valuePadding;
|
|
|
|
if ((labelBottomY + lineHeight) > chartConfig.canvasBottom) {
|
|
labelBottomY = chartConfig.canvasBottom - lineHeight;
|
|
}
|
|
|
|
attr = {
|
|
text: numberFormatter.dataLabels(config.min),
|
|
x: crispyX,
|
|
title: (upperQuartile.originalText || BLANKSTRING),
|
|
y: labelBottomY,
|
|
'text-anchor': rotateValues ? POSITION_END : textAlign,
|
|
'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_TOP,
|
|
'visibility': visibleStr,
|
|
direction: conf.textDirection,
|
|
fill: style.color,
|
|
transform: paper.getSuggestiveRotation(rotateValues, crispyX, labelBottomY),
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
};
|
|
|
|
if (config.showMinValues) {
|
|
if (!graphic.label[4]) {
|
|
graphic.label[4] =
|
|
paper.text(attr, dataLabelContainer);
|
|
// .hover(rolloverResponseSetter(plotItem, set.hoverEffects),
|
|
// rolloutResponseSetter(plotItem, hoverOutEffects))
|
|
}
|
|
else {
|
|
graphic.label[4].show();
|
|
x = crispyX;
|
|
y = lastDataSetYpos || labelBottomY;
|
|
|
|
graphic.label[4].animateWith(dummyObj, animObj, {
|
|
x: x,
|
|
y: y,
|
|
transform: paper.getSuggestiveRotation(rotateValues, x, y)
|
|
}, animationDuration, animType, (animFlag && animCallBack));
|
|
|
|
graphic.label[4].attr({
|
|
text: numberFormatter.dataLabels(config.min),
|
|
title: (upperQuartile.originalText || BLANKSTRING),
|
|
'text-anchor': rotateValues ? POSITION_END : textAlign,
|
|
'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_TOP,
|
|
'visibility': visibleStr,
|
|
direction: conf.textDirection,
|
|
fill: style.color,
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
});
|
|
}
|
|
graphic.label[4]
|
|
.data(GROUPID, groupId);
|
|
}
|
|
else {
|
|
graphic.label[4] && graphic.label[4].hide() && graphic.label[4].attr({'text-bound': []});
|
|
}
|
|
|
|
attr = {
|
|
path: errorPath,
|
|
// In case of tooltip disabled this element should act as the hot element.
|
|
ishot: !showTooltip,
|
|
'stroke-width': config.lowerWhiskerThickness,
|
|
'cursor': setLink ? POINTER : BLANKSTRING,
|
|
'stroke-linecap': ROUND
|
|
};
|
|
|
|
if (!lowerWhiskerEle) {
|
|
lowerWhiskerEle = dataObj.graphics.lowerWhiskerEle =
|
|
paper.path(attr, lowerWhiskerContainer);
|
|
newlowerWhiskerEle = true;
|
|
}
|
|
else
|
|
{
|
|
lowerWhiskerEle.animateWith(dummyObj, animObj, attr, animationDuration,
|
|
animType, (animFlag && animCallBack));
|
|
}
|
|
|
|
lowerWhiskerEle.attr({
|
|
stroke: config.lowerWhiskerColor
|
|
});
|
|
|
|
lowerWhiskerEle.shadow({opacity : config.lowerWhiskerShadowOpacity}, shadowContainer);
|
|
|
|
// draw medianBorder
|
|
crispY = mathRound(yMedPos) + median.borderWidth % 2 * 0.5;
|
|
|
|
attr = {
|
|
path: [M, crispX, lastDataSetYpos || crispY, H, (crispX + columnWidth)]
|
|
};
|
|
|
|
midLineElem = dataObj.graphics.midLineElem;
|
|
|
|
if (!midLineElem) {
|
|
midLineElem = dataObj.graphics.midLineElem = paper.path(attr, medianContainer);
|
|
newmidLineElem = true;
|
|
}
|
|
else
|
|
{
|
|
midLineElem.animateWith(dummyObj, animObj, attr, animationDuration,
|
|
animType, (animFlag && animCallBack));
|
|
}
|
|
|
|
midLineElem.attr(hoverOutEffects.median);
|
|
|
|
hoverInAttr = {
|
|
upperBoxElem: config.setUpperBoxRolloverAttr,
|
|
lowerBoxElem: config.setLowerBoxRolloverAttr,
|
|
upperBoxBorderEle: config.setUpperBoxBorderRolloverAttr,
|
|
lowerBoxBorderEle: config.setLowerBoxBorderRolloverAttr,
|
|
upperQuartileEle: config.setUpperQuartileRolloverAttr,
|
|
lowerQuartileEle: config.setLowerQuartileRolloverAttr,
|
|
midLineElem: config.setMedianRolloverAttr
|
|
|
|
};
|
|
|
|
hoverOutAttr = {
|
|
upperBoxElem: config.setUpperBoxRolloutAttr,
|
|
lowerBoxElem: config.setLowerBoxRolloutAttr,
|
|
upperBoxBorderEle: config.setUpperBoxBorderRolloutAttr,
|
|
lowerBoxBorderEle: config.setLowerBoxBorderRolloutAttr,
|
|
upperQuartileEle: config.setUpperQuartileRolloutAttr,
|
|
lowerQuartileEle: config.setLowerQuartileRolloutAttr,
|
|
midLineElem: config.setMedianRolloutAttr
|
|
};
|
|
|
|
upperBoxElem.data(GROUPID, groupId)
|
|
.data(EVENTARGS, eventArgs)
|
|
.data(showHoverEffectStr, showHoverEffect)
|
|
.data(SETROLLOVERATTR, hoverInAttr)
|
|
.data(SETROLLOUTATTR, hoverOutAttr);
|
|
|
|
if (newupperBoxElem) {
|
|
upperBoxElem
|
|
.click(clickFunc)
|
|
.hover(
|
|
rolloverResponseSetter(dataObj.graphics),
|
|
rolloutResponseSetter(dataObj.graphics)
|
|
);
|
|
}
|
|
|
|
lowerBoxElem.data(GROUPID, groupId)
|
|
.data(EVENTARGS, eventArgs)
|
|
.data(showHoverEffectStr, showHoverEffect)
|
|
.data(SETROLLOVERATTR, hoverInAttr)
|
|
.data(SETROLLOUTATTR, hoverOutAttr);
|
|
|
|
|
|
if (newlowerBoxElem) {
|
|
lowerBoxElem
|
|
.click(clickFunc)
|
|
.hover(
|
|
rolloverResponseSetter(dataObj.graphics),
|
|
rolloutResponseSetter(dataObj.graphics)
|
|
);
|
|
}
|
|
|
|
upperBoxBorderEle.data(GROUPID, groupId)
|
|
.data(EVENTARGS, eventArgs)
|
|
.data(showHoverEffectStr, showHoverEffect)
|
|
.data(SETROLLOVERATTR, hoverInAttr)
|
|
.data(SETROLLOUTATTR, hoverOutAttr);
|
|
|
|
if (newupperBoxBorderEle) {
|
|
upperBoxBorderEle
|
|
.click(clickFunc)
|
|
.hover(
|
|
rolloverResponseSetter(dataObj.graphics),
|
|
rolloutResponseSetter(dataObj.graphics)
|
|
);
|
|
}
|
|
|
|
lowerBoxBorderEle.data(GROUPID, groupId)
|
|
.data(EVENTARGS, eventArgs)
|
|
.data(showHoverEffectStr, showHoverEffect)
|
|
.data(SETROLLOVERATTR, hoverInAttr)
|
|
.data(SETROLLOUTATTR, hoverOutAttr);
|
|
|
|
if (newlowerBoxBorderEle) {
|
|
lowerBoxBorderEle
|
|
.click(clickFunc)
|
|
.hover(
|
|
rolloverResponseSetter(dataObj.graphics),
|
|
rolloutResponseSetter(dataObj.graphics)
|
|
);
|
|
}
|
|
|
|
upperQuartileEle.data(GROUPID, groupId)
|
|
.data(EVENTARGS, eventArgs)
|
|
.data(showHoverEffectStr, showHoverEffect)
|
|
.data(SETROLLOVERATTR, hoverInAttr)
|
|
.data(SETROLLOUTATTR, hoverOutAttr);
|
|
|
|
if (newupperQuartileEle) {
|
|
upperQuartileEle
|
|
.click(clickFunc)
|
|
.hover(
|
|
rolloverResponseSetter(dataObj.graphics),
|
|
rolloutResponseSetter(dataObj.graphics)
|
|
);
|
|
}
|
|
|
|
lowerQuartileEle.data(GROUPID, groupId)
|
|
.data(EVENTARGS, eventArgs)
|
|
.data(showHoverEffectStr, showHoverEffect)
|
|
.data(SETROLLOVERATTR, hoverInAttr)
|
|
.data(SETROLLOUTATTR, hoverOutAttr);
|
|
|
|
if (newlowerQuartileEle) {
|
|
lowerQuartileEle
|
|
.click(clickFunc)
|
|
.hover(
|
|
rolloverResponseSetter(dataObj.graphics),
|
|
rolloutResponseSetter(dataObj.graphics)
|
|
);
|
|
}
|
|
|
|
midLineElem.data(GROUPID, groupId)
|
|
.data(EVENTARGS, eventArgs)
|
|
.data(showHoverEffectStr, showHoverEffect)
|
|
.data(SETROLLOVERATTR, hoverInAttr)
|
|
.data(SETROLLOUTATTR, hoverOutAttr);
|
|
|
|
if (newmidLineElem) {
|
|
midLineElem
|
|
.click(clickFunc)
|
|
.hover(
|
|
rolloverResponseSetter(dataObj.graphics),
|
|
rolloutResponseSetter(dataObj.graphics)
|
|
);
|
|
}
|
|
|
|
upperWhiskerEle.data(GROUPID, groupId)
|
|
.data(EVENTARGS, eventArgs)
|
|
.data(showHoverEffectStr, showHoverEffect)
|
|
.data(SETROLLOVERATTR, hoverInAttr)
|
|
.data(SETROLLOUTATTR, hoverOutAttr);
|
|
|
|
if (newupperWhiskerEle) {
|
|
upperWhiskerEle
|
|
.click(clickFunc)
|
|
.hover(
|
|
rolloverResponseSetter(dataObj.graphics),
|
|
rolloutResponseSetter(dataObj.graphics)
|
|
);
|
|
}
|
|
|
|
lowerWhiskerEle.data(GROUPID, groupId)
|
|
.data(EVENTARGS, eventArgs)
|
|
.data(showHoverEffectStr, showHoverEffect)
|
|
.data(SETROLLOVERATTR, hoverInAttr)
|
|
.data(SETROLLOUTATTR, hoverOutAttr);
|
|
|
|
if (newlowerWhiskerEle) {
|
|
lowerWhiskerEle
|
|
.click(clickFunc)
|
|
.hover(
|
|
rolloverResponseSetter(dataObj.graphics),
|
|
rolloutResponseSetter(dataObj.graphics)
|
|
);
|
|
}
|
|
|
|
textAlign = rotateValues ? POSITION_LEFT :
|
|
POSITION_MIDDLE;
|
|
|
|
attr = {
|
|
text: upperQuartile.displayValue,
|
|
x: xPos + (columnWidth / 2),
|
|
title: (upperQuartile.originalText || BLANKSTRING),
|
|
y: yTopPos - valuePadding,
|
|
'text-anchor': rotateValues ? POSITION_START : textAlign,
|
|
'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_BOTTOM,
|
|
'visibility': visibleStr,
|
|
direction: conf.textDirection,
|
|
fill: style.color,
|
|
transform: paper.getSuggestiveRotation(rotateValues, xPos + (columnWidth / 2),
|
|
yTopPos - valuePadding),
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
};
|
|
|
|
if (defined(upperQuartile.displayValue) &&
|
|
upperQuartile.displayValue !== BLANK && config.showQ3Values) {
|
|
if (!graphic.label[0]) {
|
|
graphic.label[0] =
|
|
paper.text(attr, dataLabelContainer);
|
|
// .hover(rolloverResponseSetter(plotItem, set.hoverEffects),
|
|
// rolloutResponseSetter(plotItem, hoverOutEffects))
|
|
}
|
|
else {
|
|
graphic.label[0].show();
|
|
x = xPos + (columnWidth / 2);
|
|
y = lastDataSetYpos || yTopPos - valuePadding;
|
|
graphic.label[0].animateWith(dummyObj, animObj, {
|
|
x: x,
|
|
y: y,
|
|
transform: paper.getSuggestiveRotation(rotateValues, x, y)
|
|
}, animationDuration, animType, (animFlag && animCallBack));
|
|
|
|
graphic.label[0].attr({
|
|
text: upperQuartile.displayValue,
|
|
title: (upperQuartile.originalText || BLANKSTRING),
|
|
'text-anchor': rotateValues ? POSITION_START : textAlign,
|
|
'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_BOTTOM,
|
|
'visibility': visibleStr,
|
|
direction: conf.textDirection,
|
|
fill: style.color,
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
});
|
|
}
|
|
graphic.label[0]
|
|
.data(GROUPID, groupId);
|
|
}
|
|
else {
|
|
graphic.label[0] && graphic.label[0].hide() && graphic.label[0].attr({'text-bound': []});
|
|
}
|
|
|
|
attr = {
|
|
text: median.displayValue,
|
|
x: crispX + columnWidth/2,
|
|
y: yMedPos - valuePadding,
|
|
title: (median.originalText || BLANKSTRING),
|
|
'text-anchor': rotateValues ? POSITION_START : textAlign,
|
|
'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_BOTTOM,
|
|
'visibility': visibleStr,
|
|
direction: conf.textDirection,
|
|
fill: style.color,
|
|
transform: paper.getSuggestiveRotation(rotateValues, crispX + columnWidth/2,
|
|
yMedPos - valuePadding),
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
};
|
|
|
|
if (defined(median.displayValue) && median.displayValue !== BLANK && config.showMedianValues) {
|
|
if (!graphic.label[1]) {
|
|
graphic.label[1] =
|
|
paper.text(attr, dataLabelContainer);
|
|
// .hover(rolloverResponseSetter(plotItem, set.hoverEffects),
|
|
// rolloutResponseSetter(plotItem, hoverOutEffects))
|
|
}
|
|
else {
|
|
graphic.label[1].show();
|
|
|
|
x = crispX + columnWidth/2;
|
|
y = lastDataSetYpos || yMedPos - valuePadding;
|
|
|
|
graphic.label[1].animateWith(dummyObj, animObj, {
|
|
x: x,
|
|
y: y,
|
|
transform: paper.getSuggestiveRotation(rotateValues, x, y)
|
|
}, animationDuration, animType, (animFlag && animCallBack));
|
|
|
|
graphic.label[1].attr({
|
|
text: median.displayValue,
|
|
title: (median.originalText || BLANKSTRING),
|
|
'text-anchor': rotateValues ? POSITION_START : textAlign,
|
|
'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_BOTTOM,
|
|
'visibility': visibleStr,
|
|
direction: conf.textDirection,
|
|
fill: style.color,
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
});
|
|
|
|
}
|
|
graphic.label[1]
|
|
.data(GROUPID, groupId);
|
|
}
|
|
else {
|
|
graphic.label[1] && graphic.label[1].hide() && graphic.label[1].attr({'text-bound': []});
|
|
}
|
|
|
|
attr = {
|
|
text: lowerQuartile.displayValue,
|
|
x: xPos + columnWidth / 2,
|
|
y: yBottomPos + valuePadding,
|
|
title: (lowerQuartile.originalText || BLANKSTRING),
|
|
'text-anchor': rotateValues ? POSITION_START : textAlign,
|
|
'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_TOP,
|
|
'visibility': visibleStr,
|
|
direction: conf.textDirection,
|
|
fill: style.color,
|
|
transform: paper.getSuggestiveRotation(rotateValues, xPos + columnWidth / 2,
|
|
yBottomPos + valuePadding),
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
};
|
|
|
|
if (defined(lowerQuartile.displayValue) &&
|
|
lowerQuartile.displayValue !== BLANK && config.showQ1Values) {
|
|
if (!graphic.label[2]) {
|
|
graphic.label[2] =
|
|
paper.text(attr, dataLabelContainer);
|
|
// .hover(rolloverResponseSetter(plotItem, set.hoverEffects),
|
|
// rolloutResponseSetter(plotItem, hoverOutEffects))
|
|
}
|
|
else {
|
|
graphic.label[2].show();
|
|
|
|
x = xPos + columnWidth / 2;
|
|
y = lastDataSetYpos || yBottomPos + valuePadding;
|
|
|
|
graphic.label[2].animateWith(dummyObj, animObj, {
|
|
x: x,
|
|
y: y,
|
|
transform: paper.getSuggestiveRotation(rotateValues, x, y)
|
|
}, animationDuration, animType, (animFlag && animCallBack));
|
|
|
|
graphic.label[2].attr({
|
|
text: lowerQuartile.displayValue,
|
|
title: (lowerQuartile.originalText || BLANKSTRING),
|
|
'text-anchor': rotateValues ? POSITION_START : textAlign,
|
|
'vertical-align': rotateValues ? POSITION_MIDDLE : POSITION_TOP,
|
|
'visibility': visibleStr,
|
|
direction: conf.textDirection,
|
|
fill: style.color,
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
});
|
|
}
|
|
graphic.label[2]
|
|
.data(GROUPID, groupId);
|
|
}
|
|
else {
|
|
graphic.label[2] && graphic.label[2].hide() && graphic.label[2].attr({'text-bound': []});
|
|
}
|
|
|
|
animFlag && animCallBack();
|
|
|
|
if (showTooltip) {
|
|
upperBoxElem.tooltip(toolText);
|
|
lowerBoxElem.tooltip(toolText);
|
|
upperBoxBorderEle.tooltip(toolText);
|
|
lowerBoxBorderEle.tooltip(toolText);
|
|
upperQuartileEle.tooltip(toolText);
|
|
lowerQuartileEle.tooltip(toolText);
|
|
midLineElem.tooltip(toolText);
|
|
upperWhiskerEle.tooltip(toolText);
|
|
lowerWhiskerEle.tooltip(toolText);
|
|
}
|
|
else {
|
|
upperBoxElem.tooltip(false);
|
|
lowerBoxElem.tooltip(false);
|
|
upperBoxBorderEle.tooltip(false);
|
|
lowerBoxBorderEle.tooltip(false);
|
|
upperQuartileEle.tooltip(false);
|
|
lowerQuartileEle.tooltip(false);
|
|
midLineElem.tooltip(false);
|
|
upperWhiskerEle.tooltip(false);
|
|
lowerWhiskerEle.tooltip(false);
|
|
}
|
|
|
|
xPos += (columnWidth / 2);
|
|
dataSet.components.mean.components.data[i].config.xPos = xPos;
|
|
dataSet.components.sd.components.data[i].config.xPos = xPos;
|
|
dataSet.components.qd.components.data[i].config.xPos = xPos;
|
|
dataSet.components.md.components.data[i].config.xPos = xPos;
|
|
|
|
for (j = 0; j < conf.maxNumberOfOutliers; j++) {
|
|
dataSet.components.outliers[j].components.data[i].config.xPos = xPos;
|
|
}
|
|
|
|
}
|
|
|
|
dataSet.flag = true;
|
|
removeDataArrLen && dataSet.remove();
|
|
},
|
|
|
|
// Function to remove a data from a dataset during real time update.
|
|
remove : function () {
|
|
var dataSet = this,
|
|
components = dataSet.components,
|
|
removeDataArr = components.removeDataArr,
|
|
pool = components.pool || (components.pool = {
|
|
element :[],
|
|
hotElement : [],
|
|
label : []
|
|
}),
|
|
len = removeDataArr.length,
|
|
removeData,
|
|
maxminFlag = dataSet.maxminFlag,
|
|
ele,
|
|
graphics,
|
|
i,
|
|
innerLen,
|
|
j;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
removeData = removeDataArr[0];
|
|
removeDataArr.splice(0,1);
|
|
// In case of non existing data plot continue;
|
|
if (!removeData || !removeData.graphics) {
|
|
continue;
|
|
}
|
|
|
|
graphics = removeData.graphics;
|
|
for (ele in graphics) {
|
|
if (ele !== LABEL) {
|
|
graphics[ele].shadow({opacity: 0});
|
|
graphics[ele].hide();
|
|
}
|
|
else {
|
|
innerLen = graphics[ele].length;
|
|
for (j = 0; j < innerLen; j++) {
|
|
if (graphics[ele][j]) {
|
|
graphics[ele][j].shadow({opacity: 0});
|
|
graphics[ele][j].hide();
|
|
graphics[ele][j].attr({'text-bound': []});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Storing the graphic elements for reuse.
|
|
removeData.graphics.element && (pool.element = pool.element.concat(removeData.graphics.element));
|
|
removeData.graphics.hotElement && (pool.hotElement = pool.hotElement.concat(removeData.graphics.
|
|
hotElement));
|
|
removeData.graphics.label && (pool.label = pool.label.concat(removeData.graphics.label));
|
|
}
|
|
components.pool = pool;
|
|
maxminFlag && dataSet.setMaxMin();
|
|
},
|
|
|
|
// Function to remove a data with a given index.
|
|
removeData : function (index, stretch, draw) {
|
|
var dataSet = this,
|
|
components = dataSet.components,
|
|
dataStore = components.data,
|
|
removeDataArr = components.removeDataArr || (components.removeDataArr = []),
|
|
meanArr = components.mean.components.removeDataArr ||
|
|
(components.mean.components.removeDataArr = []),
|
|
sdArr = components.sd.components.removeDataArr ||
|
|
(components.sd.components.removeDataArr = []),
|
|
mdArr = components.md.components.removeDataArr ||
|
|
(components.md.components.removeDataArr = []),
|
|
qdArr = components.qd.components.removeDataArr ||
|
|
(components.qd.components.removeDataArr = []),
|
|
outliersArr,
|
|
conf = dataSet.config,
|
|
i,
|
|
config,
|
|
groupManager = dataSet.groupManager,
|
|
len,
|
|
maxminFlag = dataSet.maxminFlag;
|
|
|
|
stretch = stretch || 1;
|
|
index = index || 0;
|
|
|
|
// Storing the direction of input data for the type of animation to be done during remove.
|
|
if ((index + stretch)=== dataStore.length ) {
|
|
dataSet.endPosition = true;
|
|
}
|
|
else if (index === 0 || index === UNDEFINED) {
|
|
dataSet.endPosition = false;
|
|
}
|
|
|
|
components.removeDataArr = removeDataArr = removeDataArr.concat(dataStore.splice(index, stretch));
|
|
|
|
components.mean.components.removeDataArr =
|
|
meanArr.concat(components.mean.components.data.splice(index, stretch));
|
|
|
|
components.sd.components.removeDataArr =
|
|
sdArr.concat(components.sd.components.data.splice(index, stretch));
|
|
|
|
components.md.components.removeDataArr =
|
|
mdArr.concat(components.md.components.data.splice(index, stretch));
|
|
|
|
components.qd.components.removeDataArr =
|
|
qdArr.concat(components.qd.components.data.splice(index, stretch));
|
|
|
|
len = components.outliers.length;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
outliersArr = components.outliers[i].components.removeDataArr ||
|
|
(components.outliers[i].components.removeDataArr = []);
|
|
|
|
components.outliers[i].components.removeDataArr =
|
|
outliersArr.concat(components.outliers[i].components.data.splice(index, stretch));
|
|
}
|
|
|
|
groupManager && groupManager.removeSumLabels &&
|
|
groupManager.removeSumLabels(index, stretch, dataSet.positionIndex);
|
|
|
|
len = removeDataArr.length;
|
|
for (i = 0; i < len; i++) {
|
|
if (!removeDataArr[i]) {
|
|
continue;
|
|
}
|
|
config = removeDataArr[i].config;
|
|
if (config.setValue === conf.maxValue || config.setValue === conf.minValue) {
|
|
maxminFlag = dataSet.maxminFlag = true;
|
|
}
|
|
if (maxminFlag) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
maxminFlag && dataSet.setMaxMin();
|
|
draw && dataSet.draw();
|
|
},
|
|
|
|
_addLegendSubDS: function (dataSet) {
|
|
var dataset = dataSet,
|
|
chart = dataset.chart,
|
|
config,
|
|
conf = dataset.config,
|
|
thisConf = this.config,
|
|
upperBoxColor = thisConf.upperBoxColor,
|
|
legend = chart.components.legend,
|
|
color = conf.anchorBgColor;
|
|
|
|
config = {
|
|
anchorSide: conf.anchorSides,
|
|
legendBackgroundColor: upperBoxColor,
|
|
fillColor : convertColor(color),
|
|
strokeColor: convertColor(COLOR_000000),
|
|
enabled: this.config.includeInLegend,
|
|
label : this.JSONData.seriesname && getFirstValue(dataset.name),
|
|
customLegendIcon: false,
|
|
spoke: conf.dip ? 1 : 0,
|
|
drawLine: conf.drawLine ? true : false,
|
|
lineColor: toRaphaelColor({
|
|
color: color,
|
|
alpha: HUNDREDSTRING
|
|
})
|
|
};
|
|
dataset.itemId = legend.addItems(dataset, dataset.legendInteractivity, config);
|
|
},
|
|
|
|
_addLegendOutliers: function (Outliers) {
|
|
var dataset = this,
|
|
JSONData = dataset.JSONData,
|
|
chart = dataset.chart,
|
|
chartAttr = chart.jsonData.chart,
|
|
strokeColor,
|
|
fillColor,
|
|
config,
|
|
conf = dataset.config,
|
|
upperBoxColor = conf.upperBoxColor,
|
|
legend = dataset.chart.components.legend,
|
|
color = pluck(JSONData.outliericoncolor, chartAttr.outliericoncolor, COLOR_000000);
|
|
strokeColor = COLOR_000000;
|
|
|
|
fillColor = {
|
|
FCcolor: {
|
|
color: color,
|
|
angle: 0,
|
|
ratio: ZEROSTRING,
|
|
alpha: HUNDREDSTRING
|
|
}
|
|
};
|
|
|
|
config = {
|
|
anchorSide: pluckNumber(JSONData.outliericonsides, chartAttr.outliericonsides, 3),
|
|
fillColor : convertColor(color),
|
|
legendBackgroundColor: upperBoxColor,
|
|
strokeColor: convertColor(COLOR_000000),
|
|
enabled: conf.includeInLegend,
|
|
label : dataset.JSONData.seriesname && OUTLIERS_STR,
|
|
customLegendIcon: false,
|
|
spoke: Outliers[0].config.dip ? 1 : 0,
|
|
drawLine: false,
|
|
datasetObj: Outliers[0]
|
|
};
|
|
Outliers.visible = pluckNumber(dataset.JSONData.visible,
|
|
!Number(dataset.JSONData.initiallyhidden), 1) === 1;
|
|
// (Outliers.visible === UNDEFINED) && (Outliers.visible = true);
|
|
Outliers[0] &&
|
|
(Outliers[0].itemId = legend.addItems(Outliers, dataset.legendInteractivityOutliers, config));
|
|
},
|
|
|
|
legendInteractivityOutliers : function (dataSet, legendItem) {
|
|
var legend = this,
|
|
legendConfig = legend.config,
|
|
config = legendItem.config,
|
|
legendGraphics = legendItem.graphics,
|
|
itemHiddenStyle = legendConfig.itemHiddenStyle,
|
|
hiddenColor = itemHiddenStyle.color,
|
|
itemStyle = legendConfig.itemStyle,
|
|
itemTextColor = itemStyle.color,
|
|
color = config.fillColor,
|
|
stroke = config.strokeColor,
|
|
i,
|
|
visible;
|
|
|
|
dataSet.visible = dataSet.visible ? false : true;
|
|
|
|
for (i = 0; i < dataSet.length; i++) {
|
|
|
|
visible = dataSet[i].visible;
|
|
|
|
if (visible) {
|
|
dataSet[i].visible = false;
|
|
}
|
|
else {
|
|
dataSet[i].visible = true;
|
|
}
|
|
|
|
dataSet[i].draw();
|
|
|
|
if (!visible) {
|
|
legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
|
|
fill: color,
|
|
'stroke': stroke
|
|
});
|
|
legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
|
|
fill: itemTextColor
|
|
});
|
|
legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
|
|
'stroke': color
|
|
});
|
|
} else {
|
|
dataSet.visible = false;
|
|
legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
|
|
fill: hiddenColor,
|
|
'stroke': hiddenColor
|
|
});
|
|
legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
|
|
fill: hiddenColor
|
|
});
|
|
legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
|
|
'stroke': hiddenColor
|
|
});
|
|
}
|
|
}
|
|
},
|
|
|
|
_addLegend: function () {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
strokeColor,
|
|
fillColor,
|
|
config,
|
|
conf = dataset.config,
|
|
legend = chart.components.legend,
|
|
upperBoxColor = conf.upperBoxColor,
|
|
lowerBoxColor = conf.lowerBoxColor;
|
|
|
|
strokeColor = COLOR_000000;
|
|
|
|
fillColor = {
|
|
FCcolor: {
|
|
color: upperBoxColor + COMMA + lowerBoxColor,
|
|
angle: 90,
|
|
ratio: '50, 0',
|
|
alpha: '100, 100'
|
|
}
|
|
};
|
|
|
|
config = {
|
|
fillColor : toRaphaelColor(fillColor),
|
|
legendBackgroundColor: upperBoxColor,
|
|
strokeColor: toRaphaelColor(strokeColor),
|
|
rawFillColor: upperBoxColor,
|
|
rawStrokeColor: strokeColor,
|
|
enabled: conf.includeInLegend,
|
|
label : getFirstValue(dataset.JSONData.seriesname),
|
|
index: dataset.index,
|
|
mainDS: true
|
|
};
|
|
dataset.itemId = legend.addItems(dataset, dataset.legendInteractivity, config);
|
|
},
|
|
|
|
legendInteractivity : function (dataSet, legendItem) {
|
|
var legend = this,
|
|
legendConfig = legend.config,
|
|
visible = dataSet.visible,
|
|
config = legendItem.config,
|
|
legendGraphics = legendItem.graphics,
|
|
itemHiddenStyle = legendConfig.itemHiddenStyle,
|
|
hiddenColor = itemHiddenStyle.color,
|
|
itemStyle = legendConfig.itemStyle,
|
|
itemTextColor = itemStyle.color,
|
|
color = config.fillColor,
|
|
stroke = config.strokeColor,
|
|
legendItemIndex = legendItem.index,
|
|
subDSNumber = dataSet.subDS,
|
|
legendItems,
|
|
i;
|
|
|
|
visible ? dataSet.hide() : dataSet.show();
|
|
if (!visible) {
|
|
legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
|
|
fill: color,
|
|
'stroke': stroke
|
|
});
|
|
legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
|
|
fill: itemTextColor
|
|
});
|
|
legendGraphics.legendItemLine && legendGraphics.legendItemLine.attr({
|
|
'stroke': color
|
|
});
|
|
|
|
for (i = legendItemIndex + 1; i <= (legendItemIndex + subDSNumber); i++) {
|
|
|
|
legendItems = legend.components.items[i];
|
|
legendGraphics = legendItems && legendItems.graphics;
|
|
|
|
if (!legendGraphics) {
|
|
continue;
|
|
}
|
|
|
|
config = legendItems.config;
|
|
itemTextColor = itemStyle.color;
|
|
color = config.fillColor;
|
|
stroke = config.strokeColor;
|
|
|
|
legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
|
|
fill: color,
|
|
'stroke': stroke
|
|
});
|
|
legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
|
|
fill: itemTextColor
|
|
});
|
|
legendGraphics.legendItemLine && legendGraphics.legendItemLine.attr({
|
|
'stroke': color
|
|
});
|
|
}
|
|
|
|
} else {
|
|
legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
|
|
fill: hiddenColor,
|
|
'stroke': hiddenColor
|
|
});
|
|
legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
|
|
fill: hiddenColor
|
|
});
|
|
legendGraphics.legendItemLine && legendGraphics.legendItemLine.attr({
|
|
'stroke': hiddenColor
|
|
});
|
|
|
|
|
|
for (i = legendItemIndex + 1; i <= (legendItemIndex + subDSNumber); i++) {
|
|
|
|
legendItems = legend.components.items[i];
|
|
legendGraphics = legendItems && legendItems.graphics;
|
|
|
|
if (!legendGraphics) {
|
|
continue;
|
|
}
|
|
|
|
legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
|
|
fill: hiddenColor,
|
|
'stroke': hiddenColor
|
|
});
|
|
legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
|
|
fill: hiddenColor
|
|
});
|
|
legendGraphics.legendItemLine && legendGraphics.legendItemLine.attr({
|
|
'stroke': hiddenColor
|
|
});
|
|
}
|
|
}
|
|
},
|
|
|
|
/*
|
|
* This function is used to make a dataset visible when clicked on its respective legend.
|
|
* This fucntion is fired from drawGraph() every time a deactivated legend is clicked.
|
|
*/
|
|
show : function() {
|
|
var dataSet = this,
|
|
upperBoxContainer = dataSet.graphics.upperBoxContainer,
|
|
lowerBoxContainer = dataSet.graphics.lowerBoxContainer,
|
|
medianContainer = dataSet.graphics.medianContainer,
|
|
|
|
upperWhiskerContainer = dataSet.graphics.upperWhiskerContainer,
|
|
lowerWhiskerContainer = dataSet.graphics.lowerWhiskerContainer,
|
|
|
|
dataLabelContainer = dataSet.graphics.dataLabelContainer,
|
|
shadowContainer = dataSet.graphics.shadowContainer,
|
|
chart = dataSet.chart,
|
|
yAxis = dataSet.yAxis,
|
|
i;
|
|
|
|
chart._chartAnimation();
|
|
dataSet.visible = true;
|
|
|
|
dataSet.components.outliers.visible = true;
|
|
|
|
dataSet._conatinerHidden = false;
|
|
|
|
upperBoxContainer.show();
|
|
lowerBoxContainer.show();
|
|
medianContainer.show();
|
|
upperWhiskerContainer.show();
|
|
lowerWhiskerContainer.show();
|
|
dataLabelContainer.show();
|
|
shadowContainer.show();
|
|
|
|
for (i = 0; i < dataSet.config.maxNumberOfOutliers; i++) {
|
|
dataSet.components.outliers[i].show();
|
|
}
|
|
|
|
chart._setAxisLimits();
|
|
yAxis.draw();
|
|
chart._drawDataset();
|
|
|
|
dataSet.components.mean.show();
|
|
dataSet.components.sd.show();
|
|
dataSet.components.qd.show();
|
|
dataSet.components.md.show();
|
|
},
|
|
|
|
/*
|
|
* This function is used to make a dataset hidden when clicked on its respective legend.
|
|
* This fucntion is fired from drawGraph() every time an activated legend is clicked.
|
|
*/
|
|
hide : function() {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
yAxis = dataSet.yAxis,
|
|
len,
|
|
i;
|
|
|
|
chart._chartAnimation();
|
|
dataSet.visible = false;
|
|
|
|
len = dataSet.config.maxNumberOfOutliers;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
dataSet.components.outliers[i].hide();
|
|
}
|
|
|
|
chart._setAxisLimits();
|
|
yAxis.draw();
|
|
chart._drawDataset();
|
|
|
|
dataSet.components.mean.hide();
|
|
dataSet.components.sd.hide();
|
|
dataSet.components.qd.hide();
|
|
dataSet.components.md.hide();
|
|
|
|
len = dataSet.config.maxNumberOfOutliers || dataSet.components.outliers.length;
|
|
|
|
dataSet.components.outliers.visible = false;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
dataSet.components.outliers[i].visible = false;
|
|
dataSet.components.outliers[i].draw();
|
|
}
|
|
}
|
|
|
|
},'Column', {
|
|
showplotborder: UNDEFINED,
|
|
plotborderdashlen: UNDEFINED,
|
|
plotborderdashgap: UNDEFINED,
|
|
plotfillalpha: UNDEFINED,
|
|
useroundedges: UNDEFINED,
|
|
ratio: UNDEFINED,
|
|
plotborderthickness: UNDEFINED,
|
|
showvalues: UNDEFINED,
|
|
valuepadding: UNDEFINED,
|
|
showtooltip: UNDEFINED,
|
|
maxcolwidth: UNDEFINED,
|
|
rotatevalues: UNDEFINED,
|
|
use3dlighting: UNDEFINED,
|
|
whiskerslimitswidthratio: UNDEFINED,
|
|
outliersupperrangeratio: UNDEFINED,
|
|
outlierslowerrangeratio: UNDEFINED,
|
|
showalloutliers: UNDEFINED,
|
|
showmean: UNDEFINED,
|
|
showsd: UNDEFINED,
|
|
showmd: UNDEFINED,
|
|
showqd: UNDEFINED,
|
|
showminvalues: UNDEFINED,
|
|
showmaxvalues: UNDEFINED,
|
|
showq1values: UNDEFINED,
|
|
showq3values: UNDEFINED,
|
|
showmedianvalues: UNDEFINED
|
|
}]);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-subds',
|
|
function () {
|
|
var COMPONENT = 'component',
|
|
DATASET = 'dataset';
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'subDS', {
|
|
show : function() {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
yAxis = dataSet.yAxis;
|
|
|
|
chart._chartAnimation();
|
|
dataSet.visible = true;
|
|
dataSet._conatinerHidden = false;
|
|
if (chart.config.transposeAxis) {
|
|
chart._setAxisLimits();
|
|
yAxis.draw();
|
|
}
|
|
// Calling the draw function for redrawing the dataset
|
|
dataSet.draw();
|
|
},
|
|
|
|
hide : function() {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
yAxis = dataSet.yAxis;
|
|
chart._chartAnimation();
|
|
dataSet.visible = false;
|
|
if (chart.config.transposeAxis) {
|
|
chart._setAxisLimits();
|
|
yAxis.draw();
|
|
}
|
|
dataSet.draw();
|
|
},
|
|
|
|
getEventArgs: function () {
|
|
var dataset = this,
|
|
config = dataset.config || {},
|
|
eventArgs = {
|
|
datasetName: dataset.name,
|
|
datasetIndex: dataset.index,
|
|
id: config.userID,
|
|
visible: dataset.visible
|
|
};
|
|
return eventArgs;
|
|
},
|
|
|
|
// Fuction to be fired on legend click
|
|
legendInteractivity : function (dataSet, legendItem) {
|
|
var legend = this,
|
|
legendConfig = legend.config,
|
|
visible = dataSet.visible,
|
|
config = legendItem.config,
|
|
legendGraphics = legendItem.graphics,
|
|
itemHiddenStyle = legendConfig.itemHiddenStyle,
|
|
hiddenColor = itemHiddenStyle.color,
|
|
itemStyle = legendConfig.itemStyle,
|
|
itemTextColor = itemStyle.color,
|
|
color = config.fillColor,
|
|
attrObj,
|
|
type,
|
|
element,
|
|
stroke = config.strokeColor;
|
|
|
|
visible ? dataSet.hide() : dataSet.show();
|
|
attrObj = {
|
|
'legendItemSymbol': {
|
|
fill: visible ? hiddenColor : color,
|
|
'stroke': visible ? hiddenColor : stroke
|
|
},
|
|
legendItemText: {
|
|
fill: visible ? hiddenColor : itemTextColor
|
|
},
|
|
legendItemLine: {
|
|
'stroke': visible ? hiddenColor : (config.lineAttr && config.lineAttr.stroke)
|
|
}
|
|
};
|
|
|
|
for (type in legendGraphics) {
|
|
element = legendGraphics[type];
|
|
if (element && attrObj[type]) {
|
|
element.attr(attrObj[type]);
|
|
}
|
|
}
|
|
}
|
|
|
|
},'Line']);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-heatmap',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
//strings
|
|
preDefStr = lib.preDefStr,
|
|
colorStrings = preDefStr.colors,
|
|
COLOR_FFFFFF = colorStrings.FFFFFF,
|
|
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
showHoverEffectStr = preDefStr.showHoverEffectStr,
|
|
columnStr = preDefStr.columnStr,
|
|
shadowStr = preDefStr.shadowStr,
|
|
dataLabelStr = preDefStr.dataLabelStr,
|
|
miterStr = preDefStr.miterStr,
|
|
hiddenStr = preDefStr.hiddenStr,
|
|
visibleStr = preDefStr.visibleStr,
|
|
ZEROSTRING = lib.ZEROSTRING,
|
|
pStr = preDefStr.pStr,
|
|
sStr = preDefStr.sStr,
|
|
POSITION_START = preDefStr.POSITION_START,
|
|
POSITION_TOP = preDefStr.POSITION_TOP,
|
|
POSITION_END = preDefStr.POSITION_END,
|
|
POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
|
|
NORMAL = preDefStr.NORMAL,
|
|
pInt = function (s, mag) {
|
|
return parseInt(s, mag || 10);
|
|
},
|
|
PXSTRING = 'px',
|
|
|
|
tlLabelStr = 'tlLabel',
|
|
blLabelStr = 'blLabel',
|
|
trLabelStr = 'trLabel',
|
|
brLabelStr = 'brLabel',
|
|
BLANK = lib.BLANKSTRING,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
getValidValue = lib.getValidValue,
|
|
pluckNumber = lib.pluckNumber,
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
isIE = lib.isIE,
|
|
dropHash = lib.regex.dropHash,
|
|
HASHSTRING = lib.HASHSTRING,
|
|
UNDEFINED,
|
|
NONE = 'none',
|
|
|
|
PLOTBORDERCOLOR = 'plotBorderColor',
|
|
PLOTGRADIENTCOLOR = 'plotGradientColor',
|
|
SHOWSHADOW = 'showShadow',
|
|
BOLDSTARTTAG = '<b>',
|
|
BOLDENDTAG = '</b>',
|
|
BREAKSTRING = '<br />',
|
|
POINTER = 'pointer',
|
|
SETROLLOVERATTR = 'setRolloverAttr',
|
|
SETROLLOUTATTR = 'setRolloutAttr',
|
|
EVENTARGS = 'eventArgs',
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
|
|
schedular = lib.schedular,
|
|
defined = function(obj) {
|
|
return obj !== UNDEFINED && obj !== null;
|
|
},
|
|
TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')', // invisible but clickable
|
|
TOUCH_THRESHOLD_PIXELS = lib.TOUCH_THRESHOLD_PIXELS,
|
|
CLICK_THRESHOLD_PIXELS = lib.CLICK_THRESHOLD_PIXELS,
|
|
COMMA = ',',
|
|
math = Math,
|
|
mathRound = math.round,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
hasTouch = lib.hasTouch,
|
|
// hot/tracker threshold in pixels
|
|
HTP = hasTouch ? TOUCH_THRESHOLD_PIXELS :
|
|
CLICK_THRESHOLD_PIXELS,
|
|
setLineHeight = lib.setLineHeight,
|
|
getLightColor = lib.graphics.getLightColor,
|
|
convertColor = lib.graphics.convertColor,
|
|
// POSITION_CENTER = lib.POSITION_CENTER,
|
|
// INT_ZERO = 0,
|
|
HUNDREDSTRING = lib.HUNDREDSTRING;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'HeatMap', {
|
|
type: 'heatmap',
|
|
configure : function () {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
components = chart.components,
|
|
postLegendInitFn = components.postLegendInitFn,
|
|
gradientLegend = components.gradientLegend,
|
|
chartConfig = chart.config,
|
|
// dataLabelStyle = chartConfig.dataLabelStyle,
|
|
style = chartConfig.style,
|
|
|
|
conf = dataSet.config,
|
|
jsonData = chart.jsonData,
|
|
|
|
JSONData = dataSet.JSONData,
|
|
setDataArr = JSONData.data,
|
|
|
|
singleSeries = chart.singleseries,
|
|
|
|
len = setDataArr && setDataArr.length,
|
|
chartAttr = chart.jsonData.chart,
|
|
colorM = chart.components.colorManager,
|
|
index = dataSet.index || dataSet.positionIndex,
|
|
showplotborder,
|
|
plotColor = conf.plotColor = colorM.getPlotColor(index),
|
|
plotBorderDash = pluckNumber(JSONData.dashed, chartAttr.plotborderdashed),
|
|
usePlotGradientColor = pluckNumber(chartAttr.useplotgradientcolor, 1),
|
|
showTooltip = pluckNumber(chartAttr.showtooltip, 1),
|
|
parseUnsafeString = lib.parseUnsafeString,
|
|
yAxisName = parseUnsafeString(chartAttr.yaxisname),
|
|
xAxisName = parseUnsafeString(chartAttr.xaxisname),
|
|
tooltipSepChar = parseUnsafeString(pluck(chartAttr.tooltipsepchar, ': ')),
|
|
|
|
parseTooltext = lib.parseTooltext,
|
|
formatedVal,
|
|
parserConfig,
|
|
setTooltext,
|
|
|
|
macroIndices,
|
|
tempPlotfillAngle,
|
|
toolText,
|
|
plotDashLen,
|
|
plotDashGap,
|
|
plotBorderThickness,
|
|
isRoundEdges,
|
|
showHoverEffect,
|
|
plotfillAngle,
|
|
plotFillAlpha,
|
|
plotRadius,
|
|
plotFillRatio,
|
|
plotgradientcolor,
|
|
plotBorderAlpha,
|
|
plotBorderColor,
|
|
plotBorderDashStyle,
|
|
initailPlotBorderDashStyle,
|
|
setData,
|
|
setValue,
|
|
dataObj,
|
|
config,
|
|
|
|
colorRange = jsonData.colorrange || {},
|
|
colorArr,
|
|
xAxis = chart.components.xAxis[0],
|
|
yAxis = chart.components.yAxis[0],
|
|
column,
|
|
row,
|
|
mapByPercent = conf.mapByPercent = pluckNumber(colorRange.mapbypercent, 0),
|
|
mapByCategory = conf.mapByCategory =
|
|
pluckNumber(chartAttr.mapbycategory, 0),
|
|
rawData = chart.jsonData,
|
|
useColorGradient = rawData.colorrange && pluckNumber(rawData.colorrange.gradient),
|
|
ColorRangeManager = lib.nonGradientColorRange,
|
|
hoverColor,
|
|
hoverAlpha,
|
|
hoverGradientColor,
|
|
hoverRatio,
|
|
hoverAngle,
|
|
hoverBorderColor,
|
|
hoverBorderAlpha,
|
|
hoverBorderThickness,
|
|
hoverBorderDashed,
|
|
hoverBorderDashGap,
|
|
hoverBorderDashLen,
|
|
hoverDashStyle,
|
|
hoverColorArr,
|
|
getDashStyle = lib.getDashStyle,
|
|
dataStore = dataSet.components.data,
|
|
plotGrid = dataSet.components.plotGrid = [],
|
|
numberFormatter = chart.components.numberFormatter,
|
|
toolTipValue,
|
|
setDisplayValue,
|
|
definedGroupPadding,
|
|
isBar = chart.isBar,
|
|
is3D = chart.is3D,
|
|
enableAnimation,
|
|
parentYAxis,
|
|
setDataDashed,
|
|
setDataPlotDashLen,
|
|
setDataPlotDashGap,
|
|
i,
|
|
r,
|
|
c,
|
|
maxValue = -Infinity,
|
|
minValue = +Infinity,
|
|
heatRange,
|
|
colorObj,
|
|
tlType = getValidValue(chartAttr.tltype, BLANK),
|
|
trType = getValidValue(chartAttr.trtype, BLANK),
|
|
blType = getValidValue(chartAttr.bltype, BLANK),
|
|
brType = getValidValue(chartAttr.brtype, BLANK),
|
|
tlLabel,
|
|
trLabel,
|
|
blLabel,
|
|
brLabel,
|
|
tlTypeToolText = BLANK,
|
|
trTypeToolText = BLANK,
|
|
blTypeToolText = BLANK,
|
|
brTypeToolText = BLANK,
|
|
percentValue,
|
|
toolTextValue,
|
|
font,
|
|
fontSize,
|
|
fontColor,
|
|
fontWeight,
|
|
fontStyle,
|
|
value,
|
|
totalRows = jsonData.rows.row.length,
|
|
totalColumns = jsonData.columns.column.length,
|
|
color;
|
|
|
|
for (r = 0; r < totalRows; r++) {
|
|
plotGrid.push([]);
|
|
for(c = 0; c < totalColumns; c++) {
|
|
plotGrid[r].push([]);
|
|
}
|
|
}
|
|
|
|
|
|
showplotborder = conf.showplotborder = pluckNumber(chartAttr.showplotborder, is3D ? 0 : 1);
|
|
conf.plotDashLen = plotDashLen = pluckNumber(chartAttr.plotborderdashlen, 5);
|
|
conf.plotDashGap = plotDashGap = pluckNumber(chartAttr.plotborderdashgap, 4);
|
|
conf.plotfillAngle = plotfillAngle = pluckNumber(360 - chartAttr.plotfillangle, (isBar ? 180 : 90));
|
|
conf.plotFillAlpha = plotFillAlpha = pluck(JSONData.alpha, chartAttr.plotfillalpha, HUNDREDSTRING);
|
|
conf.plotColor = plotColor = pluck(JSONData.color, plotColor);
|
|
conf.isRoundEdges = isRoundEdges = pluckNumber(chartAttr.useroundedges,0);
|
|
conf.plotRadius = plotRadius = pluckNumber(chartAttr.useRoundEdges, conf.isRoundEdges ? 1 : 0);
|
|
conf.plotFillRatio = plotFillRatio = pluck(JSONData.ratio, chartAttr.plotfillratio);
|
|
conf.plotgradientcolor = plotgradientcolor = lib.getDefinedColor(chartAttr.plotgradientcolor,
|
|
colorM.getColor(PLOTGRADIENTCOLOR));
|
|
!usePlotGradientColor && (plotgradientcolor = BLANKSTRING);
|
|
conf.plotBorderAlpha = plotBorderAlpha = showplotborder ? pluck(chartAttr.plotborderalpha,
|
|
plotFillAlpha, HUNDREDSTRING): 0;
|
|
conf.plotBorderColor = plotBorderColor = pluck(chartAttr.plotbordercolor,
|
|
is3D ? COLOR_FFFFFF : colorM.getColor(PLOTBORDERCOLOR));
|
|
conf.plotBorderThickness = plotBorderThickness = pluckNumber(chartAttr.plotborderthickness, 1);
|
|
conf.plotBorderDashStyle = initailPlotBorderDashStyle = plotBorderDash ?
|
|
getDashStyle(plotDashLen, plotDashGap, plotBorderThickness) : NONE;
|
|
conf.showValues = pluckNumber(JSONData.showvalues, chartAttr.showvalues, 1);
|
|
conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
|
|
conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
|
|
chartAttr.defaultanimation, 1);
|
|
conf.animation = !enableAnimation ? false : {
|
|
duration: pluckNumber(chartAttr.animationduration, 1) * 1000
|
|
};
|
|
conf.transposeAnimation =
|
|
pluckNumber(chartAttr.transposeanimation, enableAnimation);
|
|
conf.transposeAnimDuration = pluckNumber(chartAttr.transposeanimduration, 0.2) * 1000;
|
|
|
|
conf.showShadow = (isRoundEdges || is3D) ? pluckNumber(chartAttr.showshadow, 1) :
|
|
pluckNumber(chartAttr.showshadow, colorM.getColor(SHOWSHADOW));
|
|
conf.showHoverEffect = showHoverEffect = pluckNumber(chartAttr.plothovereffect,
|
|
chartAttr.showhovereffect, UNDEFINED);
|
|
conf.showTooltip = pluckNumber(chartAttr.showtooltip, 1);
|
|
conf.definedGroupPadding = definedGroupPadding = mathMax(pluckNumber(chartAttr.plotspacepercent), 0);
|
|
conf.plotSpacePercent = mathMax(pluckNumber(chartAttr.plotspacepercent, 20) % 100, 0);
|
|
conf.maxColWidth = pluckNumber(isBar ? chartAttr.maxbarheight : chartAttr.maxcolwidth, 50);
|
|
conf.plotPaddingPercent = pluckNumber(chartAttr.plotpaddingpercent),
|
|
conf.rotateValues = pluckNumber(chartAttr.rotatevalues) ? 270 : 0;
|
|
conf.placeValuesInside = pluckNumber(chartAttr.placevaluesinside, 0);
|
|
|
|
font = style.inCanfontFamily;
|
|
fontSize = pInt(style.inCanfontSize, 10);
|
|
fontColor = style.inCancolor;
|
|
fontWeight = NORMAL;
|
|
fontStyle = NORMAL;
|
|
|
|
conf.tlLabelStyle = {
|
|
fontFamily: pluck(chartAttr.tlfont, font),
|
|
fontSize: pluckNumber(chartAttr.tlfontsize, fontSize) + PXSTRING,
|
|
color: convertColor(pluck(chartAttr.tlfontcolor, fontColor), 100),
|
|
fontWeight: fontWeight,
|
|
fontStyle: fontStyle
|
|
};
|
|
|
|
setLineHeight(conf.tlLabelStyle);
|
|
|
|
conf.trLabelStyle = {
|
|
fontFamily: pluck(chartAttr.trfont, font),
|
|
fontSize: pluckNumber(chartAttr.trfontsize, fontSize) + PXSTRING,
|
|
color: convertColor(pluck(chartAttr.trfontcolor, fontColor), 100),
|
|
fontWeight: fontWeight,
|
|
fontStyle: fontStyle
|
|
};
|
|
|
|
conf.brLabelStyle = {
|
|
fontFamily: pluck(chartAttr.brfont, font),
|
|
fontSize: pluckNumber(chartAttr.brfontsize, fontSize) + PXSTRING,
|
|
color: convertColor(pluck(chartAttr.brfontcolor, fontColor), 100),
|
|
fontWeight: fontWeight,
|
|
fontStyle: fontStyle
|
|
};
|
|
|
|
conf.blLabelStyle = {
|
|
fontFamily: pluck(chartAttr.blfont, font),
|
|
fontSize: pluckNumber(chartAttr.blfontsize, fontSize) + PXSTRING,
|
|
color: convertColor(pluck(chartAttr.blfontcolor, fontColor), 100),
|
|
fontWeight: fontWeight,
|
|
fontStyle: fontStyle
|
|
};
|
|
|
|
conf.use3DLighting = pluckNumber(chartAttr.use3dlighting, 1);
|
|
conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
|
|
pStr) === sStr ? 1 : 0 ;
|
|
if (!dataStore) {
|
|
dataStore = dataSet.components.data = [];
|
|
}
|
|
|
|
// Parsing the attributes and values at set level.
|
|
for (i = 0; i < len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
config = dataObj && dataObj.config;
|
|
|
|
if (!dataObj) {
|
|
dataObj = dataStore[i] = {
|
|
graphics : {}
|
|
};
|
|
}
|
|
|
|
if (!dataObj.config) {
|
|
config = dataStore[i].config = {};
|
|
|
|
}
|
|
|
|
config.showValue = pluckNumber(setData.showvalue, conf.showValues);
|
|
config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
|
|
config.setLink = pluck(setData.link);
|
|
config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
|
|
config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
|
|
config.displayValue = pluck(setDisplayValue, toolTipValue);
|
|
setDataDashed = pluckNumber(setData.dashed);
|
|
setDataPlotDashLen = pluckNumber(setData.dashlen, plotDashLen);
|
|
setDataPlotDashGap = plotDashGap = pluckNumber(setData.dashgap, plotDashGap);
|
|
|
|
maxValue = mathMax(maxValue, setValue);
|
|
minValue = mathMin(minValue, setValue);
|
|
|
|
config.plotBorderDashStyle = plotBorderDashStyle = setDataDashed === 1 ?
|
|
getDashStyle(setDataPlotDashLen, setDataPlotDashGap, plotBorderThickness) :
|
|
(setDataDashed === 0 ? NONE : initailPlotBorderDashStyle);
|
|
if (singleSeries) {
|
|
plotColor = colorM.getPlotColor(i);
|
|
plotColor = pluck(setData.color, plotColor);
|
|
plotFillRatio = pluck(setData.ratio, conf.plotFillRatio);
|
|
}
|
|
else {
|
|
plotColor = pluck(setData.color, conf.plotColor);
|
|
}
|
|
config.plotFillAlpha = plotFillAlpha = pluck(setData.alpha, conf.plotFillAlpha);
|
|
|
|
// Setting the angle for plot fill for negative data
|
|
if (setValue < 0 && !isRoundEdges) {
|
|
|
|
tempPlotfillAngle = plotfillAngle;
|
|
plotfillAngle = isBar ? 180 - plotfillAngle : 360 - plotfillAngle;
|
|
}
|
|
config.colorArr = colorArr = lib.graphics.getColumnColor (
|
|
plotColor + COMMA + conf.plotgradientcolor,
|
|
plotFillAlpha,
|
|
plotFillRatio = conf.plotFillRatio,
|
|
plotfillAngle,
|
|
isRoundEdges,
|
|
conf.plotBorderColor,
|
|
plotBorderAlpha.toString(),
|
|
(isBar ? 1 : 0),
|
|
(is3D ? true : false)
|
|
);
|
|
|
|
formatedVal = config.toolTipValue;
|
|
tempPlotfillAngle && (plotfillAngle = tempPlotfillAngle);
|
|
}
|
|
|
|
conf.maxValue = maxValue;
|
|
conf.minValue = minValue;
|
|
heatRange = maxValue - minValue;
|
|
|
|
if (useColorGradient && !mapByCategory) {
|
|
postLegendInitFn({
|
|
min: minValue,
|
|
max: maxValue
|
|
});
|
|
|
|
// gradientLegend.notifyWhenUpdate(dataSet.updatePlot, dataSet);
|
|
dataSet.components.colorRange = colorRange = gradientLegend.colorRange;
|
|
}
|
|
else {
|
|
dataSet.components.colorRange = colorRange = new ColorRangeManager({
|
|
colorRange: jsonData.colorrange,
|
|
dataMin: minValue,
|
|
dataMax: maxValue,
|
|
sortLegend: 0,
|
|
mapByCategory: mapByCategory,
|
|
defaultColor: 'cccccc',
|
|
numberFormatter: numberFormatter
|
|
});
|
|
|
|
conf.colorMap = [];
|
|
|
|
for (i = 0; i < colorRange.colorArr.length; i++) {
|
|
conf.colorMap[i] = {
|
|
config: colorRange.colorArr[i],
|
|
dataSet: dataSet
|
|
};
|
|
conf.colorMap[i].config.visible = true;
|
|
}
|
|
if (conf.colorMap.length === 0) {
|
|
chart.setChartMessage();
|
|
gradientLegend && gradientLegend.elem && gradientLegend.elem.gl.carpet.group.hide();
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
config = dataObj && dataObj.config;
|
|
|
|
if (mapByPercent) {
|
|
config.percentValue = percentValue = setData.value && (mathRound((setData.value -
|
|
minValue) / heatRange * 10000) / 100);
|
|
}
|
|
else {
|
|
config.percentValue = UNDEFINED;
|
|
}
|
|
|
|
config.value = value = mapByCategory ?
|
|
(setData.colorrangelabel || setData.categoryid) : mapByPercent ? percentValue : config.setValue;
|
|
|
|
if (useColorGradient && !mapByCategory) {
|
|
color = colorRange.getColorByValue(value);
|
|
}
|
|
else {
|
|
colorObj = colorRange.getColorObj(value);
|
|
dataObj.legendItemIndex = colorObj.seriesIndex;
|
|
}
|
|
if (colorObj === UNDEFINED && color === UNDEFINED) {
|
|
config.visible = false;
|
|
continue;
|
|
}
|
|
|
|
if (colorObj && colorObj.outOfRange) {
|
|
config.visible = false;
|
|
config.displayValue = BLANKSTRING;
|
|
continue;
|
|
}
|
|
config.visible = true;
|
|
|
|
plotColor = pluck(setData.color, (colorObj && colorObj.code) || color);
|
|
config.color = convertColor(plotColor, pluck(setData.alpha, conf.plotFillAlpha));
|
|
|
|
// Parsing the hover effects only if showhovereffect is not 0.
|
|
if (showHoverEffect !== 0) {
|
|
|
|
hoverColor = pluck(setData.hovercolor, JSONData.hovercolor, chartAttr.plotfillhovercolor,
|
|
chartAttr.columnhovercolor, plotColor);
|
|
hoverAlpha = pluck(setData.hoveralpha, JSONData.hoveralpha,
|
|
chartAttr.plotfillhoveralpha, chartAttr.columnhoveralpha, '25');
|
|
hoverGradientColor = pluck(setData.hovergradientcolor,
|
|
JSONData.hovergradientcolor, chartAttr.plothovergradientcolor, plotgradientcolor);
|
|
!hoverGradientColor && (hoverGradientColor = BLANKSTRING);
|
|
hoverRatio = pluck(setData.hoverratio,
|
|
JSONData.hoverratio, chartAttr.plothoverratio, plotFillRatio);
|
|
hoverAngle = pluckNumber(360 - setData.hoverangle,
|
|
360 - JSONData.hoverangle, 360 - chartAttr.plothoverangle, plotfillAngle);
|
|
hoverBorderColor = pluck(setData.borderhovercolor,
|
|
JSONData.borderhovercolor, chartAttr.plotborderhovercolor, plotBorderColor);
|
|
hoverBorderAlpha = pluck(setData.borderhoveralpha,
|
|
JSONData.borderhoveralpha, chartAttr.plotborderhoveralpha, plotBorderAlpha, plotFillAlpha);
|
|
hoverBorderThickness = pluckNumber(setData.borderhoverthickness,
|
|
JSONData.borderhoverthickness, chartAttr.plotborderhoverthickness, plotBorderThickness);
|
|
hoverBorderDashed = pluckNumber(setData.borderhoverdashed,
|
|
JSONData.borderhoverdashed, chartAttr.plotborderhoverdashed);
|
|
hoverBorderDashGap = pluckNumber(setData.borderhoverdashgap,
|
|
JSONData.borderhoverdashgap, chartAttr.plotborderhoverdashgap, plotDashLen);
|
|
hoverBorderDashLen = pluckNumber(setData.borderhoverdashlen,
|
|
JSONData.borderhoverdashlen, chartAttr.plotborderhoverdashlen, plotDashGap);
|
|
hoverDashStyle = hoverBorderDashed ?
|
|
getDashStyle(hoverBorderDashLen, hoverBorderDashGap, hoverBorderThickness) :
|
|
plotBorderDashStyle;
|
|
|
|
/* If no hover effects are explicitly defined and
|
|
* showHoverEffect is not 0 then hoverColor is set.
|
|
*/
|
|
if (showHoverEffect == 1 && hoverColor === plotColor) {
|
|
hoverColor = getLightColor(hoverColor, 70);
|
|
}
|
|
|
|
// setting the hover color array which is always applied except when showHoverEffect is not 0.
|
|
hoverColorArr = lib.graphics.getColumnColor (
|
|
hoverColor,
|
|
hoverAlpha,
|
|
hoverRatio,
|
|
hoverAngle,
|
|
isRoundEdges,
|
|
hoverBorderColor,
|
|
hoverBorderAlpha.toString(),
|
|
(isBar ? 1 : 0),
|
|
(is3D ? true : false)
|
|
);
|
|
|
|
config.setRolloutAttr = {
|
|
fill: toRaphaelColor(config.color),
|
|
stroke: showplotborder && toRaphaelColor(hoverColorArr[1]),
|
|
'stroke-width': plotBorderThickness,
|
|
'stroke-dasharray': plotBorderDashStyle
|
|
};
|
|
config.setRolloverAttr = {
|
|
fill: toRaphaelColor(hoverColorArr[0]),
|
|
stroke: showplotborder && toRaphaelColor(hoverColorArr[1]),
|
|
'stroke-width': hoverBorderThickness,
|
|
'stroke-dasharray': hoverDashStyle
|
|
};
|
|
}
|
|
|
|
mapByPercent && (percentValue = numberFormatter.percentValue(percentValue));
|
|
|
|
config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
|
|
config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue, parentYAxis);
|
|
formatedVal = config.toolTipValue;
|
|
setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
|
|
JSONData.plottooltext, chartAttr.plottooltext)));
|
|
|
|
config.tlLabel = tlLabel = parseUnsafeString(pluck(setData.tllabel, setData.ltlabel));
|
|
config.trLabel = trLabel = parseUnsafeString(pluck(setData.trlabel, setData.rtlabel));
|
|
config.blLabel = blLabel = parseUnsafeString(pluck(setData.bllabel, setData.lblabel));
|
|
config.brLabel = brLabel = parseUnsafeString(pluck(setData.brlabel, setData.rblabel));
|
|
|
|
setDisplayValue = getValidValue(parseUnsafeString(
|
|
setData.displayvalue));
|
|
toolTextValue = mapByCategory ?
|
|
setDisplayValue : pluck(setData.displayvalue, formatedVal);
|
|
|
|
config.displayValue = pluck(setDisplayValue, percentValue, config.toolTipValue);
|
|
|
|
if (tlType !== BLANK) {
|
|
tlTypeToolText = BOLDSTARTTAG + tlType + tooltipSepChar + BOLDENDTAG;
|
|
}
|
|
if (trType !== BLANK) {
|
|
trTypeToolText = BOLDSTARTTAG + trType + tooltipSepChar + BOLDENDTAG;
|
|
}
|
|
if (blType !== BLANK) {
|
|
blTypeToolText = BOLDSTARTTAG + blType + tooltipSepChar + BOLDENDTAG;
|
|
}
|
|
if (brType !== BLANK) {
|
|
brTypeToolText = BOLDSTARTTAG + brType + tooltipSepChar + BOLDENDTAG;
|
|
}
|
|
|
|
column = xAxis.getCategoryFromId(setDataArr[i].columnid.toLowerCase());
|
|
row = yAxis.getCategoryFromId(setDataArr[i].rowid.toLowerCase());
|
|
|
|
//create the tooltext
|
|
if (!showTooltip) {
|
|
config.toolText = false;
|
|
}
|
|
else {
|
|
if (formatedVal === null) {
|
|
toolText = false;
|
|
}
|
|
else if (setTooltext !== UNDEFINED) {
|
|
macroIndices = [1, 2, 5, 6, 7, 14, 93, 94, 95, 96, 97, 98, 112, 113, 114, 115, 116,
|
|
117];
|
|
parserConfig = {
|
|
formattedValue : formatedVal,
|
|
value: setData.value,
|
|
yaxisName: yAxisName,
|
|
xaxisName: xAxisName,
|
|
displayValue: setDisplayValue,
|
|
percentValue: mapByPercent ? percentValue : BLANK,
|
|
tlLabel: tlLabel,
|
|
trLabel: trLabel,
|
|
blLabel: blLabel,
|
|
brLabel: brLabel,
|
|
rowLabel: row.catObj && row.catObj.label,
|
|
columnLabel: column.catObj && column.catObj.label,
|
|
percentDataValue: mapByPercent ? percentValue : BLANK,
|
|
trtype: trType,
|
|
tltype: tlType,
|
|
brType: brType,
|
|
blType: blType,
|
|
colorRangeLabel: config.colorRangeLabel
|
|
};
|
|
toolText = parseTooltext(setTooltext, macroIndices,
|
|
parserConfig, setData, chartAttr, parserConfig);
|
|
}
|
|
else {
|
|
toolText = ((mapByPercent ? BOLDSTARTTAG + 'Value' + tooltipSepChar + BOLDENDTAG +
|
|
formatedVal +
|
|
BREAKSTRING + BOLDSTARTTAG + 'Percentage' + tooltipSepChar + BOLDENDTAG +
|
|
percentValue :
|
|
toolTextValue) +
|
|
// Now we add special labels in toolTip
|
|
(tlLabel !== BLANK ? BREAKSTRING +
|
|
(tlTypeToolText + tlLabel) : BLANK) + (trLabel !== BLANK ? BREAKSTRING +
|
|
trTypeToolText + trLabel : BLANK) + (blLabel !== BLANK ? BREAKSTRING +
|
|
blTypeToolText + blLabel : BLANK) + (brLabel !== BLANK ? BREAKSTRING +
|
|
brTypeToolText + brLabel : BLANK));
|
|
}
|
|
config.toolText = toolText;
|
|
config.setTooltext = toolText;
|
|
}
|
|
|
|
// dataObj = extend2(dataObj, this.getPointStub(dataObj,
|
|
// dataObj.value, BLANK, HCObj, FCObj));
|
|
}
|
|
(chart.hasLegend !== false && (!useColorGradient || mapByCategory)) && dataSet._addLegend();
|
|
},
|
|
|
|
/*
|
|
* Function for initializing the column class object.
|
|
* This function is called once.
|
|
* @param {object} chart - The default FutionCharts chart object.
|
|
* @param {number} datasetIndex - The postion index of a dataset.
|
|
* @param {number} stackIndex - The stack index of a dataset.
|
|
*/
|
|
init : function(datasetJSON) {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
components = chart.components,
|
|
visible,
|
|
parentYAxis = datasetJSON.parentyaxis && datasetJSON.parentyaxis.toLowerCase() === sStr ? 1 : 0,
|
|
yAxis = components.yAxis[parentYAxis];
|
|
|
|
|
|
|
|
if (!datasetJSON) {
|
|
return false;
|
|
}
|
|
dataSet.JSONData = datasetJSON;
|
|
dataSet.yAxis = yAxis;
|
|
dataSet.chartGraphics = chart.chartGraphics;
|
|
dataSet.components = {
|
|
};
|
|
|
|
dataSet.graphics = {
|
|
};
|
|
|
|
dataSet.visible = visible = pluckNumber(dataSet.JSONData.visible,
|
|
!Number(dataSet.JSONData.initiallyhidden), 1) === 1;
|
|
dataSet.configure();
|
|
},
|
|
|
|
_addLegend: function () {
|
|
var dataset = this,
|
|
entityComponents = dataset.components.data,
|
|
chart = dataset.chart,
|
|
chartAttr = chart.jsonData.chart,
|
|
strokeColor,
|
|
fillColor,
|
|
lightColor,
|
|
config,
|
|
conf = dataset.config,
|
|
colorMap = conf.colorMap,
|
|
colorRange = dataset.components.colorRange,
|
|
color,
|
|
i,
|
|
j,
|
|
colorCode,
|
|
len,
|
|
item,
|
|
legend = chart.components.legend,
|
|
use3DLighting = pluckNumber(chartAttr.us3dlighting, chartAttr.useplotgradientcolor, 1);
|
|
|
|
legend.emptyItems();
|
|
|
|
for (i = 0, len = colorMap.length; i < len; i++) {
|
|
item = colorMap[i];
|
|
color = colorRange.colorArr[i].code;
|
|
strokeColor = getLightColor(color, 60).replace(dropHash, HASHSTRING);
|
|
lightColor = getLightColor(color, 40);
|
|
if (use3DLighting) {
|
|
lightColor = getLightColor(color, 40);
|
|
fillColor = {
|
|
FCcolor: {
|
|
color: color + COMMA + color + COMMA + lightColor,
|
|
ratio: '0,70,30',
|
|
angle: 270,
|
|
alpha: '100,100,100'
|
|
}
|
|
};
|
|
}
|
|
else {
|
|
fillColor = {
|
|
FCcolor: {
|
|
color: color,
|
|
angle: 0,
|
|
ratio: ZEROSTRING,
|
|
alpha: HUNDREDSTRING
|
|
}
|
|
};
|
|
}
|
|
config = {
|
|
fillColor: toRaphaelColor(fillColor),
|
|
label: item.config.label,
|
|
rawFillColor: color,
|
|
strokeColor: toRaphaelColor(strokeColor),
|
|
datasetObj: dataset
|
|
};
|
|
colorMap[i].legendItemId =
|
|
chart.components.legend.addItems(item, dataset.legendInteractivity, config);
|
|
}
|
|
|
|
for (i = 0; i < entityComponents.length; i++) {
|
|
colorCode = colorRange.getColorObj(entityComponents[i].config.value).code;
|
|
|
|
for (j = 0; j < colorMap.length; j++) {
|
|
if (colorMap[j].config.code == colorCode) {
|
|
entityComponents[i].legendItemId = colorMap[j].legendItemId;
|
|
entityComponents[i].datasetIndex = j;
|
|
entityComponents[i].datasetName = colorMap[j].config.label;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
legendInteractivity: function (item, legendItem) {
|
|
var legend = this,
|
|
legendConfig = legend.config,
|
|
visible = item.config.visible,
|
|
dataset = item.dataSet,
|
|
config = legendItem.config,
|
|
legendGraphics = legendItem.graphics,
|
|
itemHiddenStyle = legendConfig.itemHiddenStyle,
|
|
hiddenColor = itemHiddenStyle.color,
|
|
itemStyle = legendConfig.itemStyle,
|
|
itemTextColor = itemStyle.color,
|
|
color = config.fillColor,
|
|
stroke = config.strokeColor;
|
|
|
|
visible ? dataset.hide(item) : dataset.show(item);
|
|
|
|
if (!visible) {
|
|
legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
|
|
fill: color,
|
|
'stroke': stroke
|
|
});
|
|
legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
|
|
fill: itemTextColor
|
|
});
|
|
legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
|
|
'stroke': color
|
|
});
|
|
} else {
|
|
legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
|
|
fill: hiddenColor,
|
|
'stroke': hiddenColor
|
|
});
|
|
legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
|
|
fill: hiddenColor
|
|
});
|
|
legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
|
|
'stroke': hiddenColor
|
|
});
|
|
}
|
|
},
|
|
|
|
hide: function (item) {
|
|
var dataset = this,
|
|
entityComponents = dataset.components.data,
|
|
chart = dataset.chart,
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animType = animationObj.animType,
|
|
animObj = animationObj.animObj,
|
|
dummyObj = animationObj.dummyObj,
|
|
animationDuration = animationObj.duration,
|
|
colorRange = dataset.components.colorRange,
|
|
i,
|
|
len,
|
|
config,
|
|
legendItemColor,
|
|
colorCode;
|
|
|
|
legendItemColor = item.config.code;
|
|
|
|
for (i = 0, len = entityComponents.length; i < len; i++) {
|
|
|
|
colorCode = colorRange.getColorObj(entityComponents[i].config.value).code;
|
|
config = entityComponents[i].config;
|
|
|
|
if (legendItemColor === colorCode) {
|
|
entityComponents[i].graphics.element && entityComponents[i].graphics.element
|
|
.animateWith(dummyObj, animObj, {
|
|
'fill-opacity': 0,
|
|
'stroke-width': 0
|
|
}, animationDuration, animType);
|
|
|
|
//animFlagHide = false;
|
|
|
|
entityComponents[i].graphics.hotElement &&
|
|
entityComponents[i].graphics.hotElement.hide();
|
|
entityComponents[i].graphics.valEle && entityComponents[i].graphics.valEle.hide();
|
|
|
|
entityComponents[i].graphics.tlLabel && entityComponents[i].graphics.tlLabel.hide();
|
|
entityComponents[i].graphics.trLabel && entityComponents[i].graphics.trLabel.hide();
|
|
entityComponents[i].graphics.blLabel && entityComponents[i].graphics.blLabel.hide();
|
|
entityComponents[i].graphics.brLabel && entityComponents[i].graphics.brLabel.hide();
|
|
config.visible = false;
|
|
entityComponents[i].visible = false;
|
|
}
|
|
}
|
|
item.visible = false;
|
|
item.config.visible = false;
|
|
},
|
|
|
|
show: function (item) {
|
|
var dataset = this,
|
|
entityComponents = dataset.components.data,
|
|
conf = dataset.config,
|
|
chart = dataset.chart,
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animType = animationObj.animType,
|
|
animObj = animationObj.animObj,
|
|
dummyObj = animationObj.dummyObj,
|
|
animationDuration = animationObj.duration,
|
|
config,
|
|
plotFillAlpha,
|
|
colorRange = dataset.components.colorRange,
|
|
i,
|
|
len,
|
|
legendItemColor,
|
|
colorCode;
|
|
|
|
legendItemColor = item.config.code;
|
|
|
|
for (i = 0, len = entityComponents.length; i < len; i++) {
|
|
config = entityComponents[i].config;
|
|
plotFillAlpha = config.plotFillAlpha / 100;
|
|
colorCode = colorRange.getColorObj(entityComponents[i].config.value).code;
|
|
|
|
if (legendItemColor === colorCode) {
|
|
|
|
entityComponents[i].graphics.element && entityComponents[i].graphics.element
|
|
.attr({
|
|
'visibility': visibleStr
|
|
})
|
|
.animateWith(dummyObj, animObj, {
|
|
'fill-opacity': plotFillAlpha,
|
|
'stroke-width': conf.plotBorderThickness
|
|
}, animationDuration, animType);
|
|
|
|
//animFlagShow = false;
|
|
|
|
entityComponents[i].graphics.hotElement &&
|
|
entityComponents[i].graphics.hotElement.show();
|
|
entityComponents[i].graphics.valEle && entityComponents[i].graphics.valEle.show();
|
|
|
|
entityComponents[i].graphics.tlLabel && entityComponents[i].graphics.tlLabel.show();
|
|
entityComponents[i].graphics.trLabel && entityComponents[i].graphics.trLabel.show();
|
|
entityComponents[i].graphics.blLabel && entityComponents[i].graphics.blLabel.show();
|
|
entityComponents[i].graphics.brLabel && entityComponents[i].graphics.brLabel.show();
|
|
config.visible = true;
|
|
entityComponents[i].visible = true;
|
|
}
|
|
}
|
|
item.visible = true;
|
|
item.config.visible = true;
|
|
},
|
|
|
|
updatePlot : function() {
|
|
var dataset = this,
|
|
minValue = arguments[0],
|
|
maxValue = arguments[1],
|
|
|
|
conf = dataset.config,
|
|
chart = dataset.chart,
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animType = animationObj.animType,
|
|
animObj = animationObj.animObj,
|
|
dummyObj = animationObj.dummyObj,
|
|
animationDuration = animationObj.duration,
|
|
config,
|
|
plotFillAlpha,
|
|
entityComponents = dataset.components.data,
|
|
i,
|
|
len,
|
|
value;
|
|
|
|
for (i = 0, len = entityComponents.length; i < len; i++) {
|
|
|
|
config = entityComponents[i].config;
|
|
plotFillAlpha = config.plotFillAlpha / 100;
|
|
|
|
value = entityComponents[i].config.value;
|
|
|
|
if (value < minValue || value > maxValue) {
|
|
if(config.visible) {
|
|
entityComponents[i].graphics.element && entityComponents[i].graphics.element
|
|
.animateWith(dummyObj, animObj, {
|
|
'fill-opacity': 0,
|
|
'stroke-width': 0
|
|
}, animationDuration, animType);
|
|
|
|
//animFlagHide = false;
|
|
|
|
entityComponents[i].graphics.hotElement &&
|
|
entityComponents[i].graphics.hotElement.hide();
|
|
entityComponents[i].graphics.valEle && entityComponents[i].graphics.valEle.hide();
|
|
|
|
entityComponents[i].graphics.tlLabel && entityComponents[i].graphics.tlLabel.hide();
|
|
entityComponents[i].graphics.trLabel && entityComponents[i].graphics.trLabel.hide();
|
|
entityComponents[i].graphics.blLabel && entityComponents[i].graphics.blLabel.hide();
|
|
entityComponents[i].graphics.brLabel && entityComponents[i].graphics.brLabel.hide();
|
|
config.visible = false;
|
|
entityComponents[i].visible = false;
|
|
}
|
|
}
|
|
else {
|
|
if (!config.visible) {
|
|
entityComponents[i].graphics.element && entityComponents[i].graphics.element
|
|
.animateWith(dummyObj, animObj, {
|
|
'fill-opacity': plotFillAlpha,
|
|
'stroke-width': conf.plotBorderThickness
|
|
}, animationDuration, animType);
|
|
|
|
//animFlagShow = false;
|
|
|
|
entityComponents[i].graphics.hotElement &&
|
|
entityComponents[i].graphics.hotElement.show();
|
|
entityComponents[i].graphics.valEle && entityComponents[i].graphics.valEle.show();
|
|
|
|
entityComponents[i].graphics.tlLabel && entityComponents[i].graphics.tlLabel.show();
|
|
entityComponents[i].graphics.trLabel && entityComponents[i].graphics.trLabel.show();
|
|
entityComponents[i].graphics.blLabel && entityComponents[i].graphics.blLabel.show();
|
|
entityComponents[i].graphics.brLabel && entityComponents[i].graphics.brLabel.show();
|
|
config.visible = true;
|
|
entityComponents[i].visible = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
},
|
|
//helper function for gethoveredplot function
|
|
_checkPointObj : function (pX, pY, chartX, chartY) {
|
|
var dataset = this,
|
|
plotGrid = dataset.components.plotGrid,
|
|
pointObj,
|
|
chart = dataset.chart,
|
|
chartConfig = chart.config,
|
|
viewPortConfig = chartConfig.viewPortConfig,
|
|
x = viewPortConfig.x,
|
|
scaleX = viewPortConfig.scaleX,
|
|
plotBorderThickness = chartConfig.plotborderthickness,
|
|
showPlotBorder = chartConfig.showplotborder,
|
|
halfPlotBorderThickness,
|
|
dx,
|
|
dy,
|
|
hovered;
|
|
|
|
pointObj = plotGrid[pY] && plotGrid[pY][pX];
|
|
plotBorderThickness = showPlotBorder ? plotBorderThickness : 0;
|
|
halfPlotBorderThickness = plotBorderThickness / 2;
|
|
|
|
halfPlotBorderThickness = halfPlotBorderThickness % 2 === 0 ? halfPlotBorderThickness + 1 :
|
|
Math.round(halfPlotBorderThickness);
|
|
|
|
if(pointObj && pointObj.config && pointObj.config.visible){
|
|
dx = chartX - (pointObj._xPos - x * scaleX) + halfPlotBorderThickness;
|
|
dy = chartY - pointObj._yPos + halfPlotBorderThickness;
|
|
|
|
hovered = dx >= 0 && dx <= pointObj._width + plotBorderThickness && dy >= 0 &&
|
|
dy <= pointObj._height + plotBorderThickness;
|
|
|
|
if (hovered) {
|
|
return {
|
|
pointIndex: pointObj._index,
|
|
hovered: hovered,
|
|
pointObj: pointObj
|
|
};
|
|
}
|
|
}
|
|
},
|
|
// function to return the hovered data object
|
|
_getHoveredPlot : function (chartX, chartY) {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
chartConfig = chart.config,
|
|
xAxis = chart.components.xAxis[0],
|
|
yAxis = chart.components.yAxis[0],
|
|
height = chart.config.canvasHeight / chart.jsonData.rows.row.length,
|
|
canvas = chart.components.canvas,
|
|
canvasConfig = canvas.config,
|
|
canvasPadding = Math.max(canvasConfig.canvasPaddingLeft, canvasConfig.canvasPadding),
|
|
canvasLeft = chartConfig.canvasLeft,
|
|
canvasTop = chartConfig.canvasTop,
|
|
x,
|
|
y,
|
|
pX,
|
|
pY;
|
|
|
|
y = yAxis.getValue(chartY + height/2 - canvasTop - canvasPadding);
|
|
pY = Math.floor(y);
|
|
|
|
x = xAxis.getValue(chartX - canvasLeft - canvasPadding);
|
|
pX = Math.round(x);
|
|
|
|
if(pX - x > 0){
|
|
return (y - pY > 0.5) ? (dataset._checkPointObj(pX, pY, chartX, chartY) ||
|
|
dataset._checkPointObj(pX - 1, pY, chartX, chartY)) :
|
|
(dataset._checkPointObj(pX, pY - 1, chartX, chartY) ||
|
|
dataset._checkPointObj(pX, pY, chartX, chartY));
|
|
}else{
|
|
return (y - pY > 0.5) ? (dataset._checkPointObj(pX + 1, pY, chartX, chartY) ||
|
|
dataset._checkPointObj(pX, pY, chartX, chartY)) :
|
|
(dataset._checkPointObj(pX, pY - 1, chartX, chartY) ||
|
|
dataset._checkPointObj(pX + 1, pY, chartX, chartY) ||
|
|
dataset._checkPointObj(pX, pY, chartX, chartY));
|
|
}
|
|
},
|
|
draw: function () {
|
|
var dataSet = this,
|
|
JSONData = dataSet.JSONData,
|
|
conf = dataSet.config,
|
|
setDataArr = JSONData.data,
|
|
len,
|
|
setData,
|
|
attr,
|
|
i,
|
|
visible = dataSet.visible,
|
|
chart = dataSet.chart,
|
|
jobList = chart.getJobList(),
|
|
paper = chart.components.paper,
|
|
xAxis = chart.components.xAxis[0],
|
|
yAxis = chart.components.yAxis[0],
|
|
gradientLegend = chart.components.gradientLegend,
|
|
parentContainer = chart.graphics.datasetGroup,
|
|
xPos,
|
|
yPos,
|
|
crispBox,
|
|
layers = chart.graphics,
|
|
showTooltip = chart.config.showtooltip,
|
|
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animType = animationObj.animType,
|
|
animObj = animationObj.animObj,
|
|
dummyObj = animationObj.dummyObj,
|
|
animationDuration = animationObj.duration,
|
|
|
|
columnWidth,
|
|
height,
|
|
toolText,
|
|
dataStore = dataSet.components.data,
|
|
dataObj,
|
|
setElement,
|
|
clip = chart.components.canvas.config.clip,
|
|
clipCanvas = clip['clip-canvas'].slice(0),
|
|
// hotElement,
|
|
setLink,
|
|
setValue,
|
|
// eventArgs,
|
|
displayValue,
|
|
// groupId,
|
|
config,
|
|
setRolloutAttr = {},
|
|
setRolloverAttr = {},
|
|
isPositive,
|
|
yBase = yAxis.getAxisBase(),
|
|
yBasePos = yAxis.yBasePos = yAxis.getAxisPosition(yBase),
|
|
heightBase = 0,
|
|
showShadow = conf.showShadow,
|
|
plotBorderThickness = conf.plotBorderThickness,
|
|
plotRadius = conf.plotRadius,
|
|
container = dataSet.graphics.container,
|
|
dataLabelContainer = dataSet.graphics.dataLabelContainer,
|
|
shadowContainer = dataSet.graphics.shadowContainer,
|
|
dataLabelsLayer = layers.datalabelsGroup,
|
|
colorArr,
|
|
plotBorderDashStyle,
|
|
animFlag = true,
|
|
drawDataLabel = false,
|
|
removeLabel = false,
|
|
legendActive = chart.components.legend.config.isActive,
|
|
plotGrid = dataSet.components.plotGrid,
|
|
|
|
width,
|
|
column,
|
|
row,
|
|
|
|
elemIdStore = [],
|
|
elemId,
|
|
removeDataArr = dataSet.components.removeDataArr || [],
|
|
removeDataArrLen = removeDataArr.length,
|
|
isNewElem,
|
|
showHoverEffect = conf.showHoverEffect,
|
|
trackerConfig;
|
|
|
|
(gradientLegend && gradientLegend.enabled) && (gradientLegend.resetLegend(),
|
|
gradientLegend.clearListeners());
|
|
gradientLegend.notifyWhenUpdate(dataSet.updatePlot, dataSet);
|
|
|
|
/*
|
|
* Creating a container group for the graphic element of column plots if
|
|
* not present and attaching it to its parent group.
|
|
*/
|
|
if (!container) {
|
|
container = dataSet.graphics.container = paper.group(columnStr, parentContainer);
|
|
// Clipping the group so that the plots do not come out of the canvas area when given thick border.
|
|
container.attr({
|
|
'clip-rect': clipCanvas
|
|
});
|
|
|
|
if (!visible) {
|
|
container.hide();
|
|
}
|
|
}
|
|
|
|
//chart.addCSSDefinition('.fusioncharts-datalabels .fusioncharts-label', labelCSS);
|
|
|
|
/*
|
|
* Creating the shadow element container group for each plots if not present
|
|
* and attaching it its parent group.
|
|
*/
|
|
if (!shadowContainer) {
|
|
// Always sending the shadow group to the back of the plots group.
|
|
shadowContainer = dataSet.graphics.shadowContainer =
|
|
paper.group(shadowStr, parentContainer).toBack();
|
|
// Clipping the group so that the shadow do not come out of the canvas area when given thick border.
|
|
// if (!shadowContainer.attrs['clip-rect'] && !isScroll) {
|
|
// shadowContainer.attr({
|
|
// 'clip-rect': elements['clip-canvas']
|
|
// });
|
|
// }
|
|
if (!visible) {
|
|
shadowContainer.hide();
|
|
}
|
|
|
|
}
|
|
|
|
if (!dataLabelContainer) {
|
|
dataLabelContainer = dataSet.graphics.dataLabelContainer =
|
|
paper.group(dataLabelStr, dataLabelsLayer);
|
|
if (!visible) {
|
|
dataLabelContainer.hide();
|
|
}
|
|
}
|
|
|
|
len = setDataArr && setDataArr.length;
|
|
|
|
width = chart.config.canvasWidth / chart.jsonData.columns.column.length;
|
|
height = chart.config.canvasHeight / chart.jsonData.rows.row.length;
|
|
|
|
// Create plot elements.
|
|
for (i = 0; i < len; i++) {
|
|
setData = setDataArr && setDataArr[i];
|
|
dataObj = dataStore[i];
|
|
trackerConfig = dataObj.trackerConfig = {};
|
|
config = dataObj && dataObj.config;
|
|
setValue = config.setValue;
|
|
isPositive = setValue >= 0;
|
|
isNewElem = false;
|
|
(gradientLegend && gradientLegend.enabled && !legendActive) && (config.visible = true);
|
|
column = xAxis.getCategoryFromId(setDataArr[i].columnid.toLowerCase());
|
|
row = yAxis.getCategoryFromId(setDataArr[i].rowid.toLowerCase());
|
|
|
|
if (!column.catObj || !row.catObj || (config.value === BLANKSTRING)) {
|
|
continue;
|
|
}
|
|
|
|
if (!conf.mapByCategory && setValue === null) {
|
|
dataObj.graphics.element && dataObj.graphics.element.hide();
|
|
dataObj.graphics.hotElement && dataObj.graphics.hotElement.hide();
|
|
removeLabel = true;
|
|
continue;
|
|
}
|
|
|
|
removeLabel = false;
|
|
|
|
elemId = column.index.toString() + row.index.toString();
|
|
|
|
elemIdStore.push(elemId);
|
|
|
|
setLink = config.setLink;
|
|
colorArr = config.colorArr;
|
|
|
|
// Creating the data structure if not present for storing the graphics elements.
|
|
if (!dataObj.graphics) {
|
|
dataStore[i].graphics = {};
|
|
|
|
}
|
|
|
|
displayValue = config.displayValue;
|
|
|
|
xPos = xAxis.getAxisPosition(column.index) - width/2;
|
|
|
|
yPos = yAxis.getAxisPosition(row.index) - height/2;
|
|
|
|
columnWidth = width;
|
|
|
|
// Setting the final tooltext.
|
|
toolText = config.toolText;
|
|
toolText && (config.finalTooltext = toolText);
|
|
|
|
dataObj.graphics.valEle && dataObj.graphics.valEle.hide();
|
|
dataObj.graphics.tlLabel && dataObj.graphics.tlLabel.hide();
|
|
dataObj.graphics.trLabel && dataObj.graphics.trLabel.hide();
|
|
dataObj.graphics.blLabel && dataObj.graphics.blLabel.hide();
|
|
dataObj.graphics.brLabel && dataObj.graphics.brLabel.hide();
|
|
|
|
// Setting the event arguments.
|
|
trackerConfig.eventArgs = {
|
|
index: i,
|
|
link: setLink,
|
|
value: config.percentValue || setValue,
|
|
displayValue: displayValue,
|
|
columnId: column.catObj.id,
|
|
rowId: row.catObj.id,
|
|
tlLabel: config.tlLabel,
|
|
trLabel: config.trLabel,
|
|
blLabel: config.blLabel,
|
|
brLabel: config.brLabel,
|
|
//categoryLabel: categories[i].label,
|
|
toolText: !toolText ? '' : toolText,
|
|
id: BLANKSTRING,
|
|
datasetIndex: legendActive ? dataObj.datasetIndex : UNDEFINED,
|
|
datasetName: legendActive ? dataObj.datasetName : UNDEFINED,
|
|
visible: visible
|
|
};
|
|
|
|
setRolloutAttr = config.setRolloutAttr;
|
|
setRolloverAttr = config.setRolloverAttr;
|
|
|
|
yBasePos = yPos;
|
|
heightBase = height;
|
|
|
|
// Setting the attributes for plot drawing.
|
|
attr = {
|
|
x: xPos,
|
|
y: yBasePos,
|
|
width: columnWidth,
|
|
height: heightBase || 1,
|
|
r: plotRadius,
|
|
ishot: !showTooltip,
|
|
fill: config.color,
|
|
stroke: toRaphaelColor(colorArr[1]),
|
|
'stroke-width': animationDuration ? 0 : plotBorderThickness,
|
|
'stroke-dasharray': plotBorderDashStyle,
|
|
'fill-opacity': animationDuration ? 0 : config.plotFillAlpha / 100,
|
|
'stroke-linejoin': miterStr,
|
|
'visibility': config.visible ? visibleStr : hiddenStr,
|
|
cursor: setLink ? POINTER : BLANKSTRING
|
|
};
|
|
|
|
//todo- remove _ to make it public
|
|
dataObj._xPos = xPos;
|
|
dataObj._yPos = yPos;
|
|
dataObj._height = height;
|
|
dataObj._width = columnWidth;
|
|
dataObj._index = i;
|
|
plotGrid[row.index][column.index] = dataObj;
|
|
/*
|
|
* If the data plots are not present then they are created, else only attributes are set for the
|
|
* existing plots.
|
|
*/
|
|
if (!dataObj.graphics.element) {
|
|
setElement = dataObj.graphics.element = paper.rect(attr, container);
|
|
isNewElem = true;
|
|
|
|
setElement.animateWith(dummyObj, animObj, {
|
|
'fill-opacity': config.plotFillAlpha / 100,
|
|
'stroke-width': plotBorderThickness
|
|
}, animationDuration, animType/*, (animFlag && initAnimCallBack)*/);
|
|
|
|
animFlag = false;
|
|
config.elemCreated = true;
|
|
}
|
|
|
|
else {
|
|
drawDataLabel = true;
|
|
attr = {
|
|
x: xPos,
|
|
y: yPos,
|
|
width: columnWidth,
|
|
height: height || 1
|
|
};
|
|
|
|
setElement = dataObj.graphics.element;
|
|
|
|
setElement.animateWith(dummyObj, animObj, attr,
|
|
animationDuration, animationObj.animType);
|
|
|
|
setElement.attr({
|
|
ishot: !showTooltip,
|
|
fill: config.color,
|
|
stroke: toRaphaelColor(colorArr[1]),
|
|
'fill-opacity': config.visible ? config.plotFillAlpha / 100 : 0,
|
|
'stroke-width': config.visible ? plotBorderThickness : 0,
|
|
'stroke-dasharray': plotBorderDashStyle,
|
|
'stroke-linejoin': miterStr,
|
|
'visibility': config.visible ? visibleStr : hiddenStr,
|
|
cursor: setLink ? POINTER : BLANKSTRING
|
|
});
|
|
config.elemCreated = false;
|
|
}
|
|
|
|
// The shadow element is set for the dataplots.
|
|
setElement
|
|
.shadow({opacity : showShadow}, shadowContainer)
|
|
.data('BBox', crispBox);
|
|
|
|
if (setLink || showTooltip) {
|
|
// Fix for touch devices.
|
|
if (height < HTP) {
|
|
yPos -= (HTP - height) / 2;
|
|
height = HTP;
|
|
}
|
|
|
|
// Setting attributes for the tooltip.
|
|
trackerConfig.attr = {
|
|
x: xPos,
|
|
y: yPos,
|
|
width: columnWidth,
|
|
height: height,
|
|
r: plotRadius,
|
|
cursor: setLink ? POINTER : BLANKSTRING,
|
|
stroke: TRACKER_FILL,
|
|
'stroke-width': plotBorderThickness,
|
|
fill: TRACKER_FILL,
|
|
ishot: true,
|
|
'visibility': config.visible ? visibleStr : hiddenStr
|
|
};
|
|
}
|
|
|
|
chart.config.enablemousetracking && setElement
|
|
.data(EVENTARGS, trackerConfig.eventArgs)
|
|
.data(showHoverEffectStr, showHoverEffect)
|
|
.data(SETROLLOVERATTR, config.setRolloverAttr || {})
|
|
.data(SETROLLOUTATTR, config.setRolloutAttr || {});
|
|
}
|
|
|
|
dataSet.drawn ? dataSet.drawLabel() : jobList.labelDrawID.push(schedular.addJob(dataSet.drawLabel,
|
|
dataSet, [], lib.priorityList.label));
|
|
dataSet.drawn = true;
|
|
// (drawDataLabel || removeLabel) && dataSet.drawLabel();
|
|
removeDataArrLen && dataSet.remove();
|
|
},
|
|
|
|
drawLabel: function () {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
chartConf = chart.config,
|
|
layers = chart.graphics,
|
|
chartComponents = chart.components,
|
|
canvasConf = chartComponents.canvas.config,
|
|
paper = chartComponents.paper,
|
|
smartLabel = chart.linkedItems.smartLabel,
|
|
style = chart.config.dataLabelStyle,
|
|
conf = dataSet.config,
|
|
JSONData = dataSet.JSONData,
|
|
setDataArr = JSONData.data,
|
|
len = setDataArr.length,
|
|
components = dataSet.components,
|
|
dataStore = components.data,
|
|
visible = dataSet.visible,
|
|
dataObj,
|
|
dataLabelsLayer,
|
|
i,
|
|
displayValue,
|
|
canvasHeight = chartConf.canvasHeight,
|
|
graphic,
|
|
textY,
|
|
textX,
|
|
yDepth = canvasConf.yDepth,
|
|
yPos,
|
|
xPos,
|
|
attr,
|
|
dataLabelContainer = dataSet.graphics.dataLabelContainer,
|
|
|
|
tlLabelContainer = dataSet.graphics.tlLabelContainer,
|
|
blLabelContainer = dataSet.graphics.blLabelContainer,
|
|
trLabelContainer = dataSet.graphics.trLabelContainer,
|
|
brLabelContainer = dataSet.graphics.brLabelContainer,
|
|
tlStyle,
|
|
trStyle,
|
|
blStyle,
|
|
brStyle,
|
|
tlCss,
|
|
trCss,
|
|
blCss,
|
|
brCss,
|
|
graphicEle,
|
|
pointW,
|
|
pointH,
|
|
pointX,
|
|
pointY,
|
|
smartTextObj,
|
|
tlLabel,
|
|
trLabel,
|
|
blLabel,
|
|
brLabel,
|
|
isTLLabel,
|
|
isTRLabel,
|
|
isBLLabel,
|
|
isBRLabel,
|
|
maxWidth,
|
|
maxHeight,
|
|
config,
|
|
setValue,
|
|
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animObj = animationObj.animObj,
|
|
dummyObj = animationObj.dummyObj,
|
|
animationDuration = animationObj.duration,
|
|
|
|
MAX_PERCENT_SPACE = 0.9,
|
|
POINT_FIVE = 0.5,
|
|
GUTTER_4 = 4;
|
|
|
|
dataLabelsLayer = layers.datalabelsGroup;
|
|
canvasHeight = canvasHeight + yDepth;
|
|
|
|
// Creating the dataLabel container group if not present and appending it to its parent.
|
|
if (!dataLabelContainer) {
|
|
dataLabelContainer = dataSet.graphics.dataLabelContainer =
|
|
paper.group(dataLabelStr, dataLabelsLayer);
|
|
if (!visible) {
|
|
dataLabelContainer.hide();
|
|
}
|
|
}
|
|
|
|
if (!tlLabelContainer) {
|
|
tlLabelContainer = dataSet.graphics.tlLabelContainer =
|
|
paper.group(tlLabelStr, dataLabelsLayer);
|
|
}
|
|
|
|
if (!blLabelContainer) {
|
|
blLabelContainer = dataSet.graphics.blLabelContainer =
|
|
paper.group(blLabelStr, dataLabelsLayer);
|
|
}
|
|
|
|
if (!trLabelContainer) {
|
|
trLabelContainer = dataSet.graphics.trLabelContainer =
|
|
paper.group(trLabelStr, dataLabelsLayer);
|
|
}
|
|
|
|
if (!brLabelContainer) {
|
|
brLabelContainer = dataSet.graphics.brLabelContainer =
|
|
paper.group(brLabelStr, dataLabelsLayer);
|
|
}
|
|
|
|
tlStyle = conf.tlLabelStyle;
|
|
trStyle = conf.trLabelStyle;
|
|
blStyle = conf.blLabelStyle;
|
|
brStyle = conf.brLabelStyle;
|
|
|
|
tlCss = {
|
|
fontFamily: tlStyle.fontFamily,
|
|
fontSize: tlStyle.fontSize,
|
|
lineHeight: tlStyle.lineHeight,
|
|
fontWeight: tlStyle.fontWeight,
|
|
fontStyle: tlStyle.fontStyle
|
|
};
|
|
trCss = {
|
|
fontFamily: trStyle.fontFamily,
|
|
fontSize: trStyle.fontSize,
|
|
lineHeight: trStyle.lineHeight,
|
|
fontWeight: trStyle.fontWeight,
|
|
fontStyle: trStyle.fontStyle
|
|
};
|
|
blCss = {
|
|
fontFamily: blStyle.fontFamily,
|
|
fontSize: blStyle.fontSize,
|
|
lineHeight: blStyle.lineHeight,
|
|
fontWeight: blStyle.fontWeight,
|
|
fontStyle: blStyle.fontStyle
|
|
};
|
|
brCss = {
|
|
fontFamily: brStyle.fontFamily,
|
|
fontSize: brStyle.fontSize,
|
|
lineHeight: brStyle.lineHeight,
|
|
fontWeight: brStyle.fontWeight,
|
|
fontStyle: brStyle.fontStyle
|
|
};
|
|
smartLabel.useEllipsesOnOverflow(chartConf.useEllipsesWhenOverflow);
|
|
smartLabel.setStyle(style);
|
|
|
|
tlLabelContainer.css(tlCss);
|
|
blLabelContainer.css(blCss);
|
|
trLabelContainer.css(trCss);
|
|
brLabelContainer.css(brCss);
|
|
|
|
for(i = 0; i < len; i++) {
|
|
dataObj = dataStore[i];
|
|
// Condition arises when user has removed data in real time update
|
|
if (dataObj === undefined) {
|
|
continue;
|
|
}
|
|
graphic = dataObj.graphics;
|
|
|
|
// Condition arises when feedData enters less number of data in a dataset compared to the other.
|
|
if (!graphic) {
|
|
continue;
|
|
}
|
|
|
|
config = dataObj && dataObj.config;
|
|
setValue = config.setValue;
|
|
|
|
if (!conf.mapByCategory && setValue === null) {
|
|
dataObj.graphics.valEle && dataObj.graphics.valEle.hide();
|
|
dataObj.graphics.tlLabel && dataObj.graphics.tlLabel.hide();
|
|
dataObj.graphics.trLabel && dataObj.graphics.trLabel.hide();
|
|
dataObj.graphics.blLabel && dataObj.graphics.blLabel.hide();
|
|
dataObj.graphics.brLabel && dataObj.graphics.brLabel.hide();
|
|
continue;
|
|
}
|
|
|
|
displayValue = config.displayValue;
|
|
|
|
graphicEle = dataObj.graphics.element;
|
|
|
|
if (!graphicEle) {
|
|
continue;
|
|
}
|
|
|
|
pointW = dataObj._width;
|
|
pointH = dataObj._height;
|
|
pointX = dataObj._xPos;
|
|
pointY = dataObj._yPos;
|
|
|
|
// Setting style for smartLabel
|
|
smartLabel.setStyle(style);
|
|
|
|
// Drawing of displayValue
|
|
if (defined(displayValue) && displayValue !== BLANK && config.showValue) {
|
|
// First render the value text
|
|
// Get the displayValue text according to the
|
|
smartTextObj = smartLabel.getSmartText(displayValue,
|
|
pointW, pointH, false);
|
|
displayValue = smartTextObj.text;
|
|
|
|
textY = pointY + (pointH * 0.5);
|
|
textX = pointX + (pointW * 0.5);
|
|
|
|
if (!dataObj.graphics.valEle) {
|
|
attr = {
|
|
text: displayValue,
|
|
title: (smartTextObj.tooltext || BLANKSTRING),
|
|
visibility: config.visible ? visibleStr : hiddenStr,
|
|
fill: style.color,
|
|
direction: config.textDirection,
|
|
x: textX,
|
|
y: textY,
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
};
|
|
dataObj.graphics.valEle = paper.text(attr, dataLabelContainer);
|
|
|
|
// dataObj.graphics.valEle.attr({
|
|
// text: displayValue,
|
|
// title: (smartTextObj.tooltext || BLANKSTRING),
|
|
// visibility: config.visible ? visibleStr : hiddenStr,
|
|
// fill: style.color,
|
|
// direction: config.textDirection,
|
|
// x: textX,
|
|
// y: textY,
|
|
// 'text-bound': [style.backgroundColor, style.borderColor,
|
|
// style.borderThickness, style.borderPadding,
|
|
// style.borderRadius, style.borderDash
|
|
// ]
|
|
// });
|
|
}
|
|
else {
|
|
|
|
dataObj.graphics.valEle.animateWith(dummyObj, animObj, {
|
|
x: textX,
|
|
y: textY
|
|
}, animationDuration, animationObj.animType);
|
|
|
|
dataObj.graphics.valEle.attr({
|
|
text: displayValue,
|
|
title: (smartTextObj.tooltext || BLANKSTRING),
|
|
visibility: config.visible ? visibleStr : hiddenStr,
|
|
fill: style.color,
|
|
direction: config.textDirection,
|
|
'text-bound': [style.backgroundColor, style.borderColor,
|
|
style.borderThickness, style.borderPadding,
|
|
style.borderRadius, style.borderDash
|
|
]
|
|
});
|
|
}
|
|
|
|
config.visible && dataObj.graphics.valEle.show();
|
|
|
|
tlLabel = config.tlLabel;
|
|
trLabel = config.trLabel;
|
|
blLabel = config.blLabel;
|
|
brLabel = config.brLabel;
|
|
|
|
isTLLabel = (defined(tlLabel) &&
|
|
tlLabel !== BLANK);
|
|
isTRLabel = (defined(trLabel) &&
|
|
trLabel !== BLANK);
|
|
isBLLabel = (defined(blLabel) &&
|
|
blLabel !== BLANK);
|
|
isBRLabel = (defined(brLabel) &&
|
|
brLabel !== BLANK);
|
|
|
|
maxWidth = pointW * (isTLLabel && isTRLabel ?
|
|
POINT_FIVE : MAX_PERCENT_SPACE);
|
|
maxHeight = (pointH - (smartTextObj && smartTextObj.height || 0)) * 0.5;
|
|
// For top labels
|
|
yPos = pointY + GUTTER_4;
|
|
|
|
if (isTLLabel) {
|
|
// Setting style for smartLabel
|
|
smartLabel.setStyle(tlStyle);
|
|
smartTextObj = smartLabel.getSmartText(tlLabel,
|
|
maxWidth, maxHeight, false);
|
|
displayValue = smartTextObj.text;
|
|
// Get the x and y position of the dataValue
|
|
xPos = pointX;
|
|
|
|
if (!dataObj.graphics.tlLabel) {
|
|
attr = {
|
|
text: displayValue,
|
|
title: (smartTextObj.tooltext || BLANKSTRING),
|
|
visibility: config.visible ? visibleStr : hiddenStr,
|
|
fill: tlStyle.color,
|
|
'text-anchor': POSITION_START,
|
|
'vertical-align': POSITION_TOP,
|
|
direction: config.textDirection,
|
|
x: xPos + GUTTER_4,
|
|
y: yPos,
|
|
'text-bound': [tlStyle.backgroundColor, tlStyle.borderColor,
|
|
tlStyle.borderThickness, tlStyle.borderPadding,
|
|
tlStyle.borderRadius, tlStyle.borderDash]
|
|
};
|
|
dataObj.graphics.tlLabel = paper.text(attr, tlLabelContainer);
|
|
|
|
// dataObj.graphics.tlLabel.attr({
|
|
// text: displayValue,
|
|
// title: (smartTextObj.tooltext || BLANKSTRING),
|
|
// visibility: config.visible ? visibleStr : hiddenStr,
|
|
// fill: tlStyle.color,
|
|
// 'text-anchor': POSITION_START,
|
|
// 'vertical-align': POSITION_TOP,
|
|
// direction: config.textDirection,
|
|
// x: xPos + GUTTER_4,
|
|
// y: yPos,
|
|
// 'text-bound': [tlStyle.backgroundColor, tlStyle.borderColor,
|
|
// tlStyle.borderThickness, tlStyle.borderPadding,
|
|
// tlStyle.borderRadius, tlStyle.borderDash]
|
|
// });
|
|
}
|
|
else {
|
|
|
|
dataObj.graphics.tlLabel.animateWith(dummyObj, animObj, {
|
|
x: xPos + GUTTER_4,
|
|
y: yPos
|
|
}, animationDuration, animationObj.animType);
|
|
|
|
dataObj.graphics.tlLabel.attr({
|
|
text: displayValue,
|
|
title: (smartTextObj.tooltext || BLANKSTRING),
|
|
visibility: config.visible ? visibleStr : hiddenStr,
|
|
fill: tlStyle.color,
|
|
'text-anchor': POSITION_START,
|
|
'vertical-align': POSITION_TOP,
|
|
direction: config.textDirection,
|
|
'text-bound': [tlStyle.backgroundColor, tlStyle.borderColor,
|
|
tlStyle.borderThickness, tlStyle.borderPadding,
|
|
tlStyle.borderRadius, tlStyle.borderDash]
|
|
});
|
|
}
|
|
config.visible && dataObj.graphics.tlLabel.show();
|
|
}
|
|
else {
|
|
if (dataObj.graphics.tlLabel) {
|
|
dataObj.graphics.tlLabel.remove();
|
|
delete dataObj.graphics.tlLabel;
|
|
}
|
|
}
|
|
|
|
if (isTRLabel) {
|
|
// Setting style for smartRabel
|
|
smartLabel.setStyle(trStyle);
|
|
smartTextObj = smartLabel.getSmartText(trLabel,
|
|
maxWidth, maxHeight, false);
|
|
displayValue = smartTextObj.text;
|
|
// Get the x and y position of the dataValue
|
|
xPos = pointX + pointW;
|
|
if (!dataObj.graphics.trLabel) {
|
|
attr = {
|
|
text: displayValue,
|
|
title: (smartTextObj.tooltext || BLANKSTRING),
|
|
visibility: config.visible ? visibleStr : hiddenStr,
|
|
fill: trStyle.color,
|
|
'text-anchor': POSITION_END,
|
|
'vertical-align': POSITION_TOP,
|
|
direction: config.textDirection,
|
|
x: xPos - GUTTER_4,
|
|
y: yPos,
|
|
'text-bound': [trStyle.backgroundColor, trStyle.borderColor,
|
|
trStyle.borderThickness, trStyle.borderPadding,
|
|
trStyle.borderRadius, trStyle.borderDash]
|
|
};
|
|
dataObj.graphics.trLabel = paper.text(attr, trLabelContainer);
|
|
|
|
// dataObj.graphics.trLabel.attr({
|
|
// text: displayValue,
|
|
// title: (smartTextObj.tooltext || BLANKSTRING),
|
|
// visibility: config.visible ? visibleStr : hiddenStr,
|
|
// fill: trStyle.color,
|
|
// 'text-anchor': POSITION_END,
|
|
// 'vertical-align': POSITION_TOP,
|
|
// direction: config.textDirection,
|
|
// x: xPos - GUTTER_4,
|
|
// y: yPos,
|
|
// 'text-bound': [trStyle.backgroundColor, trStyle.borderColor,
|
|
// trStyle.borderThickness, trStyle.borderPadding,
|
|
// trStyle.borderRadius, trStyle.borderDash]
|
|
// });
|
|
}
|
|
else {
|
|
|
|
dataObj.graphics.trLabel.animateWith(dummyObj, animObj, {
|
|
x: xPos - GUTTER_4,
|
|
y: yPos
|
|
}, animationDuration, animationObj.animType);
|
|
|
|
dataObj.graphics.trLabel.attr({
|
|
text: displayValue,
|
|
title: (smartTextObj.tooltext || BLANKSTRING),
|
|
visibility: config.visible ? visibleStr : hiddenStr,
|
|
fill: trStyle.color,
|
|
'text-anchor': POSITION_END,
|
|
'vertical-align': POSITION_TOP,
|
|
direction: config.textDirection,
|
|
'text-bound': [trStyle.backgroundColor, trStyle.borderColor,
|
|
trStyle.borderThickness, trStyle.borderPadding,
|
|
trStyle.borderRadius, trStyle.borderDash]
|
|
});
|
|
}
|
|
config.visible && dataObj.graphics.trLabel.show();
|
|
}
|
|
else {
|
|
if (dataObj.graphics.trLabel) {
|
|
dataObj.graphics.trLabel.remove();
|
|
delete dataObj.graphics.trLabel;
|
|
}
|
|
}
|
|
|
|
// For top labels
|
|
yPos = (pointY + pointH) - GUTTER_4;
|
|
|
|
if (isBLLabel) {
|
|
// Setting style for smartRabel
|
|
smartLabel.setStyle(blStyle);
|
|
smartTextObj = smartLabel.getSmartText(blLabel,
|
|
maxWidth, maxHeight, false);
|
|
displayValue = smartTextObj.text;
|
|
// Get the x and y position of the dataValue
|
|
xPos = pointX;
|
|
if (!dataObj.graphics.blLabel) {
|
|
attr = {
|
|
text: displayValue,
|
|
title: (smartTextObj.tooltext || BLANKSTRING),
|
|
visibility: config.visible ? visibleStr : hiddenStr,
|
|
fill: blStyle.color,
|
|
'text-anchor': POSITION_START,
|
|
'vertical-align': POSITION_BOTTOM,
|
|
direction: config.textDirection,
|
|
x: xPos + GUTTER_4,
|
|
y: yPos,
|
|
'text-bound': [blStyle.backgroundColor, blStyle.borderColor,
|
|
blStyle.borderThickness, blStyle.borderPadding,
|
|
blStyle.borderRadius, blStyle.borderDash]
|
|
};
|
|
dataObj.graphics.blLabel = paper.text(attr, blLabelContainer);
|
|
|
|
// dataObj.graphics.blLabel.attr({
|
|
// text: displayValue,
|
|
// title: (smartTextObj.tooltext || BLANKSTRING),
|
|
// visibility: config.visible ? visibleStr : hiddenStr,
|
|
// fill: blStyle.color,
|
|
// 'text-anchor': POSITION_START,
|
|
// 'vertical-align': POSITION_BOTTOM,
|
|
// direction: config.textDirection,
|
|
// x: xPos + GUTTER_4,
|
|
// y: yPos,
|
|
// 'text-bound': [blStyle.backgroundColor, blStyle.borderColor,
|
|
// blStyle.borderThickness, blStyle.borderPadding,
|
|
// blStyle.borderRadius, blStyle.borderDash]
|
|
// });
|
|
}
|
|
else {
|
|
|
|
dataObj.graphics.blLabel.animateWith(dummyObj, animObj, {
|
|
x: xPos + GUTTER_4,
|
|
y: yPos
|
|
}, animationDuration, animationObj.animType);
|
|
|
|
dataObj.graphics.blLabel.attr({
|
|
text: displayValue,
|
|
title: (smartTextObj.tooltext || BLANKSTRING),
|
|
visibility: config.visible ? visibleStr : hiddenStr,
|
|
fill: blStyle.color,
|
|
'text-anchor': POSITION_START,
|
|
'vertical-align': POSITION_BOTTOM,
|
|
direction: config.textDirection,
|
|
'text-bound': [blStyle.backgroundColor, blStyle.borderColor,
|
|
blStyle.borderThickness, blStyle.borderPadding,
|
|
blStyle.borderRadius, blStyle.borderDash]
|
|
});
|
|
}
|
|
config.visible && dataObj.graphics.blLabel.show();
|
|
}
|
|
else {
|
|
if (dataObj.graphics.blLabel) {
|
|
dataObj.graphics.blLabel.remove();
|
|
delete dataObj.graphics.blLabel;
|
|
}
|
|
}
|
|
|
|
if (isBRLabel) {
|
|
// Setting style for smartRabel
|
|
smartLabel.setStyle(blStyle);
|
|
smartTextObj = smartLabel.getSmartText(brLabel,
|
|
maxWidth, maxHeight, false);
|
|
displayValue = smartTextObj.text;
|
|
// Get the x and y position of the dataValue
|
|
xPos = pointX + pointW - GUTTER_4;
|
|
if (!dataObj.graphics.brLabel) {
|
|
attr = {
|
|
text: displayValue,
|
|
title: (smartTextObj.tooltext || BLANKSTRING),
|
|
visibility: config.visible ? visibleStr : hiddenStr,
|
|
fill: brStyle.color,
|
|
'text-anchor': POSITION_END,
|
|
'vertical-align': POSITION_BOTTOM,
|
|
direction: config.textDirection,
|
|
x: xPos,
|
|
y: yPos,
|
|
'text-bound': [brStyle.backgroundColor, brStyle.borderColor,
|
|
brStyle.borderThickness, brStyle.borderPadding,
|
|
brStyle.borderRadius, brStyle.borderDash]
|
|
};
|
|
dataObj.graphics.brLabel = paper.text(attr, brLabelContainer);
|
|
|
|
// dataObj.graphics.brLabel.attr({
|
|
// text: displayValue,
|
|
// title: (smartTextObj.tooltext || BLANKSTRING),
|
|
// visibility: config.visible ? visibleStr : hiddenStr,
|
|
// fill: brStyle.color,
|
|
// 'text-anchor': POSITION_END,
|
|
// 'vertical-align': POSITION_BOTTOM,
|
|
// direction: config.textDirection,
|
|
// x: xPos,
|
|
// y: yPos,
|
|
// 'text-bound': [brStyle.backgroundColor, brStyle.borderColor,
|
|
// brStyle.borderThickness, brStyle.borderPadding,
|
|
// brStyle.borderRadius, brStyle.borderDash]
|
|
// });
|
|
}
|
|
else {
|
|
|
|
dataObj.graphics.brLabel.animateWith(dummyObj, animObj, {
|
|
x: xPos,
|
|
y: yPos
|
|
}, animationDuration, animationObj.animType);
|
|
|
|
dataObj.graphics.brLabel.attr({
|
|
text: displayValue,
|
|
title: (smartTextObj.tooltext || BLANKSTRING),
|
|
visibility: config.visible ? visibleStr : hiddenStr,
|
|
fill: brStyle.color,
|
|
'text-anchor': POSITION_END,
|
|
'vertical-align': POSITION_BOTTOM,
|
|
direction: config.textDirection,
|
|
'text-bound': [brStyle.backgroundColor, brStyle.borderColor,
|
|
brStyle.borderThickness, brStyle.borderPadding,
|
|
brStyle.borderRadius, brStyle.borderDash]
|
|
});
|
|
}
|
|
config.visible && dataObj.graphics.brLabel.show();
|
|
}
|
|
else {
|
|
if (dataObj.graphics.brLabel) {
|
|
dataObj.graphics.brLabel.remove();
|
|
delete dataObj.graphics.brLabel;
|
|
}
|
|
}
|
|
|
|
}
|
|
else {
|
|
|
|
if (dataObj.graphics.valEle) {
|
|
dataObj.graphics.valEle.remove();
|
|
delete dataObj.graphics.valEle;
|
|
}
|
|
|
|
if (dataObj.graphics.tlLabel) {
|
|
dataObj.graphics.tlLabel.remove();
|
|
delete dataObj.graphics.tlLabel;
|
|
}
|
|
|
|
if (dataObj.graphics.trLabel) {
|
|
dataObj.graphics.trLabel.remove();
|
|
delete dataObj.graphics.trLabel;
|
|
}
|
|
|
|
if (dataObj.graphics.blLabel) {
|
|
dataObj.graphics.blLabel.remove();
|
|
delete dataObj.graphics.blLabel;
|
|
}
|
|
|
|
if (dataObj.graphics.brLabel) {
|
|
dataObj.graphics.brLabel.remove();
|
|
delete dataObj.graphics.brLabel;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
dataSet.labelDrawn = true;
|
|
},
|
|
|
|
// Function to remove a data from a dataset during real time update.
|
|
remove : function () {
|
|
var dataSet = this,
|
|
components = dataSet.components,
|
|
removeDataArr = components.removeDataArr,
|
|
pool = components.pool || (components.pool = {
|
|
element :[],
|
|
hotElement : [],
|
|
label : []
|
|
}),
|
|
len = removeDataArr.length,
|
|
removeData,
|
|
maxminFlag = dataSet.maxminFlag,
|
|
ele,
|
|
graphics,
|
|
i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
removeData = removeDataArr[0];
|
|
removeDataArr.splice(0,1);
|
|
// In case of non existing data plot continue;
|
|
if (!removeData || !removeData.graphics) {
|
|
continue;
|
|
}
|
|
|
|
graphics = removeData.graphics;
|
|
for (ele in graphics) {
|
|
// Stopping any previous animation.
|
|
graphics[ele].stop();
|
|
graphics[ele].hide();
|
|
}
|
|
|
|
// Storing the graphic elements for reuse.
|
|
removeData.graphics.element && (pool.element = pool.element.concat(removeData.graphics.element));
|
|
removeData.graphics.hotElement && (pool.hotElement = pool.hotElement.concat(removeData.graphics.
|
|
hotElement));
|
|
removeData.graphics.label && (pool.label = pool.label.concat(removeData.graphics.label));
|
|
}
|
|
components.pool = pool;
|
|
maxminFlag && dataSet.setMaxMin();
|
|
},
|
|
|
|
getEventArgs: function (legendItem) {
|
|
var dataset = legendItem.dataset,
|
|
config = dataset.config || {},
|
|
label = config.label,
|
|
index = legendItem.index,
|
|
eventArgs = {
|
|
datasetName: label,
|
|
datasetIndex: index,
|
|
visible: config.visible
|
|
};
|
|
return eventArgs;
|
|
}
|
|
|
|
},'Column']);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-kagi',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
win = global.window,
|
|
Image = win.Image,
|
|
|
|
//strings
|
|
preDefStr = lib.preDefStr,
|
|
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
dataLabelStr = preDefStr.dataLabelStr,
|
|
hiddenStr = preDefStr.hiddenStr,
|
|
ROUND = preDefStr.ROUND,
|
|
POSITION_TOP = preDefStr.POSITION_TOP,
|
|
POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
|
|
|
|
LINE = preDefStr.line,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
pluckNumber = lib.pluckNumber,
|
|
toRaphaelColor = lib.toRaphaelColor,
|
|
UNDEFINED,
|
|
EVENTARGS = 'eventArgs',
|
|
NONE = 'none',
|
|
SETROLLOVERATTR = 'setRolloverAttr',
|
|
SETROLLOUTATTR = 'setRolloutAttr',
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
|
|
schedular = lib.schedular,
|
|
each = lib.each,
|
|
defined = function(obj) {
|
|
return obj !== UNDEFINED && obj !== null;
|
|
},
|
|
TOUCH_THRESHOLD_PIXELS = lib.TOUCH_THRESHOLD_PIXELS,
|
|
CLICK_THRESHOLD_PIXELS = lib.CLICK_THRESHOLD_PIXELS,
|
|
M = 'M',
|
|
H = 'H',
|
|
V = 'V',
|
|
POSITION_MIDDLE = 'middle',
|
|
math = Math,
|
|
mathRound = math.round,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
mathAbs = math.abs,
|
|
hasTouch = lib.hasTouch,
|
|
// hot/tracker threshold in pixels
|
|
HTP = hasTouch ? TOUCH_THRESHOLD_PIXELS :
|
|
CLICK_THRESHOLD_PIXELS,
|
|
// POSITION_CENTER = lib.POSITION_CENTER,
|
|
POSITION_RIGHT = lib.POSITION_RIGHT;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET, 'Kagi', {
|
|
type: 'kagi',
|
|
_parseShadowOptions: function () {
|
|
var dataSet = this,
|
|
chart = dataSet.chart,
|
|
conf = dataSet.config,
|
|
chartAttr = chart.jsonData.chart;
|
|
return {
|
|
opacity: pluckNumber(chartAttr.showshadow, 1) ? conf.alpha/100 : 0
|
|
};
|
|
},
|
|
configure: function () {
|
|
var dataSetComponents,
|
|
datasetObj = this,
|
|
removeDataArr,
|
|
chart = datasetObj.chart,
|
|
canvasWidth = chart.config.canvasWidth,
|
|
xAxis = chart.components.xAxis[0],
|
|
temp = 0,
|
|
data,
|
|
catArr = [],
|
|
series,
|
|
JSONData,
|
|
FCChartObj,
|
|
valueMax,
|
|
valueMin,
|
|
isRallyInitialised,
|
|
shiftCounter,
|
|
vLinePosition,
|
|
reversalValue,
|
|
reversalPercentage,
|
|
lastFcDataObj,
|
|
rallyDashLen,
|
|
rallyDashGap,
|
|
declineDashLen,
|
|
declineDashGap,
|
|
getDashStyle = lib.getDashStyle,
|
|
lastPlotValue,
|
|
setShowLabel,
|
|
length,
|
|
index,
|
|
fcIndex,
|
|
fcDataObj,
|
|
lastShift,
|
|
prevDataObj,
|
|
plotValue,
|
|
dataObj,
|
|
nextDataValue,
|
|
valueDifference,
|
|
dataValue,
|
|
isRally,
|
|
lastLow,
|
|
lastHigh,
|
|
isMovingUp,
|
|
isShift,
|
|
checkValue,
|
|
t,
|
|
count = 0,
|
|
vAlign,
|
|
effectiveCanvasWidth,
|
|
maxHShiftPercent,
|
|
canvasPadding,
|
|
align;
|
|
//call the base class i.e. line dataset configure().
|
|
datasetObj.__base__.configure.call(datasetObj);
|
|
dataSetComponents = datasetObj.components;
|
|
data = dataSetComponents.data;
|
|
series = datasetObj.config;
|
|
JSONData = datasetObj.JSONData.data;
|
|
FCChartObj = chart.jsonData.chart;
|
|
valueMax = series.maxValue;
|
|
valueMin = series.minValue;
|
|
removeDataArr = dataSetComponents.removeDataArr || (dataSetComponents.removeDataArr = []),
|
|
// First vertical point for shift is yet to be obtained
|
|
isRallyInitialised = false;
|
|
// Initialised to one to avoid zero dividing the width of the canvas
|
|
// (as the case may be) to get the xShiftLength
|
|
shiftCounter = 0;
|
|
vLinePosition = 0.5;
|
|
// The value which determines whether to make a horizontal shift
|
|
// to deal with the next point
|
|
reversalValue = pluckNumber(FCChartObj.reversalvalue, -1);
|
|
// The percentage of the range of values, which determines whether
|
|
// to make a horizontal shift to deal with the next point
|
|
reversalPercentage = pluckNumber(FCChartObj.reversalpercentage, 5);
|
|
lastFcDataObj = {};
|
|
|
|
for (index = 0; index < data.length; index += 1) {
|
|
data[index].config.__nullCount = count;
|
|
if (data[index].config.setValue === null) {
|
|
removeDataArr.push(data.splice(index, 1)[0]);
|
|
count ++;
|
|
index -= 1;
|
|
}
|
|
}
|
|
if (data.length) {
|
|
// Color of line denoting rally
|
|
series.rallyColor = pluck(FCChartObj.rallycolor, 'FF0000');
|
|
series.rallyAlpha = pluckNumber(FCChartObj.rallyalpha,
|
|
FCChartObj.linealpha, 100);
|
|
//color of line denoting decline
|
|
series.declineColor = pluck(FCChartObj.declinecolor, '0000FF');
|
|
series.declineAlpha = pluckNumber(FCChartObj.declinealpha,
|
|
FCChartObj.linealpha, 100);
|
|
//Default canvasPadding is 15.
|
|
canvasPadding = series.canvasPadding = pluckNumber(FCChartObj.canvaspadding, 15);
|
|
// The maximum horizontal shift in percentage of the
|
|
// available canvas width
|
|
maxHShiftPercent = series.maxHShiftPercent = pluckNumber(FCChartObj.maxhshiftpercent, 10);
|
|
effectiveCanvasWidth = canvasWidth - canvasPadding * 2;
|
|
// Thickness of line denoting rally
|
|
series.rallyThickness = pluckNumber(FCChartObj.rallythickness,
|
|
FCChartObj.linethickness, 2);
|
|
// length of the dash
|
|
rallyDashLen = pluckNumber(FCChartObj.rallydashlen,
|
|
FCChartObj.linedashlen, 5);
|
|
// distance between dash
|
|
rallyDashGap = pluckNumber(FCChartObj.rallydashgap,
|
|
FCChartObj.linedashgap, 4);
|
|
|
|
// Thickness of line denoting decline
|
|
series.declineThickness = pluckNumber(FCChartObj.declinethickness,
|
|
FCChartObj.linethickness, 2);
|
|
// length of the dash
|
|
declineDashLen = pluckNumber(FCChartObj.declinedashlen,
|
|
FCChartObj.linedashlen, 5);
|
|
// distance between dash
|
|
declineDashGap = pluckNumber(FCChartObj.declinedashgap,
|
|
FCChartObj.linedashgap, 4);
|
|
|
|
series.lineDashed = {
|
|
'true': pluckNumber(FCChartObj.rallydashed,
|
|
FCChartObj.linedashed, 0),
|
|
'false': pluckNumber(FCChartObj.declinedashed,
|
|
FCChartObj.linedashed, 0)
|
|
};
|
|
|
|
// Storing dashStyle in series to be use while drawing graph and
|
|
series.rallyDashed = pluckNumber(FCChartObj.rallydashed,
|
|
FCChartObj.linedashed, 0) ? getDashStyle(rallyDashLen, rallyDashGap,
|
|
series.rallyThickness) : NONE;
|
|
series.declineDashed = pluckNumber(FCChartObj.declinedashed,
|
|
FCChartObj.linedashed, 0) ? getDashStyle(declineDashLen, declineDashGap,
|
|
series.declineThickness) : NONE;
|
|
|
|
//canvasPadding to be use by Kagi chart Drawing
|
|
series.canvasPadding = pluckNumber(FCChartObj.canvaspadding,
|
|
this.canvasPadding, 15);
|
|
|
|
//setting the reversal value
|
|
reversalValue = (reversalValue > 0) ?
|
|
reversalValue : reversalPercentage * (valueMax - valueMin) / 100;
|
|
|
|
// Initialised by the first data value
|
|
lastPlotValue = data[0].config.setValue;
|
|
// Local function to set anchor and value visibility of
|
|
// unwanted points, after the first point is found to draw
|
|
// vertical kagi line
|
|
setShowLabel = function(id, _isRally) {
|
|
// Initial data value
|
|
var dataXValue, r = 1,
|
|
data1Value = data[0].config.setValue;
|
|
// Looping to check for unwanted points
|
|
while (r < id) {
|
|
// Value of point under check
|
|
dataXValue = data[r].config.setValue;
|
|
// If current trend is rally
|
|
if (_isRally) {
|
|
if (dataXValue <= data1Value) {
|
|
data[r].config.isDefined = false;
|
|
}
|
|
// Else current trend is decline
|
|
} else {
|
|
if (dataXValue >= data1Value) {
|
|
data[r].config.isDefined = false;
|
|
}
|
|
}
|
|
r += 1;
|
|
}
|
|
// Setting alignment of value for the first data
|
|
data[0].config.vAlign = (_isRally) ? POSITION_BOTTOM :
|
|
POSITION_TOP;
|
|
data[0].config.align = 'center';
|
|
};
|
|
|
|
length = JSONData.length;
|
|
//iterating to set values of properties in data for each respective
|
|
//point (main algorithm of KagiChart)
|
|
//loop counter starts from 2 since data for plot 1 is unique
|
|
for (index = 0, fcIndex = 0; fcIndex < length; fcIndex += 1, index += 1) {
|
|
fcDataObj = JSONData[fcIndex];
|
|
// Calculation of vLine based on hShift.
|
|
if (fcDataObj && fcDataObj.vline) {
|
|
continue;
|
|
}
|
|
dataObj = data[index] && data[index].config;
|
|
lastFcDataObj = JSONData[fcIndex];
|
|
// Special handling for vLines
|
|
if (lastShift) {
|
|
lastShift = false;
|
|
vLinePosition += 0.5;
|
|
}
|
|
dataObj && (dataObj.isDefined = true);
|
|
if (!(fcDataObj.tooltext || datasetObj.JSONData.plottooltext || FCChartObj.plottooltext)){
|
|
dataObj && (dataObj.toolText += dataObj.displayValue);
|
|
}
|
|
if (index && dataObj) {
|
|
dataObj.isShift = undefined;
|
|
|
|
prevDataObj = data[index - 1].config;
|
|
dataObj.vAlign = POSITION_MIDDLE;
|
|
dataObj.align = POSITION_RIGHT;
|
|
dataObj.showLabel = false;
|
|
//initialised to null each time
|
|
plotValue = null;
|
|
//data value of plot under current loop
|
|
dataValue = dataObj.setValue;
|
|
//data value of previous plot
|
|
//lastDataValue = data[i-1].y;
|
|
//data value of next plot
|
|
nextDataValue = data[index + 1] && data[index + 1].config.setValue;
|
|
valueDifference = mathAbs(lastPlotValue - dataValue);
|
|
|
|
//if current plot is yet render the trend,then care is taken
|
|
//to make few initial assumptions as algorithm starts with it
|
|
if (!isRallyInitialised) {
|
|
//if current plot is higher than the last plotted one
|
|
//(first data) by significant amount
|
|
if (dataValue > lastPlotValue && valueDifference > reversalValue) {
|
|
//is assumed to be true
|
|
isRally = true;
|
|
//value of last low point of swing (assumed)
|
|
lastLow = lastPlotValue;
|
|
//none assumed
|
|
lastHigh = null;
|
|
//kagi rising
|
|
isMovingUp = true;
|
|
//first vertical point for shift is obtained
|
|
isRallyInitialised = true;
|
|
//call of local function to set visibility false for
|
|
//anchors and values of unwanted points
|
|
setShowLabel(index, isRally);
|
|
//if current plot is lower than the last plotted one
|
|
//(first data) by significant amount
|
|
} else if (dataValue < lastPlotValue && valueDifference > reversalValue) {
|
|
//is assumed to be false
|
|
isRally = false;
|
|
//none assumed
|
|
lastLow = null;
|
|
//value of last high point of swing (assumed)
|
|
lastHigh = lastPlotValue;
|
|
//kagi falling
|
|
isMovingUp = false;
|
|
//first vertical point for shift is obtained
|
|
isRallyInitialised = true;
|
|
//call of local function to set visibility false for
|
|
//anchors and values of unwanted points
|
|
setShowLabel(index, isRally);
|
|
// else, point under loop is not significant to
|
|
// draw the first vertical kagi line to
|
|
} else {
|
|
//is set to null
|
|
isRally = null;
|
|
//vertical shifting direction is set to null
|
|
isMovingUp = null;
|
|
//first vertical point for shift is yet to be obtained
|
|
isRallyInitialised = false;
|
|
}
|
|
//trend property for plot 1 is set
|
|
if (defined(prevDataObj)) {
|
|
prevDataObj.isRally = isRally;
|
|
}
|
|
if (isRally != null) {
|
|
//to get the initial horizontal line in trend color
|
|
//(in case data[1].value = data[2].value=... so on or not)
|
|
data[0].config.isRally = isRally;
|
|
}
|
|
//else, for plot 3 and above, only trend is evaluated
|
|
} else {
|
|
//setting trends by concept of Kagi Chart
|
|
if (dataValue < lastLow && isRally) {
|
|
isRally = false;
|
|
} else if (dataValue > lastHigh && !isRally) {
|
|
isRally = true;
|
|
}
|
|
//else isRally remains unchanged
|
|
}
|
|
|
|
// Setting in data for the plot
|
|
dataObj.isRally = isRally;
|
|
// To check for having horizontal shift or not,
|
|
// we need to use the pertinent value
|
|
if ((isMovingUp && dataValue < lastPlotValue) ||
|
|
(!isMovingUp && dataValue > lastPlotValue)) {
|
|
plotValue = lastPlotValue;
|
|
}
|
|
// To find if there is a horizontal shift associated
|
|
// with this plot
|
|
checkValue = (plotValue) ? plotValue : dataValue;
|
|
valueDifference = mathAbs(checkValue - nextDataValue);
|
|
//if the line is static till now
|
|
if (isMovingUp == null) {
|
|
isShift = null;
|
|
//if the line is rising
|
|
} else if (isMovingUp) {
|
|
isShift = (checkValue > nextDataValue &&
|
|
valueDifference >= reversalValue);
|
|
//else if the line is falling
|
|
} else {
|
|
isShift = (checkValue < nextDataValue &&
|
|
valueDifference >= reversalValue);
|
|
}
|
|
|
|
//To get the last extremes preceding the current point
|
|
//and setting the vertical/horizontal
|
|
//alignment of the value to be shown for it.
|
|
if (prevDataObj && prevDataObj.isShift) {
|
|
if (isMovingUp) {
|
|
lastLow = lastPlotValue;
|
|
vAlign = POSITION_BOTTOM;
|
|
} else if (!isMovingUp) {
|
|
lastHigh = lastPlotValue;
|
|
vAlign = POSITION_TOP;
|
|
}
|
|
align = 'center';
|
|
//looping to get the actual plot corresponding to the
|
|
//maxima/minima and setting label properties for the same
|
|
for (t = index; t > 1; t -= 1) {
|
|
if (data[t].y == lastPlotValue) {
|
|
data[t].vAlign = vAlign;
|
|
data[t].align = align;
|
|
data[t].showLabel = true;
|
|
//extreme obtained and thus stop looping
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//if there is a horizontal shift, then
|
|
if (isShift) {
|
|
//updating counter to have to total number of horizontal
|
|
// shifts in the total plot.This is vital for calculation
|
|
//of the length of each horizontal shifts.
|
|
shiftCounter += 1;
|
|
vLinePosition += 0.5;
|
|
lastShift = true;
|
|
//updating the flag by reversing the boolean
|
|
// value of the flag itself
|
|
isMovingUp = !isMovingUp;
|
|
//setting in data for the plot, to be used for
|
|
//drawing the graph
|
|
dataObj.isShift = true;
|
|
//updating last plotting value
|
|
lastPlotValue = checkValue;
|
|
catArr.push(JSONData[index + dataObj.__nullCount]);
|
|
temp = datasetObj._appendCategory(temp, index, catArr, 0);
|
|
} else if ((isMovingUp && dataValue > lastPlotValue) ||
|
|
(!isMovingUp && dataValue < lastPlotValue)) {
|
|
//updating last plotting value
|
|
lastPlotValue = dataValue;
|
|
//if cuurent data value is to be skipped for plotting
|
|
} else {
|
|
//setting the value to be plotted
|
|
//(virtually drawing pen stays still due to this)
|
|
plotValue = lastPlotValue;
|
|
}
|
|
//plotValue assigned is either defined or set to null
|
|
dataObj.plotValue = plotValue;
|
|
//few local variables are bundled together in an object to be
|
|
//used later-on to work around a Catch-22 problem
|
|
dataObj.objParams = {
|
|
isRally: isRally,
|
|
lastHigh: lastHigh,
|
|
lastLow: lastLow,
|
|
isRallyInitialised: isRallyInitialised
|
|
};
|
|
}
|
|
}
|
|
// insert if any remaining categories to be appended.
|
|
datasetObj._appendCategory(temp, index, catArr, 1);
|
|
// insert the categories before setting the final category.
|
|
catArr.push(fcDataObj);
|
|
xAxis.setCategory(catArr);
|
|
series.shiftCount = shiftCounter + 1;
|
|
}
|
|
},
|
|
_appendCategory: function (temp, index, catArr, lineposition) {
|
|
var i,
|
|
catObj,
|
|
catData,
|
|
refIndex,
|
|
datasetObj = this,
|
|
catOnlyData = datasetObj.JSONData.catData;
|
|
if (temp < catOnlyData.length) {
|
|
for (i = temp; i < catOnlyData.length; i += 1, temp = i){
|
|
catObj = catOnlyData[i];
|
|
catData = catObj.data;
|
|
refIndex = catObj.index - (i + 1);
|
|
if (refIndex < index) {
|
|
catData.lineposition = pluckNumber(catData.lineposition, lineposition);
|
|
}
|
|
else if (refIndex > index){
|
|
break;
|
|
}
|
|
catArr.push(catData);
|
|
}
|
|
}
|
|
return temp;
|
|
},
|
|
manageSpace: function () {},
|
|
_getHoveredPlot: function (chartX, chartY) {
|
|
var dataset = this,
|
|
chart = dataset.chart,
|
|
chartConfig = chart.config,
|
|
xAxis = chart.components.xAxis[0],
|
|
conf = dataset.config,
|
|
trackIndex = conf.trackIndex,
|
|
dataStore = dataset.components.data,
|
|
canvas = chart.components.canvas,
|
|
canvasConfig = canvas.config,
|
|
canvasPadding = Math.max(canvasConfig.canvasPaddingLeft, canvasConfig.canvasPadding),
|
|
canvasLeft = chartConfig.canvasLeft,
|
|
axisX = chartX - canvasLeft - canvasPadding,
|
|
i,
|
|
j,
|
|
index,
|
|
returnValue,
|
|
xMin,
|
|
xMax,
|
|
pointObjs,
|
|
len;
|
|
|
|
xMin = Math.floor(Math.max(xAxis.getValue(axisX - conf.maxRadius)));
|
|
xMax = Math.ceil(Math.min(xAxis.getValue(axisX + conf.maxRadius)));
|
|
|
|
for(j = xMax; j >= xMin; j--){
|
|
pointObjs = trackIndex[j];
|
|
len = pointObjs && pointObjs.length;
|
|
// search point objects under current value
|
|
for(i = len; i >= 0; i--){
|
|
index = pointObjs[i];
|
|
returnValue = dataset.isWithinShape(dataStore[index], index, chartX, chartY);
|
|
if (returnValue) {
|
|
return returnValue;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
draw: function () {// retrive requitrd objects
|
|
var i,
|
|
trackerConfig,
|
|
graphics,
|
|
dataSet = this,
|
|
datasetGraphics = dataSet.graphics,
|
|
JSONData = dataSet.JSONData,
|
|
chart = dataSet.chart,
|
|
jobList = chart.getJobList(),
|
|
chartComponents = chart.components,
|
|
chartConfig = chart.config,
|
|
conf = dataSet.config,
|
|
//temp hardcoded.
|
|
datasetIndex = 0,
|
|
trackIndex = conf.trackIndex = {},
|
|
dataSetComponents = dataSet.components,
|
|
setDataArr = dataSetComponents.data,
|
|
removeDataArr = dataSetComponents.removeDataArr,
|
|
removeDataArrLen = removeDataArr && removeDataArr.length,
|
|
categories = setDataArr,
|
|
catLen = categories && categories.length,
|
|
dataSetLen = setDataArr && setDataArr.length,
|
|
len,
|
|
paper = chartComponents.paper,
|
|
xAxis = chartComponents.xAxis[0],
|
|
xPos,
|
|
yPos,
|
|
layers = chart.graphics,
|
|
dataLabelsLayer = layers.datalabelsGroup,
|
|
toolText,
|
|
setElement,
|
|
setLink,
|
|
setValue,
|
|
eventArgs,
|
|
displayValue,
|
|
dataStore = dataSet.components.data,
|
|
dataObj,
|
|
setRolloutAttr,
|
|
setRolloverAttr,
|
|
container = datasetGraphics.container,
|
|
anchorRadius,
|
|
group = layers.datasetGroup,
|
|
hoverEffects,
|
|
shadow = conf.shadow,
|
|
anchorShadow,
|
|
dataLabelContainer = datasetGraphics.dataLabelContainer,
|
|
anchorProps = {},
|
|
imgRef,
|
|
symbol,
|
|
config,
|
|
showValue,
|
|
isNewElem = false,
|
|
// animCompleteFn = chart.getAnimationCompleteFn(),
|
|
/*
|
|
Called when the initial animation compeletes
|
|
for showing the dataset
|
|
*/
|
|
initAnimCallBack = function () {
|
|
container.lineGroup.attr({
|
|
'clip-rect': null
|
|
});
|
|
container.lineShadowGroup.show();
|
|
container.anchorShadowGroup.show();
|
|
container.anchorGroup.show();
|
|
dataLabelContainer && dataLabelContainer.show();
|
|
// animCompleteFn();
|
|
},
|
|
animFlag = true,
|
|
xAxisZeroPos = xAxis.getAxisPosition(0),
|
|
xAxisFirstPos = xAxis.getAxisPosition(1),
|
|
pointDistance = xAxisFirstPos - xAxisZeroPos,
|
|
totalCanvasWidth,
|
|
clipCanvas = {
|
|
'clip-rect': [ mathMax(0, chartConfig.canvasLeft), mathMax(0, chartConfig.canvasTop),
|
|
mathMax(1, chartConfig.canvasWidth), mathMax(1, chartConfig.canvasHeight)]
|
|
},
|
|
clipCanvasInit = {
|
|
'clip-rect': [ mathMax(0, chartConfig.canvasLeft), mathMax(0, chartConfig.canvasTop), 1,
|
|
mathMax(1, chartConfig.canvasHeight)]
|
|
},
|
|
initialAnimation = false,
|
|
rallyThickness = conf.rallyThickness,
|
|
declineThickness = conf.declineThickness,
|
|
rallyAttr = {
|
|
stroke: toRaphaelColor({
|
|
color: conf.rallyColor,
|
|
alpha: conf.rallyAlpha
|
|
}),
|
|
'stroke-linecap': ROUND,
|
|
'stroke-linejoin': ROUND,
|
|
'stroke-width': rallyThickness,
|
|
'stroke-dasharray': conf.rallyDashed
|
|
},
|
|
declineAttr = {
|
|
stroke: toRaphaelColor({
|
|
color: conf.declineColor,
|
|
alpha: conf.declineAlpha
|
|
}),
|
|
'stroke-linecap': ROUND,
|
|
'stroke-linejoin': ROUND,
|
|
'stroke-width': declineThickness,
|
|
'stroke-dasharray': conf.declineDashed
|
|
},
|
|
thickness = {
|
|
'true': rallyThickness,
|
|
'false': declineThickness
|
|
},
|
|
rallyPath = [],
|
|
declinePath = [],
|
|
rallyElem = datasetGraphics.rallyElem,
|
|
declineElem = datasetGraphics.declineElem,
|
|
visible = dataSet.visible,
|
|
xValue = 0,
|
|
plotX = xAxis.getAxisPosition(xValue),
|
|
isRally = setDataArr[0] && !! setDataArr[0].isRally,
|
|
nextPointIsRally,
|
|
startX = xAxisZeroPos - (pointDistance / 2),
|
|
plotY,
|
|
setShadow,
|
|
crispY,
|
|
nextPoint,
|
|
path,
|
|
lineElement = datasetGraphics.lineElement,
|
|
pool = dataSet.pool || (dataSet.pool = {}),
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animationDuration = animationObj.duration || 0,
|
|
mainElm = animationObj.dummyObj,
|
|
animObj = animationObj.animObj,
|
|
noOfImages = 0,
|
|
animType = animationObj.animType,
|
|
imageElement;
|
|
|
|
conf.imagesLoaded = 0;
|
|
removeDataArrLen && dataSet.remove();
|
|
// save the world if no valid data is there.
|
|
if (!setDataArr.length) {
|
|
rallyElem && rallyElem.hide();
|
|
declineElem && declineElem.hide();
|
|
return;
|
|
}
|
|
else {
|
|
rallyElem && rallyElem.show();
|
|
declineElem && declineElem.show();
|
|
}
|
|
// Create dataset container if not created
|
|
if (!container) {
|
|
container = dataSet.graphics.container = {
|
|
lineShadowGroup: paper.group('connector-shadow', group).attr(clipCanvasInit),
|
|
anchorShadowGroup: paper.group('anchor-shadow', group).attr(clipCanvasInit),
|
|
lineGroup: paper.group(LINE, group).attr(clipCanvasInit),
|
|
anchorGroup: paper.group('anchors', group).attr(clipCanvasInit)
|
|
};
|
|
if (!visible) {
|
|
container.lineShadowGroup.hide();
|
|
container.anchorShadowGroup.hide();
|
|
container.lineGroup.hide();
|
|
container.anchorGroup.hide();
|
|
}
|
|
|
|
}
|
|
|
|
if (!dataStore) {
|
|
dataStore = dataSet.components.data = [];
|
|
}
|
|
|
|
|
|
if (!dataLabelContainer) {
|
|
dataLabelContainer = dataSet.graphics.dataLabelContainer = dataSet.graphics.dataLabelContainer ||
|
|
paper.group(dataLabelStr, dataLabelsLayer);
|
|
if (!visible) {
|
|
dataLabelContainer.hide();
|
|
}
|
|
}
|
|
len = mathMin(catLen, dataSetLen);
|
|
/* Calculating total canvas width
|
|
Required for scroll charts
|
|
*/
|
|
totalCanvasWidth = pointDistance * len;
|
|
|
|
//draw graph
|
|
// Special situation for first null data.
|
|
if (!setDataArr[0].config.setValue) {
|
|
for (i = 1; i < dataSetLen; i += 1) {
|
|
setValue = setDataArr[i].config.setValue;
|
|
if (setValue) {
|
|
// Get the first valid value.
|
|
plotY = setDataArr[i].config.plotY;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
plotY = setDataArr[0].config.plotY;
|
|
}
|
|
isRally = !! setDataArr[0].config.isRally;
|
|
setShadow = setDataArr[0].config.shadow;
|
|
//drawing starts with an initial half horizontal-shift
|
|
crispY = mathRound(plotY) + (thickness[isRally] % 2 / 2);
|
|
if (isRally) {
|
|
rallyPath.push(M, startX, crispY, H, plotX);
|
|
} else {
|
|
declinePath.push(M, startX, crispY, H, plotX);
|
|
}
|
|
|
|
each(setDataArr, function(point, i) {
|
|
point = point.config;
|
|
dataObj = dataStore[i];
|
|
config = dataObj.config;
|
|
trackerConfig = point.trackerConfig = {};
|
|
graphics = dataObj.graphics;
|
|
imageElement = graphics.image;
|
|
hoverEffects = config.hoverEffects;
|
|
setValue = config.setValue;
|
|
showValue = config.showValue;
|
|
displayValue = config.displayValue;
|
|
isNewElem = false;
|
|
//looping to draw the plots
|
|
nextPoint = (setDataArr[i + 1] && setDataArr[i + 1].config) || {};
|
|
if (nextPoint) {
|
|
path = [M, plotX, plotY];
|
|
isRally = point.isRally;
|
|
//if there is a shift corresponding to this point
|
|
if (point.isShift) {
|
|
plotX += pointDistance;
|
|
plotY = point.graphY;
|
|
path.push(H, plotX);
|
|
path[2] = mathRound(path[2]) +
|
|
(thickness[isRally] % 2 / 2);
|
|
path = path.toString();
|
|
//draw the path
|
|
if (isRally) {
|
|
rallyPath.push(path);
|
|
} else {
|
|
declinePath.push(path);
|
|
}
|
|
path = [M, plotX, plotY];
|
|
}
|
|
//if there is a change in trend between the current and
|
|
//the next points
|
|
if (nextPoint.isChanged) {
|
|
plotY = nextPoint.ty;
|
|
path.push(V, plotY);
|
|
path[1] = mathRound(path[1]) +
|
|
(thickness[isRally] % 2 / 2);
|
|
path = path.toString();
|
|
if (isRally) {
|
|
rallyPath.push(path);
|
|
} else {
|
|
declinePath.push(path);
|
|
}
|
|
path = [M, plotX, plotY];
|
|
}
|
|
|
|
nextPointIsRally = nextPoint.isRally;
|
|
/** @todo: If path contains move to and line to at the
|
|
* same point line is not visible in native VML brewers
|
|
* need to remove this code when this issue in fixed in
|
|
* core.
|
|
*/
|
|
|
|
if (nextPoint.graphY !== path[2]) {
|
|
path.push(V, nextPoint.graphY);
|
|
path[1] = mathRound(path[1]) +
|
|
(thickness[nextPointIsRally] % 2 / 2);
|
|
path = path.toString();
|
|
if (nextPointIsRally) {
|
|
rallyPath.push(path);
|
|
} else {
|
|
declinePath.push(path);
|
|
}
|
|
}
|
|
//updating value
|
|
plotY = nextPoint.graphY;
|
|
}
|
|
xPos = (dataObj._xPos = xAxis.getAxisPosition(point.plotX));
|
|
yPos = (dataObj._yPos = point.plotY);
|
|
trackIndex[point.plotX] ? trackIndex[point.plotX].push(i) : (trackIndex[point.plotX] = [],
|
|
trackIndex[point.plotX].push(i));
|
|
dataObj._index = point.plotX;
|
|
anchorProps = config.anchorProps;
|
|
symbol = anchorProps.symbol;
|
|
anchorShadow = anchorProps.shadow;
|
|
toolText = point.finalTooltext = point.toolText;
|
|
setLink = config.setLink;
|
|
if (yPos !== UNDEFINED && !isNaN(yPos) && point.isDefined) {
|
|
|
|
// Storing the event arguments
|
|
eventArgs = point.eventArgs = point.eventArgs || {};
|
|
|
|
// point.eventArgs = {
|
|
// index: i,
|
|
// link: setLink,
|
|
// value: setValue,
|
|
// displayValue: displayValue,
|
|
// categoryLabel: config.label,
|
|
// toolText: toolText,
|
|
// id: conf.userID,
|
|
// datasetIndex: datasetIndex,
|
|
// datasetName: JSONData.seriesname,
|
|
// visible: visible
|
|
// };
|
|
|
|
// Storing the event arguments
|
|
eventArgs.index = i;
|
|
eventArgs.link = setLink;
|
|
eventArgs.value = setValue;
|
|
eventArgs.displayValue = displayValue;
|
|
eventArgs.categoryLabel = config.label;
|
|
eventArgs.toolText = toolText;
|
|
eventArgs.id = conf.userID;
|
|
eventArgs.datasetIndex = datasetIndex || 0;
|
|
eventArgs.datasetName = JSONData.seriesname;
|
|
eventArgs.visible = visible;
|
|
|
|
// Hover consmetics
|
|
setRolloutAttr = setRolloverAttr = {};
|
|
|
|
// If imageurl is present
|
|
if (anchorProps.imageUrl) {
|
|
imgRef = new Image();
|
|
config.anchorImageLoaded = false;
|
|
imgRef.onload = dataSet._onAnchorImageLoad(dataSet, i, eventArgs, xPos, yPos, dataObj);
|
|
imgRef.onerror = dataSet._onErrorSetter(dataSet, i);
|
|
imgRef.src = anchorProps.imageUrl;
|
|
noOfImages++;
|
|
}
|
|
else {
|
|
imageElement && imageElement.hide();
|
|
setElement = graphics.element;
|
|
// If there is no existing graphics element then create it
|
|
if (!setElement) {
|
|
// Reuse the cache element
|
|
if(pool.element && pool.element.length) {
|
|
setElement = graphics.element = pool.element.shift();
|
|
}
|
|
// If there is no element in cachestore then create it freshly
|
|
else {
|
|
setElement = graphics.element = paper.polypath(container.anchorGroup);
|
|
isNewElem = true;
|
|
}
|
|
initialAnimation = true;
|
|
setElement.attr({
|
|
polypath: [symbol[1] || 2, xPos, yPos, anchorProps.radius,
|
|
anchorProps.startAngle, 0]
|
|
});
|
|
}
|
|
else {
|
|
setElement.animateWith(mainElm, animObj, {
|
|
polypath: [symbol[1] || 2, xPos, yPos, anchorProps.radius,
|
|
anchorProps.startAngle, 0]
|
|
},animationDuration, animType);
|
|
animFlag && initAnimCallBack();
|
|
animFlag = false;
|
|
}
|
|
|
|
// Set all attributes that are not related to non position
|
|
setElement.attr({
|
|
fill: toRaphaelColor({
|
|
color: anchorProps.bgColor,
|
|
alpha: anchorProps.bgAlpha
|
|
}),
|
|
stroke: toRaphaelColor({
|
|
color: anchorProps.borderColor,
|
|
alpha: anchorProps.borderAlpha
|
|
}),
|
|
'stroke-width': anchorProps.borderThickness,
|
|
visibility: !anchorProps.radius ? hiddenStr : visible
|
|
})
|
|
.shadow(anchorShadow, container.anchorShadowGroup)
|
|
.data('anchorRadius', anchorProps.radius)
|
|
.data('anchorHoverRadius', hoverEffects.anchorRadius)
|
|
.data('hoverEnabled', hoverEffects.enabled)
|
|
.data(EVENTARGS,eventArgs);
|
|
|
|
// anchor Radius of hot element is set to maximum of hover radius and anchor radius
|
|
anchorRadius = mathMax(anchorProps.radius,
|
|
hoverEffects &&
|
|
|
|
hoverEffects.anchorRadius || 0, HTP)+ anchorProps.borderThickness / 2;
|
|
|
|
trackerConfig.trackerRadius = anchorRadius;
|
|
}
|
|
|
|
|
|
if (hoverEffects.enabled) {
|
|
setRolloverAttr = {
|
|
polypath: [hoverEffects.anchorSides || 2,
|
|
xPos, yPos,
|
|
hoverEffects.anchorRadius,
|
|
hoverEffects.startAngle,
|
|
hoverEffects.dip
|
|
],
|
|
fill: toRaphaelColor({
|
|
color: hoverEffects.anchorColor,
|
|
alpha: hoverEffects.anchorBgAlpha
|
|
}),
|
|
stroke: toRaphaelColor({
|
|
color: hoverEffects.anchorBorderColor,
|
|
alpha: hoverEffects.anchorBorderAlpha
|
|
}),
|
|
'stroke-width': hoverEffects.anchorBorderThickness
|
|
};
|
|
setRolloutAttr = {
|
|
polypath: [anchorProps.sides, xPos, yPos,
|
|
anchorProps.radius, anchorProps.startAngle, 0
|
|
],
|
|
fill: toRaphaelColor({
|
|
color: anchorProps.bgColor,
|
|
alpha: anchorProps.bgAlpha
|
|
}),
|
|
stroke: toRaphaelColor({
|
|
color: anchorProps.borderColor,
|
|
alpha: anchorProps.borderAlpha
|
|
}),
|
|
'stroke-width': anchorProps.borderThickness
|
|
};
|
|
setElement && setElement
|
|
.data('anchorRadius', anchorProps.radius)
|
|
.data('anchorHoverRadius', hoverEffects.anchorRadius)
|
|
.data('hoverEnabled', hoverEffects.enabled)
|
|
.data(SETROLLOVERATTR, setRolloverAttr)
|
|
.data(SETROLLOUTATTR, setRolloutAttr)
|
|
.data(EVENTARGS,eventArgs);
|
|
}
|
|
|
|
// dataSet.drawLabel(i);
|
|
}
|
|
else {
|
|
graphics.element && graphics.element.hide();
|
|
imageElement && imageElement.hide();
|
|
}
|
|
});
|
|
|
|
if (!lineElement) {
|
|
if (!rallyElem) {
|
|
lineElement = rallyElem = datasetGraphics.rallyElem = paper.path(container.lineGroup);
|
|
}
|
|
rallyElem
|
|
.animateWith(mainElm, animObj, {
|
|
path: rallyPath
|
|
}, animFlag ? 0 : animationDuration, animType)
|
|
.attr(rallyAttr)
|
|
.shadow(rallyThickness && shadow, container.lineShadowGroup);
|
|
if (!declineElem) {
|
|
lineElement = declineElem = datasetGraphics.declineElem = paper.path(container.lineGroup);
|
|
}
|
|
declineElem
|
|
.animateWith(mainElm, animObj, {
|
|
path: declinePath
|
|
}, animFlag ? 0 : animationDuration, animType)
|
|
.attr(declineAttr)
|
|
.shadow(declineThickness && shadow, container.lineShadowGroup);
|
|
initialAnimation = true;
|
|
}
|
|
|
|
!(animationDuration && animFlag) && (animFlag = false);
|
|
|
|
conf.noOfImages = conf.totalImages = noOfImages;
|
|
if (noOfImages === 0) {
|
|
dataSet.drawn ? dataSet.drawLabel() :
|
|
jobList.labelDrawID.push(schedular.addJob(dataSet.drawLabel, dataSet, [],
|
|
lib.priorityList.tracker));
|
|
}
|
|
dataSet.drawn = true;
|
|
container.anchorGroup
|
|
.animateWith(mainElm, animObj, clipCanvas, animationDuration, animType);
|
|
// container.anchorGroup.hide();
|
|
dataLabelContainer.hide();
|
|
container.lineShadowGroup
|
|
.animateWith(mainElm, animObj, clipCanvas, animationDuration, animType);
|
|
container.anchorShadowGroup
|
|
.animateWith(mainElm, animObj, clipCanvas, animationDuration, animType);
|
|
|
|
container.lineShadowGroup
|
|
.animateWith(mainElm, animObj, clipCanvas, animationDuration, animType);
|
|
|
|
// clip-canvas animation to line chart
|
|
container.lineGroup
|
|
.animateWith(mainElm, animObj, clipCanvas, animationDuration, animType, initAnimCallBack);
|
|
},
|
|
hidingPosition: function () {
|
|
return function (data) {
|
|
var element = data.graphics.element,
|
|
oldPos = element && element.attr('polypath');
|
|
return {
|
|
// Only the radius of the anchor elements.
|
|
polypath: (oldPos[3] = 0 && oldPos),
|
|
// for the hot elements to be zero radius.
|
|
r: 0,
|
|
// for the text element to hide itself.
|
|
text: BLANKSTRING
|
|
};
|
|
};
|
|
}
|
|
},'Line']);
|
|
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-errorbar2d',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
COMPONENT = 'component',
|
|
DATASET_GROUP = 'datasetGroup',
|
|
preDefStr = lib.preDefStr,
|
|
COLUMN = preDefStr.column;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET_GROUP, 'errorbar2d', {
|
|
},COLUMN]);
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-dragnode',
|
|
function() {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
//strings
|
|
preDefStr = lib.preDefStr,
|
|
colorStrings = preDefStr.colors,
|
|
COLOR_FFFFFF = colorStrings.FFFFFF,
|
|
COLOR_000000 = colorStrings.c000000,
|
|
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
BLANK = lib.BLANKSTRING,
|
|
BLANKSTRING = lib.BLANKSTRING,
|
|
//add the tools thats are requared
|
|
pluck = lib.pluck,
|
|
getFirstValue = lib.getFirstValue,
|
|
// getDefinedColor = lib.getDefinedColor,
|
|
extend2 = lib.extend2, //old: jarendererExtend / margecolone
|
|
HASHSTRING = lib.HASHSTRING,
|
|
UNDEFINED,
|
|
// The default value for stroke-dash attribute.
|
|
// getLinkAction = lib.getLinkAction,
|
|
// NumberFormatter = lib.NumberFormatter,
|
|
hashify = lib.hashify,
|
|
PXSTRING = 'px',
|
|
POLYGON = 'polygon',
|
|
CIRCLE = 'circle',
|
|
RECTANGLE = 'rectangle',
|
|
POINTER = 'pointer',
|
|
NORMALSTRING = 'normal',
|
|
COMPONENT = 'component',
|
|
DATASET = 'dataset',
|
|
DATASET_GROUP = 'datasetGroup',
|
|
each = lib.each,
|
|
componentDispose = lib.componentDispose,
|
|
defined = function(obj) {
|
|
return obj !== UNDEFINED && obj !== null;
|
|
},
|
|
|
|
// CRISP = 'crisp',
|
|
PX = PXSTRING,
|
|
COMMA = ',',
|
|
math = Math,
|
|
mathMin = math.min,
|
|
mathMax = math.max,
|
|
hasTouch = lib.hasTouch,
|
|
// hot/tracker threshold in pixels
|
|
// getColumnColor = lib.graphics.getColumnColor,
|
|
// pluckColor = lib.pluckColor,
|
|
COMMASTRING = lib.COMMASTRING,
|
|
HUNDREDSTRING = lib.HUNDREDSTRING,
|
|
// COMMASPACE = lib.COMMASPACE,
|
|
//strings
|
|
BLANKSPACE = ' ',
|
|
//add the tools thats are requared
|
|
libGraphics = lib.graphics,
|
|
parseColor = libGraphics.parseColor,
|
|
getValidColor = libGraphics.getValidColor,
|
|
LABEL = 'label',
|
|
INPUT = 'input';
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET_GROUP, 'Dragnode', {
|
|
init: function() {
|
|
var manager = this;
|
|
manager.connectorSet = [];
|
|
manager.nodes = {};
|
|
manager.datasets = [];
|
|
manager.components = [];
|
|
manager.graphics = {};
|
|
manager.labelSet = [];
|
|
},
|
|
addDataset: function(dataSet, index) {
|
|
var manager = this,
|
|
dataset = manager.datasets[index];
|
|
dataSet.groupManager = manager;
|
|
dataSet.datasetIndex = index;
|
|
if (!dataset) {
|
|
dataset = manager.datasets[index] = {
|
|
dataset: dataSet
|
|
};
|
|
}
|
|
|
|
},
|
|
addLabels: function(labels, index) {
|
|
var manager = this,
|
|
labelSet = manager.labelSet[index];
|
|
labels.groupManager = manager;
|
|
if (!labelSet) {
|
|
labelSet = manager.labelSet[index] = {
|
|
labels: labels
|
|
};
|
|
}
|
|
},
|
|
addConnectors: function(connectors, index) {
|
|
var manager = this,
|
|
connectorSet = manager.connectorSet[index];
|
|
connectors.groupManager = manager;
|
|
if (!connectorSet) {
|
|
connectorSet = manager.connectorSet[index] = {
|
|
connectors: connectors
|
|
};
|
|
}
|
|
},
|
|
showNodeAddUI: function() {
|
|
var manager = this,
|
|
chart = manager.chart,
|
|
datasets = chart.components.dataset,
|
|
datasetDropDownStr = BLANKSTRING,
|
|
str1 = '<option value="',
|
|
str2 = '">',
|
|
str3 = '</option>',
|
|
index,
|
|
conf,
|
|
dataset,
|
|
type,
|
|
i;
|
|
for (i = 0; i < datasets.length; i++) {
|
|
dataset = datasets[i] || {};
|
|
index = dataset.index;
|
|
conf = dataset.config;
|
|
type = dataset.plotType;
|
|
if (type === 'dragnode') {
|
|
datasetDropDownStr += str1 + conf.id + str2 + ((conf.name !== BLANK && conf.name !==
|
|
UNDEFINED) && conf.name + COMMASTRING + BLANKSPACE || BLANK) + conf.id + str3;
|
|
}
|
|
|
|
}
|
|
manager.showNodeUpdateUI(chart, {
|
|
dataset: {
|
|
innerHTML: datasetDropDownStr
|
|
}
|
|
});
|
|
},
|
|
showConnectorAddUI: function() {
|
|
var manager = this,
|
|
chart = manager.chart,
|
|
nodes = manager.nodes,
|
|
nodeStr = BLANKSTRING,
|
|
str1 = '<option value="',
|
|
str2 = '">',
|
|
str3 = '</option>',
|
|
id,
|
|
i,
|
|
config,
|
|
node;
|
|
for (i in nodes) {
|
|
node = nodes[i];
|
|
config = node.config;
|
|
id = config.id;
|
|
nodeStr += str1 + id + str2 + id + str3;
|
|
}
|
|
manager.showConnectorUpdateUI(chart, {
|
|
fromid: {
|
|
innerHTML: nodeStr
|
|
},
|
|
toid: {
|
|
innerHTML: nodeStr
|
|
}
|
|
});
|
|
},
|
|
draw: function() {
|
|
var manager = this,
|
|
datasets = manager.datasets,
|
|
connectorSet = manager.connectorSet,
|
|
i,
|
|
dataset,
|
|
connectors,
|
|
labelSet = manager.labelSet,
|
|
labels,
|
|
ln;
|
|
|
|
manager.updateUIvisuals();
|
|
for (i = 0, ln = datasets.length; i < ln; i++) {
|
|
dataset = datasets[i].dataset;
|
|
dataset.draw();
|
|
}
|
|
for (i = 0, ln = connectorSet.length; i < ln; i++) {
|
|
connectors = connectorSet[i].connectors;
|
|
connectors.draw();
|
|
}
|
|
for (i = 0, ln = labelSet.length; i < ln; i++) {
|
|
labels = labelSet[i].labels;
|
|
labels.draw();
|
|
}
|
|
manager.drawn = true;
|
|
},
|
|
getJSONData: function() {
|
|
var manager = this,
|
|
nodeSets = manager.datasets,
|
|
connectorSets = manager.connectorSet,
|
|
labelSets = manager.labelSet,
|
|
jsonData = {},
|
|
i,
|
|
len,
|
|
JSONData,
|
|
dataset;
|
|
jsonData.dataset = [];
|
|
jsonData.connectors = [];
|
|
jsonData.labels = [];
|
|
for (i = 0, len = nodeSets.length; i < len; i++) {
|
|
dataset = nodeSets[i] && nodeSets[i].dataset;
|
|
JSONData = dataset.JSONData;
|
|
if (!jsonData.dataset[i]) {
|
|
jsonData.dataset[i] = extend2({}, dataset.JSONData);
|
|
}
|
|
jsonData.dataset[i].data = dataset.getJSONData();
|
|
}
|
|
for (i = 0, len = connectorSets.length; i < len; i++) {
|
|
dataset = connectorSets[i] && connectorSets[i].connectors;
|
|
if (!jsonData.connectors[i]) {
|
|
jsonData.connectors[i] = extend2({}, dataset.JSONData);
|
|
}
|
|
jsonData.connectors[i].connector = dataset.getJSONData();
|
|
}
|
|
for (i = 0, len = labelSets.length; i < len; i++) {
|
|
dataset = labelSets[i] && labelSets[i].labels;
|
|
if (!jsonData.labels[i]) {
|
|
jsonData.labels[i] = {
|
|
label: []
|
|
};
|
|
}
|
|
jsonData.labels[i].label = dataset.getJSONData();
|
|
}
|
|
return jsonData;
|
|
},
|
|
clearLongPress: function() {
|
|
var ele = this;
|
|
ele.data('move', false);
|
|
clearTimeout(ele._longpressactive);
|
|
delete ele._longpressactive;
|
|
},
|
|
createHtmlDialog: function(chart, dialogWidth, dialogHeight,
|
|
onsubmit, oncancel, onremove, cacheUI) {
|
|
var paper = chart.components.paper,
|
|
conf = chart.config,
|
|
inCanvasStyle = conf.style.inCanvasStyle || {},
|
|
chartWidth = chart.config.width,
|
|
chartHeight = chart.config.height,
|
|
padding = 5,
|
|
dialogAttrs,
|
|
okAttrs,
|
|
cancelAttrs,
|
|
removeAttrs,
|
|
transposeAnimDuration = chart.get(configStr, animationObjStr).transposeAnimDuration,
|
|
buttonStyle = {
|
|
color: hashify(inCanvasStyle.color),
|
|
textAlign: 'center',
|
|
paddingTop: 1 + PX,
|
|
border: '1px solid #cccccc',
|
|
borderRadius: 4 + PX,
|
|
cursor: POINTER,
|
|
'_cursor': 'hand',
|
|
backgroundColor: HASHSTRING + COLOR_FFFFFF,
|
|
zIndex: 21,
|
|
'-webkit-border-radius': 4 + PX
|
|
},
|
|
ui = cacheUI;
|
|
if (!ui) {
|
|
ui = paper.html('div', {
|
|
fill: 'transparent',
|
|
width: chartWidth,
|
|
height: chartHeight
|
|
}, {
|
|
fontSize: 10 + PX,
|
|
lineHeight: 15 + PX,
|
|
fontFamily: inCanvasStyle.fontFamily
|
|
}, chart.linkedItems.container);
|
|
} else {
|
|
if (transposeAnimDuration) {
|
|
ui.animate({
|
|
width: chartWidth,
|
|
height: chartHeight
|
|
}, transposeAnimDuration, NORMALSTRING);
|
|
} else {
|
|
ui.attr({
|
|
width: chartWidth,
|
|
height: chartHeight
|
|
});
|
|
}
|
|
}
|
|
if (!ui.veil) {
|
|
ui.veil = paper.html('div', {
|
|
fill: COLOR_000000,
|
|
width: chartWidth,
|
|
height: chartHeight,
|
|
opacity: 0.3
|
|
}, undefined, ui);
|
|
} else {
|
|
if (transposeAnimDuration) {
|
|
ui.veil.animate({
|
|
width: chartWidth,
|
|
height: chartHeight
|
|
}, transposeAnimDuration, NORMALSTRING);
|
|
} else {
|
|
ui.veil.attr({
|
|
width: chartWidth,
|
|
height: chartHeight
|
|
});
|
|
}
|
|
}
|
|
dialogAttrs = {
|
|
x: (chartWidth - dialogWidth) / 2,
|
|
y: (chartHeight - dialogHeight) / 2,
|
|
fill: 'efefef',
|
|
strokeWidth: 1,
|
|
stroke: COLOR_000000,
|
|
width: dialogWidth,
|
|
height: dialogHeight
|
|
};
|
|
if (!ui.dialog) {
|
|
ui.dialog = paper.html('div', dialogAttrs, {
|
|
borderRadius: 5 + PX,
|
|
boxShadow: '1px 1px 3px #000000',
|
|
'-webkit-border-radius': 5 + PX,
|
|
'-webkit-box-shadow': '1px 1px 3px #000000',
|
|
filter: 'progid:DXImageTransform.Microsoft.Shadow(Strength=4, Direction=135, Color="#000000")'
|
|
}, ui);
|
|
} else {
|
|
if (transposeAnimDuration) {
|
|
ui.dialog.animate({
|
|
x: dialogAttrs.x,
|
|
y: dialogAttrs.y,
|
|
width: dialogAttrs.width,
|
|
height: dialogAttrs.height
|
|
}, transposeAnimDuration, NORMALSTRING);
|
|
} else {
|
|
ui.dialog.attr(dialogAttrs);
|
|
}
|
|
}
|
|
|
|
okAttrs = {
|
|
x: dialogWidth - 70 - padding,
|
|
y: dialogHeight - 23 - padding,
|
|
width: 65,
|
|
height: 17,
|
|
text: 'Submit',
|
|
tabIndex: 1
|
|
};
|
|
if (!ui.ok) {
|
|
ui.ok = paper.html('div', okAttrs, buttonStyle, ui.dialog)
|
|
.on('click', onsubmit);
|
|
} else {
|
|
if (transposeAnimDuration) {
|
|
ui.ok.animate({
|
|
x: okAttrs.x,
|
|
y: okAttrs.y,
|
|
width: okAttrs.width,
|
|
height: okAttrs.height
|
|
}, transposeAnimDuration, NORMALSTRING);
|
|
} else {
|
|
ui.ok.attr(okAttrs);
|
|
}
|
|
}
|
|
|
|
cancelAttrs = {
|
|
x: dialogWidth - 140 - padding,
|
|
y: dialogHeight - 23 - padding,
|
|
width: 65,
|
|
height: 17,
|
|
text: 'Cancel',
|
|
tabIndex: 2
|
|
};
|
|
if (!ui.cancel) {
|
|
ui.cancel = paper.html('div', cancelAttrs, buttonStyle, ui.dialog).on('click', oncancel);
|
|
} else {
|
|
if (transposeAnimDuration) {
|
|
ui.cancel.animate({
|
|
x: cancelAttrs.x,
|
|
y: cancelAttrs.y,
|
|
width: cancelAttrs.width,
|
|
height: cancelAttrs.height
|
|
}, transposeAnimDuration, NORMALSTRING);
|
|
} else {
|
|
ui.cancel.attr(cancelAttrs);
|
|
}
|
|
}
|
|
|
|
removeAttrs = {
|
|
x: dialogWidth - 210 - padding,
|
|
y: dialogHeight - 23 - padding,
|
|
width: 65,
|
|
height: 17,
|
|
text: 'Delete',
|
|
tabIndex: 3
|
|
};
|
|
if (!ui.remove) {
|
|
ui.remove = paper.html('div', removeAttrs, buttonStyle, ui.dialog).on('click', onremove);
|
|
} else {
|
|
if (transposeAnimDuration) {
|
|
ui.remove.animate({
|
|
x: removeAttrs.x,
|
|
y: removeAttrs.y,
|
|
width: removeAttrs.width,
|
|
height: removeAttrs.height
|
|
}, transposeAnimDuration, NORMALSTRING);
|
|
} else {
|
|
ui.remove.attr(removeAttrs);
|
|
}
|
|
}
|
|
|
|
if (!ui.handleKeyPress) {
|
|
// Add an event that would handle enter and esc on input
|
|
// elements
|
|
ui.handleKeyPress = function(e) {
|
|
if (e.keyCode === 13) {
|
|
ui.ok.trigger(hasTouch ? 'touchStart' : 'click', e);
|
|
} else if (e.keyCode === 27) {
|
|
ui.cancel.trigger(hasTouch ? 'touchStart' : 'click', e);
|
|
}
|
|
};
|
|
}
|
|
|
|
// Keep initially hidden.
|
|
// ui.hide();
|
|
|
|
return ui;
|
|
},
|
|
updateUIvisuals: function() {
|
|
var manager = this,
|
|
cacheConnectorUpdateUI = manager.graphics.cacheConnectorUpdateUI,
|
|
chart = manager.chart,
|
|
cacheLabelUpdateUI = manager.graphics.cacheLabelUpdateUI,
|
|
cacheLabelDeleteUI = manager.graphics.cacheLabelDeleteUI,
|
|
cacheUpdateUI = manager.graphics.cacheUpdateUI;
|
|
if (cacheConnectorUpdateUI) {
|
|
manager.createHtmlDialog(chart, 350, 215, undefined, undefined, undefined, cacheConnectorUpdateUI);
|
|
}
|
|
if (cacheUpdateUI) {
|
|
manager.createHtmlDialog(chart, 350, 215, undefined, undefined, undefined, cacheUpdateUI);
|
|
}
|
|
if (cacheLabelUpdateUI) {
|
|
manager.createHtmlDialog(chart, 350, 215, undefined, undefined, undefined, cacheLabelUpdateUI);
|
|
}
|
|
if (cacheLabelDeleteUI) {
|
|
manager.createHtmlDialog(chart, 350, 215, undefined, undefined, undefined, cacheLabelDeleteUI);
|
|
}
|
|
|
|
},
|
|
showConnectorUpdateUI: function(chart, config, edit) {
|
|
var manager = this,
|
|
renderer = chart.components.paper,
|
|
conf = chart.config,
|
|
inCanvasStyle = conf.style.inCanvasStyle || {},
|
|
ui = manager.cacheConnectorUpdateUI,
|
|
inputStyle = {
|
|
border: '1px solid #cccccc',
|
|
fontSize: 10 + PX,
|
|
lineHeight: 15 + PX,
|
|
fontFamily: inCanvasStyle.fontFamily,
|
|
padding: 2 + PX
|
|
},
|
|
labelStyle = {
|
|
textAlign: 'right'
|
|
},
|
|
fields = ui && ui.fields,
|
|
labels = ui && ui.labels,
|
|
innerHTML,
|
|
field,
|
|
value,
|
|
onDelete = function() {
|
|
var fields = ui && ui.fields,
|
|
config = {
|
|
from: fields.fromid.val(),
|
|
to: fields.toid.val(),
|
|
id: fields.id.val()
|
|
};
|
|
|
|
chart.deleteConnector(config);
|
|
ui.hide();
|
|
},
|
|
dialog;
|
|
|
|
if (!ui) {
|
|
ui = manager.graphics.cacheConnectorUpdateUI = manager.createHtmlDialog(chart,
|
|
315, 215,
|
|
function() {
|
|
var fields = ui && ui.fields,
|
|
submitObj;
|
|
if (fields) {
|
|
submitObj = {
|
|
from: fields.fromid.val(),
|
|
to: fields.toid.val(),
|
|
id: fields.id.val(),
|
|
label: fields.label.val(),
|
|
color: fields.color.val(),
|
|
alpha: fields.alpha.val(),
|
|
link: fields.url.val(),
|
|
tooltext: fields.tooltext.val(),
|
|
strength: fields.strength.val(),
|
|
arrowatstart: fields.arratstart.val(),
|
|
arrowatend: fields.arratend.val(),
|
|
dashed: fields.dashed.val(),
|
|
dashlen: fields.dashlen.val(),
|
|
dashgap: fields.dashgap.val()
|
|
};
|
|
|
|
// Validate
|
|
if (submitObj.from) {
|
|
if (submitObj.to) {
|
|
if (submitObj.from != submitObj.to) {
|
|
edit ? chart.editConnector(submitObj) :
|
|
chart.addConnector(submitObj);
|
|
ui.enableFields();
|
|
ui.hide();
|
|
ui.clearFields();
|
|
return;
|
|
} else {
|
|
ui.error.attr({
|
|
text: 'Connector cannot start and end at the same node!'
|
|
});
|
|
fields.fromid.focus();
|
|
}
|
|
} else {
|
|
ui.error.attr({
|
|
text: 'Please select a valid connector end.'
|
|
});
|
|
fields.toid.focus();
|
|
}
|
|
} else {
|
|
ui.error.attr({
|
|
text: 'Please select a valid connector start.'
|
|
});
|
|
fields.fromid.focus();
|
|
}
|
|
}
|
|
},
|
|
// Cancel function
|
|
function() {
|
|
ui.error.attr({
|
|
text: BLANKSTRING
|
|
});
|
|
ui.enableFields();
|
|
ui.hide();
|
|
},
|
|
// Delete function
|
|
onDelete);
|
|
dialog = ui.dialog;
|
|
labels = ui.labels = {};
|
|
fields = ui.fields = {};
|
|
} else {
|
|
ui.attr({
|
|
width: chart.config.width,
|
|
height: chart.config.height
|
|
});
|
|
ui.veil.attr({
|
|
width: chart.config.width,
|
|
height: chart.config.height
|
|
});
|
|
ui.dialog.attr({
|
|
x: (chart.config.width - 315) / 2,
|
|
y: (chart.config.height - 215) / 2,
|
|
width: 315,
|
|
height: 215
|
|
});
|
|
}
|
|
ui.config = config;
|
|
if (!ui.enableFields) {
|
|
ui.enableFields = function() {
|
|
var key;
|
|
for (key in config) {
|
|
if (config[key] && config[key].disabled && fields[key]) {
|
|
fields[key].element.removeAttribute('disabled');
|
|
}
|
|
}
|
|
};
|
|
}
|
|
if (!ui.clearFields) {
|
|
ui.clearFields = function() {
|
|
var key,
|
|
fields = ui.fields;
|
|
for (key in fields) {
|
|
if (!fields[key].element.disabled) {
|
|
fields[key].element.value = BLANKSTRING;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
|
|
|
|
each(manager.connectorUpdateUIDefinition, function(def) {
|
|
var key = def.key,
|
|
attr = config[key] || {};
|
|
|
|
if (!labels[key]) {
|
|
labels[key] = renderer.html(LABEL, {
|
|
x: def.x,
|
|
y: def.y,
|
|
width: def.labelWidth || 45,
|
|
text: def.text
|
|
}, labelStyle, dialog);
|
|
}
|
|
|
|
// No need to proceed of this label has no input box
|
|
// associated with itself.
|
|
if (def.noInput) {
|
|
return;
|
|
}
|
|
|
|
if (!(field = fields[key])) {
|
|
field = fields[key] = renderer.html(def.inputType || INPUT, {
|
|
y: -2 + (def.inputPaddingTop || 0),
|
|
x: def.labelWidth && (def.labelWidth + 5) || 50,
|
|
width: def.inputWidth || 50,
|
|
name: key || BLANKSTRING
|
|
}, inputStyle);
|
|
|
|
if (def.inputType !== 'select') {
|
|
field.attr({
|
|
type: def.type || 'text'
|
|
}).on('keyup', ui.handleKeyPress);
|
|
}
|
|
field.add(labels[key]);
|
|
}
|
|
|
|
if ((innerHTML = pluck(attr.innerHTML, def.innerHTML))) {
|
|
field.attr({
|
|
innerHTML: innerHTML
|
|
});
|
|
}
|
|
if ((value = pluck(attr.val, def.val)) !== undefined) {
|
|
field.val(value);
|
|
}
|
|
if (attr.disabled) {
|
|
field.attr({
|
|
disabled: 'disabled'
|
|
});
|
|
}
|
|
});
|
|
|
|
//dash checking and ui modification
|
|
//call to set default fro the first time
|
|
ui.checkDash = function() {
|
|
var checked = fields.dashed && fields.dashed.val(),
|
|
showHideFn = checked ? 'show' : 'hide';
|
|
labels.dashgap && labels.dashgap[showHideFn]();
|
|
fields.dashgap && fields.dashgap[showHideFn]();
|
|
labels.dashlen && labels.dashlen[showHideFn]();
|
|
fields.dashlen && fields.dashlen[showHideFn]();
|
|
};
|
|
ui.checkDash();
|
|
fields.dashed.on('click', ui.checkDash);
|
|
|
|
if (!ui.error) {
|
|
ui.error = renderer.html('span', {
|
|
color: 'ff0000',
|
|
x: 10,
|
|
y: 170
|
|
}, undefined, dialog);
|
|
}
|
|
|
|
|
|
ui.remove[edit ? 'show' : 'hide']();
|
|
// Show the dialog box
|
|
if (chart.animation) {
|
|
ui.fadeIn('fast');
|
|
} else {
|
|
ui.show();
|
|
}
|
|
},
|
|
labelUpdateUIDefinition: [{
|
|
key: LABEL,
|
|
text: 'Label*',
|
|
x: 10,
|
|
y: 15,
|
|
inputWidth: 235
|
|
}, {
|
|
key: 'size',
|
|
text: 'Size',
|
|
x: 10,
|
|
y: 40
|
|
}, {
|
|
key: 'padding',
|
|
text: 'Padding',
|
|
x: 10,
|
|
y: 65
|
|
}, {
|
|
key: 'x',
|
|
text: 'Position',
|
|
x: 120,
|
|
y: 65,
|
|
labelWidth: 70,
|
|
inputWidth: 25
|
|
}, {
|
|
key: 'y',
|
|
text: COMMA,
|
|
x: 225,
|
|
y: 65,
|
|
labelWidth: 10,
|
|
inputWidth: 25
|
|
}, {
|
|
key: 'xy',
|
|
text: '(x, y)',
|
|
x: 260,
|
|
y: 65,
|
|
noInput: true
|
|
}, {
|
|
key: 'allowdrag',
|
|
text: 'Allow Drag',
|
|
x: 120,
|
|
y: 40,
|
|
inputType: 'checkbox',
|
|
inputPaddingTop: 3,
|
|
inputWidth: 15,
|
|
labelWidth: 70,
|
|
val: 1
|
|
}, {
|
|
key: 'color',
|
|
text: 'Color',
|
|
x: 10,
|
|
y: 90
|
|
}, {
|
|
key: 'alpha',
|
|
text: 'Alpha',
|
|
x: 145,
|
|
y: 90,
|
|
inputWidth: 30,
|
|
val: HUNDREDSTRING
|
|
}, {
|
|
key: 'bordercolor',
|
|
text: 'Border Color',
|
|
x: 10,
|
|
y: 125,
|
|
labelWidth: 100
|
|
}, {
|
|
key: 'bgcolor',
|
|
text: 'Background Color',
|
|
x: 10,
|
|
y: 150,
|
|
labelWidth: 100
|
|
}],
|
|
showLabelUpdateUI: function(chart, options) {
|
|
var manager = this,
|
|
paper = chart.components.paper,
|
|
conf = chart.config,
|
|
inCanvasStyle = conf.style.inCanvasStyle || {},
|
|
ui = manager.graphics.cacheLabelUpdateUI,
|
|
inputStyle = {
|
|
border: '1px solid #cccccc',
|
|
fontSize: 10 + PX,
|
|
lineHeight: 15 + PX,
|
|
fontFamily: inCanvasStyle.fontFamily,
|
|
padding: 2 + PX
|
|
},
|
|
labelStyle = {
|
|
textAlign: 'right'
|
|
},
|
|
fields = ui && ui.fields,
|
|
labels = ui && ui.labels,
|
|
field,
|
|
value,
|
|
dialog;
|
|
|
|
if (!ui) {
|
|
ui = manager.graphics.cacheLabelUpdateUI = manager.createHtmlDialog(chart,
|
|
315, 205,
|
|
function() {
|
|
var fields = ui && ui.fields,
|
|
submitObj;
|
|
if (fields) {
|
|
// Prepare obbject for submission.
|
|
submitObj = {
|
|
text: fields.label.val(),
|
|
x: fields.x.val(),
|
|
y: fields.y.val(),
|
|
color: fields.color.val(),
|
|
alpha: fields.alpha.val(),
|
|
bgcolor: fields.bgcolor.val(),
|
|
bordercolor: fields.bordercolor.val(),
|
|
fontsize: fields.size.val(),
|
|
allowdrag: fields.allowdrag.val(),
|
|
padding: fields.padding.val()
|
|
};
|
|
|
|
if (submitObj.text) {
|
|
chart.addLabel && chart.addLabel(submitObj);
|
|
ui.hide();
|
|
return;
|
|
} else {
|
|
ui.error.attr({
|
|
text: 'Label cannot be blank.'
|
|
});
|
|
fields.label.focus();
|
|
|
|
}
|
|
}
|
|
},
|
|
function() {
|
|
ui.error.attr({
|
|
text: BLANKSTRING
|
|
});
|
|
ui.hide();
|
|
});
|
|
dialog = ui.dialog;
|
|
labels = ui.labels = {};
|
|
fields = ui.fields = {};
|
|
}
|
|
|
|
each(manager.labelUpdateUIDefinition, function(def) {
|
|
var key = def.key;
|
|
|
|
if (!labels[key]) {
|
|
labels[key] = paper.html(LABEL, {
|
|
x: def.x,
|
|
y: def.y,
|
|
width: def.labelWidth || 45,
|
|
text: def.text
|
|
}, labelStyle, dialog);
|
|
}
|
|
|
|
// No need to proceed of this label has no input box
|
|
// associated with itself.
|
|
if (def.noInput) {
|
|
return;
|
|
}
|
|
|
|
if (!(field = fields[key])) {
|
|
field = fields[key] = paper.html(INPUT, {
|
|
y: -2 + (def.inputPaddingTop || 0),
|
|
x: def.labelWidth && (def.labelWidth + 5) || 50,
|
|
width: def.inputWidth || 50,
|
|
type: def.inputType || 'text',
|
|
name: key || BLANKSTRING
|
|
}, inputStyle, labels[key]).on('keyup', ui.handleKeyPress);
|
|
}
|
|
|
|
if ((value = pluck(options[key], def.val)) !== undefined) {
|
|
field.val(value);
|
|
}
|
|
|
|
});
|
|
|
|
if (!ui.error) {
|
|
ui.error = paper.html('span', {
|
|
color: 'ff0000',
|
|
x: 10,
|
|
y: 180
|
|
}, undefined, dialog);
|
|
}
|
|
|
|
// Show the dialog box
|
|
if (chart.animation) {
|
|
ui.fadeIn('fast');
|
|
} else {
|
|
ui.show();
|
|
}
|
|
// Focus on label textbox
|
|
ui.fields.label.focus();
|
|
},
|
|
showLabelDeleteUI: function(label) {
|
|
var manager = this,
|
|
chart = manager.chart,
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animation = animationObj.duration,
|
|
paper = chart.components.paper,
|
|
ui = manager.graphics.cacheLabelDeleteUI;
|
|
if (!ui) {
|
|
ui = manager.graphics.cacheLabelDeleteUI =
|
|
manager.createHtmlDialog(chart, 250, 100, undefined, function() {
|
|
ui.hide();
|
|
},
|
|
function() {
|
|
chart.deleteLabel(label.config.index);
|
|
ui.hide();
|
|
});
|
|
|
|
// create a location where to show the text message
|
|
ui.message = paper.html('span', {
|
|
x: 10,
|
|
y: 10,
|
|
width: 230,
|
|
height: 80
|
|
}).add(ui.dialog);
|
|
// since submit button is not needed, hide it and move the
|
|
// delete button to its place.
|
|
ui.ok.hide();
|
|
ui.remove.translate(175).show();
|
|
}
|
|
|
|
// Update the message with proper text.
|
|
ui.message.attr({
|
|
text: 'Would you really like to delete the label: \"' +
|
|
label.config.text + '\"?'
|
|
});
|
|
|
|
// Show the dialog box
|
|
if (animation) {
|
|
ui.fadeIn('fast');
|
|
} else {
|
|
ui.show();
|
|
}
|
|
},
|
|
connectorUpdateUIDefinition: [{
|
|
key: 'fromid',
|
|
text: 'Connect From',
|
|
inputType: 'select',
|
|
x: 10,
|
|
y: 15,
|
|
labelWidth: 80,
|
|
inputWidth: 100
|
|
}, {
|
|
key: 'toid',
|
|
text: 'Connect To',
|
|
inputType: 'select',
|
|
x: 10,
|
|
y: 40,
|
|
labelWidth: 80,
|
|
inputWidth: 100
|
|
}, {
|
|
key: 'arratstart',
|
|
text: 'Arrow At Start',
|
|
x: 200,
|
|
y: 15,
|
|
type: 'checkbox',
|
|
inputPaddingTop: 3,
|
|
labelWidth: 80,
|
|
inputWidth: 15
|
|
}, {
|
|
key: 'arratend',
|
|
text: 'Arrow At End',
|
|
x: 200,
|
|
y: 40,
|
|
type: 'checkbox',
|
|
inputPaddingTop: 3,
|
|
labelWidth: 80,
|
|
inputWidth: 15
|
|
}, {
|
|
key: LABEL,
|
|
text: 'Label',
|
|
x: 10,
|
|
y: 75,
|
|
labelWidth: 40,
|
|
inputWidth: 120
|
|
}, {
|
|
key: 'id',
|
|
text: 'Node ID',
|
|
x: 190,
|
|
y: 75,
|
|
inputWidth: 55
|
|
}, {
|
|
key: 'color',
|
|
text: 'Color',
|
|
x: 10,
|
|
y: 100,
|
|
labelWidth: 40,
|
|
inputWidth: 35
|
|
}, {
|
|
key: 'alpha',
|
|
text: 'Alpha',
|
|
x: 110,
|
|
y: 100,
|
|
inputWidth: 25,
|
|
labelWidth: 35
|
|
}, {
|
|
key: 'strength',
|
|
text: 'Strength',
|
|
x: 190,
|
|
y: 100,
|
|
inputWidth: 55,
|
|
val: '0.1'
|
|
}, {
|
|
key: 'url',
|
|
text: 'Link',
|
|
x: 10,
|
|
y: 125,
|
|
labelWidth: 40,
|
|
inputWidth: 120
|
|
}, {
|
|
key: 'tooltext',
|
|
text: 'Tooltip',
|
|
x: 190,
|
|
y: 125,
|
|
labelWidth: 40,
|
|
inputWidth: 60
|
|
}, {
|
|
key: 'dashed',
|
|
text: 'Dashed',
|
|
x: 10,
|
|
y: 150,
|
|
type: 'checkbox',
|
|
inputPaddingTop: 3,
|
|
inputWidth: 15,
|
|
labelWidth: 40
|
|
}, {
|
|
key: 'dashgap',
|
|
text: 'Dash Gap',
|
|
x: 85,
|
|
y: 150,
|
|
labelWidth: 60,
|
|
inputWidth: 25
|
|
}, {
|
|
key: 'dashlen',
|
|
text: 'Dash Length',
|
|
x: 190,
|
|
y: 150,
|
|
labelWidth: 70,
|
|
inputWidth: 30
|
|
}],
|
|
nodeUpdateUIDefinition: [{
|
|
key: 'id',
|
|
text: 'Id',
|
|
inputWidth: 60,
|
|
x: 10,
|
|
y: 15
|
|
}, {
|
|
key: DATASET,
|
|
text: DATASET,
|
|
inputType: 'select',
|
|
inputWidth: 110,
|
|
innerHTML: undefined,
|
|
x: 170,
|
|
y: 15
|
|
}, {
|
|
key: 'x',
|
|
text: 'Value',
|
|
x: 10,
|
|
y: 40,
|
|
inputWidth: 21
|
|
}, {
|
|
key: 'y',
|
|
text: COMMA,
|
|
x: 88,
|
|
y: 40,
|
|
inputWidth: 21,
|
|
labelWidth: 5
|
|
}, {
|
|
text: '(x, y)',
|
|
x: 125,
|
|
y: 40,
|
|
labelWidth: 33,
|
|
noInput: true
|
|
}, {
|
|
key: 'tooltip',
|
|
text: 'Tooltip',
|
|
inputWidth: 105,
|
|
x: 170,
|
|
y: 40
|
|
}, {
|
|
key: LABEL,
|
|
text: 'Label',
|
|
inputWidth: 92,
|
|
x: 10,
|
|
y: 65
|
|
}, {
|
|
key: 'labelalign',
|
|
text: 'Align',
|
|
labelWidth: 70,
|
|
inputWidth: 110,
|
|
inputType: 'select',
|
|
innerHTML: '<option></option><option value="top">Top</option><option value="middle">Middle</option>' +
|
|
'<option value="bottom">Bottom</option>',
|
|
x: 145,
|
|
y: 63
|
|
}, {
|
|
key: 'color',
|
|
text: 'Color',
|
|
x: 10,
|
|
y: 90,
|
|
inputWidth: 60
|
|
}, {
|
|
key: 'colorOut',
|
|
innerHTML: ' ',
|
|
x: 85,
|
|
y: 90,
|
|
inputWidth: 15,
|
|
inputType: 'span'
|
|
}, {
|
|
key: 'alpha',
|
|
text: 'Alpha',
|
|
x: 170,
|
|
y: 90,
|
|
inputWidth: 20
|
|
}, {
|
|
key: 'draggable',
|
|
text: 'Allow Drag',
|
|
value: true,
|
|
inputWidth: 20,
|
|
x: 250,
|
|
y: 90,
|
|
labelWidth: 58,
|
|
inputPaddingTop: 3,
|
|
type: 'checkbox'
|
|
}, {
|
|
key: 'shape',
|
|
text: 'Shape',
|
|
inputType: 'select',
|
|
inputWidth: 97,
|
|
innerHTML: '<option value="rect">Rectangle</option><option value="circ">Circle</option><option ' +
|
|
'value="poly">Polygon</option>',
|
|
x: 10,
|
|
y: 115
|
|
}, {
|
|
key: 'rectHeight',
|
|
text: 'Height',
|
|
x: 170,
|
|
y: 115,
|
|
inputWidth: 20
|
|
}, {
|
|
key: 'rectWidth',
|
|
text: 'Width',
|
|
x: 255,
|
|
y: 115,
|
|
inputWidth: 20
|
|
}, {
|
|
key: 'circPolyRadius',
|
|
text: 'Radius',
|
|
x: 170,
|
|
y: 115,
|
|
inputWidth: 20
|
|
}, {
|
|
key: 'polySides',
|
|
text: 'Sides',
|
|
x: 255,
|
|
y: 115,
|
|
inputWidth: 20
|
|
}, {
|
|
key: 'link',
|
|
text: 'Link',
|
|
x: 10,
|
|
y: 140,
|
|
inputWidth: 92
|
|
}, {
|
|
key: 'image',
|
|
text: 'Image',
|
|
type: 'checkbox',
|
|
inputPaddingTop: 4,
|
|
inputWidth: 20,
|
|
x: 10,
|
|
y: 170
|
|
}, {
|
|
key: 'imgUrl',
|
|
text: 'URL',
|
|
inputWidth: 105,
|
|
x: 170,
|
|
y: 170
|
|
}, {
|
|
key: 'imgWidth',
|
|
text: 'Width',
|
|
inputWidth: 20,
|
|
x: 10,
|
|
y: 195
|
|
}, {
|
|
key: 'imgHeight',
|
|
text: 'Height',
|
|
inputWidth: 20,
|
|
x: 82,
|
|
y: 195
|
|
}, {
|
|
key: 'imgAlign',
|
|
text: 'Align',
|
|
inputType: 'select',
|
|
inputWidth: 75,
|
|
innerHTML: '<option value="top">Top</option><option value="middle">Middle</option><option ' +
|
|
'value="bottom">Bottom</option>',
|
|
x: 170,
|
|
y: 195
|
|
}],
|
|
showNodeUpdateUI: (function() {
|
|
var manageShapeFields = function() {
|
|
var ui = this.graphics.cacheUpdateUI,
|
|
fields = ui.fields,
|
|
ele = fields.shape,
|
|
shapeFields = ['rectWidth', 'rectHeight', 'circPolyRadius',
|
|
'polySides'
|
|
],
|
|
i = shapeFields.length,
|
|
key;
|
|
|
|
while (i--) {
|
|
key = shapeFields[i];
|
|
if (/rect|poly|circ/ig.test(key)) {
|
|
ui.labels[key].hide();
|
|
ui.fields[key].hide();
|
|
}
|
|
if (new RegExp(pluck(ele.val(), 'rect'), 'ig').test(key)) {
|
|
ui.labels[key].show();
|
|
ui.fields[key].show();
|
|
}
|
|
}
|
|
},
|
|
showGivenColor = function() {
|
|
var ui = this.graphics.cacheUpdateUI,
|
|
fields = ui.fields,
|
|
color = getValidColor(fields.color.val());
|
|
|
|
color && fields.colorOut.css({
|
|
background: parseColor(color)
|
|
});
|
|
},
|
|
manageImageFields = function(chart, animate) {
|
|
var ui = this.graphics.cacheUpdateUI,
|
|
fields = ui.fields,
|
|
ele = fields.image,
|
|
chartHeight = chart.config.height,
|
|
padding = 5,
|
|
isChecked = ele.val(),
|
|
animation = animate ? 300 : 0,
|
|
imgKey = ['imgWidth', 'imgHeight', 'imgAlign', 'imgUrl'],
|
|
dialogHeight,
|
|
i,
|
|
key;
|
|
|
|
dialogHeight = isChecked ? 250 : 215;
|
|
|
|
ui.ok.hide();
|
|
ui.cancel.hide();
|
|
ui.remove.hide();
|
|
ui.error.hide();
|
|
i = imgKey.length;
|
|
while (!isChecked && i--) {
|
|
key = imgKey[i];
|
|
ui.labels[key].hide();
|
|
ui.fields[key].hide();
|
|
}
|
|
|
|
lib.danimate.animate(ui.dialog.element, {
|
|
top: (chartHeight - dialogHeight) / 2,
|
|
height: dialogHeight
|
|
}, animation, 'linear', function() {
|
|
i = imgKey.length;
|
|
while (i-- && isChecked) {
|
|
key = imgKey[i];
|
|
ui.labels[key].show();
|
|
ui.fields[key].show();
|
|
}
|
|
ui.ok.attr({
|
|
y: dialogHeight - 23 - padding
|
|
}).show();
|
|
ui.cancel.attr({
|
|
y: dialogHeight - 23 - padding
|
|
}).show();
|
|
ui.remove.attr({
|
|
y: dialogHeight - 23 - padding
|
|
});
|
|
ui.error.attr({
|
|
y: dialogHeight - 23 - padding + 4
|
|
}).show();
|
|
if (ui.edit) {
|
|
ui.remove.show();
|
|
} else {
|
|
ui.remove.hide();
|
|
}
|
|
});
|
|
|
|
};
|
|
|
|
return function(chart, config, edit) {
|
|
var manager = this,
|
|
graphics = manager.graphics,
|
|
ui = graphics.cacheUpdateUI,
|
|
nodes = manager.nodes,
|
|
conf = chart.config,
|
|
animation = conf.animation,
|
|
inCanvasStyle = conf.style.inCanvasStyle || {},
|
|
paper = chart.components.paper,
|
|
borderStyle = '1px solid #cccccc',
|
|
inputStyle = {
|
|
width: 80 + PX,
|
|
border: borderStyle,
|
|
fontSize: 10 + PX,
|
|
lineHeight: 15 + PX,
|
|
padding: 2 + PX,
|
|
fontFamily: inCanvasStyle.fontFamily
|
|
},
|
|
labelStyle = {
|
|
textAlign: 'right'
|
|
},
|
|
fields = ui && ui.fields,
|
|
labels = ui && ui.labels,
|
|
dialog,
|
|
node,
|
|
index,
|
|
onSubmit = function() {
|
|
var fields = ui && ui.fields,
|
|
edit = ui.edit,
|
|
chart = manager.chart,
|
|
components = chart.components,
|
|
xMin,
|
|
yMin,
|
|
datasets,
|
|
sLn,
|
|
idFound,
|
|
id,
|
|
submitObj,
|
|
shapeType;
|
|
|
|
xMin = components.xAxis[0].config.axisRange.min;
|
|
yMin = components.yAxis[0].config.axisRange.min;
|
|
datasets = manager.datasets;
|
|
sLn = datasets.length;
|
|
|
|
if (fields) {
|
|
switch (fields.shape.val()) {
|
|
case 'circ':
|
|
shapeType = CIRCLE;
|
|
break;
|
|
case 'poly':
|
|
shapeType = POLYGON;
|
|
break;
|
|
default:
|
|
shapeType = RECTANGLE;
|
|
break;
|
|
}
|
|
|
|
submitObj = {
|
|
x: getFirstValue(fields.x.val(), xMin),
|
|
y: getFirstValue(fields.y.val(), yMin),
|
|
id: id = fields.id.val(),
|
|
datasetId: fields.dataset.val(),
|
|
name: fields.label.val(),
|
|
tooltext: fields.tooltip.val(),
|
|
color: fields.color.val(),
|
|
alpha: fields.alpha.val(),
|
|
labelalign: fields.labelalign.val(),
|
|
allowdrag: fields.draggable.val(),
|
|
shape: shapeType,
|
|
width: fields.rectWidth.val(),
|
|
height: fields.rectHeight.val(),
|
|
radius: fields.circPolyRadius.val(),
|
|
numsides: fields.polySides.val(),
|
|
imagenode: fields.image.val(),
|
|
imagewidth: fields.imgWidth.val(),
|
|
imageheight: fields.imgHeight.val(),
|
|
imagealign: fields.imgAlign.val(),
|
|
imageurl: fields.imgUrl.val(),
|
|
link: fields.link.val()
|
|
};
|
|
|
|
// Check if node already exists
|
|
if (nodes[submitObj.id]) {
|
|
idFound = true;
|
|
}
|
|
|
|
// If node already exists then we do not add a node and show an error
|
|
if (!idFound || edit !== undefined) {
|
|
node = nodes[submitObj.id] || {};
|
|
id = submitObj.datasetId;
|
|
// Dont add nodes when dataset id is not given
|
|
if (id !== BLANKSTRING || edit) {
|
|
id = Number(id);
|
|
index = node.config && node.config.index;
|
|
edit ? chart.updateNode(submitObj) : chart.addNode(submitObj);
|
|
ui.hide();
|
|
ui.visible = false;
|
|
}
|
|
|
|
return;
|
|
} else {
|
|
ui.error.attr({
|
|
text: 'ID already exist.'
|
|
});
|
|
fields.label.focus();
|
|
}
|
|
}
|
|
// Remobe disabled from attr
|
|
ui.enableFields();
|
|
},
|
|
onCancel = function() {
|
|
// Hide the UI
|
|
ui.hide();
|
|
ui.visible = false;
|
|
// Remobe disabled from attr
|
|
ui.enableFields();
|
|
// Hide error msg
|
|
ui.error.attr({
|
|
text: BLANK
|
|
});
|
|
ui.visible = false;
|
|
},
|
|
onDelete = function() {
|
|
chart.deleteNode(ui.fields.id.val());
|
|
ui.hide();
|
|
ui.visible = false;
|
|
};
|
|
|
|
if (!ui) {
|
|
ui = graphics.cacheUpdateUI = this.createHtmlDialog(chart,
|
|
350, 215, onSubmit, onCancel, onDelete);
|
|
// add fields.
|
|
dialog = ui.dialog;
|
|
labels = ui.labels = {};
|
|
fields = ui.fields = {};
|
|
}
|
|
ui.config = config;
|
|
ui.edit = edit;
|
|
if (!ui.error) {
|
|
ui.error = paper.html('span', {
|
|
color: 'ff0000',
|
|
x: 30,
|
|
y: 228
|
|
}, undefined, dialog);
|
|
}
|
|
if (!ui.enableFields) {
|
|
ui.enableFields = function() {
|
|
var key;
|
|
for (key in config) {
|
|
if (config[key] && config[key].disabled && fields[key]) {
|
|
fields[key].element.removeAttribute('disabled');
|
|
}
|
|
}
|
|
};
|
|
}
|
|
if (!ui.clearFields) {
|
|
ui.clearFields = function() {
|
|
var key,
|
|
fields = ui.fields;
|
|
for (key in fields) {
|
|
if (!fields[key].element.disabled) {
|
|
fields[key].element.value = BLANKSTRING;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
each(this.nodeUpdateUIDefinition, function(def) {
|
|
var field,
|
|
key = def.key,
|
|
attrs = {},
|
|
confObj = config[key] || {},
|
|
innerHTML,
|
|
value;
|
|
|
|
!labels[key] && (labels[key] = paper.html(LABEL, {
|
|
x: def.x,
|
|
y: def.y,
|
|
width: def.labelWidth || 45,
|
|
text: def.text
|
|
}, labelStyle, dialog));
|
|
|
|
|
|
// No need to proceed of this label has no input box
|
|
// associated with itself.
|
|
if (def.noInput) {
|
|
return;
|
|
}
|
|
|
|
field = fields[key];
|
|
|
|
if (!field) {
|
|
inputStyle.border = def.type == 'checkbox' ? BLANK : borderStyle;
|
|
field = fields[key] =
|
|
paper.html(def.inputType || 'input', {
|
|
x: def.labelWidth && (def.labelWidth + 5) || 50,
|
|
y: -2 + (def.inputPaddingTop || 0),
|
|
width: def.inputWidth || 50,
|
|
name: key || BLANKSTRING
|
|
}, inputStyle);
|
|
|
|
if (def.inputType !== 'select') {
|
|
field.attr({
|
|
type: def.type || 'text'
|
|
}).on('keyup', ui.handleKeyPress);
|
|
}
|
|
field.add(labels[key]);
|
|
}
|
|
|
|
|
|
if (defined(innerHTML = getFirstValue(confObj.innerHTML, def.innerHTML))) {
|
|
attrs.innerHTML = innerHTML;
|
|
}
|
|
if (confObj.disabled) {
|
|
attrs.disabled = 'disabled';
|
|
} else {
|
|
|
|
field.element && (field.element.disabled = false);
|
|
}
|
|
field.attr(attrs);
|
|
if (defined(value = getFirstValue(confObj.value, def.value))) {
|
|
field.val(value);
|
|
}
|
|
|
|
key == 'shape' && field.on('change', function() {
|
|
manageShapeFields.call(manager, chart);
|
|
});
|
|
key == 'image' && field.on('click', function() {
|
|
manageImageFields.call(manager, chart, true);
|
|
});
|
|
key == 'color' && field.on('keyup', function() {
|
|
showGivenColor.call(manager, chart);
|
|
});
|
|
});
|
|
|
|
showGivenColor.call(this, chart);
|
|
manageImageFields.call(this, chart);
|
|
manageShapeFields.call(this, chart);
|
|
if (animation) {
|
|
ui.fadeIn('fast');
|
|
} else {
|
|
ui.show();
|
|
}
|
|
ui.visible = true;
|
|
ui.fields[edit ? LABEL : 'id'].focus();
|
|
};
|
|
})(),
|
|
getDataLimits: function() {
|
|
var manager = this,
|
|
datasets = manager.datasets,
|
|
i,
|
|
yMin = +Infinity,
|
|
yMax = -Infinity,
|
|
xMax = -Infinity,
|
|
xMin = +Infinity,
|
|
conf;
|
|
for (i = 0; i < datasets.length; i++) {
|
|
conf = datasets[i].dataset.config;
|
|
yMax = mathMax(yMax, conf.yMax);
|
|
yMin = mathMin(yMin, conf.yMin);
|
|
xMax = mathMax(xMax, conf.xMax);
|
|
xMin = mathMin(xMin, conf.xMin);
|
|
}
|
|
return {
|
|
max: yMax,
|
|
min: yMin,
|
|
xMax: xMax,
|
|
xMin: xMin
|
|
};
|
|
},
|
|
removeNodeDataset: function(index) {
|
|
var manager = this,
|
|
datasets = manager.datasets;
|
|
datasets.splice(index);
|
|
},
|
|
removeConnectorSet: function(index) {
|
|
var manager = this,
|
|
datasets = manager.connectorSet;
|
|
datasets.splice(index);
|
|
},
|
|
removeLabelSet: function(index) {
|
|
var manager = this,
|
|
datasets = manager.labelSet;
|
|
|
|
datasets.splice(index);
|
|
},
|
|
_clearConnectors: function() {
|
|
var manager = this,
|
|
nodes = manager.nodes,
|
|
id,
|
|
startConnectors,
|
|
endConnectors,
|
|
graphics,
|
|
j,
|
|
node;
|
|
// Deleting all connectors from nodes object
|
|
for (id in nodes) {
|
|
node = nodes[id];
|
|
if (node) {
|
|
startConnectors = node.config.startConnectors || {};
|
|
endConnectors = node.config.endConnectors || {};
|
|
for (j in startConnectors) {
|
|
graphics = {
|
|
graphics: startConnectors[j].graphics || {}
|
|
};
|
|
componentDispose.call(graphics);
|
|
}
|
|
for (j in endConnectors) {
|
|
graphics = {
|
|
graphics: endConnectors[j].graphics || {}
|
|
};
|
|
componentDispose.call(graphics);
|
|
}
|
|
}
|
|
}
|
|
// Clearing nodes object
|
|
manager.nodes = {};
|
|
}
|
|
}]);
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-dragcolumn',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
extend2 = lib.extend2,
|
|
COMPONENT = 'component',
|
|
DATASET_GROUP = 'datasetGroup',
|
|
math = Math,
|
|
mathCeil = math.ceil,
|
|
preDefStr = lib.preDefStr,
|
|
COLUMN = preDefStr.column;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET_GROUP, 'DragColumn', {
|
|
getJSONData: function () {
|
|
var manager = this,
|
|
chart = manager.chart,
|
|
datasets = chart.components.dataset,
|
|
rawDatasets = chart.jsonData && chart.jsonData.dataset,
|
|
jsonData = [],
|
|
dataset,
|
|
datasetObj,
|
|
rawDataset,
|
|
i,
|
|
len = datasets.length;
|
|
for (i = 0; i < len; i++) {
|
|
dataset = datasets[i];
|
|
rawDataset = extend2({}, rawDatasets[i]);
|
|
delete rawDataset.data;
|
|
datasetObj = dataset.getJSONData();
|
|
jsonData.push(extend2(rawDataset, datasetObj));
|
|
}
|
|
return jsonData;
|
|
},
|
|
//helper function of skipOverlapPlot()
|
|
_decidePlotableData : function (data, plotsPerBin, visible, isLast) {
|
|
var group = this,
|
|
stackSumValues = group.stackSumValue && group.stackSumValue[0],
|
|
i,
|
|
j,
|
|
k,
|
|
l,
|
|
chart = group.chart,
|
|
chartConfig = chart.config,
|
|
binSize = chartConfig.binSize,
|
|
lenData = data && data.length,
|
|
value,
|
|
dataConfig,
|
|
dataGraphics,
|
|
element,
|
|
limit = lenData - plotsPerBin,
|
|
count,
|
|
isDataRestored = chartConfig.isDataRestored,
|
|
drawLabelFlag,
|
|
labelSkipMatrics = mathCeil((1 / binSize) * chartConfig.labelBinSize),
|
|
lastPlotIndexPositive,
|
|
lastPlotIndexNegative,
|
|
positvePlot,
|
|
negativePlot;
|
|
|
|
|
|
for (k = 0, i = 0, j = 0, count = 0; k < limit && visible; k += plotsPerBin, i++, j++) {
|
|
drawLabelFlag = count % labelSkipMatrics;
|
|
count++;
|
|
positvePlot = negativePlot = undefined;
|
|
for(l = (k + plotsPerBin); l >= k + 1; l--) {
|
|
dataConfig = data[l].config;
|
|
dataGraphics = data[l].graphics;
|
|
element = dataGraphics && dataGraphics.element;
|
|
value = (stackSumValues && stackSumValues[l]) || dataConfig.setValue;
|
|
|
|
isDataRestored && (delete data[l].dragged);
|
|
|
|
if (!data[l].dragged) {
|
|
dataConfig.labelSkip = true;
|
|
dataConfig.isSkipped = true;
|
|
}
|
|
|
|
if(value >= 0) {
|
|
if(!positvePlot) {
|
|
positvePlot = value;
|
|
(drawLabelFlag === 0) && (delete dataConfig.labelSkip);
|
|
lastPlotIndexPositive = l;
|
|
delete dataConfig.isSkipped;
|
|
}
|
|
if(positvePlot < value) {
|
|
positvePlot = value;
|
|
lastPlotIndexPositive = l;
|
|
delete dataConfig.isSkipped;
|
|
}
|
|
} else {
|
|
if(!negativePlot) {
|
|
negativePlot = value;
|
|
(drawLabelFlag === 0) && (delete dataConfig.labelSkip);
|
|
lastPlotIndexNegative = l;
|
|
delete dataConfig.isSkipped;
|
|
}
|
|
if(negativePlot > value) {
|
|
negativePlot = value;
|
|
lastPlotIndexNegative = l;
|
|
delete dataConfig.isSkipped;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (drawLabelFlag === 0) {
|
|
data[lastPlotIndexPositive] && (delete data[lastPlotIndexPositive].config.labelSkip);
|
|
data[lastPlotIndexNegative] && (delete data[lastPlotIndexNegative].config.labelSkip);
|
|
}
|
|
}
|
|
isLast && (delete group.lastPlot);
|
|
}
|
|
}, COLUMN]);
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-dragarea',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
extend2 = lib.extend2,
|
|
math = Math,
|
|
mathCeil = math.ceil,
|
|
COMPONENT = 'component',
|
|
DATASET_GROUP = 'datasetGroup';
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET_GROUP, 'DragArea', {
|
|
getJSONData: function () {
|
|
var manager = this,
|
|
chart = manager.chart,
|
|
datasets = chart.components.dataset,
|
|
rawDatasets = chart.jsonData && chart.jsonData.dataset,
|
|
jsonData = [],
|
|
dataset,
|
|
datasetObj,
|
|
rawDataset,
|
|
i,
|
|
len = datasets.length;
|
|
for (i = 0; i < len; i++) {
|
|
dataset = datasets[i];
|
|
rawDataset = extend2({}, rawDatasets[i]);
|
|
delete rawDataset.data;
|
|
datasetObj = dataset.getJSONData();
|
|
jsonData.push(extend2(rawDataset, datasetObj));
|
|
}
|
|
return jsonData;
|
|
},
|
|
//helper function of skipOverlapPlot()
|
|
_decidePlotableData : function (data, plotsPerBin, visible) {
|
|
var group = this,
|
|
chart = group.chart,
|
|
chartConfig = chart.config,
|
|
isDataRestored = chartConfig.isDataRestored,
|
|
binSize = chartConfig.binSize,
|
|
i,
|
|
j,
|
|
k,
|
|
l,
|
|
lenData = data && data.length,
|
|
setValue,
|
|
dataConfig,
|
|
maxValueIndex,
|
|
minValueIndex,
|
|
maxValue,
|
|
minValue,
|
|
limit = lenData - plotsPerBin,
|
|
count,
|
|
drawLabelFlag,
|
|
labelSkipMatrics = mathCeil((1 / binSize) * chartConfig.labelBinSize);
|
|
|
|
for (k = 0, i = 0, j = 0, count = 0; k < limit && visible; k += plotsPerBin, i++, j++) {
|
|
drawLabelFlag = count % labelSkipMatrics;
|
|
count++;
|
|
maxValueIndex = minValueIndex = maxValue = minValue = undefined;
|
|
for(l = (k + plotsPerBin); l >= k + 1; l--) {
|
|
dataConfig = data[l].config;
|
|
setValue = dataConfig.setValue;
|
|
|
|
isDataRestored && (delete data[l].dragged);
|
|
|
|
if (!data[l].dragged) {
|
|
dataConfig.labelSkip = true;
|
|
dataConfig.isSkipped = true;
|
|
}
|
|
if (!maxValue) {
|
|
maxValueIndex = l;
|
|
maxValue = setValue;
|
|
} else {
|
|
if (maxValue < setValue) {
|
|
maxValueIndex = l;
|
|
maxValue = setValue;
|
|
}
|
|
}
|
|
|
|
if (!minValue) {
|
|
minValueIndex = l;
|
|
minValue = setValue;
|
|
} else {
|
|
if (minValue > setValue) {
|
|
minValueIndex = l;
|
|
minValue = setValue;
|
|
}
|
|
}
|
|
|
|
}
|
|
delete data[minValueIndex].config.isSkipped;
|
|
delete data[maxValueIndex].config.isSkipped;
|
|
if (drawLabelFlag === 0) {
|
|
delete data[minValueIndex].config.labelSkip;
|
|
delete data[maxValueIndex].config.labelSkip;
|
|
}
|
|
}
|
|
}
|
|
}, 'area']);
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-dragline',
|
|
function () {
|
|
var COMPONENT = 'component',
|
|
DATASET_GROUP = 'datasetGroup';
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET_GROUP, 'DragLine', {
|
|
|
|
//helper function of skipOverlapPlot()
|
|
_decidePlotableData :
|
|
FusionCharts.get(COMPONENT, [DATASET_GROUP, 'DragArea']).prototype._decidePlotableData
|
|
}, 'line']);
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-boxandwhisker2d',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
extend2 = lib.extend2,
|
|
COMPONENT = 'component',
|
|
DATASET_GROUP = 'datasetGroup',
|
|
preDefStr = lib.preDefStr,
|
|
configStr = preDefStr.configStr,
|
|
animationObjStr = preDefStr.animationObjStr,
|
|
COLUMN = preDefStr.column;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET_GROUP, 'boxandwhisker2d', {
|
|
draw : function() {
|
|
var group = this,
|
|
positionStackArr = group.positionStackArr,
|
|
length = positionStackArr.length,
|
|
i,
|
|
j,
|
|
subDataset,
|
|
subDatasetLen,
|
|
dataSet,
|
|
chart = group.chart,
|
|
elements = chart.components.canvas.config.clip,
|
|
parentContainer = chart.graphics.datasetGroup,
|
|
graphics = chart.graphics,
|
|
clipCanvas = elements['clip-canvas'].slice(0),
|
|
clipCanvasInit = extend2([], chart.components.canvas.config.clip['clip-canvas-init']),
|
|
dataLabelsLayer = graphics.datalabelsGroup,
|
|
|
|
animationObj = chart.get(configStr, animationObjStr),
|
|
animType = animationObj.animType,
|
|
animObj = animationObj.animObj,
|
|
dummyObj = animationObj.dummyObj,
|
|
animationDuration = animationObj.duration;
|
|
|
|
if (chart.fireInitialAnimation) {
|
|
parentContainer.attr({
|
|
'clip-rect': clipCanvasInit
|
|
});
|
|
|
|
dataLabelsLayer.attr({
|
|
'clip-rect': clipCanvasInit
|
|
});
|
|
|
|
}
|
|
chart.fireInitialAnimation = false;
|
|
|
|
parentContainer.animateWith(dummyObj, animObj, {
|
|
'clip-rect': clipCanvas
|
|
}, animationDuration, animType);
|
|
|
|
dataLabelsLayer.animateWith(dummyObj, animObj, {
|
|
'clip-rect': clipCanvas
|
|
}, animationDuration, animType);
|
|
|
|
group.preDrawCalculate();
|
|
group.drawSumValueFlag = true;
|
|
for( i=0; i<length; i++) {
|
|
subDataset = positionStackArr[i];
|
|
subDatasetLen = subDataset.length;
|
|
group.manageClip = true;
|
|
for(j=0; j<subDatasetLen; j++) {
|
|
dataSet = positionStackArr[i][j].dataSet;
|
|
dataSet.draw();
|
|
}
|
|
}
|
|
}
|
|
},COLUMN]);
|
|
}
|
|
]);
|
|
|
|
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-group-heatmap',
|
|
function () {
|
|
var global = this,
|
|
lib = global.hcLib,
|
|
COMPONENT = 'component',
|
|
DATASET_GROUP = 'datasetGroup',
|
|
preDefStr = lib.preDefStr,
|
|
COLUMN = preDefStr.column;
|
|
|
|
FusionCharts.register(COMPONENT, [DATASET_GROUP, 'heatmap', {
|
|
},COLUMN]);
|
|
}
|
|
]);
|
|
|
|
/* jshint ignore: end */
|
|
|
|
}));
|