Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Commit

Permalink
fix(dialog): Closing Animations not running #433 (#504)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: 

-  Dialogs do not require a style="visibility:hidden" attribute in html.
-  registerTransitionEndHandler, deregisterTransitionEndHandler, and isDialog methods must be implemented by the adapter
  • Loading branch information
tranrate authored and amsheehan committed May 22, 2017
1 parent a5c6542 commit 2b03c6b
Show file tree
Hide file tree
Showing 8 changed files with 235 additions and 177 deletions.
189 changes: 88 additions & 101 deletions demos/dialog.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
<!DOCTYPE html>
<!--
Copyright 2017 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Expand All @@ -31,11 +28,9 @@
margin: 0;
box-sizing: border-box;
}

.demo-content > button {
margin-bottom: 6px;
}

.mdc-theme--dark {
background-color: #303030;
}
Expand Down Expand Up @@ -84,128 +79,121 @@ <h2 id="mdc-dialog-default-label" class="mdc-dialog__header__title">

<div class="demo-body">
<aside id="mdc-dialog-default"
style="visibility:hidden;"
class="mdc-dialog"
role="alertdialog"
aria-hidden="true"
aria-labelledby="mdc-dialog-default-label"
aria-describedby="mdc-dialog-default-description">
<div class="mdc-dialog__surface">
<header class="mdc-dialog__header">
<h2 id="mdc-dialog-default-label" class="mdc-dialog__header__title">
Use Google's location service?
</h2>
</header>
<section id="mdc-dialog-default-description" class="mdc-dialog__body">
Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.
</section>
<footer class="mdc-dialog__footer">
<button type="button" class="mdc-button mdc-dialog__footer__button mdc-dialog__footer__button--cancel">Decline</button>
<button type="button" class="mdc-button mdc-dialog__footer__button mdc-dialog__footer__button--accept">Accept</button>
</footer>
</div>
<div class="mdc-dialog__backdrop"></div>
</aside>
class="mdc-dialog"
role="alertdialog"
aria-hidden="true"
aria-labelledby="mdc-dialog-default-label"
aria-describedby="mdc-dialog-default-description">
<div class="mdc-dialog__surface">
<header class="mdc-dialog__header">
<h2 id="mdc-dialog-default-label" class="mdc-dialog__header__title">
Use Google's location service?
</h2>
</header>
<section id="mdc-dialog-default-description" class="mdc-dialog__body">
Let Google help apps determine location. This means sending anonymous location data to Google, even when no apps are running.
</section>
<footer class="mdc-dialog__footer">
<button type="button" class="mdc-button mdc-dialog__footer__button mdc-dialog__footer__button--cancel">Decline</button>
<button type="button" class="mdc-button mdc-dialog__footer__button mdc-dialog__footer__button--accept">Accept</button>
</footer>
</div>
<div class="mdc-dialog__backdrop"></div>
</aside>

<aside id="mdc-dialog-with-list"
style="visibility:hidden;"
class="mdc-dialog"
role="alertdialog"
aria-hidden="true"
aria-labelledby="mdc-dialog-with-list-label"
aria-describedby="mdc-dialog-with-list-description">
<div class="mdc-dialog__surface">
<header class="mdc-dialog__header">
<h2 id="mdc-dialog-with-list-label" class="mdc-dialog__header__title">
Choose a Ringtone
</h2>
</header>
<section id="mdc-dialog-with-list-description" class="mdc-dialog__body mdc-dialog__body--scrollable">
<ul class="mdc-list">
<li class="mdc-list-item">None</li>
<li class="mdc-list-item">Callisto</li>
<li class="mdc-list-item">Ganymede</li>
<li class="mdc-list-item">Luna</li>
<li class="mdc-list-item">Marimba</li>
<li class="mdc-list-item">Schwifty</li>
<li class="mdc-list-item">Callisto</li>
<li class="mdc-list-item">Ganymede</li>
<li class="mdc-list-item">Luna</li>
<li class="mdc-list-item">Marimba</li>
<li class="mdc-list-item">Schwifty</li>
</ul>
</section>
<footer class="mdc-dialog__footer">
<button type="button" class="mdc-button mdc-dialog__footer__button mdc-dialog__footer__button--cancel">Decline</button>
<button type="button" class="mdc-button mdc-dialog__footer__button mdc-dialog__footer__button--accept">Accept</button>
</footer>
</div>
<div class="mdc-dialog__backdrop"></div>
</aside>
</div>
<section class="example">
<button id="default-dialog-activation" class="mdc-button mdc-button--primary mdc-button--raised">Show Dialog</button>
<button id="dialog-with-list-activation" class="mdc-button mdc-button--primary mdc-button--raised">Show Scrolling Dialog</button>
<div class="mdc-form-field">
<div class="mdc-checkbox">
<input type="checkbox"
<aside id="mdc-dialog-with-list"
class="mdc-dialog"
role="alertdialog"
aria-hidden="true"
aria-labelledby="mdc-dialog-with-list-label"
aria-describedby="mdc-dialog-with-list-description">
<div class="mdc-dialog__surface">
<header class="mdc-dialog__header">
<h2 id="mdc-dialog-with-list-label" class="mdc-dialog__header__title">
Choose a Ringtone
</h2>
</header>
<section id="mdc-dialog-with-list-description" class="mdc-dialog__body mdc-dialog__body--scrollable">
<ul class="mdc-list">
<li class="mdc-list-item">None</li>
<li class="mdc-list-item">Callisto</li>
<li class="mdc-list-item">Ganymede</li>
<li class="mdc-list-item">Luna</li>
<li class="mdc-list-item">Marimba</li>
<li class="mdc-list-item">Schwifty</li>
<li class="mdc-list-item">Callisto</li>
<li class="mdc-list-item">Ganymede</li>
<li class="mdc-list-item">Luna</li>
<li class="mdc-list-item">Marimba</li>
<li class="mdc-list-item">Schwifty</li>
</ul>
</section>
<footer class="mdc-dialog__footer">
<button type="button" class="mdc-button mdc-dialog__footer__button mdc-dialog__footer__button--cancel">Decline</button>
<button type="button" class="mdc-button mdc-dialog__footer__button mdc-dialog__footer__button--accept">Accept</button>
</footer>
</div>
<div class="mdc-dialog__backdrop"></div>
</aside>
</div>
<section class="example">
<button id="default-dialog-activation" class="mdc-button mdc-button--primary mdc-button--raised">Show Dialog</button>
<button id="dialog-with-list-activation" class="mdc-button mdc-button--primary mdc-button--raised">Show Scrolling Dialog</button>
<div class="mdc-form-field">
<div class="mdc-checkbox">
<input type="checkbox"
id="toggle-rtl"
class="mdc-checkbox__native-control"/>
<div class="mdc-checkbox__background">
<svg class="mdc-checkbox__checkmark"
viewBox="0 0 24 24">
<path class="mdc-checkbox__checkmark__path"
fill="none"
stroke="white"
d="M1.73,12.91 8.1,19.28 22.79,4.59"/>
</svg>
<div class="mdc-checkbox__mixedmark"></div>
<div class="mdc-checkbox__background">
<svg class="mdc-checkbox__checkmark"
viewBox="0 0 24 24">
<path class="mdc-checkbox__checkmark__path"
fill="none"
stroke="white"
d="M1.73,12.91 8.1,19.28 22.79,4.59"/>
</svg>
<div class="mdc-checkbox__mixedmark"></div>
</div>
</div>
<label for="toggle-rtl">Toggle RTL</label>
</div>
<label for="toggle-rtl">Toggle RTL</label>
</div>

<div class="mdc-form-field">
<div class="mdc-checkbox">
<input type="checkbox"
<div class="mdc-form-field">
<div class="mdc-checkbox">
<input type="checkbox"
id="toggle-dark"
class="mdc-checkbox__native-control"/>
<div class="mdc-checkbox__background">
<svg class="mdc-checkbox__checkmark"
<div class="mdc-checkbox__background">
<svg class="mdc-checkbox__checkmark"
viewBox="0 0 24 24">
<path class="mdc-checkbox__checkmark__path"
fill="none"
stroke="white"
d="M1.73,12.91 8.1,19.28 22.79,4.59"/>
</svg>
<div class="mdc-checkbox__mixedmark"></div>
<path class="mdc-checkbox__checkmark__path"
fill="none"
stroke="white"
d="M1.73,12.91 8.1,19.28 22.79,4.59"/>
</svg>
<div class="mdc-checkbox__mixedmark"></div>
</div>
</div>
<label for="toggle-dark">Toggle Dark</label>
</div>
<label for="toggle-dark">Toggle Dark</label>
</div>
</section>

</section>
</main>
<script src="assets/material-components-web.js" charset="utf-8"></script>
<script>
(function() {

var dialog = new mdc.dialog.MDCDialog(document.querySelector('#mdc-dialog-default'));

dialog.listen('MDCDialog:accept', function() {
console.log('accepted');
});

dialog.listen('MDCDialog:cancel', function() {
console.log('canceled');
});

document.querySelector('#default-dialog-activation').addEventListener('click', function (evt) {
dialog.lastFocusedTarget = evt.target;
dialog.show();
});

var dialogScrollable = new mdc.dialog.MDCDialog(document.querySelector('#mdc-dialog-with-list'));

document.querySelector('#dialog-with-list-activation').addEventListener('click', function (evt) {
dialogScrollable.lastFocusedTarget = evt.target;
dialogScrollable.show();
Expand All @@ -229,7 +217,6 @@ <h2 id="mdc-dialog-with-list-label" class="mdc-dialog__header__title">
document.getElementById('toggle-dark').addEventListener('change', function(evt) {
document.body.classList[evt.target.checked ? 'add' : 'remove']('mdc-theme--dark');
});

// Hack to work around style-loader async loading styles
setTimeout(function() {
mdc.ripple.MDCRipple.attachTo(document.querySelector('#default-dialog-activation'));
Expand Down
5 changes: 3 additions & 2 deletions packages/mdc-dialog/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ Dialogs inform users about a specific task and may contain critical information

```html
<aside id="my-mdc-dialog"
style="visibility:hidden"
class="mdc-dialog"
role="alertdialog"
aria-labelledby="my-mdc-dialog-label"
Expand Down Expand Up @@ -76,7 +75,6 @@ Some dialogs will not be tall enough to accomodate everything you would like to

```html
<aside id="mdc-dialog-with-list"
style="visibility:hidden"
class="mdc-dialog"
role="alertdialog"
aria-labelledby="mdc-dialog-with-list-label"
Expand Down Expand Up @@ -240,8 +238,11 @@ do so. We provide instructions on how to add ripples to buttons within the [mdc-
| `deregisterSurfaceInteractionHandler(evt: string, handler: EventListener) => void` | Deregisters an event handler from the dialog surface element. |
| `registerDocumentKeydownHandler(handler: EventListener) => void` | Registers an event handler on the `document` object for a `keydown` event. |
| `deregisterDocumentKeydownHandler(handler: EventListener) => void` | Deregisters an event handler on the `document` object for a `keydown` event. |
| `registerTransitionEndHandler: (handler: EventListener) => void` | Registers an event handler to be called when a transitionend event is triggered on the dialog container sub-element element. |
| `deregisterTransitionEndHandler: (handler: EventListener) => void` | Deregisters an event handler from a transitionend event listener. This will only be called with handlers that have previously been passed to registerTransitionEndHandler calls. |
| `notifyAccept() => {}` | Broadcasts an event denoting that the user has accepted the dialog. |
| `notifyCancel() => {}` | Broadcasts an event denoting that the user has cancelled the dialog. |
| `isDialog(el: Element) => boolean` | Returns boolean indicating whether the provided element is the dialog surface element. |
| `trapFocusOnSurface() => {}` | Sets up the DOM which the dialog is contained in such that focusability is restricted to the elements on the dialog surface (see [Handling Focus Trapping](#handling-focus-trapping) below for more details). |
| `untrapFocusOnSurface() => {}` | Removes any affects of focus trapping on the dialog surface from the DOM (see [Handling Focus Trapping](#handling-focus-trapping) below for more details). |

Expand Down
1 change: 1 addition & 0 deletions packages/mdc-dialog/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
export const cssClasses = {
ROOT: 'mdc-dialog',
OPEN: 'mdc-dialog--open',
ANIMATING: 'mdc-dialog--animating',
BACKDROP: 'mdc-dialog__backdrop',
SCROLL_LOCK: 'mdc-dialog-scroll-lock',
ACCEPT_BTN: 'mdc-dialog__footer__button--accept',
Expand Down
48 changes: 35 additions & 13 deletions packages/mdc-dialog/foundation.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export default class MDCDialogFoundation extends MDCFoundation {
return {
addClass: (/* className: string */) => {},
removeClass: (/* className: string */) => {},
setStyle: (/* propertyName: string, value: string */) => {},
addBodyClass: (/* className: string */) => {},
removeBodyClass: (/* className: string */) => {},
eventTargetHasClass: (/* target: EventTarget, className: string */) => /* boolean */ false,
Expand All @@ -40,16 +39,18 @@ export default class MDCDialogFoundation extends MDCFoundation {
deregisterSurfaceInteractionHandler: (/* evt: string, handler: EventListener */) => {},
registerDocumentKeydownHandler: (/* handler: EventListener */) => {},
deregisterDocumentKeydownHandler: (/* handler: EventListener */) => {},
registerTransitionEndHandler: (/* handler: EventListener */) => {},

This comment has been minimized.

Copy link
@ensecoz

ensecoz Jul 28, 2017

does this line should be deregister? @tranrate

deregisterTransitionEndHandler: (/* handler: EventListener */) => {},
notifyAccept: () => {},
notifyCancel: () => {},
trapFocusOnSurface: () => {},
untrapFocusOnSurface: () => {},
isDialog: (/* el: Element */) => /* boolean */ false,
};
}

constructor(adapter) {
super(Object.assign(MDCDialogFoundation.defaultAdapter, adapter));

this.isOpen_ = false;
this.componentClickHandler_ = () => this.cancel(true);
this.dialogClickHandler_ = (evt) => this.handleDialogClick_(evt);
Expand All @@ -58,34 +59,43 @@ export default class MDCDialogFoundation extends MDCFoundation {
this.cancel(true);
}
};
}
this.transitionEndHandler_ = (evt) => this.handleTransitionEnd_(evt);
};

destroy() {
this.close();
// Ensure that dialog is cleaned up when destroyed
if (this.isOpen_) {
this.adapter_.deregisterSurfaceInteractionHandler('click', this.dialogClickHandler_);
this.adapter_.deregisterDocumentKeydownHandler(this.documentKeydownHandler_);
this.adapter_.deregisterInteractionHandler('click', this.componentClickHandler_);
this.adapter_.untrapFocusOnSurface();
this.adapter_.deregisterTransitionEndHandler(this.transitionEndHandler_);
this.adapter_.removeClass(MDCDialogFoundation.cssClasses.ANIMATING);
this.adapter_.removeClass(MDCDialogFoundation.cssClasses.OPEN);
this.enableScroll_();

This comment has been minimized.

Copy link
@ensecoz

ensecoz Jul 28, 2017

this never get call if user accept the dialog and remove the dialog from the page (the transitionEnd is never finish) and the result is that the scroll-lock never get removed.

}
}

open() {
this.isOpen_ = true;
this.disableScroll_();
this.adapter_.setStyle('visibility', 'visible');
this.adapter_.addClass(MDCDialogFoundation.cssClasses.OPEN);
this.adapter_.trapFocusOnSurface();

this.adapter_.registerDocumentKeydownHandler(this.documentKeydownHandler_);
this.adapter_.registerSurfaceInteractionHandler('click', this.dialogClickHandler_);
this.adapter_.registerInteractionHandler('click', this.componentClickHandler_);
this.adapter_.registerTransitionEndHandler(this.transitionEndHandler_);
this.adapter_.addClass(MDCDialogFoundation.cssClasses.ANIMATING);
this.adapter_.addClass(MDCDialogFoundation.cssClasses.OPEN);
}

close() {
this.isOpen_ = false;
this.adapter_.untrapFocusOnSurface();
this.adapter_.removeClass(MDCDialogFoundation.cssClasses.OPEN);
this.adapter_.setStyle('visibility', 'hidden');
this.enableScroll_();

this.adapter_.deregisterSurfaceInteractionHandler('click', this.dialogClickHandler_);
this.adapter_.deregisterDocumentKeydownHandler(this.documentKeydownHandler_);
this.adapter_.deregisterInteractionHandler('click', this.componentClickHandler_);
this.adapter_.untrapFocusOnSurface();
this.adapter_.registerTransitionEndHandler(this.transitionEndHandler_);
this.adapter_.addClass(MDCDialogFoundation.cssClasses.ANIMATING);
this.adapter_.removeClass(MDCDialogFoundation.cssClasses.OPEN);
}

isOpen() {
Expand Down Expand Up @@ -118,6 +128,18 @@ export default class MDCDialogFoundation extends MDCFoundation {
}
}

handleTransitionEnd_(evt) {
if (this.adapter_.isDialog(evt.target)) {
this.adapter_.deregisterTransitionEndHandler(this.transitionEndHandler_);
this.adapter_.removeClass(MDCDialogFoundation.cssClasses.ANIMATING);
if (this.isOpen_) {
this.adapter_.trapFocusOnSurface();
} else {
this.enableScroll_();
};
};
};

disableScroll_() {
this.adapter_.addBodyClass(cssClasses.SCROLL_LOCK);
}
Expand Down
Loading

0 comments on commit 2b03c6b

Please sign in to comment.