Files
line_chart_demo/fusioncharts.powercharts.js
T

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 />&nbsp;<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: '&nbsp;',
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 */
}));