component.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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 { getCorrectPropertyName } from '@material/animation/util';
  25. import { MDCComponent } from '@material/base/component';
  26. import { cssClasses, strings } from './constants';
  27. import { MDCMenuSurfaceFoundation } from './foundation';
  28. /** MDC Menu Surface */
  29. var MDCMenuSurface = /** @class */ (function (_super) {
  30. __extends(MDCMenuSurface, _super);
  31. function MDCMenuSurface() {
  32. return _super !== null && _super.apply(this, arguments) || this;
  33. }
  34. MDCMenuSurface.attachTo = function (root) {
  35. return new MDCMenuSurface(root);
  36. };
  37. MDCMenuSurface.prototype.initialSyncWithDOM = function () {
  38. var _this = this;
  39. var parentEl = this.root.parentElement;
  40. this.anchorElement =
  41. parentEl && parentEl.classList.contains(cssClasses.ANCHOR) ? parentEl :
  42. null;
  43. if (this.root.classList.contains(cssClasses.FIXED)) {
  44. this.setFixedPosition(true);
  45. }
  46. this.handleKeydown = function (event) {
  47. _this.foundation.handleKeydown(event);
  48. };
  49. this.handleBodyClick = function (event) {
  50. _this.foundation.handleBodyClick(event);
  51. };
  52. // capture so that no race between handleBodyClick and quickOpen when
  53. // menusurface opened on button click which registers this listener
  54. this.registerBodyClickListener = function () {
  55. document.body.addEventListener('click', _this.handleBodyClick, { capture: true });
  56. };
  57. this.deregisterBodyClickListener = function () {
  58. document.body.removeEventListener('click', _this.handleBodyClick, { capture: true });
  59. };
  60. this.listen('keydown', this.handleKeydown);
  61. this.listen(strings.OPENED_EVENT, this.registerBodyClickListener);
  62. this.listen(strings.CLOSED_EVENT, this.deregisterBodyClickListener);
  63. };
  64. MDCMenuSurface.prototype.destroy = function () {
  65. this.unlisten('keydown', this.handleKeydown);
  66. this.unlisten(strings.OPENED_EVENT, this.registerBodyClickListener);
  67. this.unlisten(strings.CLOSED_EVENT, this.deregisterBodyClickListener);
  68. _super.prototype.destroy.call(this);
  69. };
  70. MDCMenuSurface.prototype.isOpen = function () {
  71. return this.foundation.isOpen();
  72. };
  73. MDCMenuSurface.prototype.open = function () {
  74. this.foundation.open();
  75. };
  76. MDCMenuSurface.prototype.close = function (skipRestoreFocus) {
  77. if (skipRestoreFocus === void 0) { skipRestoreFocus = false; }
  78. this.foundation.close(skipRestoreFocus);
  79. };
  80. Object.defineProperty(MDCMenuSurface.prototype, "quickOpen", {
  81. set: function (quickOpen) {
  82. this.foundation.setQuickOpen(quickOpen);
  83. },
  84. enumerable: false,
  85. configurable: true
  86. });
  87. /**
  88. * Sets the foundation to use page offsets for a positioning when the menu is
  89. * hoisted to the body.
  90. */
  91. MDCMenuSurface.prototype.setIsHoisted = function (isHoisted) {
  92. this.foundation.setIsHoisted(isHoisted);
  93. };
  94. /** Sets the element that the menu-surface is anchored to. */
  95. MDCMenuSurface.prototype.setMenuSurfaceAnchorElement = function (element) {
  96. this.anchorElement = element;
  97. };
  98. /** Sets the menu-surface to position: fixed. */
  99. MDCMenuSurface.prototype.setFixedPosition = function (isFixed) {
  100. if (isFixed) {
  101. this.root.classList.add(cssClasses.FIXED);
  102. }
  103. else {
  104. this.root.classList.remove(cssClasses.FIXED);
  105. }
  106. this.foundation.setFixedPosition(isFixed);
  107. };
  108. /**
  109. * Sets the absolute x/y position to position based on. Requires the menu to
  110. * be hoisted.
  111. */
  112. MDCMenuSurface.prototype.setAbsolutePosition = function (x, y) {
  113. this.foundation.setAbsolutePosition(x, y);
  114. this.setIsHoisted(true);
  115. };
  116. /**
  117. * @param corner Default anchor corner alignment of top-left surface corner.
  118. */
  119. MDCMenuSurface.prototype.setAnchorCorner = function (corner) {
  120. this.foundation.setAnchorCorner(corner);
  121. };
  122. MDCMenuSurface.prototype.setAnchorMargin = function (margin) {
  123. this.foundation.setAnchorMargin(margin);
  124. };
  125. MDCMenuSurface.prototype.getDefaultFoundation = function () {
  126. var _this = this;
  127. // DO NOT INLINE this variable. For backward compatibility, foundations take
  128. // a Partial<MDCFooAdapter>. To ensure we don't accidentally omit any
  129. // methods, we need a separate, strongly typed adapter variable.
  130. // tslint:disable:object-literal-sort-keys Methods should be in the same order as the adapter interface.
  131. var adapter = {
  132. addClass: function (className) {
  133. _this.root.classList.add(className);
  134. },
  135. removeClass: function (className) {
  136. _this.root.classList.remove(className);
  137. },
  138. hasClass: function (className) { return _this.root.classList.contains(className); },
  139. hasAnchor: function () { return !!_this.anchorElement; },
  140. notifyClose: function () {
  141. _this.emit(MDCMenuSurfaceFoundation.strings.CLOSED_EVENT, {});
  142. },
  143. notifyClosing: function () {
  144. _this.emit(MDCMenuSurfaceFoundation.strings.CLOSING_EVENT, {});
  145. },
  146. notifyOpen: function () {
  147. _this.emit(MDCMenuSurfaceFoundation.strings.OPENED_EVENT, {});
  148. },
  149. notifyOpening: function () {
  150. _this.emit(MDCMenuSurfaceFoundation.strings.OPENING_EVENT, {});
  151. },
  152. isElementInContainer: function (el) { return _this.root.contains(el); },
  153. isRtl: function () {
  154. return getComputedStyle(_this.root).getPropertyValue('direction') === 'rtl';
  155. },
  156. setTransformOrigin: function (origin) {
  157. var propertyName = getCorrectPropertyName(window, 'transform') + "-origin";
  158. _this.root.style.setProperty(propertyName, origin);
  159. },
  160. isFocused: function () { return document.activeElement === _this.root; },
  161. saveFocus: function () {
  162. _this.previousFocus =
  163. document.activeElement;
  164. },
  165. restoreFocus: function () {
  166. if (_this.root.contains(document.activeElement)) {
  167. if (_this.previousFocus && _this.previousFocus.focus) {
  168. _this.previousFocus.focus();
  169. }
  170. }
  171. },
  172. getInnerDimensions: function () {
  173. return { width: _this.root.offsetWidth, height: _this.root.offsetHeight };
  174. },
  175. getAnchorDimensions: function () { return _this.anchorElement ?
  176. _this.anchorElement.getBoundingClientRect() :
  177. null; },
  178. getViewportDimensions: function () {
  179. return { width: window.innerWidth, height: window.innerHeight };
  180. },
  181. getBodyDimensions: function () {
  182. return {
  183. width: document.body.clientWidth,
  184. height: document.body.clientHeight
  185. };
  186. },
  187. getWindowScroll: function () {
  188. return { x: window.pageXOffset, y: window.pageYOffset };
  189. },
  190. setPosition: function (position) {
  191. var rootHTML = _this.root;
  192. rootHTML.style.left = 'left' in position ? position.left + "px" : '';
  193. rootHTML.style.right = 'right' in position ? position.right + "px" : '';
  194. rootHTML.style.top = 'top' in position ? position.top + "px" : '';
  195. rootHTML.style.bottom =
  196. 'bottom' in position ? position.bottom + "px" : '';
  197. },
  198. setMaxHeight: function (height) {
  199. _this.root.style.maxHeight = height;
  200. },
  201. registerWindowEventHandler: function (evtType, handler) {
  202. window.addEventListener(evtType, handler);
  203. },
  204. deregisterWindowEventHandler: function (evtType, handler) {
  205. window.removeEventListener(evtType, handler);
  206. },
  207. };
  208. // tslint:enable:object-literal-sort-keys
  209. return new MDCMenuSurfaceFoundation(adapter);
  210. };
  211. return MDCMenuSurface;
  212. }(MDCComponent));
  213. export { MDCMenuSurface };
  214. //# sourceMappingURL=component.js.map