scrollbar.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. /**
  2. * @fileoverview added by tsickle
  3. * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  4. */
  5. import { Injectable, Inject } from '@angular/core';
  6. import { DOCUMENT } from '@angular/common';
  7. import * as i0 from "@angular/core";
  8. import * as i1 from "@angular/common";
  9. /** @type {?} */
  10. var noop = (/**
  11. * @return {?}
  12. */
  13. function () { });
  14. var ɵ0 = noop;
  15. /**
  16. * Utility to handle the scrollbar.
  17. *
  18. * It allows to compensate the lack of a vertical scrollbar by adding an
  19. * equivalent padding on the right of the body, and to remove this compensation.
  20. */
  21. var ScrollBar = /** @class */ (function () {
  22. function ScrollBar(_document) {
  23. this._document = _document;
  24. }
  25. /**
  26. * To be called right before a potential vertical scrollbar would be removed:
  27. *
  28. * - if there was a scrollbar, adds some compensation padding to the body
  29. * to keep the same layout as when the scrollbar is there
  30. * - if there was none, there is nothing to do
  31. *
  32. * @return a callback used to revert the compensation (noop if there was none,
  33. * otherwise a function removing the padding)
  34. */
  35. /**
  36. * To be called right before a potential vertical scrollbar would be removed:
  37. *
  38. * - if there was a scrollbar, adds some compensation padding to the body
  39. * to keep the same layout as when the scrollbar is there
  40. * - if there was none, there is nothing to do
  41. *
  42. * @return {?} a callback used to revert the compensation (noop if there was none,
  43. * otherwise a function removing the padding)
  44. */
  45. ScrollBar.prototype.compensate = /**
  46. * To be called right before a potential vertical scrollbar would be removed:
  47. *
  48. * - if there was a scrollbar, adds some compensation padding to the body
  49. * to keep the same layout as when the scrollbar is there
  50. * - if there was none, there is nothing to do
  51. *
  52. * @return {?} a callback used to revert the compensation (noop if there was none,
  53. * otherwise a function removing the padding)
  54. */
  55. function () {
  56. /** @type {?} */
  57. var width = this._getWidth();
  58. return !this._isPresent(width) ? noop : this._adjustBody(width);
  59. };
  60. /**
  61. * Adds a padding of the given width on the right of the body.
  62. *
  63. * @return a callback used to revert the padding to its previous value
  64. */
  65. /**
  66. * Adds a padding of the given width on the right of the body.
  67. *
  68. * @private
  69. * @param {?} scrollbarWidth
  70. * @return {?} a callback used to revert the padding to its previous value
  71. */
  72. ScrollBar.prototype._adjustBody = /**
  73. * Adds a padding of the given width on the right of the body.
  74. *
  75. * @private
  76. * @param {?} scrollbarWidth
  77. * @return {?} a callback used to revert the padding to its previous value
  78. */
  79. function (scrollbarWidth) {
  80. /** @type {?} */
  81. var body = this._document.body;
  82. /** @type {?} */
  83. var userSetPaddingStyle = body.style.paddingRight;
  84. /** @type {?} */
  85. var actualPadding = parseFloat(window.getComputedStyle(body)['padding-right']);
  86. body.style['padding-right'] = actualPadding + scrollbarWidth + "px";
  87. return (/**
  88. * @return {?}
  89. */
  90. function () { return body.style['padding-right'] = userSetPaddingStyle; });
  91. };
  92. /**
  93. * Tells whether a scrollbar is currently present on the body.
  94. *
  95. * @return true if scrollbar is present, false otherwise
  96. */
  97. /**
  98. * Tells whether a scrollbar is currently present on the body.
  99. *
  100. * @private
  101. * @param {?} scrollbarWidth
  102. * @return {?} true if scrollbar is present, false otherwise
  103. */
  104. ScrollBar.prototype._isPresent = /**
  105. * Tells whether a scrollbar is currently present on the body.
  106. *
  107. * @private
  108. * @param {?} scrollbarWidth
  109. * @return {?} true if scrollbar is present, false otherwise
  110. */
  111. function (scrollbarWidth) {
  112. /** @type {?} */
  113. var rect = this._document.body.getBoundingClientRect();
  114. /** @type {?} */
  115. var bodyToViewportGap = window.innerWidth - (rect.left + rect.right);
  116. /** @type {?} */
  117. var uncertainty = 0.1 * scrollbarWidth;
  118. return bodyToViewportGap >= scrollbarWidth - uncertainty;
  119. };
  120. /**
  121. * Calculates and returns the width of a scrollbar.
  122. *
  123. * @return the width of a scrollbar on this page
  124. */
  125. /**
  126. * Calculates and returns the width of a scrollbar.
  127. *
  128. * @private
  129. * @return {?} the width of a scrollbar on this page
  130. */
  131. ScrollBar.prototype._getWidth = /**
  132. * Calculates and returns the width of a scrollbar.
  133. *
  134. * @private
  135. * @return {?} the width of a scrollbar on this page
  136. */
  137. function () {
  138. /** @type {?} */
  139. var measurer = this._document.createElement('div');
  140. measurer.className = 'modal-scrollbar-measure';
  141. /** @type {?} */
  142. var body = this._document.body;
  143. body.appendChild(measurer);
  144. /** @type {?} */
  145. var width = measurer.getBoundingClientRect().width - measurer.clientWidth;
  146. body.removeChild(measurer);
  147. return width;
  148. };
  149. ScrollBar.decorators = [
  150. { type: Injectable, args: [{ providedIn: 'root' },] }
  151. ];
  152. /** @nocollapse */
  153. ScrollBar.ctorParameters = function () { return [
  154. { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
  155. ]; };
  156. /** @nocollapse */ ScrollBar.ngInjectableDef = i0.ɵɵdefineInjectable({ factory: function ScrollBar_Factory() { return new ScrollBar(i0.ɵɵinject(i1.DOCUMENT)); }, token: ScrollBar, providedIn: "root" });
  157. return ScrollBar;
  158. }());
  159. export { ScrollBar };
  160. if (false) {
  161. /**
  162. * @type {?}
  163. * @private
  164. */
  165. ScrollBar.prototype._document;
  166. }
  167. export { ɵ0 };
  168. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Nyb2xsYmFyLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG5nLWJvb3RzdHJhcC9uZy1ib290c3RyYXAvIiwic291cmNlcyI6WyJ1dGlsL3Njcm9sbGJhci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDakQsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGlCQUFpQixDQUFDOzs7O0lBR25DLElBQUk7OztBQUFHLGNBQU8sQ0FBQyxDQUFBOzs7Ozs7OztBQWVyQjtJQUVFLG1CQUFzQyxTQUFjO1FBQWQsY0FBUyxHQUFULFNBQVMsQ0FBSztJQUFHLENBQUM7SUFFeEQ7Ozs7Ozs7OztPQVNHOzs7Ozs7Ozs7OztJQUNILDhCQUFVOzs7Ozs7Ozs7O0lBQVY7O1lBQ1EsS0FBSyxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUU7UUFDOUIsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBRUQ7Ozs7T0FJRzs7Ozs7Ozs7SUFDSywrQkFBVzs7Ozs7OztJQUFuQixVQUFvQixjQUFzQjs7WUFDbEMsSUFBSSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSTs7WUFDMUIsbUJBQW1CLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZOztZQUM3QyxhQUFhLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUNoRixJQUFJLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxHQUFNLGFBQWEsR0FBRyxjQUFjLE9BQUksQ0FBQztRQUNwRTs7O1FBQU8sY0FBTSxPQUFBLElBQUksQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLEdBQUcsbUJBQW1CLEVBQWpELENBQWlELEVBQUM7SUFDakUsQ0FBQztJQUVEOzs7O09BSUc7Ozs7Ozs7O0lBQ0ssOEJBQVU7Ozs7Ozs7SUFBbEIsVUFBbUIsY0FBc0I7O1lBQ2pDLElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsRUFBRTs7WUFDbEQsaUJBQWlCLEdBQUcsTUFBTSxDQUFDLFVBQVUsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQzs7WUFDaEUsV0FBVyxHQUFHLEdBQUcsR0FBRyxjQUFjO1FBQ3hDLE9BQU8saUJBQWlCLElBQUksY0FBYyxHQUFHLFdBQVcsQ0FBQztJQUMzRCxDQUFDO0lBRUQ7Ozs7T0FJRzs7Ozs7OztJQUNLLDZCQUFTOzs7Ozs7SUFBakI7O1lBQ1EsUUFBUSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQztRQUNwRCxRQUFRLENBQUMsU0FBUyxHQUFHLHlCQUF5QixDQUFDOztZQUV6QyxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJO1FBQ2hDLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7O1lBQ3JCLEtBQUssR0FBRyxRQUFRLENBQUMscUJBQXFCLEVBQUUsQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFDLFdBQVc7UUFDM0UsSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUUzQixPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7O2dCQTNERixVQUFVLFNBQUMsRUFBQyxVQUFVLEVBQUUsTUFBTSxFQUFDOzs7O2dEQUVqQixNQUFNLFNBQUMsUUFBUTs7O29CQXJCOUI7Q0ErRUMsQUE1REQsSUE0REM7U0EzRFksU0FBUzs7Ozs7O0lBQ1IsOEJBQXdDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3RhYmxlLCBJbmplY3R9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtET0NVTUVOVH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcblxuXG5jb25zdCBub29wID0gKCkgPT4ge307XG5cblxuXG4vKiogVHlwZSBmb3IgdGhlIGNhbGxiYWNrIHVzZWQgdG8gcmV2ZXJ0IHRoZSBzY3JvbGxiYXIgY29tcGVuc2F0aW9uLiAqL1xuZXhwb3J0IHR5cGUgQ29tcGVuc2F0aW9uUmV2ZXJ0ZXIgPSAoKSA9PiB2b2lkO1xuXG5cblxuLyoqXG4gKiBVdGlsaXR5IHRvIGhhbmRsZSB0aGUgc2Nyb2xsYmFyLlxuICpcbiAqIEl0IGFsbG93cyB0byBjb21wZW5zYXRlIHRoZSBsYWNrIG9mIGEgdmVydGljYWwgc2Nyb2xsYmFyIGJ5IGFkZGluZyBhblxuICogZXF1aXZhbGVudCBwYWRkaW5nIG9uIHRoZSByaWdodCBvZiB0aGUgYm9keSwgYW5kIHRvIHJlbW92ZSB0aGlzIGNvbXBlbnNhdGlvbi5cbiAqL1xuQEluamVjdGFibGUoe3Byb3ZpZGVkSW46ICdyb290J30pXG5leHBvcnQgY2xhc3MgU2Nyb2xsQmFyIHtcbiAgY29uc3RydWN0b3IoQEluamVjdChET0NVTUVOVCkgcHJpdmF0ZSBfZG9jdW1lbnQ6IGFueSkge31cblxuICAvKipcbiAgICogVG8gYmUgY2FsbGVkIHJpZ2h0IGJlZm9yZSBhIHBvdGVudGlhbCB2ZXJ0aWNhbCBzY3JvbGxiYXIgd291bGQgYmUgcmVtb3ZlZDpcbiAgICpcbiAgICogLSBpZiB0aGVyZSB3YXMgYSBzY3JvbGxiYXIsIGFkZHMgc29tZSBjb21wZW5zYXRpb24gcGFkZGluZyB0byB0aGUgYm9keVxuICAgKiB0byBrZWVwIHRoZSBzYW1lIGxheW91dCBhcyB3aGVuIHRoZSBzY3JvbGxiYXIgaXMgdGhlcmVcbiAgICogLSBpZiB0aGVyZSB3YXMgbm9uZSwgdGhlcmUgaXMgbm90aGluZyB0byBkb1xuICAgKlxuICAgKiBAcmV0dXJuIGEgY2FsbGJhY2sgdXNlZCB0byByZXZlcnQgdGhlIGNvbXBlbnNhdGlvbiAobm9vcCBpZiB0aGVyZSB3YXMgbm9uZSxcbiAgICogb3RoZXJ3aXNlIGEgZnVuY3Rpb24gcmVtb3ZpbmcgdGhlIHBhZGRpbmcpXG4gICAqL1xuICBjb21wZW5zYXRlKCk6IENvbXBlbnNhdGlvblJldmVydGVyIHtcbiAgICBjb25zdCB3aWR0aCA9IHRoaXMuX2dldFdpZHRoKCk7XG4gICAgcmV0dXJuICF0aGlzLl9pc1ByZXNlbnQod2lkdGgpID8gbm9vcCA6IHRoaXMuX2FkanVzdEJvZHkod2lkdGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBwYWRkaW5nIG9mIHRoZSBnaXZlbiB3aWR0aCBvbiB0aGUgcmlnaHQgb2YgdGhlIGJvZHkuXG4gICAqXG4gICAqIEByZXR1cm4gYSBjYWxsYmFjayB1c2VkIHRvIHJldmVydCB0aGUgcGFkZGluZyB0byBpdHMgcHJldmlvdXMgdmFsdWVcbiAgICovXG4gIHByaXZhdGUgX2FkanVzdEJvZHkoc2Nyb2xsYmFyV2lkdGg6IG51bWJlcik6IENvbXBlbnNhdGlvblJldmVydGVyIHtcbiAgICBjb25zdCBib2R5ID0gdGhpcy5fZG9jdW1lbnQuYm9keTtcbiAgICBjb25zdCB1c2VyU2V0UGFkZGluZ1N0eWxlID0gYm9keS5zdHlsZS5wYWRkaW5nUmlnaHQ7XG4gICAgY29uc3QgYWN0dWFsUGFkZGluZyA9IHBhcnNlRmxvYXQod2luZG93LmdldENvbXB1dGVkU3R5bGUoYm9keSlbJ3BhZGRpbmctcmlnaHQnXSk7XG4gICAgYm9keS5zdHlsZVsncGFkZGluZy1yaWdodCddID0gYCR7YWN0dWFsUGFkZGluZyArIHNjcm9sbGJhcldpZHRofXB4YDtcbiAgICByZXR1cm4gKCkgPT4gYm9keS5zdHlsZVsncGFkZGluZy1yaWdodCddID0gdXNlclNldFBhZGRpbmdTdHlsZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUZWxscyB3aGV0aGVyIGEgc2Nyb2xsYmFyIGlzIGN1cnJlbnRseSBwcmVzZW50IG9uIHRoZSBib2R5LlxuICAgKlxuICAgKiBAcmV0dXJuIHRydWUgaWYgc2Nyb2xsYmFyIGlzIHByZXNlbnQsIGZhbHNlIG90aGVyd2lzZVxuICAgKi9cbiAgcHJpdmF0ZSBfaXNQcmVzZW50KHNjcm9sbGJhcldpZHRoOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICBjb25zdCByZWN0ID0gdGhpcy5fZG9jdW1lbnQuYm9keS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBjb25zdCBib2R5VG9WaWV3cG9ydEdhcCA9IHdpbmRvdy5pbm5lcldpZHRoIC0gKHJlY3QubGVmdCArIHJlY3QucmlnaHQpO1xuICAgIGNvbnN0IHVuY2VydGFpbnR5ID0gMC4xICogc2Nyb2xsYmFyV2lkdGg7XG4gICAgcmV0dXJuIGJvZHlUb1ZpZXdwb3J0R2FwID49IHNjcm9sbGJhcldpZHRoIC0gdW5jZXJ0YWludHk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyBhbmQgcmV0dXJucyB0aGUgd2lkdGggb2YgYSBzY3JvbGxiYXIuXG4gICAqXG4gICAqIEByZXR1cm4gdGhlIHdpZHRoIG9mIGEgc2Nyb2xsYmFyIG9uIHRoaXMgcGFnZVxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0V2lkdGgoKTogbnVtYmVyIHtcbiAgICBjb25zdCBtZWFzdXJlciA9IHRoaXMuX2RvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIG1lYXN1cmVyLmNsYXNzTmFtZSA9ICdtb2RhbC1zY3JvbGxiYXItbWVhc3VyZSc7XG5cbiAgICBjb25zdCBib2R5ID0gdGhpcy5fZG9jdW1lbnQuYm9keTtcbiAgICBib2R5LmFwcGVuZENoaWxkKG1lYXN1cmVyKTtcbiAgICBjb25zdCB3aWR0aCA9IG1lYXN1cmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoIC0gbWVhc3VyZXIuY2xpZW50V2lkdGg7XG4gICAgYm9keS5yZW1vdmVDaGlsZChtZWFzdXJlcik7XG5cbiAgICByZXR1cm4gd2lkdGg7XG4gIH1cbn1cbiJdfQ==