Files
line_chart_demo/fusioncharts.widgets.js
T

20538 lines
916 KiB
JavaScript

(function (factory) {
if (typeof module === 'object' && typeof module.exports !== "undefined") {
module.exports = factory;
} else {
factory(FusionCharts);
}
}(function (FusionCharts) {
/**
* @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.sparkcharts
* @_export fusioncharts.sparkcharts.js
*
*/
FusionCharts.register('module', ['private', 'modules.renderer.js-spark', function () {
var global = this,
lib = global.hcLib,
//strings
BLANKSTRING = lib.BLANKSTRING,
//add the tools thats are requared
pluck = lib.pluck,
pluckNumber = lib.pluckNumber,
extend2 = lib.extend2,//old: jarendererExtend / maegecolone
chartAPI = lib.chartAPI,
getLightColor = lib.graphics.getLightColor,
COMMASTRING = lib.COMMASTRING,
convertColor = lib.graphics.convertColor,
// chartPaletteStr = lib.chartPaletteStr,
getValidValue = lib.getValidValue,
// getFirstValue = lib.getFirstValue,
// getFirstAlpha = lib.getFirstAlpha,
win = global.window,
math = Math,
mathMin = math.min,
mathMax = math.max,
mathCeil = math.ceil,
// mathRound = math.round,
toRaphaelColor = lib.toRaphaelColor,
parseUnsafeString = lib.parseUnsafeString,
getColumnColor = lib.graphics.getColumnColor,
GUTTER_PADDING = 2,
parseColor = lib.graphics.parseColor,
COLOR_TRANSPARENT = lib.COLOR_TRANSPARENT,
UNDEFINED,
NORMALSTRING = 'normal',
defined = function (obj) {
return obj !== UNDEFINED && obj !== null;
},
extend = function (a, b) { /** @todo refactor dependency */
var n;
if (!a) {
a = {};
}
for (n in b) {
a[n] = b[n];
}
return a;
},
POSITION_BOTTOM = lib.POSITION_BOTTOM,
// POSITION_RIGHT = lib.POSITION_RIGHT,
// POSITION_LEFT = lib.POSITION_LEFT,
POSITION_MIDDLE = lib.POSITION_MIDDLE,
POSITION_START = lib.POSITION_START,
POSITION_END = lib.POSITION_END,
HUNDREDSTRING = lib.HUNDREDSTRING,
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname),
defaultGaugePaletteOptions = extend2({}, lib.defaultGaugePaletteOptions),
drawSparkValues = function () {
var dataSet = this,
chart = dataSet.chart,
chartConf = chart.config,
chartComponents = chart.components,
style = chartConf.dataLabelStyle,
paper = chartComponents.paper,
valuePadding = chartConf.valuepadding + GUTTER_PADDING,
dataLabelContainer = dataSet.graphics.dataLabelContainer || chart.graphics.datalabelsGroup,
sparkValues = chartConf.sparkValues || (chartConf.sparkValues = {}),
graphic = chart.graphics,
sparkLabels = graphic.sparkLabels || (graphic.sparkLabels = {}),
SmartLabel = chart.linkedItems.smartLabel,
animObj = chart.get('config', 'animationObj'),
transposeAnimDuration = animObj.transposeAnimDuration,
animType = animObj.animType,
START_BRACES = '[',
END_BRACES = ']',
SEPARATER = '|',
textAttr = {
'class': 'fusioncharts-label',
'text-anchor': POSITION_END,
fill: style.color,
'font-size': style.fontSize,
'font-weight': style.fontWeight,
'font-style': style.fontStyle,
'font-family': style.fontFamily,
visibility: 'visible'
},
attr = {
x: 0,
y: 0
};
// Spark values are not visible due to the clip-rect,
// so removing clip-rect in order to make spark labels visible
dataLabelContainer && dataLabelContainer.attr({
'clip-rect': null
});
attr.y = chartConf.canvasHeight * 0.5 + chartConf.canvasTop;
// openValue
attr.x = chartConf.canvasLeft - valuePadding;
if (sparkValues.openValue && sparkValues.openValue.label || sparkLabels.openValue) {
if (!sparkLabels.openValue) {
sparkLabels.openValue = paper.text({
text: sparkValues.openValue.label,
x: attr.x,
y: attr.y,
fill: sparkValues.openValue.color || textAttr.fill,
'text-anchor': POSITION_END,
'line-height': style.lineHeight,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding, style.borderRadius, style.borderDash],
visibility: 'visible'
}, dataLabelContainer);
}
else {
sparkLabels.openValue.attr({
text: sparkValues.openValue.label,
fill: sparkValues.openValue.color || textAttr.fill,
'text-anchor': POSITION_END,
'line-height': style.lineHeight,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding, style.borderRadius, style.borderDash],
visibility: 'visible'
});
// Transpose the sumlabels with animation
if (transposeAnimDuration) {
sparkLabels.openValue.animate(attr, transposeAnimDuration, animType);
}
// Transpose without animation
else {
sparkLabels.openValue.attr(attr);
}
}
// sparkLabels.openValue.attr({
// text: sparkValues.openValue.label
// })
// .attr(textAttr)
// .attr({
// 'line-height': style.lineHeight,
// 'text-bound': [style.backgroundColor, style.borderColor,
// style.borderThickness, style.borderPadding, style.borderRadius, style.borderDash]
// })
// .css('color', sparkValues.openValue.color);
// // Transpose the sumlabels with animation
// if (transposeAnimDuration) {
// sparkLabels.openValue.animate(attr, transposeAnimDuration, animType);
// }
// // Transpose without animation
// else {
// sparkLabels.openValue.attr(attr);
// }
}
// closeValue
textAttr['text-anchor'] = POSITION_START;
attr.x = chartConf.canvasWidth + chartConf.canvasLeft + valuePadding;
if (sparkValues.closeValue && sparkValues.closeValue.label || sparkLabels.closeValue) {
if (!sparkLabels.closeValue) {
sparkLabels.closeValue = paper.text({
text: sparkValues.closeValue.label,
x: attr.x,
y: attr.y,
fill: sparkValues.closeValue.color || textAttr.fill,
'text-anchor': POSITION_START,
'line-height': style.lineHeight,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding, style.borderRadius, style.borderDash],
visibility: 'visible'
}, dataLabelContainer);
}
else {
sparkLabels.closeValue.attr({
text: sparkValues.closeValue.label,
fill: sparkValues.closeValue.color || textAttr.fill,
'text-anchor': POSITION_START,
'line-height': style.lineHeight,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding, style.borderRadius, style.borderDash],
visibility: 'visible'
});
if (transposeAnimDuration) {
sparkLabels.closeValue.animate(attr, transposeAnimDuration, animType);
}
// Transpose without animation
else {
sparkLabels.closeValue.attr(attr);
}
}
// sparkLabels.closeValue.attr({
// text: sparkValues.closeValue.label
// })
// .attr(textAttr)
// .attr({
// 'line-height': style.lineHeight,
// 'text-bound': [style.backgroundColor, style.borderColor,
// style.borderThickness, style.borderPadding, style.borderRadius, style.borderDash]
// })
// .css('color', sparkValues.closeValue.color);
// // Transpose the sumlabels with animation
// if (transposeAnimDuration) {
// sparkLabels.closeValue.animate(attr, transposeAnimDuration, animType);
// }
// // Transpose without animation
// else {
// sparkLabels.closeValue.attr(attr);
// }
// textAttr.x += sparkLabels.closeValue._getBBox().width;
attr.x += sparkValues.closeValue.smartObj &&
sparkValues.closeValue.smartObj.width + GUTTER_PADDING + valuePadding || 0;
}
// High-low value
if (sparkValues.highLowValue && sparkValues.highLowValue.label || sparkLabels.highValue) {
if (sparkValues.highLowValue && sparkValues.highLowValue.label === BLANKSTRING) {
SEPARATER = START_BRACES = END_BRACES = BLANKSTRING;
}
SmartLabel.useEllipsesOnOverflow(chartConf.useEllipsesWhenOverflow);
SmartLabel.setStyle(style);
if (!sparkLabels.startBraces) {
sparkLabels.startBraces = paper.text({
text: START_BRACES,
x: attr.x,
y: attr.y,
'text-anchor': POSITION_START,
visibility: 'visible'
}, dataLabelContainer);
// .attr(attr)
// .attr(textAttr);
}
else {
// Transpose the sumlabels with animation
if (transposeAnimDuration) {
sparkLabels.startBraces.animate(attr, transposeAnimDuration, animType);
}
// Transpose without animation
else {
sparkLabels.startBraces.attr(attr);
}
}
attr.x += SmartLabel.getSmartText(START_BRACES).width;
if (!sparkLabels.highValue) {
sparkLabels.highValue = paper.text({
text: sparkValues.highValue.label,
x: attr.x,
y: attr.y,
'text-anchor': POSITION_START,
fill: sparkValues.highValue.color || textAttr.fill,
visibility: 'visible'
}, dataLabelContainer);
// .attr(attr)
// .attr(textAttr);
}
else {
sparkLabels.highValue.attr({
text: sparkValues.highValue.label,
'text-anchor': POSITION_START,
fill: sparkValues.highValue.color || textAttr.fill,
visibility: 'visible'
});
if (transposeAnimDuration) {
sparkLabels.highValue.animate(attr, transposeAnimDuration, animType);
}
// Transpose without animation
else {
sparkLabels.highValue.attr(attr);
}
}
attr.x += SmartLabel.getSmartText(sparkValues.highValue.label).width;
if (!sparkLabels.separater) {
sparkLabels.separater = paper.text({
text: SEPARATER,
x: attr.x,
y: attr.y,
'text-anchor': POSITION_START,
visibility: 'visible'
}, dataLabelContainer);
// .attr(attr)
// .attr(textAttr);
}
else {
if (transposeAnimDuration) {
sparkLabels.separater.animate(attr, transposeAnimDuration, animType);
}
// Transpose without animation
else {
sparkLabels.separater.attr(attr);
}
}
attr.x += SmartLabel.getSmartText(SEPARATER).width;
if (!sparkLabels.lowValue) {
sparkLabels.lowValue = paper.text({
text: sparkValues.lowValue.label,
x: attr.x,
y: attr.y,
'text-anchor': POSITION_START,
fill: sparkValues.lowValue.color || textAttr.fill,
visibility: 'visible'
}, dataLabelContainer);
// .attr(attr)
// .attr(textAttr);
}
else {
sparkLabels.lowValue.attr({
text: sparkValues.lowValue.label,
'text-anchor': POSITION_START,
fill: sparkValues.lowValue.color || textAttr.fill,
visibility: 'visible'
});
if (transposeAnimDuration) {
sparkLabels.lowValue.animate(attr, transposeAnimDuration, animType);
}
// Transpose without animation
else {
sparkLabels.lowValue.attr(attr);
}
}
attr.x += SmartLabel.getSmartText(sparkValues.lowValue.label).width;
if (!sparkLabels.endBraces) {
sparkLabels.endBraces = paper.text({
text: END_BRACES,
x: attr.x,
y: attr.y,
'text-anchor': POSITION_START,
visibility: 'visible'
}, dataLabelContainer);
// .attr(attr)
// .attr(textAttr);
}
else {
if (transposeAnimDuration) {
sparkLabels.endBraces.animate(attr, transposeAnimDuration, animType);
}
// Transpose without animation
else {
sparkLabels.endBraces.attr(attr);
}
}
// SmartLabel.useEllipsesOnOverflow(chartConf.useEllipsesWhenOverflow);
// SmartLabel.setStyle(style);
// startBraces
// sparkLabels.startBraces
// .attr({
// text: START_BRACES
// });
// // Transpose the sumlabels with animation
// if (transposeAnimDuration) {
// sparkLabels.startBraces.animate(attr, transposeAnimDuration, animType);
// }
// // Transpose without animation
// else {
// sparkLabels.startBraces.attr(attr);
// }
// attr.x += SmartLabel.getSmartText(START_BRACES).width;
// highValue
// sparkLabels.highValue
// .attr({
// text: sparkValues.highValue.label
// })
// .css('color', sparkValues.highValue.color);
// Transpose the sumlabels with animation
// if (transposeAnimDuration) {
// sparkLabels.highValue.animate(attr, transposeAnimDuration, animType);
// }
// // Transpose without animation
// else {
// sparkLabels.highValue.attr(attr);
// }
// attr.x += SmartLabel.getSmartText(sparkValues.highValue.label).width;
// separater
// sparkLabels.separater
// .attr({
// text: SEPARATER
// });
// Transpose the sumlabels with animation
// if (transposeAnimDuration) {
// sparkLabels.separater.animate(attr, transposeAnimDuration, animType);
// }
// // Transpose without animation
// else {
// sparkLabels.separater.attr(attr);
// }
// attr.x += SmartLabel.getSmartText(SEPARATER).width;
// lowValue
// sparkLabels.lowValue
// .attr({
// text: sparkValues.lowValue.label
// })
// .css('color', sparkValues.lowValue.color);
// Transpose the sumlabels with animation
// if (transposeAnimDuration) {
// sparkLabels.lowValue.animate(attr, transposeAnimDuration, animType);
// }
// // Transpose without animation
// else {
// sparkLabels.lowValue.attr(attr);
// }
// attr.x += SmartLabel.getSmartText(sparkValues.lowValue.label).width;
// endBraces
// sparkLabels.endBraces
// .attr({
// text: END_BRACES
// });
// Transpose the sumlabels with animation
// if (transposeAnimDuration) {
// sparkLabels.endBraces.animate(attr, transposeAnimDuration, animType);
// }
// // Transpose without animation
// else {
// sparkLabels.endBraces.attr(attr);
// }
}
dataSet.labelDrawn = true;
},
_drawPeriod = function () {
var dataSet = this,
chart = dataSet.chart,
chartAttr = chart.jsonData.chart,
components = chart.components,
colorM = components.colorManager,
dataArr = dataSet.components.data,
axis = components.xAxis[0],
periodLength = pluckNumber(chartAttr.periodlength, 0),
axisLimit;
axisLimit = axis.getLimit();
axis.config.band.isDraw = true;
periodLength && axis.setAxisConfig({
alternateGridColor: pluck(chartAttr.periodcolor, colorM.getColor('periodColor')),
alternateGridAlpha: pluck(chartAttr.periodalpha, 100),
showAlternateGridColor : true,
categoryNumDivLines: dataArr && ((axisLimit.max - axisLimit.min) / periodLength - 1),
categoryDivLinesFromZero: 0
});
axis.draw();
};
chartAPI('sparkchartbase', {
standaloneInit: true,
creditLabel: creditLabel,
showBorder: 0,
chartTopMargin: 3,
chartRightMargin: 3,
chartBottomMargin: 3,
chartLeftMargin: 3,
canvasBorderThickness: 1,
subTitleFontSizeExtender: 0,
subTitleFontWeight: 0,
defaultPaletteOptions: extend(extend2({}, defaultGaugePaletteOptions), {
//Store colors now
paletteColors: [['555555', 'A6A6A6', 'CCCCCC', 'E1E1E1', 'F0F0F0'],
['A7AA95', 'C4C6B7', 'DEDFD7', 'F2F2EE'],
['04C2E3', '66E7FD', '9CEFFE', 'CEF8FF'],
['FA9101', 'FEB654', 'FED7A0', 'FFEDD5'],
['FF2B60', 'FF6C92', 'FFB9CB', 'FFE8EE']],
//Store other colors
// ------------- For 2D Chart ---------------//
//We're storing 5 combinations, as we've 5 defined palettes.
bgColor: ['FFFFFF', 'CFD4BE,F3F5DD', 'C5DADD,EDFBFE', 'A86402,FDC16D', 'FF7CA0,FFD1DD'],
bgAngle: [270, 270, 270, 270, 270],
bgRatio: ['0,100', '0,100', '0,100', '0,100', '0,100'],
bgAlpha: ['100', '60,50', '40,20', '20,10', '30,30'],
canvasBgColor: ['FFFFFF', 'FFFFFF', 'FFFFFF', 'FFFFFF', 'FFFFFF'],
canvasBgAngle: [0, 0, 0, 0, 0],
canvasBgAlpha: ['100', '100', '100', '100', '100'],
canvasBgRatio: [BLANKSTRING, BLANKSTRING, BLANKSTRING, BLANKSTRING, BLANKSTRING],
canvasBorderColor: ['BCBCBC', 'BEC5A7', '93ADBF', 'C97901', 'FF97B1'],
toolTipBgColor: ['FFFFFF', 'FFFFFF', 'FFFFFF', 'FFFFFF', 'FFFFFF'],
toolTipBorderColor: ['545454', '545454', '415D6F', '845001', '68001B'],
baseFontColor: ['333333', '60634E', '025B6A', 'A15E01', '68001B'],
trendColor: ['666666', '60634E', '415D6F', '845001', '68001B'],
plotFillColor: ['666666', 'A5AE84', '93ADBF', 'C97901', 'FF97B1'],
borderColor: ['767575', '545454', '415D6F', '845001', '68001B'],
borderAlpha: [50, 50, 50, 50, 50],
periodColor: ['EEEEEE', 'ECEEE6', 'E6ECF0', 'FFF4E6', 'FFF2F5'],
//Colors for win loss chart
winColor: ['666666', '60634E', '025B6A', 'A15E01', 'FF97B1'],
lossColor: ['CC0000', 'CC0000', 'CC0000', 'CC0000', 'CC0000'],
drawColor: ['666666', 'A5AE84', '93ADBF', 'C97901', 'FF97B1'],
scorelessColor: ['FF0000', 'FF0000', 'FF0000', 'FF0000', 'FF0000']
}),
_setAxisLimits : function () {
var iapi = this,
yAxis = iapi.components.yAxis;
yAxis[0] && yAxis[0].setAxisConfig({
numDivLines: 0
});
chartAPI.mscartesian._setAxisLimits.call(iapi);
},
/*
* Returns the postion for the caption placement.
* @return extra spaces.
*/
_fetchCaptionPos: function () {
var extraSpace,
iapi = this,
components = iapi.components,
caption = components.caption,
captionConfig = caption.config;
// check if even after placing the caption
// space available on right.
//left aligned.
/** @todo need to optimize this logic */
if (captionConfig.isOnLeft) {
extraSpace = -1;
}
// right aligned
else {
extraSpace = -1;
}
return extraSpace;
},
_spaceManager: function () {
// todo marge _allocateSpace and _spacemanager
var availableWidth,
availableHeight,
iapi = this,
config = iapi.config,
components = iapi.components,
// xAxis = components.xAxis && components.xAxis[0],
// yAxis = components.yAxis && components.yAxis[0],
// legend = components.legend,
// legendPosition = legend.config.legendPos,
// xDepth = config.xDepth,
// yDepth = config.yDepth,
// allottedSpace,
canvasBaseDepth = config.canvasBaseDepth,
// canvasBasePadding = config.canvasBasePadding,
canvasBorderWidth = components.canvas.config.canvasBorderWidth,
// showRTValue = config.realTimeConfig && config.realTimeConfig.showRTValue,
chartBorderWidth = config.borderWidth,
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;
iapi._allocateSpace ( {
top : chartBorderWidth,
bottom : chartBorderWidth,
left : chartBorderWidth,
right : chartBorderWidth
});
// if (legendPosition === 'right') {
// allottedSpace = config.availableWidth * 0.4;
// }
// else {
// allottedSpace = config.availableHeight * 0.4;
// }
// availableHeight = config.availableHeight * 0.225;
// iapi._manageActionBarSpace && iapi._allocateSpace(iapi._manageActionBarSpace(availableHeight));
//****** Manage space
// availableWidth = config.availableWidth * 0.7;
// yAxis && iapi._allocateSpace (yAxis.placeAxis (availableWidth));
//No space is allocated for legend drawing in single series charts
// iapi._manageLegendSpace(allottedSpace);
// availableHeight = (legendPosition === POSITION_BOTTOM) ? config.availableHeight * 0.225 :
// config.availableWidth *0.225;
// a space manager that manages the space for the tools as well as the captions.
// iapi._manageChartMenuBar(availableHeight);
// availableHeight = config.availableHeight * 0.3;
// config.realtimeEnabled && showRTValue && iapi._allocateSpace
// (iapi._realTimeValuePositioning (availableHeight));
// availableHeight = config.availableHeight * 0.6;
// xAxis && iapi._allocateSpace (xAxis.placeAxis (availableHeight));
// alocate the space for datasets
availableHeight = config.availableHeight * 0.325;
iapi._getDSspace && iapi._allocateSpace (iapi._getDSspace (availableHeight));
// alocate the space for scroll.
// availableHeight = config.availableHeight * 0.3;
// iapi._manageScrollerPosition && iapi._manageScrollerPosition(availableHeight);
//space management for 3d canvas
// if (yDepth) {
// iapi._allocateSpace ( {
// bottom : yDepth
// });
// config.shift = xDepth + canvasBasePadding + canvasBaseDepth;
// }
iapi._allocateSpace(iapi._manageActionBarSpace &&
iapi._manageActionBarSpace(config.availableHeight * 0.225) || {});
config.availableWidth = config.width;
availableWidth = config.availableWidth * 0.75;
availableWidth = (availableWidth - config.origMarginLeft - config.origMarginRight -
(config.borderWidth * 2));
availableWidth = mathMax(config.availableWidth * 0.1, availableWidth);
// a space manager that manages the space for the tools as well as the captions.
iapi._manageChartMenuBar(availableWidth);
// iapi._allocateSpace(iapi._manageCaptionSpacing(availableWidth));
availableWidth = (config.availableWidth - config.borderWidth * 2) * 0.75;
// Space management for SparkWinLoss and SparkLine charts
iapi._placeOpenCloseValues && iapi._allocateSpace(iapi._placeOpenCloseValues(availableWidth));
iapi._allocateSpace ({
top : canvasBorderWidth,
bottom : canvasBorderWidth,
left : canvasBorderWidth,
right : canvasBorderWidth
});
iapi._allocateSpace({
bottom: canvasBaseDepth
});
// Check for minimum canvas width and height
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;
}
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;
}
// 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
});
}
// Manage canvasMargins
// If there is user given canvasMargins apply those to the chart
if (config.origCanvasLeftMargin !== undefined) {
config.canvasWidth = mathMax((config.canvasWidth + config.canvasLeft -
config.origCanvasLeftMargin), config.availableWidth * 0.2);
// config.marginLeft = config.marginLeft - (config.canvasLeft - config.origCanvasLeftMargin);
config.canvasLeft = config.origCanvasLeftMargin;
}
},
_manageCaptionSpacing: function (availableWidth) {
var iapi = this,
chartConfig = iapi.config,
components = iapi.components,
//chartGraphics = iapi.graphics,
caption = components.caption,
subCaption = components.subCaption,
captionConfig = caption.config,
subCaptionConfig = subCaption.config,
captionComponents = caption.components,
subCaptionComponents = subCaption.components,
chartAttrs = iapi.jsonData.chart,
SmartLabel = iapi.linkedItems.smartLabel,
titleText = parseUnsafeString(chartAttrs.caption),
subTitleText = parseUnsafeString(chartAttrs.subcaption),
captionPadding = captionConfig.captionPadding = pluckNumber(chartAttrs.captionpadding, 2),
chartMenuBar = components.chartMenuBar,
chartMenuLogicalSpace = chartMenuBar && chartMenuBar.getLogicalSpace(),
height = chartConfig.height - ((chartMenuLogicalSpace && chartMenuLogicalSpace.height) || 0),
// width = chartConfig.width,
captionLineHeight = 0,
subCaptionLineHeight = 0,
//topGutterWidth = 5,
canvasBorderThickness = mathMax(components.canvas.config.canvasBorderThickness, 0),
captionHeight = 0,
captionWidth = 0,
// subCaptionHeight = 0,
// subCaptionWidth = 0,
allowedHeight = height * 0.7,
allowedWidth = availableWidth,
dimensions = {},
maxCaptionWidth,
captionObj,
subCaptionObj,
capStyle,
subCapStyle;
// text below 3px is not properly visible
if (allowedHeight > 3) {
if (captionPadding < canvasBorderThickness) {
captionPadding = canvasBorderThickness + 2;
}
captionConfig.captionPadding = subCaptionConfig.captionPadding = captionPadding;
if (titleText !== BLANKSTRING) { //calculatethe single line's height
capStyle = captionConfig.style;
captionLineHeight = captionConfig.captionLineHeight =
mathCeil(parseFloat(pluck(capStyle.fontHeight, capStyle.lineHeight), 10), 12);
// captionFontSize = subCaptionConfig.captionLineHeight =
// pluckNumber(parseInt(capStyle.fontSize, 10), 10);
}
if (subTitleText !== BLANKSTRING) {
subCapStyle = subCaptionConfig.style;
subCaptionLineHeight = mathCeil(parseInt(pluck(subCapStyle.lineHeight,
subCapStyle.fontHeight), 10), 12);
// subCaptionFontSize = pluckNumber(parseInt(subCapStyle.fontSize, 10), 10);
}
SmartLabel.useEllipsesOnOverflow(chartConfig.useEllipsesWhenOverflow);
if (captionLineHeight > 0 || subCaptionLineHeight > 0) {
SmartLabel.setStyle(capStyle);
captionObj = SmartLabel.getSmartText(titleText, allowedWidth, height);
// Forcefully increase width to give a gutter in caption and sub-caption
if (captionObj.width > 0) {
captionObj.width += GUTTER_PADDING;
captionHeight = captionObj.height;
}
SmartLabel.setStyle(subCapStyle);
subCaptionObj = SmartLabel.getSmartText(subTitleText, allowedWidth, height - captionHeight);
// Force fully increase width to give a gutter in caption and subCaption
if (subCaptionObj.width > 0) {
subCaptionObj.width += GUTTER_PADDING;
}
captionConfig.captionSubCaptionGap = captionObj.height + 0 +
(subCaptionLineHeight * 0.2);
maxCaptionWidth = Math.max(captionObj.width, subCaptionObj.width);
// Replace the caption and subCaption text with the new wrapped text
captionComponents.text = captionObj.text;
captionConfig.height = captionHeight = captionObj.height;
captionConfig.width = captionWidth = captionObj.width;
captionConfig.tooltext && (captionComponents.originalText = captionObj.tooltext);
subCaptionComponents.text = subCaptionObj.text;
subCaptionConfig.height = captionHeight = subCaptionObj.height;
subCaptionConfig.width = captionWidth = subCaptionObj.width;
subCaptionConfig.tooltext && (captionComponents.originalText = subCaptionObj.tooltext);
maxCaptionWidth = Math.max(captionObj.width, subCaptionObj.width);
captionConfig.captionPadding = captionPadding = mathMin(availableWidth - maxCaptionWidth,
captionPadding);
//Add caption padding, if either caption or sub-caption is to be shown
if (maxCaptionWidth > 0) {
maxCaptionWidth = mathMin(availableWidth, maxCaptionWidth + captionPadding);
}
captionConfig.maxCaptionWidth = subCaptionConfig.maxCaptionWidth = maxCaptionWidth;
// totalHeight = totalHeight || canvasBorderThickness;
if (captionConfig.isOnLeft) {
dimensions.left = maxCaptionWidth;
}
else {
dimensions.right = maxCaptionWidth;
}
}
}
return dimensions;
},
_manageCaptionPosition: function () {
var iapi = this,
chartConfig = iapi.config,
components = iapi.components,
caption = components.caption,
subCaption = components.subCaption,
captionConfig = caption.config,
subCaptionConfig = subCaption.config,
captionPosition = captionConfig.captionPosition,
maxWidth = mathMax(captionConfig.width, subCaptionConfig.width),
borderWidth = chartConfig.borderWidth || 0,
height = chartConfig.height,
sparkValues = chartConfig.sparkValues || {},
openValueWidth = sparkValues.openValueWidth || 0,
captionPadding = captionConfig.captionPadding,
captionSubCaptionGap = captionConfig.captionSubCaptionGap;
switch (captionPosition) {
case POSITION_MIDDLE:
captionConfig.y = ((height - (captionConfig.height + subCaptionConfig.height)) / 2) +
((captionConfig._offsetHeight || 0) * 0.5);
break;
case POSITION_BOTTOM:
captionConfig.y = (height - (captionConfig.height + subCaptionConfig.height)) -
chartConfig.marginBottom - borderWidth;
break;
default: // We put it on top by default
captionConfig.y = chartConfig.marginTop + borderWidth + (captionConfig._offsetHeight || 0);
break;
}
subCaptionConfig.y = captionConfig.y + captionSubCaptionGap;
if (captionConfig.isOnLeft) {
captionConfig.align = subCaptionConfig.align = POSITION_END;
captionConfig.x = subCaptionConfig.x = chartConfig.canvasLeft -
(borderWidth + openValueWidth + GUTTER_PADDING + captionPadding) +
chartConfig.borderWidth;
} else {
captionConfig.align = subCaptionConfig.align = POSITION_START;
captionConfig.x = subCaptionConfig.x = chartConfig.width -
chartConfig.marginRight - maxWidth - borderWidth;
}
}
}, chartAPI.sscartesian);
chartAPI('sparkcolumn', {
standaloneInit: true,
creditLabel: creditLabel,
friendlyName: 'sparkcolumn Chart',
defaultDatasetType: 'sparkcolumn',
// parse canvas cosmetics.
// parse canvas cosmetics.
_parseCanvasCosmetics: function () {
var canvasBorderThickness,
canBGAlpha,
showCanvasBorder,
shadow,
iapi = this,
config = iapi.config,
components = iapi.components,
canvasConfig = components.canvas.config,
chartAttrs = iapi.jsonData.chart,
colorM = components.colorManager,
is3D = iapi.is3D,
oriCanvasBorderThickness,
palleteString = is3D ? lib.chartPaletteStr.chart3D : lib.chartPaletteStr.chart2D,
isRoundEdges = canvasConfig.isRoundEdges = pluckNumber (chartAttrs.useroundedges, 0),
showAxisLine = pluckNumber(chartAttrs.showxaxisline, chartAttrs.showyaxisline, 0),
hideAxisLine = showAxisLine ? 0 : 1;
canvasConfig.canvasBorderRadius = pluckNumber (chartAttrs.plotborderradius, isRoundEdges ? 2 : 0);
showCanvasBorder = canvasConfig.showCanvasBorder =
Boolean (pluckNumber(chartAttrs.showcanvasborder, hideAxisLine, canvasBorderThickness,
isRoundEdges ? 0 : 1));
// Storing original canvasBorderThickness for future reference
oriCanvasBorderThickness = canvasConfig.oriCanvasBorderThickness = mathMax(pluckNumber(
chartAttrs.canvasborderthickness, isRoundEdges ? 0 : pluckNumber(iapi.canvasborderthickness, 1), 0));
canvasBorderThickness = canvasConfig.canvasBorderWidth = iapi.is3D ? 0 :
showCanvasBorder ? oriCanvasBorderThickness : 0;
canvasConfig.canvasBorderColor = convertColor (pluck (chartAttrs.canvasbordercolor,
colorM.getColor ('canvasBorderColor')),
pluck (chartAttrs.canvasborderalpha, colorM.getColor ('canvasBorderAlpha')));
canBGAlpha = canvasConfig.canBGAlpha = pluck (chartAttrs.canvasbgalpha,
colorM.getColor ('canvasBgAlpha'));
canvasConfig.canBGColor = {
FCcolor : {
color : pluck (chartAttrs.canvasbgcolor, colorM.getColor (palleteString.canvasBgColor)),
alpha : pluck (chartAttrs.canvasbgalpha, 100),
angle : pluck (chartAttrs.canvasbgangle, 0),
ratio : pluck (chartAttrs.canvasbgratio)
}
};
shadow = canvasConfig.shadow = pluckNumber (chartAttrs.showshadow, isRoundEdges, 0) && isRoundEdges ? {
enabled: true,
opacity: canBGAlpha / 100
} : 0;
canvasConfig.shadowOnCanvasFill = shadow && shadow.enabled;
// borderThickness = pluckNumber(chartAttrs.showborder, 1) ? pluckNumber(chartAttrs.borderthickness, 1) : 0;
// chart margins
config.origMarginTop = pluckNumber(chartAttrs.charttopmargin, 3);
config.origMarginLeft = pluckNumber(chartAttrs.chartleftmargin, 3);
config.origMarginBottom = pluckNumber(chartAttrs.chartbottommargin, 3);
config.origMarginRight = pluckNumber(chartAttrs.chartrightmargin, 3);
config.origCanvasLeftMargin = pluckNumber(chartAttrs.canvasleftmargin);
config.origCanvasRightMargin = pluckNumber(chartAttrs.canvasrightmargin);
config.origCanvasTopMargin = pluckNumber(chartAttrs.canvastopmargin);
config.origCanvasBottomMargin = pluckNumber(chartAttrs.canvasbottommargin);
// canvas padding
canvasConfig.canvasPadding = pluckNumber(chartAttrs.canvaspadding, 0);
canvasConfig.origCanvasTopPad = pluckNumber(chartAttrs.canvastoppadding, 0);
canvasConfig.origCanvasBottomPad = pluckNumber(chartAttrs.canvasbottompadding, 0);
canvasConfig.origCanvasLeftPad = pluckNumber(chartAttrs.canvasleftpadding, 0);
canvasConfig.origCanvasRightPad = pluckNumber(chartAttrs.canvasrightpadding, 0);
},
canvasBorderThickness: 1,
singleseries: false
}, chartAPI.sparkchartbase, {
showplotborder: 0,
enablemousetracking: true
});
FusionCharts.register('component', ['dataset', 'sparkcolumn', {
_setConfigure: function (newDataset) {
var dataSet = this,
chart = dataSet.chart,
chartAttr = chart.jsonData.chart,
conf = dataSet.config,
chartConfig = chart.config,
JSONData = dataSet.JSONData,
setDataArr = newDataset || JSONData.data,
setDataLen = setDataArr && setDataArr.length,
categories = chart.config.categories,
catLen = categories && categories.length,
len = (newDataset && newDataset.data.length) || mathMin(catLen, setDataLen),
showHoverEffect = chartConfig.plothovereffect,
components = chart.components,
colorM = components.colorManager,
isRoundEdges = chartConfig.useroundedges,
plotFillColor,
color,
borderColor,
hoverColor,
hoverAlpha,
hoverGradientColor,
hoverBorderColor,
hoverBorderAlpha,
hoverBorderThickness,
borderThickness,
config,
plotFillAlpha,
plotBorderAlpha,
plotBorderColor,
highColor,
lowColor,
highBorderColor,
lowBorderColor,
setData,
dataObj,
colorArr,
hoverColorArr,
i,
cLen,
cInd,
dataStore,
maxValue,
minValue;
conf.plotgradientcolor = BLANKSTRING;
conf.showvalues = pluckNumber(JSONData.showvalues, chartAttr.showvalues, 0);
conf.showShadow = pluckNumber(chartAttr.showshadow, 0);
this.__base__._setConfigure.call(this);
dataStore = dataSet.components.data;
maxValue = conf.maxValue;
minValue = conf.minValue;
plotFillColor = pluck(chartAttr.plotfillcolor, colorM.getColor('plotFillColor'));
plotFillAlpha = pluck(chartAttr.plotfillalpha, HUNDREDSTRING);
plotBorderAlpha = pluck(chartAttr.plotborderalpha, HUNDREDSTRING);
plotBorderColor = pluck(chartAttr.plotbordercolor, plotFillColor);
//Fill Color for high column and low column
highColor = pluck(chartAttr.highcolor, '000000');
lowColor = pluck(chartAttr.lowcolor, '000000');
highBorderColor = pluck(chartAttr.highbordercolor, chartAttr.plotbordercolor, highColor);
lowBorderColor = pluck(chartAttr.lowbordercolor, chartAttr.plotbordercolor, lowColor);
// conf.plotBorderThickness = borderThickness = pluckNumber(chartAttr.showplotborder, 0) ?
// pluckNumber(chartAttr.plotborderthickness, 1) : 0;
// Loop through datastore and change the cosmetics
for (i = 0; i < len; i++) {
// Original data provided by user
setData = setDataArr[i];
// Parsed data previously
dataObj = dataStore[i];
config = dataObj.config;
colorArr = null;
color = plotFillColor;
borderColor = plotBorderColor;
// Max value
if (config.setValue == maxValue) {
color = highColor;
borderColor = highBorderColor;
}
// Min value
if (dataObj.config.setValue == minValue) {
color = lowColor;
borderColor = lowBorderColor;
}
// Setting the color Array to be applied to the bar/column.
config.colorArr = colorArr = getColumnColor(
color + COMMASTRING + conf.plotgradientcolor,
plotFillAlpha,
'0',
'90',
isRoundEdges,
borderColor,
plotBorderAlpha,
0,
0);
// Parsing the hover effects only if showhovereffect is not 0.
if (showHoverEffect !== 0 && colorArr) {
hoverColor = hoverAlpha = UNDEFINED;
// Max value
if (config.setValue == maxValue) {
hoverColor = chartAttr.highhovercolor;
hoverAlpha = chartAttr.highhoveralpha;
}
// Min value
if (dataObj.config.setValue == minValue) {
hoverColor = chartAttr.lowhovercolor;
hoverAlpha = chartAttr.lowhoveralpha;
}
hoverColor = pluck(setData.hovercolor, JSONData.hovercolor, hoverColor,
chartAttr.plotfillhovercolor, chartAttr.columnhovercolor,
colorArr[0].FCcolor.color);
hoverColor = hoverColor.split(/\s{0,},\s{0,}/);
cLen = hoverColor.length;
for (cInd = 0; cInd < cLen; cInd++) {
hoverColor[cInd] = getLightColor(hoverColor[cInd], 70);
}
hoverColor = hoverColor.join(',');
hoverAlpha = pluck(setData.hoveralpha, JSONData.hoveralpha, hoverAlpha,
chartAttr.plotfillhoveralpha, chartAttr.columnhoveralpha, plotFillAlpha);
hoverGradientColor = pluck(setData.hovergradientcolor,
JSONData.hovergradientcolor, chartAttr.plothovergradientcolor, conf.plotgradientcolor);
!hoverGradientColor && (hoverGradientColor = BLANKSTRING);
hoverBorderColor = pluck(setData.borderhovercolor,
JSONData.borderhovercolor, chartAttr.plotborderhovercolor, conf.plotbordercolor);
hoverBorderAlpha = pluck(setData.borderhoveralpha,
JSONData.borderhoveralpha, chartAttr.plotborderhoveralpha,
chartAttr.plotfillhoveralpha, plotBorderAlpha, plotFillAlpha);
hoverBorderThickness = pluckNumber(setData.borderhoverthickness,
JSONData.borderhoverthickness, chartAttr.plotborderhoverthickness, borderThickness);
/* If no hover effects are explicitly defined and
* showHoverEffect is not 0 then hoverColor is set.
*/
if (showHoverEffect == 1 && hoverColor === colorArr[0].FCcolor.color) {
hoverColor = getLightColor(hoverColor, 70);
}
// setting the hover color array which is always applied except when showHoverEffect is not 0.
hoverColorArr = getColumnColor(
hoverColor + COMMASTRING + hoverGradientColor,
hoverAlpha,
'0',
'90',
isRoundEdges,
hoverBorderColor,
hoverBorderAlpha.toString(),
0,
0);
config.setRolloutAttr = {
fill: toRaphaelColor(colorArr[0]),
stroke: borderThickness && toRaphaelColor(colorArr[1]),
'stroke-width': borderThickness
};
config.setRolloverAttr = {
fill: toRaphaelColor(hoverColorArr[0]),
stroke: borderThickness && toRaphaelColor(hoverColorArr[1]),
'stroke-width': borderThickness
};
}
}
},
draw: function () {
var dataSet = this;
dataSet.__base__.draw.call(dataSet);
_drawPeriod.call(dataSet);
}
}, 'Column']);
FusionCharts.register('component', ['datasetGroup', 'SparkColumn', {
}, 'column']);
chartAPI('sparkwinloss', {
standaloneInit: true,
friendlyName: 'sparkwinloss Chart',
creditLabel: creditLabel,
defaultDatasetType: 'sparkwinloss',
canvasBorderThickness: 0,
applicableDSList: {
'sparkwinloss': true
},
_setAxisLimits : function () {
var iapi = this,
yAxis = iapi.components.yAxis;
chartAPI.mscartesian._setAxisLimits.call(iapi);
yAxis[0] && yAxis[0].setAxisRange({
min: -1,
max: 1
});
},
_placeOpenCloseValues: function (availableWidth) {
var iapi = this,
config = iapi.config,
smartLabel = iapi.linkedItems.smartLabel,
style = config.dataLabelStyle,
borderThickness = pluckNumber(style.borderThickness, 0),
valuePadding = iapi.config.valuepadding + GUTTER_PADDING + borderThickness,
openValueWidth = 0,
closeValueWidth = 0,
// height = chartConfig.height,
// width = availableWidth,
sparkValues = config.sparkValues || {},
left,
right;
smartLabel.useEllipsesOnOverflow(config.useEllipsesWhenOverflow);
smartLabel.setStyle(style);
if (sparkValues.openValue && sparkValues.openValue.label) {
sparkValues.openValue.smartObj = smartLabel.getSmartText(sparkValues.openValue.label);
openValueWidth = sparkValues.openValue.smartObj.width + valuePadding;
}
if (sparkValues.closeValue && sparkValues.closeValue.label) {
sparkValues.closeValue.smartObj = smartLabel.getSmartText(sparkValues.closeValue.label);
closeValueWidth += sparkValues.closeValue.smartObj.width + valuePadding;
}
if (sparkValues.highValue && sparkValues.highValue.label) {
sparkValues.highValue.smartObj = smartLabel.getSmartText(sparkValues.highValue.label);
}
if (sparkValues.lowValue && sparkValues.lowValue.label) {
sparkValues.lowValue.smartObj = smartLabel.getSmartText(sparkValues.lowValue.label);
}
if (sparkValues.highLowValue && sparkValues.highLowValue.label) {
sparkValues.highLowValue.smartObj = smartLabel.getSmartText(sparkValues.highLowValue.label);
closeValueWidth += sparkValues.highLowValue.smartObj.width + valuePadding;
}
// Restrict the space to availableWidth
left = sparkValues.openValueWidth = mathMin(openValueWidth, availableWidth);
right = sparkValues.closeValueWidth = mathMin(closeValueWidth, (availableWidth - left));
return {
left: left,
right: right
};
},
// parse canvas cosmetics.
_parseCanvasCosmetics: function () {
var canvasBorderThickness,
showCanvasBorder,
shadow,
iapi = this,
components = iapi.components,
config = iapi.config,
canvasConfig = components.canvas.config,
chartAttrs = iapi.jsonData.chart,
colorM = components.colorManager;
canvasConfig.canvasBorderRadius = 0;
canvasBorderThickness = canvasConfig.canvasBorderThickness = 0;
showCanvasBorder = canvasConfig.showCanvasBorder = 0;
canvasConfig.canvasBorderWidth = !showCanvasBorder ? 0 : canvasBorderThickness;
canvasConfig.canvasBorderColor = convertColor(pluck(chartAttrs.canvasbordercolor,
colorM.getColor('canvasBorderColor')));
// Make canvas background transparent for sparkWinLoss and sparkLine charts.
canvasConfig.canBGColor = COLOR_TRANSPARENT;
shadow = canvasConfig.shadow = 0;
canvasConfig.shadowOnCanvasFill = shadow && shadow.enabled;
// canvas padding
canvasConfig.origCanvasTopPad = pluckNumber(chartAttrs.canvastoppadding, 0);
canvasConfig.origCanvasBottomPad = pluckNumber(chartAttrs.canvasbottompadding, 0);
canvasConfig.origCanvasLeftPad = pluckNumber(chartAttrs.canvasleftpadding, 0);
canvasConfig.origCanvasRightPad = pluckNumber(chartAttrs.canvasrightpadding, 0);
canvasConfig.canvasPadding = 0;
config.origCanvasLeftMargin = pluckNumber(chartAttrs.canvasleftmargin);
config.origCanvasRightMargin = pluckNumber(chartAttrs.canvasrightmargin);
config.origCanvasTopMargin = pluckNumber(chartAttrs.canvastopmargin);
config.origCanvasBottomMargin = pluckNumber(chartAttrs.canvasbottommargin);
},
singleseries: true
}, chartAPI.sparkchartbase, {
enablemousetracking : true
});
FusionCharts.register('component', ['dataset', 'sparkwinloss', {
_setConfigure : function (newDataset, newIndex) {
var dataSet = this,
chart = dataSet.chart,
chartConfig = chart.config,
conf = dataSet.config,
JSONData = dataSet.JSONData,
setDataArr = newDataset || JSONData.data,
setDataLen = setDataArr && setDataArr.length,
categories = chart.config.categories,
catLen = categories && categories.length,
len = (newDataset && newDataset.data.length) || mathMin(catLen, setDataLen),
chartAttr = chart.jsonData.chart,
components = chart.components,
colorM = components.colorManager,
xAxis = components.xAxis[0],
index = dataSet.index || dataSet.positionIndex,
showplotborder = chartConfig.showplotborder,
plotColor = conf.plotColor = colorM.getPlotColor(index),
//plotBorderDash = pluckNumber(JSONData.dashed, chartAttr.plotborderdashed),
//usePlotGradientColor = pluckNumber(chartAttr.useplotgradientcolor, 1),
parseUnsafeString = lib.parseUnsafeString,
plotFillColor = pluck(chartAttr.plotfillcolor, colorM.getColor('plotFillColor')),
winColor = pluck(chartAttr.wincolor, colorM.getColor('winColor')),
lossColor = pluck(chartAttr.losscolor, colorM.getColor('lossColor')),
drawColor = pluck(chartAttr.drawcolor, colorM.getColor('drawColor')),
scorelessColor = pluck(chartAttr.scorelesscolor, colorM.getColor('scorelessColor')),
winHoverColor = chartAttr.winhovercolor,
lossHoverColor = chartAttr.losshovercolor,
drawHoverColor = chartAttr.drawhovercolor,
scoreLessHoverColor = chartAttr.scorelesshovercolor,
numWon = 0,
numLost = 0,
numDraw = 0,
formatedVal,
tempPlotfillAngle,
// toolText,
plotDashLen,
plotDashGap,
plotBorderThickness = chartConfig.plotborderthickness,
isRoundEdges = chartConfig.isroundedges,
showHoverEffect = chartConfig.plothovereffect,
plotfillAngle = conf.plotfillangle,
plotFillAlpha,
//plotRadius,
plotFillRatio,
//plotgradientcolor,
plotBorderAlpha,
plotBorderDashStyle,
initailPlotBorderDashStyle = conf.plotBorderDashStyle,
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,
setDisplayValue,
//definedGroupPadding,
isBar = chart.isBar,
is3D = chart.is3D,
//isStacked = chart.isStacked,
//stack100Percent,
//enableAnimation,
setDataDashed,
setDataPlotDashLen,
setDataPlotDashGap,
i,
maxValue = conf.maxValue || -Infinity,
minValue = conf.minValue || +Infinity,
showPlotBorder,
tempIndex;
if (!dataStore) {
dataStore = dataSet.components.data = [];
}
dataSet.__base__._setConfigure.call(dataSet);
conf.plotgradientcolor = '';
showPlotBorder = conf.showPlotBorder = pluckNumber(chartAttr.showplotborder, 0);
conf.plotborderalpha = plotBorderAlpha = showPlotBorder ? pluck(chartAttr.plotborderalpha,
plotFillAlpha, HUNDREDSTRING): 0;
conf.showTooltip = 0;
chartConfig.showtooltip = 0;
// Parsing the attributes and values at set level.
for (i = 0; i < len; i++) {
if (newDataset) {
setData = (newDataset && newDataset.data[i]);
if (newIndex !== undefined) {
tempIndex = newIndex + i ;
dataObj = dataStore[tempIndex];
}
else {
tempIndex = dataStore.length - len + i;
dataObj = dataStore[tempIndex];
}
}
else {
dataObj = dataStore[i];
setData = setDataArr[i];
}
config = dataObj && dataObj.config;
if (!dataObj) {
dataObj = dataStore[i] = {};
}
if (!dataObj.config) {
config = dataStore[i].config = {};
}
switch ((setData.value || '').toLowerCase()) {
case 'w':
plotColor = pluck(setData.color, winColor, plotFillColor);
hoverColor = pluck(setData.hovercolor, winHoverColor, plotColor);
config.setValue = setValue = 1;
numWon += 1;
break;
case 'l':
plotColor = pluck(setData.color, lossColor, plotFillColor);
hoverColor = pluck(setData.hovercolor, lossHoverColor, plotColor);
config.setValue = setValue = -1;
numLost += 1;
break;
case 'd':
plotColor = pluck(setData.color, drawColor, plotFillColor);
hoverColor = pluck(setData.hovercolor, drawHoverColor, plotColor);
config.setValue = setValue = 0.1;
numDraw += 1;
break;
default :
config.setValue = setValue = null;
}
if (setData.scoreless == 1) {
plotColor = pluck(setData.color, scorelessColor, plotFillColor);
hoverColor = pluck(setData.hovercolor, scoreLessHoverColor,
setData.color, scorelessColor, hoverColor);
}
config.toolText = false;
// config.showValue = pluckNumber(setData.showvalue, conf.showValues);
config.setLink = pluck(setData.link);
// config.toolTipValue = toolTipValue = yAxis.dataLabels(setValue);
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, conf.plotDashGap);
if (setValue !== null) {
maxValue = mathMax(maxValue, setValue);
minValue = mathMin(minValue, setValue);
}
config.plotBorderDashStyle = plotBorderDashStyle = setDataDashed === 1 ?
getDashStyle(setDataPlotDashLen, setDataPlotDashGap, plotBorderThickness) :
(setDataDashed === 0 ? 'none' : initailPlotBorderDashStyle);
plotFillAlpha = pluck(setData.alpha, conf.plotfillalpha);
plotBorderAlpha = pluck(setData.alpha, conf.plotborderalpha, plotFillAlpha).toString();
// Setting the angle for plot fill for negative data
if (setValue < 0 && !isRoundEdges) {
tempPlotfillAngle = conf.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 + ',' + conf.plotgradientcolor,
plotFillAlpha,
plotFillRatio = conf.plotfillratio,
plotfillAngle,
isRoundEdges,
conf.plotbordercolor,
plotBorderAlpha,
(isBar ? 1 : 0),
(is3D ? true : false)
);
label = config.label = getValidValue(parseUnsafeString(xAxis.getLabel(pluckNumber(tempIndex -
len, 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, conf.plotgradientcolor);
!hoverGradientColor && (hoverGradientColor = '');
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, conf.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 + ',' + hoverGradientColor,
hoverAlpha,
hoverRatio,
hoverAngle,
isRoundEdges,
hoverBorderColor,
hoverBorderAlpha.toString(),
(isBar ? 1 : 0),
(is3D ? true : false)
);
config.setRolloutAttr = {
fill: !is3D ? toRaphaelColor(colorArr[0])
: [toRaphaelColor(colorArr[0]), !chartConfig.use3dlighting],
stroke: showplotborder && toRaphaelColor(colorArr[1]),
'stroke-width': plotBorderThickness,
'stroke-dasharray': plotBorderDashStyle
};
config.setRolloverAttr = {
fill: !is3D ? toRaphaelColor(hoverColorArr[0])
: [toRaphaelColor(hoverColorArr[0]), !chartConfig.use3dlighting],
stroke: showplotborder && toRaphaelColor(hoverColorArr[1]),
'stroke-width': hoverBorderThickness,
'stroke-dasharray': hoverDashStyle
};
}
formatedVal = config.toolTipValue;
// config.toolText = toolText;
// config.setTooltext = toolText;
tempPlotfillAngle && (plotfillAngle = tempPlotfillAngle);
tempIndex++;
}
conf.maxValue = 1;
conf.minValue = -1;
if (pluckNumber(chartAttr.showvalue, 1) == 1) {
chart.config.sparkValues = {
closeValue: {
}
};
chart.config.sparkValues.closeValue.label = numWon + '-' + numLost + ((numDraw > 0) ?
('-' + numDraw) : BLANKSTRING);
}
},
draw: function () {
var dataSet = this;
dataSet.__base__.draw.call(dataSet);
_drawPeriod.call(dataSet);
},
drawLabel: drawSparkValues
},'column']);
FusionCharts.register('component', ['datasetGroup', 'SparkWinLoss', {
// Override draw function in order to stop clipping of dataLabes group
manageSpace: function () {
},
draw: function () {
var group = this,
positionStackArr = group.positionStackArr,
length = positionStackArr.length,
i,
j,
subDataset,
subDatasetLen,
dataSet,
chart = group.chart,
viewPortConfig = chart.config.viewPortConfig,
scaleX = viewPortConfig.scaleX || 1,
elements = chart.components.canvas.config.clip,
is3D = chart.is3D,
parentContainer = chart.graphics.columnGroup,
graphics = chart.graphics,
clipCanvas = elements['clip-canvas'].slice(0),
dataLabelsLayer = graphics.datalabelsGroup,
animationObj = chart.get('config', 'animationObj'),
animationDuration = animationObj.duration;
clipCanvas[2] = clipCanvas[2] * scaleX;
if (!parentContainer.clip && !is3D) {
parentContainer.attr({
'clip-rect': clipCanvas
});
dataLabelsLayer.attr({
// 'clip-rect': [clipCanvas[0], 0 , clipCanvas[2], clipCanvas[3] + clipCanvas[1]]
});
}
if (animationDuration) {
!is3D && parentContainer.animate({
'clip-rect': clipCanvas
}, animationDuration, NORMALSTRING);
!is3D && dataLabelsLayer.animate({
// 'clip-rect': [clipCanvas[0], 0 , clipCanvas[2], clipCanvas[3] + clipCanvas[1]]
}, animationDuration, NORMALSTRING);
}
else {
!is3D && parentContainer.attr({
'clip-rect': clipCanvas
});
!is3D && dataLabelsLayer.attr({
// 'clip-rect': [clipCanvas[0], 0 , clipCanvas[2], clipCanvas[3] + clipCanvas[1]]
});
}
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']);
chartAPI('sparkline', {
standaloneInit: true,
friendlyName: 'SparkLine Chart',
creditLabel: creditLabel,
defaultDatasetType: 'sparkline',
singleseries: true,
showValues: 0,
_parseCanvasCosmetics: chartAPI.sparkwinloss._parseCanvasCosmetics,
_placeOpenCloseValues: chartAPI.sparkwinloss._placeOpenCloseValues,
defaultPlotShadow: 0,
axisPaddingLeft: 0,
axisPaddingRight: 0,
applicableDSList: { 'line': true }
}, chartAPI.sparkchartbase, {
showvalues: 0,
enablemousetracking: true
});
FusionCharts.register('component', ['dataset', 'sparkline', {
type : 'sparkline',
configure: function () {
var dataSet = this,
chart = dataSet.chart,
// parseUnsafeString = lib.parseUnsafeString,
conf = dataSet.config,
JSONData = dataSet.JSONData,
chartAttr = chart.jsonData.chart;
this.__base__.configure.call(this);
// Line configuration attributes parsing
conf.linethickness = pluckNumber(JSONData.linethickness,
chartAttr.linethickness, 1);
},
_setConfigure: function (newDataset) {
var dataSet = this,
chart = dataSet.chart,
// parseUnsafeString = lib.parseUnsafeString,
conf = dataSet.config,
JSONData = dataSet.JSONData,
chartAttr = chart.jsonData.chart,
setDataArr = newDataset || JSONData.data,
setData,
dataObj,
xAxis = chart.components.xAxis[0],
len = (newDataset && newDataset.data.length) || xAxis.getCategoryLen(),
colorM = chart.components.colorManager,
chartConf = chart.config,
dataStore,
// dataLabelStyle = chartConf.dataLabelStyle,
config,
i,
//Fill Color for high, low, open and close (SparkLine Charts)
openColor = parseColor(pluck(chartAttr.opencolor, '0099FF')),
closeColor = parseColor(pluck(chartAttr.closecolor, '0099FF')),
highColor = parseColor(pluck(chartAttr.highcolor, '00CC00')),
lowColor = parseColor(pluck(chartAttr.lowcolor, 'CC0000')),
anchorColor = parseColor(pluck(chartAttr.anchorcolor, colorM.getColor('plotFillColor'))),
//Whether to show anchors for open, close, high & low
showOpenAnchor =
pluckNumber(chartAttr.showopenanchor, chartAttr.drawanchors, chartAttr.showanchors, 1),
showCloseAnchor = pluckNumber(chartAttr.showcloseanchor, chartAttr.drawanchors,
chartAttr.showanchors, 1),
showHighAnchor =
pluckNumber(chartAttr.showhighanchor, chartAttr.drawanchors, chartAttr.showanchors, 1),
showLowAnchor =
pluckNumber(chartAttr.showlowanchor, chartAttr.drawanchors, chartAttr.showanchors, 1),
anchorAlpha = pluckNumber(chartAttr.anchoralpha, 100),
showAnchors = pluckNumber(chartAttr.drawanchors, chartAttr.showanchors, 0),
defAnchorAlpha = showAnchors ? pluckNumber(chartAttr.anchoralpha, 100) : 0,
lineColor = pluck(chartAttr.linecolor, colorM.getColor('plotFillColor')),
sparkValues,
hasValidValue,
highValue,
lowValue,
pointAnchorAlpha,
anchorHoverColor,
highDisplayValue,
lowDisplayValue,
openDisplayValue,
closeDisplayValue;
// Call the original _setConfigure function
dataSet.__base__._setConfigure.call(dataSet);
dataStore = dataSet.components.data;
highValue = conf.maxValue;
lowValue = conf.minValue;
conf.shadow = {
opacity: pluckNumber(chartAttr.showshadow, 0) ?
conf.alpha / 100 : 0
};
// openValue
dataObj = dataStore[0];
config = dataObj.config;
config.anchorProps.bgColor = pluck(dataObj.anchorbgcolor, openColor);
config.anchorProps.enabled = !!showOpenAnchor;
config.anchorProps.bgAlpha = showOpenAnchor ? pointAnchorAlpha : 0;
// Apply appropriate hover efffects on openValue
if (config.anchorProps.enabled && config.hoverEffects) {
config.hoverEffects.anchorColor = pluck(chartAttr.openhovercolor,
chartAttr.anchorhovercolor, chartAttr.plotfillhovercolor, getLightColor(openColor, 70));
config.hoverEffects.anchorBgAlpha = pluckNumber(chartAttr.openhoveralpha, chartAttr.anchorhoveralpha,
chartAttr.plotfillhoveralpha, 100);
}
openDisplayValue = config.displayValue;
// closeValue
dataObj = dataStore[len - 1];
config = dataObj.config;
config.anchorProps.bgColor = pluck(dataObj.anchorbgcolor, closeColor);
config.anchorProps.enabled = !!showCloseAnchor;
config.anchorProps.bgAlpha = showCloseAnchor ? pointAnchorAlpha : 0;
// Apply appropriate hover efffects on openValue
if (config.anchorProps.enabled && config.hoverEffects) {
config.hoverEffects.anchorColor = pluck(chartAttr.closehovercolor,
chartAttr.anchorhovercolor, chartAttr.plotfillhovercolor, getLightColor(closeColor, 70));
config.hoverEffects.anchorBgAlpha = pluckNumber(chartAttr.closehoveralpha, chartAttr.anchorhoveralpha,
chartAttr.plotfillhoveralpha, 100);
}
closeDisplayValue = config.displayValue;
for (i = 0; i < len; i++) {
dataObj = dataStore[i];
config = dataObj.config;
setData = setDataArr[i];
pointAnchorAlpha = pluckNumber(setData.anchorbgalpha, anchorAlpha);
conf.maxRadius = -Infinity;
// Skipp color parsing for open and close values
if (i !== 0 && i !== len-1) {
config.anchorProps.bgColor = pluck(setData.anchorbgcolor, anchorColor);
config.anchorProps.bgAlpha = pluckNumber(setData.anchorbgalpha, defAnchorAlpha);
config.hoverEffects.anchorColor = parseColor(pluck(chartAttr.anchorhovercolor,
chartAttr.plotfillhovercolor, getLightColor(lineColor, 70)));
config.hoverEffects.anchorBgAlpha = pluckNumber(
chartAttr.lowhoveralpha, chartAttr.anchorhoveralpha, chartAttr.plotfillhoveralpha, 100);
}
config.anchorProps.radius = pluckNumber(chartAttr.anchorradius, setData.anchorradius, 2);
config.anchorProps.borderThickness = 0;
config.hoverEffects.anchorBorderThickness = 0;
config.hoverEffects.anchorRadius = pluckNumber(chartAttr.anchorhoverradius, chartAttr.anchorradius,
setData.anchorradius, 3);
conf.maxRadius = Math.max(config.anchorProps.radius + (config.anchorProps.borderThickness / 2),
conf.maxRadius);
if (config.setValue === lowValue) {
config.anchorProps.bgColor = pluck(setData.anchorbgcolor, lowColor);
config.hoverEffects.anchorColor = pluck(chartAttr.lowhovercolor,
chartAttr.anchorhovercolor, chartAttr.plotfillhovercolor, getLightColor(lowColor, 70));
config.hoverEffects.anchorBgAlpha = pluckNumber(chartAttr.lowhoveralpha, chartAttr.anchorhoveralpha,
chartAttr.plotfillhoveralpha, 100);
config.anchorProps.enabled = !!showLowAnchor;
config.anchorProps.bgAlpha = showLowAnchor ? pointAnchorAlpha : 0;
lowDisplayValue = config.displayValue;
}
if (config.setValue === highValue) {
config.anchorProps.bgColor = pluck(setData.anchorbgcolor, highColor);
config.hoverEffects.anchorColor = anchorHoverColor = pluck(chartAttr.highhovercolor,
chartAttr.anchorhovercolor, chartAttr.plotfillhovercolor, getLightColor(highColor, 70));
config.hoverEffects.anchorBgAlpha = pluckNumber(chartAttr.highhoveralpha,
chartAttr.anchorhoveralpha, chartAttr.plotfillhoveralpha, 100);
config.anchorProps.enabled = !!showHighAnchor;
config.anchorProps.bgAlpha = showHighAnchor ? pointAnchorAlpha : 0;
highDisplayValue = config.displayValue;
}
if (defined(config.setValue)) {
hasValidValue = 1;
}
}
sparkValues = chartConf.sparkValues = {
openValue: {
color: openColor
},
closeValue: {
color: closeColor
},
highValue: {
color: highColor
},
lowValue: {
color: lowColor
},
highLowValue: {
}
};
if (hasValidValue) {
sparkValues.openValue.label = pluckNumber(chartAttr.showopenvalue, 1) ?
openDisplayValue : BLANKSTRING;
sparkValues.closeValue.label = pluckNumber(chartAttr.showclosevalue, 1) ?
closeDisplayValue : BLANKSTRING;
if (pluckNumber(chartAttr.showhighlowvalue, 1)) {
// Store complete high, low label to label for the space manager.
sparkValues.highLowValue.label = '[' + highDisplayValue + ' | ' +
lowDisplayValue + ']';
// Store high, low label separately to render the labels
// Using different color style.
sparkValues.highValue.label = highDisplayValue;
sparkValues.lowValue.label = lowDisplayValue;
}
}
},
draw: function () {
var dataSet = this;
dataSet.__base__.draw.call(dataSet);
dataSet._drawSparkValues();
_drawPeriod.call(dataSet);
},
_drawSparkValues: function () {
var dataSet = this;
drawSparkValues.call(dataSet);
}
}, 'Line']);
}, [3, 2, 0, 'sr2']]);
/**
* @private
* @module fusioncharts.renderer.javascript.logger.message
*/
FusionCharts.register('module', ['private', 'modules.renderer.js-messagelogger',
function () {
var global = this,
win = global.window,
doc = win.document,
docmode8 = doc.documentMode === 8,
lib = global.hcLib,
R = lib.Raphael,
componentDispose = lib.componentDispose,
pluckNumber = lib.pluckNumber,
isIE = lib.isIE,
hex2rgb = lib.graphics.HEXtoRGB,
convertColor = lib.graphics.convertColor,
pluck = lib.pluck,
mathMin = Math.min,
Message,
PX = 'px',
TITLE_HASH_STRING = '$titleVal$',
MSG_HASH_STRING = '$msgVal$',
LINK_HASH_STRING = '$msgLinkVal$',
msgTemplate = {},
CONTAINER_SPAN_STYLE = {
display: 'block',
paddingLeft: '10px',
'paddingRight': '10px',
'font-family': 'Arial',
'font-size': '11px'
},
defAnimEffect = 'normal';
msgTemplate.literal = msgTemplate.info = {
title: '<span style="color: #005900">' + TITLE_HASH_STRING + '</span>',
body: '<span>' + MSG_HASH_STRING + '</span>'
};
msgTemplate.link = {
title: msgTemplate.info.title,
body: '<a href="' + LINK_HASH_STRING + '">' + MSG_HASH_STRING + '</a>'
};
msgTemplate.error = {
title: '<span style="color: #CC0000">' + TITLE_HASH_STRING + '</span>',
body: '<span style="color: #CC0000">' + MSG_HASH_STRING + '</span>'
};
// message class
Message = function (messageObj, msgLogger) {
var message = this,
config = message.config = {},
messageType = (messageObj.msgType || '').toLowerCase(),
msgObj,
msgTitle = messageObj.msgTitle,
msgText = messageObj.msgText,
msgLink = pluck(messageObj.msgLink, msgText);
// initilize with blank string
config.totalHTML = '';
message.graphics = {};
message.linkedItems = {
msgLogger: msgLogger
};
msgObj = msgTemplate[messageType] || msgTemplate.literal;
if (msgTitle) {
config.titleHTML = msgObj.title.replace(TITLE_HASH_STRING, msgTitle);
config.totalHTML += config.titleHTML;
}
if (msgText) {
config.msgHTML = msgObj.body.replace(MSG_HASH_STRING, msgText);
// replace the link
config.msgHTML = config.msgHTML.replace(LINK_HASH_STRING, msgLink);
config.totalHTML += config.msgHTML;
}
};
Message.prototype = {
draw: function () {
var message = this,
config = message.config,
graphics = message.graphics,
prop,
element = graphics.element,
msgLogger = message.linkedItems.msgLogger,
loggerGraphics = msgLogger.graphics,
groupDOMelem = loggerGraphics && loggerGraphics.log && loggerGraphics.log.element,
logWrapperElem = loggerGraphics.logWrapper && loggerGraphics.logWrapper.element,
temp,
loggerConfig = msgLogger.config,
scrollHeight;
if (!element) {
element = graphics.element = doc.createElement('span');
//apply all style
for (prop in CONTAINER_SPAN_STYLE) {
element.style[prop] = CONTAINER_SPAN_STYLE[prop];
}
// @todo: instead of teh DOM method, use renderer standerd method
// Apend the element
groupDOMelem.appendChild && groupDOMelem.appendChild(element);
}
graphics.element.innerHTML = config.totalHTML;
//IE 8 erratically fails to renders child elements in the log divs.
//Inspection reveals that there is no problem in appending the
//elements and they gets rendered some time later as a whole.
//This could be an issue related to what style
//attributes (display & visibility) are used for showing or hiding
//the div. The follwoing checks fix the issue -
if (isIE && docmode8) {
temp = groupDOMelem.innerHTML;
groupDOMelem.innerHTML = temp;
}
//auto scrolling to bottom
if (loggerConfig.scrollToBottom) {
//set the dynamic scrolling flag to true
loggerConfig.dynamicScrolling = true;
scrollHeight = logWrapperElem.scrollHeight;
logWrapperElem.scrollTop = scrollHeight;
}
},
dispose: function () {
var message = this,
graphics = message.graphics,
msgLogger = message.linkedItems.msgLogger;
// @todo: instead of teh DOM method, use renderer standerd method
// remove the graphics element
msgLogger && msgLogger.graphics && msgLogger.graphics.log && msgLogger.graphics.log.element &&
msgLogger.graphics.log.element.removeChild &&
msgLogger.graphics.log.element.removeChild(graphics.element);
delete graphics.element;
// Now remove everything by calling the generalised dispose element
componentDispose.call(message);
}
};
Message.prototype.constractor = Message;
FusionCharts.register('component', ['logger', 'message',{
pIndex: 1,
customConfigFn : null,
/**
* Initilaze the messageLogger
*/
init: function (chart) {
var msLogger = this,
linkedItems = msLogger.linkedItems || (msLogger.linkedItems = {});
msLogger.components = msLogger.components || {};
msLogger.components.messages = msLogger.components.messages || [];
msLogger.graphics = msLogger.graphics || {};
linkedItems.chart = chart;
},
configure: function () {
var msLogger = this,
config = msLogger.config || (msLogger.config = {}),
chart = msLogger.linkedItems.chart,
chartAttr = (chart.get && chart.get('jsonData', 'chart')) || {},
usemessagelog = config.usemessagelog = chart.get('config', 'usemessagelog');
// parse the attributes
// todo: this attributes should be parsed in chart
config.messageLogWPercent = mathMin((pluckNumber(chartAttr.messagelogwpercent, 80)), 100);
config.messageLogHPercent = mathMin((pluckNumber(chartAttr.messageloghpercent, 70)), 100);
config.messageLogShowTitle = pluckNumber(chartAttr.messagelogshowtitle, 1);
config.messageLogTitle = pluck(chartAttr.messagelogtitle, 'Message Log');
config.messageLogColor = pluck(chartAttr.messagelogcolor, '#fbfbfb').replace(/^#?([a-f0-9]+)/ig, '$1');
config.messageLogColorRgb = hex2rgb(config.messageLogColor);
config.messageGoesToJS = pluckNumber(chartAttr.messagegoestojs, 0);
config.messageGoesToLog = pluckNumber(chartAttr.messagegoestolog, 1);
config.messageJSHandler = pluck(chartAttr.messagejshandler, '');
config.messagePassAllToJS = pluckNumber(chartAttr.messagepassalltojs, 0);
// @todo change the default value of "messagePassAsObject" to 1 after 2 release
config.messagePassAsObject = pluckNumber(chartAttr.messagepassasobject, 0);
config.messageLogIsCancelable = pluckNumber(chartAttr.messagelogiscancelable, 1);
config.alwaysShowMessageLogMenu = pluckNumber(chartAttr.alwaysshowmessagelogmenu, usemessagelog);
chart.config.useShowLogMenu = usemessagelog && config.messageGoesToLog;
config.dynamicScrolling = false;
config.scrollToBottom = true;
},
/**
* This function parse a message object parsed from the server and create an internal message item
* @param {object} messageObj server sent message object
* @returns {object} Internal message item
*/
_createMessage: function (messageObj) {
var msLogger = this,
messageObject = new Message(messageObj, msLogger);
// if the message logger is already drawn then draw the messages as well
if (msLogger.graphics.container) {
messageObject.draw();
}
return messageObject;
},
/*
* Function to add a message
* @param {Array(object)} messageObj this object contain the message in
*/
addLog: function (messageObj) {
var msLogger = this,
config = msLogger.config,
components = msLogger.components,
messages = components.messages,
msgGoesToLog = pluckNumber(messageObj.msgGoesToLog, config.messageGoesToLog),
msgGoesToJS = pluckNumber(messageObj.msgGoesToJS, config.messageGoesToJS),
globalJSFunc = win[config.messageJSHandler],
msgId = pluck(messageObj.msgId, ''),
title = pluck(messageObj.msgTitle, ''),
msg = pluck(messageObj.msgText, ''),
msgType = pluck(messageObj.msgType, 'literal'),
message;
if (!config.usemessagelog) {
return;
}
if (msgGoesToJS && globalJSFunc && typeof globalJSFunc === 'function') {
// check whether all parameters are to be passed.
// @note: the order of the attributes are fixed. This could be
// made dynamic through passing a whole objcet.
config.messagePassAllToJS ? (config.messagePassAsObject ? globalJSFunc(messageObj) :
globalJSFunc(msgId, title, msg, msgType)): globalJSFunc(msg);
}
// if configured, clear the log
if (messageObj.clearLog === '1') {
msLogger.clearLog();
}
if (msgGoesToLog && (messageObj.msgTitle || messageObj.msgText)) {
message = msLogger._createMessage(messageObj);
messages.push(message);
// if this is the first message and the window is hidden, open the window
if (messages.length === 1 && !config.visible) {
msLogger.show();
}
}
},
/**
* Show the logger window
*/
show: function () {
var msLogger = this,
graphics = msLogger.graphics,
config = msLogger.config;
if (!config.visible) {
// set the visibility tag
config.visible = true;
// For initial performance boost, we don't draw the message logger initially
// So draw the message logger when the first time it is getiing visible
if (!graphics.container) {
msLogger.draw();
}
// show the group
graphics.container && graphics.container.show();
}
},
/**
* Hide the logger windoew
*/
hide: function () {
var msLogger = this,
graphics = msLogger.graphics,
config = msLogger.config;
// set the visibility flag
config.visible = false;
// hide the group
graphics.container && graphics.container.hide();
},
/**
* Clear all logged message
*/
clearLog: function () {
var msLogger = this,
components = msLogger.components,
messages = components.messages,
i,
l = messages.length;
for (i = 0; i < l; i += 1) {
messages[i] && messages[i].dispose && messages[i].dispose();
}
// remove all from the store
messages.splice(0, l);
},
/**
* Function to check whether the logger is drawn or not
* @returns {Boolean} Message logger's drawing status
*/
isDrawn: function () {
return !!this.graphics.container;
},
/**
* This function draw the message logger window
*/
draw: function () {
var msLogger = this,
config = msLogger.config,
components = msLogger.components,
messages = components.messages,
i,
l;
if (!config.usemessagelog) {
if (msLogger.isDrawn()) {
msLogger.clearLog();
msLogger.hide();
}
}
else {
msLogger._createHTMLDialogue();
if (!config.visible) {
msLogger.hide();
}
l = messages.length;
// draw all messages
for (i = 0; i < l; i += 1) {
messages[i] && messages[i].draw && messages[i].draw();
}
}
},
_createHTMLDialogue: function () {
var msLogger = this,
config = msLogger.config,
graphics = msLogger.graphics,
linkedItems = msLogger.linkedItems,
components = msLogger.components,
iapi = linkedItems.chart,
paper = iapi.get('components', 'paper'),
chartContainer = iapi.get('linkedItems', 'container'),
chartConfig = iapi.get('config'),
chartWidth = chartConfig.width,
chartHeight = chartConfig.height,
styles = chartConfig.style,
inCanvasStyle = styles && styles.inCanvasStyle,
messageLogWPercent = config.messageLogWPercent,
messageLogHPercent = config.messageLogHPercent,
messageLogShowTitle = config.messageLogShowTitle,
messageLogIsCancelable = config.messageLogIsCancelable,
messageLogColor = config.messageLogColor,
messageLogTitle = config.messageLogTitle,
//properties to configure the close button
closePaper = components.paper,
cg = graphics.cg,
closeBtnRadius = 6,
closeBtnContainerW = closeBtnRadius * 3,
closeBtnContainerH = closeBtnRadius * 3,
closeBtnBorderColor = '999999',
closeBtnHalfRadius = closeBtnRadius / 2,
closeBtnXPos = closeBtnContainerW / 2,
closeBtnYPos = closeBtnContainerH / 2,
hPadding = 5 + closeBtnRadius,
vPadding = 5 + closeBtnRadius,
dialogWidth = chartWidth * (messageLogWPercent / 100), //chartWidth - (hPadding * 2),
dialogHeight = chartHeight * (messageLogHPercent / 100), //chartHeight - (vPadding * 2),
dialogXPos = (chartWidth - dialogWidth) / 2,
dialogYPos = (chartHeight - dialogHeight) / 2,
textAreaWidth = dialogWidth - closeBtnContainerW - (hPadding * 2),
textAreaHeight = dialogHeight - closeBtnContainerH - (vPadding * 2),
closeBtnX = (dialogXPos + dialogWidth) -
(closeBtnContainerW + closeBtnHalfRadius), //half radius used as padding,
closeBtnY = dialogYPos + closeBtnHalfRadius,
veilBgColor = '000000',
dialogBgColor = 'ffffff',
dialogStrokeColor = messageLogColor,
logBGColor = messageLogColor,
container = graphics.container,
transposeAnimDuration = msLogger.isDrawn() && chartConfig.animation &&
chartConfig.animation.transposeAnimDuration,
tempAttrObj,
dialogAttr,
logBgAttr,
closeContainerAttr,
logWrapperAttr;
// For forst time drawing create the emelents
if (!container) {
container = graphics.container = paper.html('div', {
fill: 'transparent'
}, {
fontSize: 10 + PX,
lineHeight: 15 + PX
}, chartContainer);
graphics.veil = paper.html('div', {
id: 'veil',
fill: veilBgColor,
opacity: 0.1
}, undefined, container)
.on('click', function () {
messageLogIsCancelable && msLogger.hide();
});
//if message log title is available
//Create title
/** @todo: in IE title becomes too big. */
if (messageLogTitle && messageLogShowTitle) {
graphics.title = paper.html('p', {
id: 'Title',
innerHTML: messageLogTitle,
x: 5,
y: 5
}, {
'font-weight': 'bold'
}, container);
}
graphics.dialog = paper.html('div', {
id: 'dialog',
strokeWidth: 1
}, {
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")'
}, container);
graphics.logBackground = paper.html('div', {
id: 'dialogBackground',
x: 0,
y: 0
}, undefined, graphics.dialog);
//create close button if required
if (messageLogIsCancelable) {
//In order to create a close button icon for message Logger
//we need to initiate a separate raphael instance on the messageLogger
//div
graphics.closeBtnContainer = paper.html('div', {
id: 'closeBtnContainer'
}, {
//'background-color': 'rgba(0, 0, 0, 0.4)'
}, container);
// @todo: recheck the use of R
components.paper = closePaper = new R('closeBtnContainer', closeBtnContainerW,
closeBtnContainerH);
closePaper.setConfig('stroke-linecap', 'round');
cg = graphics.cg = closePaper.group('closeGroup');
graphics.closeButton = closePaper.symbol('closeIcon', 0, 0, closeBtnRadius, cg)
.attr({
transform: 't' + closeBtnXPos + ',' + closeBtnYPos,
'stroke-width': 2,
//fill: convertColor(closeBtnFillColor),
stroke: convertColor(closeBtnBorderColor),
ishot: true,
'stroke-linecap': 'round',
'stroke-linejoin': 'round'
})
.css({
cursor: 'pointer',
_cursor: 'hand'
})
.click(function () {
msLogger.hide();
});
}
graphics.logWrapper = paper.html('div', {
id: 'logWrapper'
}, {
overflow: 'auto'
}, graphics.dialog)
.on('scroll', function () {
var wrapper = this,
scrollTop = wrapper && wrapper.scrollTop,
scrollHeight = wrapper && wrapper.scrollHeight,
wrapperHeight = wrapper && wrapper.offsetHeight;
if (config.dynamicScrolling) {
config.dynamicScrolling = false;
return;
}
//manual scrolling set auto scrolling bottom to false.
//if the scroller is not scrolled to bottom.
//This will prevent the scroller automatically jumping
//to end when user wants to see a specific area
config.scrollToBottom = ((scrollHeight - scrollTop) === wrapperHeight) ?
true : false;
});
graphics.log = paper.html('div', {
id: 'log',
x: 0,
y: 0
//opacity: 1
}, {}, graphics.logWrapper);
}
// update / apply the css or attributes that does not animate
container.css({
fontFamily: inCanvasStyle.fontFamily
});
graphics.dialog.attr({
fill: dialogBgColor,
stroke: dialogStrokeColor
});
graphics.logBackground.attr({
fill: logBGColor
});
// to reduce the no of line pof code store the most used object as a local variable
tempAttrObj = {
width: chartWidth,
height: chartHeight
};
dialogAttr = {
x: dialogXPos,
y: dialogYPos,
width: dialogWidth,
height: dialogHeight
};
logBgAttr = {
width: dialogWidth,
height: dialogHeight
};
closeContainerAttr = {
width: closeBtnContainerW,
height: closeBtnContainerH,
x: closeBtnX,
y: closeBtnY
};
logWrapperAttr = {
x: (dialogWidth - textAreaWidth) / 2,
y: (dialogHeight - textAreaHeight) / 2,
width: textAreaWidth,
height: textAreaHeight
};
if (transposeAnimDuration){
container.animate(tempAttrObj, transposeAnimDuration, defAnimEffect);
graphics.veil.animate(tempAttrObj, transposeAnimDuration, defAnimEffect);
graphics.dialog.animate(dialogAttr, transposeAnimDuration, defAnimEffect);
graphics.logBackground.animate(logBgAttr, transposeAnimDuration, defAnimEffect);
// if close btn is applicable then update it's attributes
graphics.closeBtnContainer && graphics.closeBtnContainer.animate(closeContainerAttr,
transposeAnimDuration, defAnimEffect);
graphics.logWrapper.animate(logWrapperAttr, transposeAnimDuration, defAnimEffect);
}
else {
container.attr(tempAttrObj);
graphics.veil.attr(tempAttrObj);
graphics.dialog.attr(dialogAttr);
graphics.logBackground.attr(logBgAttr);
// if close btn is applicable then update it's attributes
graphics.closeBtnContainer && graphics.closeBtnContainer.attr(closeContainerAttr);
graphics.logWrapper.attr(logWrapperAttr);
}
}
}]);
}
]);
/**
* @private
*
* @module fusioncharts.renderer.javascript.alertmanager
*/
FusionCharts.register('module', ['private', 'modules.renderer.js-alertmanager', function () {
var global = this,
lib = global.hcLib,
IN_ALERT_RANGE = '1',
OUT_OF_ALERT_RANGE = '2',
ACTION_CALLJS = 'calljs',
ACTION_SHOWANNOTATION = 'showannotation';
FusionCharts.register('component', ['manager', 'alert',{
pIndex: 1,
init: function(chart) {
this.linkedItems = {
chart: chart
};
},
configure: function() {
var alertManager = this,
chart = alertManager.linkedItems.chart,
alerts = chart.get('jsonData', 'alerts'),
alertArr = alerts && alerts.alert,
numberFormatter = chart.get('components', 'numberFormatter'),
config = alertManager.config || (alertManager.config = {}),
alertCount,
j,
alertObj;
if (alertArr && alertArr.length) {
config.alertArr = alertArr;
alertCount = alertArr.length;
for (j = 0; j < alertCount; j += 1) {
alertObj = alertArr[j];
alertObj.minvalue = numberFormatter.getCleanValue(alertObj.minvalue);
alertObj.maxvalue = numberFormatter.getCleanValue(alertObj.maxvalue);
}
}
else {
config.alertArr = [];
}
},
processRTData: function(rtData) {
var alertManager = this,
chart = alertManager.linkedItems.chart,
numberFormatter = chart.get('components', 'numberFormatter'),
i,
j,
dsLength,
dsObj,
dataLength,
dataObj,
val;
if (rtData && rtData.dataset && rtData.dataset.length) {
dsLength = rtData.dataset.length;
for (i = 0; i < dsLength; i += 1) {
dsObj = rtData.dataset[i];
if (dsObj.data && dsObj.data.length) {
dataLength = dsObj.data.length;
for (j = 0; j < dataLength; j += 1) {
dataObj = dsObj.data[j];
val = dataObj && numberFormatter.getCleanValue(dataObj.value);
if (val !== null) {
alertManager._doAlert(numberFormatter.getCleanValue(dataObj.value));
}
}
}
}
}
},
_doAlert: function (val) {
var alertManager = this,
chart = alertManager.linkedItems.chart,
config = alertManager.config,
alertArr = config.alertArr,
alertCount = alertArr.length,
alertObj,
j,
alertAction;
for (j = 0; j < alertCount; j += 1) {
alertObj = alertArr[j];
alertAction = alertObj.action && alertObj.action.toLowerCase();
if (alertObj.minvalue <= val && alertObj.maxvalue >= val) {
if (!(alertObj.occuronce === '1' && alertObj.hasOccurred)) {
alertObj.hasOccurred = true;
alertObj.state = IN_ALERT_RANGE;
switch (alertAction) {
case ACTION_CALLJS:
setTimeout(lib.pseudoEval(alertObj.param));
break;
case ACTION_SHOWANNOTATION:
chart.showAnnotation && chart.showAnnotation(alertObj.param);
break;
}
global.raiseEvent('AlertComplete', {
alertValue: val,
alertMaxValue: alertObj.maxvalue,
alertMinValue: alertObj.minvalue
}, chart.chartInstance);
}
}
else {
if (alertAction === ACTION_SHOWANNOTATION && alertObj.state === IN_ALERT_RANGE) {
chart.hideAnnotation &&
chart.hideAnnotation(alertObj.param);
}
// Set out of range flag
alertObj.state = OUT_OF_ALERT_RANGE;
}
}
}
}]);
}]);
/**
* @private
*
* @module fusioncharts.renderer.javascript.datastreamer
* @requires fusioncharts.renderer.javascript.logger.message
* @requires fusioncharts.renderer.javascript.alertmanager
*/
FusionCharts.register('module', ['private', 'modules.renderer.js-realtime', function () {
var global = this,
lib = global.hcLib,
win = global.window,
math = Math,
mathRandom = math.random,
pluckNumber = lib.pluckNumber,
THRESHOLD_MS = 10,
/**
* This function is to compact the routine of clearing and re-applying a timeout
* @private
*
* @example
* to = resetTimeout(theFunction, 500, to);
*
* @param {function} fn
* @param {number} ms
* @param {number} id
* @returns {number}
*/
resetTimeout = function (fn, ms, id) {
clearTimeout(id);
return setTimeout(fn, ms);
},
processRealtimeStateChange; // fn
processRealtimeStateChange = function (event) {
var chartObj = event.sender,
state = chartObj.__state,
chartAttr,
vars,
chart,
options,
chartOptions,
refreshMs,
clearMs,
dataUrl,
dataStamp,
realtimeEnabled,
animation,
ajaxObj,
clearChart,
requestData;
// In case data was set during construction, both the state-change capture events can happen to be fired before
// even them being registered. Hence, a special check is made here.
if (state.dataSetDuringConstruction && !state.rtStateChanged && state.rtPreInit === undefined) {
if (chartObj.dataReady()) {
state.rtStateChanged = true;
state.rtPreInit = true;
}
else {
state.rtPreInit = false;
}
}
// If the data has not changed then the realtime initialization should not be repeated.
if (!state.rtStateChanged) {
return;
}
// reset the state changed flag to indicate that drawcomplete will re-work upon next state change.
state.rtStateChanged = false;
// Initialize the realtime framework.
vars = chartObj.jsVars;
chart = vars && vars.instanceAPI;
// In case process happens before load
if (!chart) {
return;
}
options = chart.config || {};
chartAttr = chart.jsonData && chart.jsonData.chart;
chartOptions = (options && options.chart) || {};
refreshMs = (pluckNumber(options.updateInterval, options.refreshInterval) * 1000);
clearMs = (pluckNumber(options.clearInterval, 0) * 1000);
dataUrl = options.dataStreamURL;
realtimeEnabled = Boolean(options && options.realtimeEnabled && (refreshMs > 0) &&
(dataUrl !== undefined && dataUrl !== '') && chartOptions);
animation = options && options.plotOptions &&
options.plotOptions.series.animation &&
options.plotOptions.series.animation.duration || 0;
ajaxObj = state._rtAjaxObj;
clearChart = function () {
chartObj.clearChart && chartObj.clearChart();
if (clearMs) {
state._toClearChart = setTimeout(clearChart, clearMs);
}
};
requestData = function () {
var url = dataUrl,
dataStamp = chartAttr && chartAttr.datastamp;
// append anti-cache querystring to url (a random number)
url += (dataUrl.indexOf('?') === -1 ? '?num=' : '&num=') + mathRandom();
// append data stamp to the url
dataStamp && (url += ('&dataStamp=' + dataStamp));
// If xhr object is open, then abort it. Probably because previous request did not return on time.
ajaxObj.open && ajaxObj.abort();
ajaxObj.get(url); // fetch the URL.
state._rtAjaxLatencyStart = (new Date());
};
if (refreshMs <= 0) {
state._toRealtime = clearTimeout(state._toRealtime);
ajaxObj && ajaxObj.abort();
}
// validate whether refreshinterval is less than threshold.
else if (refreshMs < THRESHOLD_MS) {
refreshMs = THRESHOLD_MS;
}
state._toClearChart = clearTimeout(state._toClearChart);
if (clearMs > 0) {
if (clearMs < THRESHOLD_MS) {
clearMs = THRESHOLD_MS;
}
else {
state._toClearChart = setTimeout(clearChart, clearMs);
}
}
state._rtStaticRefreshMS = refreshMs;
if (realtimeEnabled) {
if (state._rtPaused === undefined) {
state._rtPaused = false;
}
state._rtDataUrl = dataUrl;
state.lastSetValues = null;
ajaxObj = state._rtAjaxObj || (state._rtAjaxObj = new global.ajax());
ajaxObj.onSuccess = function (responseText, wrapper, data, url) {
if (chartObj.disposed) {
return;
}
var iapi = vars.instanceAPI,
prevData,
feedData = iapi.feedData,
logic = {},
updateObj = {},
config = iapi.config,
redrawLatency;
// Update latency timer
state._rtAjaxLatencyStart && (state._rtAjaxLatency = (new Date()) - state._rtAjaxLatencyStart);
if (feedData && config.realtimeEnabled && dataUrl) {
dataStamp = updateObj.dataStamp ?
updateObj.dataStamp : null;
// this is done for animation duration
updateObj.interval = refreshMs < 1000 ? refreshMs : 1000;
prevData = iapi._getPrevData();
iapi.feedData(responseText, true, url, (state._rtAjaxLatency || 0));
// if (chart.realtimeUpdate) {
// chart.realtimeUpdate(updateObj);
// }
// else {
// logic.realtimeUpdate(updateObj);
// }
// vars._rtLastUpdatedData = logic.multisetRealtime ? updateObj : chartObj.getDataJSON();
// Calculate combined latency for realtime drawing
redrawLatency = (logic.realtimeDrawingLatency || 0) + (state._rtAjaxLatency || 0);
/* This event is raised every time a real-time chart or gauge updates itself with new data. This
* event is raised in any of the following cases:
*
* - Real-time update using `dataStreamUrl` attribute.
* - Real-time update of Angular gauge or Horizontal Liner gauge using user interaction (through
* edit mode).
*
* @group chart-realtime
*
* @event FusionCharts#realTimeUpdateComplete
* @param {string} data - Chart data as XML or JSON string
* @param {object} updateObject - It is the update object.
* @param {number} prevData - The previous data values.
* @param {number} source - Nature of data load request. Presently its value is 'XmlHttprequest'.
* @param {string} url - URL of the data source.
*/
// global.raiseEvent('realtimeUpdateComplete', {
// data: responseText,
// updateObject: updateObj,
// prevData: prevData,
// source: 'XmlHttpRequest',
// url: url,
// networkLatency: state._rtAjaxLatency,
// latency: redrawLatency
// }, event.sender);
try {
/* jshint camelcase: false*/
win.FC_ChartUpdated && win.FC_ChartUpdated(event.sender.id);
/* jshint camelcase: true*/
}
catch (err) {
setTimeout(function () {
throw err;
}, 1);
}
if (!state._rtPaused) {
if (redrawLatency >= state._rtStaticRefreshMS) {
redrawLatency = state._rtStaticRefreshMS - 1;
}
// re-issue realtime update.
state._toRealtime = setTimeout(requestData, state._rtStaticRefreshMS - redrawLatency);
}
}
else {
state._toRealtime = clearTimeout(state._toRealtime);
}
};
ajaxObj.onError = function (resp, wrapper, data, url) {
// Update latency timer
state._rtAjaxLatencyStart && (state._rtAjaxLatency = (new Date()) - state._rtAjaxLatencyStart);
/**
* This event is raised where there is an error in performing a real-time chart data update using
* `dataStreamUrl` attribute.
*
* @event FusionCharts#realTimeUpdateError
* @group chart-realtime
*
* @param {number} source - Nature of data load request. Presently its value is 'XmlHttprequest'.
* @param {string} url - URL of the data source.
* @param {object} xmlHttpReqestObject - The object which has fetched data.
* @param {string} httpStatus - A number which denotes the HTTP status number when the error was raised.
* For example, the status will be ``404`` for URL not found.
*/
global.raiseEvent('realtimeUpdateError', {
source: 'XmlHttpRequest',
url: url,
xmlHttpRequestObject: wrapper.xhr,
error: resp,
httpStatus: (wrapper.xhr && wrapper.xhr.status) ? wrapper.xhr.status : -1,
networkLatency: state._rtAjaxLatency
}, event.sender);
// Upon error, based on whether chart is alive and kicking, re-request the data or abandon realtime
// calls.
state._toRealtime = chartObj.isActive() ?
setTimeout(requestData, refreshMs) : clearTimeout(state._toRealtime);
};
// This is the first (initial) realtime update request to be sent. It is delayed by 0
//second as now the entire module is handled by logic.js
if (!state._rtPaused) {
state._toRealtime = resetTimeout(requestData, 0, state._toRealtime);
}
}
};
// Clear realtime threads upon data change or re-render.
global.addEventListener(['beforeDataUpdate', 'beforeRender'], function (event) {
var chartObj = event.sender,
state = chartObj.__state;
chartObj.jsVars && (chartObj.jsVars._rtLastUpdatedData = null); // remove data cache
// clear all timeouts
state._toRealtime && (state._toRealtime = clearTimeout(state._toRealtime));
state._toClearChart && (state._toClearChart = clearTimeout(state._toClearChart));
state._rtAjaxLatencyStart = null; // clear latency claculations
state._rtAjaxLatency = null;
});
// This is to prevent realtime init routines to be executed on every drawcomplete
global.addEventListener(['renderComplete', 'dataUpdated'], function (event) {
var state = event.sender.__state;
if (state) {
(state.rtPreInit === undefined) && (state.rtPreInit = false);
state._rtPaused && delete state._rtPaused;
if (!state.rtStateChanged) {
state.rtStateChanged = true;
// If the event happens to happen while rendering is inprogress, we need to force process.
processRealtimeStateChange.apply(this, arguments);
}
}
});
// This is to clear any timeouts pending upon chart disposal.
global.core.addEventListener('beforeDispose', function (event) {
var state = event.sender.__state;
state._toRealtime && (state._toRealtime = clearTimeout(state._toRealtime));
state._toClearChart && (state._toClearChart = clearTimeout(state._toClearChart));
});
global.core.addEventListener('drawComplete', processRealtimeStateChange);
}]);
/**
* @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.widgets
* @export fusioncharts.widgets.js
*
* @requires fusioncharts.renderer.javascript.sparkcharts
* @requires fusioncharts.renderer.javascript.datastreamer
*/
/* jshint ignore: start */
FusionCharts.register('module', ['private', 'modules.renderer.js-widgets', function () {
var global = this,
lib = global.hcLib,
extend2 = lib.extend2,
toPrecision = lib.toPrecision;
defaultGaugePaletteOptions = extend2({}, lib.defaultGaugePaletteOptions);
// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
if (!Array.prototype.forEach) {
/*jslint freeze: false */
Array.prototype.forEach = function(callback, thisArg) {
var T, k, O, len, kValue;
if (this == null) {
throw new TypeError(' this is null or not defined');
}
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 1) {
T = thisArg;
}
// 6. Let k be 0
k = 0;
// 7. Repeat, while k < len
while (k < len) {
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal
// method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[k];
// ii. Call the Call internal method of callback with T as the this value and
// argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);
}
// d. Increase k by 1.
k++;
}
// 8. return undefined
};
}
/**
* MathExt class bunches a group of mathematical functions
* which will be used by other classes. All the functions in
* this class are declared as static, as the methods do not
* relate to any specific instance.
* @class MathExt
* @author FusionCharts Technologies
* @version 3.0
*
* Copyright (C) FusionCharts Technologies
* @private
*/
function MathExt () {
//Nothing to do.
}
MathExt.prototype = /** @lends MathExt# */{
/**
* numDecimals method returns the number of decimal places provided
* in the given number.
* @param num Number for which we've to find the decimal places.
* @return Number of decimal places found.
*/
numDecimals: function (num) {
// Fix for upperLimits or lowerLimits given in decimal
num = toPrecision(num, 10);
//Absolute value (to avoid floor disparity for negative num)
num = Math.abs(num);
//Get decimals
var decimal = toPrecision((num-Math.floor(num)), 10),
//Number of decimals
numDecimals = (String(decimal).length-2);
//For integral values
numDecimals = (numDecimals<0) ? 0 : numDecimals;
//Return the length of string minus '0.'
return numDecimals;
},
/**
* toRadians method converts angle from degrees to radians
* @param angle The numeric value of the angle in
* degrees
* @return The numeric value of the angle in radians
*/
toRadians: function (angle) {
return (angle/180)*Math.PI;
},
/**
* toDegrees method converts angle from radians to degrees
* @param angle The numeric value of the angle in
* radians
* @returns The numeric value of the angle in degrees
*/
toDegrees: function (angle) {
return (angle/Math.PI)*180;
},
/**
* flashToStandardAngle method converts angles from Flash angle to normal angles (0-360).
* @param ang Angle to be converted
* @return Converted angle
*/
flashToStandardAngle: function (ang) {
return -1*ang;
},
/**
* standardToFlashAngle method converts angles from normal angle to Flash angles
* @param ang Angle to be converted
* @return Converted angle
*/
standardToFlashAngle: function (ang) {
return -1*ang;
},
/**
* flash180ToStandardAngle method changes a Flash angle (-180° to 180°) into standard
* angle (0° to 360° CCW) wrt the positive x-axis using angle input.
* @param ang Angle in degrees (-180° to 180°).
* @return Angle in degrees (0° to 360° CCW).
**/
flash180ToStandardAngle: function (ang) {
var a = 360-(((ang%=360)<0) ? ang+360 : ang);
return (a==360) ? 0 : a;
},
/**
* getAngularPoint method calculates a point at a given angle
* and radius from the given point.
* @param fromX From point's X co-ordinate
* @param fromY From point's Y co-ordinate
* @param distance How much distance (pixels) from current point?
* @param angle At what angle (degrees - standard) from current point
*/
getAngularPoint: function(fromX, fromY, distance, angle) {
//Convert the angle into radians
angle = angle*(Math.PI/180);
var xPos = fromX+(distance*Math.cos(angle)),
yPos = fromY-(distance*Math.sin(angle));
return ({
x:xPos,
y:yPos
});
},
/**
* remainderOf method calculates the remainder in
* a division to the nearest twip.
* @param a dividend in a division
* @param b divisor in a division
* @returns Remainder in the division rounded
* to the nearest twip.
*/
remainderOf: function (a, b) {
return roundUp(a%b);
},
/**
* boundAngle method converts any angle in degrees
* to its equivalent in the range of 0 to 360 degrees.
* @param angle Angle in degrees to be procesed;
* can take negetive values.
* @returns Equivalent non-negetive angle in degrees
* less than or equal to 360 degrees
*/
boundAngle: function (angle) {
if (angle>=0) {
return MathExt.prototype.remainderOf(angle, 360);
}
else {
return 360-MathExt.prototype.remainderOf(Math.abs(angle), 360);
}
},
/**
* toNearestTwip method converts a numeric value by
* rounding it to the nearest twip value ( one twentieth
* of a pixel ) for propermost rendering in flash.
* @param num Number to rounded
* @returns Number rounded upto 2 decimal places and
* second significant digit right of decimal
* point, if exists at all is 5.
*/
toNearestTwip: function(num) {
var n = num,
s = (n<0) ? -1 : 1,
k = Math.abs(n),
r = mathRound(k*100),
b = Math.floor(r/5),
t = Number(String(r-b*5)),
m = (t>2) ? b*5+5 : b*5;
return s*(m/100);
},
/**
* roundUp method is used to format trailing decimal
* places to the required precision, with default base 2.
* @param num number to be formatted
* @param base number of precision digits
* @returns formatted number
* @private
*/
roundUp: function (num, base) {
// precise to number of decimal places
base = (base === undefined) ? 2 : base;
var factor = mathPow(10, base);
num *= factor;
num = mathRound(Number(String(num)));
num /= factor;
return num;
}
};
MathExt.prototype.constructor = MathExt;
lib.MathExt = MathExt;
}
]);
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-funnelpyramidbase',
function () {
var global = this,
lib = global.hcLib,
COMPONENT = 'component',
DATASET = 'dataset',
pluck = lib.pluck,
pluckNumber = lib.pluckNumber,
BLANK = lib.BLANKSTRING,
BLANKSTRING = BLANK,
preDefStr = lib.preDefStr,
showHoverEffectStr = preDefStr.showHoverEffectStr,
convertColor = lib.graphics.convertColor,
noneStr = 'none',
extend2 = lib.extend2,
PXSTRING = 'px',
fillStr = 'fill',
NORMALSTRING = 'normal',
parseUnsafeString = lib.parseUnsafeString,
getLightColor = lib.graphics.getLightColor,
COMMASTRING = lib.COMMASTRING,
ZEROSTRING = lib.ZEROSTRING,
getValidValue = lib.getValidValue,
UNDEFINED,
parseTooltext = lib.parseTooltext,
setLineHeight = lib.setLineHeight,
math = Math,
mathRound = math.round,
mathCeil = math.ceil,
mathMax = math.max,
mathMin = math.min,
mathPow = math.pow,
mathSqrt = math.sqrt,
COMMASPACE = lib.COMMASPACE,
EMPTY_OBJ = {},
getDarkColor = lib.graphics.getDarkColor,
colorStrings = preDefStr.colors,
COLOR_000000 = colorStrings.c000000,
configStr = preDefStr.configStr,
animationObjStr = preDefStr.animationObjStr,
POSITION_START = preDefStr.POSITION_START,
POSITION_MIDDLE = preDefStr.POSITION_MIDDLE,
pathStr = 'path',
zeroCommaHundredStr = '0,100',
CRISP = 'crisp',
win = global.window,
userAgent = win.navigator.userAgent,
isIE = /msie/i.test(userAgent) && !win.opera,
HEXCODE = lib.regex.hexcode,
TRACKER_FILL = 'rgba(192,192,192,'+ (isIE ? 0.002 : 0.000001) +')',
dropHash = lib.regex.dropHash,
POINTER = 'pointer',
EVENTARGS = 'eventArgs',
HASHSTRING = lib.HASHSTRING,
toRaphaelColor = lib.toRaphaelColor,
plotEventHandler = lib.plotEventHandler,
isObject = function (obj) {
return typeof obj === 'object';
},
isString = function (s) {
return typeof s === 'string';
},
defined = function (obj) {
return obj !== UNDEFINED && obj !== null;
},
M = 'M',
A = 'A',
L = 'L',
Z = 'Z',
startsRGBA = lib.regex.startsRGBA,
/**
* Handle color operations. The object methods are chainable.
* @param {string} input The input color in either rbga or hex format
* @private
*/
Color = function(input) {
// declare variables
var rgba = [], result;
/**
* Parse the input color to rgba array
* @param {string} input
* @private
*/
function init(input) {
// rgba
/* jshint maxlen:200*/
result = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/.exec(input);
/* jshint maxlen:120*/
if (result) {
rgba = [parseInt(result[1], 10), parseInt(result[2], 10),
parseInt(result[3], 10), parseFloat(result[4])];
}
// hex
else {
result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(input);
if (result) {
rgba = [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16), 1];
}
}
}
/**
* Return the color a specified format
* @param {string} format
* @private
*/
function get(format) {
var ret;
// it's NaN if gradient color on a column chart
if (rgba && !isNaN(rgba[0])) {
if (format === 'rgb') {
ret = 'rgb('+ rgba[0] +','+ rgba[1] +','+ rgba[2] +')';
/**^
* capability to return hex code
*/
} else if (format === 'hex') {
ret = '#' + (COLOR_000000 +
(rgba[0] << 16 | rgba[1] << 8 | rgba[2]).toString(16)).slice(-6);
} else if (format === 'a') {
/*EOP^*/
ret = rgba[3];
} else {
ret = 'rgba('+ rgba.join(',') +')';
}
}else {
ret = input;
}
return ret;
}
/**
* Brighten the color
* @param {number} alpha
* @private
*/
function brighten(alpha) {
if (!isNaN(alpha) && alpha !== 0) {
var i;
for (i = 0; i < 3; i++) {
rgba[i] += parseInt(alpha * 255, 10);
if (rgba[i] < 0) {
rgba[i] = 0;
}
if (rgba[i] > 255) {
rgba[i] = 255;
}
}
}
return this;
}
/**
* Set the color's opacity to a given alpha value
* @param {number} alpha
* @private
*/
function setOpacity(alpha) {
rgba[3] = alpha;
return this;
}
// initialize: parse the input
init(input);
// public methods
return {
get: get,
brighten: brighten,
setOpacity: setOpacity
};
};
FusionCharts.register(COMPONENT, [DATASET, 'FunnelPyramidBase', {
type: 'funnelpyramidbase',
pIndex: 2,
customConfigFn: '_createDatasets',
init : function (datasetJSON) {
var datasetDefStore = this,
utils = datasetDefStore.utils(datasetDefStore),
invokeHookFns = utils.invokeHookFns,
postInitHookFn = datasetDefStore.postInitHook;
if (!datasetJSON) {
// If for some reason the json data is not passed return to the caller.
return false;
}
// Utils needs to be context to be set before using it.
// utils.setContext(datasetDefStore);
// Saves reference of input data
datasetDefStore.JSONData = datasetJSON;
// Stub for saving all the child component
datasetDefStore.components = { };
// Stub for saving all the computed configuration
datasetDefStore.conf ={ };
// Stub for saving all the graphics component
datasetDefStore.graphics = { };
// Post initialization hook if any charts need any specific case where there has to be special operation
// to be performed after init method is called but before configure.
invokeHookFns(postInitHookFn);
datasetDefStore.configure();
},
removeData: function () {},
_configure : function () {
var datasetStore = this,
chart = datasetStore.chart,
chartComponents = chart.components,
colorManager = chartComponents.colorManager,
chartConfig = chart.config,
globalStyle = chartConfig.style,
dataStoreComponent = datasetStore.components,
datasetConf = datasetStore.conf || {},
jsonDataObj = datasetStore.JSONData,
datasetDataArr = jsonDataObj.data || [],
chartAttr = chart.jsonData ? chart.jsonData.chart : {},
utils = datasetStore.utils(datasetStore),
invokeHookFns = utils.invokeHookFns,
copyProperties = utils.copyProperties,
setLineHeight = lib.setLineHeight,
heightAllotted = chartConfig.canvasHeight,
BLANK_SPACE = 3,
DEFAULT_LABEL_DISTANCE = 50,
DEFAULT_BLANK_SPACE = 3,
configureSpecificsFn = datasetStore.configureSpecifics,
preDrawingHook = datasetStore.preDrawingHook,
baseFontColor = colorManager.getColor ('baseFontColor');
// Parse all the attributes common to pyramid and funnel
copyProperties(chartAttr, datasetConf, [
['showlabels', 'showLabels', pluckNumber, 1],
['showvalues', 'showValues', pluckNumber, 1],
['plottooltext', 'toolText', pluck, BLANK],
['enableslicing', 'enableSlicing', pluckNumber, 1],
['plotfillalpha', 'plotFillAlpha', pluckNumber, 100],
['showplotborder', 'showPlotBorder', pluckNumber, 0],
['plotborderalpha', 'plotBorderAlpha', pluckNumber, undefined],
['plotbordercolor', 'plotBorderColor', pluck, undefined],
['plotborderthickness', 'plotBorderThickness', pluckNumber, 1],
['showshadow', 'showShadow', pluckNumber, 1],
['showhovereffect', showHoverEffectStr, pluckNumber, 0],
['hovercapsepchar', 'hoverCapSepChar', pluck, COMMASPACE],
['tooltipsepchar', 'tooltipSepChar', pluck, '$hoverCapSepChar'],
['labelsepchar', 'labelSepChar', pluck, '$tooltipSepChar'],
['showpercentintooltip', 'showPercentInToolTip', pluckNumber, 1],
['showpercentvalues', 'showPercentValues', pluckNumber, 0],
[BLANK, 'slicingDistance', pluckNumber, (heightAllotted * 0.1)],
['slicingdistance', 'slicingHeight', pluckNumber, '$slicingDistance', function (datasetConf) {
if (datasetConf.slicingHeight > 2 * datasetConf.slicingDistance) {
datasetConf.slicingDistance = 0;
}
else {
datasetConf.slicingDistance = datasetConf.slicingHeight;
}
}],
[BLANK, 'blankSpace', pluckNumber, BLANK_SPACE],
['labeldistance', 'labelDistance', pluckNumber, DEFAULT_LABEL_DISTANCE],
['issliced', 'isSliced', pluckNumber, 0],
['is2d', 'is2d', pluckNumber, 0],
[BLANK, 'blankSpace', pluckNumber, DEFAULT_BLANK_SPACE],
['showlabelsatcenter', 'showLabelsAtCenter', pluckNumber, 0],
['smartlinethickness', 'connectorWidth', pluckNumber, 1],
['smartlinealpha', 'connectorAlpha', pluckNumber, 100],
['smartlinecolor', 'rawSmartLineColorCode', pluck, function () {
return colorManager.getColor('baseFontColor');
}],
['labelalpha', 'labelAlpha', pluckNumber, 100],
['basefont', 'baseFont', pluck, 'Verdana,sans'],
['basefontsize', 'baseFontSize', pluckNumber, 10],
['basefontcolor', 'baseFontColor', pluck, baseFontColor],
['labelfontcolor', 'labelFontColor', pluck, '$baseFontColor'],
['showtooltip', 'showTooltip', pluckNumber, 1],
['percentofprevious', 'percentOfPrevious', pluckNumber, 0],
['animationduration', 'animationDuration', pluckNumber, 1, function (datasetConf) {
datasetConf.animationDuration *= 1000;
}]
]);
datasetConf.connectorColor = convertColor(datasetConf.rawSmartLineColorCode,
datasetConf.connectorAlpha);
// Calculate the line height with the style applied in chart level
setLineHeight(globalStyle);
// Get only the starting digits from the line height string. This is a temprary property.
globalStyle.nLineHeight = (globalStyle.lineHeight.match(/^\d+/))[0];
copyProperties(globalStyle, datasetConf, [
[BLANK, 'lineHeight', pluckNumber, datasetConf.baseFontSize]
]);
// Detele the property as it was created for computation purpose only.
delete globalStyle.nLineHeight;
// Call function for specific configuration partucular to a chart.
invokeHookFns(configureSpecificsFn);
if (!datasetConf.showLabels && !datasetConf.showValues) {
// If the labels and values both are disabled, refrain from plotting the datalabels.
// This is a flag that let the drawing components know about the user choice.
datasetConf.datalabelDisabled = true;
} else {
datasetConf.datalabelDisabled = false;
}
// Normalize the data set. This process handles all the parseInt, parseFloat like methods, computes
// additional keys if necessary
dataStoreComponent.data = datasetStore.getNormalizeDataSet(datasetDataArr);
// Call functions that are to be executed before the drawing starts.
invokeHookFns(preDrawingHook);
},
_checkValidData: function (data) {
var datasetDefStore = this,
chart = datasetDefStore.chart;
if (!(data && data.length)) {
chart.setChartMessage();
return false;
}
return true;
},
addLegend : function () {
var dataSet = this,
chart = dataSet.chart,
chartAttr = chart.jsonData.chart,
i,
dataObj,
data = dataSet.JSONData.data,
legend = chart.components.legend;
legend.emptyItems();
for (i = 0; i < data.length; i += 1) {
dataObj = data[i];
if (dataObj.pseudoPoint) {
continue;
}
dataObj.legendItemId = legend.addItems(dataSet, undefined, {
type: dataSet.type,
label: dataObj.label,
index: i,
enabled: pluckNumber(chartAttr.includeinlegend, 1),
legendItemId: dataObj.legendItemId
});
}
},
getNormalizeDataSet : function(dataArr, options) {
var datasetStore = this,
Point = datasetStore.getPointInContext(),
chart = datasetStore.chart,
conf = datasetStore.conf,
chartComponents = chart.components,
numberFormatter = chartComponents.numberFormatter,
smartLabel = datasetStore.chart.linkedItems.smartLabel,
colorManager = chartComponents.colorManager,
index, dataObj,
filteredData = [],
refreshedData,
stubFn, hasValidPoint, highestValue,
sumValue = 0,
countPoint = 0,
sum, refreshedDataLength, dataValue, prevValue, name, smartTextObj,
noOFSlicedElement = 0, pointSliced, pValue, formatedVal, labelText,
displayValueText, displayValue, toolText, ttValue, filteredDataObj,
showPercentValues = conf.showPercentValues,
labelSepChar = conf.labelSepChar,
chartAttr = chart.jsonData.chart,
isSliced = conf.isSliced,
plotColor, plotAlpha, plotBorderColor, plotBorderAlpha,
pointShadow = {
apply: conf.showShadow,
opacity: 1
},
tooltipOptions, defStyle, hoverEffects, displayValueArgs,
plotBorderWidth = conf.plotBorderThickness,
dataConnectorStyle = conf.dataConnectorStyle = {},
colorIndexStart = chart.config.PLOT_COLOR_INDEX_START,
res,
legendItemId,
colorApplied,
legendColor;
function extractTextStyle (dataObj) {
var keyMap = {
'labelfont' : 'fontFamily',
'labelfontcolor' : 'color',
'labelfontsize' : 'fontSize',
'labelfontbold' : 'fontWeight',
'labelfontitalic': 'fontStyle'
},
style,
key;
for (key in keyMap) {
if (!(key in dataObj)) { continue; }
style = style || {};
style[keyMap[key]] = dataObj[key];
}
if (!style) { return style; }
if (style.fontWeight) {
style.fontWeight = pluckNumber(style.fontWeight) ? 'bold' : 'normal';
}
if (style.fontStyle) {
style.fontStyle = pluckNumber(style.fontStyle) ? 'italic' : 'normal';
}
return style;
}
extend2((defStyle = conf.style = {}), chart.config.style);
defStyle.borderDash = noneStr;
defStyle.borderPadding = 2;
defStyle.borderRadius = 0;
defStyle.borderThickness = 1;
defStyle.color = convertColor(conf.labelFontColor, conf.labelAlpha);
defStyle.fontFamily = conf.baseFont;
defStyle.fontSize = conf.baseFontSize + PXSTRING;
defStyle.fontStyle = NORMALSTRING;
defStyle.fontWeight = NORMALSTRING;
dataConnectorStyle.connectorWidth = conf.connectorWidth;
dataConnectorStyle.connectorColor = conf.connectorColor;
options = options || {};
stubFn = options.getEmptyStubObject;
res = datasetStore.datasetCalculations(dataArr);
hasValidPoint = res.hasValidPoint;
refreshedData = res.refreshedData;
sumValue = res.sumValue;
countPoint = res.countPoint;
highestValue = res.highestValue;
datasetStore._chartLevelAttr = lib.parsexAxisStyles({}, {}, chartAttr, defStyle);
if (hasValidPoint) {
conf.sumValue = sumValue;
sum = numberFormatter.dataLabels(sumValue);
refreshedDataLength = refreshedData.length;
smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
for (index = 0; index < refreshedDataLength; index += 1) {
dataObj = refreshedData[index];
legendItemId = dataObj.legendItemId;
dataValue = dataObj.cleanValue;
prevValue = index ? refreshedData[index - 1].value : dataValue;
name = parseUnsafeString(pluck(dataObj.label, dataObj.name, BLANKSTRING));
smartTextObj = smartLabel.getOriSize(name);
plotAlpha = dataObj.alpha || conf.plotFillAlpha;
colorApplied = pluck(dataObj.color, colorManager.getPlotColor(colorIndexStart++));
legendColor = convertColor(colorApplied);
plotColor = convertColor(colorApplied, plotAlpha);
plotBorderColor = pluck(dataObj.bordercolor, conf.plotBorderColor,
getLightColor(colorApplied, 25)).split(COMMASTRING)[0];
plotBorderAlpha = !conf.showPlotBorder ? ZEROSTRING :
pluck(dataObj.borderalpha, conf.plotBorderAlpha, '80');
pointShadow.opacity = Math.max(plotAlpha, plotBorderAlpha) / 100;
pointSliced = pluckNumber(dataObj.issliced, isSliced);
if (pointSliced) {
noOFSlicedElement += 1;
conf.preSliced = pointSliced;
}
if (res.prevPerValReq) {
sumValue = prevValue;
}
pValue = numberFormatter.percentValue(dataValue / sumValue * 100);
if(!conf.datalabelDisabled) {
formatedVal = numberFormatter.dataLabels(dataValue) || BLANKSTRING;
labelText = conf.showLabels === 1 ? name : BLANKSTRING;
displayValueText = pluckNumber(dataObj.showvalue, conf.showValues) === 1 ?
(showPercentValues === 1 ? pValue : formatedVal ) : BLANKSTRING;
displayValue = getValidValue(parseUnsafeString(dataObj.displayvalue));
displayValueArgs = pluck(displayValue, name + labelSepChar + (showPercentValues ? pValue :
formatedVal), BLANKSTRING);
if (displayValue) {
displayValueText = displayValue;
} else {
if (displayValueText !== BLANKSTRING && labelText !== BLANKSTRING) {
displayValueText = labelText + labelSepChar + displayValueText;
}
else {
displayValueText = pluck(labelText, displayValueText) || BLANKSTRING;
}
}
}
toolText = getValidValue(parseUnsafeString(pluck(dataObj.tooltext, conf.toolText)));
if (toolText !== undefined) {
tooltipOptions = {
formatedVal : formatedVal,
name : name,
pValue : pValue,
sum : sum,
sumValue : sum,
dataValue: dataValue,
prevValue: prevValue,
highestValue: highestValue
};
toolText = parseTooltext(toolText, [1,2,3,7,14,24,25,37],
datasetStore.getTooltipMacroStub(tooltipOptions), dataObj, chartAttr);
}
else {
ttValue = conf.showPercentInToolTip === 1 ? pValue : formatedVal;
toolText = name !== BLANKSTRING ? name + conf.tooltipSepChar + ttValue : ttValue;
}
hoverEffects = datasetStore.pointHoverOptions(dataObj, {
color: colorApplied,
alpha: plotAlpha,
borderColor: plotBorderColor,
borderAlpha: plotBorderAlpha,
borderWidth: plotBorderWidth
});
filteredDataObj = {
displayValue: displayValueText,
displayValueArgs: displayValueArgs,
style: lib.parsexAxisStyles(dataObj, {}, chartAttr, defStyle, plotColor),
appliedStyle: extractTextStyle(dataObj),
name: name,
categoryLabel: name,
rawColor: colorApplied,
rawAlpha: plotAlpha,
toolText: toolText,
legendCosmetics: undefined,
legendItemId: legendItemId,
showInLegend: undefined,
y: dataValue,
shadow: pointShadow,
smartTextObj: smartTextObj,
legendColor: legendColor,
color: plotColor,
alpha: plotAlpha,
borderColor: convertColor(plotBorderColor, plotBorderAlpha),
borderWidth: plotBorderWidth,
link : getValidValue(dataObj.link),
isSliced : pointSliced,
doNotSlice: !conf.enableSlicing,
hoverEffects: hoverEffects.enabled && hoverEffects.options,
rolloverProperties: hoverEffects.enabled && hoverEffects.rolloverOptions
};
filteredData.push(new Point(filteredDataObj));
}
}
conf.noOFSlicedElement = noOFSlicedElement;
return filteredData;
},
datasetCalculations : function (dataArr) {
var datasetStore = this,
chart = datasetStore.chart,
chartComponents = chart.components,
numberFormatter = chartComponents.numberFormatter,
index, length, dataObj, itemValue, res = {};
res.refreshedData = [];
res.sumValue = res.countPoint = 0;
res.highestValue = Number.NEGATIVE_INFINITY;
for (index = 0, length = dataArr.length; index < length; index++) {
dataObj = dataArr[index];
if (dataObj.vline) {
// Funnel or pyramid does not use vline. Ignoring the same if user put it mistakenly.
continue;
}
dataObj.cleanValue = itemValue = Math.abs(numberFormatter.getCleanValue(dataObj.value, true));
if (itemValue !== null) {
// If a valid value is provided in the configuration
res.hasValidPoint = true;
res.highestValue = res.highestValue || itemValue;
res.refreshedData.push(dataObj);
res.sumValue += itemValue;
res.countPoint += 1;
res.highestValue = Math.max(res.highestValue, res.itemValue);
}
}
return res;
},
pointHoverOptions: function (dataObj, pointCosmetics) {
var datasetStore = this,
conf = datasetStore.conf,
chart = datasetStore.chart,
hoverEffect = pluckNumber(dataObj.showhovereffect, conf.showHoverEffect),
hoverEffects = {
enabled: hoverEffect
},
rolloverProperties = {},
highlightColors,
colorLen,
index,
chartAttr = chart.jsonData ? chart.jsonData.chart : {};
// Detect whether any of the hover effect attributes are explicitly set or not
// Enable hover effect when any of the hover attributes are explicitly set
if (!hoverEffect) {
hoverEffect = hoverEffects.enabled = pluck(dataObj.hovercolor,
chartAttr.plotfillhovercolor, dataObj.hoveralpha, chartAttr.plotfillhoveralpha,
dataObj.borderhovercolor, chartAttr.plotborderhovercolor,
dataObj.borderhoverthickness, chartAttr.plotborderhoverthickness,
dataObj.borderhoveralpha, chartAttr.plotborderhoveralpha) !== UNDEFINED;
}
if (hoverEffect) {
// Parse hover attributes
hoverEffects.highlight = pluckNumber(dataObj.highlightonhover,
chartAttr.highlightonhover);
hoverEffects.color = pluck(dataObj.hovercolor,
chartAttr.plotfillhovercolor);
hoverEffects.alpha = pluck(dataObj.hoveralpha,
chartAttr.plotfillhoveralpha, pointCosmetics.alpha);
hoverEffects.borderColor = pluck(dataObj.borderhovercolor,
chartAttr.plotborderhovercolor, pointCosmetics.borderColor);
hoverEffects.borderThickness = pluckNumber(dataObj.borderhoverthickness,
chartAttr.plotborderhoverthickness, pointCosmetics.borderWidth);
hoverEffects.borderAlpha = pluck(dataObj.borderhoveralpha,
chartAttr.plotborderhoveralpha, pointCosmetics.borderAlpha);
// If hover effect is enabled but no hover color is provided, just highlight the default color
if (hoverEffects.highlight !== 0 && hoverEffects.color === undefined) {
hoverEffects.highlight = 1;
}
hoverEffects.color = pluck(hoverEffects.color, pointCosmetics.color).replace(/,+?$/, BLANK);
if (hoverEffects.highlight === 1) {
highlightColors = hoverEffects.color.split(/\s{0,},\s{0,}/);
colorLen = highlightColors.length;
for (index = 0; index < colorLen; index += 1) {
highlightColors[index] = getLightColor(highlightColors[index], 70);
}
hoverEffects.color = highlightColors.join(',');
}
rolloverProperties = {
color: hoverEffects.color,
alpha: +hoverEffects.alpha,
borderColor: convertColor(hoverEffects.borderColor,
hoverEffects.borderAlpha),
borderWidth: hoverEffects.borderThickness
};
}
return {
enabled: hoverEffect,
options: hoverEffects,
rolloverOptions: rolloverProperties
};
},
getTooltipMacroStub : function (options) {
return {
formattedValue: options.formatedVal,
label: options.name,
percentValue : options.pValue,
sum: options.sum,
unformattedSum: options.sumValue
};
},
preDrawingSpaceManagement : function () {
var datasetStore = this,
Point = datasetStore.getPointInContext(),
chart = datasetStore.chart,
chartConf = chart.config,
components = chart.components,
caption = components.caption,
subCaption = components.subCaption,
capHeight = caption.config.height || 0,
subCapHeight = subCaption.config.height || 0,
conf = datasetStore.conf,
showTooltip = conf.showTooltip,
slicingDistance = conf.slicingDistance,
canvasHeight, canvasMaxWidth,
chartWorkingHeight = chartConf.height - (chartConf.marginTop + chartConf.marginBottom),
chartWorkingWidth = chartConf.width - (chartConf.marginRight + chartConf.marginLeft),
dataArr = datasetStore.components.data,
length, labelDistance, showLabelsAtCenter,
blankSpace = conf.blankSpace,
i = datasetStore.LABEL_PLACEMENT_ITERATOR_INDEX_START,
upperRadiusFactor = Point.upperRadiusFactor,
minWidthForChart, drawingWillExtend, maxWidthForLabel, useSameSlantAngle,
labelMaxUsedWidth, hasPoint, maxValue, valueRadiusIncrementRatio,
//sumValues = conf.sumValue,
smartLabel = chart.linkedItems.smartLabel,
totalValue, point, lineHeight, smartTextObj, chartDrawingWidth,
currentValue, ratioK, currentDiameter, labelMaxWidth, extraSpace,
newDiameter = 0, lowestRadiusFactor, labelMaxW = 0, tempSnap, labelOverlappingW,
utils = datasetStore.utils(datasetStore),
gutter = 5,
snapOffset,
invokeHookFns = utils.invokeHookFns,
labelStyle,
prePointProcessingHookFn = datasetStore.prePointProcessingHookFn,
legend = components.legend,
legendWidth = 0,
outCanvasSpace = 0;
if (legend.config.legendPos === 'right') {
legendWidth = legend.config.width + 2 * gutter;
}
outCanvasSpace += chartConf.oriCanvasLeft = chart.config.canvasLeft;
chartConf.oriBottomSpace = chart.config.marginBottom;
chartConf.oriTopSpace = chart.config.marginTop;
outCanvasSpace += chart.config.canvasRight;
// For Anotation macros store temp conf
tempSnap = conf._tempSnap = {
top3DSpace : 0,
bottom3DSpace : 0,
topLabelSpace : 0,
rightLabelSpace : 0
};
canvasHeight = chartWorkingHeight - slicingDistance;
canvasMaxWidth = Math.min(2 * canvasHeight, chartWorkingWidth);
chartConf.marginTop += slicingDistance / 2;
chartConf.marginBottom += slicingDistance / 2;
// Find the label maximun width
length = dataArr.length;
labelDistance = conf.labelDistance + blankSpace;
showLabelsAtCenter = conf.showLabelsAtCenter;
minWidthForChart = Math.min(canvasMaxWidth, chartWorkingWidth * 0.3);
drawingWillExtend = chartWorkingWidth - minWidthForChart;
chartWorkingWidth -= legendWidth;
maxWidthForLabel = chartWorkingWidth - minWidthForChart - labelDistance;
labelMaxUsedWidth = 0;
hasPoint = dataArr[0];
maxValue = hasPoint && dataArr[0].y ? dataArr[0].y : 1;
valueRadiusIncrementRatio = 0.8 / maxValue;
useSameSlantAngle = conf.useSameSlantAngle == 1;
invokeHookFns(prePointProcessingHookFn, [dataArr]);
totalValue = conf.totalValue || 0;
smartLabel.useEllipsesOnOverflow(chartConf.useEllipsesWhenOverflow);
for(;i < length; i += 1) {
point = dataArr[i];
if (point.legendItemId) {
legend.configureItems(point.legendItemId, {
configuration: {
fillColor: point.legendColor
}
});
}
labelStyle = point.style;
setLineHeight(labelStyle);
lineHeight = pluckNumber(mathCeil(parseFloat(labelStyle.lineHeight) +
labelStyle.borderPadding + labelStyle.borderThickness + gutter), 10);
smartLabel.setStyle(labelStyle);
currentValue = point.y;
if (showLabelsAtCenter) {
smartTextObj = smartLabel.getSmartText(point.displayValue, chartWorkingWidth, lineHeight);
} else {
currentValue = (point.getModifiedCurrentValue && point.getModifiedCurrentValue(totalValue)) ||
currentValue;
ratioK = point.getRatioK(currentValue, valueRadiusIncrementRatio,
totalValue, maxValue);
currentDiameter = minWidthForChart * ratioK;
labelMaxWidth = maxWidthForLabel + ((minWidthForChart - currentDiameter) / 2);
smartTextObj = smartLabel.getSmartText(point.displayValue, labelMaxWidth, lineHeight);
point.displayValue = smartTextObj.text;
showTooltip && smartTextObj.tooltext && (point.originalText = smartTextObj.tooltext);
labelMaxUsedWidth = Math.max(labelMaxUsedWidth, smartTextObj.width);
if (drawingWillExtend > 0) {
if (smartTextObj.width > 0) {
extraSpace = labelMaxWidth - smartTextObj.width;
}
else {
extraSpace = labelMaxWidth + labelDistance;
}
newDiameter = (1 / (ratioK + 1)) * (currentDiameter + 2 * extraSpace + minWidthForChart);
drawingWillExtend = Math.min(drawingWillExtend, newDiameter - minWidthForChart);
}
totalValue += conf.offsetVal === undefined ? point.y :
(typeof conf.offsetVal === 'function' ? conf.offsetVal(i) : conf.offsetVal);
}
}
if (legend.config.legendPos === 'right') {
chart.isLegendRight = true;
chartConf.marginRight += legendWidth;
outCanvasSpace += legendWidth;
} else {
chart.isLegendRight = false;
}
if (point) {
lowestRadiusFactor = point.getLowestRadiusFactor(maxValue);
}
chartDrawingWidth = minWidthForChart + drawingWillExtend;
if (chartDrawingWidth > canvasMaxWidth) {
chartDrawingWidth = canvasMaxWidth;
}
totalValue = conf.offsetVal === undefined ? 0 :
(typeof conf.offsetVal === 'function' ? conf.offsetVal() : conf.offsetVal);
// Now we have the actual drawing width for the
// funnel and pyramid reiterate through the data and find the
// max label width
if (!showLabelsAtCenter) {
i = datasetStore.LABEL_PLACEMENT_ITERATOR_INDEX_START;
for (length = dataArr.length; i < length; i += 1) {
point = dataArr[i];
currentValue = point.y;
currentValue = (point.getModifiedCurrentValue && point.getModifiedCurrentValue(totalValue)) ||
currentValue;
ratioK = point.getRatioK(currentValue, valueRadiusIncrementRatio, totalValue, maxValue);
currentDiameter = chartDrawingWidth * ratioK;
labelMaxWidth = maxWidthForLabel + ((minWidthForChart - currentDiameter) / 2) - legendWidth;
smartTextObj = smartLabel.getSmartText(point.displayValue, labelMaxWidth, lineHeight);
labelMaxW = mathMax(labelMaxW, (currentDiameter * 0.5) + smartTextObj.width + labelDistance);
totalValue += conf.offsetVal === undefined ? point.y :
(typeof conf.offsetVal === 'function' ? conf.offsetVal() : conf.offsetVal);
}
}
if (labelMaxUsedWidth > 0) {
tempSnap.rightLabelSpace = (chartWorkingWidth - chartDrawingWidth);
// Keep the chart at center and find extra space required to place the label
labelOverlappingW = labelMaxW - (chartConf.canvasWidth * 0.5);
if (labelOverlappingW > 0) {
// Adjust the extra space required to place the label
chartConf.marginRight += labelOverlappingW;
chartConf.marginLeft -= labelOverlappingW;
}
chartConf.marginRight += tempSnap.rightLabelSpace * 0.5;
chartConf.marginLeft += tempSnap.rightLabelSpace * 0.5;
}
else {
labelDistance = 0;
}
conf.labelDistance = conf.connectorWidth = labelDistance;
if ((showLabelsAtCenter || !labelMaxUsedWidth) && canvasMaxWidth < chartWorkingWidth) {
chartConf.marginLeft += (chartWorkingWidth - canvasMaxWidth - labelDistance) * 0.5;
chartConf.marginRight += (chartWorkingWidth - canvasMaxWidth - labelDistance) * 0.5;
}
if (!conf.is2d) {
chartConf.marginTop += tempSnap.top3DSpace =
(chartDrawingWidth * conf.yScale * upperRadiusFactor) / 2;
chartConf.marginBottom += tempSnap.bottom3DSpace =
(chartDrawingWidth * conf.yScale * lowestRadiusFactor) / 2;
}
snapOffset = capHeight + subCapHeight + gutter;
chartConf.gaugeStartX = chartConf.marginLeft;
chartConf.gaugeStartY = chartConf.marginTop + snapOffset;
chartConf.gaugeEndX = chartDrawingWidth + chartConf.marginLeft;
chartConf.gaugeEndY = chartConf.canvasHeight + chartConf.marginTop;
chartConf.gaugeCenterX = chartConf.gaugeStartX + ((chartConf.gaugeEndX - chartConf.gaugeStartX) / 2) -
chartConf.marginLeft / 2;
chartConf.gaugeCenterY = chartConf.gaugeStartY + ((chartConf.gaugeEndY - chartConf.gaugeStartY) / 2);
chartConf.plotSemiWidth = (chartConf.canvasWidth - tempSnap.rightLabelSpace) / 2;
chartConf.canvasCenterX = chartConf.oriCanvasLeft + chartDrawingWidth / 2;
},
hide: function (plotArr) {
var index,
length,
plot;
if (!plotArr || plotArr.length === 0) {
return;
}
for (index = 0, length = plotArr.length; index < length; index++) {
plot = plotArr[index];
plot.connector && plot.connector.hide();
plot.dataLabel && plot.dataLabel.hide();
plot.graphic && plot.graphic.hide();
plot.trackerObj && plot.trackerObj.hide();
}
},
animateElements: function (elements, subElem, subElemKeys, conditions, callback) {
var datasetStore = this,
chart = datasetStore.chart,
animationObj = chart.get(configStr, animationObjStr),
animDuration = animationObj.duration,
dummyAnimElem = animationObj.dummyObj,
dummyAnimObj = animationObj.animObj,
animType = animationObj.animType,
isPromiseExecuted = false,
target,
index,
length,
ele,
i,
l;
function promise () {
if (isPromiseExecuted) {
return;
}
callback();
isPromiseExecuted = true;
}
function animate (_t, point) {
var ialpha = (point || {}).alpha;
ialpha = ialpha === undefined ? conditions.post : {opacity: ialpha};
if (!_t) { return; }
_t.attr(conditions.pre);
_t.animateWith(dummyAnimElem, dummyAnimObj, ialpha, animDuration, animType, promise);
}
callback = callback || function () { };
subElemKeys = subElemKeys || [];
for (index = 0, length = elements.length; index < length; index++) {
ele = elements[index];
if (!ele) { continue; }
if (!subElemKeys.length) {
target = ele;
animate(target[subElem], ele.point);
} else {
for (i = 0, l = subElemKeys.length; i < l; i++) {
target = ((elements[index])[subElem])[subElemKeys[i]];
animate(target, ele.point);
}
}
}
},
drawIndividualDataLabel : function (point, index) {
var datasetStore = this,
conf = datasetStore.conf,
dataStore = datasetStore.components.data,
displayValue = point.displayValue,
plotItem = point.plot,
labelY = point.labelY,
labelX = point.labelX,
style = point.style || {},
fontSize = pluckNumber(parseInt(style.fontSize, 10), conf.baseFontSize),
lineHeight = conf.lineHeight,
yShift = fontSize * 0.3,
yDisplacement = lineHeight * 0.3,
connectorStartY, connectorEndY, lastConnectorEndY,
showLabelsAtCenter = conf.showLabelsAtCenter,
connectorEndSwitchHistoryY = conf.connectorEndSwitchHistoryY,
connectorEndX, connectorStartX,
labelDistance = conf.labelDistance,
blankSpace = conf.blankSpace,
connectorPath, yD,
streamLinedData = conf.streamLinedData;
if (!showLabelsAtCenter) {
connectorStartY = labelY - yShift - (point.distributionFactor * lineHeight);
connectorEndY = labelY - yShift;
lastConnectorEndY = connectorEndSwitchHistoryY[point.alignmentSwitch];
if (conf.lastplotY !== undefined && lastConnectorEndY !== undefined &&
lastConnectorEndY - connectorEndY < lineHeight) {
connectorEndY = lastConnectorEndY - lineHeight;
labelY = connectorEndY;
}
point.displayValue && (connectorEndSwitchHistoryY[point.alignmentSwitch] = connectorEndY);
conf.lastplotY = point.plotY;
if(conf.labelAlignment === conf.alignmentType.alternate){
if(point.alignmentSwitch){
connectorEndX = labelX + blankSpace + point.virtualWidth;
connectorStartX = connectorEndX + labelDistance +
(point.distributionFactor * conf.globalMinXShift);
}else{
connectorEndX = labelX - blankSpace;
connectorStartX = connectorEndX - (labelDistance - (point.lOverflow || 0)) -
(point.distributionFactor * conf.globalMinXShift);
}
}else{
connectorEndX = labelX - blankSpace;
connectorStartX = connectorEndX - (labelDistance - (point.lOverflow || 0)) -
(point.distributionFactor * conf.globalMinXShift);
}
// Drawing the connector for labels
// Check if the label is not blank and,
// label is not the first label of Funnel Chart
if ((typeof displayValue !== 'undefined' && displayValue !== BLANKSTRING) &&
!(index === 0 && streamLinedData)) {
connectorPath = [M, connectorStartX, connectorStartY, L, connectorEndX, connectorEndY];
plotItem.connector.attr({
path: connectorPath,
'shape-rendering': (connectorStartY === connectorEndY) && connectorEndY < 1 ? CRISP : BLANK
}).show();
} else {
plotItem.connector && plotItem.connector.hide();
}
if (index === 0 && streamLinedData) {
yD = (labelY + (dataStore[1].plot.dy || 0));
}
else {
yD = (connectorEndY + (plotItem.dy || 0));
}
if (displayValue !== BLANKSTRING) {
plotItem.dataLabel.transform('t' + labelX + COMMASTRING + yD).show();
} else {
plotItem.dataLabel && plotItem.dataLabel.hide();
}
} else {
if (index === 0 && streamLinedData) {
// access to the first plot item
yD = (labelY - yDisplacement + (dataStore[1].plot.distanceAvailed || 0));
}
else {
yD = (labelY - yDisplacement + (plotItem.distanceAvailed || 0));
}
if (displayValue !== BLANKSTRING) {
plotItem.dataLabel.transform('t' + labelX +','+ yD).show();
} else {
plotItem.dataLabel && plotItem.dataLabel.hide();
}
}
plotItem.dataLabel.attr({'text-bound': [style.backgroundColor, style.borderColor, style.borderThickness,
style.borderPadding, style.borderRadius, style.borderDash]});
},
drawAllLabels: function () {
var datasetStore = this,
chart = datasetStore.chart,
chartGraphics = chart.graphics,
plotItems = datasetStore.graphics.plotItems,
labelDrawingConfigArr = datasetStore.labelDrawingConfig,
dataLabelsGroup = chartGraphics.datalabelsGroup,
removeCSSProps = ['fontFamily', 'fontSize', 'fontWeight', 'fontStyle'],
groupLabelCssProps = removeCSSProps,
groupLabelCss = {},
paper = chart.components.paper,
conf = datasetStore.conf,
labelDrawingConfig,
plotItem,
setLink,
actions,
point,
value,
dlElem,
index,
length,
attr;
// Extract the required css from the list of css (guard for IE)
for (index = 0, length = groupLabelCssProps.length; index < length; index++) {
attr = groupLabelCssProps[index];
if (attr in datasetStore._chartLevelAttr) {
groupLabelCss[attr] = datasetStore._chartLevelAttr[attr];
}
}
chartGraphics.datalabelsGroup.css(groupLabelCss);
for (index = labelDrawingConfigArr.length - 1; index > -1; index--) {
labelDrawingConfig = labelDrawingConfigArr[index];
point = labelDrawingConfig.point;
setLink = !!point.link;
value = point.y;
// temporary fix till the time fill is inherited from the parent nodes in VML
if (labelDrawingConfig.args && labelDrawingConfig.css) {
labelDrawingConfig.args.fill = labelDrawingConfig.css.color || labelDrawingConfig.css.fill;
}
if (value === null || value === undefined || !point.shapeArgs) {
if (plotItems[index]) {
point.plot = plotItems[index];
dlElem = point.plot.dataLabel;
dlElem.removeCSS(removeCSSProps);
dlElem && dlElem.attr(labelDrawingConfig.args).css(labelDrawingConfig.css);
} else {
point.plot = plotItems[index] = {
dataLabel : paper.text(labelDrawingConfig.args, labelDrawingConfig.css, dataLabelsGroup)
};
}
datasetStore.drawIndividualDataLabel(point, index);
continue;
}
if (!((plotItem = plotItems[index]) && plotItem.dataLabel)) {
point.plot.dataLabel = plotItem.dataLabel = paper.text(labelDrawingConfig.args,
labelDrawingConfig.css, dataLabelsGroup);
if (!conf.showLabelsAtCenter || !(index === 0 && conf.streamLinedData)) {
plotItem.connector = paper.path(dataLabelsGroup);
}
} else {
plotItem.dataLabel.removeCSS(removeCSSProps);
plotItem.dataLabel.attr(labelDrawingConfig.args).css(labelDrawingConfig.css);
}
plotItem.dataLabel.tooltip(point.originalText);
plotItem.connector && plotItem.connector.attr({
'stroke-width': conf.dataConnectorStyle.connectorWidth,
stroke: conf.dataConnectorStyle.connectorColor,
ishot: true,
cursor: setLink ? POINTER : BLANK,
transform: labelDrawingConfig.transform
});
actions = labelDrawingConfig.actions;
!point.doNotSlice && plotItem.dataLabel.click(actions.click, labelDrawingConfig.context);
plotItem.dataLabel.hover(actions.hover[0], actions.hover[1]);
plotItem.dataLabel.attr({
transform: labelDrawingConfig.transform
});
datasetStore.drawIndividualDataLabel(point, index);
}
},
drawAllTrackers: function () {
var datasetStore = this,
trackerArgs = datasetStore.trackerArgs,
index,
length;
for (index = 0, length = trackerArgs.length; index < length; index++) {
datasetStore.drawTracker(trackerArgs[index]);
}
},
drawTracker: function(set) {
var datasetStore = this,
chart = datasetStore.chart,
renderer = chart.components.paper,
trackerGroup = chart.graphics.trackerGroup,
shapeArgs,
trackerObj,
trackerLabel = +new Date(),
point,
eventArgs;
point = set.plot;
if (! point) { return; }
trackerObj = point.trackerObj;
if (point.graphic) {
shapeArgs = point.graphic.Shapeargs.silhuette;
eventArgs = {
link: set.link,
value: set.y,
displayValue: set.displayValueArgs,
categoryLabel: set.categoryLabel,
dataIndex: point.index || BLANK,
toolText: set.toolText
};
set.datasetIndex = point.index;
if (trackerObj) {
trackerObj.attr({
path: shapeArgs,
isTracker: trackerLabel,
fill: TRACKER_FILL,
stroke: noneStr,
transform: 't0,' + (point._startTranslateY || 0),
ishot: true,
cursor: point.cursor
});
} else {
trackerObj = point.trackerObj = renderer.path(shapeArgs, trackerGroup)
.attr({
isTracker: trackerLabel,
fill: TRACKER_FILL,
stroke: noneStr,
transform: 't0,' + (point._startTranslateY || 0),
ishot: true,
cursor: point.cursor
});
}
trackerObj.data(EVENTARGS, eventArgs);
trackerObj.show();
}
},
calculatePositionCoordinate : function (dataArr, placeOtherSide) {
var datasetStore = this,
conf = datasetStore.conf,
maxValue = conf.maxValue,
is2d = conf.is2d,
x = conf.x,
plotItemArr = datasetStore.graphics.plotItems || [],
chart = datasetStore.chart,
chartConfig = chart.config,
y = chartConfig.canvasTop,
unitHeight = conf.unitHeight,
drawingRadius = conf.drawingRadius,
labelDistance = conf.labelDistance,
showLabelsAtCenter = conf.showLabelsAtCenter,
isHollow = conf.isHollow,
fontSize = chartConfig.style.fontSize,
yShift = fontSize * 0.3,
yScale = conf.yScale,
blankSpace = conf.blankSpace,
lastRadius = conf.lastRadius,
smartLabel = chart.linkedItems.smartLabel,
index, length,
totalHeight = 0,
point, sliceHeight,
lastIndex = dataArr.length - 1,
alignmentSwitchToggle = false,
distributionOffset = 0,
labelMeasurement, newRadius,
negativeSpanningDataEnd,
normalizedLabel,
lineHeight = conf.lineHeight,
widthHeightRatio = 0.8 / chartConfig.effCanvasHeight,
chartWidth = chart.config.width - 2,
streamlinedData = conf.streamLinedData,
// Base of the maximum trimmed label.
trimmedInfo = {
flag: false,
point: undefined,
sLabel: undefined,
setAll: function(flag, point, sLabel){
this.flag = flag;
this.point = point;
this.sLabel = sLabel;
}
},
// Base of the maximum spanned labels
largestLabel = {
point: undefined,
sLabel: undefined,
set: function(calcFn, predicate){
var _calcFn = calcFn,
_predicate = predicate;
return function(point, sLabel){
var existingLabelSpan,
currentLabelSpan;
if(point.dontPlot){
return;
}
if(!(this.point && this.sLabel)){
this.point = point;
this.sLabel = sLabel;
return;
}
existingLabelSpan = _calcFn(this.point, this.sLabel);
currentLabelSpan = _calcFn(point, sLabel);
if(_predicate(existingLabelSpan, currentLabelSpan)){
this.point = point;
this.sLabel = sLabel;
return;
}
};
}
},
leftTrimmedInfo = {},
rightTrimmedInfo = {},
lLargestLabel = {},
rLargestLabel = {},
extraConnectorSpace, xPos,
slicingGapPosition = conf.slicingGapPosition = {};
global.extend(leftTrimmedInfo, trimmedInfo);
global.extend(rightTrimmedInfo, trimmedInfo);
leftTrimmedInfo.setAll = function(flag, point, sLabel){
var _point = this.point,
_sLabel = this.sLabel,
existingLabelSpan,
currentLabelSpan;
this.flag = flag;
if(!(_point && _sLabel)){
this.point = point;
this.sLabel = sLabel;
return;
}
existingLabelSpan = _point.labelX - (_sLabel.oriTextWidth - _sLabel.width);
currentLabelSpan = point.labelX - (sLabel.oriTextWidth - sLabel.width);
if(existingLabelSpan > currentLabelSpan){
this.point = point;
this.sLabel = sLabel;
}
};
// Override the base class method for labels which are kept right
rightTrimmedInfo.setAll = function(flag, point, sLabel){
var _point = this.point,
_sLabel = this.sLabel,
existingLabelSpan,
currentLabelSpan;
this.flag = flag;
if(!(_point && _sLabel)){
this.point = point;
this.sLabel = sLabel;
return;
}
existingLabelSpan = _point.labelX + _sLabel.oriTextWidth;
currentLabelSpan = point.labelX + sLabel.oriTextWidth;
if(existingLabelSpan < currentLabelSpan){
this.point = point;
this.sLabel = sLabel;
}
};
global.extend(lLargestLabel, largestLabel);
global.extend(rLargestLabel, largestLabel);
lLargestLabel.set = (function(){
return largestLabel.set.apply(lLargestLabel, [function(point){
return point.labelX;
}, function(existingLabelSpan, currentLabelSpan){
return existingLabelSpan > currentLabelSpan ? true : false;
}]);
})();
rLargestLabel.set = (function(){
return largestLabel.set.apply(rLargestLabel, [function(point, sLabel){
return point.labelX + sLabel.oriTextWidth;
}, function(existingLabelSpan, currentLabelSpan){
return existingLabelSpan < currentLabelSpan ? true : false;
}]);
})();
conf.noOfGap = 0;
smartLabel.useEllipsesOnOverflow(chartConfig.useEllipsesWhenOverflow);
for(index = 0, length = dataArr.length; index < length ; index++){
point = dataArr[index];
if(!point){
continue;
}
point.x = index;
if (plotItemArr[index]) {
// @todo correct the slicing here
point.isSliced = plotItemArr[index].sliced || !!point.isSliced || !!conf.isSliced;
}
if(index){
placeOtherSide && (alignmentSwitchToggle = !alignmentSwitchToggle);
//code for slicing drawing
if (point.isSliced) {
xPos = point.x;
if (xPos > 1 && !slicingGapPosition[xPos]) {
slicingGapPosition[xPos] = true;
conf.noOfGap += 1;
}
if (xPos < lastIndex) {
slicingGapPosition[xPos + 1] = true;
conf.noOfGap += 1;
}
}
if(!streamlinedData){
totalHeight += sliceHeight = unitHeight * dataArr[index].y;
newRadius = drawingRadius * (1 - (totalHeight * widthHeightRatio));
}else{
if (conf.useSameSlantAngle == 1) {
newRadius = maxValue ? drawingRadius * point.y / maxValue : drawingRadius;
} else {
newRadius = maxValue ? drawingRadius * mathSqrt(point.y / maxValue) : drawingRadius;
}
// Default sliceHeight is set to one, in case its NaN.
sliceHeight = unitHeight * (dataArr[index - 1].y - point.y) || 1;
}
point.shapeArgs = {
x: x,
y: y,
R1: lastRadius,
R2: newRadius,
h: sliceHeight || 1,
r3dFactor: yScale,
isHollow: isHollow,
gStr: 'point',
is2D: is2d,
renderer: chart.components.paper,
isFunnel: true
};
smartLabel.setStyle(point.style);
point.oriText = point.displayValue;
labelMeasurement = labelMeasurement = smartLabel
.getSmartText(point.displayValue, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
if (showLabelsAtCenter) {
point.labelAline = POSITION_MIDDLE;
point.labelX = x;
point.labelY = (is2d ? y : y + (yScale * lastRadius)) + (sliceHeight / 2) + yShift;
}
else {
point.labelAline = POSITION_START;
point.alignmentSwitch = alignmentSwitchToggle;
point.distributionFactor = point.distributionFactor || 0;
if(alignmentSwitchToggle){
point.labelX = x - (labelDistance + newRadius + blankSpace + labelMeasurement.width);
point.labelX -= point.distributionFactor * conf.globalMinXShift;
lLargestLabel.set(point, labelMeasurement);
}else{
point.labelX = x + labelDistance + newRadius + blankSpace;
point.labelX += point.distributionFactor * conf.globalMinXShift;
rLargestLabel.set(point, labelMeasurement);
}
distributionOffset = point.distributionFactor * lineHeight;
point.labelY = y + yShift + sliceHeight + distributionOffset;
}
// Checking text overflow for alternate alignment
if(placeOtherSide){
if(alignmentSwitchToggle && (point.labelX < 0)){
// Left and behind the margin
negativeSpanningDataEnd = point.labelX + labelMeasurement.width;
normalizedLabel = smartLabel.getSmartText(point.displayValue, negativeSpanningDataEnd,
Number.POSITIVE_INFINITY, true);
point.labelX = 2;
point.isLabelTruncated = true;
point.displayValue = normalizedLabel.text;
point.virtualWidth = normalizedLabel.maxWidth;
leftTrimmedInfo.setAll(true, point, normalizedLabel);
}else if(!alignmentSwitchToggle && (point.labelX + labelMeasurement.width > chartWidth)){
// Right side and spanning the margin
normalizedLabel = smartLabel.getSmartText(point.displayValue, chartWidth - point.labelX,
Number.POSITIVE_INFINITY, true);
point.isLabelTruncated = true;
point.displayValue = normalizedLabel.text;
point.virtualWidth = normalizedLabel.maxWidth;
rightTrimmedInfo.setAll(true, point, normalizedLabel);
}
}
point.pWidth = point.virtualWidth = point.virtualWidth || labelMeasurement.width;
y += sliceHeight;
lastRadius = newRadius;
}else{
point.oriText = point.displayValue;
if (conf.useSameSlantAngle == 1) {
newRadius = maxValue ? drawingRadius * point.y / maxValue : drawingRadius;
} else {
newRadius = maxValue ? drawingRadius * mathSqrt(point.y / maxValue) : drawingRadius;
}
if (point.labelWidth > newRadius * 2 && !placeOtherSide) {
point.labelAline = POSITION_START;
point.labelX = 0;
}
else {
point.labelAline = POSITION_MIDDLE;
point.labelX = x;
}
extraConnectorSpace = labelDistance * 2;
point.displayValue = smartLabel.getSmartText(point.displayValue, newRadius * 2 +
extraConnectorSpace, Number.POSITIVE_INFINITY, true).text;
point.labelY = (is2d ? y : y - (yScale * lastRadius)) - yShift - blankSpace;
}
point.plotX = x;
point.plotY = y;
}
// Recalculate the space one more time. Ideally this should be given by space manager.
// However in the current scope space manager cannot be called from here.
datasetStore.findBestPosition.call(datasetStore, dataArr, {
'lTrimmedInfo': leftTrimmedInfo,
'rTrimmedInfo': rightTrimmedInfo,
'lLargestLabel': lLargestLabel,
'rLargestLabel': rLargestLabel
});
},
findBestPosition : function (dataArr, config) {
var datasetStore = this,
conf = datasetStore.conf,
chart = datasetStore.chart,
chartConfig = chart.config,
shift = 0,
lTrimmedInfo = config.lTrimmedInfo,
rTrimmedInfo = config.rTrimmedInfo,
lLargestLabel = config.lLargestLabel,
rLargestLabel = config.rLargestLabel,
smartLabel = chart.linkedItems.smartLabel,
trimmedLength,
point, sLabel, leftXSpace, rightXSpace, newLabel,
data, index, length,
unfoldWidth = 0, overflow,
streamLinedData = conf.streamLinedData,
allowedLeftX = conf.blankSpace,
allowedRightX = chartConfig.width - conf.blankSpace;
if(lTrimmedInfo.flag && rTrimmedInfo.flag){
// If labels are large in both of the sides. No need to shift the system
return;
}
if(rTrimmedInfo.flag) {
// Only right side labels are large. Shift left
if(!lLargestLabel.point){
return;
}
point = rTrimmedInfo.point;
sLabel = rTrimmedInfo.sLabel;
trimmedLength = sLabel.oriTextWidth - sLabel.width;
leftXSpace = lLargestLabel.point.labelX - allowedLeftX;
shift = - Math.ceil(Math.min(trimmedLength, leftXSpace));
} else if(lTrimmedInfo.flag) {
// Only left side labels are large. Shift right
if(!rLargestLabel.point){
return;
}
point = lTrimmedInfo.point;
sLabel = lTrimmedInfo.sLabel;
trimmedLength = sLabel.oriTextWidth - sLabel.width;
rightXSpace = allowedRightX - (rLargestLabel.point.labelX + rLargestLabel.sLabel.width);
shift = Math.ceil(Math.min(trimmedLength, rightXSpace));
}
// Apply shift to the whole system
if(!shift){
smartLabel.useEllipsesOnOverflow(chartConfig.useEllipsesWhenOverflow);
for(index = 0, length = dataArr.length; index < length; index++) {
data = dataArr[index];
if((overflow = (data.labelX + data.pWidth - allowedRightX)) > 0){
data.lOverflow = overflow;
data.labelX -= overflow;
if(chart.isLegendRight){
data.displayValue = smartLabel.getSmartText(data.oriText, (data.pWidth - overflow),
Number.POSITIVE_INFINITY, true).text;
}else{
data.lOverflow = overflow;
data.labelX -= overflow;
}
}
}
return;
}
for(index = 0, length = dataArr.length; index < length; index++) {
data = dataArr[index];
if(!index && streamLinedData){
data.labelX += shift;
continue;
}
if(data.alignmentSwitch) {
// left labels
if(shift < 0){
newLabel = smartLabel
.getSmartText(data.oriText, (data.pWidth),Number.POSITIVE_INFINITY, true);
}else{
newLabel = smartLabel.getSmartText(data.oriText, (data.pWidth + shift),
Number.POSITIVE_INFINITY, true);
}
if(data.isLabelTruncated){
unfoldWidth = (newLabel.width - data.pWidth);
}
data.virtualWidth = newLabel.width;
}else {
// Labels at right
if(shift > 0){
newLabel = smartLabel
.getSmartText(data.oriText, (data.pWidth),Number.POSITIVE_INFINITY, true);
}else{
newLabel = smartLabel.getSmartText(data.oriText, (data.pWidth - shift),
Number.POSITIVE_INFINITY, true);
}
data.virtualWidth = newLabel.width;
}
data.displayValue = newLabel.text;
data.labelX += shift - unfoldWidth;
data.shapeArgs && (data.shapeArgs.x +=shift);
unfoldWidth = 0;
}
},
getPlotData: function (id) {
var datasetStore = this,
data = datasetStore.components.data[id],
userData = datasetStore.userData || (datasetStore.userData = []),
props = [
'y',
'name',
'color',
'alpha',
'borderColor',
'borderWidth',
'link',
'label',
'displayValue',
'datasetIndex',
'toolText'
],
plotData,
i,
prop;
if (!userData[id]) {
plotData = userData[id] = {};
for (i = 0; i < props.length; i++) {
plotData[prop = props[i]] = data[prop];
}
plotData.value = plotData.y;
plotData.label = plotData.name;
delete plotData.y;
delete plotData.name;
}
else {
plotData = userData[id];
}
return plotData;
},
pyramidFunnelShape: (function () {
// @todo generic fn for pyramid and funnel
//list of attr that will handled here
var attrList = {
y : true,
R1 : true,
R2 : true,
h : true,
r3dFactor : true,
color : true,
opacity : true,
fill : true,
stroke : true,
strokeColor: true,
strokeAlpha: true,
'stroke-width' : true
},
//FIX for #FWXT-600
//for zero radius calcPoints return erroneous value
minRadius = 0.01,
getArcPath = function (cX, cY, startX, startY, endX, endY, rX, rY, isClockWise, isLargeArc) {
return [A, rX, rY, 0, isLargeArc, isClockWise, endX, endY];
},
/**
* calcPoints method calculates and returns the
* coordinates of four points of common tangency
* between the upper and lower ellipses.
* @param a1 semi-major axis length of the upper ellipse
* @param b1 semi-minor axis length of the upper ellipse
* @param h1 height of upper ellipse center
* @param a2 semi-major axis length of the lower ellipse
* @param b2 semi-minor axis length of the lower ellipse
* @param h2 height of lower ellipse center
* @returns object holding point instances corresponding
* to the 4 points of tangencies.
*/
calcPoints = function (a1, b1, h1, a2, b2, h2) {
// calcuating parameters of formula
var alpha = mathPow(a2, 2) - mathPow(a1, 2),
beta = -2 * (mathPow(a2, 2) * h1 - mathPow(a1, 2) * h2),
gamma = mathPow(a1 * b2, 2) + mathPow(a2 * h1, 2) -
mathPow(a2 * b1, 2) - mathPow(a1 * h2, 2),
k = mathSqrt(mathPow(beta, 2) - 4 * alpha * gamma),
// getting the 2 y-intercepts for there are 2 pairs of tangents
c1 = (-beta + k) / (2 * alpha),
c2 = (-beta - k) / (2 * alpha),
oneHND = 100,
objPoints,
c,
m1,
m2,
p1,
p2,
p3,
p4,
i;
// but we need only one pair and hence one value of y-intercept
if (c1 < h2 && c1 > h1) {
c = c2;
}
else if (c2 < h2 && c2 > h1) {
c = c1;
}
// getting the slopes of the 2 tangents of the selected pair
m1 = mathSqrt((mathPow(c - h1, 2) - mathPow(b1, 2)) / mathPow(a1, 2));
m2 = -m1;
// getting the 4 points of tangency
// right sided points
//upper
p1 = {
x : mathRound((mathPow(a1, 2) * m1 / (c - h1)) * oneHND) / oneHND,
y : mathRound(((mathPow(b1, 2) / (c - h1)) + h1) * oneHND) / oneHND
};
//lower
p2 = {
x : mathRound((mathPow(a2, 2) * m1 / (c - h2)) * oneHND) / oneHND,
y : mathRound(((mathPow(b2, 2) / (c - h2)) + h2) * oneHND) / oneHND
};
// left sided points
//upper
p3 = {
x : mathRound((mathPow(a1, 2) * m2 / (c - h1)) * oneHND) / oneHND,
y : mathRound(((mathPow(b1, 2) / (c - h1)) + h1) * oneHND) / oneHND
};
//lower
p4 = {
x : mathRound((mathPow(a2, 2) * m2 / (c - h2)) * oneHND) / oneHND,
y : mathRound(((mathPow(b2, 2) / (c - h2)) + h2) * oneHND) / oneHND
};
// storing in object to be passed as a collection
objPoints = {
topLeft: p3,
bottomLeft: p4,
topRight: p1,
bottomRight: p2
};
// checking for invalid situations
for (i in objPoints) {
if (isNaN(objPoints[i].x) || isNaN(objPoints[i].y)) {
// The funnel is extremely thin and points of tangencies
// coincide with ellipse ends
if (i === 'topLeft' || i === 'bottomLeft') {
objPoints[i].x = -a1;
}
else {
objPoints[i].x = a1;
}
objPoints[i].y = (i === 'bottomRight' || i === 'bottomLeft') ? h2 : h1;
}
}
// object returned
return objPoints;
},
getFunnel3DShapeArgs = function (x, y, R1, R2, h, r3dFactor, isHollow) {
var y2 = y + h,
R3 = R1 * r3dFactor, R4 = R2 * r3dFactor, shapearge,
objPoints = calcPoints(R1, R3, y, R2, R4, y2),
topLeft = objPoints.topLeft,
bottomLeft = objPoints.bottomLeft,
topRight = objPoints.topRight,
bottomRight = objPoints.bottomRight,
X1 = x + topLeft.x, X2 = x + topRight.x, X3 = x + bottomLeft.x, X4 = x + bottomRight.x,
y3 = topLeft.y, y4 = bottomLeft.y,
arc1 = getArcPath(x, y, X1, y3, X2, y3, R1, R3, 0, 0),
arc2 = getArcPath(x, y, X1, y3, X2, y3, R1, R3, 1, 1),
arc3 = getArcPath(x, y2, X4, y4, X3, y4, R2, R4, 1, 0),
arc4 = getArcPath(x, y2, X4, y4, X3, y4, R2, R4, 0, 1);
shapearge = {
front : [M, X1, y3].concat(arc1, [L, X4, y4], arc3, [Z]),
back : [M, X1, y3].concat(arc2, [L, X4, y4], arc4, [Z]),
silhuette : [M, X1, y3].concat(arc2, [L, X4, y4], arc3, [Z])
};
if (!isHollow) {
shapearge.top = [M, X1, y3].concat(arc1, [L, X2, y3],
getArcPath(x, y, X2, y3, X1, y3, R1, R3, 0, 1), [Z]);
}
return shapearge;
},
getPyramid3DShapeArgs = function(x, y, R1, R2, h, r3dFactor, is2D, renderer, isFunnel, isHollow,
use3DLighting) {
if (isObject(x)) {
y = x.y;
R1 = x.R1;
R2 = x.R2;
h = x.h;
r3dFactor = x.r3dFactor;
is2D = x.is2D;
use3DLighting = x.use3DLighting;
isHollow = x.isHollow;
isFunnel = x.isFunnel;
renderer = x.renderer;
x = x.x;
}
var X1 = x - R1, X2 = x + R1, X3 = x - R2, X4 = x + R2, y2 = y + h, shapeArgs,
R3,
R4,
lightLength,
lightLengthH,
lightLengthH1,
lightWidth;
if (is2D) {
shapeArgs = {
silhuette : [M, X1, y, L, X2, y, X4, y2, X3, y2, Z]
};
if(!isFunnel){
// Rounding the x value to remove the thin white gap between following two halfs due
// to sub-pixel rendering.
x = Math.round(x);
shapeArgs.lighterHalf = [M, X1, y, L, x, y, x, y2, X3, y2, Z];
shapeArgs.darkerHalf = [M, x, y, L, X2, y, X4, y2, x, y2, Z];
}
}
else if (isFunnel){
shapeArgs = getFunnel3DShapeArgs(x, y, R1 || minRadius, R2 ||
minRadius, h, r3dFactor, isHollow, renderer);
}
else {
R3 = R1 * r3dFactor;
R4 = R2 * r3dFactor;
lightLength = mathMin(5, R1);
lightLengthH = mathMin(2, 2 * R3);
lightLengthH1 = mathMin(2, lightLengthH);
lightWidth = lightLengthH1 / r3dFactor;
shapeArgs = {
top : [M, X1, y, L, x, y + R3, X2, y, x, y - R3,Z],
front : [M, X1, y, L, x, y + R3, X2, y, X4, y2, x, y2 + R4,
X3, y2, Z],
topLight : [M, X1, y + 0.5, L, x, y + R3 + 0.5, x, y + R3 - lightLengthH,
X1 + lightWidth, y, Z],// x, y + R3 - lightLengthH, Z],
topLight1 : [M, X2, y + 0.5, L, x, y + R3 + 0.5, x, y + R3 - lightLengthH1,
X2 - lightWidth, y, Z],// x, y + R3 - lightLengthH, Z],
silhuette : [M, X1, y, L, x, y - R3, X2, y, X4, y2, x, y2 + R4,
X3, y2, Z],
centerLight : [M, x, y + R3, L, x, y2 + R4, x - 5, y2 + R4,
x - lightLength, y + R3, Z],
centerLight1 : [M, x, y + R3, L, x, y2 + R4, x + 5, y2 + R4,
x + lightLength, y + R3, Z]
};
}
return shapeArgs;
},
attr = function (hash, val) {
var key,
value,
element = this,
color,
alpha,
colorObject,
shapeChanged = false,
colorChanged = false,
lightColor,
lightColor1,
darkColor,
attr3D = this._3dAttr,
shapeArgs,
colorDark,
colorLight,
zero100STR,
lightAlphaSTR,
lightShade,
slantAngle,
lightShadeStop;
// single key-value pair
if (isString(hash) && defined(val)) {
key = hash;
hash = {};
hash[key] = val;
}
// used as a getter: first argument is a string, second is undefined
if (isString(hash)) {
//if belongs from the list then handle here
if (attrList[hash]) {
element = this._3dAttr[hash];
}
else {//else leve for the original attr
element = this._attr(hash);
}
// setter
}
else {
for (key in hash) {
value = hash[key];
//if belongs from the list then handle here
if (attrList[key]) {
//store the att in attr3D for further use
attr3D[key] = value;
//if it is 'fill' or 'lighting3D' the redefine the colors for all the 3 elements
if (key === fillStr) {
if (value && value.linearGradient && value.stops && value.stops[0]) {
value = value.stops[0][1];
}
if (startsRGBA.test(value)) {
colorObject = new Color(value);
color = colorObject.get('hex');
alpha = colorObject.get('a') * 100;
}
else if (value && value.FCcolor) {
color = value.FCcolor.color.split(COMMASTRING)[0];
alpha = value.FCcolor.opacity.split(COMMASTRING)[0];
}
else if (HEXCODE.test(value)) {
color = value.replace(dropHash, HASHSTRING);
alpha = pluckNumber(attr3D.opacity, 100);
}
attr3D.color = color;
attr3D.opacity = alpha;
colorChanged = true;
}
else if (key === 'color' || key === 'opacity') {
attr3D.fill = toRaphaelColor(convertColor(attr3D.color,
pluckNumber(attr3D.opacity, 100)));
colorChanged = true;
}
else if (key === 'stroke' || key === 'strokeColor' || key === 'strokeAlpha') {
if (attr3D.is2D) {//stroke is only applicable on 2d shape
if (key === 'stroke') {
if (value && value.linearGradient && value.stops && value.stops[0]) {
value = value.stops[0][1];
}
if (startsRGBA.test(value)) {
colorObject = new Color(value);
color = colorObject.get('hex');
alpha = colorObject.get('a') * 100;
}
else if (value && value.FCcolor) {
color = value.FCcolor.color.split(COMMASTRING)[0];
alpha = value.FCcolor.opacity.split(COMMASTRING)[0];
}
else if (HEXCODE.test(value)) {
color = value.replace(dropHash, HASHSTRING);
alpha = pluckNumber(attr3D.opacity, 100);
}
attr3D.strokeColor = color;
attr3D.strokeAlpha = alpha;
}
else {
attr3D.stroke = convertColor(attr3D.strokeColor,
pluckNumber(attr3D.strokeAlpha, 100));
}
if (attr3D.isFunnel) {
this.funnel2D.attr('stroke', attr3D.stroke);
}
else {
this.borderElement.attr('stroke', attr3D.stroke);
}
}
}
else if (key === 'stroke-width'){
if (attr3D.is2D) {//stroke is only applicable on 2d shape
if (attr3D.isFunnel) {
this.funnel2D.attr(key, value);
}
else {
this.borderElement.attr(key, value);
}
}
}
else {
shapeChanged = true;
}
}
else {//else leave for the original attr
this._attr(key, value);
}
}
if (attr3D.is2D) {
if (shapeChanged) {
shapeArgs = getPyramid3DShapeArgs(attr3D.x, attr3D.y,
attr3D.R1, attr3D.R2, attr3D.h, attr3D.r3dFactor, attr3D.is2D);
element.shadowElement.attr({
path: shapeArgs.silhuette
});
if (attr3D.isFunnel) {
element.funnel2D.attr({
path: shapeArgs.silhuette
});
}
else {
element.lighterHalf.attr({
path: shapeArgs.lighterHalf
});
element.darkerHalf.attr({
path: shapeArgs.darkerHalf
});
element.borderElement.attr({
path: shapeArgs.silhuette
});
}
}
//if color change requared
if (colorChanged) {
if (attr3D.isFunnel) {
element.funnel2D.attr(fillStr, toRaphaelColor(convertColor(attr3D.color,
pluckNumber(attr3D.opacity, 100))));
}
else {
if (attr3D.use3DLighting === false) {
colorDark = colorLight = attr3D.color;
}
else {
colorDark = getDarkColor(attr3D.color, 80);
colorLight = getLightColor(attr3D.color, 80);
}
element.lighterHalf.attr(fillStr, toRaphaelColor(convertColor(colorLight,
pluckNumber(attr3D.opacity, 100))));
element.darkerHalf.attr(fillStr, toRaphaelColor(convertColor(colorDark,
pluckNumber(attr3D.opacity, 100))));
}
}
}
else {
//if shape changed requared
if (shapeChanged) {
shapeArgs = getPyramid3DShapeArgs(attr3D.x, attr3D.y, attr3D.R1, attr3D.R2,
attr3D.h, attr3D.r3dFactor, attr3D.is2D);
element.shadowElement.attr(pathStr, shapeArgs.silhuette);
if (attr3D.isFunnel) {
element.front.attr(pathStr, shapeArgs.front);
element.back.attr(pathStr, shapeArgs.back);
if (element.toptop && shapeArgs.top) {
element.toptop.attr(pathStr, shapeArgs.top);
}
}
else {
element.front.attr(pathStr, shapeArgs.front);
element.toptop.attr(pathStr, shapeArgs.top);
element.topLight.attr(pathStr, shapeArgs.topLight);
element.topLight1.attr(pathStr, shapeArgs.topLight1);
element.centerLight.attr(pathStr, shapeArgs.centerLight);
element.centerLight1.attr(pathStr, shapeArgs.centerLight1);
}
}
//if color change requared
if (colorChanged) {
color = attr3D.color;
alpha = attr3D.opacity;
if (attr3D.isFunnel) {
lightColor = getLightColor(color, 60);
darkColor = getDarkColor(color, 60);
element.back.attr(fillStr, toRaphaelColor({
FCcolor : {
color : darkColor + COMMASTRING + lightColor + COMMASTRING + color,
alpha : alpha + COMMASTRING + alpha + COMMASTRING + alpha,
ratio : '0,60,40',
angle : 0
}
}));
element.front.attr(fillStr, toRaphaelColor({
FCcolor : {
color : color + COMMASTRING + lightColor + COMMASTRING + darkColor,
alpha : alpha + COMMASTRING + alpha + COMMASTRING + alpha,
ratio : '0,40,60',
angle : 0
}
}));
if (element.toptop) {
element.toptop.attr(fillStr, toRaphaelColor({
FCcolor : {
color : lightColor + COMMASTRING + darkColor,
alpha : alpha + COMMASTRING + alpha,
ratio : zeroCommaHundredStr,
angle : -65
}
}));
}
}
else {
lightColor = getLightColor(color, 80);
lightColor1 = getLightColor(color, 70);
darkColor = getDarkColor(color, 80);
zero100STR = zeroCommaHundredStr;
lightAlphaSTR = '0,' + alpha;
lightShade = color + COMMASTRING + lightColor1;
slantAngle = -45;
lightShadeStop = (5 / (attr3D.R1 * attr3D.r3dFactor)) * 100;
//slantAngle = - math.atan(1 / attr3D.r3dFactor) / deg2rad
element.centerLight.attr(fillStr, toRaphaelColor({
FCcolor : {
color : lightShade,
alpha : lightAlphaSTR,
ratio : zero100STR,
angle : 0
}
}));
element.centerLight1.attr(fillStr, toRaphaelColor({
FCcolor : {
color : lightShade,
alpha : lightAlphaSTR,
ratio : zero100STR,
angle : 180
}
}));
element.topLight.attr(fillStr, toRaphaelColor({
FCcolor : {
color : lightColor1 + COMMASTRING + lightColor1 + COMMASTRING +
color + COMMASTRING + color,
alpha : alpha + COMMASTRING + alpha + COMMASTRING + 0 + COMMASTRING + 0,
ratio : '0,50,' + lightShadeStop + COMMASTRING + (50 - lightShadeStop),
angle : slantAngle
}
}));
element.topLight1.attr(fillStr, toRaphaelColor({
FCcolor : {
color : lightColor1 + COMMASTRING + color + COMMASTRING + darkColor,
alpha : alpha + COMMASTRING + alpha + COMMASTRING + alpha,
ratio : '0,50,50',
angle : 0
}
}));
element.front.attr(fillStr, toRaphaelColor({
FCcolor : {
color : color + COMMASTRING + color + COMMASTRING +
darkColor + COMMASTRING + darkColor,
alpha : alpha + COMMASTRING + alpha + COMMASTRING +
alpha + COMMASTRING + alpha,
ratio : '0,50,0,50',
angle : 0
}
}));
element.toptop.attr(fillStr, toRaphaelColor({
FCcolor : {
color : lightColor + COMMASTRING + color + COMMASTRING +
darkColor + COMMASTRING + darkColor,
alpha : alpha + COMMASTRING + alpha + COMMASTRING +
alpha + COMMASTRING + alpha,
ratio : '0,25,30,45',
angle : slantAngle
}
}));
}
}
}
}
return element;
},
shadow = function () {
var silhuette = this.shadowElement;
if (shadow) {
silhuette.shadow.apply(silhuette, arguments);
}
},
normalizeShapes = function (group, newAttrs) {
var shapes = ['silhuette', 'lighterHalf', 'darkerHalf', 'centerLight', 'centerLight1', 'front',
'toptop', 'topLight', 'topLight1', 'shadowElement', 'funnel2D', 'back'],
shapeGElem,
index,
shapeName,
oldAttrs,
length;
if (!group) { return; }
oldAttrs = group._3dAttr;
if ((oldAttrs.isFunnel === newAttrs.isFunnel) && (oldAttrs.is2D === newAttrs.is2D) &&
(oldAttrs.isHollow === newAttrs.isHollow)) {
return group;
}
for (index = 0, length = shapes.length; index < length; index++) {
shapeName = shapes[index];
shapeGElem = group[shapeName];
if (!shapeGElem) { continue; }
delete group[shapeName];
shapeGElem.remove();
}
return group;
},
animatePathIfPresent = function (datasetStore, renderer, parentElem) {
var chart = datasetStore.chart,
animationObj = chart.get(configStr, animationObjStr),
animDuration = animationObj.duration,
dummyAnimElem = animationObj.dummyObj,
dummyAnimObj = animationObj.animObj,
animType = animationObj.animType;
return function (elemType, pathArr, nonAnimAttr) {
var prevEle = parentElem[elemType];
if (prevEle) {
return prevEle.animateWith(dummyAnimElem, dummyAnimObj, {
path: pathArr
}, animDuration, animType, datasetStore.postPlotCallback);
}
nonAnimAttr = nonAnimAttr || EMPTY_OBJ;
datasetStore.postPlotCallback();
return renderer.path(pathArr, parentElem).attr(nonAnimAttr);
};
};
return function (x, y, R1, R2, h, r3dFactor, gStr, is2D, renderer, isFunnel, isHollow, use3DLighting) {
var datasetStore = this,
chart = datasetStore.chart,
graphicsGroup = chart.graphics.datasetGroup,
_3dAttr,
Shapeargs,
rect3D,
existingGElement,
animDuration,
animationType = 'easeIn',
animOrDraw;
if (isObject(x)) {
y = x.y;
R1 = x.R1;
R2 = x.R2;
h = x.h;
r3dFactor = x.r3dFactor;
gStr = x.gStr;
is2D = x.is2D;
use3DLighting = x.use3DLighting;
renderer = x.renderer;
isHollow = x.isHollow;
isFunnel = x.isFunnel;
existingGElement = x.graphics;
animDuration = x.animationDuration;
x = x.x;
}
r3dFactor = pluckNumber(r3dFactor, 0.15);
_3dAttr = {
x : x,
y : y,
R1 : R1,
R2 : R2,
h : h,
r3dFactor : r3dFactor,
is2D : is2D,
use3DLighting: use3DLighting,
isHollow : isHollow,
isFunnel : isFunnel,
renderer : renderer
};
Shapeargs = getPyramid3DShapeArgs(_3dAttr);
rect3D = normalizeShapes(existingGElement, _3dAttr) || renderer.group(gStr, graphicsGroup);
rect3D.toFront();
rect3D.Shapeargs = Shapeargs;
animOrDraw = animatePathIfPresent(datasetStore, renderer, rect3D, animationType);
rect3D.shadowElement = animOrDraw('shadowElement', Shapeargs.silhuette, {
fill : TRACKER_FILL,
stroke: noneStr
});
//modify the attr function of the group so that it can handle pyramid attrs
//store the old function
rect3D._attr = rect3D._attr || rect3D.attr;
rect3D.attr = attr;
// Replace the shadow function with a modified version.
rect3D.shadow = shadow;
//store the 3d attr(requared in new attr function to change any related
// attr modiffiaction)
rect3D._3dAttr = _3dAttr;
//add the new attr function
if (isFunnel) {
//if the drawing is a 2d drawing
if (is2D) {
rect3D.funnel2D = animOrDraw('funnel2D', Shapeargs.silhuette);
} else {
rect3D.back = animOrDraw('back', Shapeargs.back, {
'stroke-width' : 0,
stroke: noneStr
});
rect3D.front = animOrDraw('front', Shapeargs.front, {
'stroke-width' : 0,
stroke: noneStr
});
if (Shapeargs.top) {
rect3D.toptop = animOrDraw('toptop', Shapeargs.top, {
'stroke-width' : 0,
stroke: noneStr
});
}
}
}
else {
//if the drawing is a 2d drawing
if (is2D) {
rect3D.lighterHalf = animOrDraw('lighterHalf', Shapeargs.lighterHalf, {
'stroke-width' : 0
});
rect3D.darkerHalf = animOrDraw('darkerHalf', Shapeargs.darkerHalf, {
'stroke-width' : 0
});
rect3D.borderElement = animOrDraw('borderElement', Shapeargs.silhuette, {
fill : TRACKER_FILL,
stroke: noneStr
});
}
else {
//else it should be 3d
rect3D.front = animOrDraw('front', Shapeargs.front, {
'stroke-width' : 0
});
rect3D.centerLight = animOrDraw('centerLight', Shapeargs.centerLight, {
'stroke-width' : 0
});
rect3D.centerLight1 = animOrDraw('centerLight1', Shapeargs.centerLight1, {
'stroke-width' : 0
});
rect3D.toptop = animOrDraw('toptop', Shapeargs.top, {
'stroke-width' : 0
});
rect3D.topLight = animOrDraw('topLight', Shapeargs.topLight, {
'stroke-width' : 0
});
rect3D.topLight1 = animOrDraw('topLight1', Shapeargs.topLight1, {
'stroke-width' : 0
});
}
}
return rect3D;
};
}
)(),
utils : function (_context) {
/*
* Utility to create associative array with the facility to get non-undefined element in optimized way.
* O(1) length retrieval
*/
function ArrayableObj() {
var _map = [],
_eLength = 0; // Effective length. Only count of defined element
// Set a value in associative array
this.set = function(key, value) {
_eLength++;
_map[key] = value;
};
// Get an value based on the key
this.get = function(key) {
return _map[key];
};
// Get the complete array
this.getAll = function() {
return _map;
};
// Merge with a given array and return a new one. However instance remains immutable.
this.mergeWith = function(anotherArray) {
var sArr,
itemIndex,
item,
newArr = _map.slice(0);
if(anotherArray instanceof Array) {
sArr = anotherArray;
} else if(anotherArray instanceof ArrayableObj) {
sArr = anotherArray.getAll();
} else {
return;
}
for(itemIndex in sArr) {
item = sArr[itemIndex];
if(newArr[itemIndex]) {
continue;
}
newArr[itemIndex] = item;
}
return newArr;
};
this.getEffectiveLength = function(){
return _eLength;
};
}
ArrayableObj.prototype.constructor = ArrayableObj;
/*
* Matrix that calculates the distribution of the labels.
* If the distribution is not uniform it calculates a variable factor to make it uniform
* It calculates the following cases :-
* a) If the distribution is permitted for one given side, it suggestes chart.alignmentType['default']
* b) If the distribution exceeds to a given limit it suggestes chart.alignmentType.alternate
*
* If the original distribution (non uniform) is like
* ------------------------------------------------------
* 4 | 2 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
* ------------------------------------------------------
* After make it uniform it would look like
* ------------------------------------------------------
* 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 |
* ------------------------------------------------------
*
* If the original distribution array is not sufficient to hold all the elements one more array is
* introduced.
* @param length - {{int}} : Permitted limit of distribution
*/
function DistributionMatrix(length){
// Allowed length of distribution
this.distributionLength = length;
// Represents the recalculated distribution for default side
this.distributedMatrix = [];
// Represents the recalculated distribution for alternate side
this.altDistributedMatrix = [];
// Represents the normal distribution
this.nonDistributedMatrix = {};
// For focefully pushing elements which are need not be distributed, but required to be placed in
// the final distribution matrix
this.forcePushObj = {};
this.flags = {
exhaustion : false
};
}
DistributionMatrix.prototype.constructor = DistributionMatrix;
/*
* Puts items in the matrix to calculate dependency.
* @param item - {{object}} : Item to be distributed
* @param rangeBottom - {{int}} : distribution index
*/
DistributionMatrix.prototype.push = function(item, rangeBottom){
// Original distribution before recalculation
this.nonDistributedMatrix[rangeBottom] = this.nonDistributedMatrix[rangeBottom] || [];
this.nonDistributedMatrix[rangeBottom].push(item);
};
/*
* Forcefully pushes element in already distributed array. The system does not calculate the overall
* distribution after the data being pushed.
* @param item {{object}} - object to be forcefully distributed
* @param index {{int}} - corrosponds to the index of the main array where the element to be placed
*/
DistributionMatrix.prototype.forcePush = function(item, index){
this.forcePushObj[index] = item;
};
/*
* Controls and spread distribution of non-uniform matrix to uniform matrix.
* Gets called when result is prepared.
*/
DistributionMatrix.prototype.distribute = function(legendSkip){
var datasetStore = _context,
distributionItems,
alternateSwitch = true,
distributedMatrix = new ArrayableObj(),
alternateDistributedMatrix = new ArrayableObj(),
orphanMatrix = new ArrayableObj(),
altOrphanMatrix = new ArrayableObj(),
flags = this.flags,
currentMatrix, distributionIndexAlt,
distributionIndex, index, length, currentItem,
matricsExhaustionIndex = 0,
diff, willMatricsExhaust = false, absIndex = 0,
data = datasetStore.components.data;
// If there are too many labels even after placing them in alternate size, the system skips label.
// This behaviour is observable especially with low height. On top of that if legend is positioned
// at right side, system places labels only one side.
// This is applied because two side space management
// cannot be done in this scope.
if(legendSkip){
// If legend is in right side place all the labels in one side
if((diff = data.length - (this.distributionLength)) > 0){
willMatricsExhaust = true;
matricsExhaustionIndex = diff;
for(distributionIndexAlt in this.nonDistributedMatrix){
distributionItems = this.nonDistributedMatrix[distributionIndexAlt];
for(index = 1 ; index < distributionItems.length; index++){
// Keep only the first element in the block as
// distribution will not be calculated since
// labels are skipped.
currentItem = distributionItems[index];
currentItem.dontPlot = true;
currentItem.displayValue = BLANK;
}
}
}
}else{
// If legend is not in right side but possibility of canvas overflow
if((diff = data.length - (2 * this.distributionLength)) > 0){
willMatricsExhaust = true;
matricsExhaustionIndex = diff;
for(distributionIndexAlt in this.nonDistributedMatrix){
distributionItems = this.nonDistributedMatrix[distributionIndexAlt];
for(index = 1 ; index < distributionItems.length - 1; index++){
currentItem = distributionItems[index];
currentItem.dontPlot = true;
currentItem.displayValue = BLANK;
}
}
}
}
/*
* If number of data to be distributed is greater than allowed length (in one side),
* alternate distribution happens.
* There are few concept here how the skipping is dealt with.
* The pyramid plot can have labels or can not. If the plot doesn't associate with a label we call
* it a orphan. While calculating the distribution orphans are not considered as their labels won't
* occupy any space. Hence these are kept in a separate matrix;
* Separately the orphans and non-orphans
* create one associative array. But when they are merged they create a complete array.
*/
if(data.length > this.distributionLength && !legendSkip){
// If data exhausts two matrics, skip labels
flags.exhaustion = true;
for(distributionIndexAlt in this.nonDistributedMatrix){
distributionItems = this.nonDistributedMatrix[distributionIndexAlt];
// Alternatively place every item in two different arrays
for(index = 0, length = distributionItems.length ; index < length ; index++){
currentItem = distributionItems[index];
if(!currentItem.dontPlot){
alternateSwitch ? (currentMatrix = distributedMatrix) :
(currentMatrix = alternateDistributedMatrix);
if(currentMatrix.getEffectiveLength() > parseInt(distributionIndexAlt, 10)){
currentItem.distributionFactor =
(currentMatrix.getEffectiveLength() - 1) - distributionIndexAlt;
}else{
//currentItem.distributionFactor = 0;
currentItem.distributionFactor = 0;
}
}else{
alternateSwitch ? (currentMatrix = orphanMatrix) :
(currentMatrix = altOrphanMatrix);
}
currentMatrix.set(absIndex++, currentItem);
alternateSwitch = !alternateSwitch;
}
}
// Forms the complete array in both of the side
this.distributedMatrix = distributedMatrix.mergeWith(orphanMatrix);
this.altDistributedMatrix = alternateDistributedMatrix.mergeWith(altOrphanMatrix);
}else{
// Distribution happens in one side. Hence data can be accommodated in one side
for(distributionIndex in this.nonDistributedMatrix){
distributionItems = this.nonDistributedMatrix[distributionIndex];
for(index = 0, length = distributionItems.length ; index < length ; index++){
currentItem = distributionItems[index];
// Calculating distribution offset
if(!currentItem.dontPlot){
currentMatrix = distributedMatrix;
if(currentMatrix.getEffectiveLength() > parseInt(distributionIndex, 10)){
currentItem.distributionFactor =
(currentMatrix.getEffectiveLength() - 1) - distributionIndex;
}else{
currentItem.distributionFactor = 0;
}
}else{
currentMatrix = orphanMatrix;
}
currentMatrix.set(absIndex++, currentItem);
}
}
this.distributedMatrix = distributedMatrix.mergeWith(orphanMatrix);
}
};
/*
* Gets the distributed result.
* @return {{object}} - {
* suggestion :
* matrix
* }
* Suggestion - suggests what kind of allignment to be taken
* Matrix - Uniform distribution matrix
*/
DistributionMatrix.prototype.getDistributedResult =function() {
var datasetStore = _context,
chart = datasetStore.chart,
chartConfig = chart.config,
legend = chart.components.legend,
conf = datasetStore.conf,
alignmentType = conf.alignmentType,
suggestion,
matrix = [],
isLegendRight = chart.isLegendRight,
allowedRightX = chartConfig.width - conf.blankSpace;
if(legend.config.width){
isLegendRight && (allowedRightX -= legend.config.width + chartConfig.marginRight);
}else{
isLegendRight = 0;
}
chart.isLegendRight = isLegendRight;
this.distribute(isLegendRight);
// When legend is in right side the plot will be in one side with skipped labels.
if(isLegendRight){
suggestion = alignmentType['default'];
matrix.push(this.distributedMatrix);
}else{
suggestion = this.flags.exhaustion ?
alignmentType.alternate : alignmentType['default'];
this.flags.exhaustion ? [].push.call(matrix, this.distributedMatrix,
this.altDistributedMatrix) : matrix.push(this.distributedMatrix);
}
return {
'forceMatrix' : this.forcePushObj,
'suggestion' : suggestion,
'matrix' : matrix
};
};
return {
DistributionMatrix: DistributionMatrix,
setContext : function(context){
_context = context;
},
invokeHookFns : function() {
var fn, params = [], ctx = _context;
switch (arguments.length) {
case 3:
ctx = arguments[2];
/* falls through */
case 2:
params = arguments[1];
/* falls through */
case 1:
fn = arguments[0];
break;
default:
return;
}
fn && typeof fn === 'function' && fn.apply(ctx, params);
},
copyProperties : function (fromObject, toObject, mappingArray) {
var index, length, confArr, fromName, toName, convertFunction, defaultValue, additionalFn,
DEFAULT_FN = function () { };
function getDefaultValue (key) {
var nKey;
if (typeof key === 'string' && key.indexOf('$') === 0) {
nKey = key.substring(1);
return toObject[nKey];
}
if (typeof key === 'function') {
return key.call(_context, toObject);
}
return key;
}
for (index = 0, length = mappingArray.length; index < length; index++) {
confArr = mappingArray[index];
fromName = confArr[0];
toName = confArr[1];
convertFunction = confArr[2];
defaultValue = getDefaultValue(confArr[3]);
additionalFn = confArr[4] || DEFAULT_FN;
toObject[toName] = convertFunction(fromObject[fromName], defaultValue);
additionalFn(toObject);
}
},
sortObjArrByKey : function(objArr, valueKey){
return objArr.sort(function(obj1, obj2){
return Math.abs(obj2[valueKey]) - Math.abs(obj1[valueKey]);
});
},
getSumValueOfObjArrByKey : function (objArr, valueKey) {
var index, length, total = 0;
for (index = 0, length = objArr.length; index < length; index++) {
total += parseFloat(objArr[index][valueKey], 10);
}
return total;
}
};
},
slice: function (evt, x, y, sliced) {
var context = this,
dataItem = context.plotItem,
datasetStore = context.datasetStore,
chart = datasetStore.chart,
animationObj = chart.get(configStr, animationObjStr),
animDuration = animationObj.duration,
dummyAnimElem = animationObj.dummyObj,
dummyAnimObj = animationObj.animObj,
animType = animationObj.animType,
conf = datasetStore.conf,
slicingDistance = conf.slicingDistance,
seriesOptionsHalf = slicingDistance / 2,
i = 0,
noOFPrevPoint = 0,
data = datasetStore.graphics.plotItems,
length = data.length,
transformObj,
dataObj,
reflowData,
itemClicked,
clickedItemId,
reflowUpdate,
dyPrev,
dyNext,
dyOld,
dyNew,
slicingEnd;
if (conf.sliceLock) {
return;
}
// Flag that informs whether slicing is on-going
conf.sliceLock = 1;
if (dataItem) {
plotEventHandler.call(dataItem.trackerObj, chart, evt, 'dataplotclick');
}
// save state
reflowUpdate = {
hcJSON: {
chart: {
issliced: false
},
series: []
}
};
reflowUpdate.hcJSON.series[0] = {
data: reflowData = []
};
sliced = dataItem.sliced = defined(sliced) ? sliced : !dataItem.sliced;
dyPrev = -seriesOptionsHalf;
dyNext = seriesOptionsHalf;
slicingEnd = function () {
return function() {
conf.sliceLock = 0;
/**
* SlicingEnd event is usually associated with a pie chart.
* In pie charts, on click a certain entity of the pie, the clicked slice is shown distinctly.
* The slicing start event is triggered as soon as the particular entity
* is clicked when the slicing is finished,
* the slicingEnd event is triggered.
* @event FusionCharts#slicingEnd
* @param {boolean} slicedState Indicates whether the data is sliced or not.
* @param {string} data The plot data from the chart to slice.
*/
global.raiseEvent('SlicingEnd', {
slicedState: sliced,
data: datasetStore.getPlotData(clickedItemId)
}, chart.chartInstance);
};
};
for (i = 0; i < length; i += 1) {
dataObj = data[i];
if (dataObj !== dataItem) {
dataObj.sliced = false;
reflowData[i] = {isSliced: false};
itemClicked = false;
}
else {
reflowData[i] = {isSliced: sliced};
itemClicked = true;
clickedItemId = i;
}
if (dataObj.graphic) {
dyOld = dataObj.dy;
dyNew = -dyOld;
if (sliced) {
if (dataObj.x < dataItem.x) {
dyNew += dyPrev;
noOFPrevPoint += 1;
}
else if (dataObj.x == dataItem.x) {
if (!noOFPrevPoint) {
dyNew += -seriesOptionsHalf * 0.5;
}
else if (i == length - 1) {
dyNew += seriesOptionsHalf * 0.5;
}
}
else {
dyNew += dyNext;
}
}
// The plot should be sent to ending y position, before invoking
// next slicing movement, as in the case of rapid slicing interactions.
dataObj.graphic.attr({
transform: 't0,' + dataObj.dy
});
dataObj.dy += dyNew;
transformObj = {transform: '...t0,' + dyNew};
//dataItem.distanceAvailed = dyNew;
/**
* SlicingStart event is usually associated with a pie chart.
* In pie charts, on click a certain entity of the pie, the clicked slice is shown distinctly.
* The slicing start event is triggered as soon as the particular entity is clicked.
* @event FusionCharts#slicingStart
* @param {boolean} slicedState Indicates whether the data is sliced or not.
* @param {string} data The plot data from the chart to slice.
*/
itemClicked && global.raiseEvent('SlicingStart', {
slicedState: !sliced,
data: datasetStore.getPlotData(clickedItemId)
}, chart.chartInstance);
dataObj.graphic.animateWith(dummyAnimElem, dummyAnimObj, transformObj, animDuration, animType,
itemClicked && slicingEnd(sliced, clickedItemId));
//for labels at center translate the labels
if (dataObj.dataLabel) {
dataObj.dataLabel.animateWith(dummyAnimElem, dummyAnimObj, transformObj, animDuration,
animType);
}
if (dataObj.connector) {
dataObj.connector.animateWith(dummyAnimElem, dummyAnimObj, transformObj, animDuration,
animType);
}
//for tracker translate it
if (dataObj.trackerObj) {
dataObj.trackerObj.animateWith(dummyAnimElem, dummyAnimObj, transformObj, animDuration,
animType);
}
// For Funnel streamlinedData, the top label should move with top funnel,
// characterised by no graphic but with label for the plot. Topmost funnel
// is not the topmost plot here.
if (i == 1 && !data[0].graphic && data[0].dataLabel) {
data[0].dataLabel.animateWith(dummyAnimElem, dummyAnimObj, transformObj, animDuration,
animType);
}
}
}
},
legendClick: function (plotItem) {
this.slice.call(plotItem);
},
getEventArgs: function (legendItem) {
var dataset = this,
dataStore = dataset.components.data,
configuration = legendItem.configuration,
index = configuration.index,
dataObj = dataStore[index] || {},
eventArgs;
eventArgs = {
alpha: dataObj.alpha,
value: dataObj.y,
color: dataObj.color,
borderColor: dataObj.borderColor,
borderWidth: dataObj.borderWidth,
link: dataObj.link,
displayValue: dataObj.displayValue,
datasetIndex: dataObj.datasetIndex,
toolText: dataObj.toolText,
label: dataObj.categoryLabel
};
return eventArgs;
}
}]);
}
]);
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-funnel',
function () {
var global = this,
lib = global.hcLib,
pluckNumber = lib.pluckNumber,
BLANK = lib.BLANKSTRING,
setLineHeight = lib.setLineHeight,
plotEventHandler = lib.plotEventHandler,
ROLLOVER = 'DataPlotRollOver',
ROLLOUT = 'DataPlotRollOut',
schedular = lib.schedular,
preDefStr = lib.preDefStr,
configStr = preDefStr.configStr,
animationObjStr = preDefStr.animationObjStr,
POSITION_START = preDefStr.POSITION_START,
POSITION_END = preDefStr.POSITION_END,
POSITION_MIDDLE = preDefStr.POSITION_MIDDLE,
textHAlign = {
right: POSITION_END,
left: POSITION_START,
middle: POSITION_MIDDLE,
start: POSITION_START,
end: POSITION_END,
center: POSITION_MIDDLE,
'undefined': BLANK,
BLANK: BLANK
},
POINTER = 'pointer',
COMPONENT = 'component',
DATASET = 'dataset';
FusionCharts.register(COMPONENT, [DATASET, 'Funnel', {
type : 'funnel',
LABEL_PLACEMENT_ITERATOR_INDEX_START: 1,
configure : function () {
var datasetDefStore = this,
chart = datasetDefStore.chart,
numberFormatter = chart.components.numberFormatter,
utils = datasetDefStore.utils(datasetDefStore),
sortObjArrByKey = utils.sortObjArrByKey,
chartAttr = chart.jsonData ? chart.jsonData.chart : {},
data = datasetDefStore.JSONData.data,
streamLinedData,
index,
dsItem,
length;
if (!datasetDefStore._checkValidData(data)) { return; }
for (index = 0, length = data.length; index < length; index++) {
dsItem = data[index];
if (dsItem && dsItem.value !== undefined) {
dsItem.value = numberFormatter.getCleanValue(dsItem.value, true);
}
}
streamLinedData = +(chartAttr.streamlineddata === undefined ? 1 : chartAttr.streamlineddata);
datasetDefStore.JSONData.data = !streamLinedData ? data : sortObjArrByKey(data, 'value');
!!streamLinedData && (data[0].pseudoPoint = true);
datasetDefStore.addLegend();
},
configureSpecifics : function () {
var datasetStore = this,
chart = datasetStore.chart,
datasetConf = datasetStore.conf,
chartAttr = chart.jsonData ? chart.jsonData.chart : {},
utils = datasetStore.utils(datasetStore),
copyProperties = utils.copyProperties;
// Properties specific to the funnel only
copyProperties(chartAttr, datasetConf, [
['streamlineddata', 'streamLinedData', pluckNumber, 1],
['funnelyscale', 'yScale', pluckNumber, undefined, function (datasetConf) {
var ys = datasetConf.yScale;
datasetConf.yScale = (ys >= 0 && ys <= 40) ? ys / 200 : 0.2;
}],
['usesameslantangle', 'useSameSlantAngle', pluckNumber, function (datasetConf) {
return datasetConf.streamLinedData ? 0 : 1;
}],
['ishollow', 'isHollow', pluckNumber, undefined, function (datasetConf) {
var isHollow = datasetConf.isHollow;
if (isHollow === undefined) {
datasetConf.isHollow = datasetConf.streamLinedData ? 1 : 0;
}
}]
]);
chart.config.PLOT_COLOR_INDEX_START = datasetConf.streamLinedData ? -1 : 0;
},
preDrawingHook : function() {
// @todo change the architecture
var datasetStore = this,
dataStoreComponent = datasetStore.components,
data = dataStoreComponent.data,
conf = datasetStore.conf;
if (!conf.streamLinedData ) {
data.splice(0,0, {
displayValue: BLANK,
y: conf.sumValue
});
}
},
prePointProcessingHookFn : function (pointsArr) {
var datasetStore = this,
chart = datasetStore.chart,
chartConf = chart.config,
conf = datasetStore.conf,
chartWorkingWidth = chartConf.canvasWidth,
smartLabel = chart.linkedItems.smartLabel,
nonStreamLinedData = !conf.streamLinedData,
point, lineHeight, smartTextObj, origHeight;
point = pointsArr[0];
// Wrapping the first label to the whole drawing width
point && (point.pseudoPoint = true);
if (point && point.displayValue) {
smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
smartLabel.setStyle(point.style);
setLineHeight(point.style);
lineHeight = parseFloat(point.style.lineHeight.match(/^\d+/)[0] || conf.lineHeight, 10);
origHeight = smartLabel.getOriSize(point.displayValue).height;
smartTextObj = smartLabel.getSmartText(point.displayValue, chartWorkingWidth, origHeight);
point.displayValue = smartTextObj.text;
smartTextObj.tooltext && (point.originalText = smartTextObj.tooltext);
point.labelWidth = smartLabel.getOriSize(smartTextObj.text).width;
// Reducing the chart height to place the top most label
chartConf.marginTop += lineHeight + 4;
}
conf.totalValue = nonStreamLinedData ? (pointsArr[0].y - pointsArr[1].y) : 0;
conf.offsetVal = function (i) {
return nonStreamLinedData ? -(pointsArr[i + 1] && pointsArr[i + 1].y || 0) : point.y;
};
},
getPointInContext : function () {
var context = this;
function P (options) {
this.displayValue = options.displayValue;
this.displayValueArgs = options.displayValueArgs,
this.style = options.style;
this.appliedStyle = options.appliedStyle;
this.categoryLabel = options.categoryLabel;
this.toolText = options.toolText;
this.legendCosmetics = options.legendCosmetics;
this.showInLegend = options.showInLegend;
this.y = options.y;
this.shadow = options.shadow;
this.smartTextObj = options.smartTextObj;
this.color = options.color;
this.legendItemId = options.legendItemId;
this.name = options.name;
this.alpha = options.alpha;
this.rawColor = options.rawColor;
this.rawAlpha = options.rawAlpha;
this.legendColor = options.legendColor;
this.borderColor = options.borderColor;
this.borderWidth = options.borderWidth;
this.link = options.link;
this.isSliced = options.isSliced;
this.doNotSlice = options.doNotSlice;
this.hoverEffects = options.hoverEffects;
this.rolloverProperties = options.rolloverProperties;
}
P.upperRadiusFactor = 1;
P.prototype.getModifiedCurrentValue = function () {
return undefined;
};
P.prototype.getRatioK = function (currentValue, valueRadiusIncrementRatio, totalValue, maxValue) {
var conf = context.conf,
nonStreamlinedData = !conf.streamLinedData,
useSameSlantAngle = conf.useSameSlantAngle;
return nonStreamlinedData ? 0.2 + (valueRadiusIncrementRatio * totalValue) :
(this.y ? (useSameSlantAngle ? this.y / maxValue : Math.sqrt(this.y / maxValue)) : 1);
};
P.prototype.getLowestRadiusFactor = function (maxValue) {
var conf = context.conf,
nonStreamlinedData = !conf.streamLinedData,
useSameSlantAngle = conf.useSameSlantAngle;
return nonStreamlinedData ? 0.2 :
(this.y ? (useSameSlantAngle ? this.y / maxValue : Math.sqrt(this.y / maxValue)) : 1);
};
return P;
},
datasetCalculations : function (dataArr) {
var datasetStore = this,
chart = datasetStore.chart,
conf = datasetStore.conf,
chartComponents = chart.components,
numberFormatter = chartComponents.numberFormatter,
index, length, dataObj, itemValue, res = {},
isStreamLinedData = conf.streamLinedData,
percentOfPrevious = conf.percentOfPrevious;
res.highestValue = Number.NEGATIVE_INFINITY;
res.refreshedData = [];
res.sumValue = res.countPoint = 0;
for (index = 0, length = dataArr.length; index < length; index++) {
dataObj = dataArr[index];
if (dataObj.vline) {
// Funnel or pyramid does not use vline. Ignoring the same if user put it mistakenly.
continue;
}
dataObj.cleanValue = itemValue = Math.abs(numberFormatter.getCleanValue(dataObj.value, true));
if (itemValue !== null) {
// If a valid value is provided in the configuration
res.hasValidPoint = true;
res.highestValue = res.highestValue || itemValue;
res.refreshedData.push(dataObj);
res.sumValue += itemValue;
res.countPoint += 1;
res.highestValue = Math.max(res.highestValue, itemValue);
}
}
if (isStreamLinedData) {
res.sumValue = res.highestValue;
percentOfPrevious && (res.prevPerValReq = true);
}
return res;
},
draw : function () {
this._configure();
var datasetStore = this,
chart = datasetStore.chart,
graphics = chart.graphics,
jobList = chart.getJobList(),
chartConfig = chart.config,
conf = datasetStore.conf,
utils = datasetStore.utils(datasetStore),
trackerArgs = datasetStore.trackerArgs = [],
getSumValueOfObjArrByKey = utils.getSumValueOfObjArrByKey,
DistributionMatrix = utils.DistributionMatrix,
calculatePositionCoordinate = datasetStore.calculatePositionCoordinate,
psmMargin = {
top : chartConfig.marginTop,
bottom: chartConfig.marginBottom
},
dataStore = datasetStore.components.data,
index, length, plotObj, unitHeight,
dlGroup = graphics.datalabelsGroup,
streamLinedData = conf.streamLinedData,
heightAllotted, widthAllotted, drawingRadius, x,
section = 2,
dataStoreLength = dataStore.length,
maxDataValue = conf.maxValue = dataStore[0].y,
minDataValue = conf.minValue = dataStore[dataStoreLength - 1].y,
uhMockNonStreamLine, mvMockNonStreamLine, lastRadius, alignmentType, uh,
distributionKey, currentSliceHeight = 0, blockLabelLenFromOffset,
blockLenFromOffset = 0,
lineHeight = conf.lineHeight,
mFloorFn = Math.floor, mMinFn = Math.min, distributedResult,
dMatrix, adMatrix, curr, ele, forceKeys, fKey,
slicingDistance, noOfGap, halfDistance,
singletonCase, distributionMatrix,
plotItemArr = datasetStore.graphics.plotItems,
plotItems = [],
postPlotCallbackInitiated;
datasetStore.labelDrawingConfig = datasetStore.labelDrawingConfig || [];
datasetStore.labelDrawingConfig.length = 0;
if (!conf.sumValue) { return; }
// Plot area management to decide the drawing area measurement
datasetStore.preDrawingSpaceManagement();
datasetStore.hide(datasetStore.graphics.plotItems);
datasetStore.rolloverResponseSetter = function (elem, elemHoverAttr) {
return function (data) {
var ele = this;
elem.graphic.attr(elemHoverAttr);
plotEventHandler.call(ele, chart, data, ROLLOVER);
};
};
datasetStore.rolloutResponseSetter = function (elem, elemUnHoverAttr) {
return function (data) {
var ele = this;
elem.graphic.attr(elemUnHoverAttr);
plotEventHandler.call(ele, chart, data, ROLLOUT);
};
};
datasetStore.legendClickHandler = function (plotItem) {
return function () {
datasetStore.legendClick(plotItem, true, false);
};
};
datasetStore.animateFunction = function(group){
return function() {
chart._animCallBack();
group.attr({
opacity: 1
});
};
};
datasetStore.postPlotCallback = function () { };
chartConfig.canvasTop += chartConfig.marginTop - psmMargin.top;
chartConfig.effCanvasHeight =
heightAllotted = chartConfig.canvasHeight - (chartConfig.marginTop + chartConfig.marginBottom) +
(psmMargin.top + psmMargin.bottom);
chartConfig.effCanvasWidth =
widthAllotted = chartConfig.width - (chartConfig.marginLeft + chartConfig.marginRight);
drawingRadius = conf.drawingRadius = widthAllotted / section;
x = conf.x = drawingRadius + chartConfig.canvasLeft;
slicingDistance = conf.slicingDistance;
halfDistance = slicingDistance / 2;
if (streamLinedData && dataStoreLength < 2) {
return;
}
if (!streamLinedData) {
uh = unitHeight = maxDataValue ? heightAllotted / maxDataValue : heightAllotted;
} else {
unitHeight = heightAllotted / (maxDataValue - minDataValue);
mvMockNonStreamLine = getSumValueOfObjArrByKey(dataStore, 'value');
uh = uhMockNonStreamLine = mvMockNonStreamLine ? heightAllotted / mvMockNonStreamLine :
heightAllotted;
}
conf.unitHeight = unitHeight;
conf.lastRadius = lastRadius = drawingRadius;
// For funnel no x shift calculation required since the shape of the funnel causes the labels to be
// placed in non overlapping fashion
conf.globalMinXShift = 0;
// Defines how to align the labels of the chart.
alignmentType = conf.alignmentType = {};
// Default alignment is labels placing in the right side of the pyramid, and chart is left aligned
alignmentType['default'] = 1;
alignmentType.alternate = 2;
// Length of distribution matrix is how many labels ca be placed at one
// side of the pyramid without overlapping
distributionMatrix = new DistributionMatrix(mFloorFn(heightAllotted / lineHeight));
for(index = 0, length = dataStoreLength; index < length; index++){
plotObj = dataStore[index];
if((!streamLinedData && index === 0) || (!streamLinedData && index === length - 1)){
// For non streamedlineData the first element contains the total hence continue
distributionMatrix.forcePush(plotObj, index);
continue;
}
currentSliceHeight = plotObj.y * uh;
// Effective length of the current slice from the top of pyramid drawing
blockLenFromOffset += (plotObj.y * uh);
blockLabelLenFromOffset = blockLenFromOffset - currentSliceHeight + (currentSliceHeight / 2);
distributionKey = mFloorFn(blockLabelLenFromOffset / lineHeight);
distributionMatrix.push(plotObj, distributionKey);
}
distributedResult = distributionMatrix.getDistributedResult();
// Alternatively merge the data after distribution
dataStore.length = 0;
if((distributedResult.matrix)[1] === undefined){
[].push.apply(dataStore, (distributedResult.matrix)[0]);
}else{
dMatrix = (distributedResult.matrix)[0];
adMatrix = (distributedResult.matrix)[1];
length = Math.max(dMatrix.length, adMatrix.length);
for(index = 0; index < length; index++){
ele = dMatrix[index];
curr = adMatrix[index];
dataStore.push(ele ? ele : curr);
}
}
// Placing the elements to be forced in distribution matrix
forceKeys = Object.keys(distributedResult.forceMatrix);
if(forceKeys.length > 0){
for(fKey in distributedResult.forceMatrix){
[].splice.apply(dataStore, [parseInt(fKey, 10), 0].concat(distributedResult.forceMatrix[fKey]));
}
}
switch(distributedResult.suggestion){
case alignmentType['default']:
calculatePositionCoordinate.call(datasetStore, dataStore, false);
break;
case alignmentType.alternate:
conf.labelAlignment = alignmentType.alternate;
// 1st section for left labels, 2nd sector for chart itself, 3rd section for right label
section = 3;
drawingRadius = widthAllotted / section;
chartConfig.canvasLeft = (chartConfig.canvasWidth / 2) - (drawingRadius);
x = conf.x = chartConfig.canvasLeft + drawingRadius;
lastRadius = drawingRadius;
calculatePositionCoordinate.call(datasetStore, dataStore, true);
break;
}
if(noOfGap = conf.noOfGap) {
conf.perGapDistance = mMinFn(halfDistance * 1.5, slicingDistance / noOfGap);
conf.distanceAvailed = halfDistance;
}
dlGroup.trackTooltip(true);
singletonCase = (streamLinedData && dataStore.length == 2 || dataStore.length == 1);
index = dataStore.length;
if (!plotItemArr) {
datasetStore.graphics.plotItems = [];
}
// dlGroup.attr({
// opacity: 0
// });
if (conf.alreadyPlotted) {
datasetStore.postPlotCallback = function () {
if (postPlotCallbackInitiated){
return;
}
postPlotCallbackInitiated = true;
datasetStore.animateFunction(dlGroup)();
};
}
while (index--) {
plotItems.push(datasetStore.drawIndividualPlot(dataStore[index], index));
}
!conf.alreadyPlotted && datasetStore.animateElements(plotItems, 'graphic', [], {
pre: {opacity: 0},
post: {opacity: 100}
}, datasetStore.animateFunction(dlGroup));
conf.connectorEndSwitchHistoryY = {};
index = dataStore.length;
while (index--) {
trackerArgs.push(dataStore[index]);
}
jobList.labelDrawID.push(schedular.addJob(datasetStore.drawAllLabels, datasetStore, [],
lib.priorityList.label));
jobList.trackerDrawID.push(schedular.addJob(datasetStore.drawAllTrackers, datasetStore, [],
lib.priorityList.tracker));
conf.alreadyPlotted = true;
},
drawIndividualPlot : function (point, index) {
var datasetStore = this,
conf = datasetStore.conf,
plotItems = datasetStore.graphics.plotItems,
value = point.y,
displayValue = point.displayValue,
chartSliced = conf.isSliced,
labelAlign = point.labelAline,
css = point.appliedStyle,
parentCSS = point.style,
textDirection = BLANK,
data = datasetStore.components.data,
chart = datasetStore.chart,
chartGraphics = chart.graphics,
trackerGroup = chartGraphics.trackerGroup,
sliced, plotItem, translateXY,
paper = chart.components.paper,
setLink = !!point.link,
distanceAvailed = conf.distanceAvailed,
legend = chart.components.legend,
animationDuration = chart.get(configStr, animationObjStr).duration,
labelDrawingConfigArr = datasetStore.labelDrawingConfig,
setRolloutAttr,
setRolloverAttr,
setRolloverProperties,
sliceContext,
pointFill,
labelDrawingConfig,
textDrawingArgs;
// If all plots are sliced, then set flag to false, to make the first
// slicing click on any of the plots will make it sliced.
sliced = chartSliced ? 1 : point.isSliced;
pointFill = (css && css.color) || (parentCSS && parentCSS.color) || datasetStore._chartLevelAttr.color;
textDrawingArgs = {
text: displayValue,
ishot: true,
direction: textDirection,
cursor: setLink ? POINTER : BLANK,
x: 0,
y: 0,
fill: pointFill,
'text-anchor': textHAlign[labelAlign]
};
if (value === null || value === undefined || !point.shapeArgs) {
labelDrawingConfigArr[index] = (labelDrawingConfig = {
args: textDrawingArgs,
css: css,
point: point
});
return;
}
if (!(plotItem = plotItems[index])) {
point.shapeArgs.graphics = plotItem;
point.shapeArgs.animationDuration = animationDuration;
point.plot = plotItem = plotItems[index] = {
graphic: datasetStore.pyramidFunnelShape(point.shapeArgs).attr({
fill: point.color,
'stroke-width': point.borderWidth,
stroke: point.borderColor
}),
trackerObj: paper.path(trackerGroup)
};
labelDrawingConfigArr[index] = (labelDrawingConfig = {
args: textDrawingArgs,
css: css,
point: point
});
} else {
point.plot = plotItem;
point.shapeArgs.graphics = plotItem.graphic;
point.shapeArgs.animationDuration = animationDuration;
plotItem.graphic = datasetStore.pyramidFunnelShape(point.shapeArgs).attr({
fill: point.color,
'stroke-width': point.borderWidth,
stroke: point.borderColor
});
plotItem.graphic.show();
labelDrawingConfigArr[index] = (labelDrawingConfig = {
args: textDrawingArgs,
css: css,
point: point
});
}
if (conf.showTooltip) {
plotItem.trackerObj.tooltip(point.toolText);
} else {
plotItem.trackerObj.tooltip(false);
}
plotItem.value = value;
plotItem.displayValue = displayValue;
plotItem.sliced = !!sliced;
plotItem.cursor = setLink ? POINTER : BLANK;
plotItem.x = point.x;
plotItem.index = index;
legend.configureItems(data[index].legendItemId, {
legendClickFN: datasetStore.legendClickHandler({
datasetStore: datasetStore,
plotItem: plotItem
})
});
// Hover consmetics
setRolloutAttr = setRolloverAttr = {};
if (point.hoverEffects) {
setRolloutAttr = {
color: point.rawColor,
opacity: point.rawAlpha,
'stroke-width': point.borderWidth,
stroke: point.borderColor
};
setRolloverProperties = point.rolloverProperties;
setRolloverAttr = {
color: setRolloverProperties.color,
opacity: setRolloverProperties.alpha,
'stroke-width': setRolloverProperties.borderWidth,
stroke: setRolloverProperties.borderColor
};
}
sliceContext = {
datasetStore: datasetStore,
plotItem: plotItem
};
plotItem.trackerObj.unclick(datasetStore.slice);
!point.doNotSlice && plotItem.trackerObj.click(datasetStore.slice, sliceContext);
plotItem.trackerObj.mouseup(datasetStore.plotMouseUp, plotItem);
plotItem.trackerObj.hover(datasetStore.rolloverResponseSetter(plotItem, setRolloverAttr),
datasetStore.rolloutResponseSetter(plotItem, setRolloutAttr));
labelDrawingConfig.context = sliceContext;
labelDrawingConfig.actions = {
click: datasetStore.slice,
hover: [datasetStore.rolloverResponseSetter(plotItem, setRolloverAttr),
datasetStore.rolloutResponseSetter(plotItem, setRolloutAttr)]
};
plotItem.dy = 0;
if (conf.noOfGap) {
if (distanceAvailed) {
plotItem._startTranslateY = translateXY = 't0,' + distanceAvailed;
plotItem.dy = plotItem.distanceAvailed = distanceAvailed;
plotItem.graphic.attr({
transform: translateXY
});
labelDrawingConfig.transform = translateXY;
}
if (conf.slicingGapPosition[point.x]) {
conf.distanceAvailed -= conf.perGapDistance;
}
}
plotItem && (plotItem.point = point);
return plotItem;
},
getTooltipMacroStub : function (options) {
var datasetStore = this,
chart = datasetStore.chart,
conf = datasetStore.conf,
chartComponents = chart.components,
numberFormatter = chartComponents.numberFormatter,
base = datasetStore.__base__,
baseStub, percentOfPrevValue;
if (conf.streamLinedData){
percentOfPrevValue = conf.percentOfPrevious ? options.pValue :
numberFormatter.percentValue(options.dataValue / options.prevValue * 100);
}
baseStub = base.getTooltipMacroStub(options);
baseStub.percentValue = conf.percentOfPrevious ?
numberFormatter.percentValue(options.dataValue / options.highestValue * 100) : options.pValue,
baseStub.percentOfPrevValue = percentOfPrevValue;
return baseStub;
}
}, 'FunnelPyramidBase']);
}]);
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-pyramid',
function () {
var global = this,
lib = global.hcLib,
//strings
BLANK = lib.BLANKSTRING,
pluckNumber = lib.pluckNumber,
preDefStr = lib.preDefStr,
configStr = preDefStr.configStr,
animationObjStr = preDefStr.animationObjStr,
POSITION_START = preDefStr.POSITION_START,
POSITION_END = preDefStr.POSITION_END,
POSITION_MIDDLE = preDefStr.POSITION_MIDDLE,
win = global.window,
userAgent = win.navigator.userAgent,
isIE = /msie/i.test(userAgent) && !win.opera,
TRACKER_ALPHA = isIE ? 0.002 : 0.000001,
POINTER = 'pointer',
COMPONENT = 'component',
DATASET = 'dataset',
plotEventHandler = lib.plotEventHandler,
ROLLOVER = 'DataPlotRollOver',
ROLLOUT = 'DataPlotRollOut',
schedular = lib.schedular,
textHAlign = {
right: POSITION_END,
left: POSITION_START,
middle: POSITION_MIDDLE,
start: POSITION_START,
end: POSITION_END,
center: POSITION_MIDDLE,
'undefined': BLANK,
BLANK: BLANK
};
FusionCharts.register(COMPONENT, [DATASET, 'Pyramid', {
type : 'pyramid',
LABEL_PLACEMENT_ITERATOR_INDEX_START: 0,
configure : function () {
var datasetDefStore = this;
if (!datasetDefStore._checkValidData(datasetDefStore.JSONData.data)) { return; }
datasetDefStore.addLegend();
},
configureSpecifics : function () {
var datasetStore = this,
chart = datasetStore.chart,
datasetConf = datasetStore.conf,
chartAttr = chart.jsonData ? chart.jsonData.chart : {},
utils = datasetStore.utils(datasetStore),
copyProperties = utils.copyProperties;
copyProperties(chartAttr, datasetConf, [
['pyramidyscale', 'yScale', pluckNumber, undefined, function (datasetConf) {
var ys = datasetConf.yScale;
datasetConf.yScale = (ys >= 0 && ys <= 40) ? ys / 200 : 0.2;
}],
['use3dlighting', 'use3DLighting', pluckNumber, 1]
]);
chart.config.PLOT_COLOR_INDEX_START = 0;
},
preDrawingHook : function() { },
draw : function () {
this._configure();
var datasetStore = this,
chart = datasetStore.chart,
jobList = chart.getJobList(),
chartConfig = chart.config,
conf = datasetStore.conf,
utils = datasetStore.utils(datasetStore),
DistributionMatrix = utils.DistributionMatrix,
trackerArgs = datasetStore.trackerArgs = [],
calculatePositionCoordinate = datasetStore.calculatePositionCoordinate,
psmMargin = {
top : chartConfig.marginTop,
bottom: chartConfig.marginBottom
},
dataStore = datasetStore.components.data,
index, length, plotObj, unitHeight,
graphics = chart.graphics,
dlGroup = graphics.datalabelsGroup,
streamLinedData = conf.streamLinedData,
heightAllotted, widthAllotted, drawingRadius, x,
section = 2,
dataStoreLength = dataStore.length,
lastRadius, alignmentType,
distributionKey, currentSliceHeight = 0, blockLabelLenFromOffset,
blockLenFromOffset = 0,
lineHeight = conf.lineHeight,
mFloorFn = Math.floor, mMinFn = Math.min, distributedResult,
dMatrix, adMatrix, curr, ele,
slicingDistance, noOfGap, halfDistance,
singletonCase, distributionMatrix, inclination,
plotItemArr = datasetStore.graphics.plotItems,
plotItems = [],
postPlotCallbackInitiated;
if (!conf.sumValue) { return; }
datasetStore.labelDrawingConfig = datasetStore.labelDrawingConfig || [];
datasetStore.labelDrawingConfig.length = 0;
// Plot area management to decide the drawing area measurement
datasetStore.preDrawingSpaceManagement();
datasetStore.hide(datasetStore.graphics.plotItems);
datasetStore.rolloverResponseSetter = function (elem, elemHoverAttr) {
return function (data) {
var ele = this;
elem.graphic.attr(elemHoverAttr);
plotEventHandler.call(ele, chart, data, ROLLOVER);
};
};
datasetStore.rolloutResponseSetter = function (elem, elemUnHoverAttr) {
return function (data) {
var ele = this;
elem.graphic.attr(elemUnHoverAttr);
plotEventHandler.call(ele, chart, data, ROLLOUT);
};
};
datasetStore.legendClickHandler = function (plotItem) {
return function () {
datasetStore.legendClick(plotItem, true, false);
};
};
datasetStore.animateFunction = function(group){
return function() {
chart._animCallBack();
group.attr({
opacity: 1
});
};
};
datasetStore.postPlotCallback = function () { };
chartConfig.canvasTop += chartConfig.marginTop - psmMargin.top;
chartConfig.effCanvasHeight =
heightAllotted = chartConfig.canvasHeight - (chartConfig.marginTop + chartConfig.marginBottom) +
(psmMargin.top + psmMargin.bottom);
chartConfig.effCanvasWidth = widthAllotted = chartConfig.width - (chartConfig.marginLeft +
chartConfig.marginRight);
drawingRadius = conf.drawingRadius = widthAllotted / section;
x = conf.x = drawingRadius + chartConfig.canvasLeft;
slicingDistance = conf.slicingDistance;
halfDistance = slicingDistance / 2;
inclination = Math.atan((widthAllotted / 2) / heightAllotted);
conf.unitHeight = unitHeight = heightAllotted / conf.sumValue;
conf.lastRadius = lastRadius = 0;
// For funnel no x shift calculation required since the shape of the funnel causes the labels to be
// placed in non overlapping fashion
conf.globalMinXShift = Math.floor((lineHeight) / Math.cos(inclination));
// Defines how to align the labels of the chart.
alignmentType = conf.alignmentType = {};
// Default alignment is labels placing in the right side of the pyramid, and chart is left aligned
alignmentType['default'] = 1;
alignmentType.alternate = 2;
// Length of distribution matrix is how many labels ca be placed at one
// side of the pyramid without overlapping
distributionMatrix = new DistributionMatrix(mFloorFn(heightAllotted / lineHeight));
for(index = 0, length = dataStoreLength; index < length; index++){
plotObj = dataStore[index];
currentSliceHeight = plotObj.y * unitHeight;
// Effective length of the current slice from the top of pyramid drawing
blockLenFromOffset += (plotObj.y * unitHeight);
blockLabelLenFromOffset = blockLenFromOffset - currentSliceHeight + (currentSliceHeight / 2);
distributionKey = mFloorFn(blockLabelLenFromOffset / lineHeight);
distributionMatrix.push(plotObj, distributionKey);
}
distributedResult = distributionMatrix.getDistributedResult();
// Alternatively merge the data after distribution
dataStore.length = 0;
if((distributedResult.matrix)[1] === undefined){
[].push.apply(dataStore, (distributedResult.matrix)[0]);
}else{
dMatrix = (distributedResult.matrix)[0];
adMatrix = (distributedResult.matrix)[1];
length = Math.max(dMatrix.length, adMatrix.length);
for(index = 0; index < length; index++){
ele = dMatrix[index];
curr = adMatrix[index];
dataStore.push(ele ? ele : curr);
}
}
switch(distributedResult.suggestion){
case alignmentType['default']:
calculatePositionCoordinate.call(datasetStore, dataStore, false);
break;
case alignmentType.alternate:
conf.labelAlignment = alignmentType.alternate;
// 1st section for left labels, 2nd sector for chart itself, 3rd section for right label
section = 3;
conf.drawingRadius = drawingRadius = widthAllotted / section;
chartConfig.canvasLeft = (chartConfig.canvasWidth / 2) - (drawingRadius);
x = conf.x = chartConfig.canvasLeft + drawingRadius;
lastRadius = drawingRadius;
calculatePositionCoordinate.call(datasetStore, dataStore, true);
break;
}
if(noOfGap = conf.noOfGap) {
conf.perGapDistance = mMinFn(halfDistance * 1.5, slicingDistance / noOfGap);
conf.distanceAvailed = halfDistance;
}
dlGroup.trackTooltip(true);
singletonCase = (streamLinedData && dataStore.length == 2 || dataStore.length == 1);
index = dataStore.length;
if (!plotItemArr) {
plotItemArr = datasetStore.graphics.plotItems = [];
}
// dlGroup.attr({
// opacity: 0
// });
if (conf.alreadyPlotted) {
datasetStore.postPlotCallback = function () {
if (postPlotCallbackInitiated){
return;
}
postPlotCallbackInitiated = true;
datasetStore.animateFunction(dlGroup)();
};
}
while (index--) {
plotItems.push(datasetStore.drawIndividualPlot(dataStore[index], index));
}
!conf.alreadyPlotted && datasetStore.animateElements(plotItems, 'graphic', [], {
pre: { opacity: TRACKER_ALPHA },
post: { opacity: 100 }
}, datasetStore.animateFunction(dlGroup));
plotItemArr.splice(dataStoreLength, plotItemArr.length - dataStoreLength);
conf.connectorEndSwitchHistoryY = {};
index = dataStore.length;
while (index--) {
trackerArgs.push(dataStore[index]);
}
jobList.labelDrawID.push(schedular.addJob(datasetStore.drawAllLabels, datasetStore, [],
lib.priorityList.label));
jobList.trackerDrawID.push(schedular.addJob(datasetStore.drawAllTrackers, datasetStore, [],
lib.priorityList.tracker));
conf.alreadyPlotted = true;
},
calculatePositionCoordinate : function (dataArr, placeOtherSide) {
var datasetStore = this,
conf = datasetStore.conf,
is2d = conf.is2d,
x = conf.x,
plotItemArr = datasetStore.graphics.plotItems || [],
chart = datasetStore.chart,
chartConfig = chart.config,
y = chartConfig.canvasTop,
unitHeight = conf.unitHeight,
labelDistance = conf.labelDistance,
showLabelsAtCenter = conf.showLabelsAtCenter,
fontSize = chartConfig.style.fontSize,
yShift = fontSize * 0.3,
yScale = conf.yScale,
blankSpace = conf.blankSpace,
lastRadius = conf.lastRadius,
smartLabel = chart.linkedItems.smartLabel,
index, length,
point, sliceHeight,
lastIndex = dataArr.length - 1,
alignmentSwitchToggle = false,
distributionOffset = 0,
labelMeasurement, newRadius,
negativeSpanningDataEnd,
normalizedLabel,
lineHeight = conf.lineHeight,
totalValues = 0,
// Base of the maximum trimmed label.
trimmedInfo = {
flag: false,
point: undefined,
sLabel: undefined,
setAll: function(flag, point, sLabel){
this.flag = flag;
this.point = point;
this.sLabel = sLabel;
}
},
// Base of the maximum spanned labels
largestLabel = {
point: undefined,
sLabel: undefined,
set: function(calcFn, predicate){
var _calcFn = calcFn,
_predicate = predicate;
return function(point, sLabel){
var existingLabelSpan,
currentLabelSpan;
if(point.dontPlot){
return;
}
if(!(this.point && this.sLabel)){
this.point = point;
this.sLabel = sLabel;
return;
}
existingLabelSpan = _calcFn(this.point, this.sLabel);
currentLabelSpan = _calcFn(point, sLabel);
if(_predicate(existingLabelSpan, currentLabelSpan)){
this.point = point;
this.sLabel = sLabel;
return;
}
};
}
},
leftTrimmedInfo = {},
rightTrimmedInfo = {},
lLargestLabel = {},
rLargestLabel = {},
xPos,
chartWidth = chart.config.width - 2,
slicingGapPosition = conf.slicingGapPosition = {};
global.extend(leftTrimmedInfo, trimmedInfo);
global.extend(rightTrimmedInfo, trimmedInfo);
leftTrimmedInfo.setAll = function(flag, point, sLabel){
var _point = this.point,
_sLabel = this.sLabel,
existingLabelSpan,
currentLabelSpan;
this.flag = flag;
if(!(_point && _sLabel)){
this.point = point;
this.sLabel = sLabel;
return;
}
existingLabelSpan = _point.labelX - (_sLabel.oriTextWidth - _sLabel.width);
currentLabelSpan = point.labelX - (sLabel.oriTextWidth - sLabel.width);
if(existingLabelSpan > currentLabelSpan){
this.point = point;
this.sLabel = sLabel;
}
};
// Override the base class method for labels which are kept right
rightTrimmedInfo.setAll = function(flag, point, sLabel){
var _point = this.point,
_sLabel = this.sLabel,
existingLabelSpan,
currentLabelSpan;
this.flag = flag;
if(!(_point && _sLabel)){
this.point = point;
this.sLabel = sLabel;
return;
}
existingLabelSpan = _point.labelX + _sLabel.oriTextWidth;
currentLabelSpan = point.labelX + sLabel.oriTextWidth;
if(existingLabelSpan < currentLabelSpan){
this.point = point;
this.sLabel = sLabel;
}
};
global.extend(lLargestLabel, largestLabel);
global.extend(rLargestLabel, largestLabel);
lLargestLabel.set = (function(){
return largestLabel.set.apply(lLargestLabel, [function(point){
return point.labelX;
}, function(existingLabelSpan, currentLabelSpan){
return existingLabelSpan > currentLabelSpan ? true : false;
}]);
})();
rLargestLabel.set = (function(){
return largestLabel.set.apply(rLargestLabel, [function(point, sLabel){
return point.labelX + sLabel.oriTextWidth;
}, function(existingLabelSpan, currentLabelSpan){
return existingLabelSpan < currentLabelSpan ? true : false;
}]);
})();
conf.noOfGap = 0;
smartLabel.useEllipsesOnOverflow(chartConfig.useEllipsesWhenOverflow);
for(index = 0, length = dataArr.length; index < length ; index++){
point = dataArr[index];
if(!point){
continue;
}
point.x = index;
if (plotItemArr[index]) {
point.isSliced = plotItemArr[index].sliced || !!point.isSliced || !!conf.isSliced;
}
placeOtherSide && (alignmentSwitchToggle = !alignmentSwitchToggle);
if (point.isSliced) {
xPos = point.x;
if (xPos && !slicingGapPosition[xPos]) {
slicingGapPosition[xPos] = true;
conf.noOfGap += 1;
}
if (xPos < lastIndex) {
slicingGapPosition[xPos + 1] = true;
conf.noOfGap += 1;
}
}
smartLabel.setStyle(point.style);
point.oriText = point.displayValue;
labelMeasurement = labelMeasurement = smartLabel
.getSmartText(point.displayValue, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
totalValues += point.y;
newRadius = conf.drawingRadius * totalValues / conf.sumValue;
sliceHeight = unitHeight * point.y;
point.shapeArgs =
{
x: x,
y: y,
R1: lastRadius,
R2: newRadius,
h: sliceHeight,
r3dFactor: yScale,
gStr: 'point',
is2D: is2d,
use3DLighting: !!conf.use3DLighting,
renderer: chart.components.paper
};
if (showLabelsAtCenter) {
point.labelAline = POSITION_MIDDLE;
point.labelX = x;
point.labelY = (is2d ? y : y + (yScale * lastRadius)) + (sliceHeight / 2) + yShift;
}
else {
point.labelAline = POSITION_START;
point.alignmentSwitch = alignmentSwitchToggle;
point.distributionFactor = point.distributionFactor || 0;
if(alignmentSwitchToggle){
point.labelX = x - (labelDistance + (newRadius + lastRadius) / 2 +
blankSpace + labelMeasurement.width);
point.labelX -= point.distributionFactor * conf.globalMinXShift;
lLargestLabel.set(point, labelMeasurement);
}else{
point.labelX = x + labelDistance + (newRadius + lastRadius) / 2 + blankSpace;
point.labelX += point.distributionFactor * conf.globalMinXShift;
rLargestLabel.set(point, labelMeasurement);
}
distributionOffset = point.distributionFactor * lineHeight;
point.labelY = y + yShift + (sliceHeight / 2) + distributionOffset;
}
// Checking text overflow for alternate alignment
if(placeOtherSide){
if(alignmentSwitchToggle && (point.labelX < 0)){
// Left and behind the margin
negativeSpanningDataEnd = point.labelX + labelMeasurement.width;
normalizedLabel = smartLabel.getSmartText(point.displayValue, negativeSpanningDataEnd,
Number.POSITIVE_INFINITY, true);
point.labelX = 2;
point.isLabelTruncated = true;
point.displayValue = normalizedLabel.text;
point.virtualWidth = normalizedLabel.maxWidth;
leftTrimmedInfo.setAll(true, point, normalizedLabel);
} else if (!alignmentSwitchToggle && (point.labelX + labelMeasurement.width > chartWidth)){
// Right side and spanning the margin
normalizedLabel = smartLabel.getSmartText(point.displayValue, chartWidth -
point.labelX, Number.POSITIVE_INFINITY, true);
point.isLabelTruncated = true;
point.displayValue = normalizedLabel.text;
point.virtualWidth = normalizedLabel.maxWidth;
rightTrimmedInfo.setAll(true, point, normalizedLabel);
}
point.pWidth = point.virtualWidth || labelMeasurement.width;
distributionOffset = point.distributionFactor * lineHeight;
point.labelY = y + yShift + (sliceHeight / 2) + distributionOffset;
}
y += sliceHeight;
point.plotX = x;
point.plotY = y - sliceHeight / 2;
lastRadius = newRadius;
point.virtualWidth = point.virtualWidth || labelMeasurement.width;
}
// Recalculate the space one more time. Ideally this should be given by space manager.
// However in the current scope space manager cannot be called from here.
datasetStore.findBestPosition.call(datasetStore, dataArr, {
'lTrimmedInfo': leftTrimmedInfo,
'rTrimmedInfo': rightTrimmedInfo,
'lLargestLabel': lLargestLabel,
'rLargestLabel': rLargestLabel
});
},
getPointInContext : function () {
var context = this;
function P (options) {
this.displayValue = options.displayValue;
this.displayValueArgs = options.displayValueArgs,
this.style = options.style;
this.appliedStyle = options.appliedStyle;
this.categoryLabel = options.categoryLabel;
this.toolText = options.toolText;
this.legendCosmetics = options.legendCosmetics;
this.showInLegend = options.showInLegend;
this.y = options.y;
this.legendColor = options.legendColor;
this.shadow = options.shadow;
this.smartTextObj = options.smartTextObj;
this.color = options.color;
this.alpha = options.alpha;
this.name = options.name;
this.legendItemId = options.legendItemId;
this.rawColor = options.rawColor;
this.rawAlpha = options.rawAlpha;
this.borderColor = options.borderColor;
this.borderWidth = options.borderWidth;
this.link = options.link;
this.isSliced = options.isSliced;
this.doNotSlice = options.doNotSlice;
this.hoverEffects = options.hoverEffects;
this.rolloverProperties = options.rolloverProperties;
}
P.upperRadiusFactor = 0;
P.prototype.getModifiedCurrentValue = function (totalValue) {
return totalValue + (this.y / 2);
};
P.prototype.getRatioK = function (currentValue) {
var conf = context.conf;
return currentValue ? currentValue / conf.sumValue : 1;
};
P.prototype.getLowestRadiusFactor = function () {
return 1;
};
return P;
},
drawIndividualPlot : function (point, index) {
var datasetStore = this,
conf = datasetStore.conf,
plotItems = datasetStore.graphics.plotItems,
value = point.y,
displayValue = point.displayValue,
chartSliced = conf.isSliced,
textDirection = BLANK,
chart = datasetStore.chart,
data = datasetStore.components.data,
chartGraphics = chart.graphics,
trackerGroup = chartGraphics.trackerGroup,
sliced, plotItem, translateXY,
paper = chart.components.paper,
setLink = !!point.link,
distanceAvailed = conf.distanceAvailed,
setRolloutAttr,
labelAlign = point.labelAline,
css = point.appliedStyle,
parentCSS = point.style,
setRolloverAttr,
setRolloverProperties,
sliceContext,
legend = chart.components.legend,
textDrawingArgs,
animationDuration = chart.get(configStr, animationObjStr).duration,
labelDrawingConfigArr = datasetStore.labelDrawingConfig,
pointFill,
labelDrawingConfig;
pointFill = (css && css.color) || (parentCSS && parentCSS.color) || datasetStore._chartLevelAttr.color;
sliced = chartSliced ? 1 : point.isSliced;
textDrawingArgs = {
text: displayValue,
ishot: true,
direction: textDirection,
cursor: setLink ? POINTER : BLANK,
x: 0,
y: 0,
fill: pointFill,
'text-anchor': textHAlign[labelAlign]
};
if (value === null || value === undefined || !point.shapeArgs) {
labelDrawingConfigArr[index] = (labelDrawingConfig = {
args: textDrawingArgs,
css: css,
point: point
});
return;
}
if (!(plotItem = plotItems[index])) {
point.shapeArgs.graphics = plotItem;
point.shapeArgs.animationDuration = animationDuration;
point.plot = plotItem = plotItems[index] = {
graphic: datasetStore.pyramidFunnelShape(point.shapeArgs).attr({
fill: point.color,
'stroke-width': point.borderWidth,
stroke: point.borderColor
}),
trackerObj: paper.path(trackerGroup)
};
labelDrawingConfigArr[index] = (labelDrawingConfig = {
args: textDrawingArgs,
css: css,
point: point
});
} else {
point.plot = plotItem;
point.shapeArgs.graphics = plotItem.graphic;
point.shapeArgs.animationDuration = animationDuration;
plotItem.graphic = datasetStore.pyramidFunnelShape(point.shapeArgs).attr({
fill: point.color,
'stroke-width': point.borderWidth,
stroke: point.borderColor
});
plotItem.graphic.show();
labelDrawingConfigArr[index] = (labelDrawingConfig = {
args: textDrawingArgs,
css: css,
point: point
});
}
if (conf.showTooltip) {
plotItem.trackerObj.tooltip(point.toolText);
} else {
plotItem.trackerObj.tooltip(false);
}
plotItem.value = value;
plotItem.displayValue = displayValue;
plotItem.sliced = !!sliced;
plotItem.cursor = setLink ? POINTER : BLANK;
plotItem.x = point.x;
plotItem.index = index;
legend.configureItems(data[index].legendItemId, {
legendClickFN: datasetStore.legendClickHandler({
datasetStore: datasetStore,
plotItem: plotItem
})
});
// Hover consmetics
setRolloutAttr = setRolloverAttr = {};
if (point.hoverEffects) {
setRolloutAttr = {
color: point.rawColor,
opacity: point.rawAlpha,
'stroke-width': point.borderWidth,
stroke: point.borderColor
};
setRolloverProperties = point.rolloverProperties;
setRolloverAttr = {
color: setRolloverProperties.color,
opacity: setRolloverProperties.alpha,
'stroke-width': setRolloverProperties.borderWidth,
stroke: setRolloverProperties.borderColor
};
}
sliceContext = {
datasetStore: datasetStore,
plotItem: plotItem
};
plotItem.trackerObj.unclick(datasetStore.slice);
!point.doNotSlice && plotItem.trackerObj.click(datasetStore.slice, sliceContext);
plotItem.trackerObj.mouseup(datasetStore.plotMouseUp, plotItem);
plotItem.trackerObj.hover(datasetStore.rolloverResponseSetter(plotItem, setRolloverAttr),
datasetStore.rolloutResponseSetter(plotItem, setRolloutAttr));
labelDrawingConfig.context = sliceContext;
labelDrawingConfig.actions = {
click: datasetStore.slice,
hover: [datasetStore.rolloverResponseSetter(plotItem, setRolloverAttr),
datasetStore.rolloutResponseSetter(plotItem, setRolloutAttr)]
};
plotItem.dy = 0;
if (conf.noOfGap) {
if (distanceAvailed) {
plotItem._startTranslateY = translateXY = 't0,' + distanceAvailed;
plotItem.dy = plotItem.distanceAvailed = distanceAvailed;
plotItem.graphic.attr({
transform: translateXY
});
labelDrawingConfig.transform = translateXY;
}
if (conf.slicingGapPosition[point.x]) {
conf.distanceAvailed -= conf.perGapDistance;
}
}
plotItem.point = point;
return plotItem;
},
getTooltipMacroStub : function (options) {
var datasetStore = this,
chart = datasetStore.chart,
conf = datasetStore.conf,
chartComponents = chart.components,
numberFormatter = chartComponents.numberFormatter,
base = datasetStore.__base__,
baseStub, percentOfPrevValue;
percentOfPrevValue = conf.percentOfPrevious ? options.pValue :
numberFormatter.percentValue(options.dataValue / options.prevValue * 100);
baseStub = base.getTooltipMacroStub(options);
baseStub.percentValue = conf.percentOfPrevious ?
numberFormatter.percentValue(options.dataValue / options.highestValue * 100) : options.pValue,
baseStub.percentOfPrevValue = percentOfPrevValue;
return baseStub;
}
}, 'FunnelPyramidBase']);
}
]);
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-hlineargauge',
function () {
var global = this,
lib = global.hcLib,
pluckNumber = lib.pluckNumber,
pluck = lib.pluck,
COMMASTRING = lib.COMMASTRING,
extend2 = lib.extend2,
BLANK = lib.BLANKSTRING,
BLANKSTRING = BLANK,
AXISPOSITION_TOP = 1,
AXISPOSITION_BOTTOM = 3,
getValidValue = lib.getValidValue,
parseUnsafeString = lib.parseUnsafeString,
parseTooltext = lib.parseTooltext,
convertColor = lib.graphics.convertColor,
FILLMIXDARK10 = '{dark-10}',
POSITION_CENTER = lib.POSITION_MIDDLE,
preDefStr = lib.preDefStr,
configStr = preDefStr.configStr,
animationObjStr = preDefStr.animationObjStr,
POSITION_TOP = preDefStr.POSITION_TOP,
POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
POSITION_MIDDLE = preDefStr.POSITION_MIDDLE,
POSITION_RIGHT = lib.POSITION_RIGHT,
POSITION_LEFT = lib.POSITION_LEFT,
POSITION_START = preDefStr.POSITION_START,
POSITION_END = preDefStr.POSITION_END,
plotEventHandler = lib.plotEventHandler,
ROLLOVER = 'DataPlotRollOver',
ROLLOUT = 'DataPlotRollOut',
win = global.window,
doc = win.document,
hasTouch = doc.documentElement.ontouchstart !== undefined,
math = Math,
mathMax = math.max,
mathMin = math.min,
POINTER = 'pointer',
COMPONENT = 'component',
DATASET = 'dataset',
EVENTARGS = 'eventArgs',
ANIM_EFFECT = 'easeIn',
textHAlign = {
right: POSITION_END,
left: POSITION_START,
middle: POSITION_MIDDLE,
start: POSITION_START,
end: POSITION_END,
center: POSITION_MIDDLE,
'undefined': BLANK,
BLANK: BLANK
},
/**^ To get first touch ^*/
getTouchEvent = function (event) {
return (hasTouch && event.sourceEvent && event.sourceEvent.touches &&
event.sourceEvent.touches[0]) || event;
};
FusionCharts.register(COMPONENT, [DATASET, 'hlineargauge',{
pIndex : 2,
customConfigFn : '_createDatasets',
init : function (pointerArr) {
var dataSet = this;
dataSet.pointerArr = pointerArr;
dataSet.idMap = { };
dataSet.configure();
},
configure : function () {
var dataSet = this,
chart = dataSet.chart,
jsonData = chart.jsonData,
chartAttrs = jsonData.chart,
chartComponents = chart.components,
numberFormatter = chartComponents.numberFormatter,
colorM = chartComponents.colorManager,
datasetConfig = dataSet.config || (dataSet.config = {}),
components = dataSet.components || (dataSet.components = {}),
pointerArr = jsonData.pointers && jsonData.pointers.pointer,
len = (pointerArr && pointerArr.length) || 1,
dataObj,
data,
config,
itemValue,
i,
setToolText,
formatedVal,
tooltipSepChar,
setDisplayValue,
sides,
dataStore,
pointOrientation = {
top: 1,
right: 0,
left: 2,
bottom: 3
},
gaugeType = 1,
orient,
pointerOnOpp,
borderColor,
borderAlpha,
bgAlpha,
valueAbovePointer,
bgColor,
baseStyle = chart.config.style,
radius,
pointerBorderColor,
pointerBorderHoverAlpha,
pointerBgHoverAlpha,
pointerBgHoverColor,
pointerBorderHoverColor,
pointerBorderHoverThickness,
pointerHoverRadius,
borderWidth,
showHoverEffect,
hoverAttr,
showBorderOnHover,
showHoverAnimation,
hasHoberFillMix,
outAttr,
hasBorderHoverMix,
hoverAnimAttr,
outAnimAttr,
showBorder,
fillColor,
ticksBelowGauge,
axisPosition,
pointerSides,
chartShowHoverEffect,
pointerBorderThickness,
showValue,
label;
datasetConfig.valuePadding = pluckNumber(chartAttrs.valuepadding, 2);
datasetConfig.tooltipSepChar = tooltipSepChar = pluck(chartAttrs.tooltipsepchar, COMMASTRING);
ticksBelowGauge = pluckNumber(chartAttrs.ticksbelowgauge, chartAttrs.ticksbelowgraph, 1);
datasetConfig.axisPosition = axisPosition = ticksBelowGauge ? AXISPOSITION_BOTTOM : AXISPOSITION_TOP;
datasetConfig.pointerOnOpp = pointerOnOpp = Number(!pluckNumber(chartAttrs.pointerontop,
ticksBelowGauge, 1));
datasetConfig.valueabovepointer = valueAbovePointer = pluckNumber(chartAttrs.valueabovepointer,
!pointerOnOpp, 1);
datasetConfig.valueInsideGauge = valueAbovePointer === pointerOnOpp ? 1 : 0;
datasetConfig.showPointerShadow = pluckNumber(chartAttrs.showpointershadow, chartAttrs.showshadow, 1);
datasetConfig.showTooltip = pluckNumber(chartAttrs.showtooltip, 1);
datasetConfig.textDirection = chartAttrs.hasrtltext === '1' ? 'rtl' : BLANK;
datasetConfig.showGaugeLabels = pluckNumber(chartAttrs.showgaugelabels, 1);
datasetConfig.colorRangeStyle = {
fontFamily: baseStyle.inCanfontFamily,
fontSize: baseStyle.inCanfontSize,
lineHeight : baseStyle.inCanLineHeight,
color: baseStyle.inCancolor.replace(/^#?/, '#')
};
datasetConfig.showValue = pluckNumber(chartAttrs.showvalue, 1);
datasetConfig.editMode = pluckNumber(chartAttrs.editmode, 0);
datasetConfig.pointerSides = pointerSides = pluckNumber(chartAttrs.pointersides, 3);
datasetConfig.pointerBorderThickness = pointerBorderThickness =
pluckNumber(chartAttrs.pointerborderthickness);
datasetConfig.showHoverEffect = chartShowHoverEffect = pluckNumber(chartAttrs.showhovereffect,
chartAttrs.plothovereffect);
datasetConfig.upperLimit = pluckNumber(chartAttrs.upperlimit);
datasetConfig.lowerLimit = pluckNumber(chartAttrs.lowerlimit);
if (gaugeType === 1 ) { // horizontal gauge; left to right;
orient = (pointerOnOpp) ? POSITION_TOP : POSITION_BOTTOM;
} else if (gaugeType === 2) { // vertical gauge; top to bottom;
orient = pointerOnOpp ? 'left' : 'right';
} else if (gaugeType === 3) { // horizontal linear gauge; right to left;
orient = (pointerOnOpp) ? POSITION_TOP : POSITION_BOTTOM;
} else { // vertical linear gauge; bottom to top;
orient = pointerOnOpp ? 'left' : 'right';
}
datasetConfig.startAngle = pointOrientation[orient] * 90;
dataStore = components.data || (components.data = []);
for (i=0; i<len; i++) {
data = dataStore[i] || (components.data[i] = {});
config = data.config || (data.config = {});
dataObj = (pointerArr && pointerArr[i]) || {};
config.itemValue = itemValue = numberFormatter.getCleanValue(dataObj.value);
config.formatedVal = formatedVal = numberFormatter.dataLabels(itemValue);
config.setDisplayValue = setDisplayValue = getValidValue(parseUnsafeString(dataObj.displayvalue));
config.setToolText = setToolText = getValidValue(parseUnsafeString(dataObj.tooltext));
config.id = pluck(dataObj.id, 'pointer_' + i);
config.showHoverEffect = showHoverEffect =
pluckNumber(dataObj.showhovereffect, chartShowHoverEffect);
config.showBorder = showBorder = pluckNumber(dataObj.showborder, chartAttrs.showplotborder, 1);
config.borderWidth = borderWidth = showBorder ? pluckNumber(dataObj.borderthickness,
pointerBorderThickness) : 0;
config.showValue = showValue =pluckNumber(dataObj.showvalue, datasetConfig.showValue);
//create the displayvalue
if (!showValue) {
config.displayValue = BLANKSTRING;
}
else if (setDisplayValue !== undefined) {
config.displayValue = setDisplayValue;
config.isLabelString = true;
}
else {//determine the dispalay value then
config.displayValue = getValidValue(formatedVal, BLANK);
}
config.sides = sides = pluckNumber(dataObj.sides, pointerSides);
if (sides < 3) {
config.sides = 3;
}
config.radius = radius = pluckNumber(dataObj.radius,chartAttrs.pointerradius, 10);
//create the tooltext
if (setToolText !== undefined) {
config.toolText = parseTooltext(setToolText, [1,2], {
formattedValue: formatedVal
}, dataObj, chartAttrs);
config.isTooltextString = true;
}
else {//determine the dispalay value then
config.toolText = formatedVal === null ? false :
(label !== undefined) ? label + tooltipSepChar + formatedVal : formatedVal;
}
//Latter used in real time draw
config.tempToolText = config.toolText;
config.bgAlpha = bgAlpha = pluckNumber(dataObj.alpha, dataObj.bgalpha, chartAttrs.pointerbgalpha,
100);
config.bgColor = bgColor = pluck(dataObj.color, dataObj.bgcolor, chartAttrs.pointerbgcolor,
chartAttrs.pointercolor, colorM.getColor('pointerBgColor'));
config.fillColor = fillColor = convertColor(bgColor, bgAlpha);
config.showBorder = pluckNumber(dataObj.showborder, chartAttrs.showplotborder, 1);
config.borderAlpha = borderAlpha = pluckNumber(dataObj.borderalpha, chartAttrs.pointerborderalpha,
100);
config.borderColor = borderColor = pluck(dataObj.bordercolor, chartAttrs.pointerbordercolor,
colorM.getColor('pointerBorderColor'));
config.pointerBorderColor = pointerBorderColor = convertColor(borderColor, borderAlpha);
config.dataLink = getValidValue(dataObj.link);
config.editMode = pluckNumber(dataObj.editmode, datasetConfig.editMode);
if (showHoverEffect !== 0 && (showHoverEffect || dataObj.bghovercolor ||
chartAttrs.pointerbghovercolor || chartAttrs.plotfillhovercolor ||
dataObj.bghoveralpha || chartAttrs.pointerbghoveralpha || chartAttrs.plotfillhoveralpha ||
dataObj.bghoveralpha === 0 || chartAttrs.pointerbghoveralpha === 0 ||
dataObj.showborderonhover || chartAttrs.showborderonhover ||
dataObj.showborderonhover === 0 || chartAttrs.showborderonhover === 0 ||
dataObj.borderhoverthickness || chartAttrs.pointerborderhoverthickness ||
dataObj.borderhoverthickness === 0 || chartAttrs.pointerborderhoverthickness === 0 ||
dataObj.borderhovercolor || chartAttrs.pointerborderhovercolor ||
dataObj.borderhoveralpha || chartAttrs.pointerborderhoveralpha ||
dataObj.borderhoveralpha === 0 || chartAttrs.pointerborderhoveralpha === 0 ||
dataObj.hoverradius || chartAttrs.pointerhoverradius || dataObj.hoverradius === 0 ||
chartAttrs.pointerhoverradius === 0)) {
showHoverEffect = true;
pointerBgHoverColor = pluck(dataObj.bghovercolor, chartAttrs.pointerbghovercolor,
chartAttrs.plotfillhovercolor, FILLMIXDARK10);
pointerBgHoverAlpha = pluckNumber(dataObj.bghoveralpha,
chartAttrs.pointerbghoveralpha, chartAttrs.plotfillhoveralpha);
showBorderOnHover = pluckNumber(dataObj.showborderonhover, chartAttrs.showborderonhover);
if (showBorderOnHover === undefined){
if (dataObj.borderhoverthickness || dataObj.borderhoverthickness === 0 ||
dataObj.borderhovercolor || dataObj.borderhoveralpha ||
dataObj.borderhoveralpha === 0){
showBorderOnHover = 1;
}
else {
showBorderOnHover = showBorder;
}
}
pointerBorderHoverColor = pluck(dataObj.borderhovercolor, chartAttrs.pointerborderhovercolor,
FILLMIXDARK10);
pointerBorderHoverAlpha = pluckNumber(dataObj.borderhoveralpha,
chartAttrs.pointerborderhoveralpha);
pointerBorderHoverThickness = showBorderOnHover ? pluckNumber(dataObj.borderhoverthickness,
chartAttrs.pointerborderhoverthickness, borderWidth || 1) : 0;
pointerHoverRadius = pluckNumber(dataObj.hoverradius, chartAttrs.pointerhoverradius,
radius + 2);
showHoverAnimation = !!pluckNumber(dataObj.showhoveranimation, chartAttrs.showhoveranimation,
1);
config.hoverAttr = hoverAttr = {};
config.outAttr = outAttr = {};
if (borderWidth !== pointerBorderHoverThickness) {
hoverAttr['stroke-width'] = pointerBorderHoverThickness;
outAttr['stroke-width'] = borderWidth;
}
outAttr.fill = fillColor;
hasHoberFillMix = /\{/.test(pointerBgHoverColor);
pointerBgHoverColor = hasHoberFillMix ? colorM.parseColorMix(bgColor,
pointerBgHoverColor)[0] : pointerBgHoverColor;
hoverAttr.fill = convertColor(pointerBgHoverColor, pluckNumber(pointerBgHoverAlpha, bgAlpha));
if (pointerBorderHoverThickness) {
outAttr.stroke = pointerBorderColor;
hasBorderHoverMix = /\{/.test(pointerBorderHoverColor);
hoverAttr.stroke = convertColor(hasBorderHoverMix ? colorM.parseColorMix(borderColor,
pointerBorderHoverColor)[0] : pointerBorderHoverColor,
pluckNumber(pointerBorderHoverAlpha, borderAlpha));
}
if (pointerHoverRadius){
if (showHoverAnimation) {
hoverAnimAttr = {
r: pointerHoverRadius
};
outAnimAttr = {
r: radius
};
}
else {
hoverAttr.r = pointerHoverRadius;
outAttr.r = radius;
}
}
}
config.rolloverProperties = {
enabled: showHoverEffect,
hoverAttr: hoverAttr,
hoverAnimAttr: hoverAnimAttr,
outAttr: outAttr,
outAnimAttr: outAnimAttr
};
}
},
// Space management for the pointer value.
_manageSpace : function (availableHeight) {
var dataSet = this,
chart = dataSet.chart,
components = dataSet.components,
chartConfig = chart.config,
datasetConfig = dataSet.config,
smartLabel = chart.linkedItems.smartLabel,
canvasWidth = chartConfig.canvasWidth,
smartDataLabel, extraSpace,
style = chartConfig.dataLabelStyle,
trendStyle = chartConfig.style.trendStyle,
jsonData = chart.jsonData,
trendArray = jsonData.trendpoints && jsonData.trendpoints.point,
lineHeight = pluckNumber(parseInt(style.lineHeight, 10), 12),
maxAllowedHeight = availableHeight,
datasetValuePadding = datasetConfig.valuePadding,
valueInsideGauge = datasetConfig.valueInsideGauge,
valuePaddingWithRadius,
heightUsed = 0,
heightUsedBottom = 0,
heightUsedTop = 0,
valuePadding = 0,
trendPadding = 0,
heightReducedBottom = 0,
heightReducedTop = 0,
trendPointConfig,
point,
trendPaddingWithRadius,
tickDimension = chart.components.scale.config.spaceTaken,
i = 0,
len = dataSet.pointerArr && dataSet.pointerArr.pointer && dataSet.pointerArr.pointer.length,
pointerOnOpp = datasetConfig.pointerOnOpp,
config,
data = components.data;
trendArray && chart._configueTrendPoints();
smartLabel.useEllipsesOnOverflow(chartConfig.useEllipsesWhenOverflow);
smartLabel.setStyle(style);
for (; i < len; i += 1) {
config = data[i].config;
// Add pointer radius in value-padding
valuePaddingWithRadius = datasetValuePadding + config.radius *
(config.sides <= 3 ? 0.5 : (config.sides % 2 ? 1.1 - (1 / config.sides) : 1));
valuePadding = Math.max(valuePadding, valuePaddingWithRadius);
if (config.showValue && config.displayValue !== BLANKSTRING) {
if (config.isLabelString) {
smartDataLabel = smartLabel.getSmartText(config.displayValue, canvasWidth,
maxAllowedHeight - valuePadding);
config.displayValue = smartDataLabel.text;
smartDataLabel.tooltext && (config.originalText = smartDataLabel.tooltext);
}
else {
smartDataLabel = smartLabel.getOriSize(config.displayValue);
}
//special fix for space string
/** @todo will be removed when smartLabel will be able to handle it */
if (config.displayValue === BLANK) {
smartDataLabel = {
height : lineHeight
};
}
}
if (smartDataLabel && smartDataLabel.height > 0 && !valueInsideGauge) {
heightUsed = smartDataLabel.height + valuePaddingWithRadius;
}
else {
heightUsed = valuePaddingWithRadius;
}
if (heightUsed > maxAllowedHeight) {
extraSpace = heightUsed - maxAllowedHeight;
valuePaddingWithRadius = extraSpace < valuePaddingWithRadius ?
valuePaddingWithRadius - extraSpace : 0;
heightUsed = maxAllowedHeight;
}
if (pointerOnOpp) {
if (datasetConfig.axisPosition === AXISPOSITION_BOTTOM) {
heightReducedBottom = Math.max(tickDimension.bottom, heightReducedBottom);
heightUsed = Math.max(tickDimension.bottom, heightUsed);
}
heightUsedBottom = Math.max(heightUsedBottom, heightUsed);
} else {
if (datasetConfig.axisPosition === AXISPOSITION_TOP) {
heightReducedTop = Math.max(tickDimension.top, heightReducedTop);
heightUsed = Math.max(tickDimension.top, heightUsed);
}
heightUsedTop = Math.max(heightUsed, heightUsedTop);
}
datasetConfig.align = POSITION_CENTER;
}
datasetConfig.currentValuePadding = valuePadding;
smartLabel.setStyle(trendStyle);
if (trendArray) {
trendPointConfig = chartConfig.trendPointConfig;
for (i = 0, len = trendPointConfig.length; i < len; i += 1) {
point = trendPointConfig[i];
if (point && point.displayValue !== BLANKSTRING) {
// Add pointer radius in value-padding
trendPaddingWithRadius = datasetValuePadding + point.markerRadius * 0.5;
trendPadding = Math.max(trendPaddingWithRadius, trendPadding);
smartDataLabel = smartLabel.getOriSize(point.displayValue);
if (smartDataLabel.height > 0) {
heightUsed = smartDataLabel.height + trendPaddingWithRadius;
}
if (heightUsed > maxAllowedHeight) {
extraSpace = heightUsed - maxAllowedHeight;
trendPaddingWithRadius = extraSpace < trendPaddingWithRadius ?
trendPaddingWithRadius - extraSpace : 0;
heightUsed = maxAllowedHeight;
}
if (point.showOnTop) {
if (datasetConfig.axisPosition === AXISPOSITION_TOP) {
heightReducedTop = Math.max(tickDimension.top, heightReducedTop);
heightUsed = Math.max(tickDimension.top, heightUsed);
}
heightUsedTop = Math.max(heightUsedTop, heightUsed);
} else {
if (datasetConfig.axisPosition === AXISPOSITION_BOTTOM) {
heightReducedBottom = Math.max(tickDimension.bottom, heightReducedBottom);
heightUsed = Math.max(tickDimension.bottom, heightUsed);
}
heightUsedBottom = Math.max(heightUsed, heightUsedBottom);
}
}
}
datasetConfig.currentTrendPadding = trendPadding;
}
return {
top : heightUsedTop - heightReducedTop,
bottom : heightUsedBottom - heightReducedBottom
};
},
// draws the pointer
draw : function (animation, isRTupdate) {
var dataSet = this,
idMap = dataSet.idMap,
chart = dataSet.chart,
chartComponents = chart.components,
chartConfig = chart.config,
chartGraphics = chart.graphics,
dataLabelsGroup = chartGraphics.datalabelsGroup,
wGroup = chartGraphics.tempGroup,
paper = chartComponents.paper,
scale = chartComponents.scale,
chartData = dataSet.pointerArr && dataSet.pointerArr.pointer,
width = chartConfig.canvasWidth,
height = chartConfig.canvasHeight,
datasetConfig = dataSet.config,
pointerY = (datasetConfig.pointerOnOpp ? height : 0),
showPointerShadow = datasetConfig.showPointerShadow,
showTooltip = datasetConfig.showTooltip,
min = scale.config.axisRange.min,
max = scale.config.axisRange.max,
pxValueFactor = (max - min) / width,
i = (chartData && chartData.length) || 1,
config,
prevData,
shadowObj,
startAngle,
components = dataSet.components,
data = components.data,
animationObj = chart.get(configStr,animationObjStr),
animObj = animationObj.animObj,
dummyObj = animationObj.dummyObj,
animType = animationObj.animType,
animationDuration = (animation || animationObj).duration,
stubEvent = {
pageX: 0,
pageY: 0
},
pointerDragStart = function (x) {
var point = this;
if (point.editMode === false) {
return;
}
prevData = chart._getDataJSON();
point.dragStartX = x;
},
pointerDragEnd = function () {
var point = this,
config = point.config,
jsVars,
chartObj = chart.chartInstance;
if (point.config.editMode === false) {
return;
}
jsVars = chartObj && chartObj.jsVars;
jsVars && (jsVars._rtLastUpdatedData = chart._getDataJSON());
global.raiseEvent('RealTimeUpdateComplete', {
data: '&value=' + config.updatedValStr,
updateObject: {values: [config.updatedValStr]},
prevData: prevData.values,
source: 'editMode',
url: null
}, chartObj);
try {
/* jshint camelcase: false*/
win.FC_ChartUpdated && win.FC_ChartUpdated(chartObj.id);
/* jshint camelcase: true*/
}
catch (err) {
setTimeout(function () {
throw (err);
}, 1);
}
if (datasetConfig.showTooltip) {
pointer.tooltip(config.toolText);
}
else {
pointer.tooltip(BLANK);
}
},
pointerOnDrag = function (dx, dy, x, y, event) {
var point = this,
touchEvent = (hasTouch && getTouchEvent(event)) || stubEvent,
scaleMinMax = scale.getLimit(),
scaleMin = scaleMinMax.min,
scaleMax = scaleMinMax.max,
pointVal = pluckNumber(point.itemValue, scaleMin),
diffX = point.dragStartX - x,
newVal = pointVal - (diffX * pxValueFactor),
i = 0,
values = [],
tempValues = [];
if (point.editMode === false) {
return;
}
// Flag set for setting click link in edit mode.
point.drag = true;
if (newVal < scaleMin) {
newVal = scaleMin;
} else if (newVal > scaleMax) {
newVal = scaleMax;
}
for (;i < point.index; i += 1) {
values.push(BLANK);
tempValues.push(BLANK);
}
values.push({value : newVal});
tempValues.push(newVal);
if (pointVal !== newVal && dataSet.updateData({data: values}, {duration : 0})) {
point.updatedValStr = tempValues.join('|');
point.dragStartX = (x || event.pageX || touchEvent.pageX);
}
},
pointer,
graphics,
link,
rolloverProperties,
eventArgs,
clickHandler,
hoverRollOver,
hoverRollOut,
pool = dataSet.pool;
if (!wGroup) {
wGroup = chartGraphics.tempGroup = paper.group('tempGroup', dataLabelsGroup).trackTooltip(true);
}
clickHandler = function (graphicData) {
var ele = this,
index = ele.data(EVENTARGS).index,
config = data[index].config;
if (config.drag === true) {
config.drag = false;
return;
}
plotEventHandler.call(ele, chart, graphicData);
};
hoverRollOver = function (data) {
var ele = this,
rolloverProperties = ele.data('rolloverProperties');
if (rolloverProperties.enabled) {
ele.attr(rolloverProperties.hoverAttr);
if (rolloverProperties.hoverAnimAttr) {
ele.animate(rolloverProperties.hoverAnimAttr, 100, ANIM_EFFECT);
}
}
plotEventHandler.call(ele, chart, data, ROLLOVER);
};
hoverRollOut = function (data) {
var ele = this,
rolloverProperties = ele.data('rolloverProperties');
if (rolloverProperties.enabled) {
ele.attr(rolloverProperties.outAttr);
if (rolloverProperties.outAnimAttr) {
ele.animate(rolloverProperties.outAnimAttr, 100, ANIM_EFFECT);
}
}
plotEventHandler.call(ele, chart, data, ROLLOUT);
};
while (i--) {
config = data[i].config;
graphics = data[i].graphics || (data[i].graphics = {}),
rolloverProperties = config.rolloverProperties || {};
startAngle = datasetConfig.startAngle;
idMap[config.id] = {
index : i,
config : config
};
/**
* @note
* The slight increment in starting angle is done to avoid getting
* angles in multiples of 90 degree (default starting angle is 270).
* Issue is like, cos(270 deg) is not zero but in the range of e-16,
* when VML silently fails to render.
*/
startAngle += 0.2;
shadowObj = showPointerShadow ? {
opacity: (Math.max(config.bgAlpha, config.borderAlpha) / 100)
} : false;
link = config.dataLink;
eventArgs = {
index : i,
link: link,
value: config.itemValue,
displayValue: config.displayValue,
toolText: config.toolText
};
if (!(pointer = graphics.pointer)) {
if (pool && pool.pointer[0]) {
pointer = graphics.pointer = pool.pointer[0];
pool.pointer.splice(0, 1);
}
else {
pointer = graphics.pointer = paper.polypath(wGroup)
.click(clickHandler)
.hover(hoverRollOver, hoverRollOut);
}
pointer.attr({
polypath : [config.sides,
0,
(pointerY || 0),
config.radius,
startAngle,
0,
wGroup
]
});
pointer.show();
pointer.drag(pointerOnDrag, pointerDragStart, pointerDragEnd, config, config, data[i]);
}
if (!isRTupdate) {
pointer.attr({
fill: config.fillColor,
stroke: config.pointerBorderColor,
ishot: true,
'stroke-width': config.borderWidth
})
.shadow(!!shadowObj, shadowObj && shadowObj.opacity)
.data(EVENTARGS, eventArgs)
.data('rolloverProperties', rolloverProperties);
if (link || config.editMode) {
pointer.css({
cursor: POINTER,
'_cursor': 'hand'
});
}
else {
pointer.css({
cursor: BLANK,
'_cursor': BLANK
});
}
config._startAngle = startAngle;
if (config.editMode) {
config.index = i;
config.editMode = true;
}
else {
config.editMode = false;
}
pointer.attr({ishot: true});
}
if (showTooltip) {
pointer.tooltip(config.toolText, null, null, true);
}
else {
pointer.tooltip(BLANK);
}
pointer.animateWith(dummyObj, animObj, {
polypath: [
config.sides,
width * (pluckNumber(config.itemValue, min) - min) / (max - min),
(pointerY || 0),
config.radius,
startAngle,
0
],
r: config.radius
},animationDuration, animType);
}
isRTupdate ? dataSet.drawPointerValues(animation) : dataSet._drawWidgetLabel(animation);
dataSet.removeDataArr && dataSet.remove();
},
// Alters the data of the dataset and stores the data to be removed in a different array
removeData : function (numbers) {
var dataSet = this,
data = dataSet.components.data;
dataSet.removeDataArr || (dataSet.removeDataArr = []) ;
dataSet.removeDataArr = dataSet.removeDataArr.concat(data.splice(0, numbers));
},
// Hides the graphic element of the pointer
remove : function () {
var dataSet = this,
removeDataArr = dataSet.removeDataArr,
length = removeDataArr.length,
graphics,
pointerValue,
pointer,
i,
pool = dataSet.pool || (dataSet.pool = {
pointer : [],
pointerValue : []
});
for (i = 0; i < length; i++) {
graphics = removeDataArr[i].graphics;
pointer = graphics.pointer;
pointerValue = graphics.pointerValue;
pool.pointer[i] = graphics.pointer;
pool.pointerValue[i] = graphics.pointerValue;
pointerValue.hide();
pointer.hide();
pointer.undrag();
pointer.shadow(false);
}
delete dataSet.removeDataArr;
},
// draws Widget background(color range) values, trend point values and calls drawPointerValues
_drawWidgetLabel: function (animation) {
var dataSet = this,
chart = dataSet.chart,
chartConfig = chart.config,
chartComponents = chart.components,
numberFormatter = chartComponents.numberFormatter,
scale = chartComponents.scale,
paper = chartComponents.paper,
dataLabelsGroup = chart.graphics.datalabelsGroup,
min = scale.config.axisRange.min,
max = scale.config.axisRange.max,
datasetConfig = dataSet.config,
textDirection = datasetConfig.textDirection,
gaugeType = 1, //series.gaugeType,
colorArr = chartComponents.colorRange && chartComponents.colorRange.getColorRangeArr(min, max),
colorRangeStyle = datasetConfig.colorRangeStyle || {},
showvalue = datasetConfig.showvalue,
colorObj,
tempLabelPadding,
trendArr = chart.jsonData.trendpoints && chart.jsonData.trendpoints.point,
trendPointConfig = chartConfig.trendPointConfig,
width = chartConfig.canvasWidth,
height = chartConfig.canvasHeight,
marginRight = chartConfig.marginRight,
pointerOnOpp = datasetConfig.pointerOnOpp,
valueInsideGauge = datasetConfig.valueInsideGauge,
showGaugeLabels = datasetConfig.showGaugeLabels,
style = chartConfig.dataLabelStyle,
animationObj = chart.get(configStr,animationObjStr),
animObj = animationObj.animObj,
dummyObj = animationObj.dummyObj,
animType = animationObj.animType,
animationDuration = animationObj.duration,
colorArrLabel,
maxWidth,
truncatedWidth,
i,
length,
getPointerLabelXY,
getColorLabelXY,
labelXY,
nextPointer,
nextOriText,
nextSmartText,
nextXY,
labelGap,
isSameLevel = false,
j,
labelX,
labelY,
smartLabel = chart.linkedItems.smartLabel, smartText, testStrObj, minWidth, //labelX, labelY,
lineHeight = pluckNumber(parseInt(style.fontHeight, 10), parseInt(style.lineHeight, 10), 12),
labelPadding = (datasetConfig.currentValuePadding + (lineHeight * 0.5)) , hPad = 4,
innerLabelPadding = 4,
oppTrendLabelPadding = (datasetConfig.currentTrendPadding + (lineHeight * 0.5)),
tempx,
graphics,
attr,
trendObj,
trendLabelPadding = datasetConfig.currentTrendPadding,
css = {
fontFamily: style.fontFamily,
fontSize: style.fontSize,
lineHeight: style.lineHeight,
fontWeight: style.fontWeight,
fontStyle: style.fontStyle
},
dataArr = dataSet.pointerArr && dataSet.pointerArr.pointer,
config,
components = dataSet.components,
data = components.data,
dataLabels = components.dataLabels || (components.dataLabels = []),
trendLabels = components.trendLabels || (components.trendLabels = []),
dataLabel,
value,
trendLabel;
dataLabelsGroup.transform(['T', chartConfig.canvasLeft, chartConfig.canvasTop]);
tempLabelPadding = labelPadding - (lineHeight / 4);
// if label is below the pointer then we need to add extra pdding to compensate for lineheight.
labelPadding = (valueInsideGauge === pointerOnOpp) ? labelPadding - (lineHeight / 4) :
labelPadding + (lineHeight / 4);
smartLabel.useEllipsesOnOverflow(chartConfig.useEllipsesWhenOverflow);
smartLabel.setStyle(css);
testStrObj = smartLabel.getOriSize('W...');
minWidth = testStrObj.width;
colorRangeStyle.fontWeight = 'normal';
if (gaugeType === 1 ) { // horizontal gauge; left to right;
getPointerLabelXY = dataSet.getPointerLabelXY =
function (value, isInside, pointerOnOpp, xsHeight, xsWidth) {
var y;
if (pointerOnOpp) {
y = isInside ? (height - xsHeight - labelPadding) : (height + labelPadding);
} else {
y = isInside ? labelPadding : -(labelPadding + xsHeight);
}
tempx = (value - min) * width / (max - min);
(tempx + xsWidth > width + marginRight) && (tempx = width - xsWidth + marginRight);
return {
x: tempx,
y: y,
align: POSITION_MIDDLE
};
};
getColorLabelXY = function (minvalue, maxvalue) {
return {
x: (((minvalue - min) + (maxvalue - minvalue) / 2) * width / (max - min)),
y: (height / 2),
width: (maxvalue - minvalue) * width / (max - min),
height: height
};
};
} else if (gaugeType === 2) { // vertical gauge; top to bottom;
getPointerLabelXY = dataSet.getPointerLabelXY = function (value, isInside, pointerOnOpp) {
var x, align;
if (pointerOnOpp) {
if (isInside) {
align = POSITION_RIGHT;
x = width - labelPadding;
} else {
align = POSITION_LEFT;
x = width + labelPadding;
}
}
else {
if (isInside) {
align = POSITION_LEFT;
x = labelPadding;
}
else {
align = POSITION_RIGHT;
x = -labelPadding;
}
}
return {
x: x,
y: (value * height / (max - min)),
align: align
};
};
getColorLabelXY = function (minvalue, maxvalue) {
return {
y: (((minvalue - min) + (maxvalue - minvalue) / 2) * height / (max - min)),
x: (width / 2),
height: (maxvalue - minvalue) * height / (max - min),
width: width
};
};
}
else if (gaugeType === 3) { // horizontal linear gauge; right to left;
getPointerLabelXY = dataSet.getPointerLabelXY = function (value, isInside, pointerOnOpp) {
var y;
if (pointerOnOpp) {
y = isInside ? height - labelPadding : height + labelPadding;
} else {
y = isInside ? labelPadding : -labelPadding;
}
return {
x: width - ((value - min) * width / (max - min)),
y: y,
align: POSITION_MIDDLE
};
};
getColorLabelXY = function (minvalue, maxvalue) {
return {
x: width - (((minvalue - min) + (maxvalue - minvalue) / 2) * width / (max - min)),
y: (height / 2),
width: (maxvalue - minvalue) * width / (max - min),
height: height
};
};
}
else { // vertical linear gauge; bottom to top;
getPointerLabelXY = dataSet.getPointerLabelXY = function (value, isInside, pointerOnOpp) {
var x, align;
if (pointerOnOpp) {
if (isInside) {
align = POSITION_RIGHT;
x = width - labelPadding;
} else {
align = POSITION_LEFT;
x = width + labelPadding;
}
} else {
if (isInside) {
align = POSITION_LEFT;
x = labelPadding;
} else {
align = POSITION_RIGHT;
x = -labelPadding;
}
}
return {
x: x,
y: height - (value * height / (max - min)),
align: align
};
};
getColorLabelXY = function (minvalue, maxvalue) {
return {
y: height - (((minvalue - min) + (maxvalue - minvalue) / 2) * height / (max - min)),
x: (width / 2),
height: (maxvalue - minvalue) * height / (max - min),
width: width
};
};
}
if (dataArr && dataArr.length) {
i = dataArr.length;
while (i--) {
config = data[i].config;
if (showvalue !== 0 && config.displayValue !== BLANKSTRING) {
smartText = smartLabel.getOriSize(config.displayValue);
if (config.setWidth) {
smartText = smartLabel.getSmartText(config.displayValue,
config.setWidth, smartText.height, true);
}
labelXY = dataSet.getPointerLabelXY(config.itemValue, valueInsideGauge,
pointerOnOpp, (smartText.height / 2) , (smartText.width / 2));
if (config.isLabelString) {
isSameLevel = false, j = 1;
while (!isSameLevel) {
nextPointer = dataArr[i + j];
if (!nextPointer) {
break;
}
if (nextPointer.isLabelString) {
isSameLevel = true;
}
else {
j += 1;
}
}
if (nextPointer) {
nextOriText = smartLabel.getOriSize(nextPointer.displayValue);
nextXY = getPointerLabelXY(nextPointer.y, valueInsideGauge,
pointerOnOpp, (nextOriText.height / 2));
//calculate the overlapping area's width
labelGap = (nextXY.x - (nextOriText.width / 2)) - (labelXY.x +
(smartText.width / 2));
// get the max width i.e the distance between the pointers
maxWidth = nextXY.x - labelXY.x;
if (labelGap < 0) {
// calculate the truncated width using labelGap (should be -ve)
truncatedWidth = smartText.width + labelGap;
// the truncated width cannot be more than max width.
if (truncatedWidth > maxWidth) {
config.setWidth = truncatedWidth = maxWidth;
}
if (truncatedWidth > minWidth) {
if (config.setWidth && config.setWidth <= truncatedWidth) {
nextSmartText = smartLabel.getSmartText(
config.displayValue, config.setWidth, smartText.height, true);
config.displayValue = nextSmartText.text;
nextSmartText.tooltext &&
(config.originalText = nextSmartText.tooltext);
}
else {
nextSmartText = smartLabel.getSmartText(
config.displayValue, truncatedWidth, smartText.height, true);
config.displayValue = nextSmartText.text;
nextSmartText.tooltext &&
(config.originalText = nextSmartText.tooltext);
}
}
else {
nextSmartText = smartLabel.getSmartText(
config.displayValue, minWidth, smartText.height, true);
config.displayValue = nextSmartText.text;
nextSmartText.tooltext && (config.originalText = nextSmartText.tooltext);
// since the labelGap was not split equally we have to recalculate
// labelGap so that the next label will adjust accordingly.
labelGap = labelGap * 2 + minWidth - hPad;
}
config.setWidth = null;
truncatedWidth = nextOriText.width + labelGap - hPad;
if (truncatedWidth > maxWidth) {
nextPointer.setWidth = maxWidth;
}
else if (truncatedWidth > minWidth) {
nextPointer.setWidth = truncatedWidth;
}
else {
nextPointer.setWidth = minWidth;
}
}
}
if (config.setWidth) {
nextSmartText = smartLabel.getSmartText(
config.displayValue, config.setWidth, smartText.height, true);
config.displayValue = nextSmartText.text;
nextSmartText.tooltext && (config.originalText = nextSmartText.tooltext);
config.setWidth = null;
}
}
}
}
}
dataSet.drawPointerValues(animation);
smartLabel.setStyle(colorRangeStyle);
// Draw the colorRange labels
if (colorArr && showGaugeLabels) {
for (i = 0, length = colorArr.length; i < length; i += 1) {
dataLabel = dataLabels[i] || (components.dataLabels[i] = {});
graphics = dataLabel.graphics || (dataLabel.graphics = {});
colorObj = colorArr[i];
colorArrLabel = pluck(colorObj.label, colorObj.name);
labelXY = getColorLabelXY(colorObj.minvalue, colorObj.maxvalue);
if ((labelXY.width - innerLabelPadding) > minWidth &&
(labelXY.height - innerLabelPadding) > lineHeight) {
smartText = smartLabel.getSmartText(colorArrLabel,
labelXY.width - innerLabelPadding, labelXY.height - innerLabelPadding);
}
else {
smartText = smartLabel.getSmartText(colorArrLabel, labelXY.width, labelXY.height);
}
attr = {
'text-anchor': POSITION_MIDDLE,
'vertical-align': POSITION_MIDDLE,
x: labelXY.x,
y: labelXY.y,
direction: textDirection,
fill : colorRangeStyle.color,
text: smartText.text
};
if (!(value = graphics.value)) {
value = graphics.value = paper.text(attr, colorRangeStyle, dataLabelsGroup);
}
else {
value.show();
value.animateWith(dummyObj, animObj, attr, animationDuration, animType)
.css(colorRangeStyle)
.tooltip(smartText.tooltext);
}
}
}
else {
// Setting i to 0 so that any previously existing trendlabels can be hidden.
i = 0;
}
// Hiding the unused colorrangeLabels
while(dataLabel = dataLabels && dataLabels[i++]) {
dataLabel.graphics.value.hide();
}
// Drawing the display value of trend points
if (trendArr) {
for (i = 0, length = trendPointConfig.length; i < length; i += 1) {
trendLabel = trendLabels[i] || (components.trendLabels[i] = {});
graphics = trendLabel.graphics || (trendLabel.graphics = {});
trendObj = trendPointConfig[i];
trendObj.displayValue = pluck(trendObj.displayValue,
numberFormatter.dataLabels(trendObj.startValue));
smartLabel.setStyle(trendObj.style);
lineHeight = smartLabel.getOriSize('Wg').height;
smartText = smartLabel.getOriSize(trendObj.displayValue);
labelXY = getPointerLabelXY(trendObj.startValue, 0, !trendObj.showOnTop);
if (trendObj.setWidth) {
smartText = smartLabel.getSmartText(trendObj.displayValue,
trendObj.setWidth, smartText.height, true);
}
isSameLevel = false, j = 1;
while (!isSameLevel) {
nextPointer = trendArr[i + j];
if (!nextPointer) {
break;
}
if (nextPointer.showOnTop === trendObj.showOnTop) {
isSameLevel = true;
}
else {
j += 1;
}
}
if (nextPointer) {
nextOriText = smartLabel.getOriSize(nextPointer.displayValue);
nextXY = getPointerLabelXY(nextPointer.startValue, 0, !nextPointer.showOnTop);
// refer to the docs of pointer label drawing above.
labelGap = (nextXY.x - (nextOriText.width / 2)) - (labelXY.x + (smartText.width / 2));
if (labelGap < 0) {
maxWidth = nextXY.x - labelXY.x;
truncatedWidth = smartText.width + labelGap;
if (truncatedWidth > maxWidth) {
trendObj.setWidth = truncatedWidth = maxWidth;
}
if (truncatedWidth > minWidth) {
if (trendObj.setWidth && (trendObj.setWidth <= truncatedWidth)) {
smartText = smartLabel.getSmartText(trendObj.displayValue,
trendObj.setWidth, smartText.height, true);
trendObj.displayValue = smartText.text;
smartText.tooltext && (trendObj.originalText = smartText.tooltext);
}
else {
smartText = smartLabel.getSmartText(trendObj.displayValue,
smartText.width + labelGap - hPad, smartText.height, true);
trendObj.displayValue = smartText.text;
smartText.tooltext && (trendObj.originalText = smartText.tooltext);
}
}
else {
smartText = smartLabel.getSmartText(
trendObj.displayValue, minWidth, smartText.height, true);
trendObj.displayValue = smartText.text;
smartText.tooltext && (trendObj.originalText = smartText.tooltext);
labelGap = labelGap * 2 + minWidth - hPad;
}
trendObj.setWidth = null;
truncatedWidth = nextOriText.width + labelGap - hPad;
if (truncatedWidth > maxWidth) {
nextPointer.setWidth = maxWidth;
}
else if (truncatedWidth > minWidth) {
nextPointer.setWidth = truncatedWidth;
}
else {
nextPointer.setWidth = minWidth;
}
}
}
if (trendObj.setWidth) {
smartText = smartLabel.getSmartText(trendObj.displayValue, trendObj.setWidth,
smartText.height, true);
trendObj.displayValue = smartText.text;
smartText.tooltext && (trendObj.originalText = smartText.tooltext);
trendObj.setWidth = null;
}
labelY = trendObj.showOnTop ? -(trendLabelPadding + (smartText.height / 2)) :
height + oppTrendLabelPadding;
labelX = trendObj.isTrendZone ? getColorLabelXY(trendObj.startValue, trendObj.endValue).x :
labelXY.x;
if (!graphics.value) {
graphics.value = paper.text(dataLabelsGroup);
}
graphics.value.attr({
x : labelX,
y : labelY,
text : trendObj.displayValue,
'text-anchor': textHAlign[labelXY.align],
fill: convertColor(trendObj.textColor || colorRangeStyle.color),
'font-weight': 'normal',
direction: textDirection,
title: (trendObj.originalText || BLANK)
});
graphics.value.show();
}
}
else {
// Setting i to 0 so that any previously existing trendlabels can be hidden.
i = 0;
}
// Hiding the unused trendLabels
while(trendLabel = trendLabels && trendLabels[i++]) {
trendLabel.graphics.value.hide();
}
},
//Drawing pointer values
drawPointerValues: function (animation) {
var dataSet = this,
chart = dataSet.chart,
dataLabelsGroup = chart.graphics.datalabelsGroup,
paper = chart.components.paper,
data = dataSet.components.data,
datasetConfig = dataSet.config,
pointerOnOpp = datasetConfig.pointerOnOpp,
valueInsideGauge = datasetConfig.valueInsideGauge,
textDirection = datasetConfig.textDirection,
showValue,
smartLabel = chart.linkedItems.smartLabel,
chartData = dataSet.pointerArr && dataSet.pointerArr.pointer,
style = chart.config.dataLabelStyle,
i = chartData && chartData.length,
config,
pointerValue,
animationObj = chart.get(configStr,animationObjStr),
animObj = animationObj.animObj,
dummyObj = animationObj.dummyObj,
animType = animationObj.animType,
animationDuration = (animation || animationObj).duration,
chartConfig = chart.config,
marginLeft = chartConfig.marginLeft,
css = {
fontFamily: style.fontFamily,
fontSize: style.fontSize,
lineHeight: style.lineHeight,
fontWeight: style.fontWeight,
fontStyle: style.fontStyle
},
displayValue,
labelXY,
halfWidth,
graphics,
smartText,
pool = dataSet.pool,
attr,
textCreated;
smartLabel.useEllipsesOnOverflow(chartConfig.useEllipsesWhenOverflow);
while (i--) {
textCreated = false;
graphics = data[i].graphics;
config = data[i].config;
displayValue = config.displayValue,
showValue = config.showValue;
if (showValue !== 0 && displayValue !== BLANKSTRING) {
smartText = smartLabel.getOriSize(displayValue);
halfWidth = smartText.width / 2;
labelXY = dataSet.getPointerLabelXY(config.itemValue,
valueInsideGauge, pointerOnOpp, (smartText.height / 2), halfWidth);
attr = {
'text-anchor': textHAlign[labelXY.align],
title: (config.originalText || BLANK),
text: displayValue,
fill: style.color,
direction: textDirection,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
};
if (!(pointerValue = graphics.pointerValue)) {
if (pool && pool.pointerValue[0]) {
pointerValue = graphics.pointerValue = pool.pointerValue[0];
pool.pointerValue.splice(0, 1);
}
else {
attr.x = 0;
attr.y = labelXY.y;
textCreated = true;
pointerValue = graphics.pointerValue = paper.text(attr, css, dataLabelsGroup);
}
}
// Applying attr from second time ownwards during update.
if (!textCreated) {
pointerValue.attr(attr).css(css);
pointerValue.show();
}
// Fix for long decimal numbers moving out of the canvas.
(halfWidth > marginLeft + labelXY.x) && (labelXY.x = halfWidth - marginLeft);
pointerValue.animateWith(dummyObj, animObj, {
x: labelXY.x,
y: labelXY.y
}, animationDuration, animType);
}
else {
graphics.pointerValue && graphics.pointerValue.hide();
}
}
},
// Setting axis limits
getDataLimits : function () {
var dataSet = this,
config = dataSet.config,
jsonData = dataSet.chart.jsonData,
pointerArr = (dataSet.pointerArr && dataSet.pointerArr.pointer) ||
(jsonData.dials && jsonData.dials.dial),
colorRange = jsonData.colorrange,
colorArr = colorRange && colorRange.color,
length = pointerArr && pointerArr.length,
i,
pointerMinVal,
pointerMaxVal,
upperLimit = config.upperLimit,
lowerLimit = config.lowerLimit,
value,
maxColorRangeVal,
minColorRangeVal,
max = -Infinity,
min = +Infinity;
// finding max min amongst the pointer value
for (i=0; i<length; i++) {
value = pointerArr[i].value;
if (value === BLANK) {
continue;
}
pointerMaxVal = max = mathMax(max, Number(pointerArr[i].value));
pointerMinVal = min = mathMin(min, Number(pointerArr[i].value));
}
length = colorArr && colorArr.length;
// finding max min amongst the color range value but it has a lower
// priority than upperlimit and lowerlimit set by the user.
for (i=0; i<length; i++) {
maxColorRangeVal = Number(colorArr[i].maxvalue);
minColorRangeVal = Number(colorArr[i].minvalue);
upperLimit && (maxColorRangeVal > upperLimit) && (maxColorRangeVal = upperLimit);
lowerLimit && (minColorRangeVal < lowerLimit) && (minColorRangeVal = lowerLimit);
max = mathMax(max, maxColorRangeVal);
min = mathMin(min, minColorRangeVal);
}
return {
forceMin : pointerMinVal !== min,
forceMax : pointerMaxVal !== max,
max : max,
min : min
};
},
// Function to update the hlinear data via drag mode or realTime update
updateData: function (updateObj, updateAnimation) {
if (updateObj === this.lastUpdatedObj) {
return false;
}
var dataSet = this,
chart = dataSet.chart,
numberFormatter = chart.components.numberFormatter,
data = dataSet.components.data,
label,
toolText,
showLabel,
dataArr = dataSet.components.data,
i = (dataArr && dataArr.length) || 0,
dataObj,
config,
formatedValue = null,
newData = [],
updateData,
value,
animation,
pointObj;
updateObj = updateObj.data;
//use the realtime animation value or the default animation value
animation = updateAnimation || chart.get(configStr, animationObjStr);
if (i) {
while (i--) {
dataObj = {};
pointObj = {};
config = data[i].config;
updateData = updateObj[i];
if (!updateData) {
continue;
}
value = updateData.value;
toolText = updateData.tooltext;
label = updateData.label;
showLabel = updateData.showlabel;
if (value !== undefined && value !== BLANK) {
dataObj.value = pointObj.value = value;
formatedValue = pointObj.displayvalue =
pointObj.tooltext = numberFormatter.dataLabels(pointObj.value);
pointObj.hasNewData = true;
}
else {
pointObj.value = config.formatedVal;
}
if (label) {
pointObj.displayvalue = label;
pointObj.hasNewData = true;
}
if (showLabel == '0') {
pointObj.displayvalue = BLANKSTRING;
pointObj.hasNewData = true;
}
if (toolText) {
toolText = getValidValue(parseUnsafeString(toolText));
pointObj.hasNewData = true;
}
if (pointObj.hasNewData) {
newData[i] = pointObj;
extend2(config, {
itemValue: pointObj.value,
displayValue: ((config.displayValue || showLabel == '1') ?
pointObj.displayvalue : BLANKSTRING),
toolText: toolText !== undefined ? parseTooltext(toolText, [1,2], {
formattedValue: formatedValue
}, dataObj) : (config.setToolText ? config.tempToolText : formatedValue)
});
}
}
if (newData.length) {
this.lastUpdatedObj = updateObj;
this.draw(animation, true);
}
return Boolean(newData.length);
}
}
}]);
}]);
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-bullet',
function () {
var global = this,
lib = global.hcLib,
preDefStr = lib.preDefStr,
BLANK = lib.BLANKSTRING,
BLANKSTRING = BLANK,
pluck = lib.pluck,
getValidValue = lib.getValidValue,
COMPONENT = 'component',
UNDEFINED,
COMMASTRING = lib.COMMASTRING,
plotEventHandler = lib.plotEventHandler,
showHoverEffectStr = preDefStr.showHoverEffectStr,
SETROLLOVERATTR = 'setRolloverAttr',
DATASET = 'dataset',
configStr = preDefStr.configStr,
animationObjStr = preDefStr.animationObjStr,
getColorCodeString = lib.getColorCodeString,
ROUND = preDefStr.ROUND,
miterStr = preDefStr.miterStr,
BUTT = 'butt',
HUNDREDSTRING = lib.HUNDREDSTRING,
PLOTBORDERCOLOR = 'plotBorderColor',
PLOTGRADIENTCOLOR = 'plotGradientColor',
colorStrings = preDefStr.colors,
SHOWSHADOW = 'showShadow',
math = Math,
mathMax = math.max,
mathMin = math.min,
mathAbs = math.abs,
COLOR_FFFFFF = colorStrings.FFFFFF,
noneStr = 'none',
convertColor = lib.graphics.convertColor,
toRaphaelColor = lib.toRaphaelColor,
FILLMIXDARK10 = '{dark-10}',
COMMASPACE = lib.COMMASPACE,
ROLLOVER = 'DataPlotRollOver',
SETROLLOUTATTR = 'setRolloutAttr',
ROLLOUT = 'DataPlotRollOut',
getFirstValue = lib.getFirstValue,
getDarkColor = lib.graphics.getDarkColor,
win = global.window,
userAgent = win.navigator.userAgent,
doc = win.document,
hasTouch = doc.documentElement.ontouchstart !== undefined,
CLICK_THRESHOLD_PIXELS = lib.CLICK_THRESHOLD_PIXELS,
isIE = /msie/i.test(userAgent) && !win.opera,
TRACKER_FILL = 'rgba(192,192,192,'+ (isIE ? 0.002 : 0.000001) +')',
M = 'M',
L = 'L',
DECIDE_CRISPENING = {
'true': undefined,
'false': 'crisp'
},
EVENTARGS = 'eventArgs',
GROUPID = 'groupId',
POSITION_START = preDefStr.POSITION_START,
POSITION_TOP = preDefStr.POSITION_TOP,
POSITION_MIDDLE = preDefStr.POSITION_MIDDLE,
PLOTFILLCOLOR_STR = preDefStr.PLOTFILLCOLOR_STR,
TOUCH_THRESHOLD_PIXELS = lib.TOUCH_THRESHOLD_PIXELS,
HTP = hasTouch ? TOUCH_THRESHOLD_PIXELS :
CLICK_THRESHOLD_PIXELS,
POINTER = 'pointer',
pluckNumber = lib.pluckNumber,
schedular = lib.schedular;
FusionCharts.register(COMPONENT, [DATASET, 'bullet', {
init : function(datasetJSON) {
var dataSet = this,
chart = dataSet.chart,
components = chart.components,
visible;
if (!datasetJSON) {
return false;
}
dataSet.JSONData = datasetJSON;
dataSet.yAxis = components.scale;
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();
(chart.hasLegend !== false) && dataSet._addLegend();
},
configure : function () {
var dataSet = this,
chart = dataSet.chart,
conf = dataSet.config,
JSONData = dataSet.JSONData,
chartAttr = chart.jsonData.chart,
colorM = chart.components.colorManager,
showplotborder,
plotColor = conf.plotColor = colorM.getColor(PLOTFILLCOLOR_STR),
plotBorderDash = pluckNumber(JSONData.dashed, chartAttr.plotborderdashed),
usePlotGradientColor = pluckNumber(chartAttr.useplotgradientcolor, 1),
plotDashLen,
plotDashGap,
plotBorderThickness,
isRoundEdges,
showHoverEffect,
plotfillAngle,
plotFillAlpha,
plotRadius,
plotFillRatio,
plotgradientcolor,
plotBorderAlpha,
plotBorderColor,
initailPlotBorderDashStyle,
getDashStyle = lib.getDashStyle,
dataStore = dataSet.components.data,
definedGroupPadding,
isBar = chart.isBar,
is3D = chart.is3D,
isStacked = chart.isStacked,
stack100Percent,
targetalpha,
plotAsDot,
targetCapStyle;
conf.targetCapStyle = targetCapStyle = pluck(chartAttr.targetcapstyle, ROUND).toLowerCase();
if ((targetCapStyle !== BUTT) && (targetCapStyle !== ROUND) && (targetCapStyle !== 'square') &&
(targetCapStyle !== 'inherit')) {
conf.targetCapStyle = ROUND;
}
conf.upperLimit = pluckNumber(chartAttr.upperlimit);
conf.lowerLimit = pluckNumber(chartAttr.lowerlimit);
conf.initAnimation = true;
showplotborder = conf.showplotborder = pluckNumber(chartAttr.showplotborder, 0);
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(chartAttr.plotfillcolor, 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 = BLANK);
conf.showPlotBorderOnHover = pluckNumber(chartAttr.showplotborderonhover, 0);
conf.plotBorderAlpha = plotBorderAlpha = pluck(chartAttr.plotborderalpha, plotFillAlpha, HUNDREDSTRING);
conf.plotBorderColor = plotBorderColor = pluck(chartAttr.plotbordercolor,
is3D ? COLOR_FFFFFF : colorM.getColor(PLOTBORDERCOLOR));
conf.plotBorderThickness = plotBorderThickness = showplotborder ?
pluckNumber(chartAttr.plotborderthickness, 0) : 0;
conf.plotBorderDashStyle = initailPlotBorderDashStyle = plotBorderDash ?
getDashStyle(plotDashLen, plotDashGap, plotBorderThickness) : noneStr;
conf.showValue = pluckNumber(JSONData.showvalue, chartAttr.showvalue, 1);
conf.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
conf.showShadow = (isRoundEdges || is3D) ? pluckNumber(chartAttr.showshadow, 1) :
pluckNumber(chartAttr.showshadow, colorM.getColor(SHOWSHADOW));
conf.showHoverEffect = showHoverEffect = pluckNumber(chartAttr.plothovereffect,
chartAttr.showhovereffect, 0);
conf.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.use3DLighting = pluckNumber(chartAttr.use3dlighting, 1);
if (!dataStore) {
dataStore = dataSet.components.data = [];
}
conf.plotAsDot = plotAsDot = pluckNumber(chartAttr.plotasdot, 0);
conf.plotFillPercent = pluckNumber(chartAttr.plotfillpercent, plotAsDot ? 25 : 40);
conf.targetFillPercent = pluckNumber(chartAttr.targetfillpercent, 60);
conf.targetThickness = pluckNumber(chartAttr.targetthickness, 3);
targetalpha = conf.targetalpha = pluckNumber(chartAttr.targetalpha, 100);
conf.targetColor = convertColor(pluck(chartAttr.targetcolor,
colorM.getColor(PLOTFILLCOLOR_STR)), targetalpha);
dataSet._setConfigure();
},
_setConfigure : function (newDataset) {
var dataSet = this,
chart = dataSet.chart,
conf = dataSet.config,
JSONData = dataSet.JSONData,
setDataArr = newDataset || JSONData.data,
setDataLen = setDataArr && setDataArr.length,
categories = chart.config.categories,
catLen = categories && categories.length,
len = (newDataset && newDataset.data.length) || mathMin(catLen, setDataLen),
chartAttr = chart.jsonData.chart,
components = chart.components,
colorM = components.colorManager,
showplotborder = conf.showplotborder,
showPlotBorderOnHover = conf.showPlotBorderOnHover,
plotColor = conf.plotColor,
// showTooltip = pluckNumber(chartAttr.showtooltip, 1),
parseUnsafeString = lib.parseUnsafeString,
tooltipSepChar = parseUnsafeString(pluck(chartAttr.tooltipsepchar, COMMASPACE)),
seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1),
parseTooltext = lib.parseTooltext,
formatedVal,
parserConfig,
setTooltext,
seriesname,
macroIndices,
tempPlotfillAngle,
// toolText,
plotDashLen,
plotDashGap,
plotBorderThickness = conf.plotBorderThickness,
isRoundEdges = conf.isRoundEdges,
showHoverEffect = conf.showHoverEffect,
plotfillAngle = conf.plotFillAngle,
plotFillAlpha,
//plotRadius,
plotFillRatio,
//plotgradientcolor,
plotBorderAlpha = conf.plotBorderAlpha,
plotBorderDashStyle,
initailPlotBorderDashStyle = conf.plotBorderDashStyle,
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,
toolTipValue,
setDisplayValue,
isBar = chart.isBar,
is3D = chart.is3D,
setDataDashed,
setDataPlotDashLen,
setDataPlotDashGap,
i,
maxValue = -Infinity,
minValue = Infinity,
numberFormatter = chart.components.numberFormatter,
target,
hoverAttr,
outAttr,
targetHoverThickness,
targetHoverColor,
targetHoverAlpha,
hasTargetHoverMix,
setTooltextTarget,
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,26,27];
parserConfig = {
formattedValue : formatedVal,
targetValue : config.target,
targetDataValue : config.toolTipValueTarget
};
toolText = parseTooltext(setTooltext, macroIndices,
parserConfig, setData, chartAttr, JSONData);
}
else {
if (seriesNameInTooltip) {
seriesname = getFirstValue(JSONData && JSONData.seriesname);
}
toolText = seriesname ? seriesname + tooltipSepChar : BLANK;
toolText += config.label ? config.label + tooltipSepChar : BLANK;
}
}
return toolText;
};
if (!dataStore) {
dataStore = dataSet.components.data = [];
}
// Parsing the attributes and values at set level.
for (i = 0; i < len; i++) {
if (newDataset) {
setData = (newDataset && newDataset.data[i]);
}
else {
setData = setDataArr[i];
}
dataObj = dataStore[i];
config = dataObj && dataObj.config;
if (!dataObj) {
dataObj = dataStore[i] = {};
}
if (!dataObj.config) {
config = dataStore[i].config = {};
}
config.showValue = pluckNumber(setData.showvalue, conf.showValues);
config.valuePadding = pluckNumber(chartAttr.valuepadding, 2);
config.setValue = setValue = numberFormatter.getCleanValue(setData.value);
config.target = target = numberFormatter.getCleanValue(setData.target);
config.setLink = pluck(setData.link);
config.toolTipValue = toolTipValue = numberFormatter.dataLabels(setValue);
config.toolTipValueTarget = numberFormatter.dataLabels(target);
config.setDisplayValue = setDisplayValue = parseUnsafeString(setData.displayvalue);
config.displayValue = pluck(setData.label, setDisplayValue, toolTipValue);
setDataDashed = pluckNumber(setData.dashed);
setDataPlotDashLen = pluckNumber(setData.dashlen, plotDashLen);
setDataPlotDashGap = plotDashGap = pluckNumber(setData.dashgap, plotDashGap);
maxValue = mathMax(maxValue, setValue, target);
minValue = mathMin(minValue, setValue, target);
config.plotBorderDashStyle = plotBorderDashStyle = setDataDashed === 1 ?
getDashStyle(setDataPlotDashLen, setDataPlotDashGap, plotBorderThickness) :
(setDataDashed === 0 ? noneStr : 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,
plotFillAlpha,
plotFillRatio,
plotfillAngle,
isRoundEdges,
conf.plotBorderColor,
plotBorderAlpha.toString(),
(isBar ? 1 : 0),
(is3D ? true : false)
);
//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, conf.plotgradientcolor);
!hoverGradientColor && (hoverGradientColor = BLANK);
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, chartAttr.plotfillhovercolor,
conf.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 = getDarkColor(hoverColor, 90);
}
// 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),
false
),
config.setPlotRolloutAttr = {
fill: !is3D ? toRaphaelColor(colorArr[0])
: [toRaphaelColor(colorArr[0]), !conf.use3DLighting],
stroke: showplotborder && toRaphaelColor(colorArr[1]),
'stroke-width': plotBorderThickness,
'stroke-dasharray': plotBorderDashStyle
};
config.setPlotRolloverAttr = {
fill: !is3D ? toRaphaelColor(hoverColorArr[0])
: [toRaphaelColor(hoverColorArr[0]), !conf.use3DLighting],
stroke: toRaphaelColor(hoverColorArr[1]),
'stroke-width': showPlotBorderOnHover ? (hoverBorderThickness || 1) : hoverBorderThickness,
'stroke-dasharray': hoverDashStyle
};
}
if (showHoverEffect !== 0 && (showHoverEffect || chartAttr.targethovercolor ||
chartAttr.targethoveralpha || chartAttr.targethoveralpha === 0 ||
chartAttr.targethoverthickness || chartAttr.targethoverthickness === 0)) {
showHoverEffect = true;
hoverAttr = {};
outAttr = {};
targetHoverThickness = pluckNumber(chartAttr.targethoverthickness, conf.targetThickness + 2);
if (conf.targetThickness !== targetHoverThickness) {
hoverAttr['stroke-width'] = targetHoverThickness;
outAttr['stroke-width'] = conf.targetThickness;
}
targetHoverColor = pluck(chartAttr.targethovercolor, FILLMIXDARK10);
targetHoverAlpha = pluckNumber(chartAttr.targethoveralpha, conf.targetalpha);
if (targetHoverThickness) {
outAttr.stroke = conf.targetColor;
hasTargetHoverMix = /\{/.test(targetHoverColor);
hoverAttr.stroke = convertColor(hasTargetHoverMix ?
colorM.parseColorMix(pluck(chartAttr.targetcolor, plotColor), targetHoverColor)[0] :
targetHoverColor, targetHoverAlpha);
}
//showHoverAnimation = !!pluckNumber(chartAttr.showhoveranimation, 1);
config.tagetHoverAttr = hoverAttr;
config.targetOutAttr = outAttr;
}
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,7,26,27];
// parserConfig = {
// formattedValue : formatedVal,
// targetValue : config.target,
// targetDataValue : config.toolTipValueTarget
// };
// toolText = parseTooltext(setTooltext, macroIndices,
// parserConfig, setData, chartAttr, JSONData);
// }
// else {
// if (seriesNameInTooltip) {
// seriesname = getFirstValue(JSONData && JSONData.seriesname);
// }
// toolText = seriesname ? seriesname + tooltipSepChar : BLANK;
// toolText += label ? label + tooltipSepChar : BLANK;
// }
// }
config.toolText = getTooltext(setTooltext);
config.setTooltext = config.toolText;
tempPlotfillAngle && (plotfillAngle = tempPlotfillAngle);
setTooltextTarget = getValidValue(parseUnsafeString(pluck(setData.tooltexttarget,
JSONData.targettooltext, chartAttr.targettooltext)));
config.toolTextTarget = getTooltext(setTooltextTarget);
}
conf.maxValue = maxValue;
conf.minValue = minValue;
},
_manageSpace : function (availableHeight) {
var dataSet = this,
conf = dataSet.config,
JSONData = dataSet.JSONData,
setDataArr = JSONData.data,
dataStore = dataSet.components.data,
setData,
dataObj,
chart = dataSet.chart,
captionConfig = chart.components.caption.config,
// components = dataSet.components,
chartConfig = chart.config,
// datasetConfig = dataSet.config,
smartLabel = chart.linkedItems.smartLabel,
// canvasWidth = chartConfig.canvasWidth,
smartDataLabel, extraSpace,
style = chartConfig.dataLabelStyle,
lineHeight = pluckNumber(parseInt(style.lineHeight, 10), 12),
maxAllowedHeight = availableHeight,
valuePadding = conf.valuePadding,
// valuePaddingWithRadius,
heightUsed = 0,
// heightReducedBottom = 0, heightReducedTop = 0,
// tickDimension = 0,
i = 0,
len = 1,
//pointerOnOpp = datasetConfig.pointerOnOpp,
config;
setData = setDataArr[i];
dataObj = dataStore[i];
config = dataObj && dataObj.config;
smartLabel.useEllipsesOnOverflow(chartConfig.useEllipsesWhenOverflow);
smartLabel.setStyle(style);
for (; i < len; i += 1) {
if (conf.showValue) {
smartDataLabel = smartLabel.getOriSize(config.toolTipValue);
//special fix for space string
/** @todo will be removed when smartLabel will be able to handle it */
if (config.toolTipValue === BLANK) {
smartDataLabel = {
height : lineHeight
};
}
if (smartDataLabel.height > 0) {
heightUsed = smartDataLabel.height + valuePadding;
}
if (heightUsed > maxAllowedHeight) {
extraSpace = heightUsed - maxAllowedHeight;
heightUsed = maxAllowedHeight;
}
}
}
captionConfig.widgetValueHeight = heightUsed;
conf.heightUsed = heightUsed;
return {
top : 0,
bottom : heightUsed
};
},
_manageSpaceHorizontal : function (availableWidth) {
var dataSet = this,
conf = dataSet.config,
JSONData = dataSet.JSONData,
setDataArr = JSONData.data,
dataStore = dataSet.components.data,
setData,
dataObj,
chart = dataSet.chart,
// components = dataSet.components,
chartConfig = chart.config,
// datasetConfig = dataSet.config,
smartLabel = chart.linkedItems.smartLabel,
// canvasWidth = chartConfig.canvasWidth,
smartDataLabel, extraSpace,
style = chartConfig.dataLabelStyle,
lineHeight = pluckNumber(parseInt(style.lineHeight, 10), 12),
maxAllowedWidth = availableWidth,
valuePadding = conf.valuePadding,
// valuePaddingWithRadius,
widthUsed = 0,
i = 0,
len = 1,
config;
setData = setDataArr[i];
dataObj = dataStore[i];
config = dataObj && dataObj.config;
smartLabel.useEllipsesOnOverflow(chartConfig.useEllipsesWhenOverflow);
smartLabel.setStyle(style);
for (; i < len; i += 1) {
//config = components[i].config;
if (config && config.displayValue !== BLANKSTRING && config.displayValue !== UNDEFINED) {
if (conf.showValue) {
smartDataLabel = smartLabel.getOriSize(config.displayValue);
//special fix for space string
/** @todo will be removed when smartLabel will be able to handle it */
if (config.displayValue === BLANK) {
smartDataLabel = {
height : lineHeight
};
}
if (smartDataLabel.height > 0) {
widthUsed = smartDataLabel.width + valuePadding + 2;
}
if (widthUsed > maxAllowedWidth) {
extraSpace = widthUsed - maxAllowedWidth;
widthUsed = maxAllowedWidth;
}
}
}
}
conf.widthUsed = widthUsed;
return {
top : 0,
right : widthUsed
};
},
updateData : function (dataObj, index, draw) {
var dataSet = this,
conf = dataSet.config,
prevMax = conf.maxValue,
prevMin = conf.prevMin,
chart = dataSet.chart,
drawManager = dataSet.groupManager || dataSet,
chartComponents = chart.components,
scale = chartComponents.scale;
dataSet._setConfigure(dataObj, index);
dataSet.setMaxMin();
if (conf.maxValue !== prevMax || conf.minValue !== prevMin) {
dataSet.maxminFlag = true;
}
if (draw) {
chart._setAxisLimits();
scale.draw();
drawManager.draw();
}
},
// Get the max and min of data during real time update.
setMaxMin : function () {
var dataSet = this,
dataStore = dataSet.components.data,
conf = dataSet.config,
i,
config,
len = dataStore.length,
maxValue = -Infinity,
minValue = +Infinity;
for (i = 0; i < len; i++) {
if (!dataStore[i]) {
continue;
}
config = dataStore[i].config;
maxValue = mathMax(maxValue, config.setValue, config.target);
minValue = mathMin(minValue, config.setValue, config.target);
}
conf.maxValue = maxValue;
conf.minValue = minValue;
},
draw : function () {
var dataSet = this,
chart = dataSet.chart,
components = chart.components,
chartAttr = chart.jsonData.chart,
chartConfig = chart.config,
chartGraphics = chart.graphics,
paper = components.paper,
canvas = components.canvas,
graphics = canvas.graphics,
config = canvas.config,
canvasElement = graphics.canvasElement,
canvasLeft = chartConfig.canvasLeft,
canvasRight = chartConfig.canvasRight,
canvasTop = chartConfig.canvasTop,
canvasBottom = chartConfig.canvasBottom,
canvasWidth = chartConfig.canvasWidth,
canvasHeight = chartConfig.canvasHeight,
parentContainer = chartGraphics.datasetGroup,
shadow = config.shadow,
attr,
scale = components.scale,
min = scale.getLimit().min,
max = scale.getLimit().max,
isHorizontal = chart.isHorizontal,
animationObj = chart.get(configStr, animationObjStr),
animType = animationObj.animType,
animObj = animationObj.animObj,
dummyObj = animationObj.dummyObj,
animationDuration = animationObj.duration,
getRectXY = function (minValue, maxValue) {
if (!isHorizontal) {
return {
x: canvasLeft,
y: canvasTop + (canvasHeight - (maxValue * canvasHeight / (max - min))),
width: canvasWidth,
height: (maxValue - minValue) * canvasHeight / (max - min)
};
}
else if (isHorizontal) {
return {
x: canvasLeft + ((minValue * canvasWidth / (max - min))),
y: canvasTop,
width: (maxValue - minValue) * canvasWidth / (max - min),
height: canvasHeight
};
}
},
angle,
gaugeFillMix,
gaugeFillRatio,
paletteIndex,
colorRangeGetter,
colorArray,
colorM = chart.components.colorManager,
gaugeBorderColor,
gaugeBorderAlpha,
showShadow,
showGaugeBorder,
gaugeBorderThickness,
colorObj,
i,
len,
xyObj,
color,
borderColor,
crColor,
crAlpha,
borderAlpha,
shadowAlpha,
colorRangeElemsLength;
angle = isHorizontal ? 270 : 180;
config.colorRangeFillMix = gaugeFillMix = lib.getFirstDefinedValue(chartAttr.colorrangefillmix,
chartAttr.gaugefillmix, chart.colorRangeFillMix,
'{light-10},{dark-10},{light-10},{dark-10}');
config.colorRangeFillRatio = gaugeFillRatio = lib.getFirstDefinedValue(chartAttr.colorrangefillratio,
chartAttr.gaugefillratio, chart.colorRangeFillRatio, chartAttr.gaugefillratio,
'0,10,80,10');
paletteIndex = 0;
config.colorRangeGetter = colorRangeGetter = components.colorRange;
config.colorArray = colorArray = colorRangeGetter &&
colorRangeGetter.getColorRangeArr(min, max);
gaugeBorderColor = pluck(chartAttr.colorrangebordercolor,
chartAttr.gaugebordercolor, '{dark-20}');
gaugeBorderAlpha = pluckNumber(chartAttr.colorrangeborderalpha,
chartAttr.gaugeborderalpha, 100);
showShadow = pluckNumber(chartAttr.showshadow, 1);
showGaugeBorder = pluckNumber(chartAttr.showgaugeborder, chartAttr.showcolorrangeborder, 0);
config.colorRangeBorderThickness = gaugeBorderThickness =
showGaugeBorder ? pluckNumber(chartAttr.colorrangeborderthickness,
chartAttr.gaugeborderthickness, 2) : 0;
len = colorArray && colorArray.length;
if (!canvasElement) {
graphics.canvasElement = canvasElement = {};
canvasElement.colorRangeElems = [];
}
else {
colorRangeElemsLength = canvasElement.colorRangeElems.length;
for (i = colorRangeElemsLength; i > len; i -= 1) {
canvasElement.colorRangeElems[i-1].hide();
canvasElement.colorRangeElems[i-1].shadow({opacity: 0});
}
}
for (i = 0; i < len; i += 1) {
colorObj = colorArray[i],
xyObj = getRectXY((colorObj.minvalue - min), (colorObj.maxvalue - min));
colorObj.x = xyObj.x;
colorObj.y = xyObj.y;
colorObj.width = xyObj.width;
colorObj.height = xyObj.height;
color = colorObj.code;
borderColor = convertColor(getColorCodeString(pluck(colorObj.bordercolor, color), gaugeBorderColor),
pluckNumber(colorObj.borderalpha, gaugeBorderAlpha));
shadow = showShadow ? (Math.max(colorObj.alpha, gaugeBorderAlpha) / 100) : null;
//create the shadow element
crColor = colorM.parseColorMix(colorObj.code, gaugeFillMix);
crAlpha = colorM.parseAlphaList(colorObj.alpha, crColor.length);
borderAlpha = pluckNumber(colorObj.borderAlpha, gaugeBorderAlpha);
shadowAlpha = crAlpha.split(COMMASTRING);
shadowAlpha = mathMax.apply(Math, shadowAlpha);
shadowAlpha = mathMax(gaugeBorderThickness && borderAlpha || 0, shadowAlpha);
attr = {
x: xyObj.x,
y: xyObj.y,
width: xyObj.width,
height: xyObj.height,
r: 0,
'stroke-width': gaugeBorderThickness,
stroke: borderColor,
'fill': toRaphaelColor({
FCcolor: {
color: crColor.toString(),
ratio: gaugeFillRatio,
alpha: crAlpha,
angle: angle
}
})
};
if (!canvasElement.colorRangeElems[i]) {
canvasElement.colorRangeElems[i] = paper.rect(attr, parentContainer);
}
else {
canvasElement.colorRangeElems[i].show();
attr = {
'stroke-width': gaugeBorderThickness,
stroke: borderColor,
'fill': toRaphaelColor({
FCcolor: {
color: crColor.toString(),
ratio: gaugeFillRatio,
alpha: crAlpha,
angle: angle
}
})
};
canvasElement.colorRangeElems[i].animateWith(dummyObj, animObj, {
x: xyObj.x,
y: xyObj.y,
width: xyObj.width,
height: xyObj.height,
r: 0
}, animationDuration, animType);
canvasElement.colorRangeElems[i].attr(attr);
}
canvasElement.colorRangeElems[i]
.shadow({
apply: showShadow,
opacity: (shadowAlpha / 100)
});
}
chartConfig.gaugeStartX = canvasLeft;
chartConfig.gaugeEndX = canvasRight;
chartConfig.gaugeStartY = canvasTop;
chartConfig.gaugeEndY = canvasBottom;
chartConfig.gaugeCenterX = canvasLeft + (canvasWidth * 0.5);
chartConfig.gaugeCenterY = canvasTop + (canvasHeight * 0.5);
chartConfig.gaugeRadius = canvasWidth * 0.5;
dataSet.drawPlot();
},
drawPlot: function () {
var dataSet = this,
JSONData = dataSet.JSONData,
chartAttr = dataSet.chart.jsonData.chart,
conf = dataSet.config,
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,
jobList = chart.getJobList(),
chartConfig = chart.config,
canvasLeft = chartConfig.canvasLeft,
canvasRight = chartConfig.canvasRight,
canvasTop = chartConfig.canvasTop,
canvasBottom = chartConfig.canvasBottom,
canvasHeight = chartConfig.canvasHeight,
canvasWidth = chartConfig.canvasWidth,
paper = chart.components.paper,
scale = chart.components.scale,
parentContainer = chart.graphics.datasetGroup,
xPos,
yPos,
crispBox,
layers = chart.graphics,
parseUnsafeString = lib.parseUnsafeString,
getValidValue = lib.getValidValue,
R = lib.Raphael,
showTooltip = conf.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,
setTooltext,
setElement,
// hotElement,
setLink,
setValue,
eventArgs,
displayValue,
groupId,
config,
setPlotRolloutAttr,
setPlotRolloverAttr,
yMax = scale.max,
yMin = scale.min,
isAllPositiveZero = yMax > 0 && yMin >= 0,
isAllNegativeZero = yMax <= 0 && yMin < 0,
isPositive,
yBase = isAllNegativeZero ? yMax : isAllPositiveZero ? yMin : 0,
yBasePos = scale.yBasePos = scale.getAxisPosition(yBase),
heightBase = 0,
widthBase = 0,
showShadow = conf.showShadow,
plotBorderThickness = conf.plotBorderThickness,
plotRadius = conf.plotRadius,
container = dataSet.graphics.container,
trackerContainer = dataSet.graphics.trackerContainer,
targetContainer = dataSet.graphics.targetContainer,
trackerTargetContainer = dataSet.graphics.trackerTargetContainer,
dataLabelContainer = dataSet.graphics.dataLabelContainer,
shadowContainer = dataSet.graphics.shadowContainer,
shadowTargetContainer = dataSet.graphics.shadowTargetContainer,
trackerLayer = layers.trackerGroup,
colorArr,
plotBorderDashStyle,
animFlag = true,
isNegative = false,
targetPath,
targetLength,
startX,
endX,
startY,
endY,
initialColumnWidth,
dataLabelsLayer = layers.datalabelsGroup,
style = chart.config.dataLabelStyle,
heightUsed = conf.heightUsed,
lineHeight,
labelBBox,
labelWidth,
isNewElem,
isNewTargetElem,
lowerLimit = conf.lowerLimit,
base,
trackerConfig,
// css = {
// fontFamily: style.fontFamily,
// fontSize: style.fontSize,
// lineHeight: style.lineHeight,
// fontWeight: style.fontWeight,
// fontStyle: style.fontStyle
// },
showHoverEffect = conf.showHoverEffect,
//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 (elem) {
return function (data) {
var ele = this;
if (ele.data(showHoverEffectStr) !== 0) {
elem.attr(ele.data(SETROLLOVERATTR));
}
plotEventHandler.call(ele, chart, data, ROLLOVER);
};
},
//Fired on mouse-out over the hot elements.
rolloutResponseSetter = function (elem) {
return function (data) {
var ele = this;
if (ele.data(showHoverEffectStr) !== 0) {
elem.attr(ele.data(SETROLLOUTATTR));
}
plotEventHandler.call(ele, chart, data, ROLLOUT);
};
},
//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();
trackerContainer.hide();
shadowContainer.hide();
dataLabelContainer && dataLabelContainer.hide();
dataSet._conatinerHidden = true;
}
};
/*
* Creating a container group for the graphic element of bar plots if
* not present and attaching it to its parent group.
*/
if (!container) {
container = dataSet.graphics.container = paper.group('bar', parentContainer);
// 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.hide();
}
}
if (!dataLabelContainer) {
dataLabelContainer = dataSet.graphics.dataLabelContainer =
paper.group('datalabel', dataLabelsLayer);
}
if (!targetContainer) {
targetContainer = dataSet.graphics.targetContainer =
paper.group('target', 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) {
targetContainer.hide();
}
}
/*
* Creating the hot element container group for the column plots if not present
* and attaching it its parent group.
*/
if (!trackerContainer) {
trackerContainer = dataSet.graphics.trackerContainer = paper.group('bar-hot', trackerLayer);
if (!visible) {
trackerContainer.hide();
}
}
if (!trackerTargetContainer) {
trackerTargetContainer = dataSet.graphics.trackerTargetContainer =
paper.group('target-hot', trackerLayer);
if (!visible) {
trackerTargetContainer.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('shadow', 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 (!shadowTargetContainer) {
// Always sending the shadow group to the back of the plots group.
shadowTargetContainer = dataSet.graphics.shadowTargetContainer =
paper.group('shadow', parentContainer).toBack();
// Clipping the group so that the shadow do not come out of the canvas area when given thick border.
// if (!shadowTargetContainer.attrs['clip-rect'] && !isScroll) {
// shadowTargetContainer.attr({
// 'clip-rect': elements['clip-canvas']
// });
// }
if (!visible) {
shadowTargetContainer.hide();
}
}
len = mathMin(catLen, dataSetLen);
// Create plot elements.
for (i = 0; i < 1; i++) {
setData = setDataArr[i];
dataObj = dataStore[i];
config = dataObj && dataObj.config;
trackerConfig = dataObj.trackerConfig = {};
setValue = config.setValue;
isPositive = setValue >= 0;
(setValue < 0) && (isNegative = true);
setLink = config.setLink;
colorArr = config.colorArr;
isNewElem = false;
isNewTargetElem = false;
// 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 (!chart.isHorizontal) {
initialColumnWidth = (conf.plotFillPercent / 100) * canvasWidth;
xPos = (mathAbs(canvasLeft + canvasRight) / 2) - (initialColumnWidth / 2);
if (conf.plotAsDot) {
yPos = scale.getAxisPosition(setValue) - (initialColumnWidth / 2);
height = initialColumnWidth;
}
else{
base = lowerLimit && (lowerLimit <= setValue) &&
(scale.config.axisRange.min >= 0) ? lowerLimit : 0;
yBasePos = scale.getAxisPosition(base);
yPos = isNegative ? scale.getAxisPosition(0) : scale.getAxisPosition(setValue);
height = isNegative ? scale.getAxisPosition(setValue) - scale.getAxisPosition(0) :
scale.getAxisPosition(lowerLimit && (lowerLimit <= setValue) &&
(scale.config.axisRange.min >= 0) ? lowerLimit : 0) - yPos;
}
crispBox = R.crispBound(xPos, yPos, initialColumnWidth, height, plotBorderThickness);
xPos = crispBox.x;
yPos = crispBox.y;
columnWidth = crispBox.width;
height = crispBox.height;
// Setting the final tooltext.
toolText = config.toolText === BLANK ? config.toolTipValue : config.toolText;
plotBorderDashStyle = config.plotBorderDashStyle;
// Setting the event arguments.
trackerConfig.eventArgs = {
link: setLink,
value: setValue,
displayValue: displayValue,
toolText: toolText
};
setPlotRolloutAttr = config.setPlotRolloutAttr;
setPlotRolloverAttr = config.setPlotRolloverAttr;
/*
* 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: true,
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 + height;
dataObj._height = height;
dataObj._width = columnWidth;
if (setValue !== null) {
/*
* 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, {
y: yPos,
height: height || 1
}, animationDuration, animType);
if (animationDuration) {
// animFlag is set to false so that initAnimCallBack is called only once for
// each dataset.
animFlag = false;
}
config.elemCreated = true;
}
else {
dataObj.graphics.element.show();
attr = {
x: xPos,
y: yPos,
width: columnWidth,
height: height || 1,
r: plotRadius
};
setElement = dataObj.graphics.element;
setElement.animateWith(dummyObj, animObj, attr,
animationDuration, animType, (animFlag && animCallBack));
setElement.attr({
ishot: true,
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,
cursor: setLink ? POINTER : BLANK,
stroke: TRACKER_FILL,
'stroke-width': plotBorderThickness,
fill: TRACKER_FILL,
ishot: true,
visibility: visible
};
/*
* If the tooltips are not present then they are created over the hot element,
* else only attributes are set for the existing tooltips.
*/
// if (!dataObj.graphics.hotElement) {
// hotElement = dataObj.graphics.hotElement = paper.rect(attr, trackerContainer);
// isNewElem = true;
// }
// else {
// dataObj.graphics.hotElement.show();
// dataObj.graphics.hotElement.attr(attr);
// }
}
// hotElement = dataObj.graphics.hotElement;
// (hotElement || setElement)
// .data(EVENTARGS, eventArgs)
// .data(GROUPID, groupId)
// .data(showHoverEffectStr, showHoverEffect)
// .data(SETROLLOVERATTR, setPlotRolloverAttr)
// .data(SETROLLOUTATTR, setPlotRolloutAttr)
// .tooltip(toolText);
// if (isNewElem) {
// (hotElement || setElement)
// .click(clickFunc)
// .hover(
// rolloverResponseSetter(setElement),
// rolloutResponseSetter(setElement)
// );
// }
}
else {
dataObj.graphics.element && dataObj.graphics.element.hide();
dataObj.graphics.hotElement && dataObj.graphics.hotElement.hide();
}
//------------------------------------------------------------------------------------
if (config.target) {
setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
JSONData.targettooltext, chartAttr.targettooltext)));
toolText = config.toolTextTarget === BLANK ?
config.toolTipValueTarget : config.toolTextTarget;
targetLength = (conf.targetFillPercent / 100) * canvasWidth;
startX = ((canvasLeft + canvasRight) / 2) - (targetLength / 2);
endX = startX + targetLength;
startY = endY = scale.getAxisPosition(config.target);
targetPath = [M, startX, startY, L, endX, endY];
attr = {
stroke : conf.targetColor,
'stroke-width': conf.targetThickness,
'stroke-linecap': conf.targetCapStyle,
ishot: true,
'shape-rendering': DECIDE_CRISPENING[(3 < 1)]
};
setElement = dataObj.graphics.targetElement;
if (!setElement) {
setElement = dataObj.graphics.targetElement = paper.path(targetPath, targetContainer)
.attr(attr);
isNewTargetElem = true;
}
else {
dataObj.graphics.targetElement.show();
attr = {
path: targetPath,
stroke : conf.targetColor,
'stroke-width': conf.targetThickness,
'stroke-linecap': conf.targetCapStyle,
ishot: true,
'shape-rendering': DECIDE_CRISPENING[(3 < 1)]
};
setElement.animateWith(dummyObj, animObj, attr,
animationDuration, animType);
}
if (isNewTargetElem) {
setElement
.click(clickFunc)
.hover(
rolloverResponseSetter(setElement),
rolloutResponseSetter(setElement)
);
}
setElement
.shadow({opacity : showShadow}, shadowContainer)
.data('BBox', crispBox)
.data(EVENTARGS, eventArgs)
.data(GROUPID, groupId)
.data(showHoverEffectStr, showHoverEffect)
.data(SETROLLOVERATTR, config.tagetHoverAttr)
.data(SETROLLOUTATTR, config.targetOutAttr);
if (showTooltip) {
setElement.tooltip(toolText);
}
else {
setElement.tooltip(false);
}
}
else {
dataObj.graphics.targetElement && dataObj.graphics.targetElement.hide();
}
lineHeight = parseInt(style.lineHeight, 10);
yPos = lineHeight > heightUsed ? (chartConfig.height - chartConfig.marginBottom - heightUsed) +
lineHeight/2 : chartConfig.height - chartConfig.marginBottom - lineHeight/2;
yPos -= chartConfig.borderWidth;
yPos -= (chart._manageActionBarSpace &&
chart._manageActionBarSpace(config.availableHeight * 0.225) || {}).bottom;
if ((displayValue !== BLANKSTRING) && (displayValue !== UNDEFINED) && conf.showValue) {
attr = {
text: displayValue,
'text-anchor': POSITION_MIDDLE,
x: canvasWidth/2 + canvasLeft,
y: yPos,
'vertical-align': POSITION_MIDDLE,
fill: style.color,
direction: config.textDirection,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
};
if (!dataObj.graphics.label) {
dataObj.graphics.label = paper.text(attr, dataLabelContainer);
}
else {
dataObj.graphics.label.show();
dataObj.graphics.label.animateWith(dummyObj, animObj, {
x: canvasWidth/2 + canvasLeft,
y: yPos
}, animationDuration, animType);
dataObj.graphics.label
.attr({text: displayValue,
'text-anchor': POSITION_MIDDLE,
'vertical-align': POSITION_MIDDLE,
fill: style.color,
direction: config.textDirection,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
});
}
// Adjusting the chart label if goes out side the chart area
// we try to keep the label inside viewport
labelBBox = dataObj.graphics.label.getBBox();
if (labelBBox.x + chartConfig.marginLeft < 0) {
labelWidth = labelBBox.width - chartConfig.marginLeft;
if(chartConfig.width < labelWidth) {
labelWidth = chartConfig.width - chartConfig.marginLeft;
}
attr = {
x : labelWidth/2
};
dataObj.graphics.label.animateWith(dummyObj, animObj, attr,
animationDuration, animType);
}
}
else {
dataObj.graphics.label && dataObj.graphics.label.hide() &&
dataObj.graphics.label.attr({'text-bound': []});
}
}
else {
height = (conf.plotFillPercent / 100) * canvasHeight;
yPos = (mathAbs(canvasTop + canvasBottom) / 2) - (height / 2);
if (conf.plotAsDot) {
xPos = scale.getAxisPosition(setValue) - (height / 2);
initialColumnWidth = height;
}
else {
base = lowerLimit && (lowerLimit <= setValue) &&
(scale.config.axisRange.min >= 0) ? lowerLimit : 0;
xPos = isNegative ? scale.getAxisPosition(setValue) : scale.getAxisPosition(base);
initialColumnWidth = isNegative ? scale.getAxisPosition(0) - scale.getAxisPosition(setValue)
: scale.getAxisPosition(setValue) - scale.getAxisPosition(base);
}
crispBox = R.crispBound(xPos, yPos, initialColumnWidth, height, plotBorderThickness);
xPos = crispBox.x;
yPos = crispBox.y;
columnWidth = crispBox.width;
height = crispBox.height;
// Setting the final tooltext.
toolText = config.toolText === BLANK ? config.toolTipValue : config.toolText;
plotBorderDashStyle = config.plotBorderDashStyle;
// Setting the event arguments.
trackerConfig.eventArgs = {
link: setLink,
value: setValue,
displayValue: displayValue,
toolText: !toolText ? '' : toolText
};
setPlotRolloutAttr = config.setPlotRolloutAttr;
setPlotRolloverAttr = config.setPlotRolloverAttr;
if (!animationDuration) {
widthBase = columnWidth;
}
// Setting the attributes for plot drawing.
attr = {
x: xPos,
y: yPos,
width: widthBase || 1,
height: height,
r: plotRadius,
ishot: true,
fill: toRaphaelColor(colorArr[0]),
stroke: toRaphaelColor(colorArr[1]),
'stroke-width': plotBorderThickness,
'stroke-dasharray': plotBorderDashStyle,
'stroke-linejoin': miterStr,
'visibility': visible
};
if (setValue !== null) {
/*
* 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, {
width: columnWidth || 1
}, animationDuration, animType);
if (animationDuration) {
// animFlag is set to false so that initAnimCallBack is called only once
// for each dataset.
animFlag = false;
}
config.elemCreated = true;
}
else {
dataObj.graphics.element.show();
attr = {
x: xPos,
y: yPos,
width: columnWidth,
height: height || 1,
r: plotRadius
};
setElement = dataObj.graphics.element;
setElement.animateWith(dummyObj, animObj, attr,
animationDuration, animType, (animFlag && animCallBack));
setElement.attr({
ishot: true,
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,
cursor: setLink ? POINTER : BLANK,
stroke: TRACKER_FILL,
'stroke-width': plotBorderThickness,
fill: TRACKER_FILL,
ishot: true,
visibility: visible
};
/*
* If the tooltips are not present then they are created over the hot element,
* else only attributes are set for the existing tooltips.
*/
// if (!dataObj.graphics.hotElement) {
// hotElement = dataObj.graphics.hotElement = paper.rect(attr, trackerContainer);
// isNewElem = true;
// }
// else {
// dataObj.graphics.hotElement.show();
// dataObj.graphics.hotElement.attr(attr);
// }
}
// hotElement = dataObj.graphics.hotElement;
// (hotElement || setElement)
// .data(EVENTARGS, eventArgs)
// .data(GROUPID, groupId)
// .data(showHoverEffectStr, showHoverEffect)
// .data(SETROLLOVERATTR, setPlotRolloverAttr)
// .data(SETROLLOUTATTR, setPlotRolloutAttr)
// .tooltip(toolText);
// if (isNewElem) {
// (hotElement || setElement)
// .click(clickFunc)
// .hover(
// rolloverResponseSetter(setElement),
// rolloutResponseSetter(setElement)
// );
// }
}
else {
dataObj.graphics.element && dataObj.graphics.element.hide();
dataObj.graphics.hotElement && dataObj.graphics.hotElement.hide();
}
//------------------------------------------------------------------------------------
if (config.target) {
setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
JSONData.targettooltext, chartAttr.targettooltext)));
toolText = config.toolTextTarget === BLANK ?
config.toolTipValueTarget : config.toolTextTarget;
targetLength = (conf.targetFillPercent / 100) * canvasHeight;
startX = endX = scale.getAxisPosition(config.target);
startY = ((canvasTop + canvasBottom) / 2) - (targetLength / 2);
endY = startY + targetLength;
targetPath = [M, startX, startY, L, endX, endY];
attr = {
stroke : conf.targetColor,
'stroke-width': conf.targetThickness,
'stroke-linecap': conf.targetCapStyle,
ishot: true,
'shape-rendering': DECIDE_CRISPENING[(3 < 1)]
};
setElement = dataObj.graphics.targetElement;
if (!setElement) {
setElement = dataObj.graphics.targetElement = paper.path(targetPath, targetContainer)
.attr(attr);
isNewTargetElem = true;
}
else {
dataObj.graphics.targetElement.show();
attr = {
path: targetPath,
stroke : conf.targetColor,
'stroke-width': conf.targetThickness,
'stroke-linecap': conf.targetCapStyle,
ishot: true,
'shape-rendering': DECIDE_CRISPENING[(3 < 1)]
};
setElement.animateWith(dummyObj, animObj, attr,
animationDuration, animType);
}
if (isNewTargetElem) {
setElement
.click(clickFunc)
.hover(
rolloverResponseSetter(setElement),
rolloutResponseSetter(setElement)
);
}
setElement
.shadow({opacity : showShadow}, shadowContainer)
.data('BBox', crispBox)
.data(EVENTARGS, eventArgs)
.data(GROUPID, groupId)
.data(showHoverEffectStr, showHoverEffect)
.data(SETROLLOVERATTR, config.tagetHoverAttr)
.data(SETROLLOUTATTR, config.targetOutAttr);
if (showTooltip) {
setElement.tooltip(toolText);
}
else {
setElement.tooltip(false);
}
}
else {
dataObj.graphics.targetElement && dataObj.graphics.targetElement.hide();
}
lineHeight = parseInt(style.lineHeight, 10);
yPos = (canvasTop + canvasHeight) * 0.5;
if ((displayValue !== BLANKSTRING) && (displayValue !== UNDEFINED) && conf.showValue) {
attr = {
text: displayValue,
'text-anchor': POSITION_START,
x: canvasRight + conf.valuePadding + 2,
y: yPos,
'vertical-align': POSITION_TOP,
fill: style.color,
direction: config.textDirection,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
};
if (!dataObj.graphics.label) {
dataObj.graphics.label = paper.text(attr, dataLabelContainer);
}
else {
dataObj.graphics.label.show();
dataObj.graphics.label.animateWith(dummyObj, animObj, {
x: canvasRight + conf.valuePadding + 2,
y: yPos
}, animationDuration, animType);
dataObj.graphics.label
.attr({
text: displayValue,
'text-anchor': POSITION_START,
'vertical-align': POSITION_TOP,
fill: style.color,
direction: config.textDirection,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
});
}
// Adjusting the chart label if goes out side the chart area
// we try to keep the label inside viewport
labelBBox = dataObj.graphics.label.getBBox();
if (labelBBox.x + chartConfig.marginLeft < 0) {
labelWidth = labelBBox.width - chartConfig.marginLeft;
if(chartConfig.width < labelWidth) {
labelWidth = chartConfig.width - chartConfig.marginLeft;
}
attr = {
x : labelWidth/2
};
dataObj.graphics.label.animateWith(dummyObj, animObj, attr,
animationDuration, animType);
}
}
else {
dataObj.graphics.label && dataObj.graphics.label.hide() &&
dataObj.graphics.label.attr({'text-bound': []});
}
}
}
jobList.trackerDrawID.push(schedular.addJob(dataSet.drawTracker, dataSet, [],
lib.priorityList.tracker));
},
drawTracker : function () {
var dataSet = this,
chart = dataSet.chart,
components = dataSet.components,
pool = components.pool,
dataStore = components.data,
chartConfig = chart.config,
showHoverEffect = chartConfig.plothovereffect,
chartComponents = chart.components,
// xAxis = chartComponents.xAxis[0],
paper = chartComponents.paper,
// len = xAxis.getCategoryLen(),
trackerContainer = dataSet.graphics.trackerContainer,
trackerConfig,
config,
// i,
dataObj,
setElement,
hotElemCreated,
hotElement,
attr,
graphics,
//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 (elem) {
return function (data) {
var ele = this,
elData = ele.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(ele.getData().setRolloverAttr);
plotEventHandler.call(ele, chart, data, ROLLOVER);
}
};
},
//Fired on mouse-out over the hot elements.
rolloutResponseSetter = function (elem) {
return function (data) {
var ele = this,
elData = ele.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(ele.getData().setRolloutAttr);
plotEventHandler.call(ele, chart, data, ROLLOUT);
}
};
};
// Create tracker elements.
dataObj = dataStore[0];
config = dataObj && dataObj.config;
trackerConfig = dataObj.trackerConfig;
graphics = dataObj.graphics;
setElement = graphics.element;
hotElement = dataObj.graphics.hotElement;
if (attr = trackerConfig.attr) {
/*
* If the tooltips are not present then they are created over the hot element,
* else only attributes are set for the existing tooltips.
*/
if (!(hotElement = dataObj.graphics.hotElement)) {
// If any hot element is there in the pool then use it
if (pool && pool.hotElement[0]) {
hotElement = dataObj.graphics.hotElement = pool.hotElement[0];
pool.hotElement.splice(0, 1);
}
else {
hotElement = dataObj.graphics.hotElement = paper.rect(attr, trackerContainer);
hotElemCreated = true;
}
}
else {
hotElement.attr(attr);
}
}
// Hover effects and click function is binded to the hot element if present else the set element.
(hotElement || setElement)
.data(EVENTARGS, trackerConfig.eventArgs)
.data(showHoverEffectStr, showHoverEffect)
.data(SETROLLOVERATTR, config.setPlotRolloverAttr || {})
.data(SETROLLOUTATTR, config.setPlotRolloutAttr || {})
.tooltip(trackerConfig.eventArgs && trackerConfig.eventArgs.toolText);
if (hotElemCreated || config.elemCreated) {
(hotElement || setElement)
.click(clickFunc)
.hover(
rolloverResponseSetter(setElement),
rolloutResponseSetter(setElement)
);
}
},
addData : function() {
},
removeData : function() {
},
// Setting axis limits
getDataLimits : function () {
var dataSet = this,
config = dataSet.config,
pointerArr = dataSet.pointerArr && dataSet.pointerArr.pointer,
colorRange = dataSet.chart.jsonData.colorrange,
colorArr = colorRange && colorRange.color,
length = pointerArr && pointerArr.length,
i,
upperLimit = config.upperLimit,
lowerLimit = config.lowerLimit,
maxColorRangeVal,
minColorRangeVal,
max = config.maxValue,
min = config.minValue;
length = colorArr && colorArr.length;
// finding max min amongst the color range value
// but it has a lower priority than upperlimit and lowerlimit
// set by the user.
for (i=0; i<length; i++) {
maxColorRangeVal = Number(colorArr[i].maxvalue);
minColorRangeVal = Number(colorArr[i].minvalue);
upperLimit && (maxColorRangeVal > upperLimit) && (maxColorRangeVal = upperLimit);
lowerLimit && (minColorRangeVal < lowerLimit) && (minColorRangeVal = lowerLimit);
max = mathMax(max, maxColorRangeVal);
min = mathMin(min, minColorRangeVal);
}
return {
forceMin : true,
forceMax : true,
max : max,
min : min
};
}
},'hlineargauge']);
}
]);
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-led',
function () {
var global = this,
lib = global.hcLib,
//strings
BLANK = lib.BLANKSTRING,
BLANKSTRING = BLANK,
//add the tools thats are requared
pluck = lib.pluck,
pluckNumber = lib.pluckNumber,
plotEventHandler = lib.plotEventHandler,
getColorCodeString = lib.getColorCodeString,
getDarkColor = lib.graphics.getDarkColor,
getLightColor = lib.graphics.getLightColor,
convertColor = lib.graphics.convertColor,
preDefStr = lib.preDefStr,
colorStrings = preDefStr.colors,
COLOR_000000 = colorStrings.c000000,
configStr = preDefStr.configStr,
animationObjStr = preDefStr.animationObjStr,
showHoverEffectStr = preDefStr.showHoverEffectStr,
BUTT = 'butt',
POSITION_MIDDLE = preDefStr.POSITION_MIDDLE,
ledColorRangeFillMixStr = '{light-10},{dark-10},{light-10},{dark-10}',
ledColorRangeFillRatioStr = '0,10,80,10',
COMMASTRING = lib.COMMASTRING,
win = global.window,
userAgent = win.navigator.userAgent,
isIE = /msie/i.test(userAgent) && !win.opera,
TRACKER_FILL = 'rgba(192,192,192,'+ (isIE ? 0.002 : 0.000001) +')',
math = Math,
mathRound = math.round,
mathMax = math.max,
dropHash = lib.regex.dropHash,
// isArray = lib.isArray,
SETROLLOVERATTR = 'setRolloverAttr',
SETROLLOUTATTR = 'setRolloutAttr',
EVENTARGS = 'eventArgs',
COMPONENT = 'component',
DATASET = 'dataset',
HASHSTRING = lib.HASHSTRING,
toRaphaelColor = lib.toRaphaelColor,
UNDEFINED,
M = 'M',
L = 'L',
Z = 'Z',
HUNDREDSTRING = lib.HUNDREDSTRING;
FusionCharts.register(COMPONENT, [DATASET, 'led', {
init : function(datasetJSON) {
var dataSet = this,
chart = dataSet.chart,
components = chart.components,
visible;
if (!datasetJSON) {
return false;
}
dataSet.JSONData = datasetJSON;
dataSet.yAxis = components.scale;
dataSet.chartGraphics = chart.chartGraphics;
dataSet.components = {
};
dataSet.graphics = {
};
dataSet.visible = visible = pluckNumber(dataSet.JSONData.visible,
!Number(dataSet.JSONData.initiallyhidden), 1) === 1;
dataSet.configure();
},
draw : function () {
var dataSet = this,
chart = dataSet.chart,
conf = dataSet.config,
components = chart.components,
chartAttr = chart.jsonData.chart,
chartConfig = chart.config,
chartGraphics = chart.graphics,
paper = components.paper,
canvas = components.canvas,
graphics = canvas.graphics,
config = canvas.config,
animationObj = chart.get(configStr, animationObjStr),
animType = animationObj.animType,
animObj = animationObj.animObj,
dummyObj = animationObj.dummyObj,
animationDuration = animationObj.duration,
canvasBorderElement = graphics.canvasBorderElement,
canvasElement = graphics.canvasElement,
canvasElementPath = graphics.canvasElementPath,
canvasHotElement = graphics.canvasHotElement,
canvasLeft = chartConfig.canvasLeft,
canvasRight = chartConfig.canvasRight,
canvasTop = chartConfig.canvasTop,
canvasBottom = chartConfig.canvasBottom,
canvasWidth = chartConfig.canvasWidth,
canvasHeight = chartConfig.canvasHeight,
parentContainer = chartGraphics.datasetGroup,
shadow = config.shadow,
scale = components.scale,
min = scale.getLimit().min,
max = scale.getLimit().max,
isAxisReverse = pluckNumber(chart.jsonData.chart.reverseaxis, chart.isAxisReverse),
isHorizontal = chart.isHorizontal,
getRectXY = function (minValue, maxValue) {
if (isAxisReverse && !isHorizontal) {
return {
x: canvasLeft,
y: canvasTop + (minValue * canvasHeight / (max - min)),
width: canvasWidth,
height: (maxValue - minValue) * canvasHeight / (max - min)
};
}
else if (!isAxisReverse && !isHorizontal) {
return {
x: canvasLeft,
y: canvasTop + (canvasHeight - (maxValue * canvasHeight / (max - min))),
width: canvasWidth,
height: (maxValue - minValue) * canvasHeight / (max - min)
};
}
else if (isAxisReverse && isHorizontal) {
return {
x: canvasLeft + (canvasWidth - (maxValue * canvasWidth / (max - min))),
y: canvasTop,
width: (maxValue - minValue) * canvasWidth / (max - min),
height: canvasHeight
};
}
else if (!isAxisReverse && isHorizontal) {
return {
x: canvasLeft + ((minValue * canvasWidth / (max - min))),
y: canvasTop,
width: (maxValue - minValue) * canvasWidth / (max - min),
height: canvasHeight
};
}
},
angle = 180,
gaugeFillMix,
gaugeFillRatio,
paletteIndex,
colorArray,
colorM = chart.components.colorManager,
gaugeBorderColor,
gaugeBorderAlpha,
showShadow,
showGaugeBorder,
gaugeBorderThickness,
colorObj,
i,
len,
xyObj,
color,
borderColor,
crColor,
crAlpha,
borderAlpha,
shadowAlpha,
useSameFillColor,
useSameFillBgColor,
ledGap,
ledSize,
plotHoverEffect,
gaugeFillColor,
LEDlength,
sizeGapSum,
ledGapHalf,
ledGapQuarter,
remaningLength,
valueDistance,
halfBorderWidth,
x1,
y1,
x2,
y2,
noOfLED,
extraSpace,
LEDGapStartX,
LEDGapStartY,
pathCommand,
colorRangeGetter,
numberFormatter = chart.components.numberFormatter,
useSameFillColorCode,
lastColor,
value,
colorIndex,
showHoverEffect = conf.showHoverEffect,
//Fired when clicked over the hot elements.
clickFunc = function (data) {
var ele = this;
plotEventHandler.call(ele, chart, data);
},
rolloverResponseSetter = function (colorRangeElems) {
var i = 0,
len,
elem,
ele;
return function () {
ele = this;
if (ele.data(showHoverEffectStr) !== 0) {
for (i = 0, len = colorRangeElems.length; i < len; i += 1) {
elem = colorRangeElems[i];
elem.attr(ele.data(SETROLLOVERATTR)[i]);
}
}
};
},
rolloutResponseSetter = function (colorRangeElems) {
var i = 0,
len,
elem,
ele;
return function () {
ele = this;
if (ele.data(showHoverEffectStr) !== 0) {
for (i = 0, len = colorRangeElems.length; i < len; i += 1) {
elem = colorRangeElems[i];
elem.attr(ele.data(SETROLLOUTATTR)[i]);
}
}
};
},
setRolloverAttr = [],
setRolloutAttr = [],
layers = chart.graphics,
dataSetGraphics = dataSet.graphics,
trackerContainer = dataSetGraphics.trackerContainer,
trackerLayer = layers.trackerGroup,
setLink,
eventArgs,
LEDDrawn = 0,
perLEDValueLength,
lastX,
lastY,
colorLED,
colorLedLengthPX,
colorLEDLength,
isNewElement = false,
attr;
if (!trackerContainer) {
trackerContainer = dataSet.graphics.trackerContainer = paper.group('led-hot', trackerLayer);
}
showGaugeBorder = pluckNumber(chartAttr.showgaugeborder, 1);
gaugeBorderColor = pluck(chartAttr.gaugebordercolor, chart.gaugeBorderColor, '333333');
gaugeBorderThickness = showGaugeBorder ? pluckNumber(chartAttr.gaugeborderthickness,
chart.gaugeBorderThickness, 2) : 0;
gaugeBorderAlpha = pluck(chartAttr.gaugeborderalpha, HUNDREDSTRING);
//Gauge fill color
config.gaugeFillColor = gaugeFillColor = pluck(chartAttr.gaugefillcolor, chartAttr.ledbgcolor,
COLOR_000000);
//Whether to use same fill color?
useSameFillColor = pluckNumber(chartAttr.usesamefillcolor, 0);
//Same color for back ground
useSameFillBgColor = pluckNumber(chartAttr.usesamefillbgcolor, useSameFillColor);
conf.ledGap = ledGap = pluckNumber(chartAttr.ledgap, 2);
conf.ledSize = ledSize = pluckNumber(chartAttr.ledsize, 2);
plotHoverEffect = pluckNumber(chartAttr.showhovereffect, 0);
config.colorRangeFillMix = gaugeFillMix = lib.getFirstDefinedValue(chartAttr.colorrangefillmix,
chartAttr.gaugefillmix, chart.colorRangeFillMix,
ledColorRangeFillMixStr);
config.colorRangeFillRatio = gaugeFillRatio = lib.getFirstDefinedValue(chartAttr.colorrangefillratio,
chartAttr.gaugefillratio, chart.colorRangeFillRatio, chartAttr.gaugefillratio,
ledColorRangeFillRatioStr);
paletteIndex = 0;
config.colorRangeGetter = colorRangeGetter = components.colorRange;
config.colorArray = colorArray = colorRangeGetter && colorRangeGetter.getColorRangeArr(min, max);
gaugeBorderColor = pluck(gaugeBorderColor, COLOR_000000).replace(dropHash, HASHSTRING);
gaugeBorderAlpha = pluckNumber(chartAttr.colorrangeborderalpha,
chartAttr.gaugeborderalpha, 100);
showShadow = pluckNumber(chartAttr.showshadow, 1);
showGaugeBorder = pluckNumber(chartAttr.showgaugeborder, 1);
config.colorRangeBorderThickness = gaugeBorderThickness =
showGaugeBorder ? pluckNumber(chartAttr.colorrangeborderthickness,
chartAttr.gaugeborderthickness, 2) : 0;
LEDlength = !isHorizontal ? canvasHeight : canvasWidth;
sizeGapSum = (ledGap + ledSize) || 1;
ledGapHalf = ledGap / 2;
ledGapQuarter = ledGapHalf / 2;
remaningLength = LEDlength - ledSize;
valueDistance = max - min;
halfBorderWidth = gaugeBorderThickness / 2;
x1 = canvasLeft - halfBorderWidth;
y1 = canvasTop - halfBorderWidth;
x2 = canvasLeft + canvasWidth + halfBorderWidth;
y2 = canvasTop + canvasHeight + halfBorderWidth;
noOfLED = parseInt(remaningLength / sizeGapSum, 10) + 1;
extraSpace = remaningLength % sizeGapSum;
//devide the extra space amont all the LED
ledSize += extraSpace / noOfLED;
conf.sizeGapSum = sizeGapSum = ledSize + ledGap;
conf.perLEDValueLength = perLEDValueLength = valueDistance / noOfLED;
LEDGapStartX = canvasLeft;
LEDGapStartY = canvasTop;
setLink = pluck(chartAttr.clickurl);
if (!canvasElement) {
graphics.canvasElement = canvasElement = {};
canvasElement.colorRangeElems = [];
}
value = numberFormatter.getCleanValue(chart.jsonData.value);
if (useSameFillColor || useSameFillBgColor) {
for (i = 0, len = colorArray.length; i < len; i += 1) {
if (value >= colorArray[i].minvalue && value <= colorArray[i].maxvalue) {
useSameFillColorCode = colorArray[i].code || colorM.getPlotColor(i);
colorIndex = i;
break;
}
}
}
(colorArray && colorArray.length > 0) && (lastColor = colorArray[0].code || colorM.getPlotColor(0));
lastX = isAxisReverse ? canvasRight : canvasLeft;
lastY = isAxisReverse ? canvasTop : canvasBottom;
for (i = 0, len = colorArray && colorArray.length; i < len; i += 1) {
colorObj = colorArray[i],
xyObj = getRectXY((colorObj.minvalue - min), (colorObj.maxvalue - min));
colorLED = mathRound((colorObj.maxvalue - min) / perLEDValueLength);
colorLEDLength = colorLED - LEDDrawn;
LEDDrawn = colorLED;
colorLedLengthPX = colorLEDLength * sizeGapSum;
if (!isHorizontal && !isAxisReverse) {
xyObj.height = colorLedLengthPX - ledGap;
xyObj.y = lastY - xyObj.height;
lastY -= colorLedLengthPX;
}
else if (!isHorizontal && isAxisReverse) {
xyObj.height = colorLedLengthPX - ledGap;
xyObj.y = lastY;
lastY += colorLedLengthPX;
}
else if (isHorizontal && !isAxisReverse) {
xyObj.width = colorLedLengthPX - ledGap;
xyObj.x = lastX;
lastX += colorLedLengthPX;
}
else if (isHorizontal && isAxisReverse) {
xyObj.width = colorLedLengthPX - ledGap;
xyObj.x = lastX - xyObj.width;
lastX -= colorLedLengthPX;
}
colorObj.x = xyObj.x;
colorObj.y = xyObj.y;
colorObj.width = xyObj.width;
colorObj.height = xyObj.height;
if (useSameFillColor) {
color = useSameFillColorCode;
}
else if (useSameFillBgColor && (i > colorIndex)) {
color = lastColor;
}
else {
color = lastColor = colorObj.code || colorM.getPlotColor(i);
}
borderColor = convertColor(getColorCodeString(pluck(colorObj.bordercolor, color), gaugeBorderColor),
pluckNumber(colorObj.borderalpha, gaugeBorderAlpha));
shadow = showShadow ? (Math.max(colorObj.alpha, gaugeBorderAlpha) / 100) : null;
//create the shadow element
crColor = colorM.parseColorMix(colorObj.code, gaugeFillMix);
crAlpha = colorM.parseAlphaList(colorObj.alpha, crColor.length);
borderAlpha = pluckNumber(colorObj.borderAlpha, gaugeBorderAlpha);
shadowAlpha = crAlpha.split(COMMASTRING);
shadowAlpha = mathMax.apply(Math, shadowAlpha);
shadowAlpha = mathMax(gaugeBorderThickness && borderAlpha || 0, shadowAlpha);
attr = {
x: xyObj.x,
y: xyObj.y,
width: (xyObj.width < 0) ? 0 : xyObj.width,
height: (xyObj.height < 0) ? 0 : xyObj.height,
r: 0,
'stroke-width': 0,
stroke: borderColor,
'fill': toRaphaelColor({
FCcolor: {
color: color,
ratio: gaugeFillRatio,
alpha: crAlpha,
angle: angle
}
})
};
if (!canvasElement.colorRangeElems[i]) {
canvasElement.colorRangeElems[i] = paper.rect(attr, parentContainer).toBack();
}
else {
canvasElement.colorRangeElems[i].show();
canvasElement.colorRangeElems[i].animateWith(dummyObj, animObj, {
x: xyObj.x,
y: xyObj.y,
width: (xyObj.width < 0) ? 0 : xyObj.width,
height: (xyObj.height < 0) ? 0 : xyObj.height,
r: 0
}, animationDuration, animType);
canvasElement.colorRangeElems[i].attr({
'stroke-width': 0,
stroke: borderColor,
'fill': toRaphaelColor({
FCcolor: {
color: color,
ratio: gaugeFillRatio,
alpha: crAlpha,
angle: angle
}
})
});
}
canvasElement.colorRangeElems[i]
.shadow({
apply: showShadow,
opacity: (shadowAlpha / 100)
});
setRolloverAttr.push({
'stroke-width' : 0,
fill : toRaphaelColor({
FCcolor: {
color: getDarkColor(pluck(color, COLOR_000000), 80) + COMMASTRING +
getLightColor(pluck(color, COLOR_000000), 80),
alpha: pluckNumber(colorObj.alpha, 100),
angle: isHorizontal ? 90 : 0
}
})
});
setRolloutAttr.push({
'stroke-width' : 0,
fill : toRaphaelColor({
FCcolor: {
color: pluck(color, COLOR_000000),
alpha: pluckNumber(colorObj.alpha, 100)
}
})
});
}
if (colorArray && colorArray.length === 0) {
for (i = 0, len = canvasElement.colorRangeElems.length; i < len; i++) {
canvasElement.colorRangeElems[i].hide();
}
}
eventArgs = {
link: setLink,
value: value
};
attr = {
x: canvasLeft,
y: canvasTop,
width: canvasWidth,
height: canvasHeight,
'stroke-width': 0,
fill: TRACKER_FILL,
ishot: true
};
if (!canvasHotElement) {
canvasHotElement = graphics.canvasHotElement = paper.rect(attr, trackerContainer);
isNewElement = true;
}
else {
canvasHotElement.attr(attr);
}
canvasHotElement
.data(EVENTARGS, eventArgs)
.data(showHoverEffectStr, showHoverEffect)
.data(SETROLLOVERATTR, setRolloverAttr)
.data(SETROLLOUTATTR, setRolloutAttr);
if (isNewElement) {
if (setLink) {
canvasHotElement
.click(clickFunc);
}
canvasHotElement
.hover(
rolloverResponseSetter(canvasElement.colorRangeElems),
rolloutResponseSetter(canvasElement.colorRangeElems)
);
}
if (isHorizontal) {
LEDGapStartX += sizeGapSum - (ledGap / 2);
}
else {
LEDGapStartY += sizeGapSum - (ledGap / 2);
}
pathCommand = [];
attr = {
path: [M, x1, y1, L, x2, y1, x2, y2, x1, y2, Z],
stroke: convertColor(gaugeBorderColor, gaugeBorderAlpha),
'stroke-width': gaugeBorderThickness,
'stroke-linecap': BUTT
};
if (!canvasBorderElement) {
graphics.canvasBorderElement = paper.path(attr, parentContainer)
.shadow({
apply: showShadow
}).toBack();
}
else {
canvasBorderElement.animateWith(dummyObj, animObj, {
path: [M, x1, y1, L, x2, y1, x2, y2, x1, y2, Z]
}, animationDuration, animType);
canvasBorderElement.attr({
stroke: convertColor(gaugeBorderColor, gaugeBorderAlpha),
'stroke-width': gaugeBorderThickness
});
}
//Draw the path for the gap
for (i = 1; i < noOfLED; i += 1) {
if (isHorizontal) {
pathCommand.push(M, LEDGapStartX, LEDGapStartY, L, LEDGapStartX, LEDGapStartY + canvasHeight);
LEDGapStartX += sizeGapSum;
}
else {
pathCommand.push(M, LEDGapStartX, LEDGapStartY, L, LEDGapStartX + canvasWidth, LEDGapStartY);
LEDGapStartY += sizeGapSum;
}
}
attr = {
path: pathCommand,
stroke: convertColor(gaugeFillColor, 100),
'stroke-width': ledGap,
'stroke-linecap': BUTT
};
if (!canvasElementPath) {
graphics.canvasElementPath = paper.path(attr, parentContainer);
}
else {
canvasElementPath.animateWith(dummyObj, animObj, {
path: pathCommand
}, animationDuration, animType);
canvasElementPath.attr({
stroke: convertColor(gaugeFillColor, 100),
'stroke-width': ledGap
});
}
chartConfig.gaugeStartX = canvasLeft;
chartConfig.gaugeEndX = canvasRight;
chartConfig.gaugeStartY = canvasTop;
chartConfig.gaugeEndY = canvasBottom;
chartConfig.gaugeCenterX = canvasLeft + (canvasWidth * 0.5);
chartConfig.gaugeCenterY = canvasTop + (canvasHeight * 0.5);
chartConfig.gaugeRadius = canvasWidth * 0.5;
dataSet.drawShade();
},
drawShade : function() {
var dataSet = this,
conf = dataSet.config,
chartAttr = dataSet.chart.jsonData.chart,
dataStore = dataSet.components.data,
chart = dataSet.chart,
chartConfig = chart.config,
canvasLeft = chartConfig.canvasLeft,
canvasTop = chartConfig.canvasTop,
canvasHeight = chartConfig.canvasHeight,
canvasWidth = chartConfig.canvasWidth,
paper = chart.components.paper,
parentContainer = chart.graphics.datasetGroup,
container = dataSet.graphics.container,
gaugeFillColor,
numberFormatter = chart.components.numberFormatter,
setValue,
yPos,
isAxisReverse = pluckNumber(chartAttr.reverseaxis, chart.isaxisreverse),
isHorizontal = chart.isHorizontal,
animationObj = chart.get(configStr, animationObjStr),
animType = animationObj.animType,
animObj = animationObj.animObj,
dummyObj = animationObj.dummyObj,
animationDuration = animationObj.duration,
attr,
shadowElement,
dataObj = dataStore[0],
graphic = dataObj.graphics,
config = dataObj && dataObj.config,
layers = chart.graphics,
dataLabelContainer = dataSet.graphics.dataLabelContainer,
dataLabelsLayer = layers.datalabelsGroup,
style = chart.config.dataLabelStyle,
heightUsed = conf.heightUsed,
lineHeight,
labelBBox,
labelWidth,
setTooltext,
initAnimation = conf.initAnimation,
lightedLed,
lightedLedLength,
height,
width,
scale = chart.components.scale,
min = scale.getLimit().min;
// css = {
// fontFamily: style.fontFamily,
// fontSize: style.fontSize,
// lineHeight: style.lineHeight,
// fontWeight: style.fontWeight,
// fontStyle: style.fontStyle
// };
gaugeFillColor = chart.components.canvas.config.gaugeFillColor;
if (!container) {
container = dataSet.graphics.container = paper.group('shade', parentContainer);
}
// Creating the dataLabel container group if not present and appending it to its parent.
if (!dataLabelContainer) {
dataLabelContainer = dataSet.graphics.dataLabelContainer =
paper.group('datalabel', dataLabelsLayer);
}
setValue = numberFormatter.getCleanValue(config.setValue);
if (!dataObj.graphics) {
dataObj.graphics = {};
}
shadowElement = dataObj.graphics.element;
lightedLed = (setValue - min) / conf.perLEDValueLength;
lightedLedLength = (mathRound(lightedLed) * conf.sizeGapSum) - conf.ledGap;
height = Math.ceil(canvasHeight - lightedLedLength);
width = Math.ceil(canvasWidth - lightedLedLength);
if (isAxisReverse && !isHorizontal) {
attr = {
x: canvasLeft,
y: animationDuration && initAnimation ? canvasTop : canvasTop + lightedLedLength,
width: canvasWidth,
height: animationDuration && initAnimation ? canvasHeight : height,
r: 0,
'stroke-width': 0,
fill : convertColor(gaugeFillColor, 50)
};
if (!shadowElement) {
shadowElement = dataObj.graphics.element = paper.rect(attr, container);
shadowElement.animateWith(dummyObj, animObj, {
y: canvasTop + lightedLedLength,
height: height
}, animationDuration, animType);
}
else {
shadowElement.animateWith(dummyObj, animObj, {
x: canvasLeft,
y: canvasTop + lightedLedLength,
width: canvasWidth,
height: height,
r: 0
}, animationDuration, animType);
shadowElement.attr({
'stroke-width': 0,
fill : convertColor(gaugeFillColor, 50)
});
}
}
else if (!isAxisReverse && !isHorizontal) {
attr = {
x: canvasLeft,
y: canvasTop,
width: canvasWidth,
height: animationDuration && initAnimation ? canvasHeight : height,
r: 0,
'stroke-width': 0,
fill : convertColor(gaugeFillColor, 50)
};
if (!shadowElement) {
shadowElement = dataObj.graphics.element = paper.rect(attr, container);
shadowElement.animateWith(dummyObj, animObj, {
height: height
}, animationDuration, animType);
}
else {
shadowElement.animateWith(dummyObj, animObj, {
x: canvasLeft,
y: canvasTop,
width: canvasWidth,
height: height,
r: 0
}, animationDuration, animType);
shadowElement.attr({
'stroke-width': 0,
fill : convertColor(gaugeFillColor, 50)
});
}
}
else if (!isAxisReverse && isHorizontal) {
attr = {
x: animationDuration && initAnimation ? canvasLeft : canvasLeft + lightedLedLength,
y: canvasTop,
width: animationDuration && initAnimation ? canvasWidth : width,
height: canvasHeight,
r: 0,
'stroke-width': 0,
fill : convertColor(gaugeFillColor, 50)
};
if (!shadowElement) {
shadowElement = dataObj.graphics.element = paper.rect(attr, container);
shadowElement.animateWith(dummyObj, animObj, {
x: canvasLeft + lightedLedLength,
width: width
}, animationDuration, animType);
}
else {
shadowElement.animateWith(dummyObj, animObj, {
x: canvasLeft + lightedLedLength,
y: canvasTop,
width: width,
height: canvasHeight,
r: 0
}, animationDuration, animType);
shadowElement.attr({
'stroke-width': 0,
fill : convertColor(gaugeFillColor, 50)
});
}
}
else if (isAxisReverse && isHorizontal) {
attr = {
x: canvasLeft,
y: canvasTop,
width: animationDuration && initAnimation ? canvasWidth : width,
height: canvasHeight,
r: 0,
'stroke-width': 0,
fill : convertColor(gaugeFillColor, 50)
};
if (!shadowElement) {
shadowElement = dataObj.graphics.element = paper.rect(attr, container);
shadowElement.animateWith(dummyObj, animObj, {
width: width
}, animationDuration, animType);
}
else {
shadowElement.animateWith(dummyObj, animObj, {
x: canvasLeft,
y: canvasTop,
width: width,
height: canvasHeight,
r: 0
}, animationDuration, animType);
shadowElement.attr({
'stroke-width': 0,
fill : convertColor(gaugeFillColor, 50)
});
}
}
setTooltext = (config.setTooltext === BLANK || config.setTooltext === UNDEFINED) ?
config.toolTipValue : config.setTooltext;
if (conf.showTooltip) {
chart.components.canvas.graphics.canvasHotElement.tooltip(setTooltext);
}
else {
chart.components.canvas.graphics.canvasHotElement.tooltip(false);
}
lineHeight = parseInt(style.lineHeight, 10);
yPos = lineHeight > heightUsed ? (chartConfig.height - chartConfig.marginBottom - heightUsed) +
lineHeight/2 : chartConfig.height - chartConfig.marginBottom - lineHeight/2;
yPos -= chartConfig.borderWidth;
yPos -= (chart._manageActionBarSpace &&
chart._manageActionBarSpace(config.availableHeight * 0.225) || {}).bottom;
graphic = dataObj.graphics;
if ((config.displayValue !== BLANKSTRING) && (config.displayValue !== UNDEFINED) && conf.showValue) {
attr = {
text: config.displayValue,
'text-anchor': POSITION_MIDDLE,
x: canvasWidth/2 + canvasLeft,
y: yPos,
'vertical-align': POSITION_MIDDLE,
fill: style.color,
direction: config.textDirection,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
};
if (!graphic.label) {
graphic.label = paper.text(attr, dataLabelContainer);
}
else {
graphic.label.animateWith(dummyObj, animObj, {
x: canvasWidth/2 + canvasLeft,
y: yPos
}, animationDuration, animType);
graphic.label.attr({
text: config.displayValue,
'text-anchor': POSITION_MIDDLE,
'vertical-align': POSITION_MIDDLE,
fill: style.color,
direction: config.textDirection,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
});
}
// graphic.label
// .attr(attr);
// Adjusting the chart label if goes out side the chart area
// we try to keep the label inside viewport
labelBBox = graphic.label.getBBox();
if (labelBBox.x + chartConfig.marginLeft < 0) {
labelWidth = labelBBox.width - chartConfig.marginLeft;
if(chartConfig.width < labelWidth) {
labelWidth = chartConfig.width - chartConfig.marginLeft;
}
attr = {
x : labelWidth/2
};
graphic.label.animateWith(dummyObj, animObj, attr, animationDuration, animType);
}
}
else {
graphic.label && (graphic.label = graphic.label.remove());
}
}
},'bullet']);
}
]);
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-thermometer',
function () {
var global = this,
lib = global.hcLib,
pluckNumber = lib.pluckNumber,
pluck = lib.pluck,
COMMASTRING = lib.COMMASTRING,
BLANK = lib.BLANKSTRING,
BLANKSTRING = BLANK,
AXISPOSITION_TOP = 1,
AXISPOSITION_BOTTOM = 3,
getValidValue = lib.getValidValue,
parseTooltext = lib.parseTooltext,
convertColor = lib.graphics.convertColor,
HUNDREDSTRING = lib.HUNDREDSTRING,
getDarkColor = lib.graphics.getDarkColor,
getLightColor = lib.graphics.getLightColor,
preDefStr = lib.preDefStr,
configStr = preDefStr.configStr,
animationObjStr = preDefStr.animationObjStr,
POSITION_TOP = preDefStr.POSITION_TOP,
POSITION_MIDDLE = preDefStr.POSITION_MIDDLE,
gaugeFillColorStr = preDefStr.gaugeFillColorStr,
gaugeBorderColorStr = preDefStr.gaugeBorderColorStr,
linkedItemsStr = 'linkedItems',
smartLabelStr = 'smartLabel',
dummyStr = 'dummy',
plotEventHandler = lib.plotEventHandler,
ROLLOVER = 'DataPlotRollOver',
ROLLOUT = 'DataPlotRollOut',
FILLMIXDARK10 = '{dark-10}',
COMPONENT = 'component',
DATASET = 'dataset',
EVENTARGS = 'eventArgs',
graphicsStr = 'graphics',
trackerGroupStr = 'trackerGroup',
componentsStr = 'components',
scaleStr = 'scale',
paperStr = 'paper',
DATASET_GROUP = 'datasetGroup',
ATTRFN = 'attr',
ANIMATEFN = 'animate',
toRaphaelColor = lib.toRaphaelColor,
topLightGlowAlphaStr = '40,0',
topLightGlowRatioStr = '0,80',
topLightGlowRStr = '70%',
bulbBorderLightRStr = '50%',
bulbBorderLightAlphaStr = '0,50',
bulbBorderLightRatioStr = '78,30',
bulbTopLightAlphaStr = '60,0',
bulbTopLightRatioStr = '0,30',
bulbCenterLightAlphaStr = '80,0',
bulbCenterLightRatioStr = '0,70',
cylLeftLightAlphaStr = '50,0',
cylLeftLightRatioStr = '0,80',
cylRightLightAlphaStr = '50,0,0',
cylRightLightRatioStr = '0,40,60',
HUNDREDPERCENT = '100%',
zeroCommaHundredStr = '0,100',
M = 'M',
A = 'A',
L = 'L',
Z = 'Z',
cos50 = 0.643,
sin50 = 0.766,
win = global.window,
userAgent = win.navigator.userAgent,
isIE = /msie/i.test(userAgent) && !win.opera,
TRACKER_FILL = 'rgba(192,192,192,'+ (isIE ? 0.002 : 0.000001) +')',
getScaleFactor = function (origW, origH, canvasWidth, canvasHeight) {
var scaleFactor;
origH = pluckNumber(origH, canvasHeight);
origW = pluckNumber(origW, canvasWidth);
if (!origH || !origW) {
scaleFactor = 1;
}
// Now, if the ratio of original width,height & stage width,height are same
else if ((origW / canvasWidth) == (origH / canvasHeight)) {
//In this case, the transformation value would be the same, as the ratio
//of transformation of width and height is same.
scaleFactor = canvasWidth / origW;
} else {
//If the transformation factors are different, we do a constrained scaling
//We get the aspect whose delta is on the lower side.
scaleFactor = Math.min((canvasWidth / origW), (canvasHeight / origH));
}
return scaleFactor;
};
FusionCharts.register(COMPONENT, [DATASET, 'thermometer',{
init : function (dataSetJson) {
var dataSet = this;
dataSet.configure();
dataSet.setValue(dataSetJson && dataSetJson.data && dataSetJson.data[0]);
},
/**
* Function to update the value
* @param {number} value : value that will be added
* @param {boolean} draw : whether to update the visuals also
*/
setValue: function (setData, draw) {
var dataSet = this,
datasetConfig = dataSet.config,
chart = dataSet.chart,
jsonChartObj = chart.jsonData.chart,
chartComponents = chart.components,
numberFormatter = chartComponents.numberFormatter,
value = setData.value,
formattedValue;
datasetConfig.value = value = numberFormatter.getCleanValue(value);
if (value !== null) {
formattedValue = datasetConfig.formattedValue = numberFormatter.dataLabels(datasetConfig.value);
if (!datasetConfig.showValue) {
datasetConfig.displayValue = BLANKSTRING;
}
else {//determine the dispalay value then
datasetConfig.displayValue = setData.label || getValidValue(formattedValue, BLANK);
}
if (!datasetConfig.showTooltip) {
datasetConfig.toolText = BLANKSTRING;
}
else if (jsonChartObj.plottooltext !== undefined) {
datasetConfig.toolText = parseTooltext(pluck(setData.tooltext, jsonChartObj.plottooltext),
[1,2], { formattedValue: formattedValue
}, {}, jsonChartObj);
}
else {//determine the dispalay value then
datasetConfig.toolText = pluck(setData.tooltext,
formattedValue === null ? BLANKSTRING : formattedValue);
}
}
else {
datasetConfig.displayValue = BLANKSTRING;
datasetConfig.toolText = BLANKSTRING;
datasetConfig.formattedValue = null;
}
if (draw) {
dataSet.draw();
}
},
configure : function () {
var dataSet = this,
chart = dataSet.chart,
jsonData = chart.jsonData,
chartAttrs = jsonData.chart,
datasetConfig = dataSet.config || (dataSet.config = {}),
colorM = chart.components.colorManager,
chartConfig = chart.config,
gaugeBorderAlpha,
showHoverEffect = pluckNumber(chartAttrs.showhovereffect),
plotFillHoverColor,
gaugeFillAlpha,
gaugeFillColor;
datasetConfig.showValue = pluckNumber(chartAttrs.showvalue, chartAttrs.showvalues, 1);
datasetConfig.showTooltip = pluckNumber(chartAttrs.showtooltip, 1);
datasetConfig.valuePadding = pluckNumber(chartAttrs.valuepadding, 2);
datasetConfig.tooltipSepChar = pluck(chartAttrs.tooltipsepchar, COMMASTRING);
datasetConfig.pointerOnOpp = pluckNumber(chartAttrs.pointerontop, 0);
datasetConfig.axisPosition = pluckNumber(chartAttrs.ticksbelowgauge, chartAttrs.ticksbelowgraph,
this.ticksbelowgauge, 1) ? AXISPOSITION_BOTTOM : AXISPOSITION_TOP;
datasetConfig.valueAbovePointer = pluckNumber(chartAttrs.valueabovepointer, 1);
datasetConfig.labelStyle = chartConfig.dataLabelStyle;
gaugeFillColor = datasetConfig.gaugeFillColor = pluck(chartAttrs.gaugefillcolor,
chartAttrs.thmfillcolor, chartAttrs.cylfillcolor, colorM.getColor(gaugeFillColorStr));
gaugeFillAlpha = datasetConfig.gaugeFillAlpha = pluckNumber(chartAttrs.gaugefillalpha,
chartAttrs.cylfillalpha, chartAttrs.thmfillalpha, HUNDREDSTRING);
//Gauge Border properties
datasetConfig.showGaugeBorder = pluckNumber(chartAttrs.showgaugeborder, 1);
gaugeBorderAlpha = datasetConfig.showGaugeBorder ? pluckNumber(chartAttrs.gaugeborderalpha,40) : 0;
// We are using 40 for default alpha of Thermometer Gauge Border
datasetConfig.gaugeBorderColor = convertColor(pluck(chartAttrs.gaugebordercolor,
colorM.getColor(gaugeBorderColorStr)), gaugeBorderAlpha);
datasetConfig.gaugeBorderThickness = pluckNumber(chartAttrs.gaugeborderthickness, 1);
// Thermometer Glass color
datasetConfig.gaugeContainerColor = pluck(chartAttrs.thmglasscolor, chartAttrs.cylglasscolor,
chart.glasscolor, getLightColor(gaugeFillColor, 30));
if (showHoverEffect !== 0 && (showHoverEffect || chartAttrs.plotfillhovercolor ||
chartAttrs.plotfillhoveralpha || chartAttrs.plotfillhoveralpha === 0)) {
datasetConfig.showHoverEffect = true;
plotFillHoverColor = pluck(chartAttrs.plotfillhovercolor, chartAttrs.cylfillhovercolor,
chartAttrs.thmfillhovercolor, FILLMIXDARK10);
datasetConfig.plotFillHoverAlpha = pluckNumber(chartAttrs.plotfillhoveralpha,
chartAttrs.cylfillhoveralpha, chartAttrs.thmfillhoveralpha, gaugeFillAlpha);
datasetConfig.plotFillHoverColor = /\{/.test(plotFillHoverColor) ?
colorM.parseColorMix(gaugeFillColor, plotFillHoverColor)[0] : plotFillHoverColor;
}
dataSet.setValue(jsonData);
chart._parseSpecialConfig && chart._parseSpecialConfig();
},
_getLabelSpace: function () {
var dataSet = this,
datasetConfig = dataSet.config,
chart = dataSet.chart,
smartLabel = chart.get(linkedItemsStr, smartLabelStr),
labelObj;
smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
smartLabel.setStyle(datasetConfig.labelStyle); // @todo map datalabel style
labelObj = smartLabel.getOriSize(datasetConfig.displayValue !== BLANK ?
datasetConfig.displayValue : dummyStr);
return labelObj.height ? (labelObj.height + datasetConfig.valuePadding) : 0;
},
_manageSpace : function () {
var ds = this,
chart = this.chart,
chartConfig = chart.config,
chartWidth = chartConfig.width,
chartHeight = chartConfig.height,
canvasWidth = chartConfig.canvasWidth,
canvasHeight = chartConfig.canvasHeight,
canvasLeft = chartConfig.canvasLeft,
canvasRight = chartConfig.canvasRight,
canvasTop = chartConfig.canvasTop,
// canvasRight = chartConfig.canvasRight,
canvasBottom = chartConfig.canvasBottom,
xDefined = chartConfig.xDefined,
yDefined = chartConfig.yDefined,
rDefined = chartConfig.rDefined,
hDefined = chartConfig.hDefined,
thmOriginX = chartConfig.thmOriginX,
thmOriginY = chartConfig.thmOriginY,
thmBulbRadius = chartConfig.thmBulbRadius,
thmHeight = chartConfig.thmHeight,
scaleFactor = getScaleFactor(chartConfig.origW, chartConfig.origH, chartWidth, chartHeight),
top = 0,
bottom = 0,
left = 0,
right = 0,
thmCylenderRight,
thmhalfWidth,
bulbDiameter,
centerPos,
thmWidth,
bulbHeight,
measure,
canvasLeftShift;
// manage the space for the datalabels
measure = ds._getLabelSpace();
canvasBottom += measure;
canvasHeight -= measure;
bottom += measure;
// manage the thermometer space
/* First calculate the radius */
//if Not defined the radius then calculate it.
if (!rDefined) {
thmBulbRadius = Math.min(canvasWidth / 2, pluckNumber(thmHeight, canvasHeight) * 0.13);
rDefined = true;
}
else {
thmBulbRadius = thmBulbRadius * scaleFactor;
}
// store the effective radius
chartConfig.effectiveR = thmBulbRadius;
bulbDiameter = thmBulbRadius*2;
thmhalfWidth = thmBulbRadius * cos50;
thmWidth = 2 * thmhalfWidth;
bulbHeight = thmBulbRadius * (1 + sin50);
// add the space for the top glass effect
top += thmhalfWidth;
canvasTop += thmhalfWidth;
canvasHeight -= thmhalfWidth;
/* Calculate the x */
// if x is user defined
if (xDefined) {
thmOriginX = thmOriginX * scaleFactor;
canvasLeftShift = (thmOriginX - thmhalfWidth) - canvasLeft;
}
else { // else, place the gauge at the center
centerPos = (canvasRight - canvasLeft) / 2;
// now as per the center position calculate the extra left gap
canvasLeftShift = (centerPos - thmhalfWidth);
// check whether we have space to put the gauge at center
thmCylenderRight = canvasLeftShift + thmWidth;
if (thmCylenderRight > canvasWidth) {
canvasLeftShift = canvasWidth - thmWidth;
}
}
left += canvasLeftShift;
canvasLeft += canvasLeftShift;
canvasWidth -= canvasLeftShift;
// to make the canvas width same as thermometer's cylinder width increase the right padding
right += (canvasWidth - thmWidth);
if (yDefined) {
thmOriginY = thmOriginY * scaleFactor;
}
if (!hDefined) { // if height is not defined
if (yDefined) { // if y is defined then adjust thermometer height is available space
thmHeight = thmOriginY - canvasTop;
}
else {
thmHeight = Math.max(canvasHeight - bulbHeight, 3 * thmBulbRadius);
thmOriginY = canvasTop + thmHeight;
}
}
else { // height is defined
thmHeight = thmHeight * scaleFactor;
if (yDefined) {// if both are defined, adjust the top to accomodate this
top += thmOriginY - thmHeight - canvasTop;
}
else {
thmOriginY = canvasTop + thmHeight;
}
}
// finally adjust the bottom to accomodate y and height
bottom += (canvasTop + canvasHeight) - thmOriginY;
return {
top : top,
bottom : bottom,
left: left,
right: right
};
},
draw : function () {
var dataSet = this,
dsConfig = dataSet.config,
iapi = dataSet.chart,
dataLabelsLayer = iapi.graphics.datalabelsGroup,
trackerLayer = iapi.get(graphicsStr, trackerGroupStr),
graphics = dataSet.graphics || (dataSet.graphics = {}),
scale = iapi.get(componentsStr, scaleStr),
parentContainer = iapi.get(graphicsStr, DATASET_GROUP),
chartConfig = iapi.get(configStr),
paper = iapi.get(componentsStr, paperStr),
canvasLeft = chartConfig.canvasLeft,
canvasTop = chartConfig.canvasTop,
canvasHeight = chartConfig.canvasHeight,
r = chartConfig.effectiveR || 10,
cylinderWidthHalf = r * cos50,
use3DLighting = chartConfig.use3DLighting,
x = canvasLeft + cylinderWidthHalf,
y = canvasTop - cylinderWidthHalf,
h = canvasHeight,
scaleTop = cylinderWidthHalf,
bulbCenterDistance = r * sin50,
scaleY = y + scaleTop,
y1 = scaleY + h,
y2 = y1 + bulbCenterDistance,
value = pluckNumber(dsConfig.value, scale.getLimit().min),
thmPos = scale.getPixel(value),
topRoundR = cylinderWidthHalf * 0.33,
y4 = y + topRoundR,
y6 = thmPos,
lCylWidthHalf = cylinderWidthHalf * 0.9,
topRoundRDistance = cylinderWidthHalf - topRoundR,
lR = r + lCylWidthHalf - cylinderWidthHalf,
x1 = x - cylinderWidthHalf,
x2 = x + cylinderWidthHalf,
x3 = x - topRoundRDistance,
x4 = x + topRoundRDistance,
lx1 = x - lCylWidthHalf,
lx2 = x + lCylWidthHalf,
l1Distance = cylinderWidthHalf * 0.6,
l1x = parseInt(x - l1Distance, 10),
l2x = x + (cylinderWidthHalf / 2),
ly = y2 - Math.abs(Math.sqrt((lR * lR) - (lCylWidthHalf * lCylWidthHalf))),
container = graphics.container,
fluid = graphics.fluid,
topLightGlow = graphics.topLightGlow,
topLight = graphics.topLight,
label = graphics.label,
dataLabelContainer = graphics.dataLabelContainer,
canvasBorderElement = graphics.canvasBorderElement,
bulbBorderLight = graphics.bulbBorderLight,
bulbTopLight = graphics.bulbTopLight,
bulbCenterLight = graphics.bulbCenterLight,
trackerContainer = graphics.trackerContainer,
cylLeftLight = graphics.cylLeftLight,
cylRightLight = graphics.cylRightLight,
cylLeftLight1 = graphics.cylLeftLight1,
cylRightLight1 = graphics.cylRightLight1,
hotElement = graphics.hotElement,
gaugeFillColor = getDarkColor(dsConfig.gaugeFillColor, use3DLighting ? 70 : 80),
gaugeFillAlpha = dsConfig.gaugeFillAlpha,
conColor = dsConfig.gaugeContainerColor,
darkConColor = getDarkColor(conColor, 80),
lightConColor = getLightColor(conColor, 80),
gaugeBorderThickness = dsConfig.gaugeBorderThickness,
gaugeBorderColor = dsConfig.gaugeBorderColor,
thPath,
bulbPathType1,
showHoverEffect = dsConfig.showHoverEffect,
plotFillHoverAlpha = dsConfig.plotFillHoverAlpha,
plotFillHoverColor = dsConfig.plotFillHoverColor,
animationObj = iapi.get(configStr, animationObjStr),
animType = animationObj.animType,
animObj = animationObj.animObj,
dummyObj = animationObj.dummyObj,
animationDuration = animationObj.duration,
animation = animationObj && animationObj.duration,
eventArgs,
fluidAttrFn,
thermometerAttrFn,
fluidAnimDuration,
thmAnimDuration,
canvasRight = chartConfig.canvasRight,
canvasBottom = chartConfig.canvasBottom,
canvasWidth = chartConfig.canvasWidth,
style = iapi.config.dataLabelStyle,
// css = {
// fontFamily: style.fontFamily,
// fontSize: style.fontSize,
// lineHeight: style.lineHeight,
// fontWeight: style.fontWeight,
// fontStyle: style.fontStyle
// },
animCallbackFn = function(){
iapi._animCallBack && iapi._animCallBack();
},
applyAttr = function (element, attrString, attrObj, callback) {
if (attrString === ATTRFN) {
element.attr(attrObj);
}
else {
element.animateWith(dummyObj, animObj, attrObj, animationDuration, animType, callback);
}
return element;
},
fluidAnimCallback,
fluidAttr = dsConfig.fluidAttr;
if (!fluidAttr) {
fluidAttr = dsConfig.fluidAttr = {};
}
if (showHoverEffect) {
fluidAttr.hover = {
fill : convertColor(getDarkColor(plotFillHoverColor, use3DLighting ? 70 : 80),
plotFillHoverAlpha)
};
}
fluidAttr.out = {
fill : convertColor(gaugeFillColor, gaugeFillAlpha)
};
thPath = [M, x3, y, A, topRoundR, topRoundR, 0, 0, 0, x1, y4,
L, x1, y1, A, r, r, 0, 1, 0, x2, y1, L, x2, y4,
A, topRoundR, topRoundR, 0, 0, 0, x4, y, Z];
//Setting macros for annotation
chartConfig.gaugeStartX = canvasLeft;
chartConfig.gaugeEndX = canvasRight;
chartConfig.gaugeStartY = canvasTop;
chartConfig.gaugeEndY = canvasBottom;
chartConfig.gaugeCenterX = canvasLeft + (canvasWidth * 0.5);
chartConfig.gaugeCenterY = canvasTop + (canvasHeight * 0.5);
chartConfig.gaugeRadius = canvasWidth * 0.5;
eventArgs = {
value: dsConfig.value,
displayValue: dsConfig.displayValue,
toolText: dsConfig.toolText
};
/*
* Creating a container group for the graphic element of column plots if
* not present and attaching it to its parent group.
*/
if (!container) {
container = graphics.container = paper.group('thermometer', parentContainer);
canvasBorderElement = graphics.canvasBorderElement = paper.path(container);
fluid = graphics.fluid = paper.path(container).attr({
'stroke-width' : 0
});
topLight = graphics.topLight = paper.path(container).attr({
'stroke-width' : 1
});
topLightGlow = graphics.topLightGlow = paper.path(container).attr({
'stroke-width' : 0
});
bulbBorderLight = graphics.bulbBorderLight = paper.path(container).attr({
'stroke-width' : 0,
stroke : '#00FF00'
});
bulbTopLight = graphics.bulbTopLight = paper.path(container).attr({
'stroke-width' : 0
});
bulbCenterLight = graphics.bulbCenterLight = paper.path(container).attr({
'stroke-width' : 0
});
cylLeftLight = graphics.cylLeftLight = paper.path(container).attr({
'stroke-width' : 0
});
cylRightLight = graphics.cylRightLight = paper.path(container).attr({
'stroke-width' : 0
});
cylLeftLight1 = graphics.cylLeftLight1 = paper.path(container).attr({
'stroke-width' : 0
});
cylRightLight1 = graphics.cylRightLight1 = paper.path(container).attr({
'stroke-width' : 0
});
trackerContainer = graphics.trackerContainer = paper.group('col-hot', trackerLayer);
hotElement = graphics.hotElement = paper.path({
stroke: TRACKER_FILL,
fill: TRACKER_FILL,
ishot: true
}, trackerContainer)
.click(function (setDataArr) {
var ele = this;
plotEventHandler.call(ele, iapi, setDataArr);
})
.hover(
function (data) {
var ele = this;
if (dsConfig.showHoverEffect){
graphics.fluid && graphics.fluid.attr(fluidAttr.hover);
}
plotEventHandler.call(ele, iapi, data, ROLLOVER);
},
function (data) {
var ele = this;
if (dsConfig.showHoverEffect){
graphics.fluid && graphics.fluid.attr(fluidAttr.out);
}
plotEventHandler.call(ele, iapi, data, ROLLOUT);
}
);
dataLabelContainer = graphics.dataLabelContainer = paper.group('datalabel', dataLabelsLayer);
// label = graphics.label = paper.text({
// text: BLANK,
// 'text-anchor': POSITION_MIDDLE,
// 'vertical-align': POSITION_TOP
// }, dataLabelContainer);
if (animation) {
fluidAttrFn = ANIMATEFN;
fluidAnimDuration = animation;
fluidAnimCallback = animCallbackFn;
// set the initial view for animation
fluid.attr({
path: [M, lx1, ly, A, lR, lR, 0, 1, 0, lx2, ly, L, lx2, ly, lx1, ly, Z]
});
}
else {
fluidAttrFn = ATTRFN;
}
thermometerAttrFn = ATTRFN;
}
else { // redraw
if(animation) {
thermometerAttrFn = fluidAttrFn = ANIMATEFN;
thmAnimDuration = fluidAnimDuration = animation;
fluidAnimCallback = animCallbackFn;
}
else {
thermometerAttrFn = fluidAttrFn = ATTRFN;
}
}
// apply fluid attributes
// animate to the final view
applyAttr(fluid, fluidAttrFn, {
path: [M, lx1, ly, A, lR, lR, 0, 1, 0, lx2, ly, L, lx2, y6, lx1, y6, Z]
}, fluidAnimCallback)
.attr(fluidAttr.out);
// fluid[fluidAttrFn]({
// path: [M, lx1, ly, A, lR, lR, 0, 1, 0, lx2, ly, L, lx2, y6, lx1, y6, Z]
// }, fluidAnimDuration, fluidAnimCallback).attr(fluidAttr.out);
// thermometer attributes
applyAttr(canvasBorderElement, thermometerAttrFn, {
path: thPath
})
.attr({
'stroke-width': gaugeBorderThickness,
stroke: gaugeBorderColor
});
// canvasBorderElement[thermometerAttrFn]({
// path: thPath
// }, thmAnimDuration).attr({
// 'stroke-width': gaugeBorderThickness,
// stroke: gaugeBorderColor
// });
applyAttr(topLight, thermometerAttrFn, {
path: [M, lx1, scaleY, L, lx2, scaleY]
})
.attr({
stroke : convertColor(gaugeFillColor, 40)
});
// topLight[thermometerAttrFn]({
// path: [M, lx1, scaleY, L, lx2, scaleY]
// }, thmAnimDuration).attr({
// stroke : convertColor(gaugeFillColor, 40)
// });
applyAttr(hotElement, thermometerAttrFn, {
path: thPath
})
.tooltip(dsConfig.toolText);
hotElement.data(EVENTARGS, eventArgs);
// hotElement[thermometerAttrFn]({
// path: thPath
// }, thmAnimDuration)
// .tooltip(dsConfig.toolText);
if(dsConfig.showValue){
label = graphics.label;
if (!label) {
label = graphics.label = paper.text({
text: dsConfig.displayValue,
x: x,
y: y2 + r + (dsConfig.valuePadding || 0),
'text-anchor': POSITION_MIDDLE,
'vertical-align': POSITION_TOP,
fill: style.color,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
}, dataLabelContainer);
label.show();
}
else {
applyAttr(label.show(), thermometerAttrFn, {
x: x,
y: y2 + r + (dsConfig.valuePadding || 0),
fill: style.color,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
})
.attr({
text: dsConfig.displayValue
});
}
// label.show()[thermometerAttrFn]({
// x: x,
// y: y2 + r + (dsConfig.valuePadding || 0),
// fill: style.color,
// 'text-bound': [style.backgroundColor, style.borderColor,
// style.borderThickness, style.borderPadding,
// style.borderRadius, style.borderDash]
// }, thmAnimDuration).attr({
// text: dsConfig.displayValue
// }).css(css);
}
else {
label = graphics.label;
label && label.hide();
}
// Set elements to show the 3d effects
if (use3DLighting) {
applyAttr(topLightGlow.show(), thermometerAttrFn, {
path: [M, lx1, scaleY, L, lx2, scaleY, lx2, y4, lx1, y4, Z]
})
.attr({
fill : toRaphaelColor({
FCcolor : {
color: gaugeFillColor + COMMASTRING + gaugeFillColor,
alpha: topLightGlowAlphaStr,
ratio: topLightGlowRatioStr,
radialGradient: true,
cx : 0.5,
cy : 1,
r : topLightGlowRStr
}
})
});
// topLightGlow.show()[thermometerAttrFn]({
// path: [M, lx1, scaleY, L, lx2, scaleY, lx2, y4, lx1, y4, Z]
// }, thmAnimDuration).attr({
// fill : toRaphaelColor({
// FCcolor : {
// color: gaugeFillColor + COMMASTRING + gaugeFillColor,
// alpha: '40,0',
// ratio: '0,80',
// radialGradient: true,
// cx : 0.5,
// cy : 1,
// r : '70%'
// }
// })
// });
// draw the light effect for the bulb
bulbPathType1 = [M, x1, y1, A, r, r, 0, 0, 1, x2, y1,
A, r, r, 0, 0, 0, x1, y1,
A, r, r, 0, 1, 0, x2, y1, Z];
applyAttr(bulbBorderLight.show(), thermometerAttrFn, {
path: bulbPathType1
})
.attr({
fill : toRaphaelColor({
FCcolor : {
cx: 0.5,
cy: 0.5,
r: bulbBorderLightRStr,
color : darkConColor + COMMASTRING + lightConColor,
alpha : bulbBorderLightAlphaStr,
ratio : bulbBorderLightRatioStr,
radialGradient : true
}
})
});
// bulbBorderLight.show()[thermometerAttrFn]({
// path: bulbPathType1
// }, thmAnimDuration).attr({
// fill : toRaphaelColor({
// FCcolor : {
// cx: 0.5,
// cy: 0.5,
// r: '50%',
// color : darkConColor + COMMASTRING + lightConColor,
// alpha : '0,50',
// ratio : '78,30',
// radialGradient : true
// }
// })
// });
applyAttr(bulbTopLight.show(), thermometerAttrFn, {
path: bulbPathType1
})
.attr({
fill : toRaphaelColor({
FCcolor : {
cx: 0.3,
cy: 0.1,
r: HUNDREDPERCENT,
color : lightConColor + COMMASTRING + darkConColor,
alpha : bulbTopLightAlphaStr,
ratio : bulbTopLightRatioStr,
radialGradient : true
}
})
});
// bulbTopLight.show()[thermometerAttrFn]({
// path: bulbPathType1
// }, thmAnimDuration).attr({
// fill : toRaphaelColor({
// FCcolor : {
// cx: 0.3,
// cy: 0.1,
// r: HUNDREDPERCENT,
// color : lightConColor + COMMASTRING + darkConColor,
// alpha : '60,0',
// ratio : '0,30',
// radialGradient : true
// }
// })
// });
applyAttr(bulbCenterLight.show(), thermometerAttrFn, {
path: bulbPathType1
})
.attr({
fill : toRaphaelColor({
FCcolor : {
cx: 0.25,
cy: 0.7,
r: HUNDREDPERCENT,
color : lightConColor + COMMASTRING + darkConColor,
alpha : bulbCenterLightAlphaStr,
ratio : bulbCenterLightRatioStr,
radialGradient : true
}
})
});
// bulbCenterLight.show()[thermometerAttrFn]({
// path: bulbPathType1
// }, thmAnimDuration).attr({
// fill : toRaphaelColor({
// FCcolor : {
// cx: 0.25,
// cy: 0.7,
// r: HUNDREDPERCENT,
// color : lightConColor + COMMASTRING + darkConColor,
// alpha : '80,0',
// ratio : '0,70',
// radialGradient : true
// }
// })
// });
applyAttr(cylLeftLight.show(), thermometerAttrFn, {
path: [M, x, y, L, x3, y,
A, topRoundR, topRoundR, 0, 0, 0, x1, y4,
L, x1, y1, x, y1, Z]
})
.attr({
fill : toRaphaelColor({
FCcolor : {
color : lightConColor + COMMASTRING + darkConColor,
alpha : cylLeftLightAlphaStr,
ratio : cylLeftLightRatioStr,
angle : 0
}
})
});
// cylLeftLight.show()[thermometerAttrFn]({
// path: [M, x, y, L, x3, y,
// A, topRoundR, topRoundR, 0, 0, 0, x1, y4,
// L, x1, y1, x, y1, Z]
// }, thmAnimDuration).attr({
// fill : toRaphaelColor({
// FCcolor : {
// color : lightConColor + COMMASTRING + darkConColor,
// alpha : '50,0',
// ratio : '0,80',
// angle : 0
// }
// })
// });
applyAttr(cylRightLight.show(), thermometerAttrFn, {
path: [M, x1, y, L, x4, y,
A, topRoundR, topRoundR, 0, 0, 1, x2, y4,
L, x2, y1, x1, y1, Z]
})
.attr({
fill : toRaphaelColor({
FCcolor : {
color : lightConColor + COMMASTRING + darkConColor + COMMASTRING + darkConColor,
alpha : cylRightLightAlphaStr,
ratio : cylRightLightRatioStr,
angle : 180
}
})
});
// cylRightLight.show()[thermometerAttrFn]({
// path: [M, x1, y, L, x4, y,
// A, topRoundR, topRoundR, 0, 0, 1, x2, y4,
// L, x2, y1, x1, y1, Z]
// }, thmAnimDuration).attr({
// fill : toRaphaelColor({
// FCcolor : {
// color : lightConColor + COMMASTRING + darkConColor + COMMASTRING + darkConColor,
// alpha : '50,0,0',
// ratio : '0,40,60',
// angle : 180
// }
// })
// });
applyAttr(cylLeftLight1.show(), thermometerAttrFn, {
path: [M, l1x, y4, L, x1, y4, x1, y1, l1x, y1, Z]
})
.attr({
fill : toRaphaelColor({
FCcolor : {
color : lightConColor + COMMASTRING + darkConColor,
alpha : bulbTopLightAlphaStr,
ratio : zeroCommaHundredStr,
angle : 180
}
})
});
// cylLeftLight1.show()[thermometerAttrFn]({
// path: [M, l1x, y4, L, x1, y4, x1, y1, l1x, y1, Z]
// }, thmAnimDuration).attr({
// fill : toRaphaelColor({
// FCcolor : {
// color : lightConColor + COMMASTRING + darkConColor,
// alpha : '60,0',
// ratio : zeroCommaHundredStr,
// angle : 180
// }
// })
// });
applyAttr(cylRightLight1.show(), thermometerAttrFn, {
path: [M, l1x - 0.01, y4, L, l2x, y4, l2x, y1, l1x - 0.01, y1, Z]
})
.attr({
fill : toRaphaelColor({
FCcolor : {
color : lightConColor + COMMASTRING + darkConColor,
alpha : bulbTopLightAlphaStr,
ratio : zeroCommaHundredStr,
angle : 0
}
})
});
// cylRightLight1.show()[thermometerAttrFn]({
// path: [M, l1x - 0.01, y4, L, l2x, y4, l2x, y1, l1x - 0.01, y1, Z]
// }, thmAnimDuration).attr({
// fill : toRaphaelColor({
// FCcolor : {
// color : lightConColor + COMMASTRING + darkConColor,
// alpha : '60,0',
// ratio : zeroCommaHundredStr,
// angle : 0
// }
// })
// });
}
else { // hide all 3d effect elements
topLightGlow.hide();
bulbBorderLight.hide();
bulbTopLight.hide();
bulbCenterLight.hide();
cylLeftLight.hide();
cylRightLight.hide();
cylLeftLight1.hide();
cylRightLight1.hide();
}
// call the call back if there is no animation
if (!fluidAnimCallback) {
animCallbackFn();
}
},
getDataLimits : function () {
var dataSet = this,
datasetConfig = dataSet.config,
min,
max;
max = min = datasetConfig.value;
datasetConfig.maxValue = max;
datasetConfig.minValue = min;
return {
forceMin : true,
forceMax : true,
max : max,
min : min
};
},
updateData : function (dataObj, index, draw) {
var dataSet = this,
conf = dataSet.config,
prevMax = conf.maxValue,
prevMin = conf.prevMin,
value = conf.value,
chart = dataSet.chart,
drawManager = dataSet.groupManager || dataSet,
chartComponents = chart.components,
scale = chartComponents.scale;
dataSet.setValue(dataObj.data[0]);
conf.maxValue = value;
conf.minValue = value;
if (conf.maxValue !== prevMax || conf.minValue !== prevMin) {
dataSet.maxminFlag = true;
}
if (draw) {
chart._setAxisLimits();
scale.draw();
drawManager.draw();
}
},
addData : function() {
},
removeData : function() {
}
}]);
}]);
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-cylinder',
function () {
var global = this,
lib = global.hcLib,
preDefStr = lib.preDefStr,
ATTRFN = 'attr',
COMPONENT = 'component',
COMMASTRING = lib.COMMASTRING,
plotEventHandler = lib.plotEventHandler,
DATASET = 'dataset',
configStr = preDefStr.configStr,
animationObjStr = preDefStr.animationObjStr,
ANIMATEFN = 'animate',
A = 'A',
math = Math,
mathMax = math.max,
mathMin = math.min,
convertColor = lib.graphics.convertColor,
toRaphaelColor = lib.toRaphaelColor,
ROLLOVER = 'DataPlotRollOver',
ROLLOUT = 'DataPlotRollOut',
getDarkColor = lib.graphics.getDarkColor,
win = global.window,
userAgent = win.navigator.userAgent,
isIE = /msie/i.test(userAgent) && !win.opera,
Z = 'Z',
HUNDREDPERCENT = '100%',
zeroCommaHundredStr = '0,100',
topLightGlowAlphaStr = '40,0',
btnBorderLightAlphaStr = '50,50,50,50,50,70,50,50',
btnBorderLightRatioStr = '0,15,0,12,0,15,43,15',
backAlphaStr = '30,30,30,30,30,30,30,30',
backRatioStr = '0,15,43,15,0,12,0,15',
frontRatioStr = '0,15,0,12,0,15,43,15',
TRACKER_FILL = 'rgba(192,192,192,'+ (isIE ? 0.002 : 0.000001) +')',
M = 'M',
L = 'L',
EVENTARGS = 'eventArgs',
POSITION_TOP = preDefStr.POSITION_TOP,
POSITION_MIDDLE = preDefStr.POSITION_MIDDLE,
pluckNumber = lib.pluckNumber,
getLightColor = lib.graphics.getLightColor,
getScaleFactor = function (origW, origH, canvasWidth, canvasHeight) {
var scaleFactor;
origH = pluckNumber(origH, canvasHeight);
origW = pluckNumber(origW, canvasWidth);
if (!origH || !origW) {
scaleFactor = 1;
}
// Now, if the ratio of original width,height & stage width,height are same
else if ((origW / canvasWidth) == (origH / canvasHeight)) {
//In this case, the transformation value would be the same, as the ratio
//of transformation of width and height is same.
scaleFactor = canvasWidth / origW;
} else {
//If the transformation factors are different, we do a constrained scaling
//We get the aspect whose delta is on the lower side.
scaleFactor = Math.min((canvasWidth / origW), (canvasHeight / origH));
}
return scaleFactor;
};
FusionCharts.register(COMPONENT,[DATASET, 'cylinder',{
_manageSpace : function () {
var ds = this,
chart = this.chart,
chartConfig = chart.config,
chartWidth = chartConfig.width,
chartHwight = chartConfig.height,
canvasWidth = chartConfig.canvasWidth,
canvasHeight = chartConfig.canvasHeight,
canvasLeft = chartConfig.canvasLeft,
canvasTop = chartConfig.canvasTop,
canvasRight = chartConfig.canvasRight,
canvasBottom = chartConfig.canvasBottom,
xDefined = chartConfig.xDefined,
yDefined = chartConfig.yDefined,
rDefined = chartConfig.rDefined,
hDefined = chartConfig.hDefined,
gaugeOriginX = chartConfig.gaugeOriginX,
gaugeOriginY = chartConfig.gaugeOriginY,
gaugeRadius = chartConfig.gaugeRadius,
gaugeHeight = chartConfig.gaugeHeight,
gaugeYScale = chartConfig.gaugeYScale,
scaleFactor = getScaleFactor(chartConfig.origW, chartConfig.origH, chartWidth, chartHwight),
top = 0,
bottom = 0,
left = 0,
right = 0,
gaugeRight,
centerPos,
gaugeDiameter,
gaugeYfactor,
measure,
canvasLeftShift;
// manage the space for the datalabels
measure = ds._getLabelSpace();
canvasBottom += measure;
canvasHeight -= measure;
bottom += measure;
// lightX = r * 0.85,
// x5 = x - lightX,
// x6 = x + lightX,
// lightY = Math.sqrt((1 - ((lightX * lightX) / (r * r))) * r2 * r2),
// manage the thermometer space
/* First calculate the radius */
//if Not defined the radius then calculate it.
if (!rDefined) {
gaugeRadius = mathMax(mathMin(canvasWidth, canvasHeight * 1.2) / 2, 5);
}
else {
gaugeRadius = gaugeRadius * scaleFactor;
}
// store the effective radius
chartConfig.effectiveR = gaugeRadius;
gaugeDiameter = gaugeRadius * 2;
gaugeYfactor = gaugeRadius * gaugeYScale;
top += gaugeYfactor;
canvasTop += gaugeYfactor;
bottom += gaugeYfactor;
canvasBottom += gaugeYfactor;
canvasHeight -= (2 * gaugeYfactor);
/* Calculate the x */
// if x is user defined
if (xDefined) {
gaugeOriginX = gaugeOriginX * scaleFactor;
canvasLeftShift = (gaugeOriginX - gaugeRadius) - canvasLeft;
}
else { // else, place the gauge at the center
centerPos = (canvasRight - canvasLeft) / 2;
// now as per the center position calculate the extra left gap
canvasLeftShift = (centerPos - gaugeRadius);
// check whether we have space to put the gauge at center
gaugeRight = canvasLeftShift + gaugeDiameter;
if (gaugeRight > canvasWidth) {
canvasLeftShift = canvasWidth - gaugeDiameter;
}
}
left += canvasLeftShift;
canvasLeft += canvasLeftShift;
canvasWidth -= canvasLeftShift;
// to make the canvas width same as gauge's cylinder width increase the right padding
right += (canvasWidth - gaugeDiameter);
if (yDefined) {
gaugeOriginY = gaugeOriginY * scaleFactor;
}
if (!hDefined) { // if height is not defined
if (yDefined) { // if y is defined then adjust thermometer height is available space
gaugeHeight = gaugeOriginY - canvasTop;
}
else {
gaugeHeight = canvasHeight;
gaugeOriginY = canvasTop + gaugeHeight;
}
}
else { // height is defined
gaugeHeight = gaugeHeight * scaleFactor;
if (yDefined) {// if both are defined, adjust the top to accomodate this
top += gaugeOriginY - gaugeHeight - canvasTop;
}
else {
gaugeOriginY = canvasTop + gaugeHeight;
}
}
// finally adjust the bottom to accomodate y and height
bottom += (canvasTop + canvasHeight) - gaugeOriginY;
return {
top : top,
bottom : bottom + 8, // space for thick border at the glass bottom
left: left,
right: right
};
},
draw : function () {
var dataSet = this,
dsConfig = dataSet.config,
iapi = dataSet.chart,
graphics = dataSet.graphics || (dataSet.graphics = {}),
layers = iapi.graphics,
dataLabelsLayer = layers.datalabelsGroup,
trackerLayer = layers.trackerGroup,
parentContainer = layers.datasetGroup,
fluidTop = graphics.fluidTop,
fluid = graphics.fluid,
cylinterTop = graphics.cylinterTop,
frontLight1 = graphics.frontLight1,
frontLight = graphics.frontLight,
front = graphics.front,
back = graphics.back,
btnBorderLight = graphics.btnBorderLight,
btnBorder1 = graphics.btnBorder1,
btnBorder = graphics.btnBorder,
label = graphics.label,
dataLabelContainer = graphics.dataLabelContainer,
trackerContainer = graphics.trackerContainer,
hotElement = graphics.hotElement,
chartComponents = iapi.components,
scale = chartComponents.scale,
chartConfig = iapi.config,
paper = chartComponents.paper,
canvasLeft = chartConfig.canvasLeft,
canvasTop = chartConfig.canvasTop,
canvasHeight = chartConfig.canvasHeight,
r = chartConfig.effectiveR || 40,
value = pluckNumber(dsConfig.value, scale.getLimit().min),
gaugePos = scale.getPixel(value),
x = canvasLeft + r,
y = canvasTop,
h = canvasHeight,
style = iapi.config.dataLabelStyle,
// css = {
// fontFamily: style.fontFamily,
// fontSize: style.fontSize,
// lineHeight: style.lineHeight,
// fontWeight: style.fontWeight,
// fontStyle: style.fontStyle
// },
fluidColor = dsConfig.gaugeFillColor,
fluidDarkColor = getDarkColor(fluidColor, 70),
fluidLightColor = getLightColor(fluidColor, 70),
fluidEdgeColor = getDarkColor(fluidDarkColor, 90),
fluidAlpha = chartConfig.gaugeFillAlpha,
fluidStroke = 3,
// Thermometer Glass color
gaugeContainerColor = dsConfig.gaugeContainerColor,
darkConColor = getDarkColor(gaugeContainerColor, 80),
darkConColor1 = getDarkColor(gaugeContainerColor, 90),
lightConColor = getLightColor(gaugeContainerColor, 80),
r3dFactor = chartConfig.gaugeYScale,
container = graphics.container,
r2 = r * r3dFactor,
fluidStrHF = fluidStroke / 2,
r3 = r - fluidStrHF,
y2 = y + h,
y3 = gaugePos,
x1 = x - r,
x2 = x + r,
x3 = x1 + fluidStrHF,
x4 = x2 - fluidStrHF,
xBt1 = x1 - 2,
xBt2 = x2 + 2,
rBt1 = r + 2,
rBt2 = r2 + 2,
yBt1 = y2 + 4,
yBt2 = yBt1 + 0.001,
lightX = r * 0.85,
x5 = x - lightX,
x6 = x + lightX,
lightY = Math.sqrt((1 - ((lightX * lightX) / (r * r))) * r2 * r2),
y4 = y + lightY,
y5 = y2 + lightY,
y6 = y - 1,
use3DLighting = chartConfig.use3DLighting,
topColorStr,
topStrokeStr,
showHoverEffect = dsConfig.showHoverEffect,
plotFillHoverAlpha = dsConfig.plotFillHoverAlpha,
plotFillHoverColor = dsConfig.plotFillHoverColor,
fluidHoverDarkColor,
fluidHoverLightColor,
fluidHoverEdgeColor,
// todo: all attributes need to be parsed and ready during configuration
animationObj = iapi.get(configStr, animationObjStr),
animType = animationObj.animType,
animObj = animationObj.animObj,
dummyObj = animationObj.dummyObj,
animationDuration = animationObj.duration,
animation = animationObj && animationObj.duration,
eventArgs,
fluidAttrFn,
gaugeAttrFn,
fluidAnimDuration,
gaugeAnimDuration,
animCallbackFn = function(){
iapi._animCallBack && iapi._animCallBack();
},
applyAttr = function (element, attrString, attrObj, callback) {
if (attrString === ATTRFN) {
element.attr(attrObj);
}
else {
element.animateWith(dummyObj, animObj, attrObj, animationDuration, animType, callback);
}
return element;
},
fluidAnimCallback,
fluidAttr = dsConfig.fluidAttr,
backColor,
frontColor,
fluidFill,
canvasRight = chartConfig.canvasRight,
canvasBottom = chartConfig.canvasBottom,
canvasWidth = chartConfig.canvasWidth,
borderColor = convertColor(darkConColor, 50);
//Setting macros for annotation
chartConfig.gaugeStartX = canvasLeft;
chartConfig.gaugeEndX = canvasRight;
chartConfig.gaugeStartY = canvasTop;
chartConfig.gaugeEndY = canvasBottom;
chartConfig.gaugeCenterX = canvasLeft + (canvasWidth * 0.5);
chartConfig.gaugeCenterY = canvasTop + (canvasHeight * 0.5);
chartConfig.gaugeRadius = canvasWidth * 0.5;
if (!fluidAttr) {
fluidAttr = dsConfig.fluidAttr = {};
}
eventArgs = {
value: dsConfig.value,
displayValue: dsConfig.displayValue,
toolText: dsConfig.toolText
};
/*
* Creating a container group for the graphic element of column plots if
* not present and attaching it to its parent group.
*/
if (!container) { // first draw
container = graphics.container = paper.group('thermometer', parentContainer);
btnBorder = graphics.btnBorder = paper.path(container).attr({
'stroke-width' : 4
});
btnBorder1 = graphics.btnBorder1 = paper.path(container).attr({
'stroke-width' : 4
});
btnBorderLight = graphics.btnBorderLight = paper.path(container).attr({
'stroke-width' : 0
});
back = graphics.back = paper.path(container).attr({
'stroke-width' : 1
});
fluid = graphics.fluid = paper.path(container).attr({
'stroke-width' : 0
});
fluidTop = graphics.fluidTop = paper.path(container).attr({
'stroke-width' : 2
});
front = graphics.front = paper.path(container).attr({
'stroke-width' : 1
});
frontLight = graphics.frontLight = paper.path(container).attr({
'stroke-width' : 0
});
frontLight1 = graphics.frontLight1 = paper.path(container).attr({
'stroke-width' : 0
});
cylinterTop = graphics.cylinterTop = paper.path(container).attr({
'stroke-width' : 2
});
trackerContainer = graphics.trackerContainer = paper.group('col-hot', trackerLayer);
hotElement = graphics.hotElement = paper.path({
stroke: TRACKER_FILL,
fill: TRACKER_FILL,
ishot: true
}, trackerContainer)
.click(function (setDataArr) {
var ele = this;
plotEventHandler.call(ele, iapi, setDataArr);
})
.hover(
function (data) {
var ele = this;
if (dsConfig.showHoverEffect){
graphics.fluid && graphics.fluid.attr(fluidAttr.bodyHover);
graphics.fluidTop && graphics.fluidTop.attr(fluidAttr.topHover);
}
plotEventHandler.call(ele, iapi, data, ROLLOVER);
},
function (data) {
var ele = this;
if (dsConfig.showHoverEffect){
graphics.fluid && graphics.fluid.attr(fluidAttr.bodyOut);
graphics.fluidTop && graphics.fluidTop.attr(fluidAttr.topOut);
}
plotEventHandler.call(ele, iapi, data, ROLLOUT);
}
// rolloverResponseSetter(graphics, fluidHoverCosmetics),
// rolloutResponseSetter(graphics, fluidCosmetics)
);
dataLabelContainer = graphics.dataLabelContainer = paper.group('datalabel', dataLabelsLayer);
// label = graphics.label = paper.text({
// text: BLANK,
// 'text-anchor': POSITION_MIDDLE,
// 'vertical-align': POSITION_TOP
// }, dataLabelContainer);
if (animation) {
fluidAttrFn = ANIMATEFN;
fluidAnimDuration = animation;
fluidAnimCallback = animCallbackFn;
// set the initial view for animation
fluid.attr({
path: [M, x1, y2, A, r, mathMax(r2, 1), 0, 0, 0, x2, y2,
L, x2, y2, A, r, mathMax(r2, 1), 0, 0, 1, x1, y2, Z]
});
fluidTop.attr({
path: [M, x3, y2, A, r3, r2, 0, 0, 0, x4, y2, L, x4, y2, A, r3, r2, 0, 0, 0, x3, y2, Z]
});
}
else {
fluidAttrFn = ATTRFN;
}
gaugeAttrFn = ATTRFN;
}
else {//redraw
if(animation) {
gaugeAttrFn = fluidAttrFn = ANIMATEFN;
gaugeAnimDuration = fluidAnimDuration = animation;
fluidAnimCallback = animCallbackFn;
}
else {
gaugeAttrFn = fluidAttrFn = ATTRFN;
}
}
// prepare attributes
if (use3DLighting) {
backColor = lightConColor + COMMASTRING + darkConColor + COMMASTRING + lightConColor +
COMMASTRING + darkConColor + COMMASTRING + darkConColor1 + COMMASTRING +
darkConColor1 + COMMASTRING + darkConColor + COMMASTRING + lightConColor;
fluidFill = toRaphaelColor({
FCcolor : {
cx: 0.5,
cy: 0,
r: HUNDREDPERCENT,
color : fluidLightColor + COMMASTRING + fluidDarkColor,
alpha : fluidAlpha + COMMASTRING + fluidAlpha ,
ratio : zeroCommaHundredStr,
radialGradient : true
}
});
topColorStr = toRaphaelColor({
FCcolor : {
cx: 0.5,
cy: 0.7,
r: HUNDREDPERCENT,
color : fluidLightColor + COMMASTRING + fluidDarkColor,
alpha : fluidAlpha + COMMASTRING + fluidAlpha ,
ratio : zeroCommaHundredStr,
radialGradient : true
}
});
topStrokeStr = convertColor(fluidLightColor, fluidAlpha);
frontColor = lightConColor + COMMASTRING + darkConColor + COMMASTRING + lightConColor +
COMMASTRING + lightConColor + COMMASTRING + darkConColor + COMMASTRING +
lightConColor + COMMASTRING + darkConColor + COMMASTRING + lightConColor;
//draw the front light left
frontLight.show().attr({
fill : toRaphaelColor({
FCcolor : {
color : frontColor,
alpha : topLightGlowAlphaStr,
ratio : zeroCommaHundredStr,
angle : 0
}
})
});
applyAttr(frontLight, gaugeAttrFn, {
path: [M, x1, y2, A, r, r2, 1, 0, 0, x5, y5, L, x5, y4, A, r, r2, 0, 0, 1, x1, y, Z]
});
//draw the front light right
frontLight1.show().attr({
fill : toRaphaelColor({
FCcolor : {
color : frontColor,
alpha : topLightGlowAlphaStr,
ratio : zeroCommaHundredStr,
angle : 180
}
})
});
applyAttr(frontLight1, gaugeAttrFn, {
path: [M, x6, y5, A, r, r2, 0, 0, 0, x2, y2, L, x2, y, A, r, r2, 1, 0, 0, x6, y4, Z]
});
}
else {
backColor = lightConColor + COMMASTRING + darkConColor + COMMASTRING + darkConColor +
COMMASTRING + darkConColor + COMMASTRING + darkConColor + COMMASTRING +
darkConColor + COMMASTRING + darkConColor + COMMASTRING + lightConColor;
topColorStr = fluidFill = convertColor(fluidDarkColor, fluidAlpha);
topStrokeStr = convertColor(fluidEdgeColor);
frontColor = darkConColor + COMMASTRING + darkConColor + COMMASTRING + darkConColor +
COMMASTRING + darkConColor + COMMASTRING + darkConColor + COMMASTRING +
darkConColor + COMMASTRING + darkConColor + COMMASTRING + darkConColor;
frontLight.hide();
frontLight1.hide();
}
//draw the fluid fill
fluidAttr.bodyOut = {
fill : fluidFill
};
fluidAttr.topOut = {
stroke : topStrokeStr,
fill : topColorStr
};
// create the hover attributes
if (showHoverEffect) {
fluidHoverDarkColor = getDarkColor(plotFillHoverColor, 70);
fluidHoverLightColor = getLightColor(plotFillHoverColor, 70);
fluidHoverEdgeColor = getDarkColor(fluidHoverDarkColor, 90);
if (use3DLighting) {
fluidAttr.bodyHover = {
fill : toRaphaelColor({
FCcolor : {
cx: 0.5,
cy: 0,
r: HUNDREDPERCENT,
color : fluidHoverLightColor + COMMASTRING + fluidHoverDarkColor,
alpha : plotFillHoverAlpha + COMMASTRING + plotFillHoverAlpha ,
ratio : zeroCommaHundredStr,
radialGradient : true
}
})
};
fluidAttr.topHover = {
stroke : convertColor(fluidHoverLightColor, plotFillHoverAlpha),
fill : toRaphaelColor({
FCcolor : {
cx: 0.5,
cy: 0.7,
r: HUNDREDPERCENT,
color : fluidHoverLightColor + COMMASTRING + fluidHoverDarkColor,
alpha : plotFillHoverAlpha + COMMASTRING + plotFillHoverAlpha ,
ratio : zeroCommaHundredStr,
radialGradient : true
}
})
};
}
else {
fluidAttr.bodyHover = {
fill : convertColor(fluidHoverDarkColor, plotFillHoverAlpha)
};
fluidAttr.topHover = {
stroke : convertColor(fluidHoverEdgeColor),
fill : convertColor(fluidHoverDarkColor, plotFillHoverAlpha)
};
}
}
fluid.attr(fluidAttr.bodyOut);
fluidTop.attr(fluidAttr.topOut);
// update fluid's view
applyAttr(fluid, fluidAttrFn, {
path: [M, x1, y2, A, r, mathMax(r2, 1), 0, 0, 0, x2, y2,
L, x2, y3, A, r, mathMax(r2, 1), 0, 0, 1, x1, y3, Z]
}, fluidAnimCallback);
// fluid[fluidAttrFn]({
// path: [M, x1, y2, A, r, mathMax(r2, 1), 0, 0, 0, x2, y2,
// L, x2, y3, A, r, mathMax(r2, 1), 0, 0, 1, x1, y3, Z]
// }, fluidAnimDuration, fluidAnimCallback);
applyAttr(fluidTop, fluidAttrFn, {
path: [M, x3, y3, A, r3, r2, 0, 0, 0, x4, y3, L, x4, y3, A, r3, r2, 0, 0, 0, x3, y3, Z]
});
// fluidTop[fluidAttrFn]({
// path: [M, x3, y3, A, r3, r2, 0, 0, 0, x4, y3, L, x4, y3, A, r3, r2, 0, 0, 0, x3, y3, Z]
// }, fluidAnimDuration);
// draw the gauge
btnBorder.attr({
stroke : convertColor(darkConColor, 80)
});
applyAttr(btnBorder, gaugeAttrFn, {
path: [M, xBt1, yBt1, A, rBt1, rBt2, 0, 0, 0, xBt2, yBt1, L, xBt2, yBt2,
A, rBt1, rBt2, 0, 0, 0, xBt1, yBt2, Z]
});
btnBorder1.attr({
stroke : borderColor
});
applyAttr(btnBorder1, gaugeAttrFn, {
path: [M, x1, yBt1, A, r, r2, 0, 0, 0, x2, yBt1, L, x2, yBt2, A, r, r2, 0, 0, 0, x1, yBt2, Z]
});
btnBorderLight.attr({
fill : toRaphaelColor({
FCcolor : {
color : lightConColor + COMMASTRING + darkConColor + COMMASTRING + lightConColor +
COMMASTRING + lightConColor + COMMASTRING + darkConColor + COMMASTRING +
fluidDarkColor + COMMASTRING + darkConColor + COMMASTRING + lightConColor,
alpha : btnBorderLightAlphaStr,
ratio : btnBorderLightRatioStr,
angle : 0
}
})
});
applyAttr(btnBorderLight, gaugeAttrFn, {
path: [M, x1, y2, A, r, r2, 0, 0, 0, x2, y2, A, r, r2, 0, 0, 0, x1, y2, Z]
});
back.attr({
stroke : borderColor,
fill : toRaphaelColor({
FCcolor : {
color : backColor,
alpha : backAlphaStr,
ratio : backRatioStr,
angle : 0
}
})
});
applyAttr(back, gaugeAttrFn, {
path: [M, x1, y2, A, r, r2, 0, 0, 0, x2, y2, L, x2, y, A, r, r2, 0, 0, 0, x1, y, Z]
});
//draw the front side
front.attr({
stroke : borderColor,
fill : toRaphaelColor({
FCcolor : {
color : frontColor,
alpha : backAlphaStr,
ratio : frontRatioStr,
angle : 0
}
})
});
applyAttr(front, gaugeAttrFn, {
path: [M, x1, y2, A, r, r2, 0, 0, 0, x2, y2, L, x2, y, A, r, r2, 0, 0, 1, x1, y, Z]
});
cylinterTop.attr({
stroke : convertColor(darkConColor, 40)
});
applyAttr(cylinterTop, gaugeAttrFn, {
path: [M, x1, y6, A, r, r2, 0, 0, 0, x2, y6, L, x2, y6, A, r, r2, 0, 0, 0, x1, y6, Z]
});
applyAttr(hotElement, gaugeAttrFn, {
path: [M, x1, y2, x1, yBt1 + 4, A, r, r2, 0, 0, 0, x2, yBt1 + 4, L, x2, y2, x2, y,
A, r, r2, 0, 0, 0, x1, y, Z]
})
.tooltip(dsConfig.toolText);
hotElement.data(EVENTARGS, eventArgs);
// hotElement[gaugeAttrFn]({
// path: [M, x1, y2, x1, yBt1 + 4, A, r, r2, 0, 0, 0, x2, yBt1 + 4, L, x2, y2, x2, y,
// A, r, r2, 0, 0, 0, x1, y, Z]
// }, gaugeAnimDuration)
// .tooltip(dsConfig.toolText);
// draw the label
if(dsConfig.showValue){
label = graphics.label;
if (!label) {
label = graphics.label = paper.text({
text: dsConfig.displayValue,
x: x,
y: y2 + r2 + (dsConfig.valuePadding || 0) + 8, // glass bottom extra thick border
'text-anchor': POSITION_MIDDLE,
'vertical-align': POSITION_TOP,
fill: style.color,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
}, dataLabelContainer);
label.show();
}
else {
label.show().attr({
text: dsConfig.displayValue
});
applyAttr(label, gaugeAttrFn, {
x: x,
y: y2 + r2 + (dsConfig.valuePadding || 0) + 8, // glass bottom extra thick border
fill: style.color,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
});
}
}
else {
label = graphics.label;
label && label.hide();
}
// call the call back if there is no animation
if (!fluidAnimCallback) {
animCallbackFn();
}
}
}, 'thermometer']);
}
]);
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-angulargauge',
function () {
var global = this,
lib = global.hcLib,
R = lib.Raphael,
//strings
BLANK = lib.BLANKSTRING,
BLANKSTRING = BLANK,
//add the tools thats are requared
pluck = lib.pluck,
toPrecision = lib.toPrecision,
getValidValue = lib.getValidValue,
pluckNumber = lib.pluckNumber,
hasSVG = lib.hasSVG,
getFirstValue = lib.getFirstValue,
convertColor = lib.graphics.convertColor,
preDefStr = lib.preDefStr,
configStr = preDefStr.configStr,
animationObjStr = preDefStr.animationObjStr,
getDashStyle = lib.getDashStyle,
parseTooltext = lib.parseTooltext,
COMMASTRING = lib.COMMASTRING,
ZEROSTRING = lib.ZEROSTRING,
ANIM_EFFECT = 'easeIn',
FILLMIXDARK10 = '{dark-10}',
PXSTRING = 'px',
parseUnsafeString = lib.parseUnsafeString,
win = global.window,
doc = win.document,
math = Math,
mathAbs = math.abs,
mathATan2 = math.atan2,
mathPI = math.PI,
math2PI = 2 * mathPI,
deg2rad = mathPI / 180,
POINTER = 'pointer',
NORMALSTRING = 'normal',
EVENTARGS = 'eventArgs',
COMPONENT = 'component',
DATASET = 'dataset',
toRaphaelColor = lib.toRaphaelColor,
hasTouch = doc.documentElement.ontouchstart !== undefined,
getPosition = lib.getPosition,
plotEventHandler = lib.plotEventHandler,
ROLLOVER = 'DataPlotRollOver',
ROLLOUT = 'DataPlotRollOut',
getTouchEvent = function (event) {
return (hasTouch && event.sourceEvent && event.sourceEvent.touches &&
event.sourceEvent.touches[0]) || event;
},
UNDEFINED,
isString = function (s) {
return typeof s === 'string';
},
defined = function (obj) {
return obj !== UNDEFINED && obj !== null;
},
// pInt = function(s, mag) {
// return parseInt(s, mag || 10);
// },
M = 'M',
L = 'L',
Z = 'Z',
setLineHeight = lib.setLineHeight,
HUNDREDSTRING = lib.HUNDREDSTRING,
getAttrFunction = function () {
var rotationStr = 'angle';
return function (hash, val, animation) {
var key,
value,
element = this,
attr3D = this._Attr,
cx = R.vml ? (-1.5) : 0, // correction of -1.5 has to be added for VML.
cy = R.vml ? (-1.5) : 0,
red;
if (!attr3D) {
attr3D = element._Attr = {};
}
// single key-value pair
if (isString(hash) && defined(val)) {
key = hash;
hash = {};
hash[key] = val;
}
// used as a getter: first argument is a string, second is undefined
// And also if first argument is undefined it should return the all attrs object.
if (isString(hash) || hash === undefined) {
//if belongs from the list then handle here
if (hash == rotationStr) {
element = element._Attr[hash];
}
else {//else leve for the original attr
element = element._attr(hash);
}
// setter
}
else {
for (key in hash) {
value = hash[key];
//if belongs from the list then handle here
if (key === rotationStr) {
attr3D[key] = value;
red = value * deg2rad;
attr3D.tooltipPos[0] = attr3D.cx + (attr3D.toolTipRadius * Math.cos(red));
attr3D.tooltipPos[1] = attr3D.cy + (attr3D.toolTipRadius * Math.sin(red));
attr3D.prevValue = value;
if (animation && animation.duration) {
element.animate({
transform: ('R' + value + COMMASTRING + cx + COMMASTRING + cy)
}, animation.duration, ANIM_EFFECT);
}
else {
element.attr({transform: ('R' + value + COMMASTRING + cx + COMMASTRING + cy)});
}
}
else {//else leave for the original attr
element._attr(key, value);
}
}
}
return element;
};
};
FusionCharts.register(COMPONENT, [DATASET, 'angulargauge',{
type : 'angulargauge',
pIndex : 2,
customConfigFn : '_createDatasets',
init : function () {
var dataSet = this;
dataSet.components = dataSet.components || {};
dataSet.idMap = { };
dataSet.configure();
},
configure : function () {
var dataSet = this,
chart = dataSet.chart,
chartConfig = chart.config,
jsonData = chart.jsonData,
chartAttrs = jsonData.chart,
pointer = jsonData.pointers || jsonData.dials,
pointerArr = pointer.pointer || pointer.dial,
data = dataSet.components.data || (dataSet.components.data = []),
components = chart.components,
scale = components.scale,
colorM = components.colorManager,
datasetConfig = dataSet.config || (dataSet.config = {}),
scaleAngle = pluckNumber(chartAttrs.gaugescaleangle, 180),
startAngle = pluckNumber(chartAttrs.gaugestartangle),
endAngle = pluckNumber(chartAttrs.gaugeendangle),
startDefined = defined(startAngle), tempAngle,
//arc on 360deg is not possable SVG limitation so reduce the scale
circleHandler = hasSVG ? 0.001 : 0.01,
endDefined= defined(endAngle),
showGaugeBorder,
pvColor,
scaleOnResize,
showValue,
pointShowValue,
valueY,
dataLabelsStyle,
fontBdrColor,
i,
ln;
chartConfig.displayValueCount = 0;
for (i = 0, ln = pointerArr.length; i < ln; i += 1) {
data[i] = data[i] || (data[i] = {});
data[i].basewidth = pointerArr[i].basewidth;
data[i].color = pointerArr[i].color;
data[i].alpha = pointerArr[i].alpha;
data[i].bgcolor = pointerArr[i].bgcolor;
data[i].borderalpha = pointerArr[i].borderalpha;
data[i].bordercolor = pointerArr[i].bordercolor;
data[i].borderthickness = pointerArr[i].borderthickness;
data[i].editmode = pointerArr[i].editmode;
data[i].id = pluck(pointerArr[i].id, 'dial'+i);
data[i].link = pointerArr[i].link;
data[i].radius = pointerArr[i].radius;
data[i].rearextension = pointerArr[i].rearextension;
data[i].showvalue = pointerArr[i].showvalue;
data[i].tooltext = pointerArr[i].tooltext;
data[i].topwidth = pointerArr[i].topwidth;
data[i].value = pointerArr[i].value;
data[i].valuex = pointerArr[i].valuex;
data[i].valuey = pointerArr[i].valuey;
data[i].baseradius = pointerArr[i].baseradius;
data[i].displayvalue = pointerArr[i].displayvalue;
showValue = datasetConfig.showValue = pluckNumber(chartAttrs.showvalue,
chartAttrs.showrealtimevalue , 0),
pointShowValue = pluckNumber(data[i].showvalue, showValue);
valueY = pluckNumber(getValidValue(data[i].valuey));
if (pointShowValue && !defined(valueY)) {
chartConfig.displayValueCount += 1;
}
}
/*
*All angle should be in range of -360 to 360 of traditional methode
*At the end convert them in computer graphics methode
* relation among them is [scaleAngle = startAngle - endAngle;]
*/
if (scaleAngle > 360 || scaleAngle < -360) {
scaleAngle = scaleAngle > 0 ? 360 : -360;
}
if (endAngle > 360 || endAngle < -360) {
endAngle = endAngle % 360;
}
if (startAngle > 360 || startAngle < -360) {
startAngle = startAngle % 360;
}
//booth defined
if (startDefined && endDefined) {
//override the scale
scaleAngle = startAngle - endAngle;
//validate scale and EndAngle
if (scaleAngle > 360 || scaleAngle < -360) {
scaleAngle = scaleAngle % 360;
endAngle = startAngle - scaleAngle;
}
}
else if (startDefined) {//StartAngle Defined
//derive endAngle
endAngle = startAngle - scaleAngle;
//if derived end angle cross the limit
if (endAngle > 360 || endAngle < -360) {
endAngle = endAngle % 360;
startAngle += endAngle > 0 ? -360 : 360;
}
}
else if (endDefined) {//endAngle Defined
//derive StartAngle
startAngle = endAngle + scaleAngle;
//if derived start angle cross the limit
if (startAngle > 360 || startAngle < -360) {
startAngle = startAngle % 360;
endAngle += startAngle > 0 ? -360 : 360;
}
}
else {//booth will be derived
if (scaleAngle === 360) {
startAngle = 180;
endAngle = - 180;
}
else if (scaleAngle === -360) {
startAngle = -180;
endAngle = -180;
}
else {
tempAngle = scaleAngle / 2;
startAngle = 90 + tempAngle;
endAngle = startAngle - scaleAngle;
}
}
//Full 360 can't be drawn by arc[limitation]
if (Math.abs(scaleAngle) === 360) {
scaleAngle += scaleAngle > 0 ? -circleHandler : circleHandler;
endAngle = startAngle - scaleAngle;
}
//convert all the angles into clockwise cordinate
endAngle = 360 - endAngle;
startAngle = 360 - startAngle;
scaleAngle = -scaleAngle;
//if start angle cross the limit
if (startAngle > 360 || endAngle > 360 ) {
startAngle -= 360;
endAngle -= 360;
}
//convert into red
datasetConfig.gaugeStartAngle = startAngle = startAngle * deg2rad;
datasetConfig.gaugeEndAngle = endAngle = endAngle * deg2rad;
datasetConfig.gaugeScaleAngle = scaleAngle = scaleAngle * deg2rad;
datasetConfig.upperLimit = pluckNumber(chartAttrs.upperlimit);
datasetConfig.lowerLimit = pluckNumber(chartAttrs.lowerlimit);
// set axis configure
scale.setAxisConfig({
startAngle : startAngle,
totalAngle : -scaleAngle
});
scaleOnResize = pluckNumber(chartAttrs.scaleonresize, 1);
datasetConfig.origW = pluckNumber(chartAttrs.origw, scaleOnResize ?
chart.origRenderWidth : chartConfig.width);
datasetConfig.origH = pluckNumber(chartAttrs.origh, scaleOnResize ?
chart.origRenderHeight : chartConfig.height);
chartConfig.showtooltip = pluckNumber(chartAttrs.showtooltip, 1);
// Whether to auto-scale itself with respect to previous size
chartConfig.autoScale = pluckNumber(chartAttrs.autoscale , 1);
datasetConfig.rearExtension = pluckNumber(pointer.rearextension, 0);
datasetConfig.gaugeinnerradius = chartAttrs.gaugeinnerradius;
// gaugeOuterRadius does not have any default value.
datasetConfig.valueBelowPivot = pluckNumber(chartAttrs.valuebelowpivot , 0);
datasetConfig.showShadow = pluckNumber(chartAttrs.showshadow, 1);
showGaugeBorder = pluckNumber(chartAttrs.showgaugeborder, 1);
datasetConfig.gaugeFillMix = lib.getFirstDefinedValue(chartAttrs.colorrangefillmix,
chartAttrs.gaugefillmix, chart.colorRangeFillMix,
'{light-10},{light-70},{dark-10}');
datasetConfig.gaugeFillRatio = lib.getFirstDefinedValue(chartAttrs.colorrangefillratio,
chartAttrs.gaugefillratio, chart.colorRangeFillRatio, chartAttrs.gaugefillratio);
if (datasetConfig.gaugeFillRatio === undefined){
datasetConfig.gaugeFillRatio = ',6';
}else if (datasetConfig.gaugeFillRatio !== BLANK){
//Append a comma before the ratio
datasetConfig.gaugeFillRatio = COMMASTRING + datasetConfig.gaugeFillRatio;
}
datasetConfig.gaugeBorderColor = pluck(chartAttrs.gaugebordercolor, '{dark-20}');
datasetConfig.gaugeBorderThickness = showGaugeBorder ?
pluckNumber(chartAttrs.gaugeborderthickness, 1) : 0;
datasetConfig.gaugeBorderAlpha = pluckNumber(chartAttrs.gaugeborderalpha, 100);
//Gauge Border properties
//Parse the color, alpha and ratio array for each color range arc.
pvColor = colorM.parseColorMix(
pluck(chartAttrs.pivotfillcolor, chartAttrs.pivotcolor, chartAttrs.pivotbgcolor,
colorM.getColor('pivotColor')),
pluck(chartAttrs.pivotfillmix, '{light-10},{light-30},{dark-20}'));
datasetConfig.pivotFillAlpha = colorM.parseAlphaList(pluck(chartAttrs.pivotfillalpha,
HUNDREDSTRING), pvColor.length);
datasetConfig.pivotFillRatio = colorM.parseRatioList(pluck(chartAttrs.pivotfillratio, ZEROSTRING),
pvColor.length);
datasetConfig.pivotFillColor = pvColor.join();
datasetConfig.pivotFillAngle = pluckNumber(chartAttrs.pivotfillangle, 0);
datasetConfig.isRadialGradient = pluck(chartAttrs.pivotfilltype, 'radial').toLowerCase() == 'radial';
//Pivot border properties
datasetConfig.showPivotBorder = pluckNumber(chartAttrs.showpivotborder, 0);
datasetConfig.pivotBorderThickness = pluckNumber(chartAttrs.pivotborderthickness, 1);
datasetConfig.pivotBorderColor = convertColor(
pluck(chartAttrs.pivotbordercolor, colorM.getColor('pivotBorderColor')),
datasetConfig.showPivotBorder == 1 ? pluck(chartAttrs.pivotborderalpha, HUNDREDSTRING) :
ZEROSTRING);
chartConfig.dataLabels = chartConfig.dataLabels || {};
fontBdrColor = getFirstValue(chartAttrs.valuebordercolor,
BLANKSTRING);
fontBdrColor = fontBdrColor ? convertColor(
fontBdrColor, pluckNumber(chartAttrs.valueborderalpha,
chartAttrs.valuealpha, 100)) : BLANKSTRING;
dataLabelsStyle = chartConfig.dataLabels.style = {
fontFamily: pluck(chartAttrs.valuefont, chartConfig.style.inCanfontFamily),
fontSize: pluck(chartAttrs.valuefontsize, parseInt(chartConfig.style.inCanfontSize, 10)) + PXSTRING,
color: convertColor(pluck(chartAttrs.valuefontcolor, chartConfig.style.inCancolor),
pluckNumber(chartAttrs.valuefontalpha,
chartAttrs.valuealpha, 100)),
fontWeight: pluckNumber(chartAttrs.valuefontbold) ? 'bold' :
NORMALSTRING,
fontStyle: pluckNumber(chartAttrs.valuefontitalic) ? 'italic' :
NORMALSTRING,
border: fontBdrColor || chartAttrs.valuebgcolor ?
(pluckNumber(chartAttrs.valueborderthickness, 1) + 'px solid') :
undefined,
borderColor: fontBdrColor,
borderThickness: pluckNumber(chartAttrs.valueborderthickness, 1),
borderPadding: pluckNumber(chartAttrs.valueborderpadding, 2),
borderRadius: pluckNumber(chartAttrs.valueborderradius, 0),
backgroundColor: chartAttrs.valuebgcolor ?
convertColor(chartAttrs.valuebgcolor,
pluckNumber(chartAttrs.valuebgalpha, chartAttrs.valuealpha,
100)) : BLANKSTRING,
borderDash: pluckNumber(chartAttrs.valueborderdashed, 0) ?
getDashStyle(pluckNumber(chartAttrs.valueborderdashlen, 4),
pluckNumber(chartAttrs.valueborderdashgap, 2),
pluckNumber(chartAttrs.valueborderthickness, 1)) : BLANK
};
setLineHeight(dataLabelsStyle);
},
draw :function (animation) {
var dataSet = this,
chart = dataSet.chart,
idMap = dataSet.idMap,
chartConfig = chart.config,
jsonData = chart.jsonData,
chartAttrs = jsonData.chart,
data = dataSet.components.data,
datasetConfig = dataSet.config,
renderer = datasetConfig,
graphics = dataSet.graphics,
components = chart.components,
NumberFormatter = components.numberFormatter,
paper = components.paper,
colorM = components.colorManager,
scale = components.scale,
x = Number(datasetConfig.gaugeOriginX),
y = Number(datasetConfig.gaugeOriginY),
startAngle = datasetConfig.gaugeStartAngle,
endAngle = datasetConfig.gaugeEndAngle,
showShadow = datasetConfig.showShadow,
showTooltip = chartConfig.showtooltip,//(options.tooltip.enabled !== false),
scaleRange = scale.config.axisRange,
minValue = scaleRange.min,
maxValue = scaleRange.max,
pGroup = graphics.pointGroup,
dataLabelsGroup = graphics.dataLabelGroup,
valueRange = maxValue - minValue,
angleRange = endAngle - startAngle,
angleValueFactor = valueRange / angleRange,
editMode,
showHoverEffect = pluckNumber(chartAttrs.showhovereffect),
showValue = dataSet.showValue = pluckNumber(chartAttrs.showvalue, chartAttrs.showrealtimevalue , 0),
i = 0,
style = chartConfig.dataLabels.style,
css = {
fontFamily: style.fontFamily,
fontSize: style.fontSize,
lineHeight: style.lineHeight,
fontWeight: style.fontWeight,
fontStyle: style.fontStyle
},
scaleFactor = chartConfig.scaleFactor,
lineHeight = pluckNumber(parseInt(style.lineHeight, 10), 12),
isBelow = datasetConfig.valueBelowPivot,
animationObj = chart.get(configStr, animationObjStr),
animationDuration = animationObj.duration,
dummyObj = animationObj.dummyObj,
animObj = animationObj.animObj,
animType = animationObj.animType,
labelCounter = 0,
graphicCounter = 0,
hasHoverSizeChange,
hoverFill,
hoverAttr,
outAttr,
point,
radius,
baseWidth,
topWidth,
baseRadius,
rearExtension,
baseWidthHF,
topWidthHF,
ln = data && data.length,
rotation,
graphic,
prevData,
stubEvent = {
pageX: 0,
pageY: 0
},
attrFN = getAttrFunction(startAngle, endAngle),
chartPosition,
getClickArcTangent = function (x, y, center, ref) {
return mathATan2(y - center[1] - ref.top,
x - center[0] - ref.left);
},
dialDragStart = function (startX, startY) {
var point = data[this.pos],
pointConfig = point.config || {};
if (!point.editMode) {
return;
}
// For update previous value is retaining due to closure
x = Number(datasetConfig.gaugeOriginX);
y = Number(datasetConfig.gaugeOriginY);
chartPosition = getPosition(chart.linkedItems.container);
// Record the angle of point of drag start with respect
// to starting angle.
chartConfig.rotationStartAngle = getClickArcTangent(startX, startY, [x, y], chartPosition);
pointConfig.dragStartY = point.value;
prevData = chart._getDataJSON();
},
dialDragEnd = function () {
var point = data[this.pos],
chartObj = chart.chartInstance,
jsVars;
if (!point.editMode) {
return;
}
jsVars = chartObj && chartObj.jsVars;
jsVars && (jsVars._rtLastUpdatedData = chart._getDataJSON());
global.raiseEvent('RealTimeUpdateComplete', {
data: '&value=' + point.updatedValStr,
updateObject: {values: [point.updatedValStr]},
prevData: prevData.values,
source: 'editMode',
url: null
}, chartObj);
try {
/* jshint camelcase: false*/
win.FC_ChartUpdated &&
win.FC_ChartUpdated(chartObj.id);
/* jshint camelcase: true*/
}
catch (err) {
setTimeout(function () {
throw (err);
}, 1);
}
},
dialDragHandler = function (dx, dy, startX, startY, event) {
var point = data[this.pos],
touchEvent = (hasTouch && getTouchEvent(event)) || stubEvent,
newAngle,
angleDelta,
angleDelta2,
newVal,
newVal2,
values,
i,
len;
if (!point.editMode) {
return;
}
// set a flag to determine that drag is happened
chartConfig.fromDrag = true;
// For update previous value is retaining due to closure
x = Number(datasetConfig.gaugeOriginX);
y = Number(datasetConfig.gaugeOriginY);
minValue = scaleRange.min;
maxValue = scaleRange.max;
startAngle = datasetConfig.gaugeStartAngle;
endAngle = datasetConfig.gaugeEndAngle;
valueRange = maxValue - minValue;
angleRange = endAngle - startAngle;
angleValueFactor = valueRange / angleRange;
newAngle = getClickArcTangent(startX, startY, [x, y], chartPosition);
angleDelta = chartConfig.rotationStartAngle - newAngle;
angleDelta2 = angleDelta < 0 ? (math2PI + angleDelta) : (angleDelta - math2PI);
newVal = point.config.dragStartY - (angleDelta * angleValueFactor);
newVal2 = point.config.dragStartY - (angleDelta2 * angleValueFactor);
if ((newVal < minValue || newVal > maxValue) && (newVal2 >= minValue && newVal2 <= maxValue)) {
newVal = newVal2;
}
if (newVal < minValue) {
newVal = mathAbs(newVal2 - maxValue) < mathAbs(newVal - minValue) ? maxValue : minValue;
} else if (newVal > maxValue){
newVal = mathAbs(newVal - maxValue) < mathAbs(newVal2 - minValue) ? maxValue : minValue;
}
point.config.updatedValStr = newVal+BLANK;
point.config.updatedVal = newVal;
values = [];
i = 0;
len = point.config.index;
for(;i < len; i += 1) {
values.push(BLANK);
}
values.push({value : newVal,
animation : {
duration : 0,
transposeAnimDuration : 0,
initAnimDuration :0
}});
if (point.config.y !== newVal && dataSet.updateData({data: values}, true)) {
point.updatedValStr = values.join('|');
point.dragStartX = (x || event.pageX || touchEvent.pageX);
}
},
link,
eventArgs,
rolloverProperties,
pathComand,
hoverRadius,
baseHoverWidth,
baseHoverWidthHF,
topHoverWidth,
topHoverWidthHF,
rearHoverExtension,
clickHandler,
hoverRollOver,
hoverRollOut,
angleValue,
index,
pointConfig,
itemValue,
formatedValue,
displayValue,
pointShowValue,
valueY,
isLabelString,
displayValueCount,
setToolText,
bgColor,
bgAlpha,
dialFill,
borderColor,
borderalpha,
dialBorderColor,
borderThickness,
showDialHoverEffect,
borderHoverColor,
borderHoverAlpha,
borderHoverThickness,
hasBorderHoverMix,
bgHoverColor,
bgHoverAlpha,
hasHoberFillMix,
compositPivotRadius,
pivotRadius,
valueX,
toolText,
displayValueArgs,
lastY,
labelY,
labelX,
freshDraw;
compositPivotRadius = pivotRadius = datasetConfig.pivotRadius;
if (renderer.dataById === undefined) {
renderer.dataById = {};
}
animation = animation || animationObj;
if (!dataLabelsGroup) {
dataLabelsGroup = graphics.dataLabelGroup =
paper.group('datalabels').insertAfter(graphics.pointGroup);
}
if (!graphics.pointersPath) {
graphics.pointersPath = [];
}
if (!graphics.pointersTpath) {
graphics.pointersTpath = [];
}
if (!graphics.dataLabel) {
graphics.dataLabel = [];
}
clickHandler = function (data) {
var ele = this;
// Checking if click is fired from drag or not
if (chartConfig.fromDrag) {
chartConfig.fromDrag = false;
return;
}
plotEventHandler.call(ele, chart, data);
};
hoverRollOver = function (data) {
var ele = this,
transStr,
rolloverProperties = ele.data('rolloverProperties');
plotEventHandler.call(ele, chart, data, ROLLOVER);
if (rolloverProperties.enabled) {
transStr = ele.attr('transform');
ele.attr('transform', BLANK);
ele.attr(rolloverProperties.hoverAttr);
ele.attr('transform', transStr);
}
};
hoverRollOut = function (data) {
var ele = this,
transStr,
rolloverProperties = ele.data('rolloverProperties');
plotEventHandler.call(ele, chart, data, ROLLOUT);
if (rolloverProperties.enabled) {
transStr = ele.attr('transform');
ele.attr('transform', BLANK);
ele.attr(rolloverProperties.outAttr);
ele.attr('transform', transStr);
}
};
index = 0;
//fix for null or no data
//gauge will show the dial at min value
if (!ln) {
index = -1;
ln = 0;
}
if (showHoverEffect !== 0 && (showHoverEffect || chartAttrs.dialborderhovercolor ||
chartAttrs.dialborderhoveralpha || chartAttrs.dialborderhoveralpha === 0 ||
chartAttrs.dialborderhoverthickness || chartAttrs.dialborderhoverthickness === 0 ||
chartAttrs.dialbghovercolor || chartAttrs.plotfillhovercolor ||
chartAttrs.dialbghoveralpha || chartAttrs.plotfillhoveralpha ||
chartAttrs.dialbghoveralpha === 0)){
showHoverEffect = 1;
}
for (; i < ln; i += 1) {
point = data[i];
point.config = point.config || {};
pointConfig = point.config;
point.config.index = i;
idMap[point.id] = {
index : i,
config : point.config
};
freshDraw = false;
if (point.id !== undefined) {
renderer.dataById[point.id] = {
index: i,
point: point
};
}
itemValue = NumberFormatter.getCleanValue(point.value);
itemValue = Number(toPrecision(itemValue, 10));
rearExtension = (pluckNumber(point.rearextension, 0)) * scaleFactor;
compositPivotRadius = Math.max(compositPivotRadius, rearExtension * scaleFactor);
formatedValue = NumberFormatter.dataLabels(itemValue);
displayValue = getValidValue(point.displayvalue, formatedValue, BLANKSTRING);
pointShowValue = pluckNumber(point.showvalue, showValue);
valueY = pluckNumber(getValidValue(point.valuey) * scaleFactor);
valueX = pluckNumber(getValidValue(point.valuex) * scaleFactor);
isLabelString = pluck(point.tooltext, point.hovertext) ? true : false;
pointConfig.itemValue = itemValue;
pointConfig.formatedVal = formatedValue;
if (pointShowValue && !defined(valueY)) {
displayValueCount += 1;
}
setToolText = getValidValue(parseUnsafeString(pluck(point.tooltext, point.hovertext)));
if (setToolText){
setToolText = parseTooltext(setToolText, [1,2], {
formattedValue: formatedValue
}, point, chartAttrs);
}
else {
setToolText = displayValue;
}
bgColor = pluck(point.color, point.bgcolor, colorM.getColor('dialColor'));
bgAlpha = pluckNumber(point.alpha, point.bgalpha, 100);
dialFill = toRaphaelColor({
FCcolor : {
color: bgColor,
alpha: bgAlpha,
angle : 90
}
});
borderColor = pluck(point.bordercolor, colorM.getColor('dialBorderColor'));
borderalpha = pluckNumber(point.borderalpha, 100);
dialBorderColor = convertColor(borderColor, borderalpha);
borderThickness = pluckNumber(point.borderthickness, 1);
radius = (pluckNumber(point.radius)) * scaleFactor;
baseWidth = pluckNumber(pluckNumber(point.basewidth * scaleFactor, pivotRadius * 1.6));
topWidth = (pluckNumber(point.topwidth, 0)) * scaleFactor;
baseRadius = pluckNumber(point.baseradius, 0);
editMode = pluckNumber(point.editmode, chartAttrs.editmode, 0);
link = pluck(point.link, BLANKSTRING);
toolText = setToolText;
pointConfig.toolText = toolText;
displayValueArgs = pluck(displayValue, BLANKSTRING);
displayValue = pointShowValue ? pluck(displayValue, BLANK) : BLANKSTRING;
showDialHoverEffect = pluckNumber(point.showhovereffect, showHoverEffect);
if (showDialHoverEffect !== 0 && (showDialHoverEffect || point.borderhovercolor ||
point.borderhoveralpha || point.borderhoveralpha === 0 ||
point.borderhoverthickness || point.borderhoverthickness === 0 ||
point.bghovercolor || point.bghoveralpha || point.bghoveralpha === 0)) {
showDialHoverEffect = true;
outAttr = {};
hoverAttr = {};
borderHoverColor = pluck(point.borderhovercolor, chartAttrs.dialborderhovercolor,
FILLMIXDARK10);
borderHoverAlpha = pluckNumber(point.borderhoveralpha,
chartAttrs.dialborderhoveralpha, borderalpha);
borderHoverThickness = pluckNumber(point.borderhoverthickness,
chartAttrs.dialborderhoverthickness, borderThickness);
if (borderHoverThickness){
outAttr.stroke = dialBorderColor;
hasBorderHoverMix = /\{/.test(borderHoverColor);
hoverAttr.stroke = convertColor(hasBorderHoverMix ?
colorM.parseColorMix(borderColor, borderHoverColor)[0] :
borderHoverColor, borderHoverAlpha);
}
if (borderHoverThickness !== borderThickness) {
hoverAttr['stroke-width'] = borderHoverThickness;
outAttr['stroke-width'] = borderThickness;
}
bgHoverColor = pluck(point.bghovercolor, chartAttrs.dialbghovercolor,
chartAttrs.plotfillhovercolor, FILLMIXDARK10);
bgHoverAlpha = pluckNumber(point.bghoveralpha, chartAttrs.dialbghoveralpha,
chartAttrs.plotfillhoveralpha, bgAlpha);
outAttr.fill = dialFill;
hasHoberFillMix = /\{/.test(bgHoverColor);
bgHoverColor = hasHoberFillMix ? colorM.parseColorMix(bgColor,
bgHoverColor).join() : bgHoverColor;
hoverFill = {
FCcolor : {
color: bgHoverColor,
alpha: bgHoverAlpha,
angle : 90
}
};
hoverAttr.fill = toRaphaelColor(hoverFill);
}
// Parse data related attributed
rolloverProperties = point.rolloverProperties = {
enabled: showDialHoverEffect,
hasHoverSizeChange: hasHoverSizeChange,
hoverRadius: pluckNumber(hoverRadius * scaleFactor),
baseHoverWidth: pluckNumber(baseHoverWidth * scaleFactor, pivotRadius * 1.6),
topHoverWidth: pluckNumber(topHoverWidth * scaleFactor),
rearHoverExtension: pluckNumber(rearHoverExtension * scaleFactor),
hoverFill: hoverFill,
hoverAttr: hoverAttr,
outAttr: outAttr
},
radius = pluckNumber(radius, (Number(datasetConfig.gaugeOuterRadius) +
Number(datasetConfig.gaugeInnerRadius)) / 2);
baseWidthHF = baseWidth / 2;
topWidthHF = topWidth / 2;
//set the tooltip pos
point.tooltipPos = [x, y];
link = point.editMode ? undefined : point.link;
pathComand = [M, radius, -topWidthHF, L, radius, topWidthHF, -rearExtension,
baseWidthHF, -rearExtension, -baseWidthHF, Z];
if (rolloverProperties.hasHoverSizeChange) {
rolloverProperties.outAttr.path = pathComand;
hoverRadius = pluckNumber(rolloverProperties.hoverRadius, radius);
baseHoverWidth = rolloverProperties.baseHoverWidth;
baseHoverWidthHF = baseHoverWidth / 2;
topHoverWidth = rolloverProperties.topHoverWidth;
topHoverWidthHF = topHoverWidth / 2;
rearHoverExtension = rolloverProperties.rearHoverExtension;
rolloverProperties.hoverAttr.path = [M, hoverRadius, -topHoverWidthHF, L,
hoverRadius, topHoverWidthHF, -rearHoverExtension, baseHoverWidthHF,
-rearHoverExtension, -baseHoverWidthHF, Z];
}
eventArgs = {
link: point.link,
value: itemValue,
displayValue: displayValueArgs,
toolText: toolText
};
//graphics.pointers[i].remove()
if (!graphics.pointersTpath[i]) {
if (topWidth) {
graphics.pointersPath[i] = paper.path(pathComand, pGroup);
graphics.pointersTpath[i] = paper.trianglepath(0,0,0,0,0,0,0,0,0,pGroup);
}
// Render using trianglepath
else {
graphics.pointersPath[i] = paper.path(['M',0,0],pGroup);
graphics.pointersTpath[i] = paper.trianglepath(radius,
topWidthHF, -rearExtension, baseWidthHF,
-rearExtension, -baseWidthHF, 0, baseRadius,
baseRadius, pGroup);
}
freshDraw = true;
}
else {
if (topWidth) {
graphics.pointersPath[i].animateWith(dummyObj, animObj, {
path : pathComand
}, animationDuration, animType);
graphics.pointersTpath[i]._attr({
trianglepath : [0,0,0,0,0,0,0,0,0]
});
}
// Render using trianglepath
else {
graphics.pointersTpath[i].animateWith(dummyObj, animObj, {
trianglepath : [radius,
topWidthHF, -rearExtension, baseWidthHF,
-rearExtension, -baseWidthHF, 0, baseRadius,
baseRadius]
}, animationDuration, animType);
graphics.pointersPath[i]._attr({
path : 'M00'
});
}
}
// Render using path if topWidth present
if (topWidth) {
graphic = graphics.pointersPath[i];
} else {
graphic = graphics.pointersTpath[i];
}
if (!graphics.pointersPath[i]._attr) {
graphics.pointersPath[i]._attr = graphics.pointersPath[i].attr;
graphics.pointersPath[i].attr = attrFN;
}
if (!graphics.pointersTpath[i]._attr) {
graphics.pointersTpath[i]._attr = graphics.pointersTpath[i].attr;
graphics.pointersTpath[i].attr = attrFN;
}
graphic._attr({
fill: dialFill,
stroke: dialBorderColor,
ishot: true,
'stroke-width': borderThickness
})
// .hover(hoverRollOver, hoverRollOut)
.data(EVENTARGS, eventArgs);
// .data('rolloverProperties', rolloverProperties);
if (baseWidth || topWidth || borderThickness) {
graphic.shadow({apply: showShadow});
}
graphic._Attr = {
tooltipPos: point.tooltipPos,
cx: x,
cy: y,
toolTipRadius: radius - rearExtension,
color: point.color
};
if (freshDraw) {
rotation = (startAngle / deg2rad);
graphic.attr({
angle: rotation
});
}
point.index = i;
point.editMode = editMode;
graphic.css({
cursor: editMode || link ? POINTER : 'default',
'_cursor': editMode ? 'hand' : 'default'
})
.attr({
ishot: true
});
if (freshDraw) {
graphics.pointersPath[i].drag(dialDragHandler, dialDragStart, dialDragEnd,
{pos : i}, {pos : i}, {pos : i})
.click(clickHandler);
graphics.pointersTpath[i].drag(dialDragHandler, dialDragStart, dialDragEnd,
{pos : i}, {pos : i}, {pos : i})
.click(clickHandler);
}
pointConfig.y = itemValue;
// Rotate the dial as per the angle
if (itemValue >= minValue && itemValue <= maxValue) {
angleValue = ((itemValue - minValue) / valueRange) * angleRange;
rotation = (startAngle + angleValue) / deg2rad;
graphic.attr({
angle: rotation
}, null, animation);
if (showTooltip && toolText !== BLANK) {
graphic.tooltip(toolText);
graphic.trackTooltip(true);
} else {
graphic.trackTooltip(false);
}
}
// Draw widgets labels
graphicCounter += 1;
if (defined(displayValue) && displayValue !== BLANK) {
lastY = y + (isBelow ? (lineHeight / 2) + pivotRadius + 2 : -(lineHeight / 2) -
pivotRadius - 2);
labelY = valueY;
labelX = pluckNumber(valueX, x);
if (!defined(labelY)) {
labelY = isBelow ? lastY + (lineHeight * labelCounter) :
lastY - (lineHeight * labelCounter);
}
if (!graphics.dataLabel[i]) {
graphics.dataLabel[i] = paper.text(dataLabelsGroup)
.attr({
x: labelX,
y: labelY,
text: displayValue,
//'text-anchor': textHAlign[labelAlign],
direction: chartConfig.textDirection,
//title: (point.originalText || BLANK),
fill: style.color,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
})
.css(css)
.tooltip(point.originalText);
}
else {
graphics.dataLabel[i].attr({
text: displayValue,
title: (point.originalText || BLANK),
fill: style.color,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
})
.css(css)
.tooltip(point.originalText);
graphics.dataLabel[i].animateWith(dummyObj, animObj, {
x: labelX,
y: labelY
}, animationDuration, animType);
}
labelCounter += 1;
}
}
for (i = graphicCounter, ln = graphics.pointersPath.length; i < ln; i += 1) {
graphics.pointersPath[i].attr({
path : ['M',0,0]
});
graphics.pointersTpath[i].attr({
trianglepath : [0,0,0,0,0,0,0,0,0]
});
}
for (i = labelCounter, ln = graphics.dataLabel.length; i < ln; i += 1) {
graphics.dataLabel[i].attr({
text : BLANK,
'text-bound': []
});
}
},
updateData: function (updateObj, draw) {
if (updateObj === this.lastUpdatedObj) {
return false;
}
var dataSet = this,
chart = dataSet.chart,
data = dataSet.components.data,
label,
toolText,
showLabel,
dataArr = dataSet.components.data,
i = (dataArr && dataArr.length) || 0,
dataObj,
config,
updateData,
value,
animation,
pointObj;
updateObj = updateObj.data;
//use the realtime animation value or the default animation value
if (i) {
while (i--) {
dataObj = {};
pointObj = {};
config = data[i].config;
updateData = updateObj[i];
if (!updateData) {
continue;
}
animation = updateData.animation || chart.get(configStr, animationObjStr);
value = updateData.value;
toolText = updateData.tooltext;
label = updateData.label;
showLabel = updateData.showlabel;
data[i].value = pluckNumber(value, data[i].value, 0);
data[i].tooltext = pluck(toolText, data[i].value);
data[i].displayvalue = label;
}
this.lastUpdatedObj = updateObj;
draw && this.draw(animation);
return true;
}
}
},'hlineargauge']);
}
]);
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-bulb',
function () {
var global = this,
lib = global.hcLib,
pluckNumber = lib.pluckNumber,
pluck = lib.pluck,
COMMASTRING = lib.COMMASTRING,
COMMASPACE = lib.COMMASPACE,
BLANK = lib.BLANKSTRING,
BLANKSTRING = BLANK,
extend2 = lib.extend2,
toRaphaelColor = lib.toRaphaelColor,
schedular = lib.schedular,
getValidValue = lib.getValidValue,
convertColor = lib.graphics.convertColor,
getDarkColor = lib.graphics.getDarkColor,
getLightColor = lib.graphics.getLightColor,
preDefStr = lib.preDefStr,
parseConfiguration = lib.parseConfiguration,
parseUnsafeString = lib.parseUnsafeString,
configStr = preDefStr.configStr,
animationObjStr = preDefStr.animationObjStr,
POSITION_TOP = preDefStr.POSITION_TOP,
POSITION_MIDDLE = preDefStr.POSITION_MIDDLE,
showHoverEffectStr = preDefStr.showHoverEffectStr,
visibleStr = preDefStr.visibleStr,
ROUND = preDefStr.ROUND,
plotEventHandler = lib.plotEventHandler,
ROLLOVER = 'DataPlotRollOver',
ROLLOUT = 'DataPlotRollOut',
FILLMIXDARK10 = '{dark-10}',
COMPONENT = 'component',
DATASET = 'dataset',
EVENTARGS = 'eventArgs',
SETROLLOVERATTR = 'setRolloverAttr',
SETROLLOUTATTR = 'setRolloutAttr',
POINTER = 'pointer',
UNDEFINED,
math = Math,
mathMin = math.min,
win = global.window,
userAgent = win.navigator.userAgent,
isIE = /msie/i.test(userAgent) && !win.opera,
TRACKER_FILL = 'rgba(192,192,192,'+ (isIE ? 0.002 : 0.000001) +')';
FusionCharts.register(COMPONENT, [DATASET, 'bulb', {
pIndex : 2,
customConfigFn : '_createDatasets',
_manageSpace : function (availableHeight) {
var dataSet = this,
conf = dataSet.config,
JSONData = dataSet.JSONData,
setDataArr = JSONData.data,
dataStore = dataSet.components.data,
setData,
dataObj,
chart = dataSet.chart,
chartConfig = chart.config,
smartLabel = chart.linkedItems.smartLabel,
smartDataLabel, extraSpace,
style = chartConfig.dataLabelStyle,
lineHeight = pluckNumber(parseInt(style.lineHeight, 10), 12),
maxAllowedHeight = availableHeight,
valuePadding = chartConfig.valuepadding,
heightUsed = 0,
config;
setData = setDataArr[0];
dataObj = dataStore[0];
config = dataObj && dataObj.config;
smartLabel.useEllipsesOnOverflow(chartConfig.useEllipsesWhenOverflow);
smartLabel.setStyle(style);
if (config && config.displayValue !== BLANKSTRING && !chartConfig.placevaluesinside) {
if (conf.showValue) {
smartDataLabel = smartLabel.getOriSize(config.displayValue);
//special fix for space string
/** @todo will be removed when smartLabel will be able to handle it */
if (config.displayValue === BLANK) {
smartDataLabel = {
height : lineHeight
};
}
if (smartDataLabel.height > 0) {
heightUsed = smartDataLabel.height + valuePadding;
}
if (heightUsed > maxAllowedHeight) {
extraSpace = heightUsed - maxAllowedHeight;
heightUsed = maxAllowedHeight;
}
}
}
conf.heightUsed = heightUsed;
return {
top : 0,
bottom : heightUsed
};
},
configure : function() {
var dataSet = this,
JSONData = dataSet.JSONData,
userConfig = extend2({}, JSONData),
chart = dataSet.chart,
conf = dataSet.config,
chartConfig = chart.config,
chartAttr = chart.jsonData.chart,
is3D = pluckNumber(chartAttr.is3d, 1),
showTooltip = pluckNumber(chartAttr.showtooltip, 1),
enableAnimation;
dataSet.__setDefaultConfig();
parseConfiguration(userConfig, conf, chart.config, { data: true});
is3D = pluckNumber(chartAttr.is3d, 1);
// conf.autoScale = pluckNumber(chartAttr.autoscale, 1);
conf.origW = pluckNumber(chartAttr.origw, chartConfig.autoscale ?
chart.origRenderWidth : chartConfig.width || chart.origRenderWidth);
conf.origH = pluckNumber(chartAttr.origh, chartConfig.autoscale ?
chart.origRenderHeight : chartConfig.height || chart.origRenderHeight);
showTooltip = pluckNumber(chartAttr.showtooltip, 1);
conf.setToolText = getValidValue(parseUnsafeString(pluck(chartAttr.plottooltext, UNDEFINED)));
conf.useColorNameAsValue = pluckNumber(chartAttr.usecolornameasvalue, 0);
conf.enableAnimation = enableAnimation = pluckNumber(chartAttr.animation,
chartAttr.defaultanimation, 1);
conf.animation = !enableAnimation ? false : {
duration: pluckNumber(chartAttr.animationduration, 1) * 1000
};
conf.showValue = pluckNumber(chartAttr.showvalue, 1);
dataSet._setConfigure();
},
/*
* Function for parsing all the attributes and value given by the user at set level.
* This function is called once from the configure() function of the Column class.
*/
_setConfigure : function (newDataset) {
var dataSet = this,
chart = dataSet.chart,
conf = dataSet.config,
chartConfig = chart.config,
JSONData = dataSet.JSONData,
setDataArr = newDataset || JSONData.data,
setDataLen = setDataArr && setDataArr.length,
components = chart.components,
len = (newDataset && newDataset.data.length) || setDataLen,
chartAttr = chart.jsonData.chart,
colorM = components.colorManager,
showTooltip = pluckNumber(chartAttr.showtooltip, 1),
parseUnsafeString = lib.parseUnsafeString,
tooltipSepChar = parseUnsafeString(pluck(chartAttr.tooltipsepchar, COMMASPACE)),
parseTooltext = lib.parseTooltext,
formatedVal,
tempPlotfillAngle,
toolText,
showHoverEffect = chartConfig.showhovereffect,
plotfillAngle = conf.plotFillAngle,
dataStore = dataSet.components.data,
setData,
setValue,
dataObj,
config,
label,
setDisplayValue,
is3D = pluckNumber(chartAttr.is3d, 1),
i,
numberFormatter = chart.components.numberFormatter,
colorRangeGetter,
colorCodeObj,
gaugeFillAlpha,
colorName,
gaugeBorderColorCode,
gaugeBorderAlpha,
hasGaugeBorderMix,
fillColor,
gaugeBorderColor,
gaugeBorderThickness,
gaugeFillHoverColor,
gaugeFillHoverAlpha,
showGaugeBorderOnHover,
gaugeBorderHoverColor,
gaugeBorderHoverAlpha,
gaugeBorderHoverThickness,
is3DOnHover,
showHoverAnimation,
hasHoberFillMix,
hasBorderHoverMix,
isLabelString,
displayValue,
getPointColor = function (color, alpha, is3d) {
if (!is3d) {
return convertColor(color, alpha);
}
return {
FCcolor : {
cx: 0.4,
cy: 0.4,
r: '80%',
color : getLightColor(color, 65) + COMMASTRING + getLightColor(color, 75) +
COMMASTRING + getDarkColor(color, 65),
alpha : alpha + COMMASTRING + alpha + COMMASTRING + alpha,
ratio : '0,30,70', //BGRATIOSTRING,
radialGradient : true
}
};
},
hoverAttr,
hoverAnimAttr,
outAttr;
if (!dataStore) {
dataStore = dataSet.components.data = [];
}
// Parsing the attributes and values at set level.
for (i = 0; i < len; i++) {
if (newDataset) {
setData = (newDataset && newDataset.data[i]);
}
else {
setData = setDataArr[i];
}
dataObj = dataStore[i];
config = dataObj && dataObj.config;
if (!dataObj) {
dataObj = dataStore[i] = {};
}
if (!dataObj.config) {
config = dataStore[i].config = {};
}
config.setValue = setValue = numberFormatter.getCleanValue(setData.value) || 0;
formatedVal = numberFormatter.dataLabels(setValue);
setDisplayValue = getValidValue(parseUnsafeString(setData.displayvalue));
config.colorRangeGetter = colorRangeGetter = chart.components.colorRange;
colorCodeObj = colorRangeGetter.getColorObj(config.setValue);
colorCodeObj = colorCodeObj.colorObj || colorCodeObj.prevObj || colorCodeObj.nextObj;
gaugeFillAlpha = pluckNumber(chartAttr.gaugefillalpha, colorCodeObj.alpha, 100);
colorName = parseUnsafeString(pluck(colorCodeObj.label, colorCodeObj.name)),
gaugeBorderColorCode = pluck(colorCodeObj.bordercolor,
chartAttr.gaugebordercolor, getDarkColor(colorCodeObj.code, 70));
gaugeBorderAlpha = pluckNumber(colorCodeObj.borderalpha,
chartAttr.gaugeborderalpha, '90') * gaugeFillAlpha / 100,
hasGaugeBorderMix = /\{/.test(gaugeBorderColorCode);
gaugeBorderColorCode = hasGaugeBorderMix ? colorM.parseColorMix(pluck(colorCodeObj.bordercolor,
colorCodeObj.code),
gaugeBorderColorCode)[0] : gaugeBorderColorCode;
config.gaugeBorderColor = gaugeBorderColor = convertColor(gaugeBorderColorCode, gaugeBorderAlpha);
config.gaugeBorderThickness = gaugeBorderThickness =
chartConfig.showgaugeborder ? pluckNumber(chartAttr.gaugeborderthickness, 1) : 0,
config.fillColor = fillColor = getPointColor(colorCodeObj.code, gaugeFillAlpha, is3D);
if (showHoverEffect !== 0 && (showHoverEffect || chartAttr.gaugefillhovercolor ||
chartAttr.plotfillhovercolor || chartAttr.gaugefillhoveralpha ||
chartAttr.plotfillhoveralpha || chartAttr.gaugefillhoveralpha === 0 ||
chartAttr.is3donhover || chartAttr.is3donhover === 0 || chartAttr.showgaugeborderonhover ||
chartAttr.showgaugeborderonhover === 0 || chartAttr.gaugeborderhovercolor ||
chartAttr.gaugeborderhoveralpha || chartAttr.gaugeborderhoveralpha === 0 ||
chartAttr.gaugeborderhoverthickness || chartAttr.gaugeborderhoverthickness === 0)) {
showHoverEffect = true;
gaugeFillHoverColor = pluck(chartAttr.gaugefillhovercolor,
chartAttr.plotfillhovercolor, FILLMIXDARK10);
gaugeFillHoverAlpha = pluckNumber(chartAttr.gaugefillhoveralpha, chartAttr.plotfillhoveralpha);
showGaugeBorderOnHover = pluckNumber(chartAttr.showgaugeborderonhover);
if (showGaugeBorderOnHover === undefined) {
if (chartAttr.gaugeborderhovercolor || chartAttr.gaugeborderhoveralpha ||
chartAttr.gaugeborderhoveralpha === 0|| chartAttr.gaugeborderhoverthickness ||
chartAttr.gaugeborderhoverthickness === 0) {
showGaugeBorderOnHover = 1;
}
else {
showGaugeBorderOnHover = chartConfig.showgaugeborder;
}
}
gaugeBorderHoverColor = pluck(chartAttr.gaugeborderhovercolor, FILLMIXDARK10);
gaugeBorderHoverAlpha = pluckNumber(chartAttr.gaugeborderhoveralpha);
gaugeBorderHoverThickness =
showGaugeBorderOnHover ? pluckNumber(chartAttr.gaugeborderhoverthickness,
gaugeBorderThickness || 1) : 0;
is3DOnHover = !!pluckNumber(chartAttr.is3donhover, is3D);
showHoverAnimation = !!pluckNumber(chartAttr.showhoveranimation, 1);
hoverAttr = {};
outAttr = {};
if (gaugeBorderThickness !== gaugeBorderHoverThickness) {
hoverAttr['stroke-width'] = gaugeBorderHoverThickness;
outAttr['stroke-width'] = gaugeBorderThickness;
}
outAttr.fill = toRaphaelColor(fillColor);
hasHoberFillMix = /\{/.test(gaugeFillHoverColor);
gaugeFillHoverColor = hasHoberFillMix ? colorM.parseColorMix(colorCodeObj.code,
gaugeFillHoverColor)[0] : pluck(gaugeFillHoverColor, colorCodeObj.code);
hoverAttr.fill = toRaphaelColor(getPointColor(gaugeFillHoverColor,
pluckNumber(gaugeFillHoverAlpha, gaugeFillAlpha), is3DOnHover));
if (gaugeBorderHoverThickness) {
outAttr.stroke = gaugeBorderColor;
hasBorderHoverMix = /\{/.test(gaugeBorderHoverColor);
hoverAttr.stroke = convertColor(hasBorderHoverMix ? colorM.parseColorMix(hasGaugeBorderMix ?
gaugeFillHoverColor : gaugeBorderColorCode, gaugeBorderHoverColor)[0] :
gaugeBorderHoverColor, pluckNumber(gaugeBorderHoverAlpha, gaugeBorderAlpha));
}
}
config.setTooltext = lib.getValidValue(parseUnsafeString(pluck(setData.tooltext,
JSONData.plottooltext, chartAttr.plottooltext)));
if (!showTooltip) {
toolText = false;
}
else if (config.setTooltext !== undefined) {
toolText = parseTooltext(config.setTooltext, [1,2], {
formattedValue: formatedVal
}, setData, chartAttr);
isLabelString = true;
}
// Determine the dispalay value then
else {
toolText = conf.useColorNameAsValue ? colorName : (formatedVal === null ? false :
(label !== undefined) ? label + tooltipSepChar +
formatedVal : formatedVal);
}
// Create the displayvalue
if (setDisplayValue !== undefined) {
displayValue = setDisplayValue;
}
// Determine the dispalay value then
else {
displayValue = setData.label || (conf.useColorNameAsValue ? colorName : formatedVal);
}
config.toolText = toolText;
config.displayValue = displayValue;
config.rolloverProperties = {
enabled: showHoverEffect,
hoverAttr: hoverAttr,
hoverAnimAttr: hoverAnimAttr,
outAttr: outAttr
};
tempPlotfillAngle && (plotfillAngle = tempPlotfillAngle);
}
},
init : function(datasetJSON) {
var dataSet = this,
chart = dataSet.chart;
if (!datasetJSON) {
return false;
}
dataSet.JSONData = datasetJSON;
dataSet.chartGraphics = chart.chartGraphics;
dataSet.components = {
};
dataSet.graphics = {
};
dataSet.visible = true;
dataSet.configure();
},
updateData : function (dataObj, index, draw) {
var dataSet = this;
dataSet._setConfigure(dataObj, index);
if (draw) {
dataSet.draw();
}
},
draw: function() {
var dataSet = this,
dataStore = dataSet.components.data,
chart = dataSet.chart,
conf = dataSet.config,
jobList = chart.getJobList(),
animationObj = chart.get(configStr, animationObjStr),
animType = animationObj.animType,
animObj = animationObj.animObj,
dummyObj = animationObj.dummyObj,
animationDuration = animationObj.duration,
chartConfig = chart.config,
canvasLeft = chartConfig.canvasLeft,
canvasTop = chartConfig.canvasTop,
canvasHeight = chartConfig.canvasHeight,
canvasWidth = chartConfig.canvasWidth,
paper = chart.components.paper,
parentContainer = chart.graphics.datasetGroup,
container = dataSet.graphics.container,
trackerContainer = dataSet.graphics.trackerContainer,
layers = chart.graphics,
trackerLayer = layers.trackerGroup,
setValue,
attr,
toolText,
// eventArgs,
xPos,
yPos,
radius,
bulb,
// hotElement,
dataObj = dataStore[0],
graphic,
config = dataObj && dataObj.config,
gaugeOriginX = chartConfig.gaugeoriginx,
gaugeOriginY = chartConfig.gaugeoriginy,
gaugeRadius = chartConfig.gaugeradius,
hasGaugeOriginX = chartConfig.hasgaugeoriginx,
hasGaugeOriginY = chartConfig.hasgaugeoriginy,
hasGaugeRadius = chartConfig.hasgaugeradius,
labelY,
vAlign,
dataLabelContainer = dataSet.graphics.dataLabelContainer,
style = chart.config.dataLabelStyle,
dataLabelsLayer = layers.datalabelsGroup,
// isNewElement = false,
trackerConfig;
// css = {
// fontFamily: style.fontFamily,
// fontSize: style.fontSize,
// lineHeight: style.lineHeight,
// fontWeight: style.fontWeight,
// fontStyle: style.fontStyle
// };
if (!container) {
container = dataSet.graphics.container = paper.group('bulb', parentContainer);
}
if (!trackerContainer) {
trackerContainer = dataSet.graphics.trackerContainer = paper.group('bulb-hot', trackerLayer);
}
// Creating the datalabel container if not created
if (!dataLabelContainer) {
dataLabelContainer = dataSet.graphics.dataLabelContainer = paper.group('datalabel');
}
// Append the container to datalabelslayer
if (dataLabelsLayer) {
dataLabelsLayer.appendChild(dataLabelContainer);
}
trackerConfig = dataObj.trackerConfig = {};
setValue = config.setValue;
toolText = config.toolText;
trackerConfig.eventArgs = {
value: setValue,
displayValue: config.displayValue,
toolText: !toolText ? '' : toolText
};
if (!dataObj.graphics) {
dataObj.graphics = {};
}
gaugeOriginX = hasGaugeOriginX !== UNDEFINED ? (gaugeOriginX * conf.scaleFactor) :
canvasLeft + (canvasWidth / 2);
// (hasGaugeOriginX !== UNDEFINED) && (gaugeOriginX *= conf.scaleFactor);
gaugeOriginY = hasGaugeOriginY !== UNDEFINED ? (gaugeOriginY * conf.scaleFactor) :
canvasTop + (canvasHeight / 2);
// (hasGaugeOriginY !== UNDEFINED) && (gaugeOriginY *= conf.scaleFactor);
xPos = gaugeOriginX;
yPos = gaugeOriginY;
radius = hasGaugeRadius !== UNDEFINED ? (gaugeRadius * conf.scaleFactor) :
mathMin(canvasWidth / 2, canvasHeight / 2);
// (hasGaugeRadius !== UNDEFINED) && (radius *= conf.scaleFactor);
//Setting macros for annotation
chartConfig.gaugeStartX = gaugeOriginX - radius;
chartConfig.gaugeEndX = gaugeOriginX + radius;
chartConfig.gaugeStartY = gaugeOriginY - radius;
chartConfig.gaugeEndY = gaugeOriginY + radius;
chartConfig.gaugeCenterX = gaugeOriginX;
chartConfig.gaugeCenterY = gaugeOriginY;
chartConfig.gaugeRadius = radius;
attr = {
cx: xPos,
cy: yPos,
r: 0.001,
'stroke-linecap': ROUND,
stroke: toRaphaelColor(config.gaugeBorderColor),
'stroke-width': config.gaugeBorderThickness,
fill : toRaphaelColor(config.fillColor),
ishot: true
};
bulb = dataObj.graphics.element;
if (!bulb) {
bulb = dataObj.graphics.element = paper.circle(attr, container);
bulb.animateWith(dummyObj, animObj, {
r: radius
}, animationDuration, animType);
}
else {
dataObj.graphics.element.animateWith(dummyObj, animObj, {
cx: xPos,
cy: yPos,
r: radius
}, animationDuration, animType);
bulb = dataObj.graphics.element.attr({
'stroke-linecap': ROUND,
stroke: toRaphaelColor(config.gaugeBorderColor),
'stroke-width': config.gaugeBorderThickness,
fill : toRaphaelColor(config.fillColor),
ishot: true
});
}
trackerConfig.attr = {
cx: xPos,
cy: yPos,
r: radius,
cursor: config.setLink ? POINTER : BLANK,
stroke: TRACKER_FILL,
'stroke-width': config.plotBorderThickness,
fill: TRACKER_FILL,
ishot: true,
visibility: visibleStr
};
/*
* If the tooltips are not present then they are created over the hot element,
* else only attributes are set for the existing tooltips.
*/
// hotElement = dataObj.graphics.hotElement;
// if (!hotElement) {
// hotElement = dataObj.graphics.hotElement = paper.circle(attr, trackerContainer);
// isNewElement = true;
// }
// else {
// hotElement = dataObj.graphics.hotElement.attr(attr);
// }
// hotElement
// .data(EVENTARGS, eventArgs)
// .data(SETROLLOVERATTR, rolloverProperties.hoverAttr)
// .data(SETROLLOUTATTR, rolloverProperties.outAttr)
// .tooltip(toolText);
// if (isNewElement) {
// hotElement
// .click(clickFunc)
// .hover(
// rolloverResponseSetter(bulb),
// rolloutResponseSetter(bulb)
// );
// }
graphic = dataObj.graphics;
if (!chartConfig.placevaluesinside) {
labelY = yPos + radius + chartConfig.valuepadding /*- chartConfig.borderWidth*/;
vAlign = POSITION_TOP;
} else {
labelY = yPos;
vAlign = POSITION_MIDDLE;
}
if ((config.setValue !== BLANKSTRING) && conf.showValue) {
attr = {
text: config.displayValue,
'text-anchor': POSITION_MIDDLE,
x: gaugeOriginX,
y: labelY,
//title: (bulbProperties.originalText || BLANK),
'vertical-align': vAlign,
fill: style.color,
direction: config.textDirection,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
};
if (!graphic.label) {
graphic.label = paper.text(attr, dataLabelContainer);
}
else {
graphic.label.show();
graphic.label.animateWith(dummyObj, animObj, {
x: gaugeOriginX,
y: labelY
}, animationDuration, animType);
graphic.label.attr({
text: config.displayValue,
'text-anchor': POSITION_MIDDLE,
'vertical-align': vAlign,
fill: style.color,
direction: config.textDirection,
'text-bound': [style.backgroundColor, style.borderColor,
style.borderThickness, style.borderPadding,
style.borderRadius, style.borderDash]
});
}
graphic.label
// .css(css)
.tooltip(toolText);
}
else {
graphic.label && graphic.label.hide() &&
graphic.label.attr({'text-bound': []});
}
jobList.trackerDrawID.push(schedular.addJob(dataSet.drawTracker, dataSet, [],
lib.priorityList.tracker));
},
drawTracker : function () {
var dataSet = this,
chart = dataSet.chart,
components = dataSet.components,
dataStore = components.data,
chartConfig = chart.config,
showHoverEffect = chartConfig.plothovereffect,
chartComponents = chart.components,
paper = chartComponents.paper,
trackerContainer = dataSet.graphics.trackerContainer,
trackerConfig,
config,
dataObj,
setElement,
hotElemCreated,
hotElement,
attr,
//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 (elem) {
return function (data) {
var ele = this,
elData = ele.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(ele.getData().setRolloverAttr);
plotEventHandler.call(ele, chart, data, ROLLOVER);
}
};
},
//Fired on mouse-out over the hot elements.
rolloutResponseSetter = function (elem) {
return function (data) {
var ele = this,
elData = ele.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(ele.getData().setRolloutAttr);
plotEventHandler.call(ele, chart, data, ROLLOUT);
}
};
};
// Create tracker elements.
dataObj = dataStore[0];
config = dataObj && dataObj.config;
trackerConfig = dataObj.trackerConfig;
setElement = dataObj.graphics.element;
if (attr = trackerConfig.attr) {
/*
* If the tooltips are not present then they are created over the hot element,
* else only attributes are set for the existing tooltips.
*/
if (!dataObj.graphics.hotElement) {
hotElement = dataObj.graphics.hotElement = paper.circle(attr, trackerContainer);
hotElemCreated = true;
}
else {
dataObj.graphics.hotElement.attr(attr);
hotElemCreated = false;
}
hotElement = dataObj.graphics.hotElement;
// Hover effects and click function is binded to the hot element if present else the set element.
(hotElement || setElement)
.data(EVENTARGS, trackerConfig.eventArgs)
.data(showHoverEffectStr, showHoverEffect)
.data(SETROLLOVERATTR, config.rolloverProperties.hoverAttr || {})
.data(SETROLLOUTATTR, config.rolloverProperties.outAttr || {})
.tooltip(trackerConfig.eventArgs.toolText);
if (hotElemCreated || config.elemCreated) {
(hotElement || setElement)
.click(clickFunc)
.hover(
rolloverResponseSetter(setElement),
rolloutResponseSetter(setElement)
);
}
}
},
addData : function() {
},
removeData : function() {
}
}, UNDEFINED, {
}]);
}]);
FusionCharts.register('module', ['private', 'modules.renderer.js-dataset-progressgauge',
function() {
var global = this,
lib = global.hcLib,
//strings
BLANK = lib.BLANKSTRING,
//add the tools thats are requared
pluck = lib.pluck,
getValidValue = lib.getValidValue,
pluckNumber = lib.pluckNumber,
getFirstValue = lib.getFirstValue,
getLightColor = lib.graphics.getLightColor,
convertColor = lib.graphics.convertColor,
preDefStr = lib.preDefStr,
colorStrings = preDefStr.colors,
COLOR_FFFFFF = colorStrings.FFFFFF,
visibleStr = preDefStr.visibleStr,
ROUND = preDefStr.ROUND,
noneStr = 'none',
parseUnsafeString = lib.parseUnsafeString,
win = global.window,
userAgent = win.navigator.userAgent,
isIE = /msie/i.test(userAgent) && !win.opera,
TRACKER_FILL = 'rgba(192,192,192,' + (isIE ? 0.002 : 0.000001) + ')',
// doc = win.document,
math = Math,
mathMax = math.max,
mathMin = math.min,
dropHash = lib.regex.dropHash,
// isArray = lib.isArray,
PLOTBORDERCOLOR = 'plotBorderColor',
PLOTGRADIENTCOLOR = 'plotGradientColor',
SHOWSHADOW = 'showShadow',
POINTER = 'pointer',
EVENTARGS = 'eventArgs',
GROUPID = 'groupId',
COMPONENT = 'component',
DATASET = 'dataset',
HASHSTRING = lib.HASHSTRING,
toRaphaelColor = lib.toRaphaelColor,
UNDEFINED,
HUNDREDSTRING = lib.HUNDREDSTRING,
COMMASPACE = lib.COMMASPACE,
COMMASTRING = lib.COMMASTRING;
FusionCharts.register(COMPONENT, [DATASET, 'progressgauge', {
type: 'doughnut2d',
configure: function() {
var dataSet = this,
chart = dataSet.chart,
//logic = chart.logic,
conf = dataSet.config,
//fcJSON = dataSet.fcJSON,
JSONData = dataSet.JSONData,
chartConfig = chart.config,
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),
plotDashLen,
plotDashGap,
plotBorderThickness,
isRoundEdges,
showHoverEffect,
plotfillAngle,
plotFillAlpha,
plotRadius,
plotFillRatio,
plotgradientcolor,
plotBorderAlpha,
plotBorderColor,
initailPlotBorderDashStyle,
getDashStyle = lib.getDashStyle,
definedGroupPadding,
isBar = chart.isBar,
is3D = chart.is3D,
isStacked = chart.isStacked,
stack100Percent,
enableAnimation,
parentYAxis,
reflowData = /*logic.chartInstance.jsVars._reflowData*/ {},
reflowDataObj = reflowData.dataObj || (reflowData.dataObj = {}),
reflowChartObj = reflowDataObj.chart || (reflowDataObj.chart = {});
conf.showLegend = pluckNumber(chartAttr.showlegend, 0);
conf.legendSymbolColor = conf.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, '70');
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 = BLANK);
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) : noneStr;
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, 1) * 700;
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.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.zeroPlaneColor = chartConfig.zeroPlaneColor;
conf.zeroPlaneBorderColor = chartConfig.zeroPlaneBorderColor;
conf.zeroPlaneShowBorder = chartConfig.zeroPlaneShowBorder;
conf.use3DLighting = pluckNumber(chartAttr.use3dlighting, 1);
conf.parentYAxis = parentYAxis = pluck(JSONData.parentyaxis && JSONData.parentyaxis.toLowerCase(),
'p') === 's' ? 1 : 0;
dataSet._setConfigure();
},
_setConfigure: function(newDataset, newIndex) {
var dataSet = this,
chart = dataSet.chart,
conf = dataSet.config,
JSONData = dataSet.JSONData,
setDataArr = newDataset || JSONData.data,
setDataLen = setDataArr && setDataArr.length,
categories = chart.config.categories,
singleSeries = chart.singleseries,
catLen = categories && categories.length,
len = (newDataset && newDataset.data.length) || mathMin(catLen, setDataLen),
chartAttr = chart.jsonData.chart,
components = chart.components,
colorM = components.colorManager,
// xAxis = components.xAxis[0],
index = dataSet.index || dataSet.positionIndex,
showplotborder = conf.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, COMMASPACE)),
seriesNameInTooltip = pluckNumber(chartAttr.seriesnameintooltip, 1),
parseTooltext = lib.parseTooltext,
formatedVal,
parserConfig,
setTooltext,
seriesname,
macroIndices,
tempPlotfillAngle,
toolText,
plotDashLen,
plotDashGap,
plotBorderThickness = conf.plotBorderThickness,
isRoundEdges = conf.isRoundEdges,
showHoverEffect = conf.showHoverEffect,
plotfillAngle = conf.plotFillAngle,
plotFillAlpha,
//plotRadius,
plotFillRatio,
//plotgradientcolor,
plotBorderAlpha,
plotBorderDashStyle,
initailPlotBorderDashStyle = conf.plotBorderDashStyle,
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,
toolTipValue,
setDisplayValue,
//definedGroupPadding,
isBar = chart.isBar,
is3D = chart.is3D,
//isStacked = chart.isStacked,
//stack100Percent,
//enableAnimation,
setDataDashed,
setDataPlotDashLen,
setDataPlotDashGap,
i,
maxValue = conf.maxValue || -Infinity,
minValue = conf.minValue || +Infinity,
numberFormatter = dataSet.chart.components.numberFormatter,
tempIndex;
if (!dataStore) {
dataStore = dataSet.components.data = [];
}
// Parsing the attributes and values at set level.
for (i = 0; i < len; i++) {
if (newDataset) {
setData = (newDataset && newDataset.data[i]);
if (newIndex !== undefined) {
tempIndex = newIndex + i;
dataObj = dataStore[tempIndex];
} else {
tempIndex = dataStore.length - len + i;
dataObj = dataStore[tempIndex];
}
} else {
dataObj = dataStore[i];
setData = setDataArr[i];
}
config = dataObj && dataObj.config;
if (!dataObj) {
dataObj = dataStore[i] = {};
}
if (!dataObj.config) {
config = dataStore[i].config = {};
}
config.visible = pluckNumber(setData.visible, true);
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, conf.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 ? noneStr : initailPlotBorderDashStyle);
if (singleSeries) {
plotColor = colorM.getPlotColor(isNaN(tempIndex) ? i : tempIndex);
plotColor = pluck(setData.color, plotColor);
plotFillRatio = pluck(setData.ratio, conf.plotFillRatio);
} else {
plotColor = pluck(setData.color, conf.plotColor);
}
plotFillAlpha = pluck(setData.alpha, conf.plotFillAlpha);
plotBorderAlpha = pluck(setData.alpha, conf.plotBorderAlpha, plotFillAlpha).toString();
config.plotColor = plotColor;
config.plotFillAlpha = pluck(setData.alpha, conf.plotFillAlpha);
config.plotBackgroundFillAlpha = pluckNumber(setData.plotbackgroundfillalpha,
chartAttr.plotbackgroundfillalpha, 30);
// 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,
plotFillAlpha,
plotFillRatio,
plotfillAngle,
isRoundEdges,
conf.plotBorderColor,
plotBorderAlpha,
(isBar ? 1 : 0),
(is3D ? true : false)
);
label = getValidValue(parseUnsafeString(pluck(setData.tooltext, setData.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, conf.plotgradientcolor);
!hoverGradientColor && (hoverGradientColor = BLANK);
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, conf.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 + COMMASTRING + 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)));
if (!showTooltip) {
toolText = false;
} else {
if (formatedVal === null) {
toolText = false;
} else if (setTooltext !== undefined) {
macroIndices = [1, 2, 3, 4, 5, 6, 7];
parserConfig = {
yaxisName: yAxisName,
xaxisName: xAxisName,
formattedValue: formatedVal,
label: label
};
toolText = parseTooltext(setTooltext, macroIndices,
parserConfig, setData, chartAttr, JSONData);
} else {
if (seriesNameInTooltip) {
seriesname = getFirstValue(JSONData && JSONData.seriesname);
}
toolText = seriesname ? seriesname + tooltipSepChar : BLANK;
toolText += label ? label + tooltipSepChar : BLANK;
}
}
config.toolText = toolText;
config.setTooltext = toolText;
tempPlotfillAngle && (plotfillAngle = tempPlotfillAngle);
tempIndex++;
}
conf.maxValue = maxValue;
conf.minValue = minValue;
},
init: function(datasetJSON) {
var dataSet = this,
chart = dataSet.chart,
visible,
showLegend; // need to remove later
if (!datasetJSON) {
return false;
}
dataSet.JSONData = datasetJSON;
dataSet.chartGraphics = chart.chartGraphics;
dataSet.components = {};
dataSet.graphics = {};
dataSet.visible = visible =
pluckNumber(dataSet.JSONData.visible, !Number(dataSet.JSONData.initiallyhidden), 1) === 1;
dataSet.configure();
// temp code
showLegend = dataSet.config.showLegend;
showLegend && dataSet._addLegend();
},
_addLegend: function() {
var dataSet = this,
chart = dataSet.chart,
chartAttr = chart.jsonData.chart,
setDataArr = dataSet.JSONData.data,
config,
i,
dataObj,
dataStore = dataSet.components.data,
fillColor,
strokeColor,
label;
for (i = 0; i < dataStore.length; i += 1) {
dataObj = dataStore[i];
config = dataObj.config;
label = setDataArr[i].label ? setDataArr[i].label : 'Type ' + (i + 1);
fillColor = {
FCcolor: {
color: config.plotColor,
angle: 0,
ratio: '0',
alpha: '100'
}
};
strokeColor = getLightColor(config.plotColor, 60).replace(dropHash, HASHSTRING);
chart.components.legend.addItems(dataSet, dataSet.legendInteractivity, {
type: dataSet.type,
fillColor: toRaphaelColor(fillColor),
strokeColor: toRaphaelColor(strokeColor),
enabled: pluckNumber(chartAttr.includeinlegend, 1),
label: label,
index: i
});
}
},
legendInteractivity: function(dataSet, legendItem) {
var index = legendItem.configuration.index,
set = dataSet.components.data[index],
conf = dataSet.config,
setGraphics = set.graphics,
visible = set.config.visible,
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;
set.config.visible = visible ? 0 : 1;
if (visible) {
if (!conf.animation.duration || !conf.transposeAnimation) {
setGraphics.gaugeBackground.hide();
setGraphics.gaugeMeter.hide();
setGraphics.hotElement.hide();
}
legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
fill: hiddenColor,
'stroke': hiddenColor
});
legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
fill: convertColor(hiddenColor)
});
legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
'stroke': hiddenColor
});
} else {
setGraphics.gaugeBackground.show();
setGraphics.gaugeMeter.show();
setGraphics.hotElement.show();
legendGraphics.legendItemSymbol && legendGraphics.legendItemSymbol.attr({
fill: color,
'stroke': stroke
});
legendGraphics.legendItemText && legendGraphics.legendItemText.attr({
fill: convertColor(itemTextColor)
});
legendGraphics.legendIconLine && legendGraphics.legendIconLine.attr({
'stroke': color
});
}
dataSet.draw();
},
draw: function() {
var dataSet = this,
JSONData = dataSet.JSONData,
conf = dataSet.config,
chartAttr = dataSet.chart.jsonData.chart,
setDataArr = dataSet.components.data,
dataStore = dataSet.components.data,
chart = dataSet.chart,
paper = chart.components.paper,
chartConfig = chart.config,
canvasLeft = chartConfig.canvasLeft,
// canvasRight = chartConfig.canvasRight,
canvasTop = chartConfig.canvasTop,
// canvasBottom = chartConfig.canvasBottom,
canvasHeight = chartConfig.canvasHeight,
canvasWidth = chartConfig.canvasWidth,
parentContainer = chart.graphics.datasetGroup,
gaugeBackgroundContainer = dataSet.graphics.gaugeBackgroundContainer,
gaugeMeterContainer = dataSet.graphics.gaugeMeterContainer,
trackerContainer = dataSet.graphics.trackerContainer,
layers = chart.graphics,
trackerLayer = layers.trackerGroup,
len = dataSet.components.data.length || 0,
i,
setData,
dataObj,
config,
setValue,
colorArr,
maximumOuterRadius,
innerRadius,
width,
cx,
cy,
radius1,
radius2,
startAngle,
endAngle,
gaugeBackground,
arcpath,
gaugeMeter,
attr,
centerRadius,
setLink,
setTooltext,
toolText,
eventArgs,
hotElement,
groupId,
animationDuration = conf.animation.duration,
transposeAnimation = conf.transposeAnimation,
transposeAnimDuration = conf.transposeAnimDuration,
factor = 0,
visible,
ringpath,
animCallBack = function() {
var dataStore = dataSet.components.data,
config,
len = dataSet.components.data.length,
graphics;
for (i = 0; i < len; i++) {
config = dataStore[i].config;
graphics = dataStore[i].graphics;
if (!config.visible) {
graphics.hotElement.hide();
}
}
};
if (!gaugeBackgroundContainer) {
gaugeBackgroundContainer =
dataSet.graphics.gaugeBackgroundContainer =
paper.group('gauge-background', parentContainer);
}
if (!gaugeMeterContainer) {
gaugeMeterContainer =
dataSet.graphics.gaugeMeterContainer = paper.group('gauge-meter', parentContainer);
}
if (!trackerContainer) {
trackerContainer = dataSet.graphics.trackerContainer = paper.group('meter-hot', trackerLayer);
}
for (i = 0; i < len; i++) {
setData = setDataArr[i];
dataObj = dataStore[i];
config = dataObj && dataObj.config;
if (!config.visible) {
continue;
}
factor += 1;
}
maximumOuterRadius = mathMin(canvasHeight / 2, canvasWidth / 2);
innerRadius = centerRadius = 0.2 * mathMin(chart.config.canvasWidth, chart.config.canvasHeight);
width = ((maximumOuterRadius - factor) - innerRadius) / factor;
cx = canvasLeft + canvasWidth * 0.5;
cy = canvasTop + canvasHeight * 0.5;
for (i = 0; i < len; i++) {
setData = setDataArr[i];
dataObj = dataStore[i];
config = dataObj && dataObj.config;
visible = config.visible;
if (!visible && !animationDuration) {
continue;
}
// Creating the data structure if not present for storing the graphics elements.
if (!dataObj.graphics) {
dataStore[i].graphics = {};
}
setValue = config.setValue;
setLink = config.setLink;
setTooltext = getValidValue(parseUnsafeString(pluck(setData.tooltext,
JSONData.plottooltext, chartAttr.plottooltext)));
// Setting the final tooltext.
toolText = config.toolText + (setTooltext ? BLANK : config.toolTipValue);
colorArr = config.colorArr;
groupId = i;
eventArgs = {
index: i,
link: setLink,
value: setValue,
displayValue: config.displayValue,
// categoryLabel: categories[i].label,
toolText: toolText,
id: BLANK,
datasetIndex: dataSet.datasetIndex,
datasetName: JSONData.seriesname,
dataSet: dataSet,
visible: visibleStr,
cx: cx,
cy: cy,
radius: centerRadius
};
radius1 = innerRadius;
radius2 = innerRadius + width;
startAngle = 0;
endAngle = 6.283; // value of twoPI
if (!dataObj.graphics.gaugeBackground) {
gaugeBackground = dataObj.graphics.gaugeBackground =
paper.ringpath(cx, cy, radius1, radius2,
startAngle, endAngle, gaugeBackgroundContainer)
.attr({
fill: convertColor(config.plotColor, config.plotBackgroundFillAlpha),
'stroke-width': 0
});
} else {
attr = {
ringpath: [cx, cy, radius1, radius2, startAngle, endAngle],
fill: convertColor(config.plotColor, config.plotBackgroundFillAlpha),
'stroke-width': 0
};
if (transposeAnimation) {
ringpath = visible ? [cx, cy, radius1, radius2, startAngle, endAngle] :
[cx, cy, radius1, radius1, startAngle, endAngle];
gaugeBackground = dataObj.graphics.gaugeBackground.animate({
ringpath: ringpath
}, transposeAnimDuration, 'easeIn');
} else {
gaugeBackground = dataObj.graphics.gaugeBackground.attr(attr);
}
}
endAngle = mathMin(setValue * 3.6, 359.99);
arcpath = [cx, cy, innerRadius + width / 2, mathMin(setValue * 3.6, 359.99)];
if (animationDuration) {
endAngle = 0;
}
if (!dataObj.graphics.gaugeMeter) {
gaugeMeter = dataObj.graphics.gaugeMeter = paper.arcpath(cx, cy, innerRadius + width / 2,
endAngle, gaugeMeterContainer)
.attr({
stroke: toRaphaelColor(colorArr[0]),
'stroke-width': width,
'stroke-linecap': ROUND
});
if (animationDuration) {
dataObj.graphics.gaugeMeter.animate({
arcpath: arcpath
}, animationDuration, 'easeIn');
}
} else {
attr = {
arcpath: arcpath,
stroke: toRaphaelColor(colorArr[0]),
'stroke-width': width,
'stroke-linecap': ROUND
};
if (transposeAnimation) {
if (visible) {
gaugeMeter = dataObj.graphics.gaugeMeter.animate({
arcpath: arcpath,
'stroke-width': width
}, transposeAnimDuration, 'easeIn', animCallBack);
} else {
arcpath = [cx, cy, innerRadius, 0];
gaugeMeter = dataObj.graphics.gaugeMeter.animate({
arcpath: arcpath,
'stroke-width': 0
}, transposeAnimDuration, 'easeIn', animCallBack);
}
} else {
gaugeMeter = dataObj.graphics.gaugeMeter.attr(attr);
}
}
attr = {
arcpath: arcpath,
cursor: setLink ? POINTER : BLANK,
stroke: TRACKER_FILL,
'stroke-width': width,
'stroke-linecap': ROUND,
ishot: true
};
/*
* If the tooltips are not present then they are created over the hot element,
* else only attributes are set for the existing tooltips.
*/
if (!dataObj.graphics.hotElement) {
hotElement = dataObj.graphics.hotElement = paper.arcpath(cx, cy, innerRadius + width / 2,
mathMin(setValue * 3.6, 359.99), trackerContainer);
dataObj.graphics.hotElement.attr({
cursor: setLink ? POINTER : BLANK,
stroke: TRACKER_FILL,
'stroke-width': width,
'stroke-linecap': ROUND,
ishot: true
});
} else {
dataObj.graphics.hotElement.attr(attr);
}
hotElement = dataObj.graphics.hotElement;
// Hover effects and click function is binded to the
// hot element if present else the set element.
(hotElement)
.data(EVENTARGS, eventArgs)
.data(GROUPID, groupId)
// .click(clickFunc)
.hover(
dataSet._plotRollOver,
dataSet._plotRollOut
)
.tooltip(toolText);
visible && (innerRadius += width + 1);
}
},
_drawDoughnutCenterLabel: function(labelText, cx, cy,
dx, dy, centerLabelConfig, updateConfig, visible, data) {
var dataSet = this,
chart = dataSet.chart,
seriesData = dataSet.config,
labelConfig = centerLabelConfig || seriesData.lastCenterLabelConfig,
chartComponents = chart.components,
paper = chartComponents.paper,
smartLabel = chart.linkedItems.smartLabel,
dataStore = dataSet.components.data,
dataObj = dataStore[data.index],
labelPadding = 2,
textpadding = 2 * 2,
cssObj = {
fontFamily: 'Verdana',
fontSize: 12 + 'px',
lineHeight: (1.2 * 12) + 'px',
fontWeight: 1 ? 'bold' : BLANK,
fontStyle: 0 ? 'italic' : BLANK
},
txtW = ((dx * 0.5 - labelPadding) * 1.414) - textpadding,
txtH = ((dy * 0.5 - labelPadding) * 1.414) - textpadding,
layers = chart.graphics,
dataLabelsLayer = layers.datalabelsGroup,
dataLabelContainer = dataSet.graphics.dataLabelContainer,
centerLabel,
attr,
smartLabelObj;
//labelOvalBg;
smartLabel.useEllipsesOnOverflow(chart.config.useEllipsesWhenOverflow);
smartLabel.setStyle(cssObj);
smartLabelObj = smartLabel.getSmartText(labelText, txtW, txtH);
if (!dataLabelContainer) {
dataLabelContainer = dataSet.graphics.dataLabelContainer =
paper.group('datalabel', dataLabelsLayer);
}
// if (!grp) {
// grp = dataSet.graphics.centerLabel = paper.group('centerLabel', parentContainer);
// }
attr = {
x: data.cx,
y: data.cy,
text: smartLabelObj.text,
//visibility: visibleStr,
direction: seriesData.textDirection,
opacity: visible ? 0 : 1,
//title: labelConfig.toolText ? BLANK : smartLabelObj.tooltext || BLANK,
fill: toRaphaelColor(dataObj.config.colorArr[0]),
'text-bound': labelConfig.bgOval ? noneStr : [
toRaphaelColor({
color: labelConfig.bgColor,
alpha: labelConfig.bgAlpha
}),
toRaphaelColor({
color: labelConfig.borderColor,
alpha: labelConfig.borderAlpha
}),
labelConfig.borderThickness,
labelConfig.textPadding,
labelConfig.borderRadius
]
};
if (!dataObj.graphics.label) {
centerLabel = dataObj.graphics.label = paper.text(attr, dataLabelContainer);
}
dataObj.graphics.label.attr(attr)
.css(cssObj);
if (!visible) {
dataObj.graphics.label.animate({
opacity: 0
}, 100, 'easeOut');
//dataObj.graphics.label.hide();
} else {
//dataObj.graphics.label.show();
dataObj.graphics.label.animate({
opacity: 1
}, 100, 'easeIn');
}
},
_plotRollOver: function() {
var ele = this.data(EVENTARGS),
dx = ele.radius * 2,
dy = dx;
ele.dataSet._drawDoughnutCenterLabel(ele.toolText, 300, 196, dx, dy, ele.toolText, false, true, ele);
},
_plotRollOut: function() {
var ele = this.data(EVENTARGS),
dx = ele.radius * 2,
dy = dx;
ele.dataSet
._drawDoughnutCenterLabel(ele.toolText, 300, 196, dx, dy, ele.toolText, false, false, ele);
},
// Function to an existing data of a dataset.
updateData: function(dataObj, index, draw) {
var dataSet = this,
conf = dataSet.config,
prevMax = conf.maxValue,
prevMin = conf.prevMin,
chart = dataSet.chart;
dataSet._setConfigure(dataObj, index);
dataSet.setMaxMin();
if (conf.maxValue !== prevMax || conf.minValue !== prevMin) {
dataSet.maxminFlag = true;
}
if (draw) {
chart._setAxisLimits();
dataSet.draw();
}
},
// 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 = []),
conf = dataSet.config,
i,
config,
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;
}
dataStore[index] && (dataStore[index].config.visible = 0);
draw && dataSet.draw();
components.removeDataArr = removeDataArr = removeDataArr.concat(dataStore.splice(index, stretch));
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();
},
manageSpace: function() {
}
}, 'Column']);
}
]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-realtimecolumn', function () {
var global = this,
lib = global.hcLib,
win = global.window,
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
BLANK = lib.BLANKSTRING,
COMMASPACE = lib.COMMASPACE,
NORMALSTRING = 'normal',
math = Math,
mathMax = math.max,
dropHash = lib.regex.dropHash,
HASHSTRING = lib.HASHSTRING,
PXSTRING = 'px',
convertColor = lib.graphics.convertColor,
preDefStr = lib.preDefStr,
animationObjStr = preDefStr.animationObjStr,
UNDEFINED,
visibleStr = preDefStr.visibleStr,
configStr = preDefStr.configStr,
pluck = lib.pluck,
pluckNumber = lib.pluckNumber,
schedular = lib.schedular,
priorityList = lib.priorityList,
chartAPI = lib.chartAPI;
chartAPI ('realtimecolumn', {
showRTvalue : true,
canvasPadding : true,
isRealTime : true,
standaloneInit: true,
creditLabel: creditLabel,
defaultDatasetType : 'realtimecolumn',
applicableDSList: { 'realtimecolumn': true },
transposeAxis : true,
rtManageSpace : true,
_realTimeConfigure : function () {
var iapi = this,
config = iapi.config,
animationObj = config.animationObj,
realTimeConfig = config.realTimeConfig || (config.realTimeConfig = { }),
refreshInterval,
realtimeValueFontColor,
realtimeValueFontSize,
showRTmenuItem,
jsonData = iapi.jsonData,
chartAttrs = jsonData.chart,
catLen = (jsonData.categories && jsonData.categories[0] && jsonData.categories[0].category &&
jsonData.categories[0].category.length) || 0;
// Parsing the real time attributes
realTimeConfig.showRTValue = pluckNumber (chartAttrs.showrealtimevalue, 1),
realTimeConfig.dataStreamURL = pluck (chartAttrs.datastreamurl, BLANK);
realTimeConfig.dataStamp = chartAttrs.datastamp;
realTimeConfig.useMessageLog = pluckNumber (chartAttrs.usemessagelog, 0);
realTimeConfig.clearInterval = pluckNumber (chartAttrs.clearchartinterval, 0);
realTimeConfig.realtimeValueSeparator = pluck (chartAttrs.realtimevaluesep, COMMASPACE);
realTimeConfig.refreshInterval = refreshInterval =
pluckNumber (chartAttrs.refreshinterval, chartAttrs.updateinterval, 2);
realTimeConfig.updateInterval = iapi.config.updateInterval =
pluckNumber (chartAttrs.updateinterval, refreshInterval);
realTimeConfig.realtimeValuePadding = pluckNumber(chartAttrs.realtimevaluepadding);
realTimeConfig.realtimeValueFont = pluck(chartAttrs.realtimevaluefont, BLANK);
realTimeConfig.realtimeValueFontBold = pluck(chartAttrs.realtimevaluefontbold, 0);
realTimeConfig.realtimeValueFontColor = realtimeValueFontColor =
pluck(chartAttrs.realtimevaluefontcolor, BLANK);
realTimeConfig.realtimeValueFontSize = realtimeValueFontSize =
pluckNumber(chartAttrs.realtimevaluefontsize, BLANK);
realTimeConfig.realTimeValuePadding = pluckNumber(chartAttrs.realtimevaluepadding, 5);
realTimeConfig.fontWeight = pluckNumber(chartAttrs.realtimevaluefontbold, 0) ? 'bold' : NORMALSTRING;
realTimeConfig.numDisplaySets = pluckNumber(chartAttrs.numdisplaysets, mathMax(
catLen, 15));
realTimeConfig.refreshInstantly = pluckNumber(chartAttrs.refreshinstantly, 0);
realTimeConfig.showRTmenuItem = showRTmenuItem = pluckNumber(chartAttrs.showrtmenuitem, 0);
// chartAnimation is forced to sync
realTimeConfig.sync = pluckNumber(chartAttrs.sync, refreshInterval > 0.6 ? true : false);
if (realtimeValueFontColor) {
realTimeConfig.realtimeValueFontColor = realtimeValueFontColor.replace(dropHash, HASHSTRING);
}
if (realtimeValueFontSize) {
realTimeConfig.realtimeValueFontSize = realtimeValueFontSize + PXSTRING;
}
refreshInterval *= 1000;
animationObj.duration > refreshInterval && (animationObj.duration = refreshInterval);
if (showRTmenuItem) {
iapi._setRTmenu();
}
},
// Setting the number of categories to be shown.
_setRealTimeCategories : function () {
var iapi = this,
components = iapi.components,
xAxis = components.xAxis[0],
tempArr = [],
realTimeConfig = iapi.config.realTimeConfig,
clear = realTimeConfig && realTimeConfig.clear,
categories = clear ? undefined : iapi.jsonData.categories && iapi.jsonData.categories[0] &&
iapi.jsonData.categories[0].category,
catLen = xAxis.getCategoryLen(),
numDisplaySets = realTimeConfig.numDisplaySets;
// Setting category as per numDisplaySets
catLen = xAxis.getCategoryLen ();
if (catLen < numDisplaySets) {
tempArr.length = numDisplaySets - catLen;
categories = categories ? tempArr.concat (categories) : tempArr;
xAxis.setCategory (categories);
}
else if (catLen > numDisplaySets) {
categories.splice (numDisplaySets, (catLen - numDisplaySets));
xAxis.setCategory (categories);
}
},
// Spacemanagement for real time value
_realTimeValuePositioning : function (availableHeight) {
var iapi = this,
components = iapi.components,
smartLabel = iapi.linkedItems.smartLabel,
height,
space,
config = iapi.config,
realTimeConfig = config.realTimeConfig || (config.realTimeConfig = { }),
padding = realTimeConfig.realTimeValuePadding,
axisConfig =components.xAxis[0].config,
style = axisConfig.trend.trendStyle,
attr = realTimeConfig.style = {
color: convertColor(pluck (realTimeConfig.realtimeValueFontColor, style.color),
pluck(axisConfig.trendlineAlpha, 99)),
fontFamily: pluck(realTimeConfig.realtimeValueFont, style.fontFamily),
fontSize: pluck(realTimeConfig.realtimeValueFontSize, style.fontSize),
fontWeight: pluck(realTimeConfig.fontWeight, style.fontWeight),
lineHeight : pluckNumber(style.lineHeight)
};
smartLabel.useEllipsesOnOverflow(config.useEllipsesWhenOverflow);
smartLabel.setStyle (attr);
// Setting the height to be left for displaying the value.
realTimeConfig.height = height = smartLabel.getOriSize (lib.TESTSTR).height;
realTimeConfig.canvasBottom = config.canvasBottom;
space = height + padding;
if (space > availableHeight) {
space = availableHeight;
}
return {
bottom : space
};
},
// Drwaing the real time value.
_drawRealTimeValue : function () {
var iapi = this,
components = iapi.components,
config = iapi.config,
dataset = components.dataset,
paper = components.paper,
smartLabel = iapi.linkedItems.smartLabel,
realTimeConfig = config.realTimeConfig,
realtimeValueSeparator = realTimeConfig.realtimeValueSeparator,
len = dataset.length,
displayValue = BLANK,
animationObj = iapi.get(configStr, animationObjStr),
animObj = animationObj.animObj,
dummyObj = animationObj.dummyObj,
animationDuration = animationObj.duration,
canvasBottom = realTimeConfig.canvasBottom,
height = realTimeConfig.height,
canvasLeft = config.canvasLeft,
canvasRight = config.canvasRight,
style = realTimeConfig.style || {},
width,
positionX,
positionY,
realTimeValue = components.realTimeValue || (components.realTimeValue = {}),
graphics = realTimeValue.graphics,
chartGraphics = iapi.graphics,
attr,
parentLayer = chartGraphics.parentGroup,
realTimeValueGroup = chartGraphics.realTimeValueGroup,
datasetStore,
drawn,
prevData,
dataDisplayValue,
i;
if (realTimeConfig.clear && realTimeValue.graphics) {
realTimeValue.graphics.attr({text : BLANK});
}
if (!realTimeValueGroup) {
realTimeValueGroup = chartGraphics.realTimeValueGroup = paper.group('realTimeValue',
parentLayer).insertBefore(chartGraphics.datalabelsGroup);
}
else {
for (i = 0; i < len; i ++) {
datasetStore = dataset[i].components.data;
prevData = datasetStore[datasetStore.length - 1];
dataDisplayValue = prevData && prevData.config.displayValue;
displayValue += (dataDisplayValue ?
(dataDisplayValue === UNDEFINED ? BLANK : dataDisplayValue + realtimeValueSeparator) : BLANK);
}
displayValue = displayValue.substring(0, displayValue.length - realtimeValueSeparator.length);
smartLabel.useEllipsesOnOverflow(config.useEllipsesWhenOverflow);
smartLabel.setStyle (style);
width = smartLabel.getOriSize (displayValue).width;
positionX = (canvasLeft + canvasRight) / 2;
positionY = canvasBottom - height / 2;
attr = {
x: positionX || 0,
y: positionY || 0,
'font-size': style.fontSize,
'font-weight': style.fontWeight,
'font-family': style.fontFamily,
'line-height': style.lineHeight,
visibility: visibleStr
};
if (!graphics) {
graphics = realTimeValue.graphics = paper.text(attr, realTimeValueGroup);
drawn = true;
}
graphics.attr({
text: displayValue,
fill: style.color
});
if (graphics && !drawn) {
graphics.show();
graphics.animateWith(dummyObj, animObj, attr, animationDuration);
}
}
},
_hideRealTimeValue : function () {
var iapi = this,
components = iapi.components,
realTimeValue = components.realTimeValue || (components.realTimeValue = {}),
graphics = realTimeValue && realTimeValue.graphics;
graphics && graphics.hide();
},
_getData : function () {
var iapi = this,
components = iapi.components,
dataset = components.dataset,
xAxis = (components.xAxis && components.xAxis[0]) || components.scale,
length,
i,
j,
store = [],
maxLength = 0,
data,
innerStore;
if (dataset) {
length = dataset.length;
// Finding the dataset with maximum length
for (i = 0; i < length; i ++) {
maxLength = mathMax(maxLength, dataset[i].components.data.length);
}
for (i = 0; i < maxLength; i++) {
innerStore = store[i] = [];
innerStore[0] = xAxis.getLabel(i).label;
for (j = 1; j <= length; j ++) {
data = dataset[j - 1].components.data[i];
innerStore[j] = data && data.config.setValue;
}
}
return store;
}
},
/**
* This function feeds real-time data to real-time gauges. In single value gauges (LEDs, Bulb, Cylinder,
* Thermometer) the function takes a numeric value as the parameter. For Angular gauge and Horizontal Linear
* gauge, this function accepts two parameters - the dial number and the value to update.
*
* @group chart-realtime
* @see FusionCharts#feedData
* @see FusionCharts#getData
* @param {string} value
* @param {string} label
*/
_setData : function (value, label) {
var stream = BLANK;
if ((value && value.toString) || value === BLANK || value === 0) {
stream = 'value=' + value.toString();
}
if ((label && label.toString) || label === BLANK) {
stream = stream + '&label=' + label.toString();
}
if (stream) {
this.feedData(stream);
}
},
/**
* @group chart-realtime
* @see FusionCharts#startUpdate
* @see FusionCharts#restartUpdate
* @see FusionCharts#isUpdateActive
* @see FusionCharts#clearChart
*/
_stopUpdate : function (source) {
var iapi = this,
realTimeConfig = iapi.config.realTimeConfig,
loadData = iapi.linkedItems.timers && iapi.linkedItems.timers.setTimeout.loadData,
chartObj = iapi.chartInstance,
state = chartObj.__state;
clearTimeout(state._toRealtime);
state._rtAjaxObj && state._rtAjaxObj.abort();
state._rtPaused = true;
// Clearing previously queqed updates of the chart if any ideally when update interval is less than
// refresh interval.
loadData && clearTimeout(loadData);
realTimeConfig.clearIntervalFlag = false;
/**
* This event is raised when the real time update of the chart is stopped .
*
* @event Fusioncharts#realTimeUpdateStopped
* @group chart-realtime
*/
global.raiseEvent('realimeUpdateStopped', {
source: source
}, chartObj);
},
/**
* @group chart-realtime
* @see FusionCharts#startUpdate
* @see FusionCharts#stopUpdate
* @see FusionCharts#isUpdateActive
* @see FusionCharts#clearChart
*/
_restartUpdate : function () {
var chartObj = this.chartInstance,
state = chartObj.__state;
if (state._rtDataUrl && state._rtPaused) {
state._rtPaused = false;
state._rtAjaxObj.get(state._rtDataUrl);
}
},
/**
* @group chart-realtime
* @see FusionCharts#startUpdate
* @see FusionCharts#stopUpdate
* @see FusionCharts#clearChart
* @see FusionCharts#restartUpdate
*/
_isUpdateActive : function () {
var state = this.chartInstance.__state;
return !state._rtPaused;
},
_setRTmenu : function () {
var iapi = this,
chartMenuTools = iapi.chartMenuTools,
setChartTools = chartMenuTools.set,
updateChartMenuTools = chartMenuTools.update,
stopState = false,
toggle = function () {
if (stopState) {
iapi._restartUpdate.call(iapi);
updateChartMenuTools('Restart Update', 'Stop Update', iapi);
stopState = false;
}
else {
iapi._stopUpdate.call(iapi);
updateChartMenuTools('Stop Update', 'Restart Update', iapi);
stopState = true;
}
},
toolArray = [{
'Clear Chart' : {
handler: function () {
iapi._clearChart.call(iapi);
},
action: 'click'
}
},
{
'Stop Update' : {
handler: function () {
toggle();
},
action: 'click'
}
}];
setChartTools(toolArray);
},
_getDataJSON : function () {
return this.config.realTimeConfig.legacyUpdateObj || {
values: []
};
},
// Function to copy the original data to a different DS for showing tooltip in RT charts.
_setRTdata : function () {
var iapi = this,
components = iapi.components,
datasets = components.dataset,
i,
dataRT,
dataset,
removeDataArr,
removeDataArrLen,
datasetComponents,
data,
dataLen,
len = datasets.length;
for (i = len; i--; ) {
dataset = datasets[i];
datasetComponents = dataset.components;
removeDataArr = datasetComponents.removeDataArr || [];
removeDataArrLen = removeDataArr.length;
data = datasetComponents.data;
dataLen = data.length;
dataRT = [].concat(removeDataArr, data.slice(removeDataArrLen, dataLen));
datasetComponents.dataRT = dataRT;
}
},
eiMethods : {
feedData : function () {
var chartContainer = this,
chart = chartContainer.apiInstance,
list = chart.getJobList(),
callback = arguments[1],
updateStr,
output,
asyncRender = chart.chartInstance.args.asyncRender;
if (asyncRender || callback) {
updateStr = arguments[0];
list.eiMethods.push(schedular.addJob(function(){
output = chart.feedData.call(chart, updateStr);
if (typeof callback === 'function') {
callback(output);
}
}, chart, [], priorityList.postRender));
}
else {
return chart.feedData.apply(chart, arguments);
}
},
setData : function () {
var chart = this.apiInstance,
list = chart.getJobList(),
asyncRender = chart.chartInstance.args.asyncRender;
asyncRender ? list.eiMethods.push(schedular.addJob(chart._setData, chart, arguments,
priorityList.postRender)) : chart._setData.apply(chart, arguments);
},
stopUpdate : function () {
var chart = this.apiInstance,
list = chart.getJobList(),
asyncRender = chart.chartInstance.args.asyncRender;
asyncRender ? list.eiMethods.push(schedular.addJob(chart._stopUpdate, chart, [],
priorityList.postRender)) : chart._stopUpdate.apply(chart, arguments);
},
restartUpdate : function () {
this.apiInstance._restartUpdate.apply(this.apiInstance, arguments);
},
isUpdateActive : function () {
return this.apiInstance._isUpdateActive.apply(this.apiInstance, arguments);
},
clearChart : function () {
var chart = this.apiInstance,
list = chart.getJobList(),
asyncRender = chart.chartInstance.args.asyncRender;
asyncRender ? list.eiMethods.push(schedular.addJob(chart._clearChart, chart, [],
priorityList.postRender)) : chart._clearChart.apply(chart, arguments);
},
getData : function () {
return this.apiInstance._getData.apply(this.apiInstance, arguments);
},
showLog : function () {
var msLogger = this.apiInstance.components && this.apiInstance.components.messageLogger;
return msLogger && msLogger.show && msLogger.show.apply(msLogger, arguments);
},
hideLog : function () {
var msLogger = this.apiInstance.components && this.apiInstance.components.messageLogger;
return msLogger && msLogger.hide && msLogger.hide.apply(msLogger, arguments);
},
clearLog : function () {
var msLogger = this.apiInstance.components && this.apiInstance.components.messageLogger;
return msLogger && msLogger.clearLog && msLogger.clearLog.apply(msLogger, arguments);
},
getDataForId : function () {
return this.apiInstance._getDataForId.apply(this.apiInstance, arguments);
},
setDataForId : function () {
return this.apiInstance._setDataForId.apply(this.apiInstance, arguments);
},
getDataJSON : function () {
return this.apiInstance._getDataJSON.apply(this.apiInstance, arguments);
}
}
},chartAPI.mscartesian, {
enablemousetracking: true
});
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-realtimestackedcolumn', function () {
var global = this,
lib = global.hcLib,
chartAPI = lib.chartAPI;
chartAPI ('realtimestackedcolumn', {
},chartAPI.realtimecolumn, {
isstacked: true,
enablemousetracking: true
});
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-gaugebase', function () {
var global = this,
lib = global.hcLib,
win = global.window,
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
chartAPI = lib.chartAPI,
extend2 = lib.extend2,
defaultGaugePaletteOptions = extend2({}, lib.defaultGaugePaletteOptions);
chartAPI('gaugebase', {
creaditLabel: creditLabel,
defaultPaletteOptions: defaultGaugePaletteOptions,
multiValueGauge: false,
decimals: 2,
formatnumberscale: 0,
drawAnnotations: true,
useScaleRecursively: true,
includeColorRangeInLimits: false,
isWidget : true,
_createAxes: function () {
// Empty stub because subset of guages (pyramid, funnel) dont use axis.
},
_feedAxesRawData: function () {
// Empty stub because subset of guages (pyramid, funnel) dont use axis.
},
_setCategories: function () {
// Empty stub because subset of guages category.
},
_setAxisLimits: function () {
// Empty stub because subset of guages axis.
},
// Only updates the internal data-structure without updating visuals.
realTimeUpdate : function (dataObj) {
var iapi = this,
components = iapi.components,
dataset = components.dataset,
newDataset = dataObj.dataset,
newCategory = (dataObj.categories && dataObj.categories.category) || [],
realTimeConfig = iapi.config.realTimeConfig = iapi.config.realTimeConfig ||
(iapi.config.realTimeConfig = {}),
data,
length,
i,
curDataset;
if (dataset) {
curDataset = newDataset[0];
data = curDataset.data;
for (i = 0, length = data.length; i < length; i++) {
data[i].label = newCategory[i] && newCategory[i].label;
}
//curDataset.data[0].label = newCategory[0].label;
dataset[0].updateData (curDataset);
dataset[0].maxminFlag && (realTimeConfig.maxminFlag = dataset[0].maxminFlag);
}
},
_clearChart : function () {
},
_realTimeConfigure : chartAPI.realtimecolumn,
_setRTmenu : function () {
var iapi = this,
chartMenuTools = iapi.chartMenuTools,
setChartTools = chartMenuTools.set,
updateChartMenuTools = chartMenuTools.update,
stopState = false,
toggle = function () {
if (stopState) {
iapi._restartUpdate.call(iapi);
updateChartMenuTools('Restart Update', 'Stop Update', iapi);
stopState = false;
}
else {
iapi._stopUpdate.call(iapi);
updateChartMenuTools('Stop Update', 'Restart Update', iapi);
stopState = true;
}
};
setChartTools([{
'Stop Update' : {
handler: function () {
toggle();
},
action: 'click'
}
}]);
},
_getData : chartAPI.realtimecolumn,
/**
* This function feeds real-time data to real-time gauges. In single value gauges (LEDs, Bulb, Cylinder,
* Thermometer) the function takes a numeric value as the parameter. For Angular gauge and Horizontal Linear
* gauge, this function accepts two parameters - the dial number and the value to update.
*
* @group chart-realtime
* @see FusionCharts#feedData
* @see FusionCharts#getData
* @param {string} value
* @param {string} label
*/
_setData: chartAPI.realtimecolumn,
/**
* @group chart-realtime
* @see FusionCharts#startUpdate
* @see FusionCharts#restartUpdate
* @see FusionCharts#isUpdateActive
* @see FusionCharts#clearChart
*/
_stopUpdate: chartAPI.realtimecolumn,
/**
* @group chart-realtime
* @see FusionCharts#startUpdate
* @see FusionCharts#stopUpdate
* @see FusionCharts#isUpdateActive
* @see FusionCharts#clearChart
*/
_restartUpdate: chartAPI.realtimecolumn,
/**
* @group chart-realtime
* @see FusionCharts#startUpdate
* @see FusionCharts#stopUpdate
* @see FusionCharts#clearChart
* @see FusionCharts#restartUpdate
*/
_isUpdateActive: chartAPI.realtimecolumn,
eiMethods : chartAPI.realtimecolumn
}, chartAPI.sscartesian, {
valuefontbold: 1
});
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-axisgaugebase', function () {
var global = this,
lib = global.hcLib,
chartAPI = lib.chartAPI,
pluck = lib.pluck,
pluckNumber = lib.pluckNumber,
BLANK = lib.BLANKSTRING,
pluckFontSize = lib.pluckFontSize,
UNDEFINED,
COMPONENT = 'component',
AXIS = 'axis';
chartAPI('axisgaugebase',{
chartLeftMargin: 15,
chartRightMargin: 15,
chartTopMargin: 10,
chartBottomMargin: 10,
minChartHeight : 10,
minCanvasWidth: 0,
// Below attribute is a temporary attribute which is introduced to alter the position of annotation layer.
// this is required to preserve the default behavior of gauge in version 3.11 as layer is now common for charts
// gauge and powercharts.
annotationRelativeLayer : 'axis',
_createAxes : function() {
var iapi = this,
components = iapi.components,
scale,
CartesianGaugeAxis = FusionCharts.register(COMPONENT, [AXIS, 'gauge']);
components.scale = scale = new CartesianGaugeAxis();
scale.chart = iapi;
scale.init();
},
_feedAxesRawData : function() {
var iapi = this,
components = iapi.components,
colorM = components.colorManager,
dataObj = iapi.jsonData,
chartAttrs = dataObj.chart,
scale,
scaleConf,
chartPaletteStr = lib.chartPaletteStr,
palleteString = chartPaletteStr.chart2D,
ticksBelowGauge = pluckNumber(chartAttrs.ticksbelowgauge),
ticksonright = pluckNumber(chartAttrs.ticksonright),
isAxisOpposite = pluckNumber(chartAttrs.axisontop,
chartAttrs.axisonleft !== UNDEFINED ? !pluckNumber(chartAttrs.axisonleft) : UNDEFINED, (
ticksBelowGauge !== UNDEFINED ? !ticksBelowGauge : UNDEFINED), (
ticksonright !== UNDEFINED ? ticksonright : UNDEFINED),
iapi.isAxisOpposite),
isAxisReverse = pluckNumber(chartAttrs.reverseaxis, iapi.isAxisReverse),
showTickMarks = pluckNumber(chartAttrs.showtickmarks, 1),
showTickValues = pluckNumber(chartAttrs.showtickvalues),
showLimits;
if (!showTickValues && showTickValues !== UNDEFINED) {
showLimits = false;
}
else if (!showTickMarks && showTickValues === UNDEFINED) {
showLimits = false;
}
else {
showLimits = true;
}
scaleConf = {
outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, 'Verdana,sans'),
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,
divLineColor: pluck(chartAttrs.vdivlinecolor, colorM.getColor(palleteString.divLineColor)),
divLineAlpha: pluck(chartAttrs.vdivlinealpha, colorM.getColor('divLineAlpha')),
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('altVGridColor')),
alternateGridAlpha: pluck(chartAttrs.alternatevgridalpha, colorM.getColor('altVGridAlpha')),
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.lowerlimit,
axisMaxValue: chartAttrs.upperlimit,
setAdaptiveMin: chartAttrs.setadaptivemin,
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),
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, '#000000'),
// Tick properties
majorTMNumber : chartAttrs.majortmnumber,
majorTMColor : chartAttrs.majortmcolor,
majorTMAlpha : chartAttrs.majortmalpha,
majorTMHeight : chartAttrs.majortmheight,
tickValueStep : chartAttrs.tickvaluestep,
showTickMarks : chartAttrs.showtickmarks,
connectTickMarks : chartAttrs.connecttickmarks,
showTickValues : chartAttrs.showtickvalues,
majorTMThickness : chartAttrs.majortmthickness,
upperlimit : components.numberFormatter.getCleanValue(chartAttrs.upperlimit),
lowerlimit : components.numberFormatter.getCleanValue(chartAttrs.lowerlimit),
reverseScale : chartAttrs.reversescale,
// Whether to display the Limits
showLimits: chartAttrs.showlimits || showLimits,
//Whether to automatically adjust TM
adjustTM: chartAttrs.adjusttm,
minorTMNumber: pluckNumber(chartAttrs.minortmnumber, iapi.minorTMNumber, 4),
minorTMColor: chartAttrs.minortmcolor,
minorTMAlpha : chartAttrs.minortmalpha,
minorTMHeight: pluckNumber(chartAttrs.minortmheight, chartAttrs.minortmwidth),
minorTMThickness: chartAttrs.minortmthickness,
//Padding between tick mark start position and gauge
tickMarkDistance: pluckNumber(chartAttrs.tickmarkdistance, chartAttrs.tickmarkgap),
//Tick value distance
tickValueDistance: pluckNumber(chartAttrs.tickvaluedistance, chartAttrs.displayvaluedistance),
placeTicksInside: chartAttrs.placeticksinside,
placeValuesInside: chartAttrs.placevaluesinside,
upperLimitDisplay : chartAttrs.upperlimitdisplay,
lowerLimitDisplay : chartAttrs.lowerlimitdisplay,
drawTickMarkConnector: iapi.isHorizontal ? 1 : 0
};
scale = components.scale;
scale.vtrendlines = dataObj.trendpoints;
scale.chart = iapi;
scale.setCommonConfigArr(scaleConf, !iapi.isHorizontal, isAxisReverse, isAxisOpposite);
scale.configure();
},
_setAxisLimits : function () {
var iapi = this,
components = iapi.components,
chartAttrs = iapi.jsonData.chart,
scale = components.scale,
minMaxObj;
minMaxObj = components.dataset[0].getDataLimits();
(minMaxObj.max === -Infinity) && (minMaxObj.max = 0);
(minMaxObj.min === Infinity) && (minMaxObj.min = 0);
iapi.colorRange && scale.setAxisConfig({
lowerlimit: pluckNumber(chartAttrs.lowerlimit, minMaxObj.forceMin ? minMaxObj.min : UNDEFINED),
upperlimit: pluckNumber(chartAttrs.upperlimit, minMaxObj.forceMax ? minMaxObj.max : UNDEFINED)
});
scale.setDataLimit(minMaxObj.max, minMaxObj.min);
},
_spaceManager: function () {
var spaceForActionBar,
actionBarSpace,
iapi = this,
config = iapi.config,
components = iapi.components,
dataset = components.dataset[0],
scale = components.scale,
is3d = iapi.is3D,
chartAttrs = iapi.jsonData.chart,
showBorder = pluckNumber (chartAttrs.showborder, is3d ? 0 : 1),
isHorizontal = iapi.isHorizontal,
minChartWidth = config.minChartWidth,
minChartHeight = config.minChartHeight,
chartBorderWidth =
config.borderWidth = showBorder ? pluckNumber (chartAttrs.borderthickness, 1) : 0,
chartBorderVertical,
chartBorderHorizontal;
if ((config.canvasWidth - 2 * chartBorderWidth) < minChartWidth ) {
chartBorderVertical = (config.canvasWidth - minChartWidth) / 2;
}
if ((config.canvasHeight - 2 * chartBorderWidth) < minChartHeight ) {
chartBorderHorizontal = (config.canvasHeight - minChartHeight) / 2;
}
iapi._allocateSpace ( {
top : chartBorderHorizontal || chartBorderWidth,
bottom : chartBorderHorizontal|| chartBorderWidth,
left : chartBorderVertical || chartBorderWidth,
right : chartBorderVertical || chartBorderWidth
});
spaceForActionBar = config.availableHeight * 0.225;
actionBarSpace = iapi._manageActionBarSpace && iapi._manageActionBarSpace(spaceForActionBar) ||
{};
iapi._allocateSpace(actionBarSpace);
if (isHorizontal) {
iapi._allocateSpace(scale.placeAxis(config.availableHeight));
}
else {
iapi._allocateSpace(scale.placeAxis(config.availableWidth));
}
// iapi._allocateSpace(iapi._manageCaptionSpacing(config.availableHeight * 0.4));
iapi._manageChartMenuBar(config.availableHeight * 0.4);
dataset._manageSpace && iapi._allocateSpace(dataset._manageSpace(config.availableHeight));
scale.setAxisConfig({
drawPlotlines : iapi.drawPlotlines,
drawPlotBands : iapi.drawPlotBands
});
},
_postSpaceManagement : function () {
var iapi = this,
config = iapi.config,
components = iapi.components,
scale = components.scale,
isHorizontal = iapi.isHorizontal;
if (isHorizontal) {
scale.setAxisDimention({
axisLength : config.canvasWidth
});
}
else {
scale.setAxisDimention({
axisLength : config.canvasHeight
});
}
},
_getDataJSON: function () {
var i = 0,
len,
dataObj,
values = [],
labels = [],
toolTexts = [],
data = this.components.dataset[0].components.data;
if (!data || !data.length) {
len = 0;
} else {
len = data.length;
}
for (;i < len; i += 1) {
dataObj = data[i].config;
values.push(dataObj.itemValue);
labels.push(dataObj.formatedVal || BLANK);
toolTexts.push(dataObj.toolText || BLANK);
}
return {
values: values,
labels: labels,
toolTexts: toolTexts
};
}
}, chartAPI.gaugebase);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-funnelpyramidbase', function () {
var global = this,
lib = global.hcLib,
chartAPI = lib.chartAPI,
preDefStr = lib.preDefStr,
R = lib.Raphael,
configStr = preDefStr.configStr,
ROUND = preDefStr.ROUND,
animationObjStr = preDefStr.animationObjStr;
chartAPI('funnelpyramidbase', {
showRTvalue : false,
canvasPadding : false,
sliceOnLegendClick: true,
defaultDatasetType : 'funnelpyramidbaseds',
applicableDSList: {'funnel': true},
hasCanvas: false,
defaultPlotShadow: 1,
subTitleFontSizeExtender: 0,
tooltippadding: 3,
defaultPaletteOptions: lib.defaultPaletteOptions,
drawAnnotations: true,
hasLegend: true,
isDataLabelBold : false,
dontShowLegendByDefault: true,
formatnumberscale: 1,
isSingleSeries: true,
alignCaptionWithCanvas: 0,
_updateVisuals : function () {
var iapi = this,
config = iapi.config,
container = iapi.linkedItems.container,
components = iapi.components,
legend = components.legend,
paper = components.paper,
tooltip = components.tooltip,
chartInstance = iapi.chartInstance,
animationObj = iapi.get(configStr, animationObjStr),
animType = animationObj.animType,
dummyObj = animationObj.dummyObj,
animObj = animationObj.animObj,
animationDuration = animationObj.duration,
attr,
animationStarted;
config.animationStarted = true;
if (!paper) {
paper = components.paper = new R (container, container.offsetWidth, container.offsetHeight);
paper.setConfig('stroke-linecap', ROUND);
}
else {
attr = {
width: container.offsetWidth,
height: container.offsetHeight
};
animationStarted = true;
iapi._chartAnimation(true);
paper.animateWith(dummyObj, animObj, attr, animationDuration, animType);
}
// Setting tooltip style
paper.tooltip (tooltip.style, tooltip.config.shadow, tooltip.config.constrain);
iapi.setChartCursor();
//create drawing layers
iapi._createLayers ();
iapi._setDataLabelStyle();
//Start the chart animation
!animationStarted && iapi._chartAnimation(true);
// draw components
iapi._drawBackground ();
components.chartMenuBar && iapi._drawChartMenuBar();
iapi._manageCaptionPosition ();
components.caption && components.caption.draw();
components.actionBar && iapi.drawActionBar();
iapi._drawDataset ();
if (iapi.hasLegend !== false) {
legend.drawLegend ();
}
iapi._drawCreditLabel ();
iapi._drawLogo();
if (chartInstance.annotations) {
iapi._drawAnnotations ();
}
iapi.createChartStyleSheet ();
}
}, chartAPI.gaugebase);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-funnel', function () {
var global = this,
lib = global.hcLib,
win = global.window,
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
chartAPI = lib.chartAPI;
chartAPI('funnel', {
friendlyName: 'Funnel Chart',
standaloneInit: true,
creditLabel: creditLabel,
defaultDatasetType : 'funnel',
applicableDSList: { 'funnel': true },
useSortedData: true
}, chartAPI.funnelpyramidbase);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-pyramid', function () {
var global = this,
lib = global.hcLib,
win = global.window,
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
chartAPI = lib.chartAPI;
chartAPI('pyramid', {
friendlyName: 'Funnel Chart',
standaloneInit: true,
creditLabel: creditLabel,
defaultDatasetType : 'pyramid',
applicableDSList: { 'pyramid': true },
useSortedData: false
}, chartAPI.funnelpyramidbase);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-vled', function () {
var global = this,
lib = global.hcLib,
COMPONENT = 'component',
DATASET = 'dataset',
DATASET_GROUP = 'datasetGroup',
AXIS = 'axis',
pluckNumber = lib.pluckNumber,
win = global.window,
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
chartAPI = lib.chartAPI;
chartAPI('vled', {
showRTvalue : false,
canvasPadding : false,
friendlyName: 'Vertical LED Gauge',
defaultSeriesType : 'led',
defaultPlotShadow: 1,
standaloneInit: true,
realtimeEnabled: true,
chartleftmargin: 15,
chartrightmargin: 15,
charttopmargin: 10,
chartbottommargin: 10,
showTooltip : 0,
connectTickMarks: 0,
creditLabel: creditLabel,
isHorizontal: false,
isAxisOpposite : true,
hasLegend : false,
drawPlotlines : false,
drawPlotBands : false,
isAxisReverse : false,
hasCanvas: false,
isRealTime: true,
defaultDatasetType : 'led',
colorRange: true,
applicableDSList: {'led': true},
_getData : function () {
var iapi = this,
components = iapi.components,
dataset = components.dataset,
data,
dataObj;
if (dataset) {
dataObj = dataset[0].components.data;
if (dataObj && dataObj[0]) {
data = dataObj[0].config;
return pluckNumber(data.setValue, data.itemValue);
}
}
},
_createDatasets : function () {
var iapi = this,
components = iapi.components,
dataObj = iapi.jsonData,
//data = dataObj.data,
datasetStore,
datasetObj,
value = dataObj.value,
target = dataObj.target,
defaultSeriesType = iapi.defaultDatasetType,
dsType,
GroupManager,
groupManagerName,
DsGroupClass,
DsClass,
dataOnlyArr = [],
JSONData,
prevDataLength,
currDataLength,
datasetJSON;
datasetStore = components.dataset || (components.dataset = []);
dataOnlyArr.push({
value: value,
target: target
});
datasetJSON = {data: dataOnlyArr};
iapi.config.categories = dataOnlyArr;
datasetStore = components.dataset || (components.dataset = []);
dsType = defaultSeriesType;
if (dsType) {
/// get the DsClass
DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
if (DsClass) {
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 (!datasetStore[0]) {
// create the dataset Object
datasetObj = new DsClass();
datasetStore.push(datasetObj);
datasetObj.chart = iapi;
GroupManager && GroupManager.addDataSet(datasetObj, 0, 0);
datasetObj.init(datasetJSON);
}
else {
JSONData = datasetStore[0].JSONData;
prevDataLength = JSONData.data.length;
currDataLength = datasetJSON.data.length;
// Removing data plots if the number of current data plots is more than the existing ones.
if (prevDataLength > currDataLength) {
datasetStore[0].removeData(currDataLength - 1, prevDataLength - currDataLength, false);
}
datasetStore[0].JSONData = datasetJSON;
datasetStore[0].configure();
}
}
}
},
_createAxes : function() {
var iapi = this,
components = iapi.components,
scale,
CartesianGaugeAxis = FusionCharts.register(COMPONENT, [AXIS, 'gauge']);
components.scale = scale = new CartesianGaugeAxis();
scale.chart = iapi;
scale.init();
}
}, chartAPI.axisgaugebase);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-vbullet',function () {
var global = this,
lib = global.hcLib,
//add the tools thats are requared
pluck = lib.pluck,
pluckNumber = lib.pluckNumber,
chartAPI = lib.chartAPI,
zeroCommaHundredStr = '0,100',
win = global.window,
COMPONENT = 'component',
AXIS = 'axis',
UNDEFINED,
pluckFontSize = lib.pluckFontSize, // To get the valid font size (filters negative values)
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);
chartAPI('vbullet', {
friendlyName: 'Vertical Bullet Gauge',
creditLabel: creditLabel,
defaultSeriesType: 'bullet',
gaugeType: 4,
ticksOnRight: 0,
// colorRangeFillMix: '{light-10},{dark-20},{light-50},{light-85}',
// colorRangeFillRatio: '0,8,84,8',
standaloneInit: true,
hasCanvas: true,
singleseries: true,
isHorizontal: false,
isAxisOpposite : false,
isAxisReverse : false,
defaultDatasetType : 'bullet',
applicableDSList: {'bullet': true},
defaultPaletteOptions : {
//Store colors now
paletteColors: [['A6A6A6', 'CCCCCC', 'E1E1E1', 'F0F0F0'],
['A7AA95', 'C4C6B7', 'DEDFD7', 'F2F2EE'],
['04C2E3','66E7FD','9CEFFE','CEF8FF'],
['FA9101', 'FEB654', 'FED7A0', 'FFEDD5'],
['FF2B60', 'FF6C92', 'FFB9CB', 'FFE8EE']],
//Store other colors
// ------------- For 2D Chart ---------------//
//We're storing 5 combinations, as we've 5 defined palettes.
bgColor: ['FFFFFF', 'CFD4BE,F3F5DD', 'C5DADD,EDFBFE', 'A86402,FDC16D', 'FF7CA0,FFD1DD'],
bgAngle: [270, 270, 270, 270, 270],
bgRatio: [zeroCommaHundredStr, zeroCommaHundredStr, zeroCommaHundredStr, zeroCommaHundredStr,
zeroCommaHundredStr],
bgAlpha: ['100', '60,50', '40,20', '20,10', '30,30'],
toolTipBgColor: ['FFFFFF', 'FFFFFF', 'FFFFFF', 'FFFFFF', 'FFFFFF'],
toolTipBorderColor: ['545454', '545454', '415D6F', '845001', '68001B'],
baseFontColor: ['333333', '60634E', '025B6A', 'A15E01', '68001B'],
tickColor: ['333333', '60634E', '025B6A', 'A15E01', '68001B'],
trendColor: ['545454', '60634E', '415D6F', '845001', '68001B'],
plotFillColor: ['545454', '60634E', '415D6F', '845001', '68001B'],
borderColor: ['767575', '545454', '415D6F', '845001', '68001B'],
borderAlpha: [50, 50, 50, 50, 50]
},
_createAxes : function() {
var iapi = this,
components = iapi.components,
scale,
CartesianGaugeAxis = FusionCharts.register(COMPONENT, [AXIS, 'gauge']);
components.scale = scale = new CartesianGaugeAxis();
scale.chart = iapi;
scale.init();
},
_feedAxesRawData : function() {
var iapi = this,
components = iapi.components,
colorM = components.colorManager,
dataObj = iapi.jsonData,
chartAttrs = dataObj.chart,
scale,
scaleConf,
chartPaletteStr = lib.chartPaletteStr,
palleteString = chartPaletteStr.chart2D,
ticksBelowGraph = pluckNumber(chartAttrs.ticksbelowgraph, 1),
isAxisOpposite = pluckNumber(chartAttrs.ticksonright, chartAttrs.axisontop,
chartAttrs.axisonleft !== UNDEFINED ? !pluckNumber(chartAttrs.axisonleft) : UNDEFINED,
!ticksBelowGraph, iapi.isAxisOpposite);
scaleConf = {
outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, 'Verdana,sans'),
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('divLineAlpha')),
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('altVGridColor')),
alternateGridAlpha: pluck(chartAttrs.alternatevgridalpha, colorM.getColor('altVGridAlpha')),
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.lowerlimit,
axisMaxValue: chartAttrs.upperlimit,
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),
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, '#000000'),
// Tick properties
majorTMNumber : chartAttrs.majortmnumber,
majorTMColor : chartAttrs.majortmcolor,
majorTMAlpha : chartAttrs.majortmalpha,
majorTMHeight : chartAttrs.majortmheight,
tickValueStep : chartAttrs.tickvaluestep,
showTickMarks : chartAttrs.showtickmarks,
connectTickMarks : chartAttrs.connecttickmarks,
showTickValues : chartAttrs.showtickvalues,
majorTMThickness : chartAttrs.majortmthickness,
upperlimit : components.numberFormatter.getCleanValue(chartAttrs.upperlimit),
lowerlimit : components.numberFormatter.getCleanValue(chartAttrs.lowerlimit),
reverseScale : chartAttrs.reversescale,
// Whether to display the Limits
showLimits: pluckNumber(chartAttrs.showlimits, chartAttrs.showtickmarks),
//Whether to automatically adjust TM
adjustTM: chartAttrs.adjusttm,
minorTMNumber: pluckNumber(chartAttrs.minortmnumber, 0),
minorTMColor: chartAttrs.minortmcolor,
minorTMAlpha : chartAttrs.minortmalpha,
minorTMHeight: pluckNumber(chartAttrs.minortmheight, chartAttrs.minortmwidth),
minorTMThickness: chartAttrs.minortmthickness,
//Padding between tick mark start position and gauge
tickMarkDistance: pluckNumber(chartAttrs.tickmarkdistance, chartAttrs.tickmarkgap),
//Tick value distance
tickValueDistance: pluckNumber(chartAttrs.tickvaluedistance, chartAttrs.displayvaluedistance),
placeTicksInside: chartAttrs.placeticksinside,
placeValuesInside: chartAttrs.placevaluesinside,
upperLimitDisplay : chartAttrs.upperlimitdisplay,
lowerLimitDisplay : chartAttrs.lowerlimitdisplay
};
scale = components.scale;
scale.chart = iapi;
scale.setCommonConfigArr(scaleConf, !iapi.isHorizontal, false, isAxisOpposite);
scale.configure();
},
_drawCanvas : function () {
}
}, chartAPI.vled);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-hled', function () {
var global = this,
lib = global.hcLib,
win = global.window,
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
chartAPI = lib.chartAPI;
chartAPI('hled', {
friendlyName: 'Vertical LED Gauge',
defaultSeriesType : 'led',
defaultPlotShadow: 1,
standaloneInit: true,
realtimeEnabled: true,
chartleftmargin: 15,
chartrightmargin: 15,
charttopmargin: 10,
chartbottommargin: 10,
showTooltip : 0,
connectTickMarks: 0,
isHorizontal: true,
isAxisOpposite : false,
creditLabel: creditLabel
}, chartAPI.vled);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-hlineargauge', function () {
var global = this,
lib = global.hcLib,
pluck = lib.pluck,
getValidValue = lib.getValidValue,
BLANK = lib.BLANKSTRING,
BLANKSTRING = BLANK,
getDashStyle = lib.getDashStyle,
getFirstValue = lib.getFirstValue,
COMPONENT = 'component',
DATASET = 'dataset',
UNDEFINED,
parseUnsafeString = lib.parseUnsafeString,
preDefStr = lib.preDefStr,
animationObjStr = preDefStr.animationObjStr,
configStr = preDefStr.configStr,
pluckNumber = lib.pluckNumber,
getFirstDefinedValue = lib.getFirstDefinedValue,
win = global.window,
noneStr = 'none',
convertColor = lib.graphics.convertColor,
getColorCodeString = lib.getColorCodeString,
COMMASTRING = lib.COMMASTRING,
math = Math,
mathMax = math.max,
toRaphaelColor = lib.toRaphaelColor,
priorityList = lib.priorityList,
schedular = lib.schedular,
M = 'M',
L = 'L',
POSITION_TOP = preDefStr.POSITION_TOP,
POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
chartAPI = lib.chartAPI;
chartAPI('hlineargauge', {
showRTvalue : false,
canvasPadding : false,
friendlyName: 'Horizontal Linear Gauge',
creditLabel: creditLabel,
defaultDatasetType: 'hlineargauge',
standaloneInit: true,
isHorizontal: true,
isAxisOpposite : false,
hasLegend : false,
drawPlotlines : false,
drawPlotBands : false,
isAxisReverse : false,
minorTMNumber : 4,
isRealTime : true,
colorRange : true,
applicableDSList : {'hlineargauge' : true},
rtParserModify : true,
_drawCanvas: function () {
var iapi = this,
components = iapi.components,
chartConfig = iapi.config,
// For proper annotation drawing.
canvasGroup = iapi.graphics.datasetGroup,
width = chartConfig.canvasWidth,
height = chartConfig.canvasHeight,
canvasTop = chartConfig.canvasTop,
canvasLeft = chartConfig.canvasLeft,
scale = components.scale,
min = scale.config.axisRange.min,
max = scale.config.axisRange.max,
jsonData = iapi.jsonData,
chartAttrs = jsonData.chart,
trendArray = jsonData.trendpoints && jsonData.trendpoints.point,
showGaugeBorder = pluckNumber(chartAttrs.showgaugeborder, 1),
gaugeFillMix = getFirstDefinedValue(chartAttrs.colorrangefillmix, chartAttrs.gaugefillmix,
'{light-10},{dark-20},{light-50},{light-85}'),
gaugeFillRatio = getFirstDefinedValue(chartAttrs.colorrangefillratio, chartAttrs.gaugefillratio,
chartAttrs.gaugefillratio, '0,8,84,8'),
gaugeBorderColor = pluck(chartAttrs.colorrangebordercolor, chartAttrs.gaugebordercolor, '{dark-20}'),
gaugeBorderAlpha = pluckNumber(chartAttrs.colorrangeborderalpha, chartAttrs.gaugeborderalpha, 100),
gaugeBorderThickness = showGaugeBorder ? pluckNumber(chartAttrs.colorrangeborderthickness,
chartAttrs.gaugeborderthickness, 1) : 0,
gaugeType = 1,
colorArray = components.colorRange && components.colorRange.getColorRangeArr(min, max),
showShadow = pluckNumber(chartAttrs.showshadow, 1),
shadow,
i,
y,
len,
marker,
orient,
colorGrp,
getRectXY,
angle,
color,
colorObj,
borderColor,
xyObj,
trendPointConfig,
trendZoneElem,
trendZoneElems,
trendObjElem,
trendObjElems,
trendObj,
paper = components.paper,
colorM = components.colorManager,
crColor,
crAlpha,
borderAlpha,
shadowAlpha,
startAngle,
colorRangeElem,
animationObj = iapi.get(configStr, animationObjStr),
duration = animationObj.duration,
dummyObj = animationObj.dummyObj,
animObj = animationObj.animObj,
animType = animationObj.animType,
pointOrientation= {
top: 1,
bottom: 3
},
attr,
trendZoneElemsCount = 0,
trendObjElemsCount = 0,
markerCount = 0,
canvas = components.canvas,
graphics = canvas.graphics;
//Setting macros for annotation
chartConfig.gaugeStartX = chartConfig.canvasLeft;
chartConfig.gaugeEndX = chartConfig.canvasLeft + width;
chartConfig.gaugeStartY = chartConfig.canvasTop;
chartConfig.gaugeEndY = chartConfig.canvasTop + height;
chartConfig.gaugeCenterX = chartConfig.canvasLeft + width / 2;
chartConfig.gaugeCenterY = chartConfig.canvasTop + height/2;
canvasGroup.transform(['T', canvasLeft, canvasTop]);
if (!(colorGrp = graphics.linear)) {
graphics.linear = colorGrp = paper.group('colorrange', canvasGroup);
colorGrp.trackTooltip(true);
//draw the outer rectangle
graphics.outerRect = paper.rect(canvasGroup);
}
graphics.outerRect.attr({
x: 0,
y: 0,
width: width,
height: height,
stroke: noneStr,
r: 0
});
if (gaugeType === 1 ) { // horizontal gauge; left to right;
getRectXY = function (minValue, maxValue) {
return {
x: ((minValue * width / (max - min))),
y: 0,
width: (maxValue - minValue) * width / (max - min),
height: height
};
};
angle = 270;
} else if (gaugeType === 2) { // vertical gauge; top to bottom;
getRectXY = function (minValue, maxValue) {
return {
x: 0,
y: (minValue * height / (max - min)),
width: width,
height: (maxValue - minValue) * height / (max - min)
};
};
angle = 180;
} else if (gaugeType === 3) { // horizontal linear gauge; right to left;
getRectXY = function (minValue, maxValue) {
return {
x: width - (maxValue * width / (max - min)),
y: 0,
width: (maxValue - minValue) * width / (max - min),
height: height
};
};
angle = 270;
} else { // vertical linear gauge; bottom to top;
getRectXY = function (minValue, maxValue) {
return {
x: 0,
y: height - (maxValue * height / (max - min)),
width: width,
height: (maxValue - minValue) * height / (max - min)
};
};
angle = 180;
}
if (!graphics.colorRangeElems) {
graphics.colorRangeElems = [];
}
for (i = 0, len = colorArray && colorArray.length; i < len; i += 1) {
colorObj = colorArray[i],
xyObj = getRectXY((colorObj.minvalue - min), (colorObj.maxvalue - min));
colorObj.x = xyObj.x;
colorObj.y = xyObj.y;
colorObj.width = xyObj.width;
colorObj.height = xyObj.height;
color = colorObj.code;
borderColor = convertColor(getColorCodeString(pluck(colorObj.bordercolor, color), gaugeBorderColor),
pluckNumber(colorObj.borderalpha, gaugeBorderAlpha));
shadow = showShadow ? (Math.max(colorObj.alpha, gaugeBorderAlpha) / 100) : null;
//create the shadow element
crColor = colorM.parseColorMix(colorObj.code, gaugeFillMix);
crAlpha = colorM.parseAlphaList(colorObj.alpha, crColor.length);
borderAlpha = pluckNumber(colorObj.borderAlpha, gaugeBorderAlpha);
shadowAlpha = crAlpha.split(COMMASTRING);
shadowAlpha = mathMax.apply(Math, shadowAlpha);
shadowAlpha = mathMax(gaugeBorderThickness && borderAlpha || 0, shadowAlpha);
attr = {
x: xyObj.x,
y: xyObj.y,
width: xyObj.width,
height: xyObj.height,
r: 0,
'stroke-width': gaugeBorderThickness
};
if (!(colorRangeElem = graphics.colorRangeElems[i])) {
colorRangeElem = graphics.colorRangeElems[i] = paper.rect(colorGrp);
colorRangeElem.attr(attr);
}
colorRangeElem.attr ({
stroke: borderColor,
'fill': toRaphaelColor({
FCcolor: {
color: crColor.toString(),
ratio: gaugeFillRatio,
alpha: crAlpha,
angle: angle
}
})
});
colorRangeElem.animateWith(dummyObj, animObj, attr, duration, animType);
colorRangeElem.shadow({
apply: showShadow,
opacity: (shadowAlpha / 100)
});
colorRangeElem.show();
}
while (graphics.colorRangeElems[i]) {
graphics.colorRangeElems[i].shadow(false);
graphics.colorRangeElems[i].hide();
i++;
}
if (trendArray) {
//iapi._configueTrendPoints ();
trendPointConfig = chartConfig.trendPointConfig;
if (!graphics.trendObjElems) {
graphics.trendObjElems = [];
}
if (!graphics.trendZoneElems) {
graphics.trendZoneElems = [];
}
if (!graphics.marker) {
graphics.marker = [];
}
for (i = 0, len = trendPointConfig.length; i < len; i += 1) {
trendObj = trendPointConfig[i];
xyObj = getRectXY((trendObj.startValue - min), (trendObj.endValue - min));
if (trendObj.isTrendZone) {
if (!(trendZoneElem = graphics.trendZoneElems[trendZoneElemsCount])) {
trendZoneElem = graphics.trendZoneElems[trendZoneElemsCount] = paper.rect({
height : xyObj.height > 0 ? xyObj.height : 0
},colorGrp);
}
trendZoneElem.attr({
fill: toRaphaelColor({
FCcolor: {
color: trendObj.color,
alpha: trendObj.alpha
}
})
});
trendZoneElem.animateWith(dummyObj, animObj, {
x: xyObj.x,
y: xyObj.y,
width: xyObj.width > 0 ? xyObj.width : 0,
height: xyObj.height > 0 ? xyObj.height : 0,
r: 0,
'stroke-width': 0
}, duration, animType)
.tooltip(trendObj.tooltext);
trendZoneElem.show();
trendZoneElemsCount++;
}
else {
if (!(trendObjElem = graphics.trendObjElems[trendObjElemsCount])) {
trendObjElem = graphics.trendObjElems[trendObjElemsCount] = paper.path(colorGrp);
}
trendObjElem.attr({
stroke: convertColor(trendObj.color, trendObj.alpha),
'stroke-dasharray': trendObj.dashStyle,
'stroke-width': trendObj.thickness
});
trendObjElem.animateWith(dummyObj, animObj, {
path : [M, xyObj.x, xyObj.y, L, xyObj.x, (xyObj.y + xyObj.height)]
}, duration, animType)
.tooltip(trendObj.tooltext);
trendObjElem.show();
trendObjElemsCount++;
}
if (trendObj.useMarker) {
if (trendObj.showOnTop) {
orient = POSITION_BOTTOM;
y = 0;
} else {
orient = POSITION_TOP;
y = height;
}
startAngle = pointOrientation[orient] * 90;
if (!(marker = graphics.marker[markerCount])) {
graphics.marker[markerCount] = marker = paper.polypath(colorGrp);
}
marker.attr({
fill: trendObj.markerColor,
stroke: trendObj.markerBorderColor
});
marker.animateWith(dummyObj, animObj, {
polypath : [3, xyObj.x, y, trendObj.markerRadius, startAngle, 0],
'stroke-width': 1
}, duration, animType)
.shadow({
apply: showShadow
})
.tooltip(trendObj.tooltext);
marker.show();
markerCount++;
}
}
}
// Hiding the unused graphic trendpoint elements if it exists
if (trendObjElems = graphics.trendObjElems) {
while (trendObjElems[trendObjElemsCount]) {
trendObjElems[trendObjElemsCount].hide();
trendObjElemsCount ++;
}
}
if (trendZoneElems = graphics.trendZoneElems) {
while (trendZoneElems[trendZoneElemsCount]) {
trendZoneElems[trendZoneElemsCount].hide();
trendZoneElemsCount ++;
}
}
if (marker = graphics.marker) {
while (marker[markerCount]) {
marker[markerCount].hide();
marker[markerCount].shadow(false);
markerCount ++;
}
}
},
_configueTrendPoints : function () {
var iapi = this,
jsonData = iapi.jsonData,
config = iapi.config,
style = config.style,
trendArray = jsonData.trendpoints && jsonData.trendpoints.point,
trendPointObj,
i,
chartComponents = iapi.components,
scale = chartComponents.scale,
scaleConfig = scale.config,
axisRange = scaleConfig.axisRange,
max = axisRange.max,
min = axisRange.min,
scaleFactor = scaleConfig.scaleFactor || 1,
colorM = chartComponents.colorManager,
startValue,
endValue,
isTrendZone,
trendPointConfig = config.trendPointConfig = [],
chartAttrs = jsonData.chart,
length = trendArray.length;
style.trendStyle = {
fontFamily: style.outCanfontFamily,
color: style.outCancolor,
fontSize: style.outCanfontSize
};
for (i = 0; i < length; i ++) {
trendPointObj = trendArray[i];
startValue = pluckNumber(trendPointObj.startvalue, trendPointObj.value);
endValue = pluckNumber(trendPointObj.endvalue, startValue);
isTrendZone = startValue !== endValue;
if (startValue <= max && startValue >= min && endValue <= max && endValue >= min) {
trendPointConfig.push({
startValue : startValue,
endValue : endValue,
tooltext : getValidValue(parseUnsafeString(trendPointObj.markertooltext)),
displayValue : getValidValue(parseUnsafeString(trendPointObj.displayvalue),
isTrendZone ? BLANKSTRING : chartComponents.numberFormatter.scale(startValue)),
showOnTop: pluckNumber(trendPointObj.showontop, chartAttrs.ticksbelowgauge, 1),
color: pluck(trendPointObj.color, colorM.getColor('trendLightColor')),
textColor: trendPointObj.color,
alpha: pluckNumber(trendPointObj.alpha, 99),
thickness: pluckNumber(trendPointObj.thickness, 1),
dashStyle: Number(trendPointObj.dashed) ? getDashStyle(trendPointObj.dashlen || 2,
trendPointObj.dashgap || 2, trendPointObj.thickness || 1) : BLANK,
//Marker properties
useMarker: pluckNumber(trendPointObj.usemarker, 0),
markerColor: convertColor(pluck(trendPointObj.markercolor,
trendPointObj.color, colorM.getColor('trendLightColor')), 100),
markerBorderColor: convertColor(pluck(trendPointObj.markerbordercolor,
trendPointObj.bordercolor, colorM.getColor('trendDarkColor')), 100),
markerRadius: pluckNumber(pluckNumber(trendPointObj.markerradius) *
scaleFactor, 5),
markerToolText: getFirstValue(trendPointObj.markertooltext),
trendValueDistance : pluckNumber(pluckNumber(trendPointObj.trendvaluedistance) *
scaleFactor, axisRange.tickInterval),
isTrendZone : isTrendZone
});
}
}
// Sorting the trend point array because the labels have to
// be space managed in case of hlineargauge.
lib.stableSort && lib.stableSort(config.trendPointConfig, function (a, b) {
return (a.startValue - b.startValue);
});
},
_createDatasets : function () {
var iapi = this,
components = iapi.components,
dataObj = iapi.jsonData,
pointers = dataObj.pointers,
datasetStore,
datasetObj,
defaultSeriesType = iapi.defaultDatasetType,
dsType,
prevPointers,
currPointers,
DsClass;
datasetStore = components.dataset || (components.dataset = []);
dsType = defaultSeriesType;
if (dsType) {
/// get the DsClass
DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
if (DsClass) {
if (!datasetStore[0]) {
datasetObj = new DsClass();
datasetStore.push(datasetObj);
datasetObj.chart = iapi;
datasetObj.init(pointers);
}
else {
prevPointers = datasetStore[0].pointerArr &&
datasetStore[0].pointerArr.pointer && datasetStore[0].pointerArr.pointer.length;
currPointers = (pointers && pointers.pointer && pointers.pointer.length) || 0;
if (prevPointers > currPointers) {
datasetStore[0].removeData(prevPointers - currPointers);
}
datasetStore[0].pointerArr = pointers;
datasetStore[0].configure();
}
}
}
},
_getData : function (index, callback) {
var iapi = this,
components = iapi.components,
dataset = components.dataset,
data,
dataObj,
list = iapi.getJobList(),
_helperFn = function () {
dataObj = dataset[0].components.data;
if (dataObj && dataObj[--index]) {
data = dataObj[index].config;
return pluckNumber(data.setValue, data.itemValue);
}
else {
return null;
}
};
if (dataset) {
if (typeof callback === 'function') {
list.eiMethods.push(schedular.addJob(function () {
callback(_helperFn());
}, iapi, [], priorityList.postRender));
}
else {
return _helperFn();
}
}
},
_setData : function (dialIndex, value) {
var stream = 'value=',
i;
if (dialIndex === UNDEFINED || value === UNDEFINED) {
return;
}
for (i = 1; i < Number(dialIndex); i++) {
stream += COMMASTRING;
}
if (value.toString) {
stream += value.toString();
}
if (stream) {
this.feedData(stream);
}
},
_getDataForId: function (id, callback) {
var iapi = this,
dataset = iapi.components.dataset[0],
idMap = dataset.idMap,
list = iapi.getJobList();
if (typeof callback === 'function') {
list.eiMethods.push(schedular.addJob(function () {
callback((idMap && idMap[id] && idMap[id].config.itemValue) || null);
}, iapi, [], priorityList.postRender));
}
else {
return (idMap && idMap[id] && idMap[id].config.itemValue) || null;
}
},
_setDataForId : function (id, value) {
var iapi = this,
dataset = iapi.components.dataset[0],
idMap = dataset.idMap;
return (idMap && idMap[id] && iapi._setData(idMap[id].index + 1, value));
}
}, chartAPI.axisgaugebase);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-hbullet', function () {
var global = this,
lib = global.hcLib,
win = global.window,
pluck = lib.pluck,
pluckNumber = lib.pluckNumber,
parseUnsafeString = lib.parseUnsafeString,
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
chartAPI = lib.chartAPI,
BLANK = lib.BLANKSTRING,
BLANKSTRING = BLANK,
GUTTER_PADDING = 2,
preDefStr = lib.preDefStr,
POSITION_START = preDefStr.POSITION_START,
POSITION_END = preDefStr.POSITION_END,
POSITION_BOTTOM = preDefStr.POSITION_BOTTOM,
POSITION_MIDDLE = preDefStr.POSITION_MIDDLE,
math = Math,
mathCeil = math.ceil,
mathMax = math.max;
chartAPI('hbullet', {
friendlyName: 'Horizontal Bullet Gauge',
creditLabel: creditLabel,
defaultSeriesType: 'hbullet',
gaugeType: 1,
standaloneInit: true,
//isHorizontal: true,
defaultCaptionPadding : 5,
rendererId: 'hbullet',
isHorizontal: true,
isAxisOpposite : true,
rtManageSpace: true,
_RTmanageSpace: function() {
var iapi = this,
config = iapi.config,
components = iapi.components,
scale = components.scale,
dataset = components.dataset[0],
diff,
currentLabelSpace;
currentLabelSpace = dataset._manageSpaceHorizontal(config.oriCanvasWidth * 0.7);
diff = currentLabelSpace.right - config.labelSpace.right;
iapi._allocateSpace({
right: diff
});
scale.setAxisDimention({
axisLength: config.canvasWidth
});
config.labelSpace = currentLabelSpace;
},
_spaceManager: function () {
var availableWidth,
availableHeight,
iapi = this,
config = iapi.config,
components = iapi.components,
dataset = components.dataset[0],
scale = components.scale,
is3d = iapi.is3D,
chartAttrs = iapi.jsonData.chart,
showBorder = pluckNumber (chartAttrs.showborder, is3d ? 0 : 1),
chartBorderHorizontal,
chartBorderVertical,
minChartWidth = config.minChartWidth,
minChartHeight = config.minChartHeight,
chartBorderWidth =
config.borderWidth = showBorder ? pluckNumber (chartAttrs.borderthickness, 1) : 0;
//****** Manage space
if ((config.canvasWidth - 2 * chartBorderWidth) < minChartWidth ) {
chartBorderVertical = (config.canvasWidth - minChartWidth) / 2;
}
if ((config.canvasHeight - 2 * chartBorderWidth) < minChartHeight ) {
chartBorderHorizontal = (config.canvasHeight - minChartHeight) / 2;
}
iapi._allocateSpace ( {
top : chartBorderHorizontal || chartBorderWidth,
bottom : chartBorderHorizontal || chartBorderWidth,
left : chartBorderVertical || chartBorderWidth,
right : chartBorderVertical || chartBorderWidth
});
availableWidth = config.canvasWidth * 0.7;
iapi._allocateSpace(scale.placeAxis(config.availableHeight));
iapi._allocateSpace(iapi._manageActionBarSpace &&
iapi._manageActionBarSpace(config.availableHeight * 0.225) || {});
config.oriCanvasWidth = config.canvasWidth;
config.labelSpace = dataset._manageSpaceHorizontal(availableWidth);
dataset._manageSpace && iapi._allocateSpace(config.labelSpace);
availableHeight = config.canvasHeight * 0.225;
// a space manager that manages the space for the tools as well as the captions.
iapi._manageChartMenuBar(availableHeight);
config.oriCanvasWidth -= mathMax(components.subCaption.config.width || 0,
components.caption.config.width || 0);
availableHeight = config.canvasHeight * 0.325;
},
_manageCaptionSpacing: function () {
var iapi = this,
chartConfig = iapi.config,
components = iapi.components,
//chartGraphics = iapi.graphics,
caption = components.caption,
subCaption = components.subCaption,
captionConfig = caption.config,
subCaptionConfig = subCaption.config,
captionComponents = caption.components,
subCaptionComponents = subCaption.components,
chartAttrs = iapi.jsonData.chart,
SmartLabel = iapi.linkedItems.smartLabel,
titleText = parseUnsafeString(chartAttrs.caption),
subTitleText = parseUnsafeString(chartAttrs.subcaption),
captionPadding = pluckNumber(chartAttrs.captionpadding, 2),
height = chartConfig.height,
width = chartConfig.width,
captionLineHeight = 0,
subCaptionLineHeight = 0,
captionHeight = 0,
captionWidth = 0,
// subCaptionHeight = 0,
// subCaptionWidth = 0,
allowedHeight = height * 0.7,
allowedWidth = width * 0.7,
dimensions = {},
maxCaptionWidth,
captionObj,
subCaptionObj,
capStyle,
subCapStyle;
// text below 3px is not properly visible
if (allowedHeight > 3) {
captionConfig.captionPadding = subCaptionConfig.captionPadding = captionPadding;
if (titleText !== BLANKSTRING) { //calculatethe single line's height
capStyle = captionConfig.style;
captionLineHeight = captionConfig.captionLineHeight =
mathCeil(parseFloat(pluck(capStyle.fontHeight, capStyle.lineHeight), 10), 12);
// captionFontSize = subCaptionConfig.captionLineHeight =
// pluckNumber(parseInt(capStyle.fontSize, 10), 10);
}
if (subTitleText !== BLANKSTRING) {
subCapStyle = subCaptionConfig.style;
subCaptionLineHeight = mathCeil(parseInt(pluck(subCapStyle.lineHeight,
subCapStyle.fontHeight), 10), 12);
// subCaptionFontSize = pluckNumber(parseInt(subCapStyle.fontSize, 10), 10);
}
if (captionLineHeight > 0 || subCaptionLineHeight > 0) {
SmartLabel.useEllipsesOnOverflow(chartConfig.useEllipsesWhenOverflow);
SmartLabel.setStyle(capStyle);
captionObj = SmartLabel.getSmartText(titleText, allowedWidth, height);
// Forcefully increase width to give a gutter in caption and sub-caption
if (captionObj.width > 0) {
captionObj.width += GUTTER_PADDING;
captionHeight = captionObj.height;
}
SmartLabel.setStyle(subCapStyle);
subCaptionObj = SmartLabel.getSmartText(subTitleText, allowedWidth, height - captionHeight);
// Force fully increase width to give a gutter in caption and subCaption
if (subCaptionObj.width > 0) {
subCaptionObj.width += GUTTER_PADDING;
}
captionConfig.captionSubCaptionGap = captionObj.height + 0 +
(subCaptionLineHeight * 0.2);
maxCaptionWidth = Math.max(captionObj.width, subCaptionObj.width);
// Replace the caption and subCaption text with the new wrapped text
captionComponents.text = captionObj.text;
captionConfig.height = captionHeight = captionObj.height;
captionConfig.width = captionWidth = captionObj.width;
captionConfig.tooltext && (captionComponents.originalText = captionObj.tooltext);
subCaptionComponents.text = subCaptionObj.text;
subCaptionConfig.height = captionHeight = subCaptionObj.height;
subCaptionConfig.width = captionWidth = subCaptionObj.width;
subCaptionConfig.tooltext && (captionComponents.originalText = subCaptionObj.tooltext);
maxCaptionWidth = Math.max(captionObj.width, subCaptionObj.width);
//Add caption padding, if either caption or sub-caption is to be shown
if (maxCaptionWidth > 0) {
maxCaptionWidth = maxCaptionWidth + captionPadding;
}
captionConfig.maxCaptionWidth = subCaptionConfig.maxCaptionWidth = maxCaptionWidth;
// totalHeight = totalHeight || canvasBorderThickness;
if (captionConfig.isOnLeft) {
dimensions.left = maxCaptionWidth;
}
else {
dimensions.right = maxCaptionWidth;
}
}
}
if (captionConfig.isOnLeft) {
captionConfig.align = subCaptionConfig.align = POSITION_END;
} else {
captionConfig.align = subCaptionConfig.align = POSITION_START;
}
return dimensions;
},
_manageCaptionPosition: function () {
var iapi = this,
chartConfig = iapi.config,
components = iapi.components,
caption = components.caption,
subCaption = components.subCaption,
captionConfig = caption.config,
subCaptionConfig = subCaption.config,
captionPosition = captionConfig.captionPosition,
maxWidth = mathMax(captionConfig.width, subCaptionConfig.width),
borderWidth = chartConfig.borderWidth || 0,
// height = chartConfig.height,
captionSubCaptionGap = captionConfig.captionSubCaptionGap;
switch (captionPosition) {
case POSITION_MIDDLE:
captionConfig.y = (chartConfig.canvasTop + chartConfig.canvasHeight) * 0.5;
break;
case POSITION_BOTTOM:
captionConfig.y = chartConfig.canvasBottom - (captionConfig.height + subCaptionConfig.height);
break;
default: // We put it on top by default
captionConfig.y = chartConfig.canvasTop;
break;
}
subCaptionConfig.y = captionConfig.y + captionSubCaptionGap;
if (captionConfig.isOnLeft) {
// captionConfig.align = subCaptionConfig.align = POSITION_END;
captionConfig.x = subCaptionConfig.x = chartConfig.marginLeft + maxWidth + borderWidth;
} else {
// captionConfig.align = subCaptionConfig.align = POSITION_START;
captionConfig.x = subCaptionConfig.x = chartConfig.width -
chartConfig.marginRight - maxWidth - borderWidth;
}
},
/*
* Returns the postion for the caption placement.
* @return extra spaces.
*/
_fetchCaptionPos: function () {
var extraSpace,
iapi = this,
components = iapi.components,
caption = components.caption,
captionConfig = caption.config;
// check if even after placing the caption
// space available on right.
//left aligned.
if (captionConfig.align === POSITION_END) {
extraSpace = 0;
}
// right aligned
else {
extraSpace = -1;
}
return extraSpace;
}
}, chartAPI.vbullet);
}]);
FusionCharts.register('module', ['private', 'modules.renderer.js-thermometer', function() {
var global = this,
lib = global.hcLib,
chartAPI = lib.chartAPI,
win = global.window,
COMPONENT = 'component',
pluck = lib.pluck,
pluckNumber = lib.pluckNumber,
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname),
UNDEFINED,
preDefStr = lib.preDefStr,
HUNDREDSTRING = lib.HUNDREDSTRING,
convertColor = lib.graphics.convertColor,
gaugeFillColorStr = preDefStr.gaugeFillColorStr,
gaugeBorderColorStr = preDefStr.gaugeBorderColorStr,
getLightColor = lib.graphics.getLightColor,
DATASET = 'dataset',
extend = function(a, b) {
var n;
if (!a) {
a = {};
}
for (n in b) {
a[n] = b[n];
}
return a;
},
defined = function(obj) {
return obj !== UNDEFINED && obj !== null;
},
extend2 = lib.extend2;
chartAPI('thermometer', {
showRTvalue: false,
canvasPadding: false,
friendlyName: 'Horizontal Linear Gauge',
creditLabel: creditLabel,
defaultDatasetType: 'thermometer',
defaultPaletteOptions: extend(extend2({}, lib.defaultGaugePaletteOptions), {
gaugeBorderColor: ['545454', '60634E', '415D6F', '845001', '68001B'],
gaugeFillColor: ['999999', 'ADB68F', 'A2C4C8', 'FDB548', 'FF7CA0'],
periodColor: ['EEEEEE', 'ECEEE6', 'E6ECF0', 'FFF4E6', 'FFF2F5']
}),
standaloneInit: true,
isHorizontal: false,
isAxisOpposite: true,
hasLegend: false,
hasCanvas: false,
drawPlotlines: false,
drawPlotBands: false,
isAxisReverse: false,
isRealTime: true,
applicableDSList: {
'thermometer': true
},
_getData: function() {
var iapi = this,
components = iapi.components,
dataset = components.dataset;
if (dataset && dataset[0]) {
return dataset[0].config.value;
}
},
// todo: this function need to be removed once the flow is proper
_parseSpecialConfig: function() {
var iapi = this,
chartConfig = iapi.config,
dataObj = iapi.jsonData,
chartOptions = dataObj.chart,
apiCpmponents = iapi.components,
numberFormatter = apiCpmponents.numberFormatter,
colorM = apiCpmponents.colorManager,
gaugeBorderAlpha;
chartConfig.use3DLighting = pluckNumber(chartOptions.use3dlighting, 1);
chartConfig.thmOriginX = pluckNumber(chartOptions.thmoriginx, chartOptions.gaugeoriginx);
chartConfig.thmOriginY = pluckNumber(chartOptions.thmoriginy, chartOptions.gaugeoriginy);
chartConfig.thmBulbRadius =
pluckNumber(numberFormatter.getCleanValue(chartOptions.thmbulbradius, true));
chartConfig.thmHeight = pluckNumber(numberFormatter.getCleanValue(pluckNumber(chartOptions.thmheight,
chartOptions.gaugeheight), true));
chartConfig.origW = pluckNumber(chartOptions.origw);
chartConfig.origH = pluckNumber(chartOptions.origh);
// set the falg whether the measurements are defined by user or not
chartConfig.xDefined = defined(chartConfig.thmOriginX);
chartConfig.yDefined = defined(chartConfig.thmOriginY);
chartConfig.rDefined = defined(chartConfig.thmBulbRadius);
chartConfig.hDefined = defined(chartConfig.thmHeight);
chartConfig.gaugeFillColor = pluck(chartOptions.gaugefillcolor, chartOptions.thmfillcolor,
colorM.getColor(gaugeFillColorStr));
chartConfig.gaugeFillAlpha = pluckNumber(chartOptions.gaugefillalpha,
chartOptions.thmfillalpha, HUNDREDSTRING);
//Gauge Border properties
chartConfig.showGaugeBorder = pluckNumber(chartOptions.showgaugeborder, 1);
gaugeBorderAlpha = chartConfig.showGaugeBorder ? pluckNumber(chartOptions.gaugeborderalpha, 40) : 0;
// We are using 40 for default alpha of Thermometer Gauge Border
chartConfig.gaugeBorderColor = convertColor(pluck(chartOptions.gaugebordercolor,
colorM.getColor(gaugeBorderColorStr)), gaugeBorderAlpha);
chartConfig.gaugeBorderThickness = pluckNumber(chartOptions.gaugeborderthickness, 1);
// Thermometer Glass color
chartConfig.gaugeContainerColor = pluck(chartOptions.thmglasscolor,
getLightColor(chartConfig.gaugeFillColor, 30));
},
_createDatasets: function() {
var iapi = this,
components = iapi.components,
dataObj = iapi.jsonData,
value = dataObj.value,
datasetStore,
datasetObj,
defaultSeriesType = iapi.defaultDatasetType,
dsType,
DsClass,
dymmyDS = {
data: [{
value: value
}]
};
datasetStore = components.dataset || (components.dataset = []);
dsType = defaultSeriesType;
if (dsType) {
/// get the DsClass
DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
if (DsClass) {
if (!datasetStore[0]) {
// create the dataset Object
datasetObj = new DsClass();
datasetStore.push(datasetObj);
datasetObj.chart = iapi;
datasetObj.init(dymmyDS);
} else {
datasetStore[0].setValue(dymmyDS && dymmyDS.data && dymmyDS.data[0]);
datasetStore[0].configure();
}
}
}
}
}, chartAPI.axisgaugebase);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-cylinder', function () {
var global = this,
lib = global.hcLib,
HUNDREDSTRING = lib.HUNDREDSTRING,
//add the tools thats are requared
pluck = lib.pluck,
pluckNumber = lib.pluckNumber,
extend2 = lib.extend2,
getLightColor = lib.graphics.getLightColor,
convertColor = lib.graphics.convertColor,
chartAPI = lib.chartAPI,
preDefStr = lib.preDefStr,
colorStrings = preDefStr.colors,
COLOR_FFFFFF = colorStrings.FFFFFF,
gaugeFillColorStr = preDefStr.gaugeFillColorStr,
gaugeBorderColorStr = preDefStr.gaugeBorderColorStr,
extend = function (a, b) {
var n;
if (!a) {
a = {};
}
for (n in b) {
a[n] = b[n];
}
return a;
},
UNDEFINED,
defined = function (obj) {
return obj !== UNDEFINED && obj !== null;
};
chartAPI('cylinder', {
defaultDatasetType: 'cylinder',
applicableDSList : {'cylinder' : true},
defaultPaletteOptions : extend(extend2({}, lib.defaultGaugePaletteOptions), {
gaugeBorderColor: ['545454', '60634E', '415D6F', '845001', '68001B'],
gaugeFillColor: ['CCCCCC', 'ADB68F', 'E1F5FF', 'FDB548', 'FF7CA0'],
periodColor: ['EEEEEE', 'ECEEE6', 'E6ECF0', 'FFF4E6', 'FFF2F5']
}),
glasscolor: COLOR_FFFFFF,
// todo: this function need to be removed once the flow is proper
_parseSpecialConfig: function () {
var iapi = this,
chartConfig = iapi.config,
dataObj = iapi.jsonData,
chartOptions = dataObj.chart,
apiCpmponents = iapi.components,
numberFormatter = apiCpmponents.numberFormatter,
colorM = apiCpmponents.colorManager,
gaugeBorderAlpha;
chartConfig.use3DLighting = pluckNumber(chartOptions.use3dlighting, 1);
chartConfig.gaugeOriginX = pluckNumber(chartOptions.thmoriginx, chartOptions.cyloriginx,
chartOptions.gaugeoriginx);
chartConfig.gaugeOriginY = pluckNumber(chartOptions.thmoriginy, chartOptions.cyloriginy,
chartOptions.gaugeoriginy);
chartConfig.gaugeRadius = pluckNumber(numberFormatter.getCleanValue(pluckNumber(chartOptions.thmbulbradius,
chartOptions.cylradius, chartOptions.gaugeradius), true));
chartConfig.gaugeHeight = pluckNumber(numberFormatter.getCleanValue(pluckNumber(chartOptions.thmheight,
chartOptions.cylheight, chartOptions.gaugeheight), true));
chartConfig.origW = pluckNumber(chartOptions.origw);
chartConfig.origH = pluckNumber(chartOptions.origh);
// set the falg whether the measurements are defined by user or not
chartConfig.xDefined = defined(chartConfig.gaugeOriginX);
chartConfig.yDefined = defined(chartConfig.gaugeOriginY);
chartConfig.rDefined = defined(chartConfig.gaugeRadius);
chartConfig.hDefined = defined(chartConfig.gaugeHeight);
chartConfig.gaugeFillColor = pluck(chartOptions.gaugefillcolor, chartOptions.cylfillcolor,
colorM.getColor(gaugeFillColorStr));
chartConfig.gaugeFillAlpha = pluckNumber(chartOptions.gaugefillalpha,
chartOptions.cylfillalpha, HUNDREDSTRING);
chartConfig.gaugeYScale = pluckNumber(chartOptions.cylyscale, chartOptions.gaugeyscale, 30);
if (chartConfig.gaugeYScale > 50 || chartConfig.gaugeYScale < 0){
chartConfig.gaugeYScale = 30;
}
chartConfig.gaugeYScale = chartConfig.gaugeYScale / 100;
//Gauge Border properties
chartConfig.showGaugeBorder = pluckNumber(chartOptions.showgaugeborder, 1);
gaugeBorderAlpha = chartConfig.showGaugeBorder ? pluckNumber(chartOptions.gaugeborderalpha,40) : 0;
// We are using 40 for default alpha of cylender Gauge Border
chartConfig.gaugeBorderColor = convertColor(pluck(chartOptions.gaugebordercolor,
colorM.getColor(gaugeBorderColorStr)), gaugeBorderAlpha);
chartConfig.gaugeBorderThickness = pluckNumber(chartOptions.gaugeborderthickness, 1);
// Thermometer Glass color
chartConfig.gaugeContainerColor = pluck(chartOptions.cylglasscolor,
getLightColor(chartConfig.gaugeFillColor, 30));
}
}, chartAPI.thermometer);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-angulargauge', function () {
var global = this,
lib = global.hcLib,
pluck = lib.pluck,
UNDEFINED,
getValidValue = lib.getValidValue,
BLANK = lib.BLANKSTRING,
COMPONENT = 'component',
DATASET = 'dataset',
preDefStr = lib.preDefStr,
animationObjStr = preDefStr.animationObjStr,
configStr = preDefStr.configStr,
pluckNumber = lib.pluckNumber,
win = global.window,
convertColor = lib.graphics.convertColor,
COMMASTRING = lib.COMMASTRING,
math = Math,
mathMax = math.max,
mathMin = math.min,
mathPI = math.PI,
deg2rad = mathPI / 180,
toRaphaelColor = lib.toRaphaelColor,
AXIS = 'axis',
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
chartAPI = lib.chartAPI,
extend2 = lib.extend2,
pluckFontSize = lib.pluckFontSize, // To get the valid font size (filters negative values)
defined = function (obj) {
return obj !== UNDEFINED && obj !== null;
},
extend = function (a, b) {
var n;
if (!a) {
a = {};
}
for (n in b) {
a[n] = b[n];
}
return a;
};
chartAPI('angulargauge', {
friendlyName: 'Angular Gauge',
creditLabel: creditLabel,
defaultDatasetType: 'angulargauge',
standaloneInit: true,
isHorizontal: true,
isAxisOpposite : false,
isRealTime: true,
hasLegend : false,
drawPlotlines : false,
drawPlotBands : false,
isAxisReverse : false,
colorRange : true,
defaultPaletteOptions : extend(extend2({}, lib.defaultGaugePaletteOptions), {
dialColor: ['999999,ffffff,999999', 'ADB68F,F3F5DD,ADB68F', 'A2C4C8,EDFBFE,A2C4C8',
'FDB548,FFF5E8,FDB548', 'FF7CA0,FFD1DD,FF7CA0'],
dialBorderColor: ['999999', 'ADB68F', 'A2C4C8', 'FDB548', 'FF7CA0'],
pivotColor: ['999999,ffffff,999999', 'ADB68F,F3F5DD,ADB68F', 'A2C4C8,EDFBFE,A2C4C8',
'FDB548,FFF5E8,FDB548', 'FF7CA0,FFD1DD,FF7CA0'],
pivotBorderColor: ['999999', 'ADB68F', 'A2C4C8', 'FDB548', 'FF7CA0']
}),
rtParserModify : true,
applicableDSList : {'angulargauge' : true},
_spaceManager: function () {
var iapi = this,
availableWidth,
availableHeight,
config = iapi.config,
components = iapi.components,
dataSet = components.dataset[0],
scale = components.scale,
chart = dataSet.chart,
jsonData = chart.jsonData,
chartAttrs = jsonData.chart,
datasetConfig = dataSet.config,
scaleFactor = datasetConfig.scaleFactor,
yPosExtra = 0,
yNegExtra = 0,
radius = 0,
centerX = 0,
centerY = 0,
compositPivotRadius = datasetConfig.pivotRadius,
labelFontSize = config.dataLabels.style.fontSize,
displayValueLineHeight = config.dataLabels.style.lineHeight,
displayValueCount = config.displayValueCount,
chartBorderWidth = config.borderWidth,
minChartWidth = config.minChartWidth,
minChartHeight = config.minChartHeight,
radiusDeduce = 0,
gaugeSpacingObj,
innerRadiusFactor,
pivotRadius,
axisSpace,
axisLimit,
gaugeStartPos,
gaugeEndPos,
chartBorderHorizontal,
chartBorderVertical;
//****** Manage space
if ((config.canvasWidth - 2 * chartBorderWidth) < minChartWidth ) {
chartBorderVertical = (config.canvasWidth - minChartWidth) / 2;
}
if ((config.canvasHeight - 2 * chartBorderWidth) < minChartHeight ) {
chartBorderHorizontal = (config.canvasHeight - minChartHeight) / 2;
}
iapi._allocateSpace ( {
top : chartBorderHorizontal || chartBorderWidth,
bottom : chartBorderHorizontal || chartBorderWidth,
left : chartBorderVertical || chartBorderWidth,
right : chartBorderVertical || chartBorderWidth
});
// availableHeight = config.canvasHeight * 0.225;
// iapi._allocateSpace(iapi._manageCaptionSpacing(availableHeight));
if (config.autoScale) {
config.scaleFactor = scaleFactor = iapi._getScaleFactor(datasetConfig.origW,
datasetConfig.origH, config.width, config.height);
}
else {
config.scaleFactor = scaleFactor = 1;
}
labelFontSize = labelFontSize.replace(/px/i, BLANK);
displayValueLineHeight = displayValueLineHeight.replace(/px/i, BLANK);
if (/^\d+\%$/.test(datasetConfig.gaugeinnerradius)) {
innerRadiusFactor = parseInt(datasetConfig.gaugeinnerradius, 10) / 100;
}
else {
innerRadiusFactor = 0.7;
}
pivotRadius = compositPivotRadius = pluckNumber(getValidValue(chartAttrs.pivotradius) * scaleFactor, 5);
datasetConfig.pivotRadius = pivotRadius;
compositPivotRadius = Math.max(compositPivotRadius, datasetConfig.rearExtension * scaleFactor);
datasetConfig.compositPivotRadius = compositPivotRadius;
yPosExtra = displayValueCount * displayValueLineHeight + 2 + pivotRadius;
if (!datasetConfig.valueBelowPivot) {
yNegExtra = yPosExtra;
yPosExtra = 0;
}
datasetConfig.gaugeOuterRadius = pluckNumber(Math.abs(getValidValue(chartAttrs.gaugeouterradius) *
scaleFactor));
//Asume gauge inner radius to be a default of 70% of gauge outer radius
datasetConfig.gaugeInnerRadius = pluckNumber(Math.abs(getValidValue(chartAttrs.gaugeinnerradius) *
scaleFactor), datasetConfig.gaugeOuterRadius * innerRadiusFactor);
availableWidth = config.canvasWidth * 0.7;
availableHeight = config.canvasHeight * 0.7;
// TODO space management to be done
//iapi._allocateSpace(scale.placeAxis(mathMin(availableWidth, availableHeight)));
axisSpace = scale.placeAxis(mathMin(availableWidth, availableHeight));
// radiusDeduce = mathMax(axisSpace.left, axisSpace.right, axisSpace.top, axisSpace.bottom);
availableHeight = config.canvasHeight * 0.7;
iapi._manageChartMenuBar(availableHeight);
gaugeSpacingObj = iapi._angularGaugeSpaceManager(datasetConfig.gaugeStartAngle, datasetConfig.gaugeEndAngle,
config.canvasWidth, config.canvasHeight, datasetConfig.gaugeOuterRadius,
pluckNumber((getValidValue(chartAttrs.gaugeoriginx) * scaleFactor) - config.canvasLeft),
pluckNumber((getValidValue(chartAttrs.gaugeoriginy) * scaleFactor) - config.canvasTop),
Math.max(compositPivotRadius, labelFontSize),
yPosExtra, yNegExtra);
radius = gaugeSpacingObj.radius = pluckNumber(gaugeSpacingObj.radius, gaugeSpacingObj.maxRadius);
datasetConfig.gaugeOriginX = gaugeSpacingObj.centerX + config.canvasLeft;
datasetConfig.gaugeOriginY = gaugeSpacingObj.centerY + config.canvasTop;
centerX = gaugeSpacingObj.centerX;
centerY = gaugeSpacingObj.centerY;
if (axisSpace.left < axisSpace.top) {
if ((centerX - axisSpace.left) >= (radius - axisSpace.left) &&
(centerY - axisSpace.top) >= (radius - axisSpace.left)) {
radiusDeduce = axisSpace.left;
} else {
radiusDeduce = axisSpace.top;
}
} else {
if ((centerX - axisSpace.left) >= (radius - axisSpace.top) &&
(centerY - axisSpace.top) >= (radius - axisSpace.top)) {
radiusDeduce = axisSpace.top;
} else {
radiusDeduce = axisSpace.left;
}
}
radiusDeduce += scale.config.polarPadding;
if (!datasetConfig.gaugeOuterRadius) {
datasetConfig.gaugeOuterRadius = gaugeSpacingObj.radius;
datasetConfig.gaugeOuterRadius -= radiusDeduce;
}
if (datasetConfig.gaugeInnerRadius === undefined) {
datasetConfig.gaugeInnerRadius = datasetConfig.gaugeOuterRadius * innerRadiusFactor;
}
scale.setAxisConfig({
centerX : datasetConfig.gaugeOriginX,
centerY : datasetConfig.gaugeOriginY,
radius : gaugeSpacingObj.radius || datasetConfig.gaugeOuterRadius,
gaugeOuterRadius : datasetConfig.gaugeOuterRadius,
gaugeInnerRadius : datasetConfig.gaugeInnerRadius,
scaleFactor : scaleFactor
});
// For annotations
axisLimit = scale.getLimit();
gaugeStartPos = scale.getPixel(axisLimit.min);
gaugeEndPos = scale.getPixel(axisLimit.max);
config.gaugeStartX = config.canvasLeft;
config.gaugeStartY = config.canvasTop;
config.gaugeEndX = config.canvasRight;
config.gaugeEndY = config.canvasBottom;
config.gaugeCenterX = datasetConfig.gaugeOriginX;
config.gaugeCenterY = datasetConfig.gaugeOriginY;
config.gaugeStartAngle = datasetConfig.gaugeStartAngle/deg2rad;
config.gaugeEndAngle = datasetConfig.gaugeEndAngle/deg2rad;
},
_createAxes : function() {
var iapi = this,
components = iapi.components,
scale,
PolarGaugeAxis = FusionCharts.register(COMPONENT, [AXIS, 'polarGauge']);
components.scale = scale = new PolarGaugeAxis();
scale.chart = iapi;
scale.init();
},
_feedAxesRawData : function() {
var iapi = this,
components = iapi.components,
colorM = components.colorManager,
dataObj = iapi.jsonData,
chartAttrs = dataObj.chart,
scale,
scaleConf,
chartPaletteStr = lib.chartPaletteStr,
palleteString = chartPaletteStr.chart2D,
isAxisOpposite = pluckNumber(chartAttrs.axisontop, chartAttrs.axisonleft, (chartAttrs.
ticksbelowgauge !== undefined ? !chartAttrs.ticksbelowgauge : undefined), iapi.isAxisOpposite),
isAxisReverse = pluckNumber(chartAttrs.reverseaxis, iapi.isAxisReverse);
scaleConf = {
outCanfontFamily: pluck(chartAttrs.outcnvbasefont, chartAttrs.basefont, 'Verdana,sans'),
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,
divLineColor: pluck(chartAttrs.vdivlinecolor, colorM.getColor(palleteString.divLineColor)),
divLineAlpha: pluck(chartAttrs.vdivlinealpha, colorM.getColor('divLineAlpha')),
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('altVGridColor')),
alternateGridAlpha: pluck(chartAttrs.alternatevgridalpha, colorM.getColor('altVGridAlpha')),
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.lowerlimit,
axisMaxValue: chartAttrs.upperlimit,
setAdaptiveMin: chartAttrs.setadaptivemin,
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),
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, '#000000'),
// Tick properties
majorTMNumber : chartAttrs.majortmnumber,
majorTMColor : chartAttrs.majortmcolor,
majorTMAlpha : chartAttrs.majortmalpha,
majorTMHeight : chartAttrs.majortmheight,
tickValueStep : chartAttrs.tickvaluestep,
showTickMarks : chartAttrs.showtickmarks,
connectTickMarks : chartAttrs.connecttickmarks,
showTickValues : chartAttrs.showtickvalues,
majorTMThickness : chartAttrs.majortmthickness,
upperlimit : components.numberFormatter.getCleanValue(chartAttrs.upperlimit),
lowerlimit : components.numberFormatter.getCleanValue(chartAttrs.lowerlimit),
reverseScale : chartAttrs.reversescale,
// Whether to display the Limits
showLimits: chartAttrs.showlimits,
//Whether to automatically adjust TM
adjustTM: chartAttrs.adjusttm,
minorTMNumber: chartAttrs.minortmnumber,
minorTMColor: chartAttrs.minortmcolor,
minorTMAlpha : chartAttrs.minortmalpha,
minorTMHeight: pluckNumber(chartAttrs.minortmheight, chartAttrs.minortmwidth),
minorTMThickness: chartAttrs.minortmthickness,
//Padding between tick mark start position and gauge
tickMarkDistance: pluckNumber(chartAttrs.tickmarkdistance, chartAttrs.tickmarkgap),
//Tick value distance
tickValueDistance: pluckNumber(chartAttrs.tickvaluedistance, chartAttrs.displayvaluedistance),
placeTicksInside: chartAttrs.placeticksinside,
placeValuesInside: chartAttrs.placevaluesinside,
upperLimitDisplay : chartAttrs.upperlimitdisplay,
lowerLimitDisplay : chartAttrs.lowerlimitdisplay,
ticksBelowGauge : chartAttrs.ticksbelowgauge,
ticksBelowGraph : chartAttrs.ticksbelowgraph,
trendValueDistance : chartAttrs.trendvaluedistance
};
scaleConf.trendPoints = dataObj.trendpoints;
scale = components.scale;
scale.setCommonConfigArr(scaleConf, !iapi.isHorizontal, isAxisReverse, isAxisOpposite);
scale.configure();
},
_drawCanvas: function () {
var iapi = this,
chartComponents = iapi.components,
dataSet = chartComponents.dataset[0],
dsConfig = dataSet.config,
graphics = dataSet.graphics || (dataSet.graphics = {}),
scale = chartComponents.scale,
colorM = chartComponents.colorManager,
scaleRange = scale.config.axisRange,
colorRangeGetter = chartComponents.colorRange,
parentContainer = iapi.graphics.datasetGroup,
labelParentContainer = iapi.graphics.datalabelsGroup,
paper = chartComponents.paper,
gaugeOuterRadius = dsConfig.gaugeOuterRadius,
gaugeInnerRadius = dsConfig.gaugeInnerRadius,
gaugeFillRatio = dsConfig.gaugeFillRatio,
gaugeBorderColor = dsConfig.gaugeBorderColor,
gaugeBorderThickness = dsConfig.gaugeBorderThickness,
gaugeBorderAlpha = dsConfig.gaugeBorderAlpha,
gaugeFillMix = dsConfig.gaugeFillMix,
x = dsConfig.gaugeOriginX,
y = dsConfig.gaugeOriginY,
startAngle = dsConfig.gaugeStartAngle,
showShadow = dsConfig.showShadow,
minValue = scaleRange.min,
maxValue = scaleRange.max,
colorRange = colorRangeGetter ? colorRangeGetter.getColorRangeArr(minValue, maxValue) : [],
animation = iapi.get(configStr, animationObjStr),
animationDuration = animation.duration,
dummyObj = animation.dummyObj,
animObj = animation.animObj,
animType = animation.animType,
i = 0, ln = colorRange.length,
colorObj, currentEndAngle,
lastAngle = startAngle,
nextAngle,
crColor, crAlpha, crRatio, shadowAlpha,
borderColor,
borderAlpha,
fcColorObj,
count = 0;
graphics.band = graphics.band || [];
if (!graphics.bandGroup) {
graphics.bandGroup = paper.group('bandGroup', parentContainer);
}
// Create the Point Group
if (!graphics.pointGroup) {
graphics.pointGroup = paper.group('pointers', labelParentContainer).translate(x, y);
} else {
graphics.pointGroup.animateWith(dummyObj, animObj, {
transform : 't' + x + COMMASTRING + y
}, animationDuration, animType);
}
//draw all color Bands
for (; i < ln; i += 1) {
colorObj = colorRange[i];
currentEndAngle = scale.getAngle(Math.min(colorObj.maxvalue, maxValue));
//Parse the color, alpha and ratio array for each color range arc.
crColor = colorM.parseColorMix(colorObj.code, gaugeFillMix);
crAlpha = colorM.parseAlphaList(colorObj.alpha, crColor.length);
crRatio = colorM.parseRatioList((gaugeInnerRadius / gaugeOuterRadius * 100) +
gaugeFillRatio, crColor.length);
borderColor = colorObj.bordercolor;
borderAlpha = pluckNumber(colorObj.borderAlpha, gaugeBorderAlpha);
//Set border propeties
//Which border color to use - between actual color and color mix specified?
if (borderColor && borderColor.indexOf('{') == -1) {
borderColor = convertColor(borderColor, borderAlpha);
}
else {
borderColor = colorM.parseColorMix(colorObj.code, pluck(borderColor, gaugeBorderColor))[0];
}
borderColor = convertColor(borderColor, borderAlpha);
//create the shadow element
shadowAlpha = crAlpha.split(COMMASTRING);
shadowAlpha = mathMax.apply(Math, shadowAlpha);
shadowAlpha = showShadow ?
mathMax(gaugeBorderThickness && borderAlpha || 0, shadowAlpha) : 0;
// If start angle > end angle then swap the two for intended
// behavior.
nextAngle = currentEndAngle;
if (lastAngle > currentEndAngle) {
lastAngle += (currentEndAngle);
currentEndAngle = lastAngle - currentEndAngle;
lastAngle = lastAngle - currentEndAngle;
}
if ( !graphics.band[i] ) {
graphics.band[i] = paper.ringpath(x, y, gaugeOuterRadius, gaugeInnerRadius, lastAngle,
currentEndAngle,graphics.bandGroup);
} else {
graphics.band[i].animateWith(dummyObj, animObj, {
ringpath : [x, y, gaugeOuterRadius, gaugeInnerRadius, lastAngle, currentEndAngle]
}, animationDuration, animType);
}
graphics.band[i].attr({
fill: toRaphaelColor({
FCcolor : {
cx: x,
cy: y,
r: gaugeOuterRadius,
gradientUnits: 'userSpaceOnUse',
color: crColor.join(),
alpha: crAlpha,
ratio: crRatio,
radialGradient: true
}
}),
'stroke-width': gaugeBorderThickness,
stroke: borderColor
})
.shadow({
apply: showShadow,
opacity : (shadowAlpha / 100)
});
lastAngle = nextAngle;
count += 1;
}
for (i = count, ln = graphics.band.length; i < ln; i += 1) {
graphics.band[i].attr({
ringpath : [0,0,0,0,0]
});
}
fcColorObj = dsConfig.isRadialGradient ? {
color: dsConfig.pivotFillColor,
alpha: dsConfig.pivotFillAlpha,
ratio: dsConfig.pivotFillRatio,
radialGradient: true,
angle: dsConfig.pivotFillAngle,
cx : 0.5,
cy : 0.5,
r : '50%'
} : {
color: dsConfig.pivotFillColor,
alpha: dsConfig.pivotFillAlpha,
ratio: dsConfig.pivotFillRatio,
radialGradient: false,
angle: dsConfig.pivotFillAngle
};
// Now draw the pivot
if (!graphics.pivot) {
graphics.pivot = paper.circle(labelParentContainer);
graphics.pivot.attr({
cx: x,
cy: y,
r: dsConfig.pivotRadius
});
} else {
graphics.pivot.animateWith(dummyObj, animObj, {
cx: x,
cy: y,
r: dsConfig.pivotRadius
}, animationDuration, animType);
}
graphics.pivot.attr({
fill: toRaphaelColor({
FCcolor: fcColorObj
}),
'stroke-width': dsConfig.pivotBorderThickness,
stroke: dsConfig.pivotBorderColor
})
.shadow({
apply: showShadow
});
},
_createDatasets : function () {
var iapi = this,
components = iapi.components,
dataObj = iapi.jsonData,
pointers = dataObj.pointers || dataObj.dials,
datasetStore,
datasetObj,
defaultSeriesType = iapi.defaultDatasetType,
prevPointers,
currPointers,
dsType,
DsClass;
if (!pointers) {
dataObj.dials = pointers = {
dial : [{
value : 0
}]
};
}
datasetStore = components.dataset || (components.dataset = []);
dsType = defaultSeriesType;
if (dsType) {
/// get the DsClass
DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
if (DsClass) {
if (!datasetStore[0]) {
datasetObj = new DsClass();
datasetStore.push(datasetObj);
datasetObj.chart = iapi;
datasetObj.init(pointers);
}
else {
prevPointers = datasetStore[0].components.data && datasetStore[0].components.data.length;
currPointers = (pointers.dial && pointers.dial.length) || 0;
if (prevPointers > currPointers) {
datasetStore[0].removeData(prevPointers - currPointers);
}
datasetStore[0].configure();
}
}
}
},
_setCategories : function () {
},
_angularGaugeSpaceManager : function (startAngle, endAngle, canvasW, canvasH,
radius, centerX, centerY, compositPivotRadius, yPosExtra, yNegExtra) {
var rediusDefined = defined(radius),
centerXDefined = defined(centerX),
centerYDefined = defined(centerY),
PI2 = Math.PI * 2,
PI = Math.PI,
PIby2 = Math.PI / 2,
PI3by2 = PI + PIby2,
calculatedRadus,
returnObj = {
radius : radius,
centerX : centerX,
centerY : centerY
},
leftX, topY, rightX, bottomY, pivotCalRequard = false,
startX, startY, endX, endY, tempRadius,
resultantEnd, range, positiveLength, negativeLength,
scale, startAbs = startAngle % PI2;
if (startAbs < 0) {
startAbs += PI2;
}
compositPivotRadius = compositPivotRadius || 0;
if (compositPivotRadius && compositPivotRadius < canvasW / 2 && compositPivotRadius < canvasH / 2) {
pivotCalRequard = true;
}
if (yPosExtra > canvasH / 2) {//max half height will be setteled
yPosExtra = canvasH / 2;
}
if (yNegExtra > canvasH / 2) {//max half height will be setteled
yNegExtra = canvasH / 2;
}
startX = Math.cos(startAngle);
startY = Math.sin(startAngle);
endX = Math.cos(endAngle);
endY = Math.sin(endAngle);
leftX = Math.min(startX, endX, 0);
rightX = Math.max(startX, endX, 0);
topY = Math.min(startY, endY, 0);
bottomY = Math.max(startY, endY, 0);
if (!rediusDefined || !centerXDefined || !centerYDefined) {
scale = endAngle - startAngle;
resultantEnd = startAbs + scale;
if (resultantEnd > PI2 || resultantEnd < 0) {
rightX = 1;
}
if (scale > 0) {
if ((startAbs < PIby2 && resultantEnd > PIby2) || resultantEnd > PI2 + PIby2) {
bottomY = 1;
}
if ((startAbs < PI && resultantEnd > PI) || resultantEnd > PI2 + PI) {
leftX = -1;
}
if ((startAbs < PI3by2 && resultantEnd > PI3by2) || resultantEnd > PI2 + PI3by2) {
topY = -1;
}
}
else {
if ((startAbs > PIby2 && resultantEnd < PIby2) || resultantEnd < - PI3by2) {
bottomY = 1;
}
if ((startAbs > PI && resultantEnd < PI) || resultantEnd < - PI) {
leftX = -1;
}
if ((startAbs > PI3by2 && resultantEnd < PI3by2) || resultantEnd < - PIby2) {
topY = -1;
}
}
//now decide the x, y and radius
if (!centerXDefined) {
range = rightX - leftX;
tempRadius = canvasW / range;
centerX = -tempRadius * leftX;
calculatedRadus = tempRadius;
if (pivotCalRequard) {
if (canvasW - centerX < compositPivotRadius) {
centerX = canvasW - compositPivotRadius;
positiveLength = canvasW - centerX;
negativeLength = -centerX;
calculatedRadus = leftX ? Math.min(positiveLength / rightX, negativeLength / leftX):
positiveLength / rightX;
}
else if (centerX < compositPivotRadius){
centerX = compositPivotRadius;
positiveLength = canvasW - centerX;
negativeLength = -centerX;
calculatedRadus = leftX ? Math.min(positiveLength / rightX, negativeLength / leftX):
positiveLength / rightX;
}
}
returnObj.centerX = centerX;
}
else if (!rediusDefined) {
positiveLength = canvasW - centerX;
negativeLength = -centerX;
calculatedRadus = leftX ? Math.min(positiveLength / rightX, negativeLength / leftX):
positiveLength / rightX;
}
if (!centerYDefined) {
range = bottomY - topY;
tempRadius = canvasH / range;
centerY = -tempRadius * topY;
if (pivotCalRequard) {
if (canvasH - centerY < compositPivotRadius) {
centerY = canvasH - compositPivotRadius;
positiveLength = canvasH - centerY;
negativeLength = -centerY;
calculatedRadus = Math.min(calculatedRadus, topY ? Math.min(positiveLength / bottomY,
negativeLength / topY) : positiveLength / bottomY);
}
else if (centerY < compositPivotRadius){
centerY = compositPivotRadius;
positiveLength = canvasH - centerY;
negativeLength = -centerY;
calculatedRadus = Math.min(calculatedRadus, topY ? Math.min(positiveLength / bottomY,
negativeLength / topY) : positiveLength / bottomY);
}
}
//yAxisExtra
if (canvasH - centerY < yPosExtra) {
centerY = canvasH - yPosExtra;
positiveLength = canvasH - centerY;
negativeLength = -centerY;
calculatedRadus = Math.min(calculatedRadus, topY ? Math.min(positiveLength / bottomY,
negativeLength / topY) : positiveLength / bottomY);
}
else if (centerY < yNegExtra){
centerY = yNegExtra;
positiveLength = canvasH - centerY;
negativeLength = -centerY;
calculatedRadus = Math.min(calculatedRadus, topY ? Math.min(positiveLength / bottomY,
negativeLength / topY) : positiveLength / bottomY);
}
calculatedRadus = Math.min(calculatedRadus, tempRadius);
returnObj.centerY = centerY;
}
else if (!rediusDefined) {
positiveLength = canvasH - centerY;
negativeLength = -centerY;
calculatedRadus = Math.min(calculatedRadus, topY ? Math.min(positiveLength / bottomY,
negativeLength / topY) : positiveLength / bottomY);
}
returnObj.maxRadius = calculatedRadus;
if (returnObj.maxRadius <= 0) {
returnObj.maxRadius = Math.min(canvasW / 2, canvasH / 2);
}
}
return returnObj;
},
_getScaleFactor : function (origW, origH, canvasWidth, canvasHeight) {
var scaleFactor;
origH = pluckNumber(origH, canvasHeight);
origW = pluckNumber(origW, canvasWidth);
if (!origH || !origW) {
scaleFactor = 1;
}
// Now, if the ratio of original width,height & stage width,height are same
else if ((origW / canvasWidth) == (origH / canvasHeight)) {
//In this case, the transformation value would be the same, as the ratio
//of transformation of width and height is same.
scaleFactor = canvasWidth / origW;
} else {
//If the transformation factors are different, we do a constrained scaling
//We get the aspect whose delta is on the lower side.
scaleFactor = Math.min((canvasWidth / origW), (canvasHeight / origH));
}
return scaleFactor;
},
_setData : chartAPI.hlineargauge,
_getData : chartAPI.hlineargauge,
_getDataForId: chartAPI.hlineargauge,
_setDataForId : chartAPI.hlineargauge
}, chartAPI.axisgaugebase);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-bulb', function () {
var global = this,
lib = global.hcLib,
win = global.window,
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
chartAPI = lib.chartAPI,
COMPONENT = 'component',
DATASET = 'dataset',
pluckNumber = lib.pluckNumber,
UNDEFINED;
chartAPI('bulb', {
showRTvalue : false,
canvasPadding : false,
friendlyName: 'Bulb Gauge',
defaultSeriesType : 'bulb',
defaultPlotShadow: 1,
standaloneInit: true,
drawAnnotations: true,
charttopmargin : 10,
chartrightmargin : 10,
chartbottommargin : 10,
chartleftmargin : 10,
realtimeEnabled: true,
isRealTime: true,
defaultDatasetType : 'bulb',
applicableDSList: {'bulb': true},
creditLabel: creditLabel,
_createDatasets : function () {
var iapi = this,
components = iapi.components,
dataObj = iapi.jsonData,
//data = dataObj.data,
datasetStore,
datasetObj,
value = dataObj.value,
defaultSeriesType = iapi.defaultDatasetType,
dsType,
DsClass,
dataOnlyArr = [],
JSONData,
prevDataLength,
currDataLength,
datasetJSON;
dataOnlyArr.push({
value: value
});
datasetJSON = {data: dataOnlyArr};
iapi.config.categories = dataOnlyArr;
datasetStore = components.dataset || (components.dataset = []);
dsType = defaultSeriesType;
if (dsType) {
/// get the DsClass
DsClass = FusionCharts.get(COMPONENT, [DATASET, dsType]);
if (DsClass) {
if (!datasetStore[0]) {
datasetObj = new DsClass();
datasetStore.push(datasetObj);
datasetObj.chart = iapi;
datasetObj.init(datasetJSON);
}
else {
JSONData = datasetStore[0].JSONData;
prevDataLength = JSONData.data.length;
currDataLength = datasetJSON.data.length;
// Removing data plots if the number of current data plots is more than the existing ones.
if (prevDataLength > currDataLength) {
datasetStore[0].removeData(currDataLength - 1, prevDataLength - currDataLength, false);
}
datasetStore[0].JSONData = datasetJSON;
datasetStore[0].configure();
}
}
}
},
_drawCanvas: function () {
},
_spaceManager: function () {
// todo marge _allocateSpace and _spacemanager
var availableWidth,
availableHeight,
iapi = this,
hasLegend = iapi.hasLegend,
config = iapi.config,
components = iapi.components,
legend = components.legend,
dataset = components.dataset[0],
datasetConfig = dataset.config,
is3d = iapi.is3D,
chartAttrs = iapi.jsonData.chart,
showBorder = pluckNumber (chartAttrs.showborder, is3d ? 0 : 1),
chartBorderHorizontal,
chartBorderVertical,
minChartWidth = config.minChartWidth,
minChartHeight = config.minChartHeight,
chartBorderWidth =
config.borderWidth = showBorder ? pluckNumber (chartAttrs.borderthickness, 1) : 0;
if (config.autoscale) {
datasetConfig.scaleFactor = iapi._getScaleFactor(datasetConfig.origW,
datasetConfig.origH, config.width, config.height);
}
else {
datasetConfig.scaleFactor = 1;
}
if ((config.canvasWidth - 2 * chartBorderWidth) < minChartWidth ) {
chartBorderVertical = (config.canvasWidth - minChartWidth) / 2;
}
if ((config.canvasHeight - 2 * chartBorderWidth) < minChartHeight ) {
chartBorderHorizontal = (config.canvasHeight - minChartHeight) / 2;
}
iapi._allocateSpace ( {
top : chartBorderHorizontal || chartBorderWidth,
bottom : chartBorderHorizontal || chartBorderWidth,
left : chartBorderVertical || chartBorderWidth,
right : chartBorderVertical || chartBorderWidth
});
iapi._allocateSpace(iapi._manageActionBarSpace &&
iapi._manageActionBarSpace(config.availableHeight * 0.225) || {});
//****** Manage space
availableWidth = config.canvasWidth * 0.7;
availableHeight = config.canvasHeight * 0.7;
(hasLegend !== false) &&
iapi._allocateSpace (legend._manageLegendPosition (availableHeight));
// a space manager that manages the space for the tools as well as the captions.
iapi._manageChartMenuBar(availableHeight);
dataset._manageSpace && iapi._allocateSpace(dataset._manageSpace(availableHeight));
},
_getData : chartAPI.vled,
_getScaleFactor : chartAPI.angulargauge
}, chartAPI.gaugebase, {
placevaluesinside: 0,
hasgaugeoriginx: UNDEFINED,
gaugeoriginx: UNDEFINED,
hasgaugeoriginy: UNDEFINED,
gaugeoriginy: UNDEFINED,
hasgaugeradius: UNDEFINED,
gaugeradius: UNDEFINED,
valuepadding: 2,
showgaugeborder: 0,
showhovereffect: UNDEFINED,
autoscale: 1
});
}]);
FusionCharts.register('module', ['private', 'modules.renderer.js-progressgauge', function() {
var global = this,
lib = global.hcLib,
chartAPI = lib.chartAPI,
win = global.window,
creditLabel = false && !lib.CREDIT_REGEX.test(win.location.hostname);
chartAPI('progressgauge', {
friendlyName: 'Progress Gauge',
creditLabel: creditLabel,
defaultSeriesType: 'progressgauge',
singleseries: true,
gaugeType: 1,
standaloneInit: true,
defaultCaptionPadding: 5,
hasLegend: true,
defaultDatasetType: 'progressgauge',
applicableDSList: {
'progressgauge': true
},
_createDatasets: function() {
var iapi = this,
components = iapi.components,
legend = components.legend,
dataObj = iapi.jsonData,
dataset = dataObj.dataset,
data = dataObj.data || (dataset && dataset[0].data),
datasetStore,
datasetObj,
defaultSeriesType = iapi.defaultDatasetType,
dsType,
GroupManager,
groupManagerName,
DsGroupClass,
DsClass,
JSONData,
i,
prevDataLength,
currDataLength,
dataStore,
datasetJSON;
datasetJSON = iapi._dataSegregator(data);
iapi.config.categories = datasetJSON.data;
datasetStore = components.dataset || (components.dataset = []);
if (!(data && data.length !== 0)) {
iapi.setChartMessage();
return;
}
dsType = defaultSeriesType;
if (dsType) {
/// get the DsClass
DsClass = FusionCharts.get('component', ['dataset', dsType]);
if (DsClass) {
groupManagerName = 'datasetGroup_' + dsType;
// get the ds group class
DsGroupClass = FusionCharts.register('component', ['datasetGroup', 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[0]) {
// create the dataset Object
datasetObj = new DsClass();
datasetStore.push(datasetObj);
datasetObj.chart = iapi;
GroupManager && GroupManager.addDataSet(datasetObj, 0, 0);
datasetObj.index = 0;
datasetObj.init(datasetJSON);
} else {
JSONData = datasetStore[0].JSONData;
dataStore = datasetStore[0].components.data || [];
prevDataLength = JSONData.data.length;
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) {
// If there is legend then remove the extra legend items
if (legend) {
for (i = currDataLength; i < prevDataLength; i++) {
if (dataStore[i] && dataStore[i].legendItemId) {
legend.removeItem(dataStore[i].legendItemId);
}
}
}
datasetStore[0].removeData(currDataLength, prevDataLength - currDataLength, false);
}
datasetStore[0].JSONData = datasetJSON;
datasetStore[0].configure();
}
}
}
},
getDataSet: function(index) {
return this.components.dataset[index];
}
}, chartAPI.bulb);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-drawingpad', function () {
var global = this,
lib = global.hcLib,
R = lib.Raphael,
preDefStr = lib.preDefStr,
animationObjStr = preDefStr.animationObjStr,
configStr = preDefStr.configStr,
win = global.window,
ROUND = preDefStr.ROUND,
colorStrings = preDefStr.colors,
COLOR_FFFFFF = colorStrings.FFFFFF,
creditLabel = false && !lib.CREDIT_REGEX.test (win.location.hostname),
chartAPI = lib.chartAPI;
chartAPI ('drawingpad', {
standaloneInit : true,
friendlyName : 'Drawing Pad',
creditLabel : creditLabel,
bgColor : COLOR_FFFFFF,
bgAlpha : '100',
draw : function () {
var iapi = this,
config = iapi.config,
container = iapi.linkedItems.container,
chartInstance = iapi.chartInstance,
components = iapi.components,
paper = components.paper,
animationObj = iapi.get(configStr, animationObjStr),
animType = animationObj.animType,
dummyObj = animationObj.dummyObj,
animObj = animationObj.animObj,
animationDuration = animationObj.duration,
tooltip = components.tooltip,
prevWidth = config.prevWidth,
prevHeight = config.prevHeight,
animationStarted,
attr;
config.width = container.offsetWidth;
config.height = container.offsetHeight;
//show the chart if hidden
iapi._show();
config.animationStarted = true;
if (!paper) {
paper = components.paper = new R (container, container.offsetWidth, container.offsetHeight);
paper.setConfig('stroke-linecap', ROUND);
}
else {
// Fix for IE8 paper animation.
if (prevWidth || prevHeight) {
paper.setSize(prevWidth, prevHeight);
}
attr = {
width: container.offsetWidth,
height: container.offsetHeight
};
animationStarted = true;
iapi._chartAnimation(true);
paper.animateWith(dummyObj, animObj, attr, animationDuration, animType);
}
config.prevWidth = container.offsetWidth;
config.prevHeight = container.offsetHeight;
// Setting tooltip style
paper.tooltip(tooltip.style, tooltip.config.shadow, tooltip.config.constrain);
//create drawing layers
iapi._createLayers ();
//Start the chart animation
!animationStarted && iapi._chartAnimation(true);
// draw components
iapi._drawBackground ();
if (chartInstance.annotations) {
iapi._drawAnnotations ();
}
else {
iapi.setChartMessage();
return;
}
iapi._drawCreditLabel();
},
_createDatasets : function () {}
}, chartAPI.mscartesian);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-realtimearea', function () {
var global = this,
lib = global.hcLib,
chartAPI = lib.chartAPI;
chartAPI ('realtimearea', {
defaultDatasetType : 'realtimearea',
axisPaddingLeft: 0,
axisPaddingRight: 0,
applicableDSList: { 'realtimearea': true }
},chartAPI.realtimecolumn, {
enablemousetracking: true
}, chartAPI.areabase);
}]);
FusionCharts.register('module', ['private', 'modules.renderer.js-realtimestackedarea', function() {
var global = this,
lib = global.hcLib,
chartAPI = lib.chartAPI;
chartAPI('realtimestackedarea', {
defaultDatasetType: 'realtimearea',
applicableDSList: {
'realtimearea': true
}
}, chartAPI.realtimearea, {
isstacked: true,
enablemousetracking: true
});
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-realtimeline', function () {
var global = this,
lib = global.hcLib,
chartAPI = lib.chartAPI;
chartAPI ('realtimeline', {
defaultDatasetType : 'realtimeline',
axisPaddingLeft: 0,
axisPaddingRight: 0,
applicableDSList: { 'realtimeline': true },
zeroplanethickness: 1,
zeroplanealpha: 40,
showzeroplaneontop: 0
},chartAPI.realtimecolumn, {
zeroplanethickness: 1,
zeroplanealpha: 40,
showzeroplaneontop: 0,
enablemousetracking: true
}, chartAPI.areabase);
}]);
FusionCharts.register ('module', ['private', 'modules.renderer.js-realtimelinedy', function () {
var global = this,
lib = global.hcLib,
chartAPI = lib.chartAPI;
chartAPI ('realtimelinedy', {
isRealTime: true,
defaultDatasetType : 'realtimeline',
axisPaddingLeft: 0,
isDual: true,
axisPaddingRight: 0,
applicableDSList: { 'realtimeline': true },
_createAxes: chartAPI.msdybasecartesian._createAxes,
_setAxisLimits: chartAPI.msdybasecartesian._setAxisLimits,
_postSpaceManagement: chartAPI.msdybasecartesian._postSpaceManagement,
_feedAxesRawData: chartAPI.msdybasecartesian._feedAxesRawData
},chartAPI.realtimecolumn, {
isdual: true,
zeroplanethickness: 1,
zeroplanealpha: 40,
showzeroplaneontop: 0,
enablemousetracking: true
}, chartAPI.areabase);
}]);
/* jshint ignore: end */
}));