* <p>Sparkline: <span class="sparkline" values="1,4,6,6,8,5,3,5"></span></p>
* $('.sparkline').sparkline();
*
-* For line charts, x values can also be specified:
-* <p>Sparkline: <span class="sparkline">1:1,2.7:4,3.4:6,5:6,6:8,8.7:5,9:3,10:5</span></p>
-* $('#sparkline1').sparkline([ [1,1], [2.7,4], [3.4,6], [5,6], [6,8], [8.7,5], [9,3], [10,5] ])
-*
* By default, options should be passed in as teh second argument to the sparkline function:
* $('.sparkline').sparkline([1,2,3,4], {type: 'bar'})
*
* numberDecimalMark - Character to use for the decimal point when formatting numbers - Defaults to "."
* numberDigitGroupCount - Number of digits between group separator - Defaults to 3
*
-* There are 7 types of sparkline, selected by supplying a "type" option of 'line' (default),
-* 'bar', 'tristate', 'bullet', 'discrete', 'pie' or 'box'
-* line - Line chart. Options:
-* spotColor - Set to '' to not end each line in a circular spot
-* minSpotColor - If set, color of spot at minimum value
-* maxSpotColor - If set, color of spot at maximum value
-* spotRadius - Radius in pixels
-* lineWidth - Width of line in pixels
-* normalRangeMin
-* normalRangeMax - If set draws a filled horizontal bar between these two values marking the "normal"
-* or expected range of values
-* normalRangeColor - Color to use for the above bar
-* drawNormalOnTop - Draw the normal range above the chart fill color if true
-* defaultPixelsPerValue - Defaults to 3 pixels of width for each value in the chart
-* highlightSpotColor - The color to use for drawing a highlight spot on mouseover - Set to null to disable
-* highlightLineColor - The color to use for drawing a highlight line on mouseover - Set to null to disable
-* valueSpots - Specify which points to draw spots on, and in which color. Accepts a range map
+* There is 1 type of sparkline, selected by supplying a "type" option of 'bar' (default),
*
* bar - Bar chart. Options:
* barColor - Color of bars for postive values
* barSpacing - Gap between bars in pixels
* zeroAxis - Centers the y-axis around zero if true
*
-* tristate - Charts values of win (>0), lose (<0) or draw (=0)
-* posBarColor - Color of win values
-* negBarColor - Color of lose values
-* zeroBarColor - Color of draw values
-* barWidth - Width of bars in pixels
-* barSpacing - Gap between bars in pixels
-* colorMap - Optional mappnig of values to colors to override the *BarColor values above
-* can be an Array of values to control the color of individual bars or a range map
-* to specify colors for individual ranges of values
-*
-* discrete - Options:
-* lineHeight - Height of each line in pixels - Defaults to 30% of the graph height
-* thesholdValue - Values less than this value will be drawn using thresholdColor instead of lineColor
-* thresholdColor
*
-* bullet - Values for bullet graphs msut be in the order: target, performance, range1, range2, range3, ...
-* options:
-* targetColor - The color of the vertical target marker
-* targetWidth - The width of the target marker in pixels
-* performanceColor - The color of the performance measure horizontal bar
-* rangeColors - Colors to use for each qualitative range background color
*
-* pie - Pie chart. Options:
-* sliceColors - An array of colors to use for pie slices
-* offset - Angle in degrees to offset the first slice - Try -90 or +90
-* borderWidth - Width of border to draw around the pie chart, in pixels - Defaults to 0 (no border)
-* borderColor - Color to use for the pie chart border - Defaults to #000
-*
-* box - Box plot. Options:
-* raw - Set to true to supply pre-computed plot points as values
-* values should be: low_outlier, low_whisker, q1, median, q3, high_whisker, high_outlier
-* When set to false you can supply any number of values and the box plot will
-* be computed for you. Default is false.
-* showOutliers - Set to true (default) to display outliers as circles
-* outlierIQR - Interquartile range used to determine outliers. Default 1.5
-* boxLineColor - Outline color of the box
-* boxFillColor - Fill color for the box
-* whiskerColor - Line color used for whiskers
-* outlierLineColor - Outline color of outlier circles
-* outlierFillColor - Fill color of the outlier circles
-* spotRadius - Radius of outlier circles
-* medianColor - Line color of the median line
-* target - Draw a target cross hair at the supplied value (default undefined)
*
*
*
* Examples:
* $('#sparkline1').sparkline(myvalues, { lineColor: '#f00', fillColor: false });
* $('.barsparks').sparkline('html', { type:'bar', height:'40px', barWidth:5 });
-* $('#tristate').sparkline([1,1,-1,1,0,0,-1], { type:'tristate' }):
-* $('#discrete').sparkline([1,3,4,5,5,3,4,5], { type:'discrete' });
-* $('#bullet').sparkline([10,12,12,9,7], { type:'bullet' });
-* $('#pie').sparkline([1,1,2], { type:'pie' });
*/
/*jslint regexp: true, browser: true, jquery: true, white: true, nomen: false, plusplus: false, maxerr: 500, indent: 4 */
getDefaults, createClass, SPFormat, clipval, quartile, normalizeValue, normalizeValues,
remove, isNumber, all, sum, addCSS, ensureArray, formatNumber, RangeMap,
MouseHandler, Tooltip, barHighlightMixin,
- line, bar, tristate, discrete, bullet, pie, box, defaultStyles, initStyles,
- VShape, VCanvas_base, VCanvas_canvas, VCanvas_vml, pending, shapeCount = 0;
+ bar, defaultStyles, initStyles,
+ VShape, VCanvas_base, VCanvas_canvas, pending, shapeCount = 0;
/**
* Default configuration settings
return {
// Settings common to most/all chart types
common: {
- type: 'line',
+ type: 'bar',
lineColor: '#00f',
fillColor: '#cdf',
defaultPixelsPerValue: 3,
disableTooltips: false,
disableInteraction: false
},
- // Defaults for line charts
- line: {
- spotColor: '#f80',
- highlightSpotColor: '#5f5',
- highlightLineColor: '#f22',
- spotRadius: 1.5,
- minSpotColor: '#f80',
- maxSpotColor: '#f80',
- lineWidth: 1,
- normalRangeMin: undefined,
- normalRangeMax: undefined,
- normalRangeColor: '#ccc',
- drawNormalOnTop: false,
- chartRangeMin: undefined,
- chartRangeMax: undefined,
- chartRangeMinX: undefined,
- chartRangeMaxX: undefined,
- tooltipFormat: new SPFormat('<span style="color: {{color}}">●</span> {{prefix}}{{y}}{{suffix}}')
- },
// Defaults for bar charts
bar: {
barColor: '#3366cc',
colorMap: undefined,
tooltipFormat: new SPFormat('<span style="color: {{color}}">●</span> {{prefix}}{{value}}{{suffix}}')
},
- // Defaults for tristate charts
- tristate: {
- barWidth: 4,
- barSpacing: 1,
- posBarColor: '#6f6',
- negBarColor: '#f44',
- zeroBarColor: '#999',
- colorMap: {},
- tooltipFormat: new SPFormat('<span style="color: {{color}}">●</span> {{value:map}}'),
- tooltipValueLookups: { map: { '-1': 'Loss', '0': 'Draw', '1': 'Win' } }
- },
- // Defaults for discrete charts
- discrete: {
- lineHeight: 'auto',
- thresholdColor: undefined,
- thresholdValue: 0,
- chartRangeMax: undefined,
- chartRangeMin: undefined,
- chartRangeClip: false,
- tooltipFormat: new SPFormat('{{prefix}}{{value}}{{suffix}}')
- },
- // Defaults for bullet charts
- bullet: {
- targetColor: '#f33',
- targetWidth: 3, // width of the target bar in pixels
- performanceColor: '#33f',
- rangeColors: ['#d3dafe', '#a8b6ff', '#7f94ff'],
- base: undefined, // set this to a number to change the base start number
- tooltipFormat: new SPFormat('{{fieldkey:fields}} - {{value}}'),
- tooltipValueLookups: { fields: {r: 'Range', p: 'Performance', t: 'Target'} }
- },
- // Defaults for pie charts
- pie: {
- offset: 0,
- sliceColors: ['#3366cc', '#dc3912', '#ff9900', '#109618', '#66aa00',
- '#dd4477', '#0099c6', '#990099'],
- borderWidth: 0,
- borderColor: '#000',
- tooltipFormat: new SPFormat('<span style="color: {{color}}">●</span> {{value}} ({{percent.1}}%)')
- },
- // Defaults for box plots
- box: {
- raw: false,
- boxLineColor: '#000',
- boxFillColor: '#cdf',
- whiskerColor: '#000',
- outlierLineColor: '#333',
- outlierFillColor: '#fff',
- medianColor: '#f00',
- showOutliers: true,
- outlierIQR: 1.5,
- spotRadius: 1.5,
- target: undefined,
- targetColor: '#4a2',
- chartRangeMax: undefined,
- chartRangeMin: undefined,
- tooltipFormat: new SPFormat('{{field:fields}}: {{value}}'),
- tooltipFormatFieldlistKey: 'field',
- tooltipValueLookups: { fields: { lq: 'Lower Quartile', med: 'Median',
- uq: 'Upper Quartile', lo: 'Left Outlier', ro: 'Right Outlier',
- lw: 'Left Whisker', rw: 'Right Whisker'} }
- }
};
};
$.fn.sparkline.canvas = function(width, height, target, interact) {
return new VCanvas_canvas(width, height, target, interact);
};
- } else if (document.namespaces && !document.namespaces.v) {
- // VML is available
- document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', '#default#VML');
- $.fn.sparkline.canvas = function(width, height, target, interact) {
- return new VCanvas_vml(width, height, target);
- };
} else {
// Neither Canvas nor VML are available
$.fn.sparkline.canvas = false;
}
};
- /**
- * Line charts
- */
- $.fn.sparkline.line = line = createClass($.fn.sparkline._base, {
- type: 'line',
-
- init: function (el, values, options, width, height) {
- line._super.init.call(this, el, values, options, width, height);
- this.vertices = [];
- this.regionMap = [];
- this.xvalues = [];
- this.yvalues = [];
- this.yminmax = [];
- this.hightlightSpotId = null;
- this.lastShapeId = null;
- this.initTarget();
- },
-
- getRegion: function (el, x, y) {
- var i,
- regionMap = this.regionMap; // maps regions to value positions
- for (i = regionMap.length; i--;) {
- if (regionMap[i] !== null && x >= regionMap[i][0] && x <= regionMap[i][1]) {
- return regionMap[i][2];
- }
- }
- return undefined;
- },
-
- getCurrentRegionFields: function () {
- var currentRegion = this.currentRegion;
- return {
- isNull: this.yvalues[currentRegion] === null,
- x: this.xvalues[currentRegion],
- y: this.yvalues[currentRegion],
- color: this.options.get('lineColor'),
- fillColor: this.options.get('fillColor'),
- offset: currentRegion
- };
- },
-
- renderHighlight: function () {
- var currentRegion = this.currentRegion,
- target = this.target,
- vertex = this.vertices[currentRegion],
- options = this.options,
- spotRadius = options.get('spotRadius'),
- highlightSpotColor = options.get('highlightSpotColor'),
- highlightLineColor = options.get('highlightLineColor'),
- highlightSpot, highlightLine;
-
- if (!vertex) {
- return;
- }
- if (spotRadius && highlightSpotColor) {
- highlightSpot = target.drawCircle(vertex[0], vertex[1],
- spotRadius, undefined, highlightSpotColor);
- this.highlightSpotId = highlightSpot.id;
- target.insertAfterShape(this.lastShapeId, highlightSpot);
- }
- if (highlightLineColor) {
- highlightLine = target.drawLine(vertex[0], this.canvasTop, vertex[0],
- this.canvasTop + this.canvasHeight, highlightLineColor);
- this.highlightLineId = highlightLine.id;
- target.insertAfterShape(this.lastShapeId, highlightLine);
- }
- },
-
- removeHighlight: function () {
- var target = this.target;
- if (this.highlightSpotId) {
- target.removeShapeId(this.highlightSpotId);
- this.highlightSpotId = null;
- }
- if (this.highlightLineId) {
- target.removeShapeId(this.highlightLineId);
- this.highlightLineId = null;
- }
- },
-
- scanValues: function () {
- var values = this.values,
- valcount = values.length,
- xvalues = this.xvalues,
- yvalues = this.yvalues,
- yminmax = this.yminmax,
- i, val, isStr, isArray, sp;
- for (i = 0; i < valcount; i++) {
- val = values[i];
- isStr = typeof(values[i]) === 'string';
- isArray = typeof(values[i]) === 'object' && values[i] instanceof Array;
- sp = isStr && values[i].split(':');
- if (isStr && sp.length === 2) { // x:y
- xvalues.push(Number(sp[0]));
- yvalues.push(Number(sp[1]));
- yminmax.push(Number(sp[1]));
- } else if (isArray) {
- xvalues.push(val[0]);
- yvalues.push(val[1]);
- yminmax.push(val[1]);
- } else {
- xvalues.push(i);
- if (values[i] === null || values[i] === 'null') {
- yvalues.push(null);
- } else {
- yvalues.push(Number(val));
- yminmax.push(Number(val));
- }
- }
- }
- if (this.options.get('xvalues')) {
- xvalues = this.options.get('xvalues');
- }
-
- this.maxy = this.maxyorg = Math.max.apply(Math, yminmax);
- this.miny = this.minyorg = Math.min.apply(Math, yminmax);
-
- this.maxx = Math.max.apply(Math, xvalues);
- this.minx = Math.min.apply(Math, xvalues);
-
- this.xvalues = xvalues;
- this.yvalues = yvalues;
- this.yminmax = yminmax;
-
- },
-
- processRangeOptions: function () {
- var options = this.options,
- normalRangeMin = options.get('normalRangeMin'),
- normalRangeMax = options.get('normalRangeMax');
-
- if (normalRangeMin !== undefined) {
- if (normalRangeMin < this.miny) {
- this.miny = normalRangeMin;
- }
- if (normalRangeMax > this.maxy) {
- this.maxy = normalRangeMax;
- }
- }
- if (options.get('chartRangeMin') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMin') < this.miny)) {
- this.miny = options.get('chartRangeMin');
- }
- if (options.get('chartRangeMax') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMax') > this.maxy)) {
- this.maxy = options.get('chartRangeMax');
- }
- if (options.get('chartRangeMinX') !== undefined && (options.get('chartRangeClipX') || options.get('chartRangeMinX') < this.minx)) {
- this.minx = options.get('chartRangeMinX');
- }
- if (options.get('chartRangeMaxX') !== undefined && (options.get('chartRangeClipX') || options.get('chartRangeMaxX') > this.maxx)) {
- this.maxx = options.get('chartRangeMaxX');
- }
-
- },
-
- drawNormalRange: function (canvasLeft, canvasTop, canvasHeight, canvasWidth, rangey) {
- var normalRangeMin = this.options.get('normalRangeMin'),
- normalRangeMax = this.options.get('normalRangeMax'),
- ytop = canvasTop + Math.round(canvasHeight - (canvasHeight * ((normalRangeMax - this.miny) / rangey))),
- height = Math.round((canvasHeight * (normalRangeMax - normalRangeMin)) / rangey);
- this.target.drawRect(canvasLeft, ytop, canvasWidth, height, undefined, this.options.get('normalRangeColor')).append();
- },
-
- render: function () {
- var options = this.options,
- target = this.target,
- canvasWidth = this.canvasWidth,
- canvasHeight = this.canvasHeight,
- vertices = this.vertices,
- spotRadius = options.get('spotRadius'),
- regionMap = this.regionMap,
- rangex, rangey, yvallast,
- canvasTop, canvasLeft,
- vertex, path, paths, x, y, xnext, xpos, xposnext,
- last, next, yvalcount, lineShapes, fillShapes, plen,
- valueSpots, hlSpotsEnabled, color, xvalues, yvalues, i;
-
- if (!line._super.render.call(this)) {
- return;
- }
-
- this.scanValues();
- this.processRangeOptions();
-
- xvalues = this.xvalues;
- yvalues = this.yvalues;
-
- if (!this.yminmax.length || this.yvalues.length < 2) {
- // empty or all null valuess
- return;
- }
-
- canvasTop = canvasLeft = 0;
-
- rangex = this.maxx - this.minx === 0 ? 1 : this.maxx - this.minx;
- rangey = this.maxy - this.miny === 0 ? 1 : this.maxy - this.miny;
- yvallast = this.yvalues.length - 1;
-
- if (spotRadius && (canvasWidth < (spotRadius * 4) || canvasHeight < (spotRadius * 4))) {
- spotRadius = 0;
- }
- if (spotRadius) {
- // adjust the canvas size as required so that spots will fit
- hlSpotsEnabled = options.get('highlightSpotColor') && !options.get('disableInteraction');
- if (hlSpotsEnabled || options.get('minSpotColor') || (options.get('spotColor') && yvalues[yvallast] === this.miny)) {
- canvasHeight -= Math.ceil(spotRadius);
- }
- if (hlSpotsEnabled || options.get('maxSpotColor') || (options.get('spotColor') && yvalues[yvallast] === this.maxy)) {
- canvasHeight -= Math.ceil(spotRadius);
- canvasTop += Math.ceil(spotRadius);
- }
- if (hlSpotsEnabled ||
- ((options.get('minSpotColor') || options.get('maxSpotColor')) && (yvalues[0] === this.miny || yvalues[0] === this.maxy))) {
- canvasLeft += Math.ceil(spotRadius);
- canvasWidth -= Math.ceil(spotRadius);
- }
- if (hlSpotsEnabled || options.get('spotColor') ||
- (options.get('minSpotColor') || options.get('maxSpotColor') &&
- (yvalues[yvallast] === this.miny || yvalues[yvallast] === this.maxy))) {
- canvasWidth -= Math.ceil(spotRadius);
- }
- }
-
-
- canvasHeight--;
-
- if (options.get('normalRangeMin') !== undefined && !options.get('drawNormalOnTop')) {
- this.drawNormalRange(canvasLeft, canvasTop, canvasHeight, canvasWidth, rangey);
- }
-
- path = [];
- paths = [path];
- last = next = null;
- yvalcount = yvalues.length;
- for (i = 0; i < yvalcount; i++) {
- x = xvalues[i];
- xnext = xvalues[i + 1];
- y = yvalues[i];
- xpos = canvasLeft + Math.round((x - this.minx) * (canvasWidth / rangex));
- xposnext = i < yvalcount - 1 ? canvasLeft + Math.round((xnext - this.minx) * (canvasWidth / rangex)) : canvasWidth;
- next = xpos + ((xposnext - xpos) / 2);
- regionMap[i] = [last || 0, next, i];
- last = next;
- if (y === null) {
- if (i) {
- if (yvalues[i - 1] !== null) {
- path = [];
- paths.push(path);
- }
- vertices.push(null);
- }
- } else {
- if (y < this.miny) {
- y = this.miny;
- }
- if (y > this.maxy) {
- y = this.maxy;
- }
- if (!path.length) {
- // previous value was null
- path.push([xpos, canvasTop + canvasHeight]);
- }
- vertex = [xpos, canvasTop + Math.round(canvasHeight - (canvasHeight * ((y - this.miny) / rangey)))];
- path.push(vertex);
- vertices.push(vertex);
- }
- }
-
- lineShapes = [];
- fillShapes = [];
- plen = paths.length;
- for (i = 0; i < plen; i++) {
- path = paths[i];
- if (path.length) {
- if (options.get('fillColor')) {
- path.push([path[path.length - 1][0], (canvasTop + canvasHeight)]);
- fillShapes.push(path.slice(0));
- path.pop();
- }
- // if there's only a single point in this path, then we want to display it
- // as a vertical line which means we keep path[0] as is
- if (path.length > 2) {
- // else we want the first value
- path[0] = [path[0][0], path[1][1]];
- }
- lineShapes.push(path);
- }
- }
-
- // draw the fill first, then optionally the normal range, then the line on top of that
- plen = fillShapes.length;
- for (i = 0; i < plen; i++) {
- target.drawShape(fillShapes[i],
- options.get('fillColor'), options.get('fillColor')).append();
- }
-
- if (options.get('normalRangeMin') !== undefined && options.get('drawNormalOnTop')) {
- this.drawNormalRange(canvasLeft, canvasTop, canvasHeight, canvasWidth, rangey);
- }
-
- plen = lineShapes.length;
- for (i = 0; i < plen; i++) {
- target.drawShape(lineShapes[i], options.get('lineColor'), undefined,
- options.get('lineWidth')).append();
- }
-
- if (spotRadius && options.get('valueSpots')) {
- valueSpots = options.get('valueSpots');
- if (valueSpots.get === undefined) {
- valueSpots = new RangeMap(valueSpots);
- }
- for (i = 0; i < yvalcount; i++) {
- color = valueSpots.get(yvalues[i]);
- if (color) {
- target.drawCircle(canvasLeft + Math.round((xvalues[i] - this.minx) * (canvasWidth / rangex)),
- canvasTop + Math.round(canvasHeight - (canvasHeight * ((yvalues[i] - this.miny) / rangey))),
- spotRadius, undefined,
- color).append();
- }
- }
-
- }
- if (spotRadius && options.get('spotColor') && yvalues[yvallast] !== null) {
- target.drawCircle(canvasLeft + Math.round((xvalues[xvalues.length - 1] - this.minx) * (canvasWidth / rangex)),
- canvasTop + Math.round(canvasHeight - (canvasHeight * ((yvalues[yvallast] - this.miny) / rangey))),
- spotRadius, undefined,
- options.get('spotColor')).append();
- }
- if (this.maxy !== this.minyorg) {
- if (spotRadius && options.get('minSpotColor')) {
- x = xvalues[$.inArray(this.minyorg, yvalues)];
- target.drawCircle(canvasLeft + Math.round((x - this.minx) * (canvasWidth / rangex)),
- canvasTop + Math.round(canvasHeight - (canvasHeight * ((this.minyorg - this.miny) / rangey))),
- spotRadius, undefined,
- options.get('minSpotColor')).append();
- }
- if (spotRadius && options.get('maxSpotColor')) {
- x = xvalues[$.inArray(this.maxyorg, yvalues)];
- target.drawCircle(canvasLeft + Math.round((x - this.minx) * (canvasWidth / rangex)),
- canvasTop + Math.round(canvasHeight - (canvasHeight * ((this.maxyorg - this.miny) / rangey))),
- spotRadius, undefined,
- options.get('maxSpotColor')).append();
- }
- }
-
- this.lastShapeId = target.getLastShapeId();
- this.canvasTop = canvasTop;
- target.render();
- }
- });
-
/**
* Bar charts
*/
}
});
- /**
- * Tristate charts
- */
- $.fn.sparkline.tristate = tristate = createClass($.fn.sparkline._base, barHighlightMixin, {
- type: 'tristate',
-
- init: function (el, values, options, width, height) {
- var barWidth = parseInt(options.get('barWidth'), 10),
- barSpacing = parseInt(options.get('barSpacing'), 10);
- tristate._super.init.call(this, el, values, options, width, height);
-
- this.regionShapes = {};
- this.barWidth = barWidth;
- this.barSpacing = barSpacing;
- this.totalBarWidth = barWidth + barSpacing;
- this.values = $.map(values, Number);
- this.width = width = (values.length * barWidth) + ((values.length - 1) * barSpacing);
-
- if ($.isArray(options.get('colorMap'))) {
- this.colorMapByIndex = options.get('colorMap');
- this.colorMapByValue = null;
- } else {
- this.colorMapByIndex = null;
- this.colorMapByValue = options.get('colorMap');
- if (this.colorMapByValue && this.colorMapByValue.get === undefined) {
- this.colorMapByValue = new RangeMap(this.colorMapByValue);
- }
- }
- this.initTarget();
- },
-
- getRegion: function (el, x, y) {
- return Math.floor(x / this.totalBarWidth);
- },
-
- getCurrentRegionFields: function () {
- var currentRegion = this.currentRegion;
- return {
- isNull: this.values[currentRegion] === undefined,
- value: this.values[currentRegion],
- color: this.calcColor(this.values[currentRegion], currentRegion),
- offset: currentRegion
- };
- },
-
- calcColor: function (value, valuenum) {
- var values = this.values,
- options = this.options,
- colorMapByIndex = this.colorMapByIndex,
- colorMapByValue = this.colorMapByValue,
- color, newColor;
-
- if (colorMapByValue && (newColor = colorMapByValue.get(value))) {
- color = newColor;
- } else if (colorMapByIndex && colorMapByIndex.length > valuenum) {
- color = colorMapByIndex[valuenum];
- } else if (values[valuenum] < 0) {
- color = options.get('negBarColor');
- } else if (values[valuenum] > 0) {
- color = options.get('posBarColor');
- } else {
- color = options.get('zeroBarColor');
- }
- return color;
- },
-
- renderRegion: function (valuenum, highlight) {
- var values = this.values,
- options = this.options,
- target = this.target,
- canvasHeight, height, halfHeight,
- x, y, color;
-
- canvasHeight = target.pixelHeight;
- halfHeight = Math.round(canvasHeight / 2);
-
- x = valuenum * this.totalBarWidth;
- if (values[valuenum] < 0) {
- y = halfHeight;
- height = halfHeight - 1;
- } else if (values[valuenum] > 0) {
- y = 0;
- height = halfHeight - 1;
- } else {
- y = halfHeight - 1;
- height = 2;
- }
- color = this.calcColor(values[valuenum], valuenum);
- if (color === null) {
- return;
- }
- if (highlight) {
- color = this.calcHighlightColor(color, options);
- }
- return target.drawRect(x, y, this.barWidth - 1, height - 1, color, color);
- }
- });
-
- /**
- * Discrete charts
- */
- $.fn.sparkline.discrete = discrete = createClass($.fn.sparkline._base, barHighlightMixin, {
- type: 'discrete',
-
- init: function (el, values, options, width, height) {
- discrete._super.init.call(this, el, values, options, width, height);
-
- this.regionShapes = {};
- this.values = values = $.map(values, Number);
- this.min = Math.min.apply(Math, values);
- this.max = Math.max.apply(Math, values);
- this.range = this.max - this.min;
- this.width = width = options.get('width') === 'auto' ? values.length * 2 : this.width;
- this.interval = Math.floor(width / values.length);
- this.itemWidth = width / values.length;
- if (options.get('chartRangeMin') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMin') < this.min)) {
- this.min = options.get('chartRangeMin');
- }
- if (options.get('chartRangeMax') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMax') > this.max)) {
- this.max = options.get('chartRangeMax');
- }
- this.initTarget();
- if (this.target) {
- this.lineHeight = options.get('lineHeight') === 'auto' ? Math.round(this.canvasHeight * 0.3) : options.get('lineHeight');
- }
- },
-
- getRegion: function (el, x, y) {
- return Math.floor(x / this.itemWidth);
- },
-
- getCurrentRegionFields: function () {
- var currentRegion = this.currentRegion;
- return {
- isNull: this.values[currentRegion] === undefined,
- value: this.values[currentRegion],
- offset: currentRegion
- };
- },
-
- renderRegion: function (valuenum, highlight) {
- var values = this.values,
- options = this.options,
- min = this.min,
- max = this.max,
- range = this.range,
- interval = this.interval,
- target = this.target,
- canvasHeight = this.canvasHeight,
- lineHeight = this.lineHeight,
- pheight = canvasHeight - lineHeight,
- ytop, val, color, x;
-
- val = clipval(values[valuenum], min, max);
- x = valuenum * interval;
- ytop = Math.round(pheight - pheight * ((val - min) / range));
- color = (options.get('thresholdColor') && val < options.get('thresholdValue')) ? options.get('thresholdColor') : options.get('lineColor');
- if (highlight) {
- color = this.calcHighlightColor(color, options);
- }
- return target.drawLine(x, ytop, x, ytop + lineHeight, color);
- }
- });
-
- /**
- * Bullet charts
- */
- $.fn.sparkline.bullet = bullet = createClass($.fn.sparkline._base, {
- type: 'bullet',
-
- init: function (el, values, options, width, height) {
- var min, max, vals;
- bullet._super.init.call(this, el, values, options, width, height);
-
- // values: target, performance, range1, range2, range3
- this.values = values = normalizeValues(values);
- // target or performance could be null
- vals = values.slice();
- vals[0] = vals[0] === null ? vals[2] : vals[0];
- vals[1] = values[1] === null ? vals[2] : vals[1];
- min = Math.min.apply(Math, values);
- max = Math.max.apply(Math, values);
- if (options.get('base') === undefined) {
- min = min < 0 ? min : 0;
- } else {
- min = options.get('base');
- }
- this.min = min;
- this.max = max;
- this.range = max - min;
- this.shapes = {};
- this.valueShapes = {};
- this.regiondata = {};
- this.width = width = options.get('width') === 'auto' ? '4.0em' : width;
- this.target = this.$el.simpledraw(width, height, options.get('composite'));
- if (!values.length) {
- this.disabled = true;
- }
- this.initTarget();
- },
-
- getRegion: function (el, x, y) {
- var shapeid = this.target.getShapeAt(el, x, y);
- return (shapeid !== undefined && this.shapes[shapeid] !== undefined) ? this.shapes[shapeid] : undefined;
- },
-
- getCurrentRegionFields: function () {
- var currentRegion = this.currentRegion;
- return {
- fieldkey: currentRegion.substr(0, 1),
- value: this.values[currentRegion.substr(1)],
- region: currentRegion
- };
- },
-
- changeHighlight: function (highlight) {
- var currentRegion = this.currentRegion,
- shapeid = this.valueShapes[currentRegion],
- shape;
- delete this.shapes[shapeid];
- switch (currentRegion.substr(0, 1)) {
- case 'r':
- shape = this.renderRange(currentRegion.substr(1), highlight);
- break;
- case 'p':
- shape = this.renderPerformance(highlight);
- break;
- case 't':
- shape = this.renderTarget(highlight);
- break;
- }
- this.valueShapes[currentRegion] = shape.id;
- this.shapes[shape.id] = currentRegion;
- this.target.replaceWithShape(shapeid, shape);
- },
-
- renderRange: function (rn, highlight) {
- var rangeval = this.values[rn],
- rangewidth = Math.round(this.canvasWidth * ((rangeval - this.min) / this.range)),
- color = this.options.get('rangeColors')[rn - 2];
- if (highlight) {
- color = this.calcHighlightColor(color, this.options);
- }
- return this.target.drawRect(0, 0, rangewidth - 1, this.canvasHeight - 1, color, color);
- },
-
- renderPerformance: function (highlight) {
- var perfval = this.values[1],
- perfwidth = Math.round(this.canvasWidth * ((perfval - this.min) / this.range)),
- color = this.options.get('performanceColor');
- if (highlight) {
- color = this.calcHighlightColor(color, this.options);
- }
- return this.target.drawRect(0, Math.round(this.canvasHeight * 0.3), perfwidth - 1,
- Math.round(this.canvasHeight * 0.4) - 1, color, color);
- },
-
- renderTarget: function (highlight) {
- var targetval = this.values[0],
- x = Math.round(this.canvasWidth * ((targetval - this.min) / this.range) - (this.options.get('targetWidth') / 2)),
- targettop = Math.round(this.canvasHeight * 0.10),
- targetheight = this.canvasHeight - (targettop * 2),
- color = this.options.get('targetColor');
- if (highlight) {
- color = this.calcHighlightColor(color, this.options);
- }
- return this.target.drawRect(x, targettop, this.options.get('targetWidth') - 1, targetheight - 1, color, color);
- },
-
- render: function () {
- var vlen = this.values.length,
- target = this.target,
- i, shape;
- if (!bullet._super.render.call(this)) {
- return;
- }
- for (i = 2; i < vlen; i++) {
- shape = this.renderRange(i).append();
- this.shapes[shape.id] = 'r' + i;
- this.valueShapes['r' + i] = shape.id;
- }
- if (this.values[1] !== null) {
- shape = this.renderPerformance().append();
- this.shapes[shape.id] = 'p1';
- this.valueShapes.p1 = shape.id;
- }
- if (this.values[0] !== null) {
- shape = this.renderTarget().append();
- this.shapes[shape.id] = 't0';
- this.valueShapes.t0 = shape.id;
- }
- target.render();
- }
- });
-
- /**
- * Pie charts
- */
- $.fn.sparkline.pie = pie = createClass($.fn.sparkline._base, {
- type: 'pie',
-
- init: function (el, values, options, width, height) {
- var total = 0, i;
-
- pie._super.init.call(this, el, values, options, width, height);
-
- this.shapes = {}; // map shape ids to value offsets
- this.valueShapes = {}; // maps value offsets to shape ids
- this.values = values = $.map(values, Number);
-
- if (options.get('width') === 'auto') {
- this.width = this.height;
- }
-
- if (values.length > 0) {
- for (i = values.length; i--;) {
- total += values[i];
- }
- }
- this.total = total;
- this.initTarget();
- this.radius = Math.floor(Math.min(this.canvasWidth, this.canvasHeight) / 2);
- },
-
- getRegion: function (el, x, y) {
- var shapeid = this.target.getShapeAt(el, x, y);
- return (shapeid !== undefined && this.shapes[shapeid] !== undefined) ? this.shapes[shapeid] : undefined;
- },
-
- getCurrentRegionFields: function () {
- var currentRegion = this.currentRegion;
- return {
- isNull: this.values[currentRegion] === undefined,
- value: this.values[currentRegion],
- percent: this.values[currentRegion] / this.total * 100,
- color: this.options.get('sliceColors')[currentRegion % this.options.get('sliceColors').length],
- offset: currentRegion
- };
- },
-
- changeHighlight: function (highlight) {
- var currentRegion = this.currentRegion,
- newslice = this.renderSlice(currentRegion, highlight),
- shapeid = this.valueShapes[currentRegion];
- delete this.shapes[shapeid];
- this.target.replaceWithShape(shapeid, newslice);
- this.valueShapes[currentRegion] = newslice.id;
- this.shapes[newslice.id] = currentRegion;
- },
-
- renderSlice: function (valuenum, highlight) {
- var target = this.target,
- options = this.options,
- radius = this.radius,
- borderWidth = options.get('borderWidth'),
- offset = options.get('offset'),
- circle = 2 * Math.PI,
- values = this.values,
- total = this.total,
- next = offset ? (2*Math.PI)*(offset/360) : 0,
- start, end, i, vlen, color;
-
- vlen = values.length;
- for (i = 0; i < vlen; i++) {
- start = next;
- end = next;
- if (total > 0) { // avoid divide by zero
- end = next + (circle * (values[i] / total));
- }
- if (valuenum === i) {
- color = options.get('sliceColors')[i % options.get('sliceColors').length];
- if (highlight) {
- color = this.calcHighlightColor(color, options);
- }
-
- return target.drawPieSlice(radius, radius, radius - borderWidth, start, end, undefined, color);
- }
- next = end;
- }
- },
-
- render: function () {
- var target = this.target,
- values = this.values,
- options = this.options,
- radius = this.radius,
- borderWidth = options.get('borderWidth'),
- shape, i;
-
- if (!pie._super.render.call(this)) {
- return;
- }
- if (borderWidth) {
- target.drawCircle(radius, radius, Math.floor(radius - (borderWidth / 2)),
- options.get('borderColor'), undefined, borderWidth).append();
- }
- for (i = values.length; i--;) {
- if (values[i]) { // don't render zero values
- shape = this.renderSlice(i).append();
- this.valueShapes[i] = shape.id; // store just the shapeid
- this.shapes[shape.id] = i;
- }
- }
- target.render();
- }
- });
-
- /**
- * Box plots
- */
- $.fn.sparkline.box = box = createClass($.fn.sparkline._base, {
- type: 'box',
-
- init: function (el, values, options, width, height) {
- box._super.init.call(this, el, values, options, width, height);
- this.values = $.map(values, Number);
- this.width = options.get('width') === 'auto' ? '4.0em' : width;
- this.initTarget();
- if (!this.values.length) {
- this.disabled = 1;
- }
- },
-
- /**
- * Simulate a single region
- */
- getRegion: function () {
- return 1;
- },
-
- getCurrentRegionFields: function () {
- var result = [
- { field: 'lq', value: this.quartiles[0] },
- { field: 'med', value: this.quartiles[1] },
- { field: 'uq', value: this.quartiles[2] }
- ];
- if (this.loutlier !== undefined) {
- result.push({ field: 'lo', value: this.loutlier});
- }
- if (this.routlier !== undefined) {
- result.push({ field: 'ro', value: this.routlier});
- }
- if (this.lwhisker !== undefined) {
- result.push({ field: 'lw', value: this.lwhisker});
- }
- if (this.rwhisker !== undefined) {
- result.push({ field: 'rw', value: this.rwhisker});
- }
- return result;
- },
-
- render: function () {
- var target = this.target,
- values = this.values,
- vlen = values.length,
- options = this.options,
- canvasWidth = this.canvasWidth,
- canvasHeight = this.canvasHeight,
- minValue = options.get('chartRangeMin') === undefined ? Math.min.apply(Math, values) : options.get('chartRangeMin'),
- maxValue = options.get('chartRangeMax') === undefined ? Math.max.apply(Math, values) : options.get('chartRangeMax'),
- canvasLeft = 0,
- lwhisker, loutlier, iqr, q1, q2, q3, rwhisker, routlier, i,
- size, unitSize;
-
- if (!box._super.render.call(this)) {
- return;
- }
-
- if (options.get('raw')) {
- if (options.get('showOutliers') && values.length > 5) {
- loutlier = values[0];
- lwhisker = values[1];
- q1 = values[2];
- q2 = values[3];
- q3 = values[4];
- rwhisker = values[5];
- routlier = values[6];
- } else {
- lwhisker = values[0];
- q1 = values[1];
- q2 = values[2];
- q3 = values[3];
- rwhisker = values[4];
- }
- } else {
- values.sort(function (a, b) { return a - b; });
- q1 = quartile(values, 1);
- q2 = quartile(values, 2);
- q3 = quartile(values, 3);
- iqr = q3 - q1;
- if (options.get('showOutliers')) {
- lwhisker = rwhisker = undefined;
- for (i = 0; i < vlen; i++) {
- if (lwhisker === undefined && values[i] > q1 - (iqr * options.get('outlierIQR'))) {
- lwhisker = values[i];
- }
- if (values[i] < q3 + (iqr * options.get('outlierIQR'))) {
- rwhisker = values[i];
- }
- }
- loutlier = values[0];
- routlier = values[vlen - 1];
- } else {
- lwhisker = values[0];
- rwhisker = values[vlen - 1];
- }
- }
- this.quartiles = [q1, q2, q3];
- this.lwhisker = lwhisker;
- this.rwhisker = rwhisker;
- this.loutlier = loutlier;
- this.routlier = routlier;
-
- unitSize = canvasWidth / (maxValue - minValue + 1);
- if (options.get('showOutliers')) {
- canvasLeft = Math.ceil(options.get('spotRadius'));
- canvasWidth -= 2 * Math.ceil(options.get('spotRadius'));
- unitSize = canvasWidth / (maxValue - minValue + 1);
- if (loutlier < lwhisker) {
- target.drawCircle((loutlier - minValue) * unitSize + canvasLeft,
- canvasHeight / 2,
- options.get('spotRadius'),
- options.get('outlierLineColor'),
- options.get('outlierFillColor')).append();
- }
- if (routlier > rwhisker) {
- target.drawCircle((routlier - minValue) * unitSize + canvasLeft,
- canvasHeight / 2,
- options.get('spotRadius'),
- options.get('outlierLineColor'),
- options.get('outlierFillColor')).append();
- }
- }
-
- // box
- target.drawRect(
- Math.round((q1 - minValue) * unitSize + canvasLeft),
- Math.round(canvasHeight * 0.1),
- Math.round((q3 - q1) * unitSize),
- Math.round(canvasHeight * 0.8),
- options.get('boxLineColor'),
- options.get('boxFillColor')).append();
- // left whisker
- target.drawLine(
- Math.round((lwhisker - minValue) * unitSize + canvasLeft),
- Math.round(canvasHeight / 2),
- Math.round((q1 - minValue) * unitSize + canvasLeft),
- Math.round(canvasHeight / 2),
- options.get('lineColor')).append();
- target.drawLine(
- Math.round((lwhisker - minValue) * unitSize + canvasLeft),
- Math.round(canvasHeight / 4),
- Math.round((lwhisker - minValue) * unitSize + canvasLeft),
- Math.round(canvasHeight - canvasHeight / 4),
- options.get('whiskerColor')).append();
- // right whisker
- target.drawLine(Math.round((rwhisker - minValue) * unitSize + canvasLeft),
- Math.round(canvasHeight / 2),
- Math.round((q3 - minValue) * unitSize + canvasLeft),
- Math.round(canvasHeight / 2),
- options.get('lineColor')).append();
- target.drawLine(
- Math.round((rwhisker - minValue) * unitSize + canvasLeft),
- Math.round(canvasHeight / 4),
- Math.round((rwhisker - minValue) * unitSize + canvasLeft),
- Math.round(canvasHeight - canvasHeight / 4),
- options.get('whiskerColor')).append();
- // median line
- target.drawLine(
- Math.round((q2 - minValue) * unitSize + canvasLeft),
- Math.round(canvasHeight * 0.1),
- Math.round((q2 - minValue) * unitSize + canvasLeft),
- Math.round(canvasHeight * 0.9),
- options.get('medianColor')).append();
- if (options.get('target')) {
- size = Math.ceil(options.get('spotRadius'));
- target.drawLine(
- Math.round((options.get('target') - minValue) * unitSize + canvasLeft),
- Math.round((canvasHeight / 2) - size),
- Math.round((options.get('target') - minValue) * unitSize + canvasLeft),
- Math.round((canvasHeight / 2) + size),
- options.get('targetColor')).append();
- target.drawLine(
- Math.round((options.get('target') - minValue) * unitSize + canvasLeft - size),
- Math.round(canvasHeight / 2),
- Math.round((options.get('target') - minValue) * unitSize + canvasLeft + size),
- Math.round(canvasHeight / 2),
- options.get('targetColor')).append();
- }
- target.render();
- }
- });
-
// Setup a very simple "virtual canvas" to make drawing the few shapes we need easier
// This is accessible as $(foo).simpledraw()
}
});
-
- VCanvas_vml = createClass(VCanvas_base, {
- init: function (width, height, target) {
- var groupel;
- VCanvas_vml._super.init.call(this, width, height, target);
- if (target[0]) {
- target = target[0];
- }
- $.data(target, '_jqs_vcanvas', this);
- this.canvas = document.createElement('span');
- $(this.canvas).css({ display: 'inline-block', position: 'relative', overflow: 'hidden', width: width, height: height, margin: '0px', padding: '0px', verticalAlign: 'top'});
- this._insert(this.canvas, target);
- this._calculatePixelDims(width, height, this.canvas);
- this.canvas.width = this.pixelWidth;
- this.canvas.height = this.pixelHeight;
- groupel = '<v:group coordorigin="0 0" coordsize="' + this.pixelWidth + ' ' + this.pixelHeight + '"' +
- ' style="position:absolute;top:0;left:0;width:' + this.pixelWidth + 'px;height=' + this.pixelHeight + 'px;"></v:group>';
- this.canvas.insertAdjacentHTML('beforeEnd', groupel);
- this.group = $(this.canvas).children()[0];
- this.rendered = false;
- this.prerender = '';
- },
-
- _drawShape: function (shapeid, path, lineColor, fillColor, lineWidth) {
- var vpath = [],
- initial, stroke, fill, closed, vel, plen, i;
- for (i = 0, plen = path.length; i < plen; i++) {
- vpath[i] = '' + (path[i][0]) + ',' + (path[i][1]);
- }
- initial = vpath.splice(0, 1);
- lineWidth = lineWidth === undefined ? 1 : lineWidth;
- stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="' + lineWidth + 'px" strokeColor="' + lineColor + '" ';
- fill = fillColor === undefined ? ' filled="false"' : ' fillColor="' + fillColor + '" filled="true" ';
- closed = vpath[0] === vpath[vpath.length - 1] ? 'x ' : '';
- vel = '<v:shape coordorigin="0 0" coordsize="' + this.pixelWidth + ' ' + this.pixelHeight + '" ' +
- ' id="jqsshape' + shapeid + '" ' +
- stroke +
- fill +
- ' style="position:absolute;left:0px;top:0px;height:' + this.pixelHeight + 'px;width:' + this.pixelWidth + 'px;padding:0px;margin:0px;" ' +
- ' path="m ' + initial + ' l ' + vpath.join(', ') + ' ' + closed + 'e">' +
- ' </v:shape>';
- return vel;
- },
-
- _drawCircle: function (shapeid, x, y, radius, lineColor, fillColor, lineWidth) {
- var stroke, fill, vel;
- x -= radius;
- y -= radius;
- stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="' + lineWidth + 'px" strokeColor="' + lineColor + '" ';
- fill = fillColor === undefined ? ' filled="false"' : ' fillColor="' + fillColor + '" filled="true" ';
- vel = '<v:oval ' +
- ' id="jqsshape' + shapeid + '" ' +
- stroke +
- fill +
- ' style="position:absolute;top:' + y + 'px; left:' + x + 'px; width:' + (radius * 2) + 'px; height:' + (radius * 2) + 'px"></v:oval>';
- return vel;
-
- },
-
- _drawPieSlice: function (shapeid, x, y, radius, startAngle, endAngle, lineColor, fillColor) {
- var vpath, startx, starty, endx, endy, stroke, fill, vel;
- if (startAngle === endAngle) {
- return ''; // VML seems to have problem when start angle equals end angle.
- }
- if ((endAngle - startAngle) === (2 * Math.PI)) {
- startAngle = 0.0; // VML seems to have a problem when drawing a full circle that doesn't start 0
- endAngle = (2 * Math.PI);
- }
-
- startx = x + Math.round(Math.cos(startAngle) * radius);
- starty = y + Math.round(Math.sin(startAngle) * radius);
- endx = x + Math.round(Math.cos(endAngle) * radius);
- endy = y + Math.round(Math.sin(endAngle) * radius);
-
- if (startx === endx && starty === endy) {
- if ((endAngle - startAngle) < Math.PI) {
- // Prevent very small slices from being mistaken as a whole pie
- return '';
- }
- // essentially going to be the entire circle, so ignore startAngle
- startx = endx = x + radius;
- starty = endy = y;
- }
-
- if (startx === endx && starty === endy && (endAngle - startAngle) < Math.PI) {
- return '';
- }
-
- vpath = [x - radius, y - radius, x + radius, y + radius, startx, starty, endx, endy];
- stroke = lineColor === undefined ? ' stroked="false" ' : ' strokeWeight="1px" strokeColor="' + lineColor + '" ';
- fill = fillColor === undefined ? ' filled="false"' : ' fillColor="' + fillColor + '" filled="true" ';
- vel = '<v:shape coordorigin="0 0" coordsize="' + this.pixelWidth + ' ' + this.pixelHeight + '" ' +
- ' id="jqsshape' + shapeid + '" ' +
- stroke +
- fill +
- ' style="position:absolute;left:0px;top:0px;height:' + this.pixelHeight + 'px;width:' + this.pixelWidth + 'px;padding:0px;margin:0px;" ' +
- ' path="m ' + x + ',' + y + ' wa ' + vpath.join(', ') + ' x e">' +
- ' </v:shape>';
- return vel;
- },
-
- _drawRect: function (shapeid, x, y, width, height, lineColor, fillColor) {
- return this._drawShape(shapeid, [[x, y], [x, y + height], [x + width, y + height], [x + width, y], [x, y]], lineColor, fillColor);
- },
-
- reset: function () {
- this.group.innerHTML = '';
- },
-
- appendShape: function (shape) {
- var vel = this['_draw' + shape.type].apply(this, shape.args);
- if (this.rendered) {
- this.group.insertAdjacentHTML('beforeEnd', vel);
- } else {
- this.prerender += vel;
- }
- this.lastShapeId = shape.id;
- return shape.id;
- },
-
- replaceWithShape: function (shapeid, shape) {
- var existing = $('#jqsshape' + shapeid),
- vel = this['_draw' + shape.type].apply(this, shape.args);
- existing[0].outerHTML = vel;
- },
-
- replaceWithShapes: function (shapeids, shapes) {
- // replace the first shapeid with all the new shapes then toast the remaining old shapes
- var existing = $('#jqsshape' + shapeids[0]),
- replace = '',
- slen = shapes.length,
- i;
- for (i = 0; i < slen; i++) {
- replace += this['_draw' + shapes[i].type].apply(this, shapes[i].args);
- }
- existing[0].outerHTML = replace;
- for (i = 1; i < shapeids.length; i++) {
- $('#jqsshape' + shapeids[i]).remove();
- }
- },
-
- insertAfterShape: function (shapeid, shape) {
- var existing = $('#jqsshape' + shapeid),
- vel = this['_draw' + shape.type].apply(this, shape.args);
- existing[0].insertAdjacentHTML('afterEnd', vel);
- },
-
- removeShapeId: function (shapeid) {
- var existing = $('#jqsshape' + shapeid);
- this.group.removeChild(existing[0]);
- },
-
- getShapeAt: function (el, x, y) {
- var shapeid = el.id.substr(8);
- return shapeid;
- },
-
- render: function () {
- if (!this.rendered) {
- // batch the intial render into a single repaint
- this.group.innerHTML = this.prerender;
- this.rendered = true;
- }
- }
- });
-
}))}(document, Math));