3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
4 This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6 The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
7 Code distributed by Google as part of the polymer project is also
8 subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
11 <link rel=
"import" href=
"../polymer/polymer.html">
12 <link rel=
"import" href=
"../iron-overlay-behavior/iron-overlay-behavior.html">
13 <link rel=
"import" href=
"../paper-styles/paper-styles.html">
18 Use `Polymer.PaperDialogBehavior` and `paper-dialog-common.css` to implement a Material Design
21 For example, if `<paper-dialog-impl>` implements this behavior:
25 <div>Dialog body</div>
27 <paper-button dialog-dismiss>Cancel</paper-button>
28 <paper-button dialog-confirm>Accept</paper-button>
32 `paper-dialog-common.css` provide styles for a header, content area, and an action area for buttons.
33 Use the `<h2>` tag for the header and the `buttons` class for the action area. You can use the
34 `paper-dialog-scrollable` element (in its own repository) if you need a scrolling content area.
36 Use the `dialog-dismiss` and `dialog-confirm` attributes on interactive controls to close the
37 dialog. If the user dismisses the dialog with `dialog-confirm`, the `closingReason` will update
38 to include `confirmed: true`.
42 The following custom properties and mixins are available for styling.
44 Custom property | Description | Default
45 ----------------|-------------|----------
46 `--paper-dialog-background-color` | Dialog background color | `--primary-background-color`
47 `--paper-dialog-color` | Dialog foreground color | `--primary-text-color`
48 `--paper-dialog` | Mixin applied to the dialog | `{}`
49 `--paper-dialog-title` | Mixin applied to the title (`<h2>`) element | `{}`
50 `--paper-dialog-button-color` | Button area foreground color | `--default-primary-color`
54 This element has `role="dialog"` by default. Depending on the context, it may be more appropriate
55 to override this attribute with `role="alertdialog"`.
57 If `modal` is set, the element will set `aria-modal` and prevent the focus from exiting the element.
58 It will also ensure that focus remains in the dialog.
60 The `aria-labelledby` attribute will be set to the header element, if one exists.
64 @polymerBehavior Polymer.PaperDialogBehavior
67 Polymer
.PaperDialogBehaviorImpl
= {
77 * If `modal` is true, this implies `no-cancel-on-outside-click` and `with-backdrop`.
80 observer
: '_modalChanged',
86 _lastFocusedElement
: {
93 return this._onFocus
.bind(this);
97 _boundOnBackdropClick
: {
100 return this._onBackdropClick
.bind(this);
107 'click': '_onDialogClick',
108 'iron-overlay-opened': '_onIronOverlayOpened',
109 'iron-overlay-closed': '_onIronOverlayClosed'
112 attached: function() {
113 this._observer
= this._observe(this);
114 this._updateAriaLabelledBy();
117 detached: function() {
118 if (this._observer
) {
119 this._observer
.disconnect();
123 _observe: function(node
) {
124 var observer
= new MutationObserver(function() {
125 this._updateAriaLabelledBy();
127 observer
.observe(node
, {
134 _modalChanged: function() {
136 this.setAttribute('aria-modal', 'true');
138 this.setAttribute('aria-modal', 'false');
140 // modal implies noCancelOnOutsideClick and withBackdrop if true, don't overwrite
141 // those properties otherwise.
143 this.noCancelOnOutsideClick
= true;
144 this.withBackdrop
= true;
148 _updateAriaLabelledBy: function() {
149 var header
= Polymer
.dom(this).querySelector('h2');
151 this.removeAttribute('aria-labelledby');
154 var headerId
= header
.getAttribute('id');
155 if (headerId
&& this.getAttribute('aria-labelledby') === headerId
) {
158 // set aria-describedBy to the header element
161 labelledById
= headerId
;
163 labelledById
= 'paper-dialog-header-' + new Date().getUTCMilliseconds();
164 header
.setAttribute('id', labelledById
);
166 this.setAttribute('aria-labelledby', labelledById
);
169 _updateClosingReasonConfirmed: function(confirmed
) {
170 this.closingReason
= this.closingReason
|| {};
171 this.closingReason
.confirmed
= confirmed
;
174 _onDialogClick: function(event
) {
175 var target
= event
.target
;
176 while (target
&& target
!== this) {
177 if (target
.hasAttribute
) {
178 if (target
.hasAttribute('dialog-dismiss')) {
179 this._updateClosingReasonConfirmed(false);
182 } else if (target
.hasAttribute('dialog-confirm')) {
183 this._updateClosingReasonConfirmed(true);
188 target
= target
.parentNode
;
192 _onIronOverlayOpened: function() {
194 document
.body
.addEventListener('focus', this._boundOnFocus
, true);
195 this.backdropElement
.addEventListener('click', this._boundOnBackdropClick
);
199 _onIronOverlayClosed: function() {
200 document
.body
.removeEventListener('focus', this._boundOnFocus
, true);
201 this.backdropElement
.removeEventListener('click', this._boundOnBackdropClick
);
204 _onFocus: function(event
) {
206 var target
= event
.target
;
207 while (target
&& target
!== this && target
!== document
.body
) {
208 target
= target
.parentNode
;
211 if (target
=== document
.body
) {
212 if (this._lastFocusedElement
) {
213 this._lastFocusedElement
.focus();
215 this._focusNode
.focus();
218 this._lastFocusedElement
= event
.target
;
224 _onBackdropClick: function() {
226 if (this._lastFocusedElement
) {
227 this._lastFocusedElement
.focus();
229 this._focusNode
.focus();
236 /** @polymerBehavior */
237 Polymer
.PaperDialogBehavior
= [Polymer
.IronOverlayBehavior
, Polymer
.PaperDialogBehaviorImpl
];