foundation.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /**
  2. * @license
  3. * Copyright 2018 Google Inc.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. */
  23. import { __extends } from "tslib";
  24. import { numbers } from '../constants';
  25. import { MDCTopAppBarBaseFoundation } from '../foundation';
  26. var INITIAL_VALUE = 0;
  27. /** MDC Top App Bar Foundation */
  28. var MDCTopAppBarFoundation = /** @class */ (function (_super) {
  29. __extends(MDCTopAppBarFoundation, _super);
  30. /* istanbul ignore next: optional argument is not a branch statement */
  31. function MDCTopAppBarFoundation(adapter) {
  32. var _this = _super.call(this, adapter) || this;
  33. /**
  34. * Indicates if the top app bar was docked in the previous scroll handler
  35. * iteration.
  36. */
  37. _this.wasDocked = true;
  38. /**
  39. * Indicates if the top app bar is docked in the fully shown position.
  40. */
  41. _this.isDockedShowing = true;
  42. /**
  43. * Variable for current scroll position of the top app bar
  44. */
  45. _this.currentAppBarOffsetTop = 0;
  46. /**
  47. * Used to prevent the top app bar from being scrolled out of view during
  48. * resize events
  49. */
  50. _this.isCurrentlyBeingResized = false;
  51. /**
  52. * The timeout that's used to throttle the resize events
  53. */
  54. _this.resizeThrottleId = INITIAL_VALUE;
  55. /**
  56. * The timeout that's used to debounce toggling the isCurrentlyBeingResized
  57. * variable after a resize
  58. */
  59. _this.resizeDebounceId = INITIAL_VALUE;
  60. _this.lastScrollPosition = _this.adapter.getViewportScrollY();
  61. _this.topAppBarHeight = _this.adapter.getTopAppBarHeight();
  62. return _this;
  63. }
  64. MDCTopAppBarFoundation.prototype.destroy = function () {
  65. _super.prototype.destroy.call(this);
  66. this.adapter.setStyle('top', '');
  67. };
  68. /**
  69. * Scroll handler for the default scroll behavior of the top app bar.
  70. */
  71. MDCTopAppBarFoundation.prototype.handleTargetScroll = function () {
  72. var currentScrollPosition = Math.max(this.adapter.getViewportScrollY(), 0);
  73. var diff = currentScrollPosition - this.lastScrollPosition;
  74. this.lastScrollPosition = currentScrollPosition;
  75. // If the window is being resized the lastScrollPosition needs to be updated
  76. // but the current scroll of the top app bar should stay in the same
  77. // position.
  78. if (!this.isCurrentlyBeingResized) {
  79. this.currentAppBarOffsetTop -= diff;
  80. if (this.currentAppBarOffsetTop > 0) {
  81. this.currentAppBarOffsetTop = 0;
  82. }
  83. else if (Math.abs(this.currentAppBarOffsetTop) > this.topAppBarHeight) {
  84. this.currentAppBarOffsetTop = -this.topAppBarHeight;
  85. }
  86. this.moveTopAppBar();
  87. }
  88. };
  89. /**
  90. * Top app bar resize handler that throttle/debounce functions that execute
  91. * updates.
  92. */
  93. MDCTopAppBarFoundation.prototype.handleWindowResize = function () {
  94. var _this = this;
  95. // Throttle resize events 10 p/s
  96. if (!this.resizeThrottleId) {
  97. this.resizeThrottleId = setTimeout(function () {
  98. _this.resizeThrottleId = INITIAL_VALUE;
  99. _this.throttledResizeHandler();
  100. }, numbers.DEBOUNCE_THROTTLE_RESIZE_TIME_MS);
  101. }
  102. this.isCurrentlyBeingResized = true;
  103. if (this.resizeDebounceId) {
  104. clearTimeout(this.resizeDebounceId);
  105. }
  106. this.resizeDebounceId = setTimeout(function () {
  107. _this.handleTargetScroll();
  108. _this.isCurrentlyBeingResized = false;
  109. _this.resizeDebounceId = INITIAL_VALUE;
  110. }, numbers.DEBOUNCE_THROTTLE_RESIZE_TIME_MS);
  111. };
  112. /**
  113. * Function to determine if the DOM needs to update.
  114. */
  115. MDCTopAppBarFoundation.prototype.checkForUpdate = function () {
  116. var offscreenBoundaryTop = -this.topAppBarHeight;
  117. var hasAnyPixelsOffscreen = this.currentAppBarOffsetTop < 0;
  118. var hasAnyPixelsOnscreen = this.currentAppBarOffsetTop > offscreenBoundaryTop;
  119. var partiallyShowing = hasAnyPixelsOffscreen && hasAnyPixelsOnscreen;
  120. // If it's partially showing, it can't be docked.
  121. if (partiallyShowing) {
  122. this.wasDocked = false;
  123. }
  124. else {
  125. // Not previously docked and not partially showing, it's now docked.
  126. if (!this.wasDocked) {
  127. this.wasDocked = true;
  128. return true;
  129. }
  130. else if (this.isDockedShowing !== hasAnyPixelsOnscreen) {
  131. this.isDockedShowing = hasAnyPixelsOnscreen;
  132. return true;
  133. }
  134. }
  135. return partiallyShowing;
  136. };
  137. /**
  138. * Function to move the top app bar if needed.
  139. */
  140. MDCTopAppBarFoundation.prototype.moveTopAppBar = function () {
  141. if (this.checkForUpdate()) {
  142. // Once the top app bar is fully hidden we use the max potential top app
  143. // bar height as our offset so the top app bar doesn't show if the window
  144. // resizes and the new height > the old height.
  145. var offset = this.currentAppBarOffsetTop;
  146. if (Math.abs(offset) >= this.topAppBarHeight) {
  147. offset = -numbers.MAX_TOP_APP_BAR_HEIGHT;
  148. }
  149. this.adapter.setStyle('top', offset + 'px');
  150. }
  151. };
  152. /**
  153. * Throttled function that updates the top app bar scrolled values if the
  154. * top app bar height changes.
  155. */
  156. MDCTopAppBarFoundation.prototype.throttledResizeHandler = function () {
  157. var currentHeight = this.adapter.getTopAppBarHeight();
  158. if (this.topAppBarHeight !== currentHeight) {
  159. this.wasDocked = false;
  160. // Since the top app bar has a different height depending on the screen
  161. // width, this will ensure that the top app bar remains in the correct
  162. // location if completely hidden and a resize makes the top app bar a
  163. // different height.
  164. this.currentAppBarOffsetTop -= this.topAppBarHeight - currentHeight;
  165. this.topAppBarHeight = currentHeight;
  166. }
  167. this.handleTargetScroll();
  168. };
  169. return MDCTopAppBarFoundation;
  170. }(MDCTopAppBarBaseFoundation));
  171. export { MDCTopAppBarFoundation };
  172. // tslint:disable-next-line:no-default-export Needed for backward compatibility with MDC Web v0.44.0 and earlier.
  173. export default MDCTopAppBarFoundation;
  174. //# sourceMappingURL=foundation.js.map