123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134 |
- /**
- * (c) 2010-2019 Torstein Honsi
- *
- * License: www.highcharts.com/license
- */
- 'use strict';
- import H from './Globals.js';
- import './Utilities.js';
- import './Axis.js';
- import './Options.js';
- var addEvent = H.addEvent,
- Axis = H.Axis,
- correctFloat = H.correctFloat,
- defaultOptions = H.defaultOptions,
- defined = H.defined,
- destroyObjectProperties = H.destroyObjectProperties,
- fireEvent = H.fireEvent,
- hasTouch = H.hasTouch,
- isTouchDevice = H.isTouchDevice,
- merge = H.merge,
- pick = H.pick,
- removeEvent = H.removeEvent,
- swapXY;
- /**
- *
- * The scrollbar is a means of panning over the X axis of a stock chart.
- * Scrollbars can also be applied to other types of axes.
- *
- * Another approach to scrollable charts is the [chart.scrollablePlotArea](
- * https://api.highcharts.com/highcharts/chart.scrollablePlotArea) option that
- * is especially suitable for simpler cartesian charts on mobile.
- *
- * In styled mode, all the presentational options for the
- * scrollbar are replaced by the classes `.highcharts-scrollbar-thumb`,
- * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`,
- * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`.
- *
- * @sample stock/yaxis/inverted-bar-scrollbar/
- * A scrollbar on a simple bar chart
- *
- * @product highstock
- * @optionparent scrollbar
- */
- var defaultScrollbarOptions = {
- /**
- * The height of the scrollbar. The height also applies to the width
- * of the scroll arrows so that they are always squares. Defaults to
- * 20 for touch devices and 14 for mouse devices.
- *
- * @sample stock/scrollbar/height/
- * A 30px scrollbar
- *
- * @type {number}
- * @default 20/14
- */
- height: isTouchDevice ? 20 : 14,
- /**
- * The border rounding radius of the bar.
- *
- * @sample stock/scrollbar/style/
- * Scrollbar styling
- */
- barBorderRadius: 0,
- /**
- * The corner radius of the scrollbar buttons.
- *
- * @sample stock/scrollbar/style/
- * Scrollbar styling
- */
- buttonBorderRadius: 0,
- /**
- * Enable or disable the scrollbar.
- *
- * @sample stock/scrollbar/enabled/
- * Disable the scrollbar, only use navigator
- *
- * @type {boolean}
- * @default true
- * @apioption scrollbar.enabled
- */
- /**
- * Whether to redraw the main chart as the scrollbar or the navigator
- * zoomed window is moved. Defaults to `true` for modern browsers and
- * `false` for legacy IE browsers as well as mobile devices.
- *
- * @sample stock/scrollbar/liveredraw
- * Setting live redraw to false
- *
- * @type {boolean}
- * @since 1.3
- */
- liveRedraw: undefined,
- /**
- * The margin between the scrollbar and its axis when the scrollbar is
- * applied directly to an axis.
- */
- margin: 10,
- /**
- * The minimum width of the scrollbar.
- *
- * @since 1.2.5
- */
- minWidth: 6,
- /**
- * Whether to show or hide the scrollbar when the scrolled content is
- * zoomed out to it full extent.
- *
- * @type {boolean}
- * @default true
- * @product highstock
- * @apioption scrollbar.showFull
- */
- step: 0.2,
- /**
- * The z index of the scrollbar group.
- */
- zIndex: 3,
- /**
- * The background color of the scrollbar itself.
- *
- * @sample stock/scrollbar/style/
- * Scrollbar styling
- *
- * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
- */
- barBackgroundColor: '#cccccc',
- /**
- * The width of the bar's border.
- *
- * @sample stock/scrollbar/style/
- * Scrollbar styling
- */
- barBorderWidth: 1,
- /**
- * The color of the scrollbar's border.
- *
- * @type {Highcharts.ColorString}
- */
- barBorderColor: '#cccccc',
- /**
- * The color of the small arrow inside the scrollbar buttons.
- *
- * @sample stock/scrollbar/style/
- * Scrollbar styling
- *
- * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
- */
- buttonArrowColor: '#333333',
- /**
- * The color of scrollbar buttons.
- *
- * @sample stock/scrollbar/style/
- * Scrollbar styling
- *
- * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
- */
- buttonBackgroundColor: '#e6e6e6',
- /**
- * The color of the border of the scrollbar buttons.
- *
- * @sample stock/scrollbar/style/
- * Scrollbar styling
- *
- * @type {Highcharts.ColorString}
- */
- buttonBorderColor: '#cccccc',
- /**
- * The border width of the scrollbar buttons.
- *
- * @sample stock/scrollbar/style/
- * Scrollbar styling
- */
- buttonBorderWidth: 1,
- /**
- * The color of the small rifles in the middle of the scrollbar.
- *
- * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
- */
- rifleColor: '#333333',
- /**
- * The color of the track background.
- *
- * @sample stock/scrollbar/style/
- * Scrollbar styling
- *
- * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
- */
- trackBackgroundColor: '#f2f2f2',
- /**
- * The color of the border of the scrollbar track.
- *
- * @sample stock/scrollbar/style/
- * Scrollbar styling
- *
- * @type {Highcharts.ColorString}
- */
- trackBorderColor: '#f2f2f2',
- /**
- * The corner radius of the border of the scrollbar track.
- *
- * @sample stock/scrollbar/style/
- * Scrollbar styling
- *
- * @type {number}
- * @default 0
- * @apioption scrollbar.trackBorderRadius
- */
- /**
- * The width of the border of the scrollbar track.
- *
- * @sample stock/scrollbar/style/
- * Scrollbar styling
- */
- trackBorderWidth: 1
- };
- defaultOptions.scrollbar = merge(
- true,
- defaultScrollbarOptions,
- defaultOptions.scrollbar
- );
- /**
- * When we have vertical scrollbar, rifles and arrow in buttons should be
- * rotated. The same method is used in Navigator's handles, to rotate them.
- *
- * @function Highcharts.swapXY
- *
- * @param {Array<number|string>} path
- * Path to be rotated.
- *
- * @param {boolean} vertical
- * If vertical scrollbar, swap x-y values.
- *
- * @return {Array<number|string>}
- */
- H.swapXY = swapXY = function (path, vertical) {
- var i,
- len = path.length,
- temp;
- if (vertical) {
- for (i = 0; i < len; i += 3) {
- temp = path[i + 1];
- path[i + 1] = path[i + 2];
- path[i + 2] = temp;
- }
- }
- return path;
- };
- /**
- * A reusable scrollbar, internally used in Highstock's navigator and optionally
- * on individual axes.
- *
- * @private
- * @class
- * @name Highcharts.Scrollbar
- *
- * @param {Highcharts.SVGRenderer} renderer
- *
- * @param {Highcharts.ScrollbarOptions} options
- *
- * @param {Highcharts.Chart} chart
- */
- function Scrollbar(renderer, options, chart) { // docs
- this.init(renderer, options, chart);
- }
- Scrollbar.prototype = {
- /**
- * @private
- * @function Highcharts.Scrollbar#init
- *
- * @param {Highcharts.SVGRenderer} renderer
- *
- * @param {Highcharts.ScrollbarOptions} options
- *
- * @param {Highcharts.Chart} chart
- */
- init: function (renderer, options, chart) {
- this.scrollbarButtons = [];
- this.renderer = renderer;
- this.userOptions = options;
- this.options = merge(defaultScrollbarOptions, options);
- this.chart = chart;
- // backward compatibility
- this.size = pick(this.options.size, this.options.height);
- // Init
- if (options.enabled) {
- this.render();
- this.initEvents();
- this.addEvents();
- }
- },
- /**
- * Render scrollbar with all required items.
- *
- * @private
- * @function Highcharts.Scrollbar#render
- */
- render: function () {
- var scroller = this,
- renderer = scroller.renderer,
- options = scroller.options,
- size = scroller.size,
- styledMode = this.chart.styledMode,
- group;
- // Draw the scrollbar group
- scroller.group = group = renderer.g('scrollbar').attr({
- zIndex: options.zIndex,
- translateY: -99999
- }).add();
- // Draw the scrollbar track:
- scroller.track = renderer.rect()
- .addClass('highcharts-scrollbar-track')
- .attr({
- x: 0,
- r: options.trackBorderRadius || 0,
- height: size,
- width: size
- }).add(group);
- if (!styledMode) {
- scroller.track.attr({
- fill: options.trackBackgroundColor,
- stroke: options.trackBorderColor,
- 'stroke-width': options.trackBorderWidth
- });
- }
- this.trackBorderWidth = scroller.track.strokeWidth();
- scroller.track.attr({
- y: -this.trackBorderWidth % 2 / 2
- });
- // Draw the scrollbar itself
- scroller.scrollbarGroup = renderer.g().add(group);
- scroller.scrollbar = renderer.rect()
- .addClass('highcharts-scrollbar-thumb')
- .attr({
- height: size,
- width: size,
- r: options.barBorderRadius || 0
- }).add(scroller.scrollbarGroup);
- scroller.scrollbarRifles = renderer
- .path(swapXY([
- 'M',
- -3, size / 4,
- 'L',
- -3, 2 * size / 3,
- 'M',
- 0, size / 4,
- 'L',
- 0, 2 * size / 3,
- 'M',
- 3, size / 4,
- 'L',
- 3, 2 * size / 3
- ], options.vertical))
- .addClass('highcharts-scrollbar-rifles')
- .add(scroller.scrollbarGroup);
- if (!styledMode) {
- scroller.scrollbar.attr({
- fill: options.barBackgroundColor,
- stroke: options.barBorderColor,
- 'stroke-width': options.barBorderWidth
- });
- scroller.scrollbarRifles.attr({
- stroke: options.rifleColor,
- 'stroke-width': 1
- });
- }
- scroller.scrollbarStrokeWidth = scroller.scrollbar.strokeWidth();
- scroller.scrollbarGroup.translate(
- -scroller.scrollbarStrokeWidth % 2 / 2,
- -scroller.scrollbarStrokeWidth % 2 / 2
- );
- // Draw the buttons:
- scroller.drawScrollbarButton(0);
- scroller.drawScrollbarButton(1);
- },
- /**
- * Position the scrollbar, method called from a parent with defined
- * dimensions.
- *
- * @private
- * @function Highcharts.Scrollbar#position
- *
- * @param {number} x
- * x-position on the chart
- *
- * @param {number} y
- * y-position on the chart
- *
- * @param {number} width
- * width of the scrollbar
- *
- * @param {number} height
- * height of the scorllbar
- */
- position: function (x, y, width, height) {
- var scroller = this,
- options = scroller.options,
- vertical = options.vertical,
- xOffset = height,
- yOffset = 0,
- method = scroller.rendered ? 'animate' : 'attr';
- scroller.x = x;
- scroller.y = y + this.trackBorderWidth;
- scroller.width = width; // width with buttons
- scroller.height = height;
- scroller.xOffset = xOffset;
- scroller.yOffset = yOffset;
- // If Scrollbar is a vertical type, swap options:
- if (vertical) {
- scroller.width = scroller.yOffset = width = yOffset = scroller.size;
- scroller.xOffset = xOffset = 0;
- scroller.barWidth = height - width * 2; // width without buttons
- scroller.x = x = x + scroller.options.margin;
- } else {
- scroller.height = scroller.xOffset = height = xOffset =
- scroller.size;
- scroller.barWidth = width - height * 2; // width without buttons
- scroller.y = scroller.y + scroller.options.margin;
- }
- // Set general position for a group:
- scroller.group[method]({
- translateX: x,
- translateY: scroller.y
- });
- // Resize background/track:
- scroller.track[method]({
- width: width,
- height: height
- });
- // Move right/bottom button ot it's place:
- scroller.scrollbarButtons[1][method]({
- translateX: vertical ? 0 : width - xOffset,
- translateY: vertical ? height - yOffset : 0
- });
- },
- /**
- * Draw the scrollbar buttons with arrows
- *
- * @private
- * @function Highcharts.Scrollbar#drawScrollbarButton
- *
- * @param {number} index
- * 0 is left, 1 is right
- */
- drawScrollbarButton: function (index) {
- var scroller = this,
- renderer = scroller.renderer,
- scrollbarButtons = scroller.scrollbarButtons,
- options = scroller.options,
- size = scroller.size,
- group,
- tempElem;
- group = renderer.g().add(scroller.group);
- scrollbarButtons.push(group);
- // Create a rectangle for the scrollbar button
- tempElem = renderer.rect()
- .addClass('highcharts-scrollbar-button')
- .add(group);
- // Presentational attributes
- if (!this.chart.styledMode) {
- tempElem.attr({
- stroke: options.buttonBorderColor,
- 'stroke-width': options.buttonBorderWidth,
- fill: options.buttonBackgroundColor
- });
- }
- // Place the rectangle based on the rendered stroke width
- tempElem.attr(tempElem.crisp({
- x: -0.5,
- y: -0.5,
- width: size + 1, // +1 to compensate for crispifying in rect method
- height: size + 1,
- r: options.buttonBorderRadius
- }, tempElem.strokeWidth()));
- // Button arrow
- tempElem = renderer
- .path(swapXY([
- 'M',
- size / 2 + (index ? -1 : 1),
- size / 2 - 3,
- 'L',
- size / 2 + (index ? -1 : 1),
- size / 2 + 3,
- 'L',
- size / 2 + (index ? 2 : -2),
- size / 2
- ], options.vertical))
- .addClass('highcharts-scrollbar-arrow')
- .add(scrollbarButtons[index]);
- if (!this.chart.styledMode) {
- tempElem.attr({
- fill: options.buttonArrowColor
- });
- }
- },
- /**
- * Set scrollbar size, with a given scale.
- *
- * @private
- * @function Highcharts.Scrollbar#setRange
- *
- * @param {number} from
- * scale (0-1) where bar should start
- *
- * @param {number} to
- * scale (0-1) where bar should end
- */
- setRange: function (from, to) {
- var scroller = this,
- options = scroller.options,
- vertical = options.vertical,
- minWidth = options.minWidth,
- fullWidth = scroller.barWidth,
- fromPX,
- toPX,
- newPos,
- newSize,
- newRiflesPos,
- method = (
- this.rendered &&
- !this.hasDragged &&
- !(this.chart.navigator && this.chart.navigator.hasDragged)
- ) ? 'animate' : 'attr';
- if (!defined(fullWidth)) {
- return;
- }
- from = Math.max(from, 0);
- fromPX = Math.ceil(fullWidth * from);
- toPX = fullWidth * Math.min(to, 1);
- scroller.calculatedWidth = newSize = correctFloat(toPX - fromPX);
- // We need to recalculate position, if minWidth is used
- if (newSize < minWidth) {
- fromPX = (fullWidth - minWidth + newSize) * from;
- newSize = minWidth;
- }
- newPos = Math.floor(fromPX + scroller.xOffset + scroller.yOffset);
- newRiflesPos = newSize / 2 - 0.5; // -0.5 -> rifle line width / 2
- // Store current position:
- scroller.from = from;
- scroller.to = to;
- if (!vertical) {
- scroller.scrollbarGroup[method]({
- translateX: newPos
- });
- scroller.scrollbar[method]({
- width: newSize
- });
- scroller.scrollbarRifles[method]({
- translateX: newRiflesPos
- });
- scroller.scrollbarLeft = newPos;
- scroller.scrollbarTop = 0;
- } else {
- scroller.scrollbarGroup[method]({
- translateY: newPos
- });
- scroller.scrollbar[method]({
- height: newSize
- });
- scroller.scrollbarRifles[method]({
- translateY: newRiflesPos
- });
- scroller.scrollbarTop = newPos;
- scroller.scrollbarLeft = 0;
- }
- if (newSize <= 12) {
- scroller.scrollbarRifles.hide();
- } else {
- scroller.scrollbarRifles.show(true);
- }
- // Show or hide the scrollbar based on the showFull setting
- if (options.showFull === false) {
- if (from <= 0 && to >= 1) {
- scroller.group.hide();
- } else {
- scroller.group.show();
- }
- }
- scroller.rendered = true;
- },
- /**
- * Init events methods, so we have an access to the Scrollbar itself
- *
- * @private
- * @function Highcharts.Scrollbar#initEvents
- *
- * @fires Highcharts.Scrollbar#event:changed
- */
- initEvents: function () {
- var scroller = this;
- /**
- * Event handler for the mouse move event.
- */
- scroller.mouseMoveHandler = function (e) {
- var normalizedEvent = scroller.chart.pointer.normalize(e),
- options = scroller.options,
- direction = options.vertical ? 'chartY' : 'chartX',
- initPositions = scroller.initPositions,
- scrollPosition,
- chartPosition,
- change;
- // In iOS, a mousemove event with e.pageX === 0 is fired when
- // holding the finger down in the center of the scrollbar. This
- // should be ignored.
- if (
- scroller.grabbedCenter &&
- // #4696, scrollbar failed on Android
- (!e.touches || e.touches[0][direction] !== 0)
- ) {
- chartPosition = scroller.cursorToScrollbarPosition(
- normalizedEvent
- )[direction];
- scrollPosition = scroller[direction];
- change = chartPosition - scrollPosition;
- scroller.hasDragged = true;
- scroller.updatePosition(
- initPositions[0] + change,
- initPositions[1] + change
- );
- if (scroller.hasDragged) {
- fireEvent(scroller, 'changed', {
- from: scroller.from,
- to: scroller.to,
- trigger: 'scrollbar',
- DOMType: e.type,
- DOMEvent: e
- });
- }
- }
- };
- /**
- * Event handler for the mouse up event.
- */
- scroller.mouseUpHandler = function (e) {
- if (scroller.hasDragged) {
- fireEvent(scroller, 'changed', {
- from: scroller.from,
- to: scroller.to,
- trigger: 'scrollbar',
- DOMType: e.type,
- DOMEvent: e
- });
- }
- scroller.grabbedCenter =
- scroller.hasDragged =
- scroller.chartX =
- scroller.chartY = null;
- };
- scroller.mouseDownHandler = function (e) {
- var normalizedEvent = scroller.chart.pointer.normalize(e),
- mousePosition = scroller.cursorToScrollbarPosition(
- normalizedEvent
- );
- scroller.chartX = mousePosition.chartX;
- scroller.chartY = mousePosition.chartY;
- scroller.initPositions = [scroller.from, scroller.to];
- scroller.grabbedCenter = true;
- };
- scroller.buttonToMinClick = function (e) {
- var range = correctFloat(scroller.to - scroller.from) *
- scroller.options.step;
- scroller.updatePosition(
- correctFloat(scroller.from - range),
- correctFloat(scroller.to - range)
- );
- fireEvent(scroller, 'changed', {
- from: scroller.from,
- to: scroller.to,
- trigger: 'scrollbar',
- DOMEvent: e
- });
- };
- scroller.buttonToMaxClick = function (e) {
- var range = (scroller.to - scroller.from) * scroller.options.step;
- scroller.updatePosition(scroller.from + range, scroller.to + range);
- fireEvent(scroller, 'changed', {
- from: scroller.from,
- to: scroller.to,
- trigger: 'scrollbar',
- DOMEvent: e
- });
- };
- scroller.trackClick = function (e) {
- var normalizedEvent = scroller.chart.pointer.normalize(e),
- range = scroller.to - scroller.from,
- top = scroller.y + scroller.scrollbarTop,
- left = scroller.x + scroller.scrollbarLeft;
- if (
- (scroller.options.vertical && normalizedEvent.chartY > top) ||
- (!scroller.options.vertical && normalizedEvent.chartX > left)
- ) {
- // On the top or on the left side of the track:
- scroller.updatePosition(
- scroller.from + range,
- scroller.to + range
- );
- } else {
- // On the bottom or the right side of the track:
- scroller.updatePosition(
- scroller.from - range,
- scroller.to - range
- );
- }
- fireEvent(scroller, 'changed', {
- from: scroller.from,
- to: scroller.to,
- trigger: 'scrollbar',
- DOMEvent: e
- });
- };
- },
- /**
- * Get normalized (0-1) cursor position over the scrollbar
- *
- * @private
- * @function Highcharts.Scrollbar#cursorToScrollbarPosition
- *
- * @param {*} normalizedEvent
- * normalized event, with chartX and chartY values
- *
- * @return {*}
- * Local position {chartX, chartY}
- */
- cursorToScrollbarPosition: function (normalizedEvent) {
- var scroller = this,
- options = scroller.options,
- minWidthDifference = options.minWidth > scroller.calculatedWidth ?
- options.minWidth :
- 0; // minWidth distorts translation
- return {
- chartX: (normalizedEvent.chartX - scroller.x - scroller.xOffset) /
- (scroller.barWidth - minWidthDifference),
- chartY: (normalizedEvent.chartY - scroller.y - scroller.yOffset) /
- (scroller.barWidth - minWidthDifference)
- };
- },
- /**
- * Update position option in the Scrollbar, with normalized 0-1 scale
- *
- * @private
- * @function Highcharts.Scrollbar#updatePosition
- *
- * @param {number} from
- *
- * @param {number} to
- */
- updatePosition: function (from, to) {
- if (to > 1) {
- from = correctFloat(1 - correctFloat(to - from));
- to = 1;
- }
- if (from < 0) {
- to = correctFloat(to - from);
- from = 0;
- }
- this.from = from;
- this.to = to;
- },
- /**
- * Update the scrollbar with new options
- *
- * @private
- * @function Highcharts.Scrollbar#update
- *
- * @param {Highcharts.ScrollbarOptions} options
- */
- update: function (options) {
- this.destroy();
- this.init(
- this.chart.renderer,
- merge(true, this.options, options),
- this.chart
- );
- },
- /**
- * Set up the mouse and touch events for the Scrollbar
- *
- * @private
- * @function Highcharts.Scrollbar#addEvents
- */
- addEvents: function () {
- var buttonsOrder = this.options.inverted ? [1, 0] : [0, 1],
- buttons = this.scrollbarButtons,
- bar = this.scrollbarGroup.element,
- track = this.track.element,
- mouseDownHandler = this.mouseDownHandler,
- mouseMoveHandler = this.mouseMoveHandler,
- mouseUpHandler = this.mouseUpHandler,
- _events;
- // Mouse events
- _events = [
- [buttons[buttonsOrder[0]].element, 'click', this.buttonToMinClick],
- [buttons[buttonsOrder[1]].element, 'click', this.buttonToMaxClick],
- [track, 'click', this.trackClick],
- [bar, 'mousedown', mouseDownHandler],
- [bar.ownerDocument, 'mousemove', mouseMoveHandler],
- [bar.ownerDocument, 'mouseup', mouseUpHandler]
- ];
- // Touch events
- if (hasTouch) {
- _events.push(
- [bar, 'touchstart', mouseDownHandler],
- [bar.ownerDocument, 'touchmove', mouseMoveHandler],
- [bar.ownerDocument, 'touchend', mouseUpHandler]
- );
- }
- // Add them all
- _events.forEach(function (args) {
- addEvent.apply(null, args);
- });
- this._events = _events;
- },
- /**
- * Removes the event handlers attached previously with addEvents.
- *
- * @private
- * @function Highcharts.Scrollbar#removeEvents
- */
- removeEvents: function () {
- this._events.forEach(function (args) {
- removeEvent.apply(null, args);
- });
- this._events.length = 0;
- },
- /**
- * Destroys allocated elements.
- *
- * @private
- * @function Highcharts.Scrollbar#destroy
- */
- destroy: function () {
- var scroller = this.chart.scroller;
- // Disconnect events added in addEvents
- this.removeEvents();
- // Destroy properties
- [
- 'track',
- 'scrollbarRifles',
- 'scrollbar',
- 'scrollbarGroup',
- 'group'
- ].forEach(
- function (prop) {
- if (this[prop] && this[prop].destroy) {
- this[prop] = this[prop].destroy();
- }
- },
- this
- );
- // #6421, chart may have more scrollbars
- if (scroller && this === scroller.scrollbar) {
- scroller.scrollbar = null;
- // Destroy elements in collection
- destroyObjectProperties(scroller.scrollbarButtons);
- }
- }
- };
- /* *
- * Wrap axis initialization and create scrollbar if enabled:
- */
- addEvent(Axis, 'afterInit', function () {
- var axis = this;
- if (
- axis.options &&
- axis.options.scrollbar &&
- axis.options.scrollbar.enabled
- ) {
- // Predefined options:
- axis.options.scrollbar.vertical = !axis.horiz;
- axis.options.startOnTick = axis.options.endOnTick = false;
- axis.scrollbar = new Scrollbar(
- axis.chart.renderer,
- axis.options.scrollbar,
- axis.chart
- );
- addEvent(axis.scrollbar, 'changed', function (e) {
- var unitedMin = Math.min(
- pick(axis.options.min, axis.min),
- axis.min,
- axis.dataMin
- ),
- unitedMax = Math.max(
- pick(axis.options.max, axis.max),
- axis.max,
- axis.dataMax
- ),
- range = unitedMax - unitedMin,
- to,
- from;
- if (
- (axis.horiz && !axis.reversed) ||
- (!axis.horiz && axis.reversed)
- ) {
- to = unitedMin + range * this.to;
- from = unitedMin + range * this.from;
- } else {
- // y-values in browser are reversed, but this also applies for
- // reversed horizontal axis:
- to = unitedMin + range * (1 - this.from);
- from = unitedMin + range * (1 - this.to);
- }
- if (
- pick(
- this.options.liveRedraw,
- H.svg && !H.isTouchDevice && !this.chart.isBoosting
- ) ||
- // Mouseup always should change extremes
- e.DOMType === 'mouseup' ||
- // Internal events
- !defined(e.DOMType)
- ) {
- axis.setExtremes(
- from,
- to,
- true,
- e.DOMType !== 'mousemove',
- e
- );
- } else {
- // When live redraw is disabled, don't change extremes
- // Only change the position of the scollbar thumb
- this.setRange(this.from, this.to);
- }
- });
- }
- });
- /* *
- * Wrap rendering axis, and update scrollbar if one is created:
- */
- addEvent(Axis, 'afterRender', function () {
- var axis = this,
- scrollMin = Math.min(
- pick(axis.options.min, axis.min),
- axis.min,
- pick(axis.dataMin, axis.min) // #6930
- ),
- scrollMax = Math.max(
- pick(axis.options.max, axis.max),
- axis.max,
- pick(axis.dataMax, axis.max) // #6930
- ),
- scrollbar = axis.scrollbar,
- titleOffset = axis.titleOffset || 0,
- offsetsIndex,
- from,
- to;
- if (scrollbar) {
- if (axis.horiz) {
- scrollbar.position(
- axis.left,
- axis.top + axis.height + 2 + axis.chart.scrollbarsOffsets[1] +
- (axis.opposite ?
- 0 :
- titleOffset + axis.axisTitleMargin + axis.offset
- ),
- axis.width,
- axis.height
- );
- offsetsIndex = 1;
- } else {
- scrollbar.position(
- axis.left + axis.width + 2 + axis.chart.scrollbarsOffsets[0] +
- (axis.opposite ?
- titleOffset + axis.axisTitleMargin + axis.offset :
- 0
- ),
- axis.top,
- axis.width,
- axis.height
- );
- offsetsIndex = 0;
- }
- if ((!axis.opposite && !axis.horiz) || (axis.opposite && axis.horiz)) {
- axis.chart.scrollbarsOffsets[offsetsIndex] +=
- axis.scrollbar.size + axis.scrollbar.options.margin;
- }
- if (
- isNaN(scrollMin) ||
- isNaN(scrollMax) ||
- !defined(axis.min) ||
- !defined(axis.max)
- ) {
- // default action: when there is not extremes on the axis, but
- // scrollbar exists, make it full size
- scrollbar.setRange(0, 0);
- } else {
- from = (axis.min - scrollMin) / (scrollMax - scrollMin);
- to = (axis.max - scrollMin) / (scrollMax - scrollMin);
- if (
- (axis.horiz && !axis.reversed) ||
- (!axis.horiz && axis.reversed)
- ) {
- scrollbar.setRange(from, to);
- } else {
- scrollbar.setRange(1 - to, 1 - from); // inverse vertical axis
- }
- }
- }
- });
- /* *
- * Make space for a scrollbar
- */
- addEvent(Axis, 'afterGetOffset', function () {
- var axis = this,
- index = axis.horiz ? 2 : 1,
- scrollbar = axis.scrollbar;
- if (scrollbar) {
- axis.chart.scrollbarsOffsets = [0, 0]; // reset scrollbars offsets
- axis.chart.axisOffset[index] +=
- scrollbar.size + scrollbar.options.margin;
- }
- });
- H.Scrollbar = Scrollbar;
|