Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / third_party / polymer / v1_0 / components / paper-dialog-behavior / paper-dialog-behavior.html
blob0afcb8b7f82da317e901295aa392c7f80d95fd3c
1 <!--
2 @license
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
9 -->
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">
15 <script>
17 /**
18 Use `Polymer.PaperDialogBehavior` and `paper-dialog-common.css` to implement a Material Design
19 dialog.
21 For example, if `<paper-dialog-impl>` implements this behavior:
23 <paper-dialog-impl>
24 <h2>Header</h2>
25 <div>Dialog body</div>
26 <div class="buttons">
27 <paper-button dialog-dismiss>Cancel</paper-button>
28 <paper-button dialog-confirm>Accept</paper-button>
29 </div>
30 </paper-dialog-impl>
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`.
40 ### Styling
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`
52 ### Accessibility
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.
62 @hero hero.svg
63 @demo demo/index.html
64 @polymerBehavior Polymer.PaperDialogBehavior
67 Polymer.PaperDialogBehaviorImpl = {
69 hostAttributes: {
70 'role': 'dialog',
71 'tabindex': '-1'
74 properties: {
76 /**
77 * If `modal` is true, this implies `no-cancel-on-outside-click` and `with-backdrop`.
79 modal: {
80 observer: '_modalChanged',
81 type: Boolean,
82 value: false
85 /** @type {?Node} */
86 _lastFocusedElement: {
87 type: Object
90 _boundOnFocus: {
91 type: Function,
92 value: function() {
93 return this._onFocus.bind(this);
97 _boundOnBackdropClick: {
98 type: Function,
99 value: function() {
100 return this._onBackdropClick.bind(this);
106 listeners: {
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();
126 }.bind(this));
127 observer.observe(node, {
128 childList: true,
129 subtree: true
131 return observer;
134 _modalChanged: function() {
135 if (this.modal) {
136 this.setAttribute('aria-modal', 'true');
137 } else {
138 this.setAttribute('aria-modal', 'false');
140 // modal implies noCancelOnOutsideClick and withBackdrop if true, don't overwrite
141 // those properties otherwise.
142 if (this.modal) {
143 this.noCancelOnOutsideClick = true;
144 this.withBackdrop = true;
148 _updateAriaLabelledBy: function() {
149 var header = Polymer.dom(this).querySelector('h2');
150 if (!header) {
151 this.removeAttribute('aria-labelledby');
152 return;
154 var headerId = header.getAttribute('id');
155 if (headerId && this.getAttribute('aria-labelledby') === headerId) {
156 return;
158 // set aria-describedBy to the header element
159 var labelledById;
160 if (headerId) {
161 labelledById = headerId;
162 } else {
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);
180 this.close();
181 break;
182 } else if (target.hasAttribute('dialog-confirm')) {
183 this._updateClosingReasonConfirmed(true);
184 this.close();
185 break;
188 target = target.parentNode;
192 _onIronOverlayOpened: function() {
193 if (this.modal) {
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) {
205 if (this.modal) {
206 var target = event.target;
207 while (target && target !== this && target !== document.body) {
208 target = target.parentNode;
210 if (target) {
211 if (target === document.body) {
212 if (this._lastFocusedElement) {
213 this._lastFocusedElement.focus();
214 } else {
215 this._focusNode.focus();
217 } else {
218 this._lastFocusedElement = event.target;
224 _onBackdropClick: function() {
225 if (this.modal) {
226 if (this._lastFocusedElement) {
227 this._lastFocusedElement.focus();
228 } else {
229 this._focusNode.focus();
236 /** @polymerBehavior */
237 Polymer.PaperDialogBehavior = [Polymer.IronOverlayBehavior, Polymer.PaperDialogBehaviorImpl];
239 </script>