UNPKG

7.25 kBJavaScriptView Raw
1/*
2Copyright 2013-2015 ASIAL CORPORATION
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15
16*/
17
18import onsElements from '../ons/elements.js';
19import util from '../ons/util.js';
20import autoStyle from '../ons/autostyle.js';
21import ModifierUtil from '../ons/internal/modifier-util.js';
22import BaseElement from './base/base-element.js';
23import contentReady from '../ons/content-ready.js';
24
25const scheme = {
26 '.progress-circular': 'progress-circular--*',
27 '.progress-circular__background': 'progress-circular--*__background',
28 '.progress-circular__primary': 'progress-circular--*__primary',
29 '.progress-circular__secondary': 'progress-circular--*__secondary'
30};
31
32const template = util.createElement(`
33 <svg class="progress-circular">
34 <circle class="progress-circular__background" />
35 <circle class="progress-circular__secondary" cx="50%" cy="50%" r="40%" />
36 <circle class="progress-circular__primary" cx="50%" cy="50%" r="40%" />
37 </svg>
38`);
39
40const INDET = 'indeterminate';
41
42/**
43 * @element ons-progress-circular
44 * @category visual
45 * @description
46 * [en]
47 * This component displays a circular progress indicator. It can either be used to show how much of a task has been completed or to show a looping animation to indicate that an operation is currently running.
48 * [/en]
49 * [ja][/ja]
50 * @codepen EVzMjR
51 * @tutorial vanilla/Reference/progress-circular
52 * @seealso ons-progress-bar
53 * [en]The `<ons-progress-bar>` component displays a bar progress indicator.[/en]
54 * [ja][/ja]
55 * @example
56 * <ons-progress-circular
57 * value="55"
58 * secondary-value="87">
59 * </ons-progress-circular>
60 *
61 * <ons-progress-circular
62 * indeterminate>
63 * </ons-progress-circular>
64 */
65export default class ProgressCircularElement extends BaseElement {
66
67 /**
68 * @attribute modifier
69 * @type {String}
70 * @description
71 * [en]Change the appearance of the progress indicator.[/en]
72 * [ja]プログレスインジケータの見た目を変更します。[/ja]
73 */
74
75 /**
76 * @attribute value
77 * @type {Number}
78 * @description
79 * [en]Current progress. Should be a value between 0 and 100.[/en]
80 * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
81 */
82
83 /**
84 * @attribute secondary-value
85 * @type {Number}
86 * @description
87 * [en]Current secondary progress. Should be a value between 0 and 100.[/en]
88 * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
89 */
90
91 /**
92 * @attribute indeterminate
93 * @description
94 * [en]If this attribute is set, an infinite looping animation will be shown.[/en]
95 * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja]
96 */
97
98 constructor() {
99 super();
100
101 contentReady(this, () => this._compile());
102 }
103
104 static get observedAttributes() {
105 return ['modifier', 'value', 'secondary-value', INDET];
106 }
107
108 attributeChangedCallback(name, last, current) {
109 if (name === 'modifier') {
110 ModifierUtil.onModifierChanged(last, current, this, scheme);
111 this.hasAttribute(INDET) && this._updateDeterminate();
112 } else if (name === 'value' || name === 'secondary-value') {
113 this._updateValue();
114 } else if (name === INDET) {
115 this._updateDeterminate();
116 }
117 }
118
119 _updateDeterminate() {
120 contentReady(this, () => util.toggleModifier(this, INDET, { force: this.hasAttribute(INDET) }));
121 }
122
123 _updateValue() {
124 if (this.hasAttribute('value')) {
125 contentReady(this, () => {
126 const per = Math.ceil(this.getAttribute('value') * 251.32 * 0.01);
127 this._primary.style['stroke-dasharray'] = per + '%, 251.32%';
128 });
129 }
130 if (this.hasAttribute('secondary-value')) {
131 contentReady(this, () => {
132 const per = Math.ceil(this.getAttribute('secondary-value') * 251.32 * 0.01);
133 this._secondary.style.display = null;
134 this._secondary.style['stroke-dasharray'] = per + '%, 251.32%';
135 });
136 } else {
137 contentReady(this, () => {
138 this._secondary.style.display = 'none';
139 });
140 }
141 }
142
143 /**
144 * @property value
145 * @type {Number}
146 * @description
147 * [en]Current progress. Should be a value between 0 and 100.[/en]
148 * [ja]現在の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
149 */
150 set value(value) {
151 if (typeof value !== 'number' || value < 0 || value > 100) {
152 util.throw('Invalid value');
153 }
154
155 this.setAttribute('value', Math.floor(value));
156 }
157
158 get value() {
159 return parseInt(this.getAttribute('value') || '0');
160 }
161
162 /**
163 * @property secondaryValue
164 * @type {Number}
165 * @description
166 * [en]Current secondary progress. Should be a value between 0 and 100.[/en]
167 * [ja]現在の2番目の進行状況の値を指定します。0から100の間の値を指定して下さい。[/ja]
168 */
169 set secondaryValue(value) {
170 if (typeof value !== 'number' || value < 0 || value > 100) {
171 util.throw('Invalid value');
172 }
173
174 this.setAttribute('secondary-value', Math.floor(value));
175 }
176
177 get secondaryValue() {
178 return parseInt(this.getAttribute('secondary-value') || '0');
179 }
180
181 /**
182 * @property indeterminate
183 * @type {Boolean}
184 * @description
185 * [en]If this property is `true`, an infinite looping animation will be shown.[/en]
186 * [ja]この属性が設定された場合、ループするアニメーションが表示されます。[/ja]
187 */
188 set indeterminate(value) {
189 if (value) {
190 this.setAttribute(INDET, '');
191 }
192 else {
193 this.removeAttribute(INDET);
194 }
195 }
196
197 get indeterminate() {
198 return this.hasAttribute(INDET);
199 }
200
201 _compile() {
202 if (this._isCompiled()) {
203 this._template = util.findChild(this, '.progress-circular');
204 } else {
205 this._template = template.cloneNode(true);
206 }
207
208 this._primary = util.findChild(this._template, '.progress-circular__primary');
209 this._secondary = util.findChild(this._template, '.progress-circular__secondary');
210
211 this._updateDeterminate();
212 this._updateValue();
213
214 this.appendChild(this._template);
215
216 autoStyle.prepare(this);
217 ModifierUtil.initModifier(this, scheme);
218 }
219
220 _isCompiled() {
221 if (!util.findChild(this, '.progress-circular')) {
222 return false;
223 }
224
225 const svg = util.findChild(this, '.progress-circular');
226
227 if (!util.findChild(svg, '.progress-circular__secondary')) {
228 return false;
229 }
230
231 if (!util.findChild(svg, '.progress-circular__primary')) {
232 return false;
233 }
234
235 return true;
236 }
237}
238
239onsElements.ProgressCircular = ProgressCircularElement;
240customElements.define('ons-progress-circular', ProgressCircularElement);