component.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /**
  2. * @license
  3. * Copyright 2017 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, __values } from "tslib";
  24. import { MDCComponent } from '@material/base/component';
  25. import { FocusTrap } from '@material/dom/focus-trap';
  26. import { closest, matches } from '@material/dom/ponyfill';
  27. import { MDCRipple } from '@material/ripple/component';
  28. import { MDCDialogFoundation } from './foundation';
  29. import * as util from './util';
  30. var strings = MDCDialogFoundation.strings;
  31. /** MDC Dialog */
  32. var MDCDialog = /** @class */ (function (_super) {
  33. __extends(MDCDialog, _super);
  34. function MDCDialog() {
  35. return _super !== null && _super.apply(this, arguments) || this;
  36. }
  37. Object.defineProperty(MDCDialog.prototype, "isOpen", {
  38. get: function () {
  39. return this.foundation.isOpen();
  40. },
  41. enumerable: false,
  42. configurable: true
  43. });
  44. Object.defineProperty(MDCDialog.prototype, "escapeKeyAction", {
  45. get: function () {
  46. return this.foundation.getEscapeKeyAction();
  47. },
  48. set: function (action) {
  49. this.foundation.setEscapeKeyAction(action);
  50. },
  51. enumerable: false,
  52. configurable: true
  53. });
  54. Object.defineProperty(MDCDialog.prototype, "scrimClickAction", {
  55. get: function () {
  56. return this.foundation.getScrimClickAction();
  57. },
  58. set: function (action) {
  59. this.foundation.setScrimClickAction(action);
  60. },
  61. enumerable: false,
  62. configurable: true
  63. });
  64. Object.defineProperty(MDCDialog.prototype, "autoStackButtons", {
  65. get: function () {
  66. return this.foundation.getAutoStackButtons();
  67. },
  68. set: function (autoStack) {
  69. this.foundation.setAutoStackButtons(autoStack);
  70. },
  71. enumerable: false,
  72. configurable: true
  73. });
  74. MDCDialog.attachTo = function (root) {
  75. return new MDCDialog(root);
  76. };
  77. MDCDialog.prototype.initialize = function (focusTrapFactory) {
  78. var e_1, _a;
  79. if (focusTrapFactory === void 0) { focusTrapFactory = function (el, focusOptions) {
  80. return new FocusTrap(el, focusOptions);
  81. }; }
  82. var container = this.root.querySelector(strings.CONTAINER_SELECTOR);
  83. if (!container) {
  84. throw new Error("Dialog component requires a " + strings.CONTAINER_SELECTOR + " container element");
  85. }
  86. this.container = container;
  87. this.content =
  88. this.root.querySelector(strings.CONTENT_SELECTOR);
  89. this.buttons = Array.from(this.root.querySelectorAll(strings.BUTTON_SELECTOR));
  90. this.defaultButton = this.root.querySelector("[" + strings.BUTTON_DEFAULT_ATTRIBUTE + "]");
  91. this.focusTrapFactory = focusTrapFactory;
  92. this.buttonRipples = [];
  93. try {
  94. for (var _b = __values(this.buttons), _c = _b.next(); !_c.done; _c = _b.next()) {
  95. var buttonEl = _c.value;
  96. this.buttonRipples.push(new MDCRipple(buttonEl));
  97. }
  98. }
  99. catch (e_1_1) { e_1 = { error: e_1_1 }; }
  100. finally {
  101. try {
  102. if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
  103. }
  104. finally { if (e_1) throw e_1.error; }
  105. }
  106. };
  107. MDCDialog.prototype.initialSyncWithDOM = function () {
  108. var _this = this;
  109. this.focusTrap = util.createFocusTrapInstance(this.container, this.focusTrapFactory, this.getInitialFocusEl() || undefined);
  110. this.handleClick = this.foundation.handleClick.bind(this.foundation);
  111. this.handleKeydown = this.foundation.handleKeydown.bind(this.foundation);
  112. this.handleDocumentKeydown =
  113. this.foundation.handleDocumentKeydown.bind(this.foundation);
  114. // this.handleLayout = this.layout.bind(this);
  115. this.handleOpening = function () {
  116. document.addEventListener('keydown', _this.handleDocumentKeydown);
  117. };
  118. this.handleClosing = function () {
  119. document.removeEventListener('keydown', _this.handleDocumentKeydown);
  120. };
  121. this.listen('click', this.handleClick);
  122. this.listen('keydown', this.handleKeydown);
  123. this.listen(strings.OPENING_EVENT, this.handleOpening);
  124. this.listen(strings.CLOSING_EVENT, this.handleClosing);
  125. };
  126. MDCDialog.prototype.destroy = function () {
  127. this.unlisten('click', this.handleClick);
  128. this.unlisten('keydown', this.handleKeydown);
  129. this.unlisten(strings.OPENING_EVENT, this.handleOpening);
  130. this.unlisten(strings.CLOSING_EVENT, this.handleClosing);
  131. this.handleClosing();
  132. this.buttonRipples.forEach(function (ripple) {
  133. ripple.destroy();
  134. });
  135. _super.prototype.destroy.call(this);
  136. };
  137. MDCDialog.prototype.layout = function () {
  138. this.foundation.layout();
  139. };
  140. MDCDialog.prototype.open = function () {
  141. this.foundation.open();
  142. };
  143. MDCDialog.prototype.close = function (action) {
  144. if (action === void 0) { action = ''; }
  145. this.foundation.close(action);
  146. };
  147. MDCDialog.prototype.getDefaultFoundation = function () {
  148. var _this = this;
  149. // DO NOT INLINE this variable. For backward compatibility, foundations take
  150. // a Partial<MDCFooAdapter>. To ensure we don't accidentally omit any
  151. // methods, we need a separate, strongly typed adapter variable.
  152. var adapter = {
  153. addBodyClass: function (className) {
  154. document.body.classList.add(className);
  155. },
  156. addClass: function (className) {
  157. _this.root.classList.add(className);
  158. },
  159. areButtonsStacked: function () { return util.areTopsMisaligned(_this.buttons); },
  160. clickDefaultButton: function () {
  161. if (_this.defaultButton && !_this.defaultButton.disabled) {
  162. _this.defaultButton.click();
  163. }
  164. },
  165. eventTargetMatches: function (target, selector) {
  166. return target ? matches(target, selector) : false;
  167. },
  168. getActionFromEvent: function (evt) {
  169. if (!evt.target) {
  170. return '';
  171. }
  172. var element = closest(evt.target, "[" + strings.ACTION_ATTRIBUTE + "]");
  173. return element && element.getAttribute(strings.ACTION_ATTRIBUTE);
  174. },
  175. getInitialFocusEl: function () { return _this.getInitialFocusEl(); },
  176. hasClass: function (className) { return _this.root.classList.contains(className); },
  177. isContentScrollable: function () { return util.isScrollable(_this.content); },
  178. notifyClosed: function (action) {
  179. _this.emit(strings.CLOSED_EVENT, action ? { action: action } : {});
  180. },
  181. notifyClosing: function (action) {
  182. _this.emit(strings.CLOSING_EVENT, action ? { action: action } : {});
  183. },
  184. notifyOpened: function () {
  185. _this.emit(strings.OPENED_EVENT, {});
  186. },
  187. notifyOpening: function () {
  188. _this.emit(strings.OPENING_EVENT, {});
  189. },
  190. releaseFocus: function () {
  191. _this.focusTrap.releaseFocus();
  192. },
  193. removeBodyClass: function (className) {
  194. document.body.classList.remove(className);
  195. },
  196. removeClass: function (className) {
  197. _this.root.classList.remove(className);
  198. },
  199. reverseButtons: function () {
  200. _this.buttons.reverse();
  201. _this.buttons.forEach(function (button) {
  202. button.parentElement.appendChild(button);
  203. });
  204. },
  205. trapFocus: function () {
  206. _this.focusTrap.trapFocus();
  207. },
  208. registerContentEventHandler: function (evt, handler) {
  209. if (_this.content instanceof HTMLElement) {
  210. _this.content.addEventListener(evt, handler);
  211. }
  212. },
  213. deregisterContentEventHandler: function (evt, handler) {
  214. if (_this.content instanceof HTMLElement) {
  215. _this.content.removeEventListener(evt, handler);
  216. }
  217. },
  218. isScrollableContentAtTop: function () {
  219. return util.isScrollAtTop(_this.content);
  220. },
  221. isScrollableContentAtBottom: function () {
  222. return util.isScrollAtBottom(_this.content);
  223. },
  224. registerWindowEventHandler: function (evt, handler) {
  225. window.addEventListener(evt, handler);
  226. },
  227. deregisterWindowEventHandler: function (evt, handler) {
  228. window.removeEventListener(evt, handler);
  229. },
  230. };
  231. return new MDCDialogFoundation(adapter);
  232. };
  233. MDCDialog.prototype.getInitialFocusEl = function () {
  234. return this.root.querySelector("[" + strings.INITIAL_FOCUS_ATTRIBUTE + "]");
  235. };
  236. return MDCDialog;
  237. }(MDCComponent));
  238. export { MDCDialog };
  239. //# sourceMappingURL=component.js.map