718 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			718 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /*
 | |
|  * heatmap.js v2.0.5 | JavaScript Heatmap Library
 | |
|  *
 | |
|  * Copyright 2008-2016 Patrick Wied <heatmapjs@patrick-wied.at> - All rights reserved.
 | |
|  * Dual licensed under MIT and Beerware license
 | |
|  *
 | |
|  * :: 2016-09-05 01:16
 | |
|  */
 | |
| ;(function (name, context, factory) {
 | |
|   // Supports UMD. AMD, CommonJS/Node.js and browser context
 | |
|   if (typeof module !== 'undefined' && module.exports) {
 | |
|     module.exports = factory()
 | |
|     // eslint-disable-next-line no-undef
 | |
|   } else if (typeof define === 'function' && define.amd) {
 | |
|     // eslint-disable-next-line no-undef
 | |
|     define(factory)
 | |
|   } else {
 | |
|     context[name] = factory()
 | |
|   }
 | |
| })('h337', this, function () {
 | |
|   // Heatmap Config stores default values and will be merged with instance config
 | |
|   var HeatmapConfig = {
 | |
|     defaultRadius: 40,
 | |
|     defaultRenderer: 'canvas2d',
 | |
|     defaultGradient: {
 | |
|       0.25: 'rgb(0,0,255)',
 | |
|       0.55: 'rgb(0,255,0)',
 | |
|       0.85: 'yellow',
 | |
|       1.0: 'rgb(255,0,0)'
 | |
|     },
 | |
|     defaultMaxOpacity: 1,
 | |
|     defaultMinOpacity: 0,
 | |
|     defaultBlur: 0.85,
 | |
|     defaultXField: 'x',
 | |
|     defaultYField: 'y',
 | |
|     defaultValueField: 'value',
 | |
|     plugins: {}
 | |
|   }
 | |
|   var Store = (function StoreClosure() {
 | |
|     var Store = function Store(config) {
 | |
|       this._coordinator = {}
 | |
|       this._data = []
 | |
|       this._radi = []
 | |
|       this._min = 10
 | |
|       this._max = 1
 | |
|       this._xField = config['xField'] || config.defaultXField
 | |
|       this._yField = config['yField'] || config.defaultYField
 | |
|       this._valueField = config['valueField'] || config.defaultValueField
 | |
| 
 | |
|       if (config['radius']) {
 | |
|         this._cfgRadius = config['radius']
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     var defaultRadius = HeatmapConfig.defaultRadius
 | |
| 
 | |
|     Store.prototype = {
 | |
|       // when forceRender = false -> called from setData, omits renderall event
 | |
|       _organiseData: function (dataPoint, forceRender) {
 | |
|         var x = dataPoint[this._xField]
 | |
|         var y = dataPoint[this._yField]
 | |
|         var radi = this._radi
 | |
|         var store = this._data
 | |
|         var max = this._max
 | |
|         var min = this._min
 | |
|         var value = dataPoint[this._valueField] || 1
 | |
|         var radius = dataPoint.radius || this._cfgRadius || defaultRadius
 | |
| 
 | |
|         if (!store[x]) {
 | |
|           store[x] = []
 | |
|           radi[x] = []
 | |
|         }
 | |
| 
 | |
|         if (!store[x][y]) {
 | |
|           store[x][y] = value
 | |
|           radi[x][y] = radius
 | |
|         } else {
 | |
|           store[x][y] += value
 | |
|         }
 | |
|         var storedVal = store[x][y]
 | |
| 
 | |
|         if (storedVal > max) {
 | |
|           if (!forceRender) {
 | |
|             this._max = storedVal
 | |
|           } else {
 | |
|             this.setDataMax(storedVal)
 | |
|           }
 | |
|           return false
 | |
|         } else if (storedVal < min) {
 | |
|           if (!forceRender) {
 | |
|             this._min = storedVal
 | |
|           } else {
 | |
|             this.setDataMin(storedVal)
 | |
|           }
 | |
|           return false
 | |
|         } else {
 | |
|           return {
 | |
|             x: x,
 | |
|             y: y,
 | |
|             value: value,
 | |
|             radius: radius,
 | |
|             min: min,
 | |
|             max: max
 | |
|           }
 | |
|         }
 | |
|       },
 | |
|       _unOrganizeData: function () {
 | |
|         var unorganizedData = []
 | |
|         var data = this._data
 | |
|         var radi = this._radi
 | |
| 
 | |
|         for (var x in data) {
 | |
|           for (var y in data[x]) {
 | |
|             unorganizedData.push({
 | |
|               x: x,
 | |
|               y: y,
 | |
|               radius: radi[x][y],
 | |
|               value: data[x][y]
 | |
|             })
 | |
|           }
 | |
|         }
 | |
|         return {
 | |
|           min: this._min,
 | |
|           max: this._max,
 | |
|           data: unorganizedData
 | |
|         }
 | |
|       },
 | |
|       _onExtremaChange: function () {
 | |
|         this._coordinator.emit('extremachange', {
 | |
|           min: this._min,
 | |
|           max: this._max
 | |
|         })
 | |
|       },
 | |
|       addData: function () {
 | |
|         if (arguments[0].length > 0) {
 | |
|           var dataArr = arguments[0]
 | |
|           var dataLen = dataArr.length
 | |
|           while (dataLen--) {
 | |
|             this.addData.call(this, dataArr[dataLen])
 | |
|           }
 | |
|         } else {
 | |
|           // add to store
 | |
|           var organisedEntry = this._organiseData(arguments[0], true)
 | |
|           if (organisedEntry) {
 | |
|             // if it's the first datapoint initialize the extremas with it
 | |
|             if (this._data.length === 0) {
 | |
|               this._min = this._max = organisedEntry.value
 | |
|             }
 | |
|             this._coordinator.emit('renderpartial', {
 | |
|               min: this._min,
 | |
|               max: this._max,
 | |
|               data: [organisedEntry]
 | |
|             })
 | |
|           }
 | |
|         }
 | |
|         return this
 | |
|       },
 | |
|       setData: function (data) {
 | |
|         var dataPoints = data.data
 | |
|         var pointsLen = dataPoints.length
 | |
| 
 | |
|         // reset data arrays
 | |
|         this._data = []
 | |
|         this._radi = []
 | |
| 
 | |
|         for (var i = 0; i < pointsLen; i++) {
 | |
|           this._organiseData(dataPoints[i], false)
 | |
|         }
 | |
|         this._max = data.max
 | |
|         this._min = data.min || 0
 | |
| 
 | |
|         this._onExtremaChange()
 | |
|         this._coordinator.emit('renderall', this._getInternalData())
 | |
|         return this
 | |
|       },
 | |
|       removeData: function () {
 | |
|         // TODO: implement
 | |
|       },
 | |
|       setDataMax: function (max) {
 | |
|         this._max = max
 | |
|         this._onExtremaChange()
 | |
|         this._coordinator.emit('renderall', this._getInternalData())
 | |
|         return this
 | |
|       },
 | |
|       setDataMin: function (min) {
 | |
|         this._min = min
 | |
|         this._onExtremaChange()
 | |
|         this._coordinator.emit('renderall', this._getInternalData())
 | |
|         return this
 | |
|       },
 | |
|       setCoordinator: function (coordinator) {
 | |
|         this._coordinator = coordinator
 | |
|       },
 | |
|       _getInternalData: function () {
 | |
|         return {
 | |
|           max: this._max,
 | |
|           min: this._min,
 | |
|           data: this._data,
 | |
|           radi: this._radi
 | |
|         }
 | |
|       },
 | |
|       getData: function () {
 | |
|         return this._unOrganizeData()
 | |
|       } /*,
 | |
| 
 | |
|         TODO: rethink.
 | |
| 
 | |
|       getValueAt: function(point) {
 | |
|         var value;
 | |
|         var radius = 100;
 | |
|         var x = point.x;
 | |
|         var y = point.y;
 | |
|         var data = this._data;
 | |
| 
 | |
|         if (data[x] && data[x][y]) {
 | |
|           return data[x][y];
 | |
|         } else {
 | |
|           var values = [];
 | |
|           // radial search for datapoints based on default radius
 | |
|           for(var distance = 1; distance < radius; distance++) {
 | |
|             var neighbors = distance * 2 +1;
 | |
|             var startX = x - distance;
 | |
|             var startY = y - distance;
 | |
| 
 | |
|             for(var i = 0; i < neighbors; i++) {
 | |
|               for (var o = 0; o < neighbors; o++) {
 | |
|                 if ((i == 0 || i == neighbors-1) || (o == 0 || o == neighbors-1)) {
 | |
|                   if (data[startY+i] && data[startY+i][startX+o]) {
 | |
|                     values.push(data[startY+i][startX+o]);
 | |
|                   }
 | |
|                 } else {
 | |
|                   continue;
 | |
|                 }
 | |
|               }
 | |
|             }
 | |
|           }
 | |
|           if (values.length > 0) {
 | |
|             return Math.max.apply(Math, values);
 | |
|           }
 | |
|         }
 | |
|         return false;
 | |
|       }*/
 | |
|     }
 | |
| 
 | |
|     return Store
 | |
|   })()
 | |
| 
 | |
|   var Canvas2dRenderer = (function Canvas2dRendererClosure() {
 | |
|     var _getColorPalette = function (config) {
 | |
|       var gradientConfig = config.gradient || config.defaultGradient
 | |
|       var paletteCanvas = document.createElement('canvas')
 | |
|       var paletteCtx = paletteCanvas.getContext('2d')
 | |
| 
 | |
|       paletteCanvas.width = 256
 | |
|       paletteCanvas.height = 1
 | |
| 
 | |
|       var gradient = paletteCtx.createLinearGradient(0, 0, 256, 1)
 | |
|       for (var key in gradientConfig) {
 | |
|         gradient.addColorStop(key, gradientConfig[key])
 | |
|       }
 | |
| 
 | |
|       paletteCtx.fillStyle = gradient
 | |
|       paletteCtx.fillRect(0, 0, 256, 1)
 | |
| 
 | |
|       return paletteCtx.getImageData(0, 0, 256, 1).data
 | |
|     }
 | |
| 
 | |
|     var _getPointTemplate = function (radius, blurFactor) {
 | |
|       var tplCanvas = document.createElement('canvas')
 | |
|       var tplCtx = tplCanvas.getContext('2d')
 | |
|       var x = radius
 | |
|       var y = radius
 | |
|       tplCanvas.width = tplCanvas.height = radius * 2
 | |
| 
 | |
|       if (blurFactor == 1) {
 | |
|         tplCtx.beginPath()
 | |
|         tplCtx.arc(x, y, radius, 0, 2 * Math.PI, false)
 | |
|         tplCtx.fillStyle = 'rgba(0,0,0,1)'
 | |
|         tplCtx.fill()
 | |
|       } else {
 | |
|         var gradient = tplCtx.createRadialGradient(
 | |
|           x,
 | |
|           y,
 | |
|           radius * blurFactor,
 | |
|           x,
 | |
|           y,
 | |
|           radius
 | |
|         )
 | |
|         gradient.addColorStop(0, 'rgba(0,0,0,1)')
 | |
|         gradient.addColorStop(1, 'rgba(0,0,0,0)')
 | |
|         tplCtx.fillStyle = gradient
 | |
|         tplCtx.fillRect(0, 0, 2 * radius, 2 * radius)
 | |
|       }
 | |
| 
 | |
|       return tplCanvas
 | |
|     }
 | |
| 
 | |
|     var _prepareData = function (data) {
 | |
|       var renderData = []
 | |
|       var min = data.min
 | |
|       var max = data.max
 | |
|       var radi = data.radi
 | |
|       var data = data.data
 | |
| 
 | |
|       var xValues = Object.keys(data)
 | |
|       var xValuesLen = xValues.length
 | |
| 
 | |
|       while (xValuesLen--) {
 | |
|         var xValue = xValues[xValuesLen]
 | |
|         var yValues = Object.keys(data[xValue])
 | |
|         var yValuesLen = yValues.length
 | |
|         while (yValuesLen--) {
 | |
|           var yValue = yValues[yValuesLen]
 | |
|           var value = data[xValue][yValue]
 | |
|           var radius = radi[xValue][yValue]
 | |
|           renderData.push({
 | |
|             x: xValue,
 | |
|             y: yValue,
 | |
|             value: value,
 | |
|             radius: radius
 | |
|           })
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       return {
 | |
|         min: min,
 | |
|         max: max,
 | |
|         data: renderData
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     function Canvas2dRenderer(config) {
 | |
|       var container = config.container
 | |
|       var shadowCanvas = (this.shadowCanvas = document.createElement('canvas'))
 | |
|       var canvas = (this.canvas =
 | |
|         config.canvas || document.createElement('canvas'))
 | |
|       var renderBoundaries = (this._renderBoundaries = [10000, 10000, 0, 0])
 | |
| 
 | |
|       var computed = getComputedStyle(config.container) || {}
 | |
| 
 | |
|       canvas.className = 'heatmap-canvas'
 | |
| 
 | |
|       this._width = canvas.width = shadowCanvas.width =
 | |
|         config.width || +computed.width.replace(/px/, '')
 | |
|       this._height = canvas.height = shadowCanvas.height =
 | |
|         config.height || +computed.height.replace(/px/, '')
 | |
| 
 | |
|       this.shadowCtx = shadowCanvas.getContext('2d')
 | |
|       this.ctx = canvas.getContext('2d')
 | |
| 
 | |
|       // @TODO:
 | |
|       // conditional wrapper
 | |
| 
 | |
|       canvas.style.cssText = shadowCanvas.style.cssText =
 | |
|         'position:absolute;left:0;top:0;'
 | |
| 
 | |
|       container.style.position = 'relative'
 | |
|       container.appendChild(canvas)
 | |
| 
 | |
|       this._palette = _getColorPalette(config)
 | |
|       this._templates = {}
 | |
| 
 | |
|       this._setStyles(config)
 | |
|     }
 | |
| 
 | |
|     Canvas2dRenderer.prototype = {
 | |
|       renderPartial: function (data) {
 | |
|         if (data.data.length > 0) {
 | |
|           this._drawAlpha(data)
 | |
|           this._colorize()
 | |
|         }
 | |
|       },
 | |
|       renderAll: function (data) {
 | |
|         // reset render boundaries
 | |
|         this._clear()
 | |
|         if (data.data.length > 0) {
 | |
|           this._drawAlpha(_prepareData(data))
 | |
|           this._colorize()
 | |
|         }
 | |
|       },
 | |
|       _updateGradient: function (config) {
 | |
|         this._palette = _getColorPalette(config)
 | |
|       },
 | |
|       updateConfig: function (config) {
 | |
|         if (config['gradient']) {
 | |
|           this._updateGradient(config)
 | |
|         }
 | |
|         this._setStyles(config)
 | |
|       },
 | |
|       setDimensions: function (width, height) {
 | |
|         this._width = width
 | |
|         this._height = height
 | |
|         this.canvas.width = this.shadowCanvas.width = width
 | |
|         this.canvas.height = this.shadowCanvas.height = height
 | |
|       },
 | |
|       _clear: function () {
 | |
|         this.shadowCtx.clearRect(0, 0, this._width, this._height)
 | |
|         this.ctx.clearRect(0, 0, this._width, this._height)
 | |
|       },
 | |
|       _setStyles: function (config) {
 | |
|         this._blur = config.blur == 0 ? 0 : config.blur || config.defaultBlur
 | |
| 
 | |
|         if (config.backgroundColor) {
 | |
|           this.canvas.style.backgroundColor = config.backgroundColor
 | |
|         }
 | |
| 
 | |
|         this._width = this.canvas.width = this.shadowCanvas.width =
 | |
|           config.width || this._width
 | |
|         this._height = this.canvas.height = this.shadowCanvas.height =
 | |
|           config.height || this._height
 | |
| 
 | |
|         this._opacity = (config.opacity || 0) * 255
 | |
|         this._maxOpacity = (config.maxOpacity || config.defaultMaxOpacity) * 255
 | |
|         this._minOpacity = (config.minOpacity || config.defaultMinOpacity) * 255
 | |
|         this._useGradientOpacity = !!config.useGradientOpacity
 | |
|       },
 | |
|       _drawAlpha: function (data) {
 | |
|         var min = (this._min = data.min)
 | |
|         var max = (this._max = data.max)
 | |
|         var data = data.data || []
 | |
|         var dataLen = data.length
 | |
|         // on a point basis?
 | |
|         var blur = 1 - this._blur
 | |
| 
 | |
|         while (dataLen--) {
 | |
|           var point = data[dataLen]
 | |
| 
 | |
|           var x = point.x
 | |
|           var y = point.y
 | |
|           var radius = point.radius
 | |
|           // if value is bigger than max
 | |
|           // use max as value
 | |
|           var value = Math.min(point.value, max)
 | |
|           var rectX = x - radius
 | |
|           var rectY = y - radius
 | |
|           var shadowCtx = this.shadowCtx
 | |
| 
 | |
|           var tpl
 | |
|           if (!this._templates[radius]) {
 | |
|             this._templates[radius] = tpl = _getPointTemplate(radius, blur)
 | |
|           } else {
 | |
|             tpl = this._templates[radius]
 | |
|           }
 | |
|           // value from minimum / value range
 | |
|           // => [0, 1]
 | |
|           var templateAlpha = (value - min) / (max - min)
 | |
|           // this fixes #176: small values are not visible because globalAlpha < .01 cannot be read from imageData
 | |
|           shadowCtx.globalAlpha = templateAlpha < 0.01 ? 0.01 : templateAlpha
 | |
| 
 | |
|           shadowCtx.drawImage(tpl, rectX, rectY)
 | |
| 
 | |
|           // update renderBoundaries
 | |
|           if (rectX < this._renderBoundaries[0]) {
 | |
|             this._renderBoundaries[0] = rectX
 | |
|           }
 | |
|           if (rectY < this._renderBoundaries[1]) {
 | |
|             this._renderBoundaries[1] = rectY
 | |
|           }
 | |
|           if (rectX + 2 * radius > this._renderBoundaries[2]) {
 | |
|             this._renderBoundaries[2] = rectX + 2 * radius
 | |
|           }
 | |
|           if (rectY + 2 * radius > this._renderBoundaries[3]) {
 | |
|             this._renderBoundaries[3] = rectY + 2 * radius
 | |
|           }
 | |
|         }
 | |
|       },
 | |
|       _colorize: function () {
 | |
|         var x = this._renderBoundaries[0]
 | |
|         var y = this._renderBoundaries[1]
 | |
|         var width = this._renderBoundaries[2] - x
 | |
|         var height = this._renderBoundaries[3] - y
 | |
|         var maxWidth = this._width
 | |
|         var maxHeight = this._height
 | |
|         var opacity = this._opacity
 | |
|         var maxOpacity = this._maxOpacity
 | |
|         var minOpacity = this._minOpacity
 | |
|         var useGradientOpacity = this._useGradientOpacity
 | |
| 
 | |
|         if (x < 0) {
 | |
|           x = 0
 | |
|         }
 | |
|         if (y < 0) {
 | |
|           y = 0
 | |
|         }
 | |
|         if (x + width > maxWidth) {
 | |
|           width = maxWidth - x
 | |
|         }
 | |
|         if (y + height > maxHeight) {
 | |
|           height = maxHeight - y
 | |
|         }
 | |
| 
 | |
|         var img = this.shadowCtx.getImageData(x, y, width, height)
 | |
|         var imgData = img.data
 | |
|         var len = imgData.length
 | |
|         var palette = this._palette
 | |
| 
 | |
|         for (var i = 3; i < len; i += 4) {
 | |
|           var alpha = imgData[i]
 | |
|           var offset = alpha * 4
 | |
| 
 | |
|           if (!offset) {
 | |
|             continue
 | |
|           }
 | |
| 
 | |
|           var finalAlpha
 | |
|           if (opacity > 0) {
 | |
|             finalAlpha = opacity
 | |
|           } else {
 | |
|             if (alpha < maxOpacity) {
 | |
|               if (alpha < minOpacity) {
 | |
|                 finalAlpha = minOpacity
 | |
|               } else {
 | |
|                 finalAlpha = alpha
 | |
|               }
 | |
|             } else {
 | |
|               finalAlpha = maxOpacity
 | |
|             }
 | |
|           }
 | |
| 
 | |
|           imgData[i - 3] = palette[offset]
 | |
|           imgData[i - 2] = palette[offset + 1]
 | |
|           imgData[i - 1] = palette[offset + 2]
 | |
|           imgData[i] = useGradientOpacity ? palette[offset + 3] : finalAlpha
 | |
|         }
 | |
| 
 | |
|         img.data = imgData
 | |
|         this.ctx.putImageData(img, x, y)
 | |
| 
 | |
|         this._renderBoundaries = [1000, 1000, 0, 0]
 | |
|       },
 | |
|       getValueAt: function (point) {
 | |
|         var value
 | |
|         var shadowCtx = this.shadowCtx
 | |
|         var img = shadowCtx.getImageData(point.x, point.y, 1, 1)
 | |
|         var data = img.data[3]
 | |
|         var max = this._max
 | |
|         var min = this._min
 | |
| 
 | |
|         value = (Math.abs(max - min) * (data / 255)) >> 0
 | |
| 
 | |
|         return value
 | |
|       },
 | |
|       getDataURL: function () {
 | |
|         return this.canvas.toDataURL()
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return Canvas2dRenderer
 | |
|   })()
 | |
| 
 | |
|   var Renderer = (function RendererClosure() {
 | |
|     var rendererFn = false
 | |
| 
 | |
|     if (HeatmapConfig['defaultRenderer'] === 'canvas2d') {
 | |
|       rendererFn = Canvas2dRenderer
 | |
|     }
 | |
| 
 | |
|     return rendererFn
 | |
|   })()
 | |
| 
 | |
|   var Util = {
 | |
|     merge: function () {
 | |
|       var merged = {}
 | |
|       var argsLen = arguments.length
 | |
|       for (var i = 0; i < argsLen; i++) {
 | |
|         var obj = arguments[i]
 | |
|         for (var key in obj) {
 | |
|           merged[key] = obj[key]
 | |
|         }
 | |
|       }
 | |
|       return merged
 | |
|     }
 | |
|   }
 | |
|   // Heatmap Constructor
 | |
|   var Heatmap = (function HeatmapClosure() {
 | |
|     var Coordinator = (function CoordinatorClosure() {
 | |
|       function Coordinator() {
 | |
|         this.cStore = {}
 | |
|       }
 | |
| 
 | |
|       Coordinator.prototype = {
 | |
|         on: function (evtName, callback, scope) {
 | |
|           var cStore = this.cStore
 | |
| 
 | |
|           if (!cStore[evtName]) {
 | |
|             cStore[evtName] = []
 | |
|           }
 | |
|           cStore[evtName].push(function (data) {
 | |
|             return callback.call(scope, data)
 | |
|           })
 | |
|         },
 | |
|         emit: function (evtName, data) {
 | |
|           var cStore = this.cStore
 | |
|           if (cStore[evtName]) {
 | |
|             var len = cStore[evtName].length
 | |
|             for (var i = 0; i < len; i++) {
 | |
|               var callback = cStore[evtName][i]
 | |
|               callback(data)
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       return Coordinator
 | |
|     })()
 | |
| 
 | |
|     var _connect = function (scope) {
 | |
|       var renderer = scope._renderer
 | |
|       var coordinator = scope._coordinator
 | |
|       var store = scope._store
 | |
| 
 | |
|       coordinator.on('renderpartial', renderer.renderPartial, renderer)
 | |
|       coordinator.on('renderall', renderer.renderAll, renderer)
 | |
|       coordinator.on('extremachange', function (data) {
 | |
|         scope._config.onExtremaChange &&
 | |
|         scope._config.onExtremaChange({
 | |
|           min: data.min,
 | |
|           max: data.max,
 | |
|           gradient:
 | |
|             scope._config['gradient'] || scope._config['defaultGradient']
 | |
|         })
 | |
|       })
 | |
|       store.setCoordinator(coordinator)
 | |
|     }
 | |
| 
 | |
|     function Heatmap() {
 | |
|       var config = (this._config = Util.merge(
 | |
|         HeatmapConfig,
 | |
|         arguments[0] || {}
 | |
|       ))
 | |
|       this._coordinator = new Coordinator()
 | |
|       if (config['plugin']) {
 | |
|         var pluginToLoad = config['plugin']
 | |
|         if (!HeatmapConfig.plugins[pluginToLoad]) {
 | |
|           throw new Error(
 | |
|             "Plugin '" +
 | |
|             pluginToLoad +
 | |
|             "' not found. Maybe it was not registered."
 | |
|           )
 | |
|         } else {
 | |
|           var plugin = HeatmapConfig.plugins[pluginToLoad]
 | |
|           // set plugin renderer and store
 | |
|           this._renderer = new plugin.renderer(config)
 | |
|           this._store = new plugin.store(config)
 | |
|         }
 | |
|       } else {
 | |
|         this._renderer = new Renderer(config)
 | |
|         this._store = new Store(config)
 | |
|       }
 | |
|       _connect(this)
 | |
|     }
 | |
| 
 | |
|     // @TODO:
 | |
|     // add API documentation
 | |
|     Heatmap.prototype = {
 | |
|       addData: function () {
 | |
|         this._store.addData.apply(this._store, arguments)
 | |
|         return this
 | |
|       },
 | |
|       removeData: function () {
 | |
|         this._store.removeData &&
 | |
|         this._store.removeData.apply(this._store, arguments)
 | |
|         return this
 | |
|       },
 | |
|       setData: function () {
 | |
|         this._store.setData.apply(this._store, arguments)
 | |
|         return this
 | |
|       },
 | |
|       setDataMax: function () {
 | |
|         this._store.setDataMax.apply(this._store, arguments)
 | |
|         return this
 | |
|       },
 | |
|       setDataMin: function () {
 | |
|         this._store.setDataMin.apply(this._store, arguments)
 | |
|         return this
 | |
|       },
 | |
|       configure: function (config) {
 | |
|         this._config = Util.merge(this._config, config)
 | |
|         this._renderer.updateConfig(this._config)
 | |
|         this._coordinator.emit('renderall', this._store._getInternalData())
 | |
|         return this
 | |
|       },
 | |
|       repaint: function () {
 | |
|         this._coordinator.emit('renderall', this._store._getInternalData())
 | |
|         return this
 | |
|       },
 | |
|       getData: function () {
 | |
|         return this._store.getData()
 | |
|       },
 | |
|       getDataURL: function () {
 | |
|         return this._renderer.getDataURL()
 | |
|       },
 | |
|       getValueAt: function (point) {
 | |
|         if (this._store.getValueAt) {
 | |
|           return this._store.getValueAt(point)
 | |
|         } else if (this._renderer.getValueAt) {
 | |
|           return this._renderer.getValueAt(point)
 | |
|         } else {
 | |
|           return null
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return Heatmap
 | |
|   })()
 | |
| 
 | |
|   // core
 | |
|   var heatmapFactory = {
 | |
|     create: function (config) {
 | |
|       return new Heatmap(config)
 | |
|     },
 | |
|     register: function (pluginKey, plugin) {
 | |
|       HeatmapConfig.plugins[pluginKey] = plugin
 | |
|     }
 | |
|   }
 | |
|   return heatmapFactory
 | |
| })
 |