diff --git a/R/highcharts-regression.R b/R/highcharts-regression.R new file mode 100644 index 00000000..8c58c239 --- /dev/null +++ b/R/highcharts-regression.R @@ -0,0 +1,47 @@ +library(ggplot2) +library(highcharter) +library(dplyr) + +data(mpg, diamonds, package = "ggplot2") + +hchart(mpg, "point", hcaes(displ, hwy, group = drv), regression = TRUE) %>% + hc_colors(c("#d35400", "#2980b9", "#2ecc71")) + + +library(quantmod) +x <- getSymbols("GOOG", auto.assign=FALSE) + +hchart(x, regression = TRUE, + regressionSettings = list(type = "loess", loessSmooth = 30)) + +highchart() %>% + hc_add_series(data = list_parse2(cars), type = "scatter", regression = TRUE, + regressionSettings = list(type = "loess", loessSmooth = 2)) + +hchart(cars, "point", hcaes(speed), regression = TRUE, + regressionSettings = list(type = "loess", loessSmooth = 0.5)) + + +ggplot(mpg, aes(displ, hwy)) + + geom_point() + + geom_smooth() + + +lm(hwy ~ displ, data = mpg) + +hchart(mpg, "point", hcaes(displ, hwy), regression = TRUE, + regressionSettings = list(type = "polynomial", order = 5, hideInLegend = TRUE)) + + +d <- sample_n(diamonds, 500) +d +hchart(d, "point", hcaes(carat, price, group = cut), + color = "transparent", + regression = TRUE, + regressionSettings = list(type = "polynomial", order = 5, hideInLegend = TRUE)) + + + +ggplot(mpg, aes(displ, hwy)) + + geom_point() + + geom_smooth(method = "lm") diff --git a/dev/download-highcharts-code.R b/dev/download-highcharts-code.R index 805bf59c..483ddc68 100644 --- a/dev/download-highcharts-code.R +++ b/dev/download-highcharts-code.R @@ -51,7 +51,8 @@ files <- c( "https://raw.githubusercontent.com/highcharts/draggable-legend/master/draggable-legend.js", "https://raw.githubusercontent.com/highcharts/export-csv/master/export-csv.js", "https://raw.githubusercontent.com/rudovjan/highcharts-tooltip-delay/master/tooltip-delay.js", - "https://raw.githubusercontent.com/blacklabel/grouped_categories/master/grouped-categories.js" + "https://raw.githubusercontent.com/blacklabel/grouped_categories/master/grouped-categories.js", + "https://raw.githubusercontent.com/streamlinesocial/highcharts-regression/master/highcharts-regression.js" ) map2( diff --git a/inst/htmlwidgets/highchart.yaml b/inst/htmlwidgets/highchart.yaml index 27a14ed2..ac6af5d4 100644 --- a/inst/htmlwidgets/highchart.yaml +++ b/inst/htmlwidgets/highchart.yaml @@ -29,6 +29,7 @@ dependencies: # - modules/accessibility.js # - modules/canvas-tools.js # - modules/boost.js + - plugins/highcharts-regression.js - plugins/draggable-points.js - plugins/export-csv.js - plugins/grouped-categories.js diff --git a/inst/htmlwidgets/lib/highcharts-5.0.6/plugins/annotations.js b/inst/htmlwidgets/lib/highcharts-5.0.6/plugins/annotations.js index 1625ad0b..ff23223d 100644 --- a/inst/htmlwidgets/lib/highcharts-5.0.6/plugins/annotations.js +++ b/inst/htmlwidgets/lib/highcharts-5.0.6/plugins/annotations.js @@ -1,1122 +1 @@ -/* global $ Highcharts document window module:true */ -(function (factory) { - if (typeof module === 'object' && module.exports) { - module.exports = factory; - } else { - factory(Highcharts); - } -}(function (H) { - 'use strict'; - // Highcharts helper methods - var UNDEFINED, - ALIGN_FACTOR, - Chart = H.Chart, - extend = H.extend, - merge = H.merge, - each = H.each, - inArray = (window.HighchartsAdapter && window.HighchartsAdapter.inArray) || H.inArray, // #52, since Highcharts 4.1.10 HighchartsAdapter is only provided by the Highcharts Standalone Framework - addEvent = H.addEvent, - removeEvent = H.removeEvent, - isOldIE = H.VMLRenderer ? true : false; - - H.ALLOWED_SHAPES = ['path', 'rect', 'circle']; - - ALIGN_FACTOR = { - top: 0, - left: 0, - center: 0.5, - middle: 0.5, - bottom: 1, - right: 1 - }; - - - H.SVGRenderer.prototype.symbols.line = function (x, y, w, h) { - var p = 2; - return [ - 'M', x + p, y + p, 'L', x + w - p, y + h - p - ]; - }; - - H.SVGRenderer.prototype.symbols.text = function (x, y, w, h) { - var p = 1; - return [ - // 'M', 0, 0, 'L', 10, 0, 'M', 5, 0, 'L', 5, 5 - 'M', x, y + p, 'L', x + w, y + p, - 'M', x + w / 2, y + p, 'L', x + w / 2, y + p + h - ]; - }; - // VML fallback - if (H.VMLRenderer) { - H.VMLRenderer.prototype.symbols.text = H.SVGRenderer.prototype.symbols.text; - H.VMLRenderer.prototype.symbols.line = H.SVGRenderer.prototype.symbols.line; - } - - - // when drawing annotation, don't zoom/select place - H.wrap(H.Pointer.prototype, 'drag', function (c, e) { - if (!this.chart.annotations || this.chart.annotations.allowZoom) { - c.call(this, e); - } - }); - - // deselect active annotation - H.wrap(H.Pointer.prototype, 'onContainerMouseDown', function (c, e) { - c.call(this, e); - if (this.chart.selectedAnnotation) { - this.chart.selectedAnnotation.events.deselect.call(this.chart.selectedAnnotation, e); - } - }); - - // utils for buttons - var utils = { - getRadius: function (e) { - var ann = this, - chart = ann.chart, - bbox = chart.container.getBoundingClientRect(), - x = e.clientX - bbox.left, - y = e.clientY - bbox.top, - xAxis = chart.xAxis[ann.options.xAxis], - yAxis = chart.yAxis[ann.options.yAxis], - dx = Math.abs(x - xAxis.toPixels(ann.options.xValue)), - dy = Math.abs(y - yAxis.toPixels(ann.options.yValue)), - radius = parseInt(Math.sqrt(dx * dx + dy * dy), 10); - ann.shape.attr({ - r: radius - }); - return radius; - }, - getRadiusAndUpdate: function (e) { - var r = utils.getRadius.call(this, e); - this.update({ - shape: { - params: { - r: r, - x: -r, - y: -r - } - } - }); - }, - getPath: function (e) { - var ann = this, - chart = ann.chart, - bbox = chart.container.getBoundingClientRect(), - x = e.clientX - bbox.left, - y = e.clientY - bbox.top, - xAxis = chart.xAxis[ann.options.xAxis], - yAxis = chart.yAxis[ann.options.yAxis], - dx = x - xAxis.toPixels(ann.options.xValue), - dy = y - yAxis.toPixels(ann.options.yValue); - - var path = ['M', 0, 0, 'L', parseInt(dx, 10), parseInt(dy, 10)]; - ann.shape.attr({ - d: path - }); - - return path; - }, - getPathAndUpdate: function (e) { - var ann = this, - chart = ann.chart, - path = utils.getPath.call(ann, e), - xAxis = chart.xAxis[ann.options.xAxis], - yAxis = chart.yAxis[ann.options.yAxis], - x = xAxis.toValue(path[4] + xAxis.toPixels(ann.options.xValue)), - y = yAxis.toValue(path[5] + yAxis.toPixels(ann.options.yValue)); - - this.update({ - xValueEnd: x, - yValueEnd: y, - shape: { - params: { - d: path - } - } - }); - }, - getRect: function (e) { - var ann = this, - chart = ann.chart, - bbox = chart.container.getBoundingClientRect(), - x = e.clientX - bbox.left, - y = e.clientY - bbox.top, - xAxis = chart.xAxis[ann.options.xAxis], - yAxis = chart.yAxis[ann.options.yAxis], - sx = xAxis.toPixels(ann.options.xValue), - sy = yAxis.toPixels(ann.options.yValue), - dx = x - sx, - dy = y - sy, - w = Math.round(dx) + 1, - h = Math.round(dy) + 1, - ret = {}; - - ret.x = w < 0 ? w : 0; - ret.width = Math.abs(w); - ret.y = h < 0 ? h : 0; - ret.height = Math.abs(h); - - ann.shape.attr({ - x: ret.x, - y: ret.y, - width: ret.width, - height: ret.height - }); - return ret; - }, - getRectAndUpdate: function (e) { - var rect = utils.getRect.call(this, e); - this.update({ - shape: { - params: rect - } - }); - }, - getText: function () { - // do nothing - }, - showInput: function (e) { - var ann = this, - chart = ann.chart, - index = chart.annotationInputIndex = chart.annotationInputIndex ? chart.annotationInputIndex : 1, - input = document.createElement('span'), - button; - - input.innerHTML = ''; - input.style.position = 'absolute'; - input.style.left = e.pageX + 'px'; - input.style.top = e.pageY + 'px'; - - document.body.appendChild(input); - input.querySelectorAll('input')[0].focus(); - button = input.querySelectorAll('button')[0]; - button.onclick = function () { - var parent = this.parentNode; - - ann.update({ - title: { - text: parent.querySelectorAll('input')[0].value - } - }); - parent.parentNode.removeChild(parent); - }; - chart.annotationInputIndex++; - } - }; - - function defaultOptions(shapeType) { - var shapeOptions, - options; - - options = { - xAxis: 0, - yAxis: 0, - shape: { - params: { - stroke: '#000000', - fill: 'rgba(0,0,0,0)', - 'stroke-width': 2 - } - }, - selectionMarker: { - 'stroke-width': 1, - stroke: 'black', - fill: 'transparent', - dashstyle: 'ShortDash', - 'shape-rendering': 'crispEdges' - } - }; - - shapeOptions = { - circle: { - params: { - x: 0, - y: 0 - } - } - }; - - if (shapeOptions[shapeType]) { - options.shape = merge(options.shape, shapeOptions[shapeType]); - } - - return options; - } - - - function defatultMainOptions() { - var buttons = [], - shapes = ['circle', 'line', 'square', 'text'], - types = ['circle', 'path', 'rect', null], - params = [{ - r: 0, - fill: 'rgba(255,0,0,0.4)', - stroke: 'black' - }, { - d: ['M', 0, 0, 'L', 10, 10], - fill: 'rgba(255,0,0,0.4)', - stroke: 'black' - }, { - width: 10, - height: 10, - fill: 'rgba(255,0,0,0.4)', - stroke: 'black' - }], - steps = [utils.getRadius, utils.getPath, utils.getRect, utils.getText], - stops = [utils.getRadiusAndUpdate, utils.getPathAndUpdate, utils.getRectAndUpdate, utils.showInput]; - - each(shapes, function (s, i) { - buttons.push({ - annotationEvents: { - step: steps[i], - stop: stops[i] - }, - annotation: { - anchorX: 'left', - anchorY: 'top', - xAxis: 0, - yAxis: 0, - shape: { - type: types[i], - params: params[i] - } - }, - symbol: { - shape: s, - size: 12, - style: { - 'stroke-width': 2, - 'stroke': 'black', - fill: 'red', - zIndex: 121 - } - }, - style: { - fill: 'black', - stroke: 'blue', - strokeWidth: 2 - }, - size: 12, - states: { - selected: { - fill: '#9BD' - }, - hover: { - fill: '#9BD' - } - } - }); - }); - - return { - enabledButtons: true, - buttons: buttons, - buttonsOffsets: [0, 0] - }; - } - - function isArray(obj) { - return Object.prototype.toString.call(obj) === '[object Array]'; - } - - function isNumber(n) { - return typeof n === 'number'; - } - - function defined(obj) { - return obj !== UNDEFINED && obj !== null; - } - - function translatePath(d, xAxis, yAxis, xOffset, yOffset) { - var len = d.length, - i = 0, - path = []; - - while (i < len) { - if (typeof d[i] === 'number' && typeof d[i + 1] === 'number') { - path[i] = xAxis.toPixels(d[i]) - xOffset; - path[i + 1] = yAxis.toPixels(d[i + 1]) - yOffset; - i += 2; - } else { - path[i] = d[i]; - i += 1; - } - } - - return path; - } - - function createGroup(chart, i, clipPath) { - var group = chart.renderer.g('annotations-group-' + i); - group.attr({ - zIndex: 7 - }); - group.add(); - group.clip(clipPath); - return group; - } - - function createClipPath(chart, y) { - var clipBox = { - x: y.left, - y: y.top, - width: y.width, - height: y.height - }; - - return chart.renderer.clipRect(clipBox); - } - - function attachEvents(chart) { - function step(e) { - var selected = chart.annotations.selected; - chart.annotations.options.buttons[selected].annotationEvents.step.call(chart.drawAnnotation, e); - } - function drag(e) { - var bbox = chart.container.getBoundingClientRect(), - clickX = e.clientX - bbox.left, - clickY = e.clientY - bbox.top; - - if (!chart.isInsidePlot(clickX - chart.plotLeft, clickY - chart.plotTop) || chart.annotations.allowZoom) { - return; - } - - var xAxis = chart.xAxis[0], - yAxis = chart.yAxis[0], - selected = chart.annotations.selected; - - var options = merge(chart.annotations.options.buttons[selected].annotation, { - xValue: xAxis.toValue(clickX), - yValue: yAxis.toValue(clickY), - allowDragX: true, - allowDragY: true - }); - - chart.addAnnotation(options); - - chart.drawAnnotation = chart.annotations.allItems[chart.annotations.allItems.length - 1]; - addEvent(document, 'mousemove', step); - } - - function drop(e) { - removeEvent(document, 'mousemove', step); - - // store annotation details - if (chart.drawAnnotation) { - var selected = chart.annotations.selected; - chart.annotations.options.buttons[selected].annotationEvents.stop.call(chart.drawAnnotation, e); - } - chart.drawAnnotation = null; - } - addEvent(chart.container, 'mousedown', drag); - addEvent(document, 'mouseup', drop); - } - - function getButtonCallback(index, chart) { - return function () { - var self = chart.annotations.buttons[index][0]; - if (self.state === 2) { - chart.annotations.selected = -1; - chart.annotations.allowZoom = true; - self.setState(0); - } else { - if (chart.annotations.selected >= 0) { - chart.annotations.buttons[chart.annotations.selected][0].setState(0); - } - chart.annotations.allowZoom = false; - chart.annotations.selected = index; - self.setState(2); - } - }; - } - - - function renderButton(chart, mainButton, i) { - var userOffset = chart.annotations.options.buttonsOffsets, - xOffset = chart.rangeSelector && chart.rangeSelector.inputGroup ? chart.rangeSelector.inputGroup.offset : 0, - renderer = chart.renderer, - symbol = mainButton.symbol, - offset = 30, - symbolSize = symbol.size, - padding = 8 / 2, // since Highcahrts 5.0, padding = 8 is hardcoded - buttonSize = mainButton.size - padding, - x = chart.plotWidth + chart.plotLeft - ((i + 1) * offset) - xOffset - userOffset[0], - y = chart.plotTop - (chart.rangeSelector ? 23 + buttonSize + padding : 0) + userOffset[1], - callback = mainButton.events && mainButton.events.click ? mainButton.events.click : getButtonCallback(i, chart), - selected = mainButton.states.selected, - hovered = mainButton.states.hover, - button, - s; - - button = renderer.button('', x, y, callback, {}, hovered, selected).attr({ width: buttonSize, height: buttonSize, zIndex: 10 }); - s = renderer.symbol( - symbol.shape, - buttonSize - symbolSize / 2 + padding, - buttonSize - symbolSize / 2 + padding, - symbolSize, - symbolSize - ).attr(symbol.style).add(button); - - button.attr(button.style).add(); - - return [button, s]; - } - - function renderButtons(chart) { - var buttons = chart.annotations.options.buttons; - - chart.annotations.buttons = chart.annotations.buttons || []; - each(buttons, function (button, i) { - chart.annotations.buttons.push(renderButton(chart, button, i)); - }); - } - - // Define annotation prototype - var Annotation = function () { // eslint-disable-line - this.init.apply(this, arguments); - }; - - Annotation.prototype = { - /* - * Initialize the annotation - */ - init: function (chart, options) { - var shapeType = options.shape && options.shape.type; - - this.chart = chart; - this.options = merge({}, defaultOptions(shapeType), options); - this.userOptions = options; - }, - - /* - * Render the annotation - */ - render: function (redraw) { - var annotation = this, - chart = this.chart, - renderer = annotation.chart.renderer, - group = annotation.group, - title = annotation.title, - shape = annotation.shape, - options = annotation.options, - titleOptions = options.title, - shapeOptions = options.shape, - allowDragX = options.allowDragX, - allowDragY = options.allowDragY, - hasEvents = annotation.hasEvents; - - function attachCustomEvents(element, events) { - if (defined(events)) { - for (var name in events) { // eslint-disable-line - (function (n) { - addEvent(element.element, n, function (e) { - events[n].call(annotation, e); - }); - })(name); - } - } - } - - if (!group) { - group = annotation.group = renderer.g(); - group.attr({ 'class': 'highcharts-annotation' }); - } - - if (!shape && shapeOptions && inArray(shapeOptions.type, H.ALLOWED_SHAPES) !== -1) { - shape = annotation.shape = shapeOptions.type === 'rect' ? renderer[options.shape.type]().attr(shapeOptions.params) : renderer[options.shape.type](shapeOptions.params); - shape.add(group); - } - - if (!title && titleOptions) { - title = annotation.title = renderer.label(titleOptions); - title.add(group); - } - if ((allowDragX || allowDragY) && !hasEvents) { - $(group.element).on('mousedown', function (e) { - annotation.events.storeAnnotation(e, annotation, chart); - annotation.events.select(e, annotation); - }); - addEvent(document, 'mouseup', function (e) { - annotation.events.releaseAnnotation(e, chart); - }); - - attachCustomEvents(group, options.events); - } else if (!hasEvents) { - $(group.element).on('mousedown', function (e) { - annotation.events.select(e, annotation); - }); - attachCustomEvents(group, options.events); - } - - this.hasEvents = true; - - group.add(chart.annotations.groups[options.yAxis]); - - // link annotations to point or series - annotation.linkObjects(); - - if (redraw !== false) { - annotation.redraw(); - } - }, - - /* - * Redraw the annotation title or shape after options update - */ - redraw: function (redraw) { - var options = this.options, - chart = this.chart, - group = this.group, - title = this.title, - shape = this.shape, - linkedTo = this.linkedObject, - xAxis = chart.xAxis[options.xAxis], - yAxis = chart.yAxis[options.yAxis], - width = options.width, - height = options.height, - anchorY = ALIGN_FACTOR[options.anchorY], - anchorX = ALIGN_FACTOR[options.anchorX], - shapeParams, - linkType, - series, - bbox, - x, - y; - - if (linkedTo) { - linkType = (linkedTo instanceof H.Point) ? 'point' : (linkedTo instanceof H.Series) ? 'series' : null; - - if (linkType === 'point') { - options.x = linkedTo.plotX + chart.plotLeft; - options.y = linkedTo.plotY + chart.plotTop; - series = linkedTo.series; - } else if (linkType === 'series') { - series = linkedTo; - } - - // #48 - series.grouping and series.stacking may reposition point.graphic - if (series.pointXOffset) { - options.x += series.pointXOffset + (linkedTo.shapeArgs.width / 2 || 0); - } - group.attr({ - visibility: series.group.attr('visibility') - }); - } - - - // Based on given options find annotation pixel position - // what is minPointOffset? Doesn't work in 4.0+ - x = (defined(options.xValue) ? xAxis.toPixels(options.xValue /* + xAxis.minPointOffset */) : options.x); - y = defined(options.yValue) ? yAxis.toPixels(options.yValue) : options.y; - if (chart.inverted && defined(options.xValue) && defined(options.yValue)) { - var tmp = x; x = y; y = tmp; - } - - if (isNaN(x) || isNaN(y) || !isNumber(x) || !isNumber(y)) { - return; - } - - - if (title) { - var attrs = options.title; - if (isOldIE) { - title.attr({ - text: attrs.text - }); - } else { - title.attr(attrs); - } - title.css(options.title.style); - } - - if (shape) { - shapeParams = extend({}, options.shape.params); - if (options.shape.units === 'values') { - var realXAxis = chart.inverted ? yAxis : xAxis; - var realYAxis = chart.inverted ? xAxis : yAxis; - - // For ordinal axis, required are x&Y values - #22 - if (defined(shapeParams.x) && shapeParams.width) { - shapeParams.width = xAxis.toPixels(shapeParams.width + shapeParams.x) - xAxis.toPixels(shapeParams.x); - shapeParams.x = xAxis.toPixels(shapeParams.x); - } else if (shapeParams.width) { - shapeParams.width = realXAxis.toPixels(shapeParams.width) - realXAxis.toPixels(0); - } else if (defined(shapeParams.x)) { - shapeParams.x = xAxis.toPixels(shapeParams.x); - } - - if (defined(shapeParams.y) && shapeParams.height) { - shapeParams.height = -yAxis.toPixels(shapeParams.height + shapeParams.y) + yAxis.toPixels(shapeParams.y); - shapeParams.y = yAxis.toPixels(shapeParams.y); - } else if (shapeParams.height) { - shapeParams.height = -realYAxis.toPixels(shapeParams.height) + realYAxis.toPixels(0); - shapeParams.height *= chart.inverted ? -1 : 1; - } else if (defined(shapeParams.y)) { - shapeParams.y = yAxis.toPixels(shapeParams.y); - } - - if (options.shape.type === 'path') { - shapeParams.d = translatePath(shapeParams.d, xAxis, yAxis, x, y); - } - } - if (defined(options.yValueEnd) && defined(options.xValueEnd)) { - shapeParams.d = shapeParams.d || options.shape.d || ['M', 0, 0, 'L', 0, 0]; - shapeParams.d[4] = xAxis.toPixels(options.xValueEnd) - xAxis.toPixels(options.xValue); - shapeParams.d[5] = yAxis.toPixels(options.yValueEnd) - yAxis.toPixels(options.yValue); - } - - // move the center of the circle to shape x/y - if (options.shape.type === 'circle') { - shapeParams.x += shapeParams.r; - shapeParams.y += shapeParams.r; - } - shape.attr(shapeParams); - } - - group.bBox = null; - - // If annotation width or height is not defined in options use bounding box size - if (!isNumber(width)) { - bbox = group.getBBox(); - width = bbox.width; - } - - if (!isNumber(height)) { - // get bbox only if it wasn't set before - if (!bbox) { - bbox = group.getBBox(); - } - - height = bbox.height; - } - // Calculate anchor point - if (!isNumber(anchorX)) { - anchorX = ALIGN_FACTOR.center; - } - - if (!isNumber(anchorY)) { - anchorY = ALIGN_FACTOR.center; - } - - // Translate group according to its dimension and anchor point - x = x - width * anchorX; - y = y - height * anchorY; - - if (this.selectionMarker) { - this.events.select({}, this); - } - - if (redraw && chart.animation && defined(group.translateX) && defined(group.translateY)) { - group.animate({ - translateX: x, - translateY: y - }); - } else { - group.translate(x, y); - } - }, - - /* - * Destroy the annotation - */ - destroy: function () { - var annotation = this, - chart = this.chart, - allItems = chart.annotations.allItems, - index = allItems.indexOf(annotation); - - chart.activeAnnotation = null; - - if (index > -1) { - allItems.splice(index, 1); - chart.options.annotations.splice(index, 1); // #33 - } - - each(['title', 'shape', 'group'], function (element) { - if (annotation[element] && annotation[element].destroy) { - annotation[element].destroy(); - annotation[element] = null; - } else if (annotation[element]) { - annotation[element].remove(); - annotation[element] = null; - } - }); - - annotation.group = annotation.title = annotation.shape = annotation.chart = annotation.options = annotation.hasEvents = null; - }, - - /* - * Show annotation, only for non-linked annotations - */ - show: function () { - if (!this.linkedObject) { - this.visible = true; - this.group.attr({ - visibility: 'visible' - }); - } - }, - - /* - * Hide annotation, only for non-linked annotations - */ - hide: function () { - if (!this.linkedObject) { - this.visible = false; - this.group.attr({ - visibility: 'hidden' - }); - } - }, - - /* - * Update the annotation with a given options - */ - update: function (options, redraw) { - var annotation = this, - chart = this.chart, - allItems = chart.annotations.allItems, - index = allItems.indexOf(annotation), - o = merge(this.options, options); - - if (index >= 0) { - chart.options.annotations[index] = o; // #33 - } - - this.options = o; - - // update link to point or series - this.linkObjects(); - - this.render(redraw); - return this; - }, - /* - * API select & deselect: - */ - select: function () { - this.events.select(null, this); - return this; - }, - deselect: function () { - this.events.deselect(null, this); - this.chart.selectedAnnotation = null; - return this; - }, - - - linkObjects: function () { - var annotation = this, - chart = annotation.chart, - linkedTo = annotation.linkedObject, - linkedId = linkedTo && (linkedTo.id || linkedTo.options.id), - options = annotation.options, - id = options.linkedTo; - - if (!defined(id)) { - annotation.linkedObject = null; - } else if (!defined(linkedTo) || id !== linkedId) { - annotation.linkedObject = chart.get(id); - } - }, - events: { - select: function (e, ann) { - var chart = ann.chart, - prevAnn = chart.selectedAnnotation, - box, - padding = 10; - - if (prevAnn && prevAnn !== ann) { - prevAnn.deselect(); - } - - if (!ann.selectionMarker) { - box = ann.group.getBBox(); - - ann.selectionMarker = chart.renderer.rect( - box.x - padding / 2, - box.y - padding / 2, - box.width + padding, - box.height + padding - ).attr(ann.options.selectionMarker); - ann.selectionMarker.add(ann.group); - } - chart.selectedAnnotation = ann; - }, - deselect: function () { - if (this.selectionMarker && this.group) { - this.selectionMarker.destroy(); - this.selectionMarker = false; - this.group.bBox = null; - } - }, - destroyAnnotation: function (event, annotation) { - annotation.destroy(); - }, - translateAnnotation: function (event, chart) { - event.stopPropagation(); - event.preventDefault(); - if (chart.activeAnnotation) { - var bbox = chart.container.getBoundingClientRect(), - clickX = event.clientX - bbox.left, - clickY = event.clientY - bbox.top; - - if (!chart.isInsidePlot(clickX - chart.plotLeft, clickY - chart.plotTop)) { - return; - } - var note = chart.activeAnnotation; - - var x = note.options.allowDragX ? event.clientX - note.startX + note.group.translateX : note.group.translateX, - y = note.options.allowDragY ? event.clientY - note.startY + note.group.translateY : note.group.translateY; - - note.transX = x; - note.transY = y; - note.group.attr({ - transform: 'translate(' + x + ',' + y + ')' - }); - note.hadMove = true; - } - }, - storeAnnotation: function (event, annotation, chart) { - if (!chart.annotationDraging) { - event.stopPropagation(); - event.preventDefault(); - } - if ((!isOldIE && event.button === 0) || (isOldIE && event.button === 1)) { - var posX = event.clientX, - posY = event.clientY; - chart.activeAnnotation = annotation; - chart.activeAnnotation.startX = posX; - chart.activeAnnotation.startY = posY; - chart.activeAnnotation.transX = 0; - chart.activeAnnotation.transY = 0; - // translateAnnotation(event); - addEvent(document, 'mousemove', function (e) { - annotation.events.translateAnnotation(e, chart); - }); - // addEvent(chart.container, 'mouseleave', releaseAnnotation); TO BE OR NOT TO BE? - } - }, - releaseAnnotation: function (event, chart) { - event.stopPropagation(); - event.preventDefault(); - if (chart.activeAnnotation && (chart.activeAnnotation.transX !== 0 || chart.activeAnnotation.transY !== 0)) { - var note = chart.activeAnnotation, - x = note.transX, - y = note.transY, - options = note.options, - xVal = options.xValue, - yVal = options.yValue, - xValEnd = options.xValueEnd, - yValEnd = options.yValueEnd, - allowDragX = options.allowDragX, - allowDragY = options.allowDragY, - xAxis = note.chart.xAxis[note.options.xAxis], - yAxis = note.chart.yAxis[note.options.yAxis], - newX = xAxis.toValue(x), - newY = yAxis.toValue(y); - - if (x !== 0 || y !== 0) { - if (allowDragX && allowDragY) { - note.update({ - xValue: defined(xVal) ? newX : null, - yValue: defined(yVal) ? newY : null, - xValueEnd: defined(xValEnd) ? xValEnd - xVal + newX : null, - yValueEnd: defined(yValEnd) ? yValEnd - yVal + newY : null, - x: defined(xVal) ? null : x, - y: defined(yVal) ? null : y - }, false); - } else if (allowDragX) { - note.update({ - xValue: defined(xVal) ? newX : null, - yValue: defined(yVal) ? yVal : null, - xValueEnd: defined(xValEnd) ? xValEnd - xVal + newX : null, - yValueEnd: defined(yValEnd) ? yValEnd : null, - x: defined(xVal) ? null : x, - y: defined(yVal) ? null : note.options.y - }, false); - } else if (allowDragY) { - note.update({ - xValue: defined(xVal) ? xVal : null, - yValue: defined(yVal) ? newY : null, - xValueEnd: defined(xValEnd) ? xValEnd : null, - yValueEnd: defined(yValEnd) ? yValEnd - yVal + newY : null, - x: defined(xVal) ? null : note.options.x, - y: defined(yVal) ? null : y - }, false); - } - } - chart.activeAnnotation = null; - chart.redraw(false); - } else { - chart.activeAnnotation = null; - } - } - } - }; - // Add annotations methods to chart prototype - extend(Chart.prototype, { - /* - * Unified method for adding annotations to the chart - */ - addAnnotation: function (options, redraw) { - var chart = this, - annotations = chart.annotations.allItems, - item, - i, - iter, - len; - - if (!isArray(options)) { - options = [options]; - } - - len = options.length; - - for (iter = 0; iter < len; iter++) { - item = new Annotation(chart, options[iter]); - i = annotations.push(item); - if (i > chart.options.annotations.length) { - chart.options.annotations.push(options[iter]); // #33 - } - item.render(redraw); - } - }, - - /* - * Redraw all annotations, method used in chart events - */ - redrawAnnotations: function () { - var chart = this, - yAxes = chart.yAxis, - yLen = yAxes.length, - ann = chart.annotations, - userOffset = ann.options.buttonsOffsets, - i = 0, - clip, y; - - - for (; i < yLen; i++) { - y = yAxes[i]; - clip = ann.clipPaths[i]; - - if (clip) { - clip.attr({ - x: y.left, - y: y.top, - width: y.width, - height: y.height - }); - } else { - var clipPath = createClipPath(chart, y); - ann.clipPaths.push(clipPath); - ann.groups.push(createGroup(chart, i, clipPath)); - } - } - - each(chart.annotations.allItems, function (annotation) { - annotation.redraw(); - }); - each(chart.annotations.buttons, function (button, j) { - var xOffset = chart.rangeSelector && chart.rangeSelector.inputGroup ? chart.rangeSelector.inputGroup.offset : 0, - x = chart.plotWidth + chart.plotLeft - ((j + 1) * 30) - xOffset - userOffset[0]; - button[0].attr({ - x: x - }); - }); - } - }); - - - // Initialize on chart load - Chart.prototype.callbacks.push(function (chart) { - var options = chart.options.annotations, - yAxes = chart.yAxis, - yLen = yAxes.length, - clipPaths = [], - groups = [], - i = 0, - y, c; - - for (; i < yLen; i++) { - y = yAxes[i]; - c = createClipPath(chart, y); - clipPaths.push(c); - groups.push(createGroup(chart, i, c)); - } - - if (!chart.annotations) { - chart.annotations = {}; - } - - if (!chart.options.annotations) { - chart.options.annotations = []; - } - - // initialize empty array for annotations - if (!chart.annotations.allItems) { - chart.annotations.allItems = []; - } - - // allow zoom or draw annotation - chart.annotations.allowZoom = true; - - // link chart object to annotations - chart.annotations.chart = chart; - - // link annotations group element to the chart - chart.annotations.groups = groups; - - // add clip path to annotations - chart.annotations.clipPaths = clipPaths; - - if (isArray(options) && options.length > 0) { - chart.addAnnotation(chart.options.annotations); - } - chart.annotations.options = merge(defatultMainOptions(), chart.options.annotationsOptions ? chart.options.annotationsOptions : {}); - - if (chart.annotations.options.enabledButtons) { - renderButtons(chart); - attachEvents(chart); - } else { - chart.annotations.buttons = []; - } - - // update annotations after chart redraw - addEvent(chart, 'redraw', function () { - chart.redrawAnnotations(); - }); - }); - - if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (searchElement) { // eslint-disable-line - if (this === null) { - throw new TypeError(); - } - var t = Object(this); - var len = t.length >>> 0; - if (len === 0) { - return -1; - } - var n = 0; - if (arguments.length > 1) { - n = Number(arguments[1]); - if (n !== n) { // shortcut for verifying if it's NaN - n = 0; - } else if (n !== 0 && n !== Infinity && n !== -Infinity) { - n = (n > 0 || -1) * Math.floor(Math.abs(n)); - } - } - if (n >= len) { - return -1; - } - var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); - for (; k < len; k++) { - if (k in t && t[k] === searchElement) { - return k; - } - } - return -1; - }; - } -})); \ No newline at end of file +!function(a){"object"==typeof module&&module.exports?module.exports=a:a(Highcharts)}(function(a){"use strict";function m(a){var b,c;return c={xAxis:0,yAxis:0,shape:{params:{stroke:"#000000",fill:"rgba(0,0,0,0)","stroke-width":2}},selectionMarker:{"stroke-width":1,stroke:"black",fill:"transparent",dashstyle:"ShortDash","shape-rendering":"crispEdges"}},b={circle:{params:{x:0,y:0}}},b[a]&&(c.shape=f(c.shape,b[a])),c}function n(){var a=[],b=["circle","line","square","text"],c=["circle","path","rect",null],d=[{r:0,fill:"rgba(255,0,0,0.4)",stroke:"black"},{d:["M",0,0,"L",10,10],fill:"rgba(255,0,0,0.4)",stroke:"black"},{width:10,height:10,fill:"rgba(255,0,0,0.4)",stroke:"black"}],e=[l.getRadius,l.getPath,l.getRect,l.getText],f=[l.getRadiusAndUpdate,l.getPathAndUpdate,l.getRectAndUpdate,l.showInput];return g(b,function(b,g){a.push({annotationEvents:{step:e[g],stop:f[g]},annotation:{anchorX:"left",anchorY:"top",xAxis:0,yAxis:0,shape:{type:c[g],params:d[g]}},symbol:{shape:b,size:12,style:{"stroke-width":2,stroke:"black",fill:"red",zIndex:121}},style:{fill:"black",stroke:"blue",strokeWidth:2},size:12,states:{selected:{fill:"#9BD"},hover:{fill:"#9BD"}}})}),{enabledButtons:!0,buttons:a,buttonsOffsets:[0,0]}}function o(a){return"[object Array]"===Object.prototype.toString.call(a)}function p(a){return"number"==typeof a}function q(a){return a!==b&&null!==a}function r(a,b,c,d,e){for(var f=a.length,g=0,h=[];g=0&&b.annotations.buttons[b.annotations.selected][0].setState(0),b.annotations.allowZoom=!1,b.annotations.selected=a,c.setState(2))}}function w(a,b,c){var q,r,d=a.annotations.options.buttonsOffsets,e=a.rangeSelector&&a.rangeSelector.inputGroup?a.rangeSelector.inputGroup.offset:0,f=a.renderer,g=b.symbol,h=30,i=g.size,j=4,k=b.size-j,l=a.plotWidth+a.plotLeft-(c+1)*h-e-d[0],m=a.plotTop-(a.rangeSelector?23+k+j:0)+d[1],n=b.events&&b.events.click?b.events.click:v(c,a),o=b.states.selected,p=b.states.hover;return q=f.button("",l,m,n,{},p,o).attr({width:k,height:k,zIndex:10}),r=f.symbol(g.shape,k-i/2+j,k-i/2+j,i,i).attr(g.style).add(q),q.attr(q.style).add(),[q,r]}function x(a){var b=a.annotations.options.buttons;a.annotations.buttons=a.annotations.buttons||[],g(b,function(b,c){a.annotations.buttons.push(w(a,b,c))})}var b,c,d=a.Chart,e=a.extend,f=a.merge,g=a.each,h=window.HighchartsAdapter&&window.HighchartsAdapter.inArray||a.inArray,i=a.addEvent,j=a.removeEvent,k=!!a.VMLRenderer;a.ALLOWED_SHAPES=["path","rect","circle"],c={top:0,left:0,center:.5,middle:.5,bottom:1,right:1},a.SVGRenderer.prototype.symbols.line=function(a,b,c,d){var e=2;return["M",a+e,b+e,"L",a+c-e,b+d-e]},a.SVGRenderer.prototype.symbols.text=function(a,b,c,d){var e=1;return["M",a,b+e,"L",a+c,b+e,"M",a+c/2,b+e,"L",a+c/2,b+e+d]},a.VMLRenderer&&(a.VMLRenderer.prototype.symbols.text=a.SVGRenderer.prototype.symbols.text,a.VMLRenderer.prototype.symbols.line=a.SVGRenderer.prototype.symbols.line),a.wrap(a.Pointer.prototype,"drag",function(a,b){this.chart.annotations&&!this.chart.annotations.allowZoom||a.call(this,b)}),a.wrap(a.Pointer.prototype,"onContainerMouseDown",function(a,b){a.call(this,b),this.chart.selectedAnnotation&&this.chart.selectedAnnotation.events.deselect.call(this.chart.selectedAnnotation,b)});var l={getRadius:function(a){var b=this,c=b.chart,d=c.container.getBoundingClientRect(),e=a.clientX-d.left,f=a.clientY-d.top,g=c.xAxis[b.options.xAxis],h=c.yAxis[b.options.yAxis],i=Math.abs(e-g.toPixels(b.options.xValue)),j=Math.abs(f-h.toPixels(b.options.yValue)),k=parseInt(Math.sqrt(i*i+j*j),10);return b.shape.attr({r:k}),k},getRadiusAndUpdate:function(a){var b=l.getRadius.call(this,a);this.update({shape:{params:{r:b,x:-b,y:-b}}})},getPath:function(a){var b=this,c=b.chart,d=c.container.getBoundingClientRect(),e=a.clientX-d.left,f=a.clientY-d.top,g=c.xAxis[b.options.xAxis],h=c.yAxis[b.options.yAxis],i=e-g.toPixels(b.options.xValue),j=f-h.toPixels(b.options.yValue),k=["M",0,0,"L",parseInt(i,10),parseInt(j,10)];return b.shape.attr({d:k}),k},getPathAndUpdate:function(a){var b=this,c=b.chart,d=l.getPath.call(b,a),e=c.xAxis[b.options.xAxis],f=c.yAxis[b.options.yAxis],g=e.toValue(d[4]+e.toPixels(b.options.xValue)),h=f.toValue(d[5]+f.toPixels(b.options.yValue));this.update({xValueEnd:g,yValueEnd:h,shape:{params:{d:d}}})},getRect:function(a){var b=this,c=b.chart,d=c.container.getBoundingClientRect(),e=a.clientX-d.left,f=a.clientY-d.top,g=c.xAxis[b.options.xAxis],h=c.yAxis[b.options.yAxis],i=g.toPixels(b.options.xValue),j=h.toPixels(b.options.yValue),k=e-i,l=f-j,m=Math.round(k)+1,n=Math.round(l)+1,o={};return o.x=m<0?m:0,o.width=Math.abs(m),o.y=n<0?n:0,o.height=Math.abs(n),b.shape.attr({x:o.x,y:o.y,width:o.width,height:o.height}),o},getRectAndUpdate:function(a){var b=l.getRect.call(this,a);this.update({shape:{params:b}})},getText:function(){},showInput:function(a){var f,b=this,c=b.chart,d=c.annotationInputIndex=c.annotationInputIndex?c.annotationInputIndex:1,e=document.createElement("span");e.innerHTML='',e.style.position="absolute",e.style.left=a.pageX+"px",e.style.top=a.pageY+"px",document.body.appendChild(e),e.querySelectorAll("input")[0].focus(),f=e.querySelectorAll("button")[0],f.onclick=function(){var a=this.parentNode;b.update({title:{text:a.querySelectorAll("input")[0].value}}),a.parentNode.removeChild(a)},c.annotationInputIndex++}},y=function(){this.init.apply(this,arguments)};y.prototype={init:function(a,b){var c=b.shape&&b.shape.type;this.chart=a,this.options=f({},m(c),b),this.userOptions=b},render:function(b){function r(a,b){if(q(b))for(var d in b)!function(d){i(a.element,d,function(a){b[d].call(c,a)})}(d)}var c=this,d=this.chart,e=c.chart.renderer,f=c.group,g=c.title,j=c.shape,k=c.options,l=k.title,m=k.shape,n=k.allowDragX,o=k.allowDragY,p=c.hasEvents;f||(f=c.group=e.g(),f.attr({class:"highcharts-annotation"})),!j&&m&&h(m.type,a.ALLOWED_SHAPES)!==-1&&(j=c.shape="rect"===m.type?e[k.shape.type]().attr(m.params):e[k.shape.type](m.params),j.add(f)),!g&&l&&(g=c.title=e.label(l),g.add(f)),!n&&!o||p?p||($(f.element).on("mousedown",function(a){c.events.select(a,c)}),r(f,k.events)):($(f.element).on("mousedown",function(a){c.events.storeAnnotation(a,c,d),c.events.select(a,c)}),i(document,"mouseup",function(a){c.events.releaseAnnotation(a,d)}),r(f,k.events)),this.hasEvents=!0,f.add(d.annotations.groups[k.yAxis]),c.linkObjects(),b!==!1&&c.redraw()},redraw:function(b){var u,v,w,x,y,z,d=this.options,f=this.chart,g=this.group,h=this.title,i=this.shape,j=this.linkedObject,l=f.xAxis[d.xAxis],m=f.yAxis[d.yAxis],n=d.width,o=d.height,s=c[d.anchorY],t=c[d.anchorX];if(j&&(v=j instanceof a.Point?"point":j instanceof a.Series?"series":null,"point"===v?(d.x=j.plotX+f.plotLeft,d.y=j.plotY+f.plotTop,w=j.series):"series"===v&&(w=j),w.pointXOffset&&(d.x+=w.pointXOffset+(j.shapeArgs.width/2||0)),g.attr({visibility:w.group.attr("visibility")})),y=q(d.xValue)?l.toPixels(d.xValue):d.x,z=q(d.yValue)?m.toPixels(d.yValue):d.y,f.inverted&&q(d.xValue)&&q(d.yValue)){var A=y;y=z,z=A}if(!isNaN(y)&&!isNaN(z)&&p(y)&&p(z)){if(h){var B=d.title;k?h.attr({text:B.text}):h.attr(B),h.css(d.title.style)}if(i){if(u=e({},d.shape.params),"values"===d.shape.units){var C=f.inverted?m:l,D=f.inverted?l:m;q(u.x)&&u.width?(u.width=l.toPixels(u.width+u.x)-l.toPixels(u.x),u.x=l.toPixels(u.x)):u.width?u.width=C.toPixels(u.width)-C.toPixels(0):q(u.x)&&(u.x=l.toPixels(u.x)),q(u.y)&&u.height?(u.height=-m.toPixels(u.height+u.y)+m.toPixels(u.y),u.y=m.toPixels(u.y)):u.height?(u.height=-D.toPixels(u.height)+D.toPixels(0),u.height*=f.inverted?-1:1):q(u.y)&&(u.y=m.toPixels(u.y)),"path"===d.shape.type&&(u.d=r(u.d,l,m,y,z))}q(d.yValueEnd)&&q(d.xValueEnd)&&(u.d=u.d||d.shape.d||["M",0,0,"L",0,0],u.d[4]=l.toPixels(d.xValueEnd)-l.toPixels(d.xValue),u.d[5]=m.toPixels(d.yValueEnd)-m.toPixels(d.yValue)),"circle"===d.shape.type&&(u.x+=u.r,u.y+=u.r),i.attr(u)}g.bBox=null,p(n)||(x=g.getBBox(),n=x.width),p(o)||(x||(x=g.getBBox()),o=x.height),p(t)||(t=c.center),p(s)||(s=c.center),y-=n*t,z-=o*s,this.selectionMarker&&this.events.select({},this),b&&f.animation&&q(g.translateX)&&q(g.translateY)?g.animate({translateX:y,translateY:z}):g.translate(y,z)}},destroy:function(){var a=this,b=this.chart,c=b.annotations.allItems,d=c.indexOf(a);b.activeAnnotation=null,d>-1&&(c.splice(d,1),b.options.annotations.splice(d,1)),g(["title","shape","group"],function(b){a[b]&&a[b].destroy?(a[b].destroy(),a[b]=null):a[b]&&(a[b].remove(),a[b]=null)}),a.group=a.title=a.shape=a.chart=a.options=a.hasEvents=null},show:function(){this.linkedObject||(this.visible=!0,this.group.attr({visibility:"visible"}))},hide:function(){this.linkedObject||(this.visible=!1,this.group.attr({visibility:"hidden"}))},update:function(a,b){var c=this,d=this.chart,e=d.annotations.allItems,g=e.indexOf(c),h=f(this.options,a);return g>=0&&(d.options.annotations[g]=h),this.options=h,this.linkObjects(),this.render(b),this},select:function(){return this.events.select(null,this),this},deselect:function(){return this.events.deselect(null,this),this.chart.selectedAnnotation=null,this},linkObjects:function(){var a=this,b=a.chart,c=a.linkedObject,d=c&&(c.id||c.options.id),e=a.options,f=e.linkedTo;q(f)?q(c)&&f===d||(a.linkedObject=b.get(f)):a.linkedObject=null},events:{select:function(a,b){var e,c=b.chart,d=c.selectedAnnotation,f=10;d&&d!==b&&d.deselect(),b.selectionMarker||(e=b.group.getBBox(),b.selectionMarker=c.renderer.rect(e.x-f/2,e.y-f/2,e.width+f,e.height+f).attr(b.options.selectionMarker),b.selectionMarker.add(b.group)),c.selectedAnnotation=b},deselect:function(){this.selectionMarker&&this.group&&(this.selectionMarker.destroy(),this.selectionMarker=!1,this.group.bBox=null)},destroyAnnotation:function(a,b){b.destroy()},translateAnnotation:function(a,b){if(a.stopPropagation(),a.preventDefault(),b.activeAnnotation){var c=b.container.getBoundingClientRect(),d=a.clientX-c.left,e=a.clientY-c.top;if(!b.isInsidePlot(d-b.plotLeft,e-b.plotTop))return;var f=b.activeAnnotation,g=f.options.allowDragX?a.clientX-f.startX+f.group.translateX:f.group.translateX,h=f.options.allowDragY?a.clientY-f.startY+f.group.translateY:f.group.translateY;f.transX=g,f.transY=h,f.group.attr({transform:"translate("+g+","+h+")"}),f.hadMove=!0}},storeAnnotation:function(a,b,c){if(c.annotationDraging||(a.stopPropagation(),a.preventDefault()),!k&&0===a.button||k&&1===a.button){var d=a.clientX,e=a.clientY;c.activeAnnotation=b,c.activeAnnotation.startX=d,c.activeAnnotation.startY=e,c.activeAnnotation.transX=0,c.activeAnnotation.transY=0,i(document,"mousemove",function(a){b.events.translateAnnotation(a,c)})}},releaseAnnotation:function(a,b){if(a.stopPropagation(),a.preventDefault(),!b.activeAnnotation||0===b.activeAnnotation.transX&&0===b.activeAnnotation.transY)b.activeAnnotation=null;else{var c=b.activeAnnotation,d=c.transX,e=c.transY,f=c.options,g=f.xValue,h=f.yValue,i=f.xValueEnd,j=f.yValueEnd,k=f.allowDragX,l=f.allowDragY,m=c.chart.xAxis[c.options.xAxis],n=c.chart.yAxis[c.options.yAxis],o=m.toValue(d),p=n.toValue(e);0===d&&0===e||(k&&l?c.update({xValue:q(g)?o:null,yValue:q(h)?p:null,xValueEnd:q(i)?i-g+o:null,yValueEnd:q(j)?j-h+p:null,x:q(g)?null:d,y:q(h)?null:e},!1):k?c.update({xValue:q(g)?o:null,yValue:q(h)?h:null,xValueEnd:q(i)?i-g+o:null,yValueEnd:q(j)?j:null,x:q(g)?null:d,y:q(h)?null:c.options.y},!1):l&&c.update({xValue:q(g)?g:null,yValue:q(h)?p:null,xValueEnd:q(i)?i:null,yValueEnd:q(j)?j-h+p:null,x:q(g)?null:c.options.x,y:q(h)?null:e},!1)),b.activeAnnotation=null,b.redraw(!1)}}}},e(d.prototype,{addAnnotation:function(a,b){var e,f,g,h,c=this,d=c.annotations.allItems;for(o(a)||(a=[a]),h=a.length,g=0;gc.options.annotations.length&&c.options.annotations.push(a[g]),e.render(b)},redrawAnnotations:function(){for(var h,i,a=this,b=a.yAxis,c=b.length,d=a.annotations,e=d.options.buttonsOffsets,f=0;f0&&a.addAnnotation(a.options.annotations),a.annotations.options=f(n(),a.options.annotationsOptions?a.options.annotationsOptions:{}),a.annotations.options.enabledButtons?(x(a),u(a)):a.annotations.buttons=[],i(a,"redraw",function(){a.redrawAnnotations()})}),Array.prototype.indexOf||(Array.prototype.indexOf=function(a){if(null===this)throw new TypeError;var b=Object(this),c=b.length>>>0;if(0===c)return-1;var d=0;if(arguments.length>1&&(d=Number(arguments[1]),d!==d?d=0:0!==d&&d!==1/0&&d!==-(1/0)&&(d=(d>0||-1)*Math.floor(Math.abs(d)))),d>=c)return-1;for(var e=d>=0?d:Math.max(c-Math.abs(d),0);e 0 && - currentX + draggedX + legend.legendWidth < chart.chartWidth && - currentY + draggedY > 0 && - currentY + draggedY + legend.legendHeight < chart.chartHeight ) { - legend.group.placed = false; // prevent animation - legend.group.align(H.extend({ - width: legend.legendWidth, - height: legend.legendHeight - }, options), true, 'spacingBox'); - legend.positionCheckboxes(); - } - if (chart.pointer.selectionMarker) { - chart.pointer.selectionMarker = chart.pointer.selectionMarker.destroy(); - } - - } - } - - function pointerUp() { - isDragging = false; - } - - if (options.draggable && title) { - - title.css({ cursor: 'move' }); - - // Mouse events - addEvent(title.element, 'mousedown', pointerDown); - addEvent(chart.container, 'mousemove', pointerMove); - addEvent(document, 'mouseup', pointerUp); - - // Touch events - addEvent(title.element, 'touchstart', pointerDown); - addEvent(chart.container, 'touchmove', pointerMove); - addEvent(document, 'touchend', pointerUp); - - } - }); -}(Highcharts)); \ No newline at end of file +!function(a){var b=a.addEvent;a.wrap(a.Chart.prototype,"init",function(c){function o(a){a=d.pointer.normalize(a),i=a.chartX,j=a.chartY,k=g.x,l=g.y,m=e.group.attr("translateX"),n=e.group.attr("translateY"),h=!0}function p(b){if(h){b=d.pointer.normalize(b);var c=b.chartX-i,f=b.chartY-j;b.preventDefault(),g.x=k+c,g.y=l+f,m+c>0&&m+c+e.legendWidth0&&n+f+e.legendHeight dragMax) { - newY = dragMax; - } - return newY; - } - - - Highcharts.Chart.prototype.callbacks.push(function (chart) { - - var container = chart.container, - dragPoint, - dragStart, - dragX, - dragY, - dragPlotX, - dragPlotY, - dragPlotHigh, - dragPlotLow, - changeLow, - newHigh, - newLow; - - /** - * Get the new values based on the drag event - */ - function getNewPos(e) { - var originalEvent = e.originalEvent || e, - pageX = originalEvent.changedTouches ? originalEvent.changedTouches[0].pageX : e.pageX, - pageY = originalEvent.changedTouches ? originalEvent.changedTouches[0].pageY : e.pageY, - series = dragPoint.series, - draggableX = series.options.draggableX && dragPoint.draggableX !== false, - draggableY = series.options.draggableY && dragPoint.draggableY !== false, - dragSensitivity = pick(series.options.dragSensitiviy, 1), - deltaX = draggableX ? dragX - pageX : 0, - deltaY = draggableY ? dragY - pageY : 0, - newPlotX = dragPlotX - deltaX, - newPlotY = dragPlotY - deltaY, - newX = dragX === undefined ? dragPoint.x : series.xAxis.toValue(newPlotX, true), - newY = dragY === undefined ? dragPoint.y : series.yAxis.toValue(newPlotY, true), - ret; - - newX = filterRange(newX, series, 'X'); - newY = filterRange(newY, series, 'Y'); - if (dragPoint.low) { - var newPlotHigh = dragPlotHigh - deltaY, - newPlotLow = dragPlotLow - deltaY; - newHigh = dragY === undefined ? dragPoint.high : series.yAxis.toValue(newPlotHigh, true); - newLow = dragY === undefined ? dragPoint.low : series.yAxis.toValue(newPlotLow, true); - newHigh = filterRange(newHigh, series, 'Y'); - newLow = filterRange(newLow, series, 'Y'); - } - if (Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)) > dragSensitivity) { - return { - x: draggableX ? newX : dragPoint.x, - y: draggableY ? newY : dragPoint.y, - high: (draggableY && !changeLow) ? newHigh : dragPoint.high, - low: (draggableY && changeLow) ? newLow : dragPoint.low, - }; - } else { - return null; - } - } - - /** - * Handler for mouseup - */ - function drop(e) { - var newPos; - if (dragPoint) { - if (e) { - newPos = getNewPos(e); - if (newPos) { - dragPoint.update(newPos); - - // Update k-d-tree immediately to prevent tooltip jump (#43) - dragPoint.series.options.kdNow = true; - dragPoint.series.buildKDTree(); - } - } - if (newPos) { - newPos.dragStart = dragStart; - dragPoint.firePointEvent('drop', newPos); - } - } - dragPoint = dragX = dragY = undefined; - } - - /** - * Handler for mousedown - */ - function mouseDown(e) { - var options, - originalEvent = e.originalEvent || e, - hoverPoint, - series; - - if ((originalEvent.target.getAttribute('class') || '').indexOf('highcharts-handle') !== -1) { - hoverPoint = originalEvent.target.point; - } - - series = chart.hoverPoint && chart.hoverPoint.series; - if (!hoverPoint && chart.hoverPoint && (!series.useDragHandle || !series.useDragHandle())) { - hoverPoint = chart.hoverPoint; - } - - if (hoverPoint) { - options = hoverPoint.series.options; - dragStart = {}; - if (options.draggableX && hoverPoint.draggableX !== false) { - dragPoint = hoverPoint; - dragX = originalEvent.changedTouches ? originalEvent.changedTouches[0].pageX : e.pageX; - dragPlotX = dragPoint.plotX; - dragStart.x = dragPoint.x; - } - - if (options.draggableY && hoverPoint.draggableY !== false) { - dragPoint = hoverPoint; - - dragY = originalEvent.changedTouches ? originalEvent.changedTouches[0].pageY : e.pageY; - dragPlotY = dragPoint.plotY + (chart.plotHeight - (dragPoint.yBottom || chart.plotHeight)); - dragStart.y = dragPoint.y; - if (dragPoint.plotHigh) { - dragPlotHigh = dragPoint.plotHigh; - dragPlotLow = dragPoint.plotLow; - changeLow = (Math.abs(dragPlotLow - (dragY - 60)) < Math.abs(dragPlotHigh - (dragY - 60))) ? true : false; - } - } - - // Disable zooming when dragging - if (dragPoint) { - chart.mouseIsDown = false; - } - } - } - - /** - * Handler for mousemove. If the mouse button is pressed, drag the element. - */ - function mouseMove(e) { - - e.preventDefault(); - - if (dragPoint) { - - var evtArgs = getNewPos(e), // Gets x and y - proceed; - - // Fire the 'drag' event with a default action to move the point. - if (evtArgs) { - evtArgs.dragStart = dragStart; - dragPoint.firePointEvent( - 'drag', - evtArgs, - function () { - - var kdTree, - series = dragPoint.series; - - proceed = true; - - dragPoint.update(evtArgs, false); - - // Hide halo while dragging (#14) - if (series.halo) { - series.halo = series.halo.destroy(); - } - - // Let the tooltip follow and reflect the drag point - if (chart.tooltip) { - chart.tooltip.refresh(chart.tooltip.shared ? [dragPoint] : dragPoint); - } - - // Stacking requires full redraw - if (series.stackKey) { - chart.redraw(); - - // Do a series redraw only. Let the k-d-tree survive the redraw in order to - // prevent tooltip flickering (#43). - } else { - - kdTree = series.kdTree; - series.redraw(); - series.kdTree = kdTree; - } - } - ); - - - // The default handler has not run because of prevented default - if (!proceed) { - drop(); - } - } - } - } - - // Kill animation on first drag when chart.animation is set to false. - chart.redraw(); - - // Add'em - addEvent(container, 'mousemove', mouseMove); - addEvent(container, 'touchmove', mouseMove); - addEvent(container, 'mousedown', mouseDown); - addEvent(container, 'touchstart', mouseDown); - addEvent(document, 'mouseup', drop); - addEvent(document, 'touchend', drop); - addEvent(container, 'mouseleave', drop); - }); - - /** - * Extend the column chart tracker by visualizing the tracker object for small points - */ - Highcharts.seriesTypes.column.prototype.useDragHandle = function () { - var is3d = this.chart.is3d && this.chart.is3d(); - return !is3d; - }; - - Highcharts.seriesTypes.column.prototype.dragHandlePath = function (shapeArgs, strokeW) { - var x1 = shapeArgs.x, - y = shapeArgs.y, - x2 = shapeArgs.x + shapeArgs.width; - - return [ - 'M', x1, y + 6 * strokeW, - 'L', x1, y, - 'L', x2, y, - 'L', x2, y + 2 * strokeW, - 'L', x1, y + 2 * strokeW, - 'L', x2, y + 2 * strokeW, - 'L', x2, y + 4 * strokeW, - 'L', x1, y + 4 * strokeW, - 'L', x2, y + 4 * strokeW, - 'L', x2, y + 6 * strokeW - ]; - }; - - Highcharts.wrap(Highcharts.seriesTypes.column.prototype, 'drawTracker', function (proceed) { - var series = this, - options = series.options, - strokeW = series.borderWidth || 0; - - proceed.apply(series); - - if (this.useDragHandle() && (options.draggableX || options.draggableY)) { - - each(series.points, function (point) { - - var path = (options.dragHandlePath || series.dragHandlePath)(point.shapeArgs, strokeW); - - if (!point.handle) { - point.handle = series.chart.renderer.path(path) - .attr({ - fill: options.dragHandleFill || 'rgba(0,0,0,0.5)', - 'class': 'highcharts-handle', - 'stroke-width': strokeW, - 'stroke': options.dragHandleStroke || options.borderColor || 1 - }) - .css({ - cursor: 'ns-resize' - }) - .add(series.group); - - point.handle.element.point = point; - } else { - point.handle.attr({d: path}); - } - }); - } - }); - -})); +!function(a){"object"==typeof module&&module.exports?module.exports=a:a(Highcharts)}(function(a){"use strict";function e(a,b,c){var e=b.options,f=d(e["dragMin"+c],void 0),g=d(e["dragMax"+c],void 0),h=d(e["dragPrecision"+c],void 0);return isNaN(h)||(a=Math.round(a/h)*h),ag&&(a=g),a}var b=a.addEvent,c=a.each,d=a.pick;a.Chart.prototype.callbacks.push(function(a){function q(a){var b=a.originalEvent||a,c=b.changedTouches?b.changedTouches[0].pageX:a.pageX,g=b.changedTouches?b.changedTouches[0].pageY:a.pageY,q=f.series,r=q.options.draggableX&&f.draggableX!==!1,s=q.options.draggableY&&f.draggableY!==!1,t=d(q.options.dragSensitiviy,1),u=r?h-c:0,v=s?i-g:0,w=j-u,x=k-v,y=void 0===h?f.x:q.xAxis.toValue(w,!0),z=void 0===i?f.y:q.yAxis.toValue(x,!0);if(y=e(y,q,"X"),z=e(z,q,"Y"),f.low){var B=l-v,C=m-v;o=void 0===i?f.high:q.yAxis.toValue(B,!0),p=void 0===i?f.low:q.yAxis.toValue(C,!0),o=e(o,q,"Y"),p=e(p,q,"Y")}return Math.sqrt(Math.pow(u,2)+Math.pow(v,2))>t?{x:r?y:f.x,y:s?z:f.y,high:s&&!n?o:f.high,low:s&&n?p:f.low}:null}function r(a){var b;f&&(a&&(b=q(a),b&&(f.update(b),f.series.options.kdNow=!0,f.series.buildKDTree())),b&&(b.dragStart=g,f.firePointEvent("drop",b))),f=h=i=void 0}function s(b){var c,e,o,d=b.originalEvent||b;(d.target.getAttribute("class")||"").indexOf("highcharts-handle")!==-1&&(e=d.target.point),o=a.hoverPoint&&a.hoverPoint.series,e||!a.hoverPoint||o.useDragHandle&&o.useDragHandle()||(e=a.hoverPoint),e&&(c=e.series.options,g={},c.draggableX&&e.draggableX!==!1&&(f=e,h=d.changedTouches?d.changedTouches[0].pageX:b.pageX,j=f.plotX,g.x=f.x),c.draggableY&&e.draggableY!==!1&&(f=e,i=d.changedTouches?d.changedTouches[0].pageY:b.pageY,k=f.plotY+(a.plotHeight-(f.yBottom||a.plotHeight)),g.y=f.y,f.plotHigh&&(l=f.plotHigh,m=f.plotLow,n=Math.abs(m-(i-60)) 1 ? ' ('+ key + ')' : ''); - }; - - // Loop the series and index values - i = 0; - each(this.series, function (series) { - var keys = series.options.keys, - pointArrayMap = keys || series.pointArrayMap || ['y'], - valueCount = pointArrayMap.length, - requireSorting = series.requireSorting, - categoryMap = {}, - j; - - // Map the categories for value axes - each(pointArrayMap, function (prop) { - categoryMap[prop] = (series[prop + 'Axis'] && series[prop + 'Axis'].categories) || []; - }); - - if (series.options.includeInCSVExport !== false && series.visible !== false) { // #55 - j = 0; - while (j < valueCount) { - names.push(columnHeaderFormatter(series, pointArrayMap[j], pointArrayMap.length)); - j = j + 1; - } - - each(series.points, function (point, pIdx) { - var key = requireSorting ? point.x : pIdx, - prop, - val; - - j = 0; - - if (!rows[key]) { - rows[key] = []; - } - rows[key].x = point.x; - - // Pies, funnels, geo maps etc. use point name in X row - if (!series.xAxis || series.exportKey === 'name') { - rows[key].name = point.name; - } - - while (j < valueCount) { - prop = pointArrayMap[j]; // y, z etc - val = point[prop]; - rows[key][i + j] = pick(categoryMap[prop][val], val); // Pick a Y axis category if present - j = j + 1; - } - - }); - i = i + j; - } - }); - - // Make a sortable array - for (x in rows) { - if (rows.hasOwnProperty(x)) { - rowArr.push(rows[x]); - } - } - // Sort it by X values - rowArr.sort(function (a, b) { - return a.x - b.x; - }); - - // Add header row - xTitle = columnHeaderFormatter(xAxis); - dataRows = [[xTitle].concat(names)]; - - // Add the category column - each(rowArr, function (row) { - - var category = row.name; - if (!category) { - if (xAxis.isDatetimeAxis) { - if (row.x instanceof Date) { - row.x = row.x.getTime(); - } - category = Highcharts.dateFormat(dateFormat, row.x); - } else if (xAxis.categories) { - category = pick(xAxis.names[row.x], xAxis.categories[row.x], row.x) - } else { - category = row.x; - } - } - - // Add the X/date/category - row.unshift(category); - dataRows.push(row); - }); - - return dataRows; - }; - - /** - * Get a CSV string - */ - Highcharts.Chart.prototype.getCSV = function (useLocalDecimalPoint) { - var csv = '', - rows = this.getDataRows(), - options = (this.options.exporting || {}).csv || {}, - itemDelimiter = options.itemDelimiter || ',', // use ';' for direct import to Excel - lineDelimiter = options.lineDelimiter || '\n'; // '\n' isn't working with the js csv data extraction - - // Transform the rows to CSV - each(rows, function (row, i) { - var val = '', - j = row.length, - n = useLocalDecimalPoint ? (1.1).toLocaleString()[1] : '.'; - while (j--) { - val = row[j]; - if (typeof val === "string") { - val = '"' + val + '"'; - } - if (typeof val === 'number') { - if (n === ',') { - val = val.toString().replace(".", ","); - } - } - row[j] = val; - } - // Add the values - csv += row.join(itemDelimiter); - - // Add the line delimiter - if (i < rows.length - 1) { - csv += lineDelimiter; - } - }); - return csv; - }; - - /** - * Build a HTML table with the data - */ - Highcharts.Chart.prototype.getTable = function (useLocalDecimalPoint) { - var html = '', - rows = this.getDataRows(); - - // Transform the rows to HTML - each(rows, function (row, i) { - var tag = i ? 'td' : 'th', - val, - j, - n = useLocalDecimalPoint ? (1.1).toLocaleString()[1] : '.'; - - html += ''; - for (j = 0; j < row.length; j = j + 1) { - val = row[j]; - // Add the cell - if (typeof val === 'number') { - val = val.toString(); - if (n === ',') { - val = val.replace('.', n); - } - html += '<' + tag + ' class="number">' + val + ''; - - } else { - html += '<' + tag + '>' + (val === undefined ? '' : val) + ''; - } - } - - html += ''; - }); - html += '
'; - return html; - }; - - function getContent(chart, href, extension, content, MIME) { - var a, - blobObject, - name, - options = (chart.options.exporting || {}).csv || {}, - url = options.url || 'http://www.highcharts.com/studies/csv-export/download.php'; - - if (chart.options.exporting.filename) { - name = chart.options.exporting.filename; - } else if (chart.title) { - name = chart.title.textStr.replace(/ /g, '-').toLowerCase(); - } else { - name = 'chart'; - } - - // MS specific. Check this first because of bug with Edge (#76) - if (window.Blob && window.navigator.msSaveOrOpenBlob) { - // Falls to msSaveOrOpenBlob if download attribute is not supported - blobObject = new Blob([content]); - window.navigator.msSaveOrOpenBlob(blobObject, name + '.' + extension); - - // Download attribute supported - } else if (downloadAttrSupported) { - a = document.createElement('a'); - a.href = href; - a.target = '_blank'; - a.download = name + '.' + extension; - chart.container.append(a); // #111 - a.click(); - a.remove(); - - } else { - // Fall back to server side handling - Highcharts.post(url, { - data: content, - type: MIME, - extension: extension - }); - } - } - - /** - * Call this on click of 'Download CSV' button - */ - Highcharts.Chart.prototype.downloadCSV = function () { - var csv = this.getCSV(true); - getContent( - this, - 'data:text/csv,\uFEFF' + csv.replace(/\n/g, '%0A'), - 'csv', - csv, - 'text/csv' - ); - }; - - /** - * Call this on click of 'Download XLS' button - */ - Highcharts.Chart.prototype.downloadXLS = function () { - var uri = 'data:application/vnd.ms-excel;base64,', - template = '' + - '' + - '' + - '' + - '' + - '' + - this.getTable(true) + - '', - base64 = function (s) { - return window.btoa(unescape(encodeURIComponent(s))); // #50 - }; - getContent( - this, - uri + base64(template), - 'xls', - template, - 'application/vnd.ms-excel' - ); - }; - - /** - * View the data in a table below the chart - */ - Highcharts.Chart.prototype.viewData = function () { - if (!this.insertedTable) { - var div = document.createElement('div'); - div.className = 'highcharts-data-table'; - // Insert after the chart container - this.renderTo.parentNode.insertBefore(div, this.renderTo.nextSibling); - div.innerHTML = this.getTable(); - this.insertedTable = true; - } - }; - - - // Add "Download CSV" to the exporting menu. Use download attribute if supported, else - // run a simple PHP script that returns a file. The source code for the PHP script can be viewed at - // https://raw.github.com/highslide-software/highcharts.com/master/studies/csv-export/csv.php - if (Highcharts.getOptions().exporting) { - Highcharts.getOptions().exporting.buttons.contextButton.menuItems.push({ - textKey: 'downloadCSV', - onclick: function () { this.downloadCSV(); } - }, { - textKey: 'downloadXLS', - onclick: function () { this.downloadXLS(); } - }, { - textKey: 'viewData', - onclick: function () { this.viewData(); } - }); - } - - // Series specific - if (seriesTypes.map) { - seriesTypes.map.prototype.exportKey = 'name'; - } - if (seriesTypes.mapbubble) { - seriesTypes.mapbubble.prototype.exportKey = 'name'; - } - -}); +!function(a){"object"==typeof module&&module.exports?module.exports=a:a(Highcharts)}(function(a){"use strict";function f(b,c,d,f,g){var h,i,j,k=(b.options.exporting||{}).csv||{},l=k.url||"http://www.highcharts.com/studies/csv-export/download.php";j=b.options.exporting.filename?b.options.exporting.filename:b.title?b.title.textStr.replace(/ /g,"-").toLowerCase():"chart",window.Blob&&window.navigator.msSaveOrOpenBlob?(i=new Blob([f]),window.navigator.msSaveOrOpenBlob(i,j+"."+d)):e?(h=document.createElement("a"),h.href=c,h.target="_blank",h.download=j+"."+d,b.container.append(h),h.click(),h.remove()):a.post(l,{data:f,type:g,extension:d})}var b=a.each,c=a.pick,d=a.seriesTypes,e=void 0!==document.createElement("a").download;a.setOptions({lang:{downloadCSV:"Download CSV",downloadXLS:"Download XLS",viewData:"View data table"}}),a.Chart.prototype.getDataRows=function(){var e,i,k,l,m,d=(this.options.exporting||{}).csv||{},f=this.xAxis,g={},h=[],j=[],n=d.dateFormat||"%Y-%m-%d %H:%M:%S",o=d.columnHeaderFormatter||function(b,c,d){return b instanceof a.Axis?b.options.title&&b.options.title.text||(b.isDatetimeAxis?"DateTime":"Category"):b?b.name+(d>1?" ("+c+")":""):"Category"},p=[];k=0,b(this.series,function(d){var q,e=d.options.keys,h=e||d.pointArrayMap||["y"],i=h.length,l=d.requireSorting,m={},n=a.inArray(d.xAxis,f);if(b(h,function(a){m[a]=d[a+"Axis"]&&d[a+"Axis"].categories||[]}),d.options.includeInCSVExport!==!1&&d.visible!==!1){for(a.find(p,function(a){return a[0]===n})||p.push([n,k]),q=0;q",g=0;g'+f+""):c+="<"+e+">"+(void 0===f?"":f)+"";c+="",d||(c+="")}),c+=""},a.Chart.prototype.downloadCSV=function(){var a=this.getCSV(!0);f(this,"data:text/csv,\ufeff"+encodeURIComponent(a),"csv",a,"text/csv")},a.Chart.prototype.downloadXLS=function(){var a="data:application/vnd.ms-excel;base64,",b=''+this.getTable(!0)+"",c=function(a){return window.btoa(unescape(encodeURIComponent(a)))};f(this,a+c(b),"xls",b,"application/vnd.ms-excel")},a.Chart.prototype.viewData=function(){this.dataTableDiv||(this.dataTableDiv=document.createElement("div"),this.dataTableDiv.className="highcharts-data-table",this.renderTo.parentNode.insertBefore(this.dataTableDiv,this.renderTo.nextSibling)),this.dataTableDiv.innerHTML=this.getTable()},a.getOptions().exporting&&a.getOptions().exporting.buttons.contextButton.menuItems.push({textKey:"downloadCSV",onclick:function(){this.downloadCSV()}},{textKey:"downloadXLS",onclick:function(){this.downloadXLS()}},{textKey:"viewData",onclick:function(){this.viewData()}}),d.map&&(d.map.prototype.exportKey="name"),d.mapbubble&&(d.mapbubble.prototype.exportKey="name"),d.treemap&&(d.treemap.prototype.exportKey="name")}); \ No newline at end of file diff --git a/inst/htmlwidgets/lib/highcharts-5.0.6/plugins/grouped-categories.js b/inst/htmlwidgets/lib/highcharts-5.0.6/plugins/grouped-categories.js index 43e2a1e7..003599c0 100644 --- a/inst/htmlwidgets/lib/highcharts-5.0.6/plugins/grouped-categories.js +++ b/inst/htmlwidgets/lib/highcharts-5.0.6/plugins/grouped-categories.js @@ -1,581 +1 @@ -/* global Highcharts module window:true */ -(function (factory) { - if (typeof module === 'object' && module.exports) { - module.exports = factory; - } else { - factory(Highcharts); - } -}(function (HC) { - 'use strict'; - /** - * Grouped Categories v1.1.0 (2016-06-21) - * - * (c) 2012-2016 Black Label - * - * License: Creative Commons Attribution (CC) - */ - - /* jshint expr:true, boss:true */ - var UNDEFINED = void 0, - mathRound = Math.round, - mathMin = Math.min, - mathMax = Math.max, - merge = HC.merge, - pick = HC.pick, - each = HC.each, - // #74, since Highcharts 4.1.10 HighchartsAdapter is only provided by the Highcharts Standalone Framework - inArray = (window.HighchartsAdapter && window.HighchartsAdapter.inArray) || HC.inArray, - - // cache prototypes - axisProto = HC.Axis.prototype, - tickProto = HC.Tick.prototype, - - // cache original methods - protoAxisInit = axisProto.init, - protoAxisRender = axisProto.render, - protoAxisSetCategories = axisProto.setCategories, - protoTickGetLabelSize = tickProto.getLabelSize, - protoTickAddLabel = tickProto.addLabel, - protoTickDestroy = tickProto.destroy, - protoTickRender = tickProto.render; - - function deepClone(thing) { - return JSON.parse(JSON.stringify(thing)); - } - - function Category(obj, parent) { - this.userOptions = deepClone(obj); - this.name = obj.name || obj; - this.parent = parent; - - return this; - } - - Category.prototype.toString = function () { - var parts = [], - cat = this; - - while (cat) { - parts.push(cat.name); - cat = cat.parent; - } - - return parts.join(', '); - }; - - // returns sum of an array - function sum(arr) { - var l = arr.length, - x = 0; - - while (l--) { - x += arr[l]; - } - - return x; - } - - // Adds category leaf to array - function addLeaf(out, cat, parent) { - out.unshift(new Category(cat, parent)); - - while (parent) { - parent.leaves = parent.leaves ? (parent.leaves + 1) : 1; - parent = parent.parent; - } - } - - // Builds reverse category tree - function buildTree(cats, out, options, parent, depth) { - var len = cats.length, - cat; - - depth = depth ? depth : 0; - options.depth = options.depth ? options.depth : 0; - - while (len--) { - cat = cats[len]; - - if (cat.categories) { - if (parent) { - cat.parent = parent; - } - buildTree(cat.categories, out, options, cat, depth + 1); - } else { - addLeaf(out, cat, parent); - } - } - options.depth = mathMax(options.depth, depth); - } - - // Pushes part of grid to path - function addGridPart(path, d, width) { - // Based on crispLine from HC (#65) - if (d[0] === d[2]) { - d[0] = d[2] = mathRound(d[0]) - (width % 2 / 2); - } - if (d[1] === d[3]) { - d[1] = d[3] = mathRound(d[1]) + (width % 2 / 2); - } - - path.push( - 'M', - d[0], d[1], - 'L', - d[2], d[3] - ); - } - - // Returns tick position - function tickPosition(tick, pos) { - return tick.getPosition(tick.axis.horiz, pos, tick.axis.tickmarkOffset); - } - - function walk(arr, key, fn) { - var l = arr.length, - children; - - while (l--) { - children = arr[l][key]; - - if (children) { - walk(children, key, fn); - } - fn(arr[l]); - } - } - - // - // Axis prototype - // - - axisProto.init = function (chart, options) { - // default behaviour - protoAxisInit.call(this, chart, options); - - if (typeof options === 'object' && options.categories) { - this.setupGroups(options); - } - }; - - // setup required axis options - axisProto.setupGroups = function (options) { - var categories, - reverseTree = [], - stats = {}; - - categories = deepClone(options.categories); - - // build categories tree - buildTree(categories, reverseTree, stats); - - // set axis properties - this.categoriesTree = categories; - this.categories = reverseTree; - this.isGrouped = stats.depth !== 0; - this.labelsDepth = stats.depth; - this.labelsSizes = []; - this.labelsGridPath = []; - this.tickLength = options.tickLength || this.tickLength || null; - // #66: tickWidth for x axis defaults to 1, for y to 0 - this.tickWidth = pick(options.tickWidth, this.isXAxis ? 1 : 0); - this.directionFactor = [-1, 1, 1, -1][this.side]; - - this.options.lineWidth = pick(options.lineWidth, 1); - }; - - - axisProto.render = function () { - // clear grid path - if (this.isGrouped) { - this.labelsGridPath = []; - } - - // cache original tick length - if (this.originalTickLength === UNDEFINED) { - this.originalTickLength = this.options.tickLength; - } - - // use default tickLength for not-grouped axis - // and generate grid on grouped axes, - // use tiny number to force highcharts to hide tick - this.options.tickLength = this.isGrouped ? 0.001 : this.originalTickLength; - - protoAxisRender.call(this); - - if (!this.isGrouped) { - if (this.labelsGrid) { - this.labelsGrid.attr({ - visibility: 'hidden' - }); - } - return false; - } - - var axis = this, - options = axis.options, - top = axis.top, - left = axis.left, - right = left + axis.width, - bottom = top + axis.height, - visible = axis.hasVisibleSeries || axis.hasData, - depth = axis.labelsDepth, - grid = axis.labelsGrid, - horiz = axis.horiz, - d = axis.labelsGridPath, - i = options.drawHorizontalBorders === false ? (depth + 1) : 0, - offset = axis.opposite ? (horiz ? top : right) : (horiz ? bottom : left), - tickWidth = axis.tickWidth, - part; - - if (axis.userTickLength) { - depth -= 1; - } - - // render grid path for the first time - if (!grid) { - grid = axis.labelsGrid = axis.chart.renderer.path() - .attr({ - // #58: use tickWidth/tickColor instead of lineWidth/lineColor: - strokeWidth: tickWidth, // < 4.0.3 - 'stroke-width': tickWidth, // 4.0.3+ #30 - stroke: options.tickColor - }) - .add(axis.axisGroup); - } - - // go through every level and draw horizontal grid line - while (i <= depth) { - offset += axis.groupSize(i); - - part = horiz ? - [left, offset, right, offset] : - [offset, top, offset, bottom]; - - addGridPart(d, part, tickWidth); - i++; - } - - // draw grid path - grid.attr({ - d: d, - visibility: visible ? 'visible' : 'hidden' - }); - - axis.labelGroup.attr({ - visibility: visible ? 'visible' : 'hidden' - }); - - - walk(axis.categoriesTree, 'categories', function (group) { - var tick = group.tick; - - if (!tick) { - return false; - } - if (tick.startAt + tick.leaves - 1 < axis.min || tick.startAt > axis.max) { - tick.label.hide(); - tick.destroyed = 0; - } else { - tick.label.attr({ - visibility: visible ? 'visible' : 'hidden' - }); - } - return true; - }); - return true; - }; - - axisProto.setCategories = function (newCategories, doRedraw) { - if (this.categories) { - this.cleanGroups(); - } - this.setupGroups({ - categories: newCategories - }); - this.categories = this.userOptions.categories = newCategories; - protoAxisSetCategories.call(this, this.categories, doRedraw); - }; - - // cleans old categories - axisProto.cleanGroups = function () { - var ticks = this.ticks, - n; - - for (n in ticks) { - if (ticks[n].parent) { - delete ticks[n].parent; - } - } - walk(this.categoriesTree, 'categories', function (group) { - var tick = group.tick; - - if (!tick) { - return false; - } - tick.label.destroy(); - - each(tick, function (v, i) { - delete tick[i]; - }); - delete group.tick; - - return true; - }); - this.labelsGrid = null; - }; - - // keeps size of each categories level - axisProto.groupSize = function (level, position) { - var positions = this.labelsSizes, - direction = this.directionFactor, - groupedOptions = this.options.labels.groupedOptions ? this.options.labels.groupedOptions[level - 1] : false, - userXY = 0; - - if (groupedOptions) { - if (direction === -1) { - userXY = groupedOptions.x ? groupedOptions.x : 0; - } else { - userXY = groupedOptions.y ? groupedOptions.y : 0; - } - } - - if (position !== UNDEFINED) { - positions[level] = mathMax(positions[level] || 0, position + 10 + Math.abs(userXY)); - } - - if (level === true) { - return sum(positions) * direction; - } else if (positions[level]) { - return positions[level] * direction; - } - - return 0; - }; - - // - // Tick prototype - // - - // Override methods prototypes - tickProto.addLabel = function () { - var category; - - protoTickAddLabel.call(this); - - if (!this.axis.categories || !(category = this.axis.categories[this.pos])) { - return false; - } - - // set label text - but applied after formatter #46 - if (this.label) { - this.label.attr('text', this.axis.labelFormatter.call({ - axis: this.axis, - chart: this.axis.chart, - isFirst: this.isFirst, - isLast: this.isLast, - value: category.name - })); - } - - // create elements for parent categories - if (this.axis.isGrouped && this.axis.options.labels.enabled) { - this.addGroupedLabels(category); - } - return true; - }; - - // render ancestor label - tickProto.addGroupedLabels = function (category) { - var tick = this, - axis = this.axis, - chart = axis.chart, - options = axis.options.labels, - useHTML = options.useHTML, - css = options.style, - userAttr = options.groupedOptions, - attr = { - align: 'center', - rotation: options.rotation, - x: 0, - y: 0 - }, - size = axis.horiz ? 'height' : 'width', - depth = 0, - label; - - - while (tick) { - if (depth > 0 && !category.tick) { - // render label element - this.value = category.name; - var name = options.formatter ? options.formatter.call(this, category) : category.name, - hasOptions = userAttr && userAttr[depth - 1], - mergedAttrs = hasOptions ? merge(attr, userAttr[depth - 1]) : attr, - mergedCSS = hasOptions && userAttr[depth - 1].style ? merge(css, userAttr[depth - 1].style) : css; - - // #63: style is passed in CSS and not as an attribute - delete mergedAttrs.style; - - label = chart.renderer.text(name, 0, 0, useHTML) - .attr(mergedAttrs) - .css(mergedCSS) - .add(axis.labelGroup); - - // tick properties - tick.startAt = this.pos; - tick.childCount = category.categories.length; - tick.leaves = category.leaves; - tick.visible = this.childCount; - tick.label = label; - tick.labelOffsets = { - x: mergedAttrs.x, - y: mergedAttrs.y - }; - - // link tick with category - category.tick = tick; - } - - // set level size - axis.groupSize(depth, tick.label.getBBox()[size]); - - // go up to the parent category - category = category.parent; - - if (category) { - tick = tick.parent = category.tick || {}; - } else { - tick = null; - } - - depth++; - } - }; - - // set labels position & render categories grid - tickProto.render = function (index, old, opacity) { - protoTickRender.call(this, index, old, opacity); - - var treeCat = this.axis.categories[this.pos]; - - if (!this.axis.isGrouped || !treeCat || this.pos > this.axis.max) { - return; - } - - var tick = this, - group = tick, - axis = tick.axis, - tickPos = tick.pos, - isFirst = tick.isFirst, - max = axis.max, - min = axis.min, - horiz = axis.horiz, - grid = axis.labelsGridPath, - size = axis.groupSize(0), - tickWidth = axis.tickWidth, - xy = tickPosition(tick, tickPos), - start = horiz ? xy.y : xy.x, - baseLine = axis.chart.renderer.fontMetrics(axis.options.labels.style.fontSize).b, - depth = 1, - reverseCrisp = ((horiz && xy.x === axis.pos + axis.len) || (!horiz && xy.y === axis.pos)) ? -1 : 0, // adjust grid lines for edges - gridAttrs, - lvlSize, - minPos, - maxPos, - attrs, - bBox; - - // render grid for "normal" categories (first-level), render left grid line only for the first category - if (isFirst) { - gridAttrs = horiz ? - [axis.left, xy.y, axis.left, xy.y + axis.groupSize(true)] : axis.isXAxis ? - [xy.x, axis.top, xy.x + axis.groupSize(true), axis.top] : [xy.x, axis.top + axis.len, xy.x + axis.groupSize(true), axis.top + axis.len]; - - addGridPart(grid, gridAttrs, tickWidth); - } - - if (horiz && axis.left < xy.x) { - addGridPart(grid, [xy.x - reverseCrisp, xy.y, xy.x - reverseCrisp, xy.y + size], tickWidth); - } else if (!horiz && axis.top <= xy.y) { - addGridPart(grid, [xy.x, xy.y + reverseCrisp, xy.x + size, xy.y + reverseCrisp], tickWidth); - } - - size = start + size; - - function fixOffset(tCat) { - var ret = 0; - if (isFirst) { - ret = inArray(tCat.name, tCat.parent.categories); - ret = ret < 0 ? 0 : ret; - return ret; - } - return ret; - } - - - while (group.parent) { - group = group.parent; - - var fix = fixOffset(treeCat), - userX = group.labelOffsets.x, - userY = group.labelOffsets.y; - - minPos = tickPosition(tick, mathMax(group.startAt - 1, min - 1)); - maxPos = tickPosition(tick, mathMin(group.startAt + group.leaves - 1 - fix, max)); - bBox = group.label.getBBox(true); - lvlSize = axis.groupSize(depth); - // check if on the edge to adjust - reverseCrisp = ((horiz && maxPos.x === axis.pos + axis.len) || (!horiz && maxPos.y === axis.pos)) ? -1 : 0; - - attrs = horiz ? { - x: (minPos.x + maxPos.x) / 2 + userX, - y: size + lvlSize / 2 + baseLine - bBox.height / 2 - 4 + userY / 2 - } : { - x: size + lvlSize / 2 + userX, - y: (minPos.y + maxPos.y - bBox.height) / 2 + baseLine + userY - }; - - if (!isNaN(attrs.x) && !isNaN(attrs.y)) { - group.label.attr(attrs); - - if (grid) { - if (horiz && axis.left < maxPos.x) { - addGridPart(grid, [maxPos.x - reverseCrisp, size, maxPos.x - reverseCrisp, size + lvlSize], tickWidth); - } else if (!horiz && axis.top <= maxPos.y) { - addGridPart(grid, [size, maxPos.y + reverseCrisp, size + lvlSize, maxPos.y + reverseCrisp], tickWidth); - } - } - } - - size += lvlSize; - depth++; - } - }; - - tickProto.destroy = function () { - var group = this.parent; - - while (group) { - group.destroyed = group.destroyed ? (group.destroyed + 1) : 1; - group = group.parent; - } - - protoTickDestroy.call(this); - }; - - // return size of the label (height for horizontal, width for vertical axes) - tickProto.getLabelSize = function () { - if (this.axis.isGrouped === true) { - // #72, getBBox might need recalculating when chart is tall - var size = protoTickGetLabelSize.call(this) + 10, - topLabelSize = this.axis.labelsSizes[0]; - if (topLabelSize < size) { - this.axis.labelsSizes[0] = size; - } - return sum(this.axis.labelsSizes); - } - return protoTickGetLabelSize.call(this); - }; - -})); \ No newline at end of file +!function(a){"object"==typeof module&&module.exports?module.exports=a:a(Highcharts)}(function(a){"use strict";function s(a){return JSON.parse(JSON.stringify(a))}function t(a,b){return this.userOptions=s(a),this.name=a.name||a,this.parent=b,this}function u(a){for(var b=a.length,c=0;b--;)c+=a[b];return c}function v(a,b,c){for(a.unshift(new t(b,c));c;)c.leaves=c.leaves?c.leaves+1:1,c=c.parent}function w(a,b,c,d,f){var h,g=a.length;for(f=f?f:0,c.depth=c.depth?c.depth:0;g--;)h=a[g],h.categories?(d&&(h.parent=d),w(h.categories,b,c,h,f+1)):v(b,h,d);c.depth=e(c.depth,f)}function x(a,b,d){b[0]===b[2]&&(b[0]=b[2]=c(b[0])-d%2/2),b[1]===b[3]&&(b[1]=b[3]=c(b[1])+d%2/2),a.push("M",b[0],b[1],"L",b[2],b[3])}function y(a,b){return a.getPosition(a.axis.horiz,b,a.axis.tickmarkOffset)}function z(a,b,c){for(var e,d=a.length;d--;)e=a[d][b],e&&z(e,b,c),c(a[d])}var b=void 0,c=Math.round,d=Math.min,e=Math.max,f=a.merge,g=a.pick,h=a.each,i=window.HighchartsAdapter&&window.HighchartsAdapter.inArray||a.inArray,j=a.Axis.prototype,k=a.Tick.prototype,l=j.init,m=j.render,n=j.setCategories,o=k.getLabelSize,p=k.addLabel,q=k.destroy,r=k.render;t.prototype.toString=function(){for(var a=[],b=this;b;)a.push(b.name),b=b.parent;return a.join(", ")},j.init=function(a,b){l.call(this,a,b),"object"==typeof b&&b.categories&&this.setupGroups(b)},j.setupGroups=function(a){var b=s(a.categories),c=[],d={},e=this.options.labels,h=e.groupedOptions,i=e.style;w(b,c,d),this.categoriesTree=b,this.categories=c,this.isGrouped=0!==d.depth,this.labelsDepth=d.depth,this.labelsSizes=[],this.labelsGridPath=[],this.tickLength=a.tickLength||this.tickLength||null,this.tickWidth=g(a.tickWidth,this.isXAxis?1:0),this.directionFactor=[-1,1,1,-1][this.side],this.options.lineWidth=g(a.lineWidth,1),this.groupFontHeights=[];for(var j=0;j<=d.depth;j++){var k=h&&h[j-1],l=k&&h[j-1].style?f(i,h[j-1].style):i;this.groupFontHeights[j]=Math.round(.3*this.chart.renderer.fontMetrics(l?l.fontSize:0).b)}},j.render=function(){if(this.isGrouped&&(this.labelsGridPath=[]),this.originalTickLength===b&&(this.originalTickLength=this.options.tickLength),this.options.tickLength=this.isGrouped?.001:this.originalTickLength,m.call(this),!this.isGrouped)return this.labelsGrid&&this.labelsGrid.attr({visibility:"hidden"}),!1;var q,a=this,c=a.options,d=a.top,e=a.left,f=e+a.width,g=d+a.height,h=a.hasVisibleSeries||a.hasData,i=a.labelsDepth,j=a.labelsGrid,k=a.horiz,l=a.labelsGridPath,n=c.drawHorizontalBorders===!1?i+1:0,o=a.opposite?k?d:f:k?g:e,p=a.tickWidth;for(a.userTickLength&&(i-=1),j||(j=a.labelsGrid=a.chart.renderer.path().attr({strokeWidth:p,"stroke-width":p,stroke:c.tickColor||""}).add(a.axisGroup),c.tickColor&&j.addClass("highcharts-axis-line"));n<=i;)o+=a.groupSize(n),q=k?[e,o,f,o]:[o,d,o,g],x(l,q,p),n++;return j.attr({d:l,visibility:h?"visible":"hidden"}),a.labelGroup.attr({visibility:h?"visible":"hidden"}),z(a.categoriesTree,"categories",function(b){var c=b.tick;return!!c&&(c.startAt+c.leaves-1a.max?(c.label.hide(),c.destroyed=0):c.label.attr({visibility:h?"visible":"hidden"}),!0)}),!0},j.setCategories=function(a,b){this.categories&&this.cleanGroups(),this.setupGroups({categories:a}),this.categories=this.userOptions.categories=a,n.call(this,this.categories,b)},j.cleanGroups=function(){var b,a=this.ticks;for(b in a)a[b].parent&&delete a[b].parent;z(this.categoriesTree,"categories",function(a){var b=a.tick;return!!b&&(b.label.destroy(),h(b,function(a,c){delete b[c]}),delete a.tick,!0)}),this.labelsGrid=null},j.groupSize=function(a,c){var d=this.labelsSizes,f=this.directionFactor,g=!!this.options.labels.groupedOptions&&this.options.labels.groupedOptions[a-1],h=0;return g&&(h=f===-1?g.x?g.x:0:g.y?g.y:0),c!==b&&(d[a]=e(d[a]||0,c+10+Math.abs(h))),a===!0?u(d)*f:d[a]?d[a]*f:0},k.addLabel=function(){var a;return p.call(this),!(!this.axis.categories||!(a=this.axis.categories[this.pos]))&&(this.label&&this.label.attr("text",this.axis.labelFormatter.call({axis:this.axis,chart:this.axis.chart,isFirst:this.isFirst,isLast:this.isLast,value:a.name})),this.axis.isGrouped&&this.axis.options.labels.enabled&&this.addGroupedLabels(a),!0)},k.addGroupedLabels=function(a){for(var m,b=this,c=this.axis,d=c.chart,e=c.options.labels,g=e.useHTML,h=e.style,i=e.groupedOptions,j={align:"center",rotation:e.rotation,x:0,y:0},k=c.horiz?"height":"width",l=0;b;){if(l>0&&!a.tick){this.value=a.name;var n=e.formatter?e.formatter.call(this,a):a.name,o=i&&i[l-1],p=o?f(j,i[l-1]):j,q=o&&i[l-1].style?f(h,i[l-1].style):h;delete p.style,m=d.renderer.text(n,0,0,g).attr(p).css(q).add(c.labelGroup),b.startAt=this.pos,b.childCount=a.categories.length,b.leaves=a.leaves,b.visible=this.childCount,b.label=m,b.labelOffsets={x:p.x,y:p.y},a.tick=b}b&&c.groupSize(l,b.label.getBBox()[k]),a=a.parent,b=a?b.parent=a.tick||{}:null,l++}},k.render=function(a,b,c){function G(a){var b=0;return l?(b=i(a.name,a.parent.categories),b=b<0?0:b):b}r.call(this,a,b,c);var f=this.axis.categories[this.pos];if(this.axis.isGrouped&&f&&!(this.pos>this.axis.max)){var A,B,C,D,E,F,g=this,h=g,j=g.axis,k=g.pos,l=g.isFirst,m=j.max,n=j.min,o=j.horiz,p=j.labelsGridPath,q=j.groupSize(0),s=j.tickWidth,t=y(g,k),u=o?t.y:t.x,v=j.chart.renderer.fontMetrics(j.options.labels.style?j.options.labels.style.fontSize:0).b,w=1,z=o&&t.x===j.pos+j.len||!o&&t.y===j.pos?-1:0;for(l&&(A=o?[j.left,t.y,j.left,t.y+j.groupSize(!0)]:j.isXAxis?[t.x,j.top,t.x+j.groupSize(!0),j.top]:[t.x,j.top+j.len,t.x+j.groupSize(!0),j.top+j.len],x(p,A,s)),o&&j.leftb[0]?1:a[0]b[0]?1:a[0]b[0]?1:a[0]b[0]?1:a[0]=0;j--)v+=j>1?Math.round(100*p[j])/100+"x^"+j+" + ":1==j?Math.round(100*p[j])/100+"x + ":Math.round(100*p[j])/100;return{equation:p,points:f,string:v}}function g(a,b){function f(a){var c,b={},d=a.length,e=[];for(c=0;cb&&(b=Math.min(2/d.length,1),console.warn("updated bandwith to "+b));var e=a.map(function(a){return a[1]}),h=[],i=0,j=Math.floor(b*c.length)-1;for(var k in c){var l=c[k];k>0&&jc[j]-c[k]?i:j;for(var n=Math.abs(1/(c[m]-l)),o=0,p=0,q=0,r=0,s=0,t=i;t<=j;){var w,u=c[t],v=e[t];w=tMath.abs(a[c][f])&&(f=d);for(e=c;e=c;e--)a[e][d]-=a[e][c]*a[c][d]/a[c][c]}for(d=h-1;d>=0;d--){for(g=0,e=d+1;eb[0]?1:a[0]= 0) { - motion.dataSeries[index] = series; - for (var i = 0; i < series.data.length; i++) { - if (series.data[i].sequence) { - motion.dataLength = Math.max(motion.dataLength, series.data[i].sequence.length); - } - } - } - }); - - // Play-controls HTML-div - this.playControls = H.createElement('div', { - id: 'play-controls' - }, null, this.chart.renderTo, null); - - // Play/pause HTML-button - this.playPauseBtn = H.createElement('button', { - id: 'play-pause-button', - title: 'play' - }, null, this.playControls, null); - this.playPauseBtn.className = this.options.playIcon; - - // Play-range HTML-input - this.playRange = H.createElement('input', { - id: 'play-range', - type: 'range', - value: this.dataLength - 1, - min: 0, - max: this.dataLength - 1, - step: this.options.magnet.step - }, null, this.playControls, null); - - // Play-range HTML-output - this.playOutput = H.createElement('label', { - id: 'play-output', - name: this.options.axisLabel - }, null, this.playControls, null); - if (isArray(this.options.labels)) { - this.playOutput.innerHTML = this.options.labels[this.dataLength - 1] || ''; - } else { - this.playOutput.innerHTML = this.dataLength - 1; - } - - // Common key event handler function - function handleKeyEvents(e) { - e = e || window.event; - switch (e.which) { - case 32: // Space - motion.togglePlayPause(); - break; - case 37: // Left - motion.playRange.value = motion.round(parseFloat(motion.playRange.value) - 1); - motion.updateChart(motion.playRange.value); - break; - case 39: // Right - motion.playRange.value = motion.round(parseFloat(motion.playRange.value) + 1); - motion.updateChart(motion.playRange.value); - break; - default: - return; - } - e.preventDefault(); - } - - // Bind controls to events - Highcharts.addEvent(this.playPauseBtn, 'click', function () { - motion.togglePlayPause(); - }); - Highcharts.addEvent(this.playRange, 'mouseup', function () { - motion.attractToStep(); - }); - Highcharts.addEvent(this.playRange, 'input', function () { - motion.updateChart(this.value); - }); - - // Request focus to the controls when clicking on controls div - Highcharts.addEvent(this.playControls, 'click', function () { - motion.playRange.focus(); - }); - // Bind keys to events - Highcharts.addEvent(this.playPauseBtn, 'keydown', handleKeyEvents); - Highcharts.addEvent(this.playRange, 'keydown', handleKeyEvents); - - // Initial value - this.inputValue = parseFloat(this.playRange.value); - - // Initial update - this.updateChart(this.inputValue); - - // Auto-play - if (this.autoPlay) { - this.play(); - } - } - - // Default options for Motion - Motion.prototype.defaultOptions = { - enabled: true, - axisLabel: 'year', - autoPlay : false, - loop: false, - series: 0, - updateInterval: 10, - magnet: { - round: 'round', - step: 0.01 - }, - playIcon: "fa fa-play", - pauseIcon: "fa fa-pause" - }; - - // Toggles between Play and Pause states, and makes calls to changeButtonType() - // From http://www.creativebloq.com/html5/build-custom-html5-video-player-9134473 - Motion.prototype.togglePlayPause = function () { - this[this.paused ? 'play' : 'pause'](); - }; - - // Plays the motion, continuously updating the chart - Motion.prototype.play = function () { - var motion = this; - if (this.paused && parseFloat(this.playRange.value) === parseFloat(this.playRange.max)) { - this.reset(); - } - this.changeButtonType('pause'); - this.paused = false; - this.timer = setInterval(function () { - motion.playUpdate(); - }, this.options.updateInterval); - }; - - // Pauses the motion, which stops updating the chart - Motion.prototype.pause = function () { - this.changeButtonType('play'); - this.paused = true; - window.clearInterval(this.timer); - this.attractToStep(); - }; - - // Resets the motion and updates the chart. Does not pause - Motion.prototype.reset = function () { - this.playRange.value = this.playRange.min; - this.updateChart(this.playRange.value); - }; - - // Updates a button's title, innerHTML and CSS class to a certain value - Motion.prototype.changeButtonType = function (value) { - this.playPauseBtn.title = value; - this.playPauseBtn.className = value + " "; - if (value == 'play') { - this.playPauseBtn.className += this.options.playIcon; - } else if (value == 'pause') { - this.playPauseBtn.className += this.options.pauseIcon;; - } - }; - - // Called continuously while playing - Motion.prototype.playUpdate = function () { - if (!this.paused) { - this.inputValue = parseFloat(this.playRange.value); - this.playRange.value = this.inputValue + this.options.magnet.step; - this.attractToStep(); - this.updateChart(this.playRange.value); // Use playRange.value to get updated value - if (this.playRange.value >= parseFloat(this.playRange.max)) { // Auto-pause - if (this.options.loop) { - this.reset(); - } else { - this.pause(); - } - } - } - }; - - // Updates chart data and redraws the chart - Motion.prototype.updateChart = function (inputValue) { - var seriesKey, - series, - point, - roundedInput = this.round(inputValue), - i; - if (this.currentAxisValue !== roundedInput) { - this.currentAxisValue = roundedInput; - for (seriesKey in this.dataSeries) { - if (this.dataSeries.hasOwnProperty(seriesKey)) { - series = this.dataSeries[seriesKey]; - for (i = 0; i < series.data.length; i++) { - point = series.data[i]; - try { - if (point.sequence) { - point.update(point.sequence[roundedInput], false, false); - } - } catch (e) { - console.error('Error:', e, ' \nat point:', point, ' \nwith new value:', point.sequence[roundedInput]); - } - } - } - } - this.chart.redraw(); - this.attractToStep(); - } - }; - - // Moves output value to data point - Motion.prototype.attractToStep = function () { - if (isArray(this.options.labels)) { - this.playOutput.innerHTML = this.options.labels[this.round(this.playRange.value)] || ''; - } else { - this.playOutput.innerHTML = this.round(this.playRange.value); - } - }; - - // Returns an integer rounded up, down or even depending on - // motion.magnet.round options. - Motion.prototype.round = function (number) { - return Math[this.options.magnet.round](number); - }; - - // Initiates motion automatically if motion options object exists and - // is not disabled - H.Chart.prototype.callbacks.push(function (chart) { - if (chart.options.motion && chart.options.motion.enabled) { - chart.motion = new Motion(chart); - } - }); - - H.Motion = Motion; -}(Highcharts)); +!function(a){function b(a){return"[object Array]"===Object.prototype.toString.call(a)}function c(c){function e(a){switch(a=a||window.event,a.which){case 32:d.togglePlayPause();break;case 37:d.playRange.value=d.round(parseFloat(d.playRange.value)-1),d.updateChart(d.playRange.value);break;case 39:d.playRange.value=d.round(parseFloat(d.playRange.value)+1),d.updateChart(d.playRange.value);break;default:return}a.preventDefault()}var d=this;this.chart=c,this.paused=!0,this.options=a.merge(this.defaultOptions,this.chart.options.motion),this.dataSeries=[],this.dataLength=0,d.options.series=a.splat(d.options.series),Highcharts.each(this.chart.series,function(a,b){if(d.options.series.indexOf(b)>=0){d.dataSeries[b]=a;for(var c=0;c=parseFloat(this.playRange.max)&&(this.options.loop?this.reset():this.pause()))},c.prototype.updateChart=function(a){var b,c,d,f,e=this.round(a);if(this.currentAxisValue!==e){this.currentAxisValue=e,this.chart.options.motion.startIndex=e;for(b in this.dataSeries)if(this.dataSeries.hasOwnProperty(b))for(c=this.dataSeries[b],f=0;f