summaryrefslogtreecommitdiff
path: root/html/includes/js/modules/heatmap.src.js
diff options
context:
space:
mode:
Diffstat (limited to 'html/includes/js/modules/heatmap.src.js')
-rw-r--r--html/includes/js/modules/heatmap.src.js687
1 files changed, 687 insertions, 0 deletions
diff --git a/html/includes/js/modules/heatmap.src.js b/html/includes/js/modules/heatmap.src.js
new file mode 100644
index 0000000..253ca2b
--- /dev/null
+++ b/html/includes/js/modules/heatmap.src.js
@@ -0,0 +1,687 @@
+/**
+ * @license Highcharts JS v4.0.4 (2014-09-02)
+ *
+ * (c) 2011-2014 Torstein Honsi
+ *
+ * License: www.highcharts.com/license
+ */
+
+/*global HighchartsAdapter*/
+(function (Highcharts) {
+
+
+var UNDEFINED,
+ Axis = Highcharts.Axis,
+ Chart = Highcharts.Chart,
+ Color = Highcharts.Color,
+ Legend = Highcharts.Legend,
+ LegendSymbolMixin = Highcharts.LegendSymbolMixin,
+ Series = Highcharts.Series,
+ SVGRenderer = Highcharts.SVGRenderer,
+
+ defaultOptions = Highcharts.getOptions(),
+ each = Highcharts.each,
+ extend = Highcharts.extend,
+ extendClass = Highcharts.extendClass,
+ merge = Highcharts.merge,
+ pick = Highcharts.pick,
+ numberFormat = Highcharts.numberFormat,
+ seriesTypes = Highcharts.seriesTypes,
+ wrap = Highcharts.wrap,
+ noop = function () {};
+
+
+
+
+/**
+ * The ColorAxis object for inclusion in gradient legends
+ */
+var ColorAxis = Highcharts.ColorAxis = function () {
+ this.isColorAxis = true;
+ this.init.apply(this, arguments);
+};
+extend(ColorAxis.prototype, Axis.prototype);
+extend(ColorAxis.prototype, {
+ defaultColorAxisOptions: {
+ lineWidth: 0,
+ gridLineWidth: 1,
+ tickPixelInterval: 72,
+ startOnTick: true,
+ endOnTick: true,
+ offset: 0,
+ marker: {
+ animation: {
+ duration: 50
+ },
+ color: 'gray',
+ width: 0.01
+ },
+ labels: {
+ overflow: 'justify'
+ },
+ minColor: '#EFEFFF',
+ maxColor: '#003875',
+ tickLength: 5
+ },
+ init: function (chart, userOptions) {
+ var horiz = chart.options.legend.layout !== 'vertical',
+ options;
+
+ // Build the options
+ options = merge(this.defaultColorAxisOptions, {
+ side: horiz ? 2 : 1,
+ reversed: !horiz
+ }, userOptions, {
+ isX: horiz,
+ opposite: !horiz,
+ showEmpty: false,
+ title: null,
+ isColor: true
+ });
+
+ Axis.prototype.init.call(this, chart, options);
+
+ // Base init() pushes it to the xAxis array, now pop it again
+ //chart[this.isXAxis ? 'xAxis' : 'yAxis'].pop();
+
+ // Prepare data classes
+ if (userOptions.dataClasses) {
+ this.initDataClasses(userOptions);
+ }
+ this.initStops(userOptions);
+
+ // Override original axis properties
+ this.isXAxis = true;
+ this.horiz = horiz;
+ this.zoomEnabled = false;
+ },
+
+ /*
+ * Return an intermediate color between two colors, according to pos where 0
+ * is the from color and 1 is the to color
+ */
+ tweenColors: function (from, to, pos) {
+ // Check for has alpha, because rgba colors perform worse due to lack of
+ // support in WebKit.
+ var hasAlpha = (to.rgba[3] !== 1 || from.rgba[3] !== 1);
+ return (hasAlpha ? 'rgba(' : 'rgb(') +
+ Math.round(to.rgba[0] + (from.rgba[0] - to.rgba[0]) * (1 - pos)) + ',' +
+ Math.round(to.rgba[1] + (from.rgba[1] - to.rgba[1]) * (1 - pos)) + ',' +
+ Math.round(to.rgba[2] + (from.rgba[2] - to.rgba[2]) * (1 - pos)) +
+ (hasAlpha ? (',' + (to.rgba[3] + (from.rgba[3] - to.rgba[3]) * (1 - pos))) : '') + ')';
+ },
+
+ initDataClasses: function (userOptions) {
+ var axis = this,
+ chart = this.chart,
+ dataClasses,
+ colorCounter = 0,
+ options = this.options,
+ len = userOptions.dataClasses.length;
+ this.dataClasses = dataClasses = [];
+ this.legendItems = [];
+
+ each(userOptions.dataClasses, function (dataClass, i) {
+ var colors;
+
+ dataClass = merge(dataClass);
+ dataClasses.push(dataClass);
+ if (!dataClass.color) {
+ if (options.dataClassColor === 'category') {
+ colors = chart.options.colors;
+ dataClass.color = colors[colorCounter++];
+ // loop back to zero
+ if (colorCounter === colors.length) {
+ colorCounter = 0;
+ }
+ } else {
+ dataClass.color = axis.tweenColors(
+ Color(options.minColor),
+ Color(options.maxColor),
+ len < 2 ? 0.5 : i / (len - 1) // #3219
+ );
+ }
+ }
+ });
+ },
+
+ initStops: function (userOptions) {
+ this.stops = userOptions.stops || [
+ [0, this.options.minColor],
+ [1, this.options.maxColor]
+ ];
+ each(this.stops, function (stop) {
+ stop.color = Color(stop[1]);
+ });
+ },
+
+ /**
+ * Extend the setOptions method to process extreme colors and color
+ * stops.
+ */
+ setOptions: function (userOptions) {
+ Axis.prototype.setOptions.call(this, userOptions);
+
+ this.options.crosshair = this.options.marker;
+ this.coll = 'colorAxis';
+ },
+
+ setAxisSize: function () {
+ var symbol = this.legendSymbol,
+ chart = this.chart,
+ x,
+ y,
+ width,
+ height;
+
+ if (symbol) {
+ this.left = x = symbol.attr('x');
+ this.top = y = symbol.attr('y');
+ this.width = width = symbol.attr('width');
+ this.height = height = symbol.attr('height');
+ this.right = chart.chartWidth - x - width;
+ this.bottom = chart.chartHeight - y - height;
+
+ this.len = this.horiz ? width : height;
+ this.pos = this.horiz ? x : y;
+ }
+ },
+
+ /**
+ * Translate from a value to a color
+ */
+ toColor: function (value, point) {
+ var pos,
+ stops = this.stops,
+ from,
+ to,
+ color,
+ dataClasses = this.dataClasses,
+ dataClass,
+ i;
+
+ if (dataClasses) {
+ i = dataClasses.length;
+ while (i--) {
+ dataClass = dataClasses[i];
+ from = dataClass.from;
+ to = dataClass.to;
+ if ((from === UNDEFINED || value >= from) && (to === UNDEFINED || value <= to)) {
+ color = dataClass.color;
+ if (point) {
+ point.dataClass = i;
+ }
+ break;
+ }
+ }
+
+ } else {
+
+ if (this.isLog) {
+ value = this.val2lin(value);
+ }
+ pos = 1 - ((this.max - value) / ((this.max - this.min) || 1));
+ i = stops.length;
+ while (i--) {
+ if (pos > stops[i][0]) {
+ break;
+ }
+ }
+ from = stops[i] || stops[i + 1];
+ to = stops[i + 1] || from;
+
+ // The position within the gradient
+ pos = 1 - (to[0] - pos) / ((to[0] - from[0]) || 1);
+
+ color = this.tweenColors(
+ from.color,
+ to.color,
+ pos
+ );
+ }
+ return color;
+ },
+
+ getOffset: function () {
+ var group = this.legendGroup,
+ sideOffset = this.chart.axisOffset[this.side];
+
+ if (group) {
+
+ Axis.prototype.getOffset.call(this);
+
+ if (!this.axisGroup.parentGroup) {
+
+ // Move the axis elements inside the legend group
+ this.axisGroup.add(group);
+ this.gridGroup.add(group);
+ this.labelGroup.add(group);
+
+ this.added = true;
+ }
+ // Reset it to avoid color axis reserving space
+ this.chart.axisOffset[this.side] = sideOffset;
+ }
+ },
+
+ /**
+ * Create the color gradient
+ */
+ setLegendColor: function () {
+ var grad,
+ horiz = this.horiz,
+ options = this.options;
+
+ grad = horiz ? [0, 0, 1, 0] : [0, 0, 0, 1];
+ this.legendColor = {
+ linearGradient: { x1: grad[0], y1: grad[1], x2: grad[2], y2: grad[3] },
+ stops: options.stops || [
+ [0, options.minColor],
+ [1, options.maxColor]
+ ]
+ };
+ },
+
+ /**
+ * The color axis appears inside the legend and has its own legend symbol
+ */
+ drawLegendSymbol: function (legend, item) {
+ var padding = legend.padding,
+ legendOptions = legend.options,
+ horiz = this.horiz,
+ box,
+ width = pick(legendOptions.symbolWidth, horiz ? 200 : 12),
+ height = pick(legendOptions.symbolHeight, horiz ? 12 : 200),
+ labelPadding = pick(legendOptions.labelPadding, horiz ? 16 : 30),
+ itemDistance = pick(legendOptions.itemDistance, 10);
+
+ this.setLegendColor();
+
+ // Create the gradient
+ item.legendSymbol = this.chart.renderer.rect(
+ 0,
+ legend.baseline - 11,
+ width,
+ height
+ ).attr({
+ zIndex: 1
+ }).add(item.legendGroup);
+ box = item.legendSymbol.getBBox();
+
+ // Set how much space this legend item takes up
+ this.legendItemWidth = width + padding + (horiz ? itemDistance : labelPadding);
+ this.legendItemHeight = height + padding + (horiz ? labelPadding : 0);
+ },
+ /**
+ * Fool the legend
+ */
+ setState: noop,
+ visible: true,
+ setVisible: noop,
+ getSeriesExtremes: function () {
+ var series;
+ if (this.series.length) {
+ series = this.series[0];
+ this.dataMin = series.valueMin;
+ this.dataMax = series.valueMax;
+ }
+ },
+ drawCrosshair: function (e, point) {
+ var newCross = !this.cross,
+ plotX = point && point.plotX,
+ plotY = point && point.plotY,
+ crossPos,
+ axisPos = this.pos,
+ axisLen = this.len;
+
+ if (point) {
+ crossPos = this.toPixels(point.value);
+ if (crossPos < axisPos) {
+ crossPos = axisPos - 2;
+ } else if (crossPos > axisPos + axisLen) {
+ crossPos = axisPos + axisLen + 2;
+ }
+
+ point.plotX = crossPos;
+ point.plotY = this.len - crossPos;
+ Axis.prototype.drawCrosshair.call(this, e, point);
+ point.plotX = plotX;
+ point.plotY = plotY;
+
+ if (!newCross && this.cross) {
+ this.cross
+ .attr({
+ fill: this.crosshair.color
+ })
+ .add(this.labelGroup);
+ }
+ }
+ },
+ getPlotLinePath: function (a, b, c, d, pos) {
+ if (pos) { // crosshairs only
+ return this.horiz ?
+ ['M', pos - 4, this.top - 6, 'L', pos + 4, this.top - 6, pos, this.top, 'Z'] :
+ ['M', this.left, pos, 'L', this.left - 6, pos + 6, this.left - 6, pos - 6, 'Z'];
+ } else {
+ return Axis.prototype.getPlotLinePath.call(this, a, b, c, d);
+ }
+ },
+
+ update: function (newOptions, redraw) {
+ each(this.series, function (series) {
+ series.isDirtyData = true; // Needed for Axis.update when choropleth colors change
+ });
+ Axis.prototype.update.call(this, newOptions, redraw);
+ if (this.legendItem) {
+ this.setLegendColor();
+ this.chart.legend.colorizeItem(this, true);
+ }
+ },
+
+ /**
+ * Get the legend item symbols for data classes
+ */
+ getDataClassLegendSymbols: function () {
+ var axis = this,
+ chart = this.chart,
+ legendItems = this.legendItems,
+ legendOptions = chart.options.legend,
+ valueDecimals = legendOptions.valueDecimals,
+ valueSuffix = legendOptions.valueSuffix || '',
+ name;
+
+ if (!legendItems.length) {
+ each(this.dataClasses, function (dataClass, i) {
+ var vis = true,
+ from = dataClass.from,
+ to = dataClass.to;
+
+ // Assemble the default name. This can be overridden by legend.options.labelFormatter
+ name = '';
+ if (from === UNDEFINED) {
+ name = '< ';
+ } else if (to === UNDEFINED) {
+ name = '> ';
+ }
+ if (from !== UNDEFINED) {
+ name += numberFormat(from, valueDecimals) + valueSuffix;
+ }
+ if (from !== UNDEFINED && to !== UNDEFINED) {
+ name += ' - ';
+ }
+ if (to !== UNDEFINED) {
+ name += numberFormat(to, valueDecimals) + valueSuffix;
+ }
+
+ // Add a mock object to the legend items
+ legendItems.push(extend({
+ chart: chart,
+ name: name,
+ options: {},
+ drawLegendSymbol: LegendSymbolMixin.drawRectangle,
+ visible: true,
+ setState: noop,
+ setVisible: function () {
+ vis = this.visible = !vis;
+ each(axis.series, function (series) {
+ each(series.points, function (point) {
+ if (point.dataClass === i) {
+ point.setVisible(vis);
+ }
+ });
+ });
+
+ chart.legend.colorizeItem(this, vis);
+ }
+ }, dataClass));
+ });
+ }
+ return legendItems;
+ },
+ name: '' // Prevents 'undefined' in legend in IE8
+});
+
+/**
+ * Handle animation of the color attributes directly
+ */
+each(['fill', 'stroke'], function (prop) {
+ HighchartsAdapter.addAnimSetter(prop, function (fx) {
+ fx.elem.attr(prop, ColorAxis.prototype.tweenColors(Color(fx.start), Color(fx.end), fx.pos));
+ });
+});
+
+/**
+ * Extend the chart getAxes method to also get the color axis
+ */
+wrap(Chart.prototype, 'getAxes', function (proceed) {
+
+ var options = this.options,
+ colorAxisOptions = options.colorAxis;
+
+ proceed.call(this);
+
+ this.colorAxis = [];
+ if (colorAxisOptions) {
+ proceed = new ColorAxis(this, colorAxisOptions); // Fake assignment for jsLint
+ }
+});
+
+
+/**
+ * Wrap the legend getAllItems method to add the color axis. This also removes the
+ * axis' own series to prevent them from showing up individually.
+ */
+wrap(Legend.prototype, 'getAllItems', function (proceed) {
+ var allItems = [],
+ colorAxis = this.chart.colorAxis[0];
+
+ if (colorAxis) {
+
+ // Data classes
+ if (colorAxis.options.dataClasses) {
+ allItems = allItems.concat(colorAxis.getDataClassLegendSymbols());
+ // Gradient legend
+ } else {
+ // Add this axis on top
+ allItems.push(colorAxis);
+ }
+
+ // Don't add the color axis' series
+ each(colorAxis.series, function (series) {
+ series.options.showInLegend = false;
+ });
+ }
+
+ return allItems.concat(proceed.call(this));
+});/**
+ * Mixin for maps and heatmaps
+ */
+var colorSeriesMixin = {
+
+ pointAttrToOptions: { // mapping between SVG attributes and the corresponding options
+ stroke: 'borderColor',
+ 'stroke-width': 'borderWidth',
+ fill: 'color',
+ dashstyle: 'dashStyle'
+ },
+ pointArrayMap: ['value'],
+ axisTypes: ['xAxis', 'yAxis', 'colorAxis'],
+ optionalAxis: 'colorAxis',
+ trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'],
+ getSymbol: noop,
+ parallelArrays: ['x', 'y', 'value'],
+ colorKey: 'value',
+
+ /**
+ * In choropleth maps, the color is a result of the value, so this needs translation too
+ */
+ translateColors: function () {
+ var series = this,
+ nullColor = this.options.nullColor,
+ colorAxis = this.colorAxis,
+ colorKey = this.colorKey;
+
+ each(this.data, function (point) {
+ var value = point[colorKey],
+ color;
+
+ color = value === null ? nullColor : (colorAxis && value !== undefined) ? colorAxis.toColor(value, point) : point.color || series.color;
+
+ if (color) {
+ point.color = color;
+ }
+ });
+ }
+};
+
+
+/**
+ * Wrap the buildText method and add the hook for add text stroke
+ */
+wrap(SVGRenderer.prototype, 'buildText', function (proceed, wrapper) {
+
+ var textStroke = wrapper.styles && wrapper.styles.HcTextStroke;
+
+ proceed.call(this, wrapper);
+
+ // Apply the text stroke
+ if (textStroke && wrapper.applyTextStroke) {
+ wrapper.applyTextStroke(textStroke);
+ }
+});
+
+/**
+ * Apply an outside text stroke to data labels, based on the custom CSS property, HcTextStroke.
+ * Consider moving this to Highcharts core, also makes sense on stacked columns etc.
+ */
+SVGRenderer.prototype.Element.prototype.applyTextStroke = function (textStroke) {
+ var elem = this.element,
+ tspans,
+ firstChild;
+
+ textStroke = textStroke.split(' ');
+ tspans = elem.getElementsByTagName('tspan');
+ firstChild = elem.firstChild;
+
+ // In order to get the right y position of the clones,
+ // copy over the y setter
+ this.ySetter = this.xSetter;
+
+ each([].slice.call(tspans), function (tspan, y) {
+ var clone;
+ if (y === 0) {
+ tspan.setAttribute('x', elem.getAttribute('x'));
+ if ((y = elem.getAttribute('y')) !== null) {
+ tspan.setAttribute('y', y);
+ }
+ }
+ clone = tspan.cloneNode(1);
+ clone.setAttribute('stroke', textStroke[1]);
+ clone.setAttribute('stroke-width', textStroke[0]);
+ clone.setAttribute('stroke-linejoin', 'round');
+ elem.insertBefore(clone, firstChild);
+ });
+};
+/**
+ * Extend the default options with map options
+ */
+defaultOptions.plotOptions.heatmap = merge(defaultOptions.plotOptions.scatter, {
+ animation: false,
+ borderWidth: 0,
+ nullColor: '#F8F8F8',
+ dataLabels: {
+ formatter: function () { // #2945
+ return this.point.value;
+ },
+ verticalAlign: 'middle',
+ crop: false,
+ overflow: false,
+ style: {
+ color: 'white',
+ fontWeight: 'bold',
+ HcTextStroke: '1px rgba(0,0,0,0.5)'
+ }
+ },
+ marker: null,
+ tooltip: {
+ pointFormat: '{point.x}, {point.y}: {point.value}<br/>'
+ },
+ states: {
+ normal: {
+ animation: true
+ },
+ hover: {
+ brightness: 0.2
+ }
+ }
+});
+
+// The Heatmap series type
+seriesTypes.heatmap = extendClass(seriesTypes.scatter, merge(colorSeriesMixin, {
+ type: 'heatmap',
+ pointArrayMap: ['y', 'value'],
+ hasPointSpecificOptions: true,
+ supportsDrilldown: true,
+ getExtremesFromAll: true,
+ init: function () {
+ seriesTypes.scatter.prototype.init.apply(this, arguments);
+ this.pointRange = this.options.colsize || 1;
+ this.yAxis.axisPointRange = this.options.rowsize || 1; // general point range
+ },
+ translate: function () {
+ var series = this,
+ options = series.options,
+ xAxis = series.xAxis,
+ yAxis = series.yAxis;
+
+ series.generatePoints();
+
+ each(series.points, function (point) {
+ var xPad = (options.colsize || 1) / 2,
+ yPad = (options.rowsize || 1) / 2,
+ x1 = Math.round(xAxis.len - xAxis.translate(point.x - xPad, 0, 1, 0, 1)),
+ x2 = Math.round(xAxis.len - xAxis.translate(point.x + xPad, 0, 1, 0, 1)),
+ y1 = Math.round(yAxis.translate(point.y - yPad, 0, 1, 0, 1)),
+ y2 = Math.round(yAxis.translate(point.y + yPad, 0, 1, 0, 1));
+
+ // Set plotX and plotY for use in K-D-Tree and more
+ point.plotX = (x1 + x2) / 2;
+ point.plotY = (y1 + y2) / 2;
+
+ point.shapeType = 'rect';
+ point.shapeArgs = {
+ x: Math.min(x1, x2),
+ y: Math.min(y1, y2),
+ width: Math.abs(x2 - x1),
+ height: Math.abs(y2 - y1)
+ };
+ });
+
+ series.translateColors();
+
+ // Make sure colors are updated on colorAxis update (#2893)
+ if (this.chart.hasRendered) {
+ each(series.points, function (point) {
+ point.shapeArgs.fill = point.options.color || point.color; // #3311
+ });
+ }
+ },
+ drawPoints: seriesTypes.column.prototype.drawPoints,
+ animate: noop,
+ getBox: noop,
+ drawLegendSymbol: LegendSymbolMixin.drawRectangle,
+
+ getExtremes: function () {
+ // Get the extremes from the value data
+ Series.prototype.getExtremes.call(this, this.valueData);
+ this.valueMin = this.dataMin;
+ this.valueMax = this.dataMax;
+
+ // Get the extremes from the y data
+ Series.prototype.getExtremes.call(this);
+ }
+
+}));
+
+
+}(Highcharts));