1<!--
2@license
3Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
4This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
5The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
7Code distributed by Google as part of the polymer project is also
8subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
9-->
10
11<link rel="import" href="../polymer/polymer.html">
12<link rel="import" href="../iron-a11y-announcer/iron-a11y-announcer.html">
13<link rel="import" href="../iron-overlay-behavior/iron-overlay-behavior.html">
14
15<!--
16Material design: [Snackbars & toasts](https://www.google.com/design/spec/components/snackbars-toasts.html)
17
18`paper-toast` provides a subtle notification toast. Only one `paper-toast` will
19be visible on screen.
20
21Use `opened` to show the toast:
22
23Example:
24
25    <paper-toast text="Hello world!" opened></paper-toast>
26
27Also `open()` or `show()` can be used to show the toast:
28
29Example:
30
31    <paper-button on-click="openToast">Open Toast</paper-button>
32    <paper-toast id="toast" text="Hello world!"></paper-toast>
33
34    ...
35
36    openToast: function() {
37      this.$.toast.open();
38    }
39
40Set `duration` to 0, a negative number or Infinity to persist the toast on screen:
41
42Example:
43
44    <paper-toast text="Terms and conditions" opened duration="0">
45      <a href="#">Show more</a>
46    </paper-toast>
47
48
49### Styling
50The following custom properties and mixins are available for styling:
51
52Custom property | Description | Default
53----------------|-------------|----------
54`--paper-toast-background-color` | The paper-toast background-color | `#323232`
55`--paper-toast-color` | The paper-toast color | `#f1f1f1`
56
57This element applies the mixin `--paper-font-common-base` but does not import `paper-styles/typography.html`.
58In order to apply the `Roboto` font to this element, make sure you've imported `paper-styles/typography.html`.
59
60@group Paper Elements
61@element paper-toast
62@demo demo/index.html
63@hero hero.svg
64-->
65
66<dom-module id="paper-toast">
67  <template>
68    <style>
69      :host {
70        display: block;
71        position: fixed;
72        background-color: var(--paper-toast-background-color, #323232);
73        color: var(--paper-toast-color, #f1f1f1);
74        min-height: 48px;
75        min-width: 288px;
76        padding: 16px 24px;
77        box-sizing: border-box;
78        box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
79        border-radius: 2px;
80        margin: 12px;
81        font-size: 14px;
82        cursor: default;
83        -webkit-transition: -webkit-transform 0.3s, opacity 0.3s;
84        transition: transform 0.3s, opacity 0.3s;
85        opacity: 0;
86        -webkit-transform: translateY(100px);
87        transform: translateY(100px);
88        @apply(--paper-font-common-base);
89      }
90
91      :host(.capsule) {
92        border-radius: 24px;
93      }
94
95      :host(.fit-bottom) {
96        width: 100%;
97        min-width: 0;
98        border-radius: 0;
99        margin: 0;
100      }
101
102      :host(.paper-toast-open) {
103        opacity: 1;
104        -webkit-transform: translateY(0px);
105        transform: translateY(0px);
106      }
107    </style>
108
109    <span id="label">{{text}}</span>
110    <content></content>
111  </template>
112
113  <script>
114    (function() {
115      // Keeps track of the toast currently opened.
116      var currentToast = null;
117
118      Polymer({
119        is: 'paper-toast',
120
121        behaviors: [
122          Polymer.IronOverlayBehavior
123        ],
124
125        properties: {
126          /**
127           * The element to fit `this` into.
128           * Overridden from `Polymer.IronFitBehavior`.
129           */
130          fitInto: {
131            type: Object,
132            value: window,
133            observer: '_onFitIntoChanged'
134          },
135
136          /**
137           * The orientation against which to align the dropdown content
138           * horizontally relative to `positionTarget`.
139           * Overridden from `Polymer.IronFitBehavior`.
140           */
141          horizontalAlign: {
142            type: String,
143            value: 'left'
144          },
145
146          /**
147           * The orientation against which to align the dropdown content
148           * vertically relative to `positionTarget`.
149           * Overridden from `Polymer.IronFitBehavior`.
150           */
151          verticalAlign: {
152            type: String,
153            value: 'bottom'
154          },
155
156          /**
157           * The duration in milliseconds to show the toast.
158           * Set to `0`, a negative number, or `Infinity`, to disable the
159           * toast auto-closing.
160           */
161          duration: {
162            type: Number,
163            value: 3000
164          },
165
166          /**
167           * The text to display in the toast.
168           */
169          text: {
170            type: String,
171            value: ''
172          },
173
174          /**
175           * Overridden from `IronOverlayBehavior`.
176           * Set to false to enable closing of the toast by clicking outside it.
177           */
178          noCancelOnOutsideClick: {
179            type: Boolean,
180            value: true
181          },
182
183          /**
184           * Overridden from `IronOverlayBehavior`.
185           * Set to true to disable auto-focusing the toast or child nodes with
186           * the `autofocus` attribute` when the overlay is opened.
187           */
188          noAutoFocus: {
189            type: Boolean,
190            value: true
191          }
192        },
193
194        listeners: {
195          'transitionend': '__onTransitionEnd'
196        },
197
198        /**
199         * Read-only. Deprecated. Use `opened` from `IronOverlayBehavior`.
200         * @property visible
201         * @deprecated
202         */
203        get visible() {
204          Polymer.Base._warn('`visible` is deprecated, use `opened` instead');
205          return this.opened;
206        },
207
208        /**
209         * Read-only. Can auto-close if duration is a positive finite number.
210         * @property _canAutoClose
211         */
212        get _canAutoClose() {
213          return this.duration > 0 && this.duration !== Infinity;
214        },
215
216        created: function() {
217          this._autoClose = null;
218          Polymer.IronA11yAnnouncer.requestAvailability();
219        },
220
221        /**
222         * Show the toast. Without arguments, this is the same as `open()` from `IronOverlayBehavior`.
223         * @param {(Object|string)=} properties Properties to be set before opening the toast.
224         * e.g. `toast.show('hello')` or `toast.show({text: 'hello', duration: 3000})`
225         */
226        show: function(properties) {
227          if (typeof properties == 'string') {
228            properties = { text: properties };
229          }
230          for (var property in properties) {
231            if (property.indexOf('_') === 0) {
232              Polymer.Base._warn('The property "' + property + '" is private and was not set.');
233            } else if (property in this) {
234              this[property] = properties[property];
235            } else {
236              Polymer.Base._warn('The property "' + property + '" is not valid.');
237            }
238          }
239          this.open();
240        },
241
242        /**
243         * Hide the toast. Same as `close()` from `IronOverlayBehavior`.
244         */
245        hide: function() {
246          this.close();
247        },
248
249        /**
250         * Called on transitions of the toast, indicating a finished animation
251         * @private
252         */
253        __onTransitionEnd: function(e) {
254          // there are different transitions that are happening when opening and
255          // closing the toast. The last one so far is for `opacity`.
256          // This marks the end of the transition, so we check for this to determine if this
257          // is the correct event.
258          if (e && e.target === this && e.propertyName === 'opacity') {
259            if (this.opened) {
260              this._finishRenderOpened();
261            } else {
262              this._finishRenderClosed();
263            }
264          }
265        },
266
267        /**
268         * Overridden from `IronOverlayBehavior`.
269         * Called when the value of `opened` changes.
270         */
271        _openedChanged: function() {
272          if (this._autoClose !== null) {
273            this.cancelAsync(this._autoClose);
274            this._autoClose = null;
275          }
276          if (this.opened) {
277            if (currentToast && currentToast !== this) {
278              currentToast.close();
279            }
280            currentToast = this;
281            this.fire('iron-announce', {
282              text: this.text
283            });
284            if (this._canAutoClose) {
285              this._autoClose = this.async(this.close, this.duration);
286            }
287          } else if (currentToast === this) {
288            currentToast = null;
289          }
290          Polymer.IronOverlayBehaviorImpl._openedChanged.apply(this, arguments);
291        },
292
293        /**
294         * Overridden from `IronOverlayBehavior`.
295         */
296        _renderOpened: function() {
297          this.classList.add('paper-toast-open');
298        },
299
300        /**
301         * Overridden from `IronOverlayBehavior`.
302         */
303        _renderClosed: function() {
304          this.classList.remove('paper-toast-open');
305        },
306
307        /**
308         * @private
309         */
310        _onFitIntoChanged: function(fitInto) {
311          this.positionTarget = fitInto;
312        }
313
314        /**
315         * Fired when `paper-toast` is opened.
316         *
317         * @event 'iron-announce'
318         * @param {{text: string}} detail Contains text that will be announced.
319         */
320      });
321    })();
322  </script>
323</dom-module>
324