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-flex-layout/iron-flex-layout.html">
13<link rel="import" href="../iron-range-behavior/iron-range-behavior.html">
14<link rel="import" href="../paper-styles/color.html">
15
16<!--
17Material design: [Progress & activity](https://www.google.com/design/spec/components/progress-activity.html)
18
19The progress bars are for situations where the percentage completed can be
20determined. They give users a quick sense of how much longer an operation
21will take.
22
23Example:
24
25    <paper-progress value="10"></paper-progress>
26
27There is also a secondary progress which is useful for displaying intermediate
28progress, such as the buffer level during a streaming playback progress bar.
29
30Example:
31
32    <paper-progress value="10" secondary-progress="30"></paper-progress>
33
34### Styling progress bar:
35
36To change the active progress bar color:
37
38    paper-progress {
39       --paper-progress-active-color: #e91e63;
40    }
41
42To change the secondary progress bar color:
43
44    paper-progress {
45      --paper-progress-secondary-color: #f8bbd0;
46    }
47
48To change the progress bar background color:
49
50    paper-progress {
51      --paper-progress-container-color: #64ffda;
52    }
53
54Add the class `transiting` to a paper-progress to animate the progress bar when
55the value changed. You can also customize the transition:
56
57    paper-progress {
58      --paper-progress-transition-duration: 0.08s;
59      --paper-progress-transition-timing-function: ease;
60      --paper-progress-transition-transition-delay: 0s;
61    }
62
63To change the duration of the indeterminate cycle:
64
65    paper-progress {
66      --paper-progress-indeterminate-cycle-duration: 2s;
67    }
68
69The following mixins are available for styling:
70
71Custom property                                  | Description                                 | Default
72-------------------------------------------------|---------------------------------------------|--------------
73`--paper-progress-container`                     | Mixin applied to container                  | `{}`
74`--paper-progress-transition-duration`           | Duration of the transition                  | `0.008s`
75`--paper-progress-transition-timing-function`    | The timing function for the transition      | `ease`
76`--paper-progress-transition-delay`              | delay for the transition                    | `0s`
77`--paper-progress-container-color`               | Color of the container                      | `--google-grey-300`
78`--paper-progress-active-color`                  | The color of the active bar                 | `--google-green-500`
79`--paper-progress-secondary-color`               | The color of the secondary bar              | `--google-green-100`
80`--paper-progress-disabled-active-color`         | The color of the active bar if disabled     | `--google-grey-500`
81`--paper-progress-disabled-secondary-color`      | The color of the secondary bar if disabled  | `--google-grey-300`
82`--paper-progress-height`                        | The height of the progress bar              | `4px`
83`--paper-progress-indeterminate-cycle-duration`  | Duration of an indeterminate cycle          | `2s`
84
85@group Paper Elements
86@element paper-progress
87@hero hero.svg
88@demo demo/index.html
89-->
90
91<dom-module id="paper-progress">
92  <template>
93    <style>
94      :host {
95        display: block;
96        width: 200px;
97        position: relative;
98        overflow: hidden;
99      }
100
101      :host([hidden]) {
102        display: none !important;
103      }
104
105      #progressContainer {
106        @apply(--paper-progress-container);
107        position: relative;
108      }
109
110      #progressContainer,
111      /* the stripe for the indeterminate animation*/
112      .indeterminate::after {
113        height: var(--paper-progress-height, 4px);
114      }
115
116      #primaryProgress,
117      #secondaryProgress,
118      .indeterminate::after {
119        @apply(--layout-fit);
120      }
121
122      #progressContainer,
123      .indeterminate::after {
124        background: var(--paper-progress-container-color, --google-grey-300);
125      }
126
127      :host(.transiting) #primaryProgress,
128      :host(.transiting) #secondaryProgress {
129        -webkit-transition-property: -webkit-transform;
130        transition-property: transform;
131
132        /* Duration */
133        -webkit-transition-duration: var(--paper-progress-transition-duration, 0.08s);
134        transition-duration: var(--paper-progress-transition-duration, 0.08s);
135
136        /* Timing function */
137        -webkit-transition-timing-function: var(--paper-progress-transition-timing-function, ease);
138        transition-timing-function: var(--paper-progress-transition-timing-function, ease);
139
140        /* Delay */
141        -webkit-transition-delay: var(--paper-progress-transition-delay, 0s);
142        transition-delay: var(--paper-progress-transition-delay, 0s);
143      }
144
145      #primaryProgress,
146      #secondaryProgress {
147        @apply(--layout-fit);
148        -webkit-transform-origin: left center;
149        transform-origin: left center;
150        -webkit-transform: scaleX(0);
151        transform: scaleX(0);
152        will-change: transform;
153      }
154
155      #primaryProgress {
156        background: var(--paper-progress-active-color, --google-green-500);
157      }
158
159      #secondaryProgress {
160        background: var(--paper-progress-secondary-color, --google-green-100);
161      }
162
163      :host([disabled]) #primaryProgress {
164        background: var(--paper-progress-disabled-active-color, --google-grey-500);
165      }
166
167      :host([disabled]) #secondaryProgress {
168        background: var(--paper-progress-disabled-secondary-color, --google-grey-300);
169      }
170
171      :host(:not([disabled])) #primaryProgress.indeterminate {
172        -webkit-transform-origin: right center;
173        transform-origin: right center;
174        -webkit-animation: indeterminate-bar var(--paper-progress-indeterminate-cycle-duration, 2s) linear infinite;
175        animation: indeterminate-bar var(--paper-progress-indeterminate-cycle-duration, 2s) linear infinite;
176      }
177
178      :host(:not([disabled])) #primaryProgress.indeterminate::after {
179        content: "";
180        -webkit-transform-origin: center center;
181        transform-origin: center center;
182
183        -webkit-animation: indeterminate-splitter var(--paper-progress-indeterminate-cycle-duration, 2s) linear infinite;
184        animation: indeterminate-splitter var(--paper-progress-indeterminate-cycle-duration, 2s) linear infinite;
185      }
186
187      @-webkit-keyframes indeterminate-bar {
188        0% {
189          -webkit-transform: scaleX(1) translateX(-100%);
190        }
191        50% {
192          -webkit-transform: scaleX(1) translateX(0%);
193        }
194        75% {
195          -webkit-transform: scaleX(1) translateX(0%);
196          -webkit-animation-timing-function: cubic-bezier(.28,.62,.37,.91);
197        }
198        100% {
199          -webkit-transform: scaleX(0) translateX(0%);
200        }
201      }
202
203      @-webkit-keyframes indeterminate-splitter {
204        0% {
205          -webkit-transform: scaleX(.75) translateX(-125%);
206        }
207        30% {
208          -webkit-transform: scaleX(.75) translateX(-125%);
209          -webkit-animation-timing-function: cubic-bezier(.42,0,.6,.8);
210        }
211        90% {
212          -webkit-transform: scaleX(.75) translateX(125%);
213        }
214        100% {
215          -webkit-transform: scaleX(.75) translateX(125%);
216        }
217      }
218
219      @keyframes indeterminate-bar {
220        0% {
221          transform: scaleX(1) translateX(-100%);
222        }
223        50% {
224          transform: scaleX(1) translateX(0%);
225        }
226        75% {
227          transform: scaleX(1) translateX(0%);
228          animation-timing-function: cubic-bezier(.28,.62,.37,.91);
229        }
230        100% {
231          transform: scaleX(0) translateX(0%);
232        }
233      }
234
235      @keyframes indeterminate-splitter {
236        0% {
237          transform: scaleX(.75) translateX(-125%);
238        }
239        30% {
240          transform: scaleX(.75) translateX(-125%);
241          animation-timing-function: cubic-bezier(.42,0,.6,.8);
242        }
243        90% {
244          transform: scaleX(.75) translateX(125%);
245        }
246        100% {
247          transform: scaleX(.75) translateX(125%);
248        }
249      }
250    </style>
251
252    <div id="progressContainer">
253      <div id="secondaryProgress" hidden$="[[_hideSecondaryProgress(secondaryRatio)]]"></div>
254      <div id="primaryProgress"></div>
255    </div>
256  </template>
257</dom-module>
258
259<script>
260  Polymer({
261    is: 'paper-progress',
262
263    behaviors: [
264      Polymer.IronRangeBehavior
265    ],
266
267    properties: {
268      /**
269       * The number that represents the current secondary progress.
270       */
271      secondaryProgress: {
272        type: Number,
273        value: 0
274      },
275
276      /**
277       * The secondary ratio
278       */
279      secondaryRatio: {
280        type: Number,
281        value: 0,
282        readOnly: true
283      },
284
285      /**
286       * Use an indeterminate progress indicator.
287       */
288      indeterminate: {
289        type: Boolean,
290        value: false,
291        observer: '_toggleIndeterminate'
292      },
293
294      /**
295       * True if the progress is disabled.
296       */
297      disabled: {
298        type: Boolean,
299        value: false,
300        reflectToAttribute: true,
301        observer: '_disabledChanged'
302      }
303    },
304
305    observers: [
306      '_progressChanged(secondaryProgress, value, min, max)'
307    ],
308
309    hostAttributes: {
310      role: 'progressbar'
311    },
312
313    _toggleIndeterminate: function(indeterminate) {
314      // If we use attribute/class binding, the animation sometimes doesn't translate properly
315      // on Safari 7.1. So instead, we toggle the class here in the update method.
316      this.toggleClass('indeterminate', indeterminate, this.$.primaryProgress);
317    },
318
319    _transformProgress: function(progress, ratio) {
320      var transform = 'scaleX(' + (ratio / 100) + ')';
321      progress.style.transform = progress.style.webkitTransform = transform;
322    },
323
324    _mainRatioChanged: function(ratio) {
325      this._transformProgress(this.$.primaryProgress, ratio);
326    },
327
328    _progressChanged: function(secondaryProgress, value, min, max) {
329      secondaryProgress = this._clampValue(secondaryProgress);
330      value = this._clampValue(value);
331
332      var secondaryRatio = this._calcRatio(secondaryProgress) * 100;
333      var mainRatio = this._calcRatio(value) * 100;
334
335      this._setSecondaryRatio(secondaryRatio);
336      this._transformProgress(this.$.secondaryProgress, secondaryRatio);
337      this._transformProgress(this.$.primaryProgress, mainRatio);
338
339      this.secondaryProgress = secondaryProgress;
340
341      this.setAttribute('aria-valuenow', value);
342      this.setAttribute('aria-valuemin', min);
343      this.setAttribute('aria-valuemax', max);
344    },
345
346    _disabledChanged: function(disabled) {
347      this.setAttribute('aria-disabled', disabled ? 'true' : 'false');
348    },
349
350    _hideSecondaryProgress: function(secondaryRatio) {
351      return secondaryRatio === 0;
352    }
353  });
354</script>
355