UNPKG

20.8 kBJavaScriptView Raw
1import _setImmediate from 'babel-runtime/core-js/set-immediate';
2import _Object$keys from 'babel-runtime/core-js/object/keys';
3import _Promise from 'babel-runtime/core-js/promise';
4import _extends from 'babel-runtime/helpers/extends';
5/*
6Copyright 2013-2015 ASIAL CORPORATION
7
8Licensed under the Apache License, Version 2.0 (the "License");
9you may not use this file except in compliance with the License.
10You may obtain a copy of the License at
11
12 http://www.apache.org/licenses/LICENSE-2.0
13
14Unless required by applicable law or agreed to in writing, software
15distributed under the License is distributed on an "AS IS" BASIS,
16WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17See the License for the specific language governing permissions and
18limitations under the License.
19
20*/
21
22import util from './util';
23import contentReady from './content-ready';
24import ToastQueue from './internal/toast-queue';
25
26var _setAttributes = function _setAttributes(element, options) {
27 ['id', 'class', 'animation'].forEach(function (a) {
28 return options.hasOwnProperty(a) && element.setAttribute(a, options[a]);
29 });
30
31 if (options.modifier) {
32 util.addModifier(element, options.modifier);
33 }
34};
35
36var _normalizeArguments = function _normalizeArguments(message) {
37 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
38 var defaults = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
39
40 options = _extends({}, options);
41 typeof message === 'string' ? options.message = message : options = message;
42 if (!options || !options.message && !options.messageHTML) {
43 util.throw('Notifications must contain a message');
44 }
45
46 if (options.hasOwnProperty('buttonLabels') || options.hasOwnProperty('buttonLabel')) {
47 options.buttonLabels = options.buttonLabels || options.buttonLabel;
48 if (!Array.isArray(options.buttonLabels)) {
49 options.buttonLabels = [options.buttonLabels || ''];
50 }
51 }
52
53 return util.extend({
54 compile: function compile(param) {
55 return param;
56 },
57 callback: function callback(param) {
58 return param;
59 },
60 animation: 'default',
61 cancelable: false,
62 primaryButtonIndex: (options.buttonLabels || defaults.buttonLabels || []).length - 1
63 }, defaults, options);
64};
65
66/**
67 * @object ons.notification
68 * @category dialog
69 * @tutorial vanilla/Reference/notification
70 * @description
71 * [en]
72 * Utility methods to create different kinds of notifications. There are three methods available:
73 *
74 * * `ons.notification.alert()`
75 * * `ons.notification.confirm()`
76 * * `ons.notification.prompt()`
77 * * `ons.notification.toast()`
78 *
79 * It will automatically display a Material Design dialog on Android devices.
80 * [/en]
81 * [ja]いくつかの種類のアラートダイアログを作成するためのユーティリティメソッドを収めたオブジェクトです。[/ja]
82 * @example
83 * ons.notification.alert('Hello, world!');
84 *
85 * ons.notification.confirm('Are you ready?')
86 * .then(
87 * function(answer) {
88 * if (answer === 1) {
89 * ons.notification.alert('Let\'s go!');
90 * }
91 * }
92 * );
93 *
94 * ons.notification.prompt('How old are ?')
95 * .then(
96 * function(age) {
97 * ons.notification.alert('You are ' + age + ' years old.');
98 * }
99 * );
100 */
101var notification = {};
102
103notification._createAlertDialog = function () {
104 for (var _len = arguments.length, params = Array(_len), _key = 0; _key < _len; _key++) {
105 params[_key] = arguments[_key];
106 }
107
108 return new _Promise(function (resolve) {
109 var options = _normalizeArguments.apply(undefined, params);
110 util.checkMissingImport('AlertDialog', 'AlertDialogButton');
111
112 // Prompt input string
113 var inputString = '';
114 if (options.isPrompt) {
115 inputString = '\n <input\n class="text-input text-input--underbar"\n type="' + (options.inputType || 'text') + '"\n placeholder="' + (options.placeholder || '') + '"\n value="' + (options.defaultValue || '') + '"\n style="width: 100%; margin-top: 10px;"\n />\n ';
116 }
117
118 // Buttons string
119 var buttons = '';
120 options.buttonLabels.forEach(function (label, index) {
121 buttons += '\n <ons-alert-dialog-button\n class="\n ' + (index === options.primaryButtonIndex ? ' alert-dialog-button--primal' : '') + '\n ' + (options.buttonLabels.length <= 2 ? ' alert-dialog-button--rowfooter' : '') + '\n "\n style="position: relative;">\n ' + label + '\n </ons-alert-dialog-button>\n ';
122 });
123
124 // Dialog Element
125 var el = {};
126 var _destroyDialog = function _destroyDialog() {
127 if (el.dialog.onDialogCancel) {
128 el.dialog.removeEventListener('dialog-cancel', el.dialog.onDialogCancel);
129 }
130
131 _Object$keys(el).forEach(function (key) {
132 return delete el[key];
133 });
134 el = null;
135
136 if (options.destroy instanceof Function) {
137 options.destroy();
138 }
139 };
140
141 el.dialog = document.createElement('ons-alert-dialog');
142 el.dialog.innerHTML = '\n <div class="alert-dialog-mask"\n style="\n ' + (options.maskColor ? 'background-color: ' + options.maskColor : '') + '\n "></div>\n <div class="alert-dialog">\n <div class="alert-dialog-container">\n <div class="alert-dialog-title">\n ' + (options.title || '') + '\n </div>\n <div class="alert-dialog-content">\n ' + (options.message || options.messageHTML) + '\n ' + inputString + '\n </div>\n <div class="\n alert-dialog-footer\n ' + (options.buttonLabels.length <= 2 ? ' alert-dialog-footer--rowfooter' : '') + '\n ">\n ' + buttons + '\n </div>\n </div>\n </div>\n ';
143 contentReady(el.dialog);
144
145 // Set attributes
146 _setAttributes(el.dialog, options);
147
148 // Prompt events
149 if (options.isPrompt && options.submitOnEnter) {
150 el.input = el.dialog.querySelector('.text-input');
151 el.input.onkeypress = function (event) {
152 if (event.keyCode === 13) {
153 el.dialog.hide().then(function () {
154 if (el) {
155 var resolveValue = el.input.value;
156 _destroyDialog();
157 options.callback(resolveValue);
158 resolve(resolveValue);
159 }
160 });
161 }
162 };
163 }
164
165 // Button events
166 el.footer = el.dialog.querySelector('.alert-dialog-footer');
167 util.arrayFrom(el.dialog.querySelectorAll('.alert-dialog-button')).forEach(function (buttonElement, index) {
168 buttonElement.onclick = function () {
169 el.dialog.hide().then(function () {
170 if (el) {
171 var resolveValue = index;
172 if (options.isPrompt) {
173 resolveValue = index === options.primaryButtonIndex ? el.input.value : null;
174 }
175 el.dialog.remove();
176 _destroyDialog();
177 options.callback(resolveValue);
178 resolve(resolveValue);
179 }
180 });
181 };
182
183 el.footer.appendChild(buttonElement);
184 });
185
186 // Cancel events
187 if (options.cancelable) {
188 el.dialog.cancelable = true;
189 el.dialog.onDialogCancel = function () {
190 _setImmediate(function () {
191 el.dialog.remove();
192 _destroyDialog();
193 });
194 var resolveValue = options.isPrompt ? null : -1;
195 options.callback(resolveValue);
196 resolve(resolveValue);
197 };
198 el.dialog.addEventListener('dialog-cancel', el.dialog.onDialogCancel, false);
199 }
200
201 // Show dialog
202 document.body.appendChild(el.dialog);
203 options.compile(el.dialog);
204 _setImmediate(function () {
205 el.dialog.show().then(function () {
206 if (el.input && options.isPrompt && options.autofocus) {
207 var strLength = el.input.value.length;
208 el.input.focus();
209 el.input.setSelectionRange(strLength, strLength);
210 }
211 });
212 });
213 });
214};
215
216/**
217 * @method alert
218 * @signature alert(message [, options] | options)
219 * @return {Promise}
220 * [en]Will resolve to the index of the button that was pressed or `-1` when canceled.[/en]
221 * [ja][/ja]
222 * @param {String} message
223 * [en]Notification message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en]
224 * [ja][/ja]
225 * @param {Object} options
226 * [en]Parameter object.[/en]
227 * [ja]オプションを指定するオブジェクトです。[/ja]
228 * @param {String} [options.message]
229 * [en]Notification message.[/en]
230 * [ja]アラートダイアログに表示する文字列を指定します。[/ja]
231 * @param {String} [options.messageHTML]
232 * [en]Notification message in HTML.[/en]
233 * [ja]アラートダイアログに表示するHTMLを指定します。[/ja]
234 * @param {String | Array} [options.buttonLabels]
235 * [en]Labels for the buttons. Default is `"OK"`.[/en]
236 * [ja]確認ボタンのラベルを指定します。"OK"がデフォルトです。[/ja]
237 * @param {Number} [options.primaryButtonIndex]
238 * [en]Index of primary button. Default is the last one.[/en]
239 * [ja]プライマリボタンのインデックスを指定します。デフォルトは 0 です。[/ja]
240 * @param {Boolean} [options.cancelable]
241 * [en]Whether the dialog is cancelable or not. Default is `false`. If the dialog is cancelable it can be closed by clicking the background or pressing the Android back button.[/en]
242 * [ja]ダイアログがキャンセル可能かどうかを指定します。[/ja]
243 * @param {String} [options.animation]
244 * [en]Animation name. Available animations are `none` and `fade`. Default is `fade`.[/en]
245 * [ja]アラートダイアログを表示する際のアニメーション名を指定します。"none", "fade"のいずれかを指定できます。[/ja]
246 * @param {String} [options.id]
247 * [en]The `<ons-alert-dialog>` element's ID.[/en]
248 * [ja]ons-alert-dialog要素のID。[/ja]
249 * @param {String} [options.class]
250 * [en]The `<ons-alert-dialog>` element's class.[/en]
251 * [ja]ons-alert-dialog要素のclass。[/ja]
252 * @param {String} [options.title]
253 * [en]Dialog title. Default is `"Alert"`.[/en]
254 * [ja]アラートダイアログの上部に表示するタイトルを指定します。"Alert"がデフォルトです。[/ja]
255 * @param {String} [options.modifier]
256 * [en]Modifier for the dialog.[/en]
257 * [ja]アラートダイアログのmodifier属性の値を指定します。[/ja]
258 * @param {String} [options.maskColor]
259 * [en]Color of the background mask. Default is "rgba(0, 0, 0, 0.2)" ("rgba(0, 0, 0, 0.3)" for Material).[/en]
260 * [ja]背景のマスクの色を指定します。"rgba(0, 0, 0, 0.2)"がデフォルト値です。[/ja]
261 * @param {Function} [options.callback]
262 * [en]Function that executes after dialog has been closed.[/en]
263 * [ja]アラートダイアログが閉じられた時に呼び出される関数オブジェクトを指定します。[/ja]
264 * @description
265 * [en]
266 * Display an alert dialog to show the user a message.
267 *
268 * The content of the message can be either simple text or HTML.
269 *
270 * It can be called in the following ways:
271 *
272 * ```
273 * ons.notification.alert(message, options);
274 * ons.notification.alert(options);
275 * ```
276 *
277 * Must specify either `message` or `messageHTML`.
278 * [/en]
279 * [ja]
280 * ユーザーへメッセージを見せるためのアラートダイアログを表示します。
281 * 表示するメッセージは、テキストかもしくはHTMLを指定できます。
282 * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。
283 * [/ja]
284 */
285notification.alert = function (message, options) {
286 return notification._createAlertDialog(message, options, {
287 buttonLabels: ['OK'],
288 title: 'Alert'
289 });
290};
291
292/**
293 * @method confirm
294 * @signature confirm(message [, options] | options)
295 * @return {Promise}
296 * [en]Will resolve to the index of the button that was pressed or `-1` when canceled.[/en]
297 * [ja][/ja]
298 * @param {String} message
299 * [en]Notification message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en]
300 * [ja][/ja]
301 * @param {Object} options
302 * [en]Parameter object.[/en]
303 * @param {Array} [options.buttonLabels]
304 * [en]Labels for the buttons. Default is `["Cancel", "OK"]`.[/en]
305 * [ja]ボタンのラベルの配列を指定します。["Cancel", "OK"]がデフォルトです。[/ja]
306 * @param {Number} [options.primaryButtonIndex]
307 * [en]Index of primary button. Default is the last one.[/en]
308 * [ja]プライマリボタンのインデックスを指定します。デフォルトは 1 です。[/ja]
309 * @description
310 * [en]
311 * Display a dialog to ask the user for confirmation. Extends `alert()` parameters.
312 * The default button labels are `"Cancel"` and `"OK"` but they can be customized.
313 *
314 * It can be called in the following ways:
315 *
316 * ```
317 * ons.notification.confirm(message, options);
318 * ons.notification.confirm(options);
319 * ```
320 *
321 * Must specify either `message` or `messageHTML`.
322 * [/en]
323 * [ja]
324 * ユーザに確認を促すダイアログを表示します。
325 * デオルとのボタンラベルは、"Cancel"と"OK"ですが、これはこのメソッドの引数でカスタマイズできます。
326 * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。
327 * [/ja]
328 */
329notification.confirm = function (message, options) {
330 return notification._createAlertDialog(message, options, {
331 buttonLabels: ['Cancel', 'OK'],
332 title: 'Confirm'
333 });
334};
335
336/**
337 * @method prompt
338 * @signature prompt(message [, options] | options)
339 * @param {String} message
340 * [en]Notification message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en]
341 * [ja][/ja]
342 * @return {Promise}
343 * [en]Will resolve to the input value when the dialog is closed or `null` when canceled.[/en]
344 * [ja][/ja]
345 * @param {Object} options
346 * [en]Parameter object.[/en]
347 * [ja]オプションを指定するオブジェクトです。[/ja]
348 * @param {String | Array} [options.buttonLabels]
349 * [en]Labels for the buttons. Default is `"OK"`.[/en]
350 * [ja]確認ボタンのラベルを指定します。"OK"がデフォルトです。[/ja]
351 * @param {Number} [options.primaryButtonIndex]
352 * [en]Index of primary button. Default is the last one.[/en]
353 * [ja]プライマリボタンのインデックスを指定します。デフォルトは 0 です。[/ja]
354 * @param {String} [options.placeholder]
355 * [en]Placeholder for the text input.[/en]
356 * [ja]テキスト欄のプレースホルダに表示するテキストを指定します。[/ja]
357 * @param {String} [options.defaultValue]
358 * [en]Default value for the text input.[/en]
359 * [ja]テキスト欄のデフォルトの値を指定します。[/ja]
360 * @param {String} [options.inputType]
361 * [en]Type of the input element (`password`, `date`...). Default is `text`.[/en]
362 * [ja][/ja]
363 * @param {Boolean} [options.autofocus]
364 * [en]Autofocus the input element. Default is `true`. In Cordova, `KeyboardDisplayRequiresUserAction` in `config.xml` must be `false` to activate this feature.[/en]
365 * [ja]input要素に自動的にフォーカスするかどうかを指定します。デフォルトはtrueです。Cordova環境では、この機能を有効にするためには `config.xml` で `KeyboardDisplayRequiresUserAction` を `false` に設定する必要があります。[/ja]
366 * @param {Boolean} [options.submitOnEnter]
367 * [en]Submit automatically when enter is pressed. Default is `true`.[/en]
368 * [ja]Enterが押された際にそのformをsubmitするかどうかを指定します。デフォルトはtrueです。[/ja]
369 * @description
370 * [en]
371 * Display a dialog with a prompt to ask the user a question. Extends `alert()` parameters.
372 *
373 * It can be called in the following ways:
374 *
375 * ```
376 * ons.notification.prompt(message, options);
377 * ons.notification.prompt(options);
378 * ```
379 *
380 * Must specify either `message` or `messageHTML`.
381 * [/en]
382 * [ja]
383 * ユーザーに入力を促すダイアログを表示します。
384 * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。
385 * [/ja]
386 */
387notification.prompt = function (message, options) {
388 return notification._createAlertDialog(message, options, {
389 buttonLabels: ['OK'],
390 title: 'Alert',
391 isPrompt: true,
392 autofocus: true,
393 submitOnEnter: true
394 });
395};
396
397/**
398 * @method toast
399 * @signature toast(message [, options] | options)
400 * @return {Promise}
401 * [en]Will resolve when the toast is hidden.[/en]
402 * [ja][/ja]
403 * @param {String} message
404 * [en]Toast message. This argument is optional but if it's not defined then `options.message` must be defined instead.[/en]
405 * [ja][/ja]
406 * @param {Object} options
407 * [en]Parameter object.[/en]
408 * [ja]オプションを指定するオブジェクトです。[/ja]
409 * @param {String} [options.message]
410 * [en]Notification message.[/en]
411 * [ja]トーストに表示する文字列を指定します。[/ja]
412 * @param {String} [options.buttonLabel]
413 * [en]Label for the button.[/en]
414 * [ja]確認ボタンのラベルを指定します。[/ja]
415 * @param {String} [options.animation]
416 * [en]Animation name. Available animations are `none`, `fade`, `ascend`, `lift` and `fall`. Default is `ascend` for Android and `lift` for iOS.[/en]
417 * [ja]トーストを表示する際のアニメーション名を指定します。"none", "fade", "ascend", "lift", "fall"のいずれかを指定できます。[/ja]
418 * @param {Number} [options.timeout]
419 * [en]Number of miliseconds where the toast is visible before hiding automatically.[/en]
420 * [ja][/ja]
421 * @param {Boolean} [options.force]
422 * [en]If `true`, the toast skips the notification queue and is shown immediately. Defaults to `false`.[/en]
423 * [ja][/ja]
424 * @param {String} [options.id]
425 * [en]The `<ons-toast>` element's ID.[/en]
426 * [ja]ons-toast要素のID。[/ja]
427 * @param {String} [options.class]
428 * [en]The `<ons-toast>` element's class.[/en]
429 * [ja]ons-toast要素のclass。[/ja]
430 * @param {String} [options.modifier]
431 * [en]Modifier for the element.[/en]
432 * [ja]トーストのmodifier属性の値を指定します。[/ja]
433 * @param {Function} [options.callback]
434 * [en]Function that executes after toast has been hidden.[/en]
435 * [ja]トーストが閉じられた時に呼び出される関数オブジェクトを指定します。[/ja]
436 * @description
437 * [en]
438 * Display a simple notification toast with an optional button that can be used for simple actions.
439 *
440 * It can be called in the following ways:
441 *
442 * ```
443 * ons.notification.toast(message, options);
444 * ons.notification.toast(options);
445 * ```
446 * [/en]
447 * [ja][/ja]
448 */
449notification.toast = function (message, options) {
450 var promise = new _Promise(function (resolve) {
451 util.checkMissingImport('Toast'); // Throws error, must be inside promise
452
453 options = _normalizeArguments(message, options, {
454 timeout: 0,
455 force: false
456 });
457
458 var toast = util.createElement('\n <ons-toast>\n ' + options.message + '\n ' + (options.buttonLabels ? '<button>' + options.buttonLabels[0] + '</button>' : '') + '\n </ons-toast>\n ');
459
460 _setAttributes(toast, options);
461
462 var finish = function finish(value) {
463 if (toast) {
464 toast.hide().then(function () {
465 if (toast) {
466 toast.remove();
467 toast = null;
468 options.callback(value);
469 resolve(value);
470 }
471 });
472 }
473 };
474
475 if (options.buttonLabels) {
476 util.findChild(toast._toast, 'button').onclick = function () {
477 return finish(0);
478 };
479 }
480
481 document.body.appendChild(toast);
482 options.compile(toast);
483
484 var show = function show() {
485 toast.parentElement && toast.show(options).then(function () {
486 if (options.timeout) {
487 setTimeout(function () {
488 return finish(-1);
489 }, options.timeout);
490 }
491 });
492 };
493
494 _setImmediate(function () {
495 return options.force ? show() : ToastQueue.add(show, promise);
496 });
497 });
498
499 return promise;
500};
501
502export default notification;
\No newline at end of file