Scrollbar.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. /* *
  2. *
  3. * (c) 2010-2021 Torstein Honsi
  4. *
  5. * License: www.highcharts.com/license
  6. *
  7. * !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
  8. *
  9. * */
  10. 'use strict';
  11. import Axis from './Axis/Axis.js';
  12. import H from './Globals.js';
  13. import palette from './Color/Palette.js';
  14. import ScrollbarAxis from './Axis/ScrollbarAxis.js';
  15. import U from './Utilities.js';
  16. var addEvent = U.addEvent, correctFloat = U.correctFloat, defined = U.defined, destroyObjectProperties = U.destroyObjectProperties, fireEvent = U.fireEvent, merge = U.merge, pick = U.pick, removeEvent = U.removeEvent;
  17. import O from './Options.js';
  18. var defaultOptions = O.defaultOptions;
  19. var isTouchDevice = H.isTouchDevice;
  20. /**
  21. * When we have vertical scrollbar, rifles and arrow in buttons should be
  22. * rotated. The same method is used in Navigator's handles, to rotate them.
  23. *
  24. * @function Highcharts.swapXY
  25. *
  26. * @param {Highcharts.SVGPathArray} path
  27. * Path to be rotated.
  28. *
  29. * @param {boolean} [vertical]
  30. * If vertical scrollbar, swap x-y values.
  31. *
  32. * @return {Highcharts.SVGPathArray}
  33. * Rotated path.
  34. *
  35. * @requires modules/stock
  36. */
  37. var swapXY = H.swapXY = function (path, vertical) {
  38. if (vertical) {
  39. path.forEach(function (seg) {
  40. var len = seg.length;
  41. var temp;
  42. for (var i = 0; i < len; i += 2) {
  43. temp = seg[i + 1];
  44. if (typeof temp === 'number') {
  45. seg[i + 1] = seg[i + 2];
  46. seg[i + 2] = temp;
  47. }
  48. }
  49. });
  50. }
  51. return path;
  52. };
  53. /* eslint-disable no-invalid-this, valid-jsdoc */
  54. /**
  55. * A reusable scrollbar, internally used in Highstock's navigator and optionally
  56. * on individual axes.
  57. *
  58. * @private
  59. * @class
  60. * @name Highcharts.Scrollbar
  61. * @param {Highcharts.SVGRenderer} renderer
  62. * @param {Highcharts.ScrollbarOptions} options
  63. * @param {Highcharts.Chart} chart
  64. */
  65. var Scrollbar = /** @class */ (function () {
  66. /* *
  67. *
  68. * Constructors
  69. *
  70. * */
  71. function Scrollbar(renderer, options, chart) {
  72. /* *
  73. *
  74. * Properties
  75. *
  76. * */
  77. this._events = [];
  78. this.chartX = 0;
  79. this.chartY = 0;
  80. this.from = 0;
  81. this.group = void 0;
  82. this.scrollbar = void 0;
  83. this.scrollbarButtons = [];
  84. this.scrollbarGroup = void 0;
  85. this.scrollbarLeft = 0;
  86. this.scrollbarRifles = void 0;
  87. this.scrollbarStrokeWidth = 1;
  88. this.scrollbarTop = 0;
  89. this.size = 0;
  90. this.to = 0;
  91. this.track = void 0;
  92. this.trackBorderWidth = 1;
  93. this.userOptions = {};
  94. this.x = 0;
  95. this.y = 0;
  96. this.chart = chart;
  97. this.options = options;
  98. this.renderer = chart.renderer;
  99. this.init(renderer, options, chart);
  100. }
  101. /* *
  102. *
  103. * Functions
  104. *
  105. * */
  106. /**
  107. * Set up the mouse and touch events for the Scrollbar
  108. *
  109. * @private
  110. * @function Highcharts.Scrollbar#addEvents
  111. * @return {void}
  112. */
  113. Scrollbar.prototype.addEvents = function () {
  114. var buttonsOrder = this.options.inverted ? [1, 0] : [0, 1], buttons = this.scrollbarButtons, bar = this.scrollbarGroup.element, track = this.track.element, mouseDownHandler = this.mouseDownHandler.bind(this), mouseMoveHandler = this.mouseMoveHandler.bind(this), mouseUpHandler = this.mouseUpHandler.bind(this), _events;
  115. // Mouse events
  116. _events = [
  117. [buttons[buttonsOrder[0]].element, 'click', this.buttonToMinClick.bind(this)],
  118. [buttons[buttonsOrder[1]].element, 'click', this.buttonToMaxClick.bind(this)],
  119. [track, 'click', this.trackClick.bind(this)],
  120. [bar, 'mousedown', mouseDownHandler],
  121. [bar.ownerDocument, 'mousemove', mouseMoveHandler],
  122. [bar.ownerDocument, 'mouseup', mouseUpHandler]
  123. ];
  124. // Touch events
  125. if (H.hasTouch) {
  126. _events.push([bar, 'touchstart', mouseDownHandler], [bar.ownerDocument, 'touchmove', mouseMoveHandler], [bar.ownerDocument, 'touchend', mouseUpHandler]);
  127. }
  128. // Add them all
  129. _events.forEach(function (args) {
  130. addEvent.apply(null, args);
  131. });
  132. this._events = _events;
  133. };
  134. Scrollbar.prototype.buttonToMaxClick = function (e) {
  135. var scroller = this;
  136. var range = (scroller.to - scroller.from) * pick(scroller.options.step, 0.2);
  137. scroller.updatePosition(scroller.from + range, scroller.to + range);
  138. fireEvent(scroller, 'changed', {
  139. from: scroller.from,
  140. to: scroller.to,
  141. trigger: 'scrollbar',
  142. DOMEvent: e
  143. });
  144. };
  145. Scrollbar.prototype.buttonToMinClick = function (e) {
  146. var scroller = this;
  147. var range = correctFloat(scroller.to - scroller.from) *
  148. pick(scroller.options.step, 0.2);
  149. scroller.updatePosition(correctFloat(scroller.from - range), correctFloat(scroller.to - range));
  150. fireEvent(scroller, 'changed', {
  151. from: scroller.from,
  152. to: scroller.to,
  153. trigger: 'scrollbar',
  154. DOMEvent: e
  155. });
  156. };
  157. /**
  158. * Get normalized (0-1) cursor position over the scrollbar
  159. *
  160. * @private
  161. * @function Highcharts.Scrollbar#cursorToScrollbarPosition
  162. *
  163. * @param {*} normalizedEvent
  164. * normalized event, with chartX and chartY values
  165. *
  166. * @return {Highcharts.Dictionary<number>}
  167. * Local position {chartX, chartY}
  168. */
  169. Scrollbar.prototype.cursorToScrollbarPosition = function (normalizedEvent) {
  170. var scroller = this, options = scroller.options, minWidthDifference = options.minWidth > scroller.calculatedWidth ?
  171. options.minWidth :
  172. 0; // minWidth distorts translation
  173. return {
  174. chartX: (normalizedEvent.chartX - scroller.x -
  175. scroller.xOffset) /
  176. (scroller.barWidth - minWidthDifference),
  177. chartY: (normalizedEvent.chartY - scroller.y -
  178. scroller.yOffset) /
  179. (scroller.barWidth - minWidthDifference)
  180. };
  181. };
  182. /**
  183. * Destroys allocated elements.
  184. *
  185. * @private
  186. * @function Highcharts.Scrollbar#destroy
  187. * @return {void}
  188. */
  189. Scrollbar.prototype.destroy = function () {
  190. var scroller = this.chart.scroller;
  191. // Disconnect events added in addEvents
  192. this.removeEvents();
  193. // Destroy properties
  194. [
  195. 'track',
  196. 'scrollbarRifles',
  197. 'scrollbar',
  198. 'scrollbarGroup',
  199. 'group'
  200. ].forEach(function (prop) {
  201. if (this[prop] && this[prop].destroy) {
  202. this[prop] = this[prop].destroy();
  203. }
  204. }, this);
  205. // #6421, chart may have more scrollbars
  206. if (scroller && this === scroller.scrollbar) {
  207. scroller.scrollbar = null;
  208. // Destroy elements in collection
  209. destroyObjectProperties(scroller.scrollbarButtons);
  210. }
  211. };
  212. /**
  213. * Draw the scrollbar buttons with arrows
  214. *
  215. * @private
  216. * @function Highcharts.Scrollbar#drawScrollbarButton
  217. * @param {number} index
  218. * 0 is left, 1 is right
  219. * @return {void}
  220. */
  221. Scrollbar.prototype.drawScrollbarButton = function (index) {
  222. var scroller = this, renderer = scroller.renderer, scrollbarButtons = scroller.scrollbarButtons, options = scroller.options, size = scroller.size, group, tempElem;
  223. group = renderer.g().add(scroller.group);
  224. scrollbarButtons.push(group);
  225. // Create a rectangle for the scrollbar button
  226. tempElem = renderer.rect()
  227. .addClass('highcharts-scrollbar-button')
  228. .add(group);
  229. // Presentational attributes
  230. if (!this.chart.styledMode) {
  231. tempElem.attr({
  232. stroke: options.buttonBorderColor,
  233. 'stroke-width': options.buttonBorderWidth,
  234. fill: options.buttonBackgroundColor
  235. });
  236. }
  237. // Place the rectangle based on the rendered stroke width
  238. tempElem.attr(tempElem.crisp({
  239. x: -0.5,
  240. y: -0.5,
  241. width: size + 1,
  242. height: size + 1,
  243. r: options.buttonBorderRadius
  244. }, tempElem.strokeWidth()));
  245. // Button arrow
  246. tempElem = renderer
  247. .path(swapXY([[
  248. 'M',
  249. size / 2 + (index ? -1 : 1),
  250. size / 2 - 3
  251. ], [
  252. 'L',
  253. size / 2 + (index ? -1 : 1),
  254. size / 2 + 3
  255. ], [
  256. 'L',
  257. size / 2 + (index ? 2 : -2),
  258. size / 2
  259. ]], options.vertical))
  260. .addClass('highcharts-scrollbar-arrow')
  261. .add(scrollbarButtons[index]);
  262. if (!this.chart.styledMode) {
  263. tempElem.attr({
  264. fill: options.buttonArrowColor
  265. });
  266. }
  267. };
  268. /**
  269. * @private
  270. * @function Highcharts.Scrollbar#init
  271. * @param {Highcharts.SVGRenderer} renderer
  272. * @param {Highcharts.ScrollbarOptions} options
  273. * @param {Highcharts.Chart} chart
  274. */
  275. Scrollbar.prototype.init = function (renderer, options, chart) {
  276. this.scrollbarButtons = [];
  277. this.renderer = renderer;
  278. this.userOptions = options;
  279. this.options = merge(Scrollbar.defaultOptions, options);
  280. this.chart = chart;
  281. // backward compatibility
  282. this.size = pick(this.options.size, this.options.height);
  283. // Init
  284. if (options.enabled) {
  285. this.render();
  286. this.addEvents();
  287. }
  288. };
  289. Scrollbar.prototype.mouseDownHandler = function (e) {
  290. var scroller = this;
  291. var normalizedEvent = scroller.chart.pointer.normalize(e), mousePosition = scroller.cursorToScrollbarPosition(normalizedEvent);
  292. scroller.chartX = mousePosition.chartX;
  293. scroller.chartY = mousePosition.chartY;
  294. scroller.initPositions = [scroller.from, scroller.to];
  295. scroller.grabbedCenter = true;
  296. };
  297. /**
  298. * Event handler for the mouse move event.
  299. * @private
  300. */
  301. Scrollbar.prototype.mouseMoveHandler = function (e) {
  302. var scroller = this;
  303. var normalizedEvent = scroller.chart.pointer.normalize(e), options = scroller.options, direction = options.vertical ? 'chartY' : 'chartX', initPositions = scroller.initPositions || [], scrollPosition, chartPosition, change;
  304. // In iOS, a mousemove event with e.pageX === 0 is fired when
  305. // holding the finger down in the center of the scrollbar. This
  306. // should be ignored.
  307. if (scroller.grabbedCenter &&
  308. // #4696, scrollbar failed on Android
  309. (!e.touches || e.touches[0][direction] !== 0)) {
  310. chartPosition = scroller.cursorToScrollbarPosition(normalizedEvent)[direction];
  311. scrollPosition = scroller[direction];
  312. change = chartPosition - scrollPosition;
  313. scroller.hasDragged = true;
  314. scroller.updatePosition(initPositions[0] + change, initPositions[1] + change);
  315. if (scroller.hasDragged) {
  316. fireEvent(scroller, 'changed', {
  317. from: scroller.from,
  318. to: scroller.to,
  319. trigger: 'scrollbar',
  320. DOMType: e.type,
  321. DOMEvent: e
  322. });
  323. }
  324. }
  325. };
  326. /**
  327. * Event handler for the mouse up event.
  328. * @private
  329. */
  330. Scrollbar.prototype.mouseUpHandler = function (e) {
  331. var scroller = this;
  332. if (scroller.hasDragged) {
  333. fireEvent(scroller, 'changed', {
  334. from: scroller.from,
  335. to: scroller.to,
  336. trigger: 'scrollbar',
  337. DOMType: e.type,
  338. DOMEvent: e
  339. });
  340. }
  341. scroller.grabbedCenter =
  342. scroller.hasDragged =
  343. scroller.chartX =
  344. scroller.chartY = null;
  345. };
  346. /**
  347. * Position the scrollbar, method called from a parent with defined
  348. * dimensions.
  349. *
  350. * @private
  351. * @function Highcharts.Scrollbar#position
  352. * @param {number} x
  353. * x-position on the chart
  354. * @param {number} y
  355. * y-position on the chart
  356. * @param {number} width
  357. * width of the scrollbar
  358. * @param {number} height
  359. * height of the scorllbar
  360. * @return {void}
  361. */
  362. Scrollbar.prototype.position = function (x, y, width, height) {
  363. var scroller = this, options = scroller.options, vertical = options.vertical, xOffset = height, yOffset = 0, method = scroller.rendered ? 'animate' : 'attr';
  364. scroller.x = x;
  365. scroller.y = y + this.trackBorderWidth;
  366. scroller.width = width; // width with buttons
  367. scroller.height = height;
  368. scroller.xOffset = xOffset;
  369. scroller.yOffset = yOffset;
  370. // If Scrollbar is a vertical type, swap options:
  371. if (vertical) {
  372. scroller.width = scroller.yOffset = width = yOffset = scroller.size;
  373. scroller.xOffset = xOffset = 0;
  374. scroller.barWidth = height - width * 2; // width without buttons
  375. scroller.x = x = x + scroller.options.margin;
  376. }
  377. else {
  378. scroller.height = scroller.xOffset = height = xOffset =
  379. scroller.size;
  380. scroller.barWidth = width - height * 2; // width without buttons
  381. scroller.y = scroller.y + scroller.options.margin;
  382. }
  383. // Set general position for a group:
  384. scroller.group[method]({
  385. translateX: x,
  386. translateY: scroller.y
  387. });
  388. // Resize background/track:
  389. scroller.track[method]({
  390. width: width,
  391. height: height
  392. });
  393. // Move right/bottom button ot it's place:
  394. scroller.scrollbarButtons[1][method]({
  395. translateX: vertical ? 0 : width - xOffset,
  396. translateY: vertical ? height - yOffset : 0
  397. });
  398. };
  399. /**
  400. * Removes the event handlers attached previously with addEvents.
  401. *
  402. * @private
  403. * @function Highcharts.Scrollbar#removeEvents
  404. * @return {void}
  405. */
  406. Scrollbar.prototype.removeEvents = function () {
  407. this._events.forEach(function (args) {
  408. removeEvent.apply(null, args);
  409. });
  410. this._events.length = 0;
  411. };
  412. /**
  413. * Render scrollbar with all required items.
  414. *
  415. * @private
  416. * @function Highcharts.Scrollbar#render
  417. */
  418. Scrollbar.prototype.render = function () {
  419. var scroller = this, renderer = scroller.renderer, options = scroller.options, size = scroller.size, styledMode = this.chart.styledMode, group;
  420. // Draw the scrollbar group
  421. scroller.group = group = renderer.g('scrollbar').attr({
  422. zIndex: options.zIndex,
  423. translateY: -99999
  424. }).add();
  425. // Draw the scrollbar track:
  426. scroller.track = renderer.rect()
  427. .addClass('highcharts-scrollbar-track')
  428. .attr({
  429. x: 0,
  430. r: options.trackBorderRadius || 0,
  431. height: size,
  432. width: size
  433. }).add(group);
  434. if (!styledMode) {
  435. scroller.track.attr({
  436. fill: options.trackBackgroundColor,
  437. stroke: options.trackBorderColor,
  438. 'stroke-width': options.trackBorderWidth
  439. });
  440. }
  441. this.trackBorderWidth = scroller.track.strokeWidth();
  442. scroller.track.attr({
  443. y: -this.trackBorderWidth % 2 / 2
  444. });
  445. // Draw the scrollbar itself
  446. scroller.scrollbarGroup = renderer.g().add(group);
  447. scroller.scrollbar = renderer.rect()
  448. .addClass('highcharts-scrollbar-thumb')
  449. .attr({
  450. height: size,
  451. width: size,
  452. r: options.barBorderRadius || 0
  453. }).add(scroller.scrollbarGroup);
  454. scroller.scrollbarRifles = renderer
  455. .path(swapXY([
  456. ['M', -3, size / 4],
  457. ['L', -3, 2 * size / 3],
  458. ['M', 0, size / 4],
  459. ['L', 0, 2 * size / 3],
  460. ['M', 3, size / 4],
  461. ['L', 3, 2 * size / 3]
  462. ], options.vertical))
  463. .addClass('highcharts-scrollbar-rifles')
  464. .add(scroller.scrollbarGroup);
  465. if (!styledMode) {
  466. scroller.scrollbar.attr({
  467. fill: options.barBackgroundColor,
  468. stroke: options.barBorderColor,
  469. 'stroke-width': options.barBorderWidth
  470. });
  471. scroller.scrollbarRifles.attr({
  472. stroke: options.rifleColor,
  473. 'stroke-width': 1
  474. });
  475. }
  476. scroller.scrollbarStrokeWidth = scroller.scrollbar.strokeWidth();
  477. scroller.scrollbarGroup.translate(-scroller.scrollbarStrokeWidth % 2 / 2, -scroller.scrollbarStrokeWidth % 2 / 2);
  478. // Draw the buttons:
  479. scroller.drawScrollbarButton(0);
  480. scroller.drawScrollbarButton(1);
  481. };
  482. /**
  483. * Set scrollbar size, with a given scale.
  484. *
  485. * @private
  486. * @function Highcharts.Scrollbar#setRange
  487. * @param {number} from
  488. * scale (0-1) where bar should start
  489. * @param {number} to
  490. * scale (0-1) where bar should end
  491. * @return {void}
  492. */
  493. Scrollbar.prototype.setRange = function (from, to) {
  494. var scroller = this, options = scroller.options, vertical = options.vertical, minWidth = options.minWidth, fullWidth = scroller.barWidth, fromPX, toPX, newPos, newSize, newRiflesPos, method = (this.rendered &&
  495. !this.hasDragged &&
  496. !(this.chart.navigator && this.chart.navigator.hasDragged)) ? 'animate' : 'attr';
  497. if (!defined(fullWidth)) {
  498. return;
  499. }
  500. from = Math.max(from, 0);
  501. fromPX = Math.ceil(fullWidth * from);
  502. toPX = fullWidth * Math.min(to, 1);
  503. scroller.calculatedWidth = newSize = correctFloat(toPX - fromPX);
  504. // We need to recalculate position, if minWidth is used
  505. if (newSize < minWidth) {
  506. fromPX = (fullWidth - minWidth + newSize) * from;
  507. newSize = minWidth;
  508. }
  509. newPos = Math.floor(fromPX + scroller.xOffset + scroller.yOffset);
  510. newRiflesPos = newSize / 2 - 0.5; // -0.5 -> rifle line width / 2
  511. // Store current position:
  512. scroller.from = from;
  513. scroller.to = to;
  514. if (!vertical) {
  515. scroller.scrollbarGroup[method]({
  516. translateX: newPos
  517. });
  518. scroller.scrollbar[method]({
  519. width: newSize
  520. });
  521. scroller.scrollbarRifles[method]({
  522. translateX: newRiflesPos
  523. });
  524. scroller.scrollbarLeft = newPos;
  525. scroller.scrollbarTop = 0;
  526. }
  527. else {
  528. scroller.scrollbarGroup[method]({
  529. translateY: newPos
  530. });
  531. scroller.scrollbar[method]({
  532. height: newSize
  533. });
  534. scroller.scrollbarRifles[method]({
  535. translateY: newRiflesPos
  536. });
  537. scroller.scrollbarTop = newPos;
  538. scroller.scrollbarLeft = 0;
  539. }
  540. if (newSize <= 12) {
  541. scroller.scrollbarRifles.hide();
  542. }
  543. else {
  544. scroller.scrollbarRifles.show(true);
  545. }
  546. // Show or hide the scrollbar based on the showFull setting
  547. if (options.showFull === false) {
  548. if (from <= 0 && to >= 1) {
  549. scroller.group.hide();
  550. }
  551. else {
  552. scroller.group.show();
  553. }
  554. }
  555. scroller.rendered = true;
  556. };
  557. Scrollbar.prototype.trackClick = function (e) {
  558. var scroller = this;
  559. var normalizedEvent = scroller.chart.pointer.normalize(e), range = scroller.to - scroller.from, top = scroller.y + scroller.scrollbarTop, left = scroller.x + scroller.scrollbarLeft;
  560. if ((scroller.options.vertical && normalizedEvent.chartY > top) ||
  561. (!scroller.options.vertical && normalizedEvent.chartX > left)) {
  562. // On the top or on the left side of the track:
  563. scroller.updatePosition(scroller.from + range, scroller.to + range);
  564. }
  565. else {
  566. // On the bottom or the right side of the track:
  567. scroller.updatePosition(scroller.from - range, scroller.to - range);
  568. }
  569. fireEvent(scroller, 'changed', {
  570. from: scroller.from,
  571. to: scroller.to,
  572. trigger: 'scrollbar',
  573. DOMEvent: e
  574. });
  575. };
  576. /**
  577. * Update the scrollbar with new options
  578. *
  579. * @private
  580. * @function Highcharts.Scrollbar#update
  581. * @param {Highcharts.ScrollbarOptions} options
  582. * @return {void}
  583. */
  584. Scrollbar.prototype.update = function (options) {
  585. this.destroy();
  586. this.init(this.chart.renderer, merge(true, this.options, options), this.chart);
  587. };
  588. /**
  589. * Update position option in the Scrollbar, with normalized 0-1 scale
  590. *
  591. * @private
  592. * @function Highcharts.Scrollbar#updatePosition
  593. * @param {number} from
  594. * @param {number} to
  595. * @return {void}
  596. */
  597. Scrollbar.prototype.updatePosition = function (from, to) {
  598. if (to > 1) {
  599. from = correctFloat(1 - correctFloat(to - from));
  600. to = 1;
  601. }
  602. if (from < 0) {
  603. to = correctFloat(to - from);
  604. from = 0;
  605. }
  606. this.from = from;
  607. this.to = to;
  608. };
  609. /* *
  610. *
  611. * Static Properties
  612. *
  613. * */
  614. /**
  615. *
  616. * The scrollbar is a means of panning over the X axis of a stock chart.
  617. * Scrollbars can also be applied to other types of axes.
  618. *
  619. * Another approach to scrollable charts is the [chart.scrollablePlotArea](
  620. * https://api.highcharts.com/highcharts/chart.scrollablePlotArea) option that
  621. * is especially suitable for simpler cartesian charts on mobile.
  622. *
  623. * In styled mode, all the presentational options for the
  624. * scrollbar are replaced by the classes `.highcharts-scrollbar-thumb`,
  625. * `.highcharts-scrollbar-arrow`, `.highcharts-scrollbar-button`,
  626. * `.highcharts-scrollbar-rifles` and `.highcharts-scrollbar-track`.
  627. *
  628. * @sample stock/yaxis/inverted-bar-scrollbar/
  629. * A scrollbar on a simple bar chart
  630. *
  631. * @product highstock gantt
  632. * @optionparent scrollbar
  633. *
  634. * @private
  635. */
  636. Scrollbar.defaultOptions = {
  637. /**
  638. * The height of the scrollbar. The height also applies to the width
  639. * of the scroll arrows so that they are always squares. Defaults to
  640. * 20 for touch devices and 14 for mouse devices.
  641. *
  642. * @sample stock/scrollbar/height/
  643. * A 30px scrollbar
  644. *
  645. * @type {number}
  646. * @default 20/14
  647. */
  648. height: isTouchDevice ? 20 : 14,
  649. /**
  650. * The border rounding radius of the bar.
  651. *
  652. * @sample stock/scrollbar/style/
  653. * Scrollbar styling
  654. */
  655. barBorderRadius: 0,
  656. /**
  657. * The corner radius of the scrollbar buttons.
  658. *
  659. * @sample stock/scrollbar/style/
  660. * Scrollbar styling
  661. */
  662. buttonBorderRadius: 0,
  663. /**
  664. * Enable or disable the scrollbar.
  665. *
  666. * @sample stock/scrollbar/enabled/
  667. * Disable the scrollbar, only use navigator
  668. *
  669. * @type {boolean}
  670. * @default true
  671. * @apioption scrollbar.enabled
  672. */
  673. /**
  674. * Whether to redraw the main chart as the scrollbar or the navigator
  675. * zoomed window is moved. Defaults to `true` for modern browsers and
  676. * `false` for legacy IE browsers as well as mobile devices.
  677. *
  678. * @sample stock/scrollbar/liveredraw
  679. * Setting live redraw to false
  680. *
  681. * @type {boolean}
  682. * @since 1.3
  683. */
  684. liveRedraw: void 0,
  685. /**
  686. * The margin between the scrollbar and its axis when the scrollbar is
  687. * applied directly to an axis.
  688. */
  689. margin: 10,
  690. /**
  691. * The minimum width of the scrollbar.
  692. *
  693. * @since 1.2.5
  694. */
  695. minWidth: 6,
  696. /**
  697. * Whether to show or hide the scrollbar when the scrolled content is
  698. * zoomed out to it full extent.
  699. *
  700. * @type {boolean}
  701. * @default true
  702. * @apioption scrollbar.showFull
  703. */
  704. step: 0.2,
  705. /**
  706. * The z index of the scrollbar group.
  707. */
  708. zIndex: 3,
  709. /**
  710. * The background color of the scrollbar itself.
  711. *
  712. * @sample stock/scrollbar/style/
  713. * Scrollbar styling
  714. *
  715. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  716. */
  717. barBackgroundColor: palette.neutralColor20,
  718. /**
  719. * The width of the bar's border.
  720. *
  721. * @sample stock/scrollbar/style/
  722. * Scrollbar styling
  723. */
  724. barBorderWidth: 1,
  725. /**
  726. * The color of the scrollbar's border.
  727. *
  728. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  729. */
  730. barBorderColor: palette.neutralColor20,
  731. /**
  732. * The color of the small arrow inside the scrollbar buttons.
  733. *
  734. * @sample stock/scrollbar/style/
  735. * Scrollbar styling
  736. *
  737. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  738. */
  739. buttonArrowColor: palette.neutralColor80,
  740. /**
  741. * The color of scrollbar buttons.
  742. *
  743. * @sample stock/scrollbar/style/
  744. * Scrollbar styling
  745. *
  746. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  747. */
  748. buttonBackgroundColor: palette.neutralColor10,
  749. /**
  750. * The color of the border of the scrollbar buttons.
  751. *
  752. * @sample stock/scrollbar/style/
  753. * Scrollbar styling
  754. *
  755. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  756. */
  757. buttonBorderColor: palette.neutralColor20,
  758. /**
  759. * The border width of the scrollbar buttons.
  760. *
  761. * @sample stock/scrollbar/style/
  762. * Scrollbar styling
  763. */
  764. buttonBorderWidth: 1,
  765. /**
  766. * The color of the small rifles in the middle of the scrollbar.
  767. *
  768. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  769. */
  770. rifleColor: palette.neutralColor80,
  771. /**
  772. * The color of the track background.
  773. *
  774. * @sample stock/scrollbar/style/
  775. * Scrollbar styling
  776. *
  777. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  778. */
  779. trackBackgroundColor: palette.neutralColor5,
  780. /**
  781. * The color of the border of the scrollbar track.
  782. *
  783. * @sample stock/scrollbar/style/
  784. * Scrollbar styling
  785. *
  786. * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
  787. */
  788. trackBorderColor: palette.neutralColor5,
  789. /**
  790. * The corner radius of the border of the scrollbar track.
  791. *
  792. * @sample stock/scrollbar/style/
  793. * Scrollbar styling
  794. *
  795. * @type {number}
  796. * @default 0
  797. * @apioption scrollbar.trackBorderRadius
  798. */
  799. /**
  800. * The width of the border of the scrollbar track.
  801. *
  802. * @sample stock/scrollbar/style/
  803. * Scrollbar styling
  804. */
  805. trackBorderWidth: 1
  806. };
  807. return Scrollbar;
  808. }());
  809. if (!H.Scrollbar) {
  810. defaultOptions.scrollbar = merge(true, Scrollbar.defaultOptions, defaultOptions.scrollbar);
  811. H.Scrollbar = Scrollbar;
  812. ScrollbarAxis.compose(Axis, Scrollbar);
  813. }
  814. export default H.Scrollbar;