jellyfin-web/dashboard-ui/bower_components/paper-dialog-behavior/paper-dialog-behavior.html
2016-01-29 21:43:11 -05:00

226 lines
7.3 KiB
HTML

<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../iron-overlay-behavior/iron-overlay-behavior.html">
<link rel="import" href="../iron-flex-layout/iron-flex-layout.html">
<link rel="import" href="../paper-styles/default-theme.html">
<link rel="import" href="../paper-styles/typography.html">
<link rel="import" href="../paper-styles/shadow.html">
<script>
/**
Use `Polymer.PaperDialogBehavior` and `paper-dialog-shared-styles.html` to implement a Material Design
dialog.
For example, if `<paper-dialog-impl>` implements this behavior:
<paper-dialog-impl>
<h2>Header</h2>
<div>Dialog body</div>
<div class="buttons">
<paper-button dialog-dismiss>Cancel</paper-button>
<paper-button dialog-confirm>Accept</paper-button>
</div>
</paper-dialog-impl>
`paper-dialog-shared-styles.html` provide styles for a header, content area, and an action area for buttons.
Use the `<h2>` tag for the header and the `buttons` class for the action area. You can use the
`paper-dialog-scrollable` element (in its own repository) if you need a scrolling content area.
Use the `dialog-dismiss` and `dialog-confirm` attributes on interactive controls to close the
dialog. If the user dismisses the dialog with `dialog-confirm`, the `closingReason` will update
to include `confirmed: true`.
### Styling
The following custom properties and mixins are available for styling.
Custom property | Description | Default
----------------|-------------|----------
`--paper-dialog-background-color` | Dialog background color | `--primary-background-color`
`--paper-dialog-color` | Dialog foreground color | `--primary-text-color`
`--paper-dialog` | Mixin applied to the dialog | `{}`
`--paper-dialog-title` | Mixin applied to the title (`<h2>`) element | `{}`
`--paper-dialog-button-color` | Button area foreground color | `--default-primary-color`
### Accessibility
This element has `role="dialog"` by default. Depending on the context, it may be more appropriate
to override this attribute with `role="alertdialog"`.
If `modal` is set, the element will set `aria-modal` and prevent the focus from exiting the element.
It will also ensure that focus remains in the dialog.
The `aria-labelledby` attribute will be set to the header element, if one exists.
@hero hero.svg
@demo demo/index.html
@polymerBehavior Polymer.PaperDialogBehavior
*/
Polymer.PaperDialogBehaviorImpl = {
hostAttributes: {
'role': 'dialog',
'tabindex': '-1'
},
properties: {
/**
* If `modal` is true, this implies `no-cancel-on-outside-click` and `with-backdrop`.
*/
modal: {
observer: '_modalChanged',
type: Boolean,
value: false
},
/** @type {?Node} */
_lastFocusedElement: {
type: Object
},
_boundOnFocus: {
type: Function,
value: function() {
return this._onFocus.bind(this);
}
},
_boundOnBackdropClick: {
type: Function,
value: function() {
return this._onBackdropClick.bind(this);
}
}
},
listeners: {
'tap': '_onDialogClick',
'iron-overlay-opened': '_onIronOverlayOpened',
'iron-overlay-closed': '_onIronOverlayClosed'
},
attached: function() {
// this._observer is used by iron-overlay-behavior
this._ariaObserver = Polymer.dom(this).observeNodes(this._updateAriaLabelledBy);
this._updateAriaLabelledBy();
},
detached: function() {
Polymer.dom(this).unobserveNodes(this._ariaObserver);
},
_modalChanged: function() {
if (this.modal) {
this.setAttribute('aria-modal', 'true');
} else {
this.setAttribute('aria-modal', 'false');
}
// modal implies noCancelOnOutsideClick and withBackdrop if true, don't overwrite
// those properties otherwise.
if (this.modal) {
this.noCancelOnOutsideClick = true;
this.withBackdrop = true;
}
},
_updateAriaLabelledBy: function() {
var header = Polymer.dom(this).querySelector('h2');
if (!header) {
this.removeAttribute('aria-labelledby');
return;
}
var headerId = header.getAttribute('id');
if (headerId && this.getAttribute('aria-labelledby') === headerId) {
return;
}
// set aria-describedBy to the header element
var labelledById;
if (headerId) {
labelledById = headerId;
} else {
labelledById = 'paper-dialog-header-' + new Date().getUTCMilliseconds();
header.setAttribute('id', labelledById);
}
this.setAttribute('aria-labelledby', labelledById);
},
_updateClosingReasonConfirmed: function(confirmed) {
this.closingReason = this.closingReason || {};
this.closingReason.confirmed = confirmed;
},
_onDialogClick: function(event) {
var target = Polymer.dom(event).rootTarget;
while (target && target !== this) {
if (target.hasAttribute) {
if (target.hasAttribute('dialog-dismiss')) {
this._updateClosingReasonConfirmed(false);
this.close();
event.stopPropagation();
break;
} else if (target.hasAttribute('dialog-confirm')) {
this._updateClosingReasonConfirmed(true);
this.close();
event.stopPropagation();
break;
}
}
target = Polymer.dom(target).parentNode;
}
},
_onIronOverlayOpened: function() {
if (this.modal) {
document.body.addEventListener('focus', this._boundOnFocus, true);
document.body.addEventListener('click', this._boundOnBackdropClick, true);
}
},
_onIronOverlayClosed: function() {
this._lastFocusedElement = null;
document.body.removeEventListener('focus', this._boundOnFocus, true);
document.body.removeEventListener('click', this._boundOnBackdropClick, true);
},
_onFocus: function(event) {
if (this.modal && this._manager.currentOverlay() === this) {
if (Polymer.dom(event).path.indexOf(this) !== -1) {
this._lastFocusedElement = event.target;
} else if (this._lastFocusedElement) {
this._lastFocusedElement.focus();
} else {
this._focusNode.focus();
}
}
},
_onBackdropClick: function(event) {
if (this.modal && this._manager.currentOverlay() === this && Polymer.dom(event).path.indexOf(this) === -1) {
if (this._lastFocusedElement) {
this._lastFocusedElement.focus();
} else {
this._focusNode.focus();
}
}
}
};
/** @polymerBehavior */
Polymer.PaperDialogBehavior = [Polymer.IronOverlayBehavior, Polymer.PaperDialogBehaviorImpl];
</script>