/* onsenui v2.10.8 - 2019-04-01 */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.ons = factory()); }(this, (function () { 'use strict'; var onsElements = {}; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * Add vendor prefix. * * @param {String} name * @return {String} */ var prefix = function () { var styles = window.getComputedStyle(document.documentElement, ''); var prefix = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || styles.OLink === '' && ['', 'o'])[1]; return function (name) { return '-' + prefix + '-' + util$1.hyphenate(name); }; }(); /** * Minimal utility library for manipulating element's style. * Set element's style. * * @param {Element} element * @param {Object} styles * @return {Element} */ var styler = function styler(element, style) { Object.keys(style).forEach(function (key) { if (key in element.style) { element.style[key] = style[key]; } else if (prefix(key) in element.style) { element.style[prefix(key)] = style[key]; } else { util$1.warn('No such style property: ' + key); } }); return element; }; /** * @param {Element} element * @param {String} styles Space-separated CSS properties to remove */ styler.clear = function (element) { var styles = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; var clearlist = styles.split(/\s+/).reduce(function (r, s) { return r.concat([util$1.hyphenate(s), prefix(s)]); }, []), keys = []; var _loop = function _loop(i) { var key = element.style[i]; if (clearlist.length === 0 || clearlist.some(function (s) { return key.indexOf(s) === 0; })) { keys.push(key); // Store the key to fix Safari style indexes } }; for (var i = element.style.length - 1; i >= 0; i--) { _loop(i); } keys.forEach(function (key) { return element.style[key] = ''; }); element.getAttribute('style') === '' && element.removeAttribute('style'); }; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var defineProperty = function (obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; var inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }; var objectWithoutProperties = function (obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }; var possibleConstructorReturn = function (self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }; var toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Save HTMLElement object before Custom Elements polyfill patch global HTMLElement. var NativeHTMLElement = window.HTMLElement; /** * @object ons.platform * @category util * @description * [en]Utility methods to detect current platform.[/en] * [ja]現在実行されているプラットフォームを検知するためのユーティリティメソッドを収めたオブジェクトです。[/ja] */ var Platform = function () { /** * All elements will be rendered as if the app was running on this platform. * @type {String} */ function Platform() { classCallCheck(this, Platform); this._selectedPlatform = null; this._ignorePlatformSelect = false; } /** * @method select * @signature select(platform) * @param {string} platform Name of the platform. * [en]Possible values are: "opera", "firefox", "safari", "chrome", "ie", "android", "blackberry", "ios" or "wp".[/en] * [ja]"opera", "firefox", "safari", "chrome", "ie", "android", "blackberry", "ios", "wp"のいずれかを指定します。[/ja] * @description * [en]Sets the platform used to render the elements. Useful for testing.[/en] * [ja]要素を描画するために利用するプラットフォーム名を設定します。テストに便利です。[/ja] */ createClass(Platform, [{ key: 'select', value: function select(platform) { if (typeof platform === 'string') { this._selectedPlatform = platform.trim().toLowerCase(); } } }, { key: '_getSelectedPlatform', value: function _getSelectedPlatform() { return this._ignorePlatformSelect ? null : this._selectedPlatform; } }, { key: '_runOnActualPlatform', value: function _runOnActualPlatform(fn) { this._ignorePlatformSelect = true; var result = fn(); this._ignorePlatformSelect = false; return result; } //---------------- // General //---------------- /** * @method isWebView * @signature isWebView() * @description * [en]Returns whether app is running in Cordova.[/en] * [ja]Cordova内で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isWebView', value: function isWebView() { if (document.readyState === 'loading' || document.readyState == 'uninitialized') { throw new Error('isWebView() method is available after dom contents loaded.'); } return !!(window.cordova || window.phonegap || window.PhoneGap); } //---------------- // iOS devices //---------------- /** * @method isIPhone * @signature isIPhone() * @description * [en]Returns whether the device is iPhone.[/en] * [ja]iPhone上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIPhone', value: function isIPhone() { return (/iPhone/i.test(navigator.userAgent) ); } /** * @method isIPhoneX * @signature isIPhoneX() * @description * [en]Returns whether the device is iPhone X, XS, XS Max, or XR.[/en] * [ja]iPhone X や XS、XS Max、または XR 上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIPhoneX', value: function isIPhoneX() { // iOS WebViews on the same iOS version have the same user agent. // We cannot avoid using window.screen. // We also cannot use cordova-plugin-device since its behavior is different between simulators and real devices. // This works well both in iOS Safari and (UI|WK)WebView of iPhone X. return this.isIPhone() && (window.screen.width === 375 && window.screen.height === 812 || // X, XS portrait window.screen.width === 812 && window.screen.height === 375 || // X, XS landscape window.screen.width === 414 && window.screen.height === 896 || // XS Max, XR portrait window.screen.width === 896 && window.screen.height === 414); // XS Max, XR landscape } /** * @method isIPad * @signature isIPad() * @description * [en]Returns whether the device is iPad.[/en] * [ja]iPad上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIPad', value: function isIPad() { return (/iPad/i.test(navigator.userAgent) ); } /** * @return {Boolean} */ }, { key: 'isIPod', value: function isIPod() { return (/iPod/i.test(navigator.userAgent) ); } //---------------- // iOS versions //---------------- /** * @method isIOS * @signature isIOS([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the OS is iOS. By default will return manually selected platform if it is set.[/en] * [ja]iOS上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIOS', value: function isIOS(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'ios'; } if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) { return (/iOS/i.test(device.platform) ); } else { return (/iPhone|iPad|iPod/i.test(navigator.userAgent) ); } } /** * @method isIOS7above * @signature isIOS7above() * @description * [en]Returns whether the iOS version is 7 or above.[/en] * [ja]iOS7以上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIOS7above', value: function isIOS7above() { if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) { return (/iOS/i.test(device.platform) && parseInt(device.version.split('.')[0]) >= 7 ); } else if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) { var ver = (navigator.userAgent.match(/\b[0-9]+_[0-9]+(?:_[0-9]+)?\b/) || [''])[0].replace(/_/g, '.'); return parseInt(ver.split('.')[0]) >= 7; } return false; } //---------------- // iOS browsers //---------------- /** * @method isIOSSafari * @signature isIOSSafari() * @description * [en]Returns whether app is running in iOS Safari.[/en] * [ja]iOS Safariで実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIOSSafari', value: function isIOSSafari() { var navigator = window.navigator; var ua = navigator.userAgent; return !!(this.isIOS() && ua.indexOf('Safari') !== -1 && ua.indexOf('Version') !== -1 && !navigator.standalone); } /** * @method isWKWebView * @signature isWKWebView() * @description * [en]Returns whether app is running in WKWebView.[/en] * [ja]WKWebViewで実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isWKWebView', value: function isWKWebView() { var lte9 = /constructor/i.test(NativeHTMLElement); return !!(this.isIOS() && window.webkit && window.webkit.messageHandlers && window.indexedDB && !lte9); } /** * @method isUIWebView * @signature isUIWebView() * @description * [en]Returns whether app is running in UIWebView.[/en] * [ja]UIWebViewで実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isUIWebView', value: function isUIWebView() { return !!(this.isIOS() && !this.isIOSSafari() && !this.isWKWebView()); } //---------------- // Android devices //---------------- /** * @method isAndroidPhone * @signature isAndroidPhone() * @description * [en]Returns whether the device is Android phone.[/en] * [ja]Android携帯上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isAndroidPhone', value: function isAndroidPhone() { return (/Android/i.test(navigator.userAgent) && /Mobile/i.test(navigator.userAgent) ); } /** * @method isAndroidTablet * @signature isAndroidTablet() * @description * [en]Returns whether the device is Android tablet.[/en] * [ja]Androidタブレット上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isAndroidTablet', value: function isAndroidTablet() { return (/Android/i.test(navigator.userAgent) && !/Mobile/i.test(navigator.userAgent) ); } //---------------- // Android versions //---------------- /** * @method isAndroid * @signature isAndroid([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the OS is Android. By default will return manually selected platform if it is set.[/en] * [ja]Android上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isAndroid', value: function isAndroid(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'android'; } if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) { return (/Android/i.test(device.platform) ); } else { return (/Android/i.test(navigator.userAgent) ); } } //---------------- // Other devices //---------------- /** * @method isWP * @signature isWP([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the OS is Windows phone. By default will return manually selected platform if it is set.[/en] * [ja][/ja] * @return {Boolean} */ }, { key: 'isWP', value: function isWP(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'wp'; } if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) { return (/Win32NT|WinCE/i.test(device.platform) ); } else { return (/Windows Phone|IEMobile|WPDesktop/i.test(navigator.userAgent) ); } } /** * @method isBlackBerry * @signature isBlackBerry([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the device is BlackBerry. By default will return manually selected platform if it is set.[/en] * [ja]BlackBerry上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isBlackBerry', value: function isBlackBerry(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'blackberry'; } if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) { return (/BlackBerry/i.test(device.platform) ); } else { return (/BlackBerry|RIM Tablet OS|BB10/i.test(navigator.userAgent) ); } } //---------------- // Other browsers //---------------- /** * @method isOpera * @signature isOpera([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the browser is Opera. By default will return manually selected platform if it is set.[/en] * [ja]Opera上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isOpera', value: function isOpera(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'opera'; } return !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; } /** * @method isFirefox * @signature isFirefox([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the browser is Firefox. By default will return manually selected platform if it is set.[/en] * [ja]Firefox上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isFirefox', value: function isFirefox(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'firefox'; } return typeof InstallTrigger !== 'undefined'; } /** * @method isSafari * @signature isSafari([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the browser is Safari. By default will return manually selected platform if it is set.[/en] * [ja]Safari上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isSafari', value: function isSafari(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'safari'; } return Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0 || function (p) { return p.toString() === '[object SafariRemoteNotification]'; }(!window['safari'] || safari.pushNotification); } /** * @method isChrome * @signature isChrome([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the browser is Chrome. By default will return manually selected platform if it is set.[/en] * [ja]Chrome上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isChrome', value: function isChrome(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'chrome'; } return !!window.chrome && !(!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) && !(navigator.userAgent.indexOf(' Edge/') >= 0); } /** * @method isIE * @signature isIE([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the browser is Internet Explorer. By default will return manually selected platform if it is set.[/en] * [ja]Internet Explorer上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isIE', value: function isIE(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'ie'; } return false || !!document.documentMode; } /** * @method isEdge * @signature isEdge([forceActualPlatform]) * @param {Boolean} forceActualPlatform * [en]If true, selected platform is ignored and the actual platform is returned.[/en] * [ja][/ja] * @description * [en]Returns whether the browser is Edge. By default will return manually selected platform if it is set.[/en] * [ja]Edge上で実行されているかどうかを返します。[/ja] * @return {Boolean} */ }, { key: 'isEdge', value: function isEdge(forceActualPlatform) { if (!forceActualPlatform && this._getSelectedPlatform()) { return this._getSelectedPlatform() === 'edge'; } return navigator.userAgent.indexOf(' Edge/') >= 0; } //---------------- // Utility functions //---------------- /** * @return {String} */ }, { key: 'getMobileOS', value: function getMobileOS() { if (this.isAndroid()) { return 'android'; } else if (this.isIOS()) { return 'ios'; } else if (this.isWP()) { return 'wp'; } else { return 'other'; } } /** * @return {String} */ }, { key: 'getIOSDevice', value: function getIOSDevice() { if (this.isIPhone()) { return 'iphone'; } else if (this.isIPad()) { return 'ipad'; } else if (this.isIPod()) { return 'ipod'; } else { return 'na'; } } }]); return Platform; }(); var platform = new Platform(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var error = function error(message) { return util$1.throw('In PageAttributeExpression: ' + message); }; var pageAttributeExpression = { _variables: {}, /** * Define a variable. * * @param {String} name Name of the variable * @param {String|Function} value Value of the variable. Can be a string or a function. The function must return a string. * @param {Boolean} overwrite If this value is false, an error will be thrown when trying to define a variable that has already been defined. */ defineVariable: function defineVariable(name, value) { var overwrite = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; if (typeof name !== 'string') { error('Variable name must be a string'); } else if (typeof value !== 'string' && typeof value !== 'function') { error('Variable value must be a string or a function'); } else if (this._variables.hasOwnProperty(name) && !overwrite) { error('"' + name + '" is already defined'); } this._variables[name] = value; }, /** * Get a variable. * * @param {String} name Name of the variable. * @return {String|Function|null} */ getVariable: function getVariable(name) { if (!this._variables.hasOwnProperty(name)) { return null; } return this._variables[name]; }, /** * Remove a variable. * * @param {String} name Name of the varaible. */ removeVariable: function removeVariable(name) { delete this._variables[name]; }, /** * Get all variables. * * @return {Object} */ getAllVariables: function getAllVariables() { return this._variables; }, _parsePart: function _parsePart(part) { var c = void 0, inInterpolation = false, currentIndex = 0; var tokens = []; if (part.length === 0) { error('Unable to parse empty string'); } for (var i = 0; i < part.length; i++) { c = part.charAt(i); if (c === '$' && part.charAt(i + 1) === '{') { if (inInterpolation) { error('Nested interpolation not supported'); } var token = part.substring(currentIndex, i); if (token.length > 0) { tokens.push(part.substring(currentIndex, i)); } currentIndex = i; inInterpolation = true; } else if (c === '}') { if (!inInterpolation) { error('} must be preceeded by ${'); } var _token = part.substring(currentIndex, i + 1); if (_token.length > 0) { tokens.push(part.substring(currentIndex, i + 1)); } currentIndex = i + 1; inInterpolation = false; } } if (inInterpolation) { error('Unterminated interpolation'); } tokens.push(part.substring(currentIndex, part.length)); return tokens; }, _replaceToken: function _replaceToken(token) { var re = /^\${(.*?)}$/, match = token.match(re); if (match) { var name = match[1].trim(); var variable = this.getVariable(name); if (variable === null) { error('Variable "' + name + '" does not exist'); } else if (typeof variable === 'string') { return variable; } else { var rv = variable(); if (typeof rv !== 'string') { error('Must return a string'); } return rv; } } else { return token; } }, _replaceTokens: function _replaceTokens(tokens) { return tokens.map(this._replaceToken.bind(this)); }, _parseExpression: function _parseExpression(expression) { return expression.split(',').map(function (part) { return part.trim(); }).map(this._parsePart.bind(this)).map(this._replaceTokens.bind(this)).map(function (part) { return part.join(''); }); }, /** * Evaluate an expression. * * @param {String} expression An page attribute expression. * @return {Array} */ evaluate: function evaluate(expression) { if (!expression) { return []; } return this._parseExpression(expression); } }; // Define default variables. pageAttributeExpression.defineVariable('mobileOS', platform.getMobileOS()); pageAttributeExpression.defineVariable('iOSDevice', platform.getIOSDevice()); pageAttributeExpression.defineVariable('runtime', function () { return platform.isWebView() ? 'cordova' : 'browser'; }); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var internal$1 = {}; internal$1.config = { autoStatusBarFill: true, animationsDisabled: false, warningsDisabled: false }; internal$1.nullElement = window.document.createElement('div'); /** * @return {Boolean} */ internal$1.isEnabledAutoStatusBarFill = function () { return !!internal$1.config.autoStatusBarFill; }; /** * @param {String} html * @return {String} */ internal$1.normalizePageHTML = function (html) { return ('' + html).trim(); }; internal$1.waitDOMContentLoaded = function (callback) { if (window.document.readyState === 'loading' || window.document.readyState == 'uninitialized') { var wrappedCallback = function wrappedCallback() { callback(); window.document.removeEventListener('DOMContentLoaded', wrappedCallback); }; window.document.addEventListener('DOMContentLoaded', wrappedCallback); } else { setImmediate(callback); } }; internal$1.autoStatusBarFill = function (action) { var onReady = function onReady() { if (internal$1.shouldFillStatusBar()) { action(); } document.removeEventListener('deviceready', onReady); }; if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object') { document.addEventListener('deviceready', onReady); } else if (['complete', 'interactive'].indexOf(document.readyState) === -1) { internal$1.waitDOMContentLoaded(onReady); } else { onReady(); } }; internal$1.shouldFillStatusBar = function () { return internal$1.isEnabledAutoStatusBarFill() && (platform.isWebView() && platform.isIOS7above() && !platform.isIPhoneX() || document.body.querySelector('.ons-status-bar-mock.ios')); }; internal$1.templateStore = { _storage: {}, /** * @param {String} key * @return {String/null} template */ get: function get$$1(key) { return internal$1.templateStore._storage[key] || null; }, /** * @param {String} key * @param {String} template */ set: function set$$1(key, template) { internal$1.templateStore._storage[key] = template; } }; window.document.addEventListener('_templateloaded', function (e) { if (e.target.nodeName.toLowerCase() === 'ons-template') { internal$1.templateStore.set(e.templateId, e.template); } }, false); internal$1.waitDOMContentLoaded(function () { register('script[type="text/ons-template"]'); register('script[type="text/template"]'); register('script[type="text/ng-template"]'); register('template'); function register(query) { var templates = window.document.querySelectorAll(query); for (var i = 0; i < templates.length; i++) { internal$1.templateStore.set(templates[i].getAttribute('id'), templates[i].textContent || templates[i].content); } } }); /** * @param {String} page * @return {Promise} */ internal$1.getTemplateHTMLAsync = function (page) { return new Promise(function (resolve, reject) { internal$1.waitDOMContentLoaded(function () { var cache = internal$1.templateStore.get(page); if (cache) { if (cache instanceof DocumentFragment) { return resolve(cache); } var html = typeof cache === 'string' ? cache : cache[1]; return resolve(internal$1.normalizePageHTML(html)); } var local = window.document.getElementById(page); if (local) { var _html = local.textContent || local.content; return resolve(_html); } var xhr = new XMLHttpRequest(); xhr.open('GET', page, true); xhr.onload = function () { var html = xhr.responseText; if (xhr.status >= 400 && xhr.status < 600) { reject(html); } else { // Refresh script tags var fragment = util$1.createFragment(html); util$1.arrayFrom(fragment.querySelectorAll('script')).forEach(function (el) { var script = document.createElement('script'); script.type = el.type || 'text/javascript'; script.appendChild(document.createTextNode(el.text || el.textContent || el.innerHTML)); el.parentNode.replaceChild(script, el); }); internal$1.templateStore.set(page, fragment); resolve(fragment); } }; xhr.onerror = function () { util$1.throw('Page template not found: ' + page); }; xhr.send(null); }); }); }; /** * @param {String} page * @return {Promise} */ internal$1.getPageHTMLAsync = function (page) { var pages = pageAttributeExpression.evaluate(page); var getPage = function getPage(page) { if (typeof page !== 'string') { return Promise.reject('Must specify a page.'); } return internal$1.getTemplateHTMLAsync(page).catch(function (error) { if (pages.length === 0) { return Promise.reject(error); } return getPage(pages.shift()); }); }; return getPage(pages.shift()); }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var AnimatorFactory = function () { /** * @param {Object} opts * @param {Object} opts.animators The dictionary for animator classes * @param {Function} opts.baseClass The base class of animators * @param {String} [opts.baseClassName] The name of the base class of animators * @param {String} [opts.defaultAnimation] The default animation name * @param {Object} [opts.defaultAnimationOptions] The default animation options */ function AnimatorFactory(opts) { classCallCheck(this, AnimatorFactory); this._animators = opts.animators; this._baseClass = opts.baseClass; this._baseClassName = opts.baseClassName || opts.baseClass.name; this._animation = opts.defaultAnimation || 'default'; this._animationOptions = opts.defaultAnimationOptions || {}; if (!this._animators[this._animation]) { util$1.throw('No such animation: ' + this._animation); } } /** * @param {String} jsonString * @return {Object/null} */ createClass(AnimatorFactory, [{ key: 'setAnimationOptions', /** * @param {Object} options */ value: function setAnimationOptions(options) { this._animationOptions = options; } /** * @param {Object} options * @param {String} [options.animation] The animation name * @param {Object} [options.animationOptions] The animation options * @param {Object} defaultAnimator The default animator instance * @return {Object} An animator instance */ }, { key: 'newAnimator', value: function newAnimator() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var defaultAnimator = arguments[1]; var animator = null; if (options.animation instanceof this._baseClass) { return options.animation; } var Animator = null; if (typeof options.animation === 'string') { Animator = this._animators[options.animation]; } if (!Animator && defaultAnimator) { animator = defaultAnimator; } else { Animator = Animator || this._animators[this._animation]; var animationOpts = util$1.extend({}, this._animationOptions, options.animationOptions || {}, internal$1.config.animationsDisabled ? { duration: 0, delay: 0 } : {}); animator = new Animator(animationOpts); if (typeof animator === 'function') { animator = new animator(animationOpts); // eslint-disable-line new-cap } } if (!(animator instanceof this._baseClass)) { util$1.throw('"animator" is not an instance of ' + this._baseClassName); } return animator; } }], [{ key: 'parseAnimationOptionsString', value: function parseAnimationOptionsString(jsonString) { try { if (typeof jsonString === 'string') { var result = util$1.animationOptionsParse(jsonString); if ((typeof result === 'undefined' ? 'undefined' : _typeof(result)) === 'object' && result !== null) { return result; } else { console.error('"animation-options" attribute must be a JSON object string: ' + jsonString); } } return {}; } catch (e) { console.error('"animation-options" attribute must be a JSON object string: ' + jsonString); return {}; } } }]); return AnimatorFactory; }(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var autoStyleEnabled = true; // Modifiers var modifiersMap = { 'quiet': 'material--flat', 'light': 'material--flat', 'outline': 'material--flat', 'cta': '', 'large--quiet': 'material--flat large', 'large--cta': 'large', 'noborder': '', 'tappable': '' }; var platforms = {}; platforms.android = function (element) { var elementName = element.tagName.toLowerCase(); if (!util$1.hasModifier(element, 'material')) { var oldModifier = element.getAttribute('modifier') || ''; var newModifier = oldModifier.trim().split(/\s+/).map(function (e) { return modifiersMap.hasOwnProperty(e) ? modifiersMap[e] : e; }); newModifier.unshift('material'); element.setAttribute('modifier', newModifier.join(' ').trim()); } var elements = ['ons-alert-dialog-button', 'ons-toolbar-button', 'ons-back-button', 'ons-button', 'ons-list-item', 'ons-fab', 'ons-speed-dial', 'ons-speed-dial-item', 'ons-tab']; // Effects if (elements.indexOf(elementName) !== -1 && !element.hasAttribute('ripple') && !element.querySelector('ons-ripple')) { if (elementName === 'ons-list-item') { if (element.hasAttribute('tappable')) { element.setAttribute('ripple', ''); element.removeAttribute('tappable'); } } else { element.setAttribute('ripple', ''); } } }; platforms.ios = function (element) { // Modifiers if (util$1.removeModifier(element, 'material')) { if (util$1.removeModifier(element, 'material--flat')) { util$1.addModifier(element, util$1.removeModifier(element, 'large') ? 'large--quiet' : 'quiet'); } if (!element.getAttribute('modifier')) { element.removeAttribute('modifier'); } } // Effects if (element.hasAttribute('ripple')) { if (element.tagName.toLowerCase() === 'ons-list-item') { element.setAttribute('tappable', ''); } element.removeAttribute('ripple'); } }; var unlocked = { android: true }; var getPlatform = function getPlatform(element, force) { if (autoStyleEnabled && !element.hasAttribute('disable-auto-styling')) { var mobileOS = platform.getMobileOS(); if (platforms.hasOwnProperty(mobileOS) && (unlocked.hasOwnProperty(mobileOS) || force)) { return mobileOS; } } return null; }; var prepare = function prepare(element, force) { var p = getPlatform(element, force); p && platforms[p](element); }; var mapModifier = function mapModifier(modifier, element, force) { if (getPlatform(element, force)) { return modifier.split(/\s+/).map(function (m) { return modifiersMap.hasOwnProperty(m) ? modifiersMap[m] : m; }).join(' '); } return modifier; }; var restoreModifier = function restoreModifier(element) { if (getPlatform(element) === 'android') { var modifier = element.getAttribute('modifier') || ''; var newModifier = mapModifier(modifier, element); if (!/(^|\s+)material($|\s+)/i.test(modifier)) { newModifier = 'material ' + newModifier; } if (newModifier !== modifier) { element.setAttribute('modifier', newModifier.trim()); return true; } } return false; }; var autoStyle = { isEnabled: function isEnabled() { return autoStyleEnabled; }, enable: function enable() { return autoStyleEnabled = true; }, disable: function disable() { return autoStyleEnabled = false; }, prepare: prepare, mapModifier: mapModifier, getPlatform: getPlatform, restoreModifier: restoreModifier }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var ModifierUtil = function () { function ModifierUtil() { classCallCheck(this, ModifierUtil); } createClass(ModifierUtil, null, [{ key: 'diff', /** * @param {String} last * @param {String} current */ value: function diff(last, current) { last = makeDict(('' + last).trim()); current = makeDict(('' + current).trim()); var removed = Object.keys(last).reduce(function (result, token) { if (!current[token]) { result.push(token); } return result; }, []); var added = Object.keys(current).reduce(function (result, token) { if (!last[token]) { result.push(token); } return result; }, []); return { added: added, removed: removed }; function makeDict(modifier) { var dict = {}; ModifierUtil.split(modifier).forEach(function (token) { return dict[token] = token; }); return dict; } } /** * @param {Object} diff * @param {Array} diff.removed * @param {Array} diff.added * @param {Object} classList * @param {String} template */ }, { key: 'applyDiffToClassList', value: function applyDiffToClassList(diff, classList, template) { diff.added.map(function (modifier) { return template.replace(/\*/g, modifier); }).forEach(function (klass) { return klass.split(/\s+/).forEach(function (k) { return classList.add(k); }); }); diff.removed.map(function (modifier) { return template.replace(/\*/g, modifier); }).forEach(function (klass) { return klass.split(/\s+/).forEach(function (k) { return classList.remove(k); }); }); } /** * @param {Object} diff * @param {Array} diff.removed * @param {Array} diff.added * @param {HTMLElement} element * @param {Object} scheme */ }, { key: 'applyDiffToElement', value: function applyDiffToElement(diff, element, scheme) { Object.keys(scheme).forEach(function (selector) { var targetElements = !selector || util$1.match(element, selector) ? [element] : Array.prototype.filter.call(element.querySelectorAll(selector), function (targetElement) { return !util$1.findParent(targetElement, element.tagName, function (parent) { return parent === element; }); }); for (var i = 0; i < targetElements.length; i++) { ModifierUtil.applyDiffToClassList(diff, targetElements[i].classList, scheme[selector]); } }); } /** * @param {String} last * @param {String} current * @param {HTMLElement} element * @param {Object} scheme */ }, { key: 'onModifierChanged', value: function onModifierChanged(last, current, element, scheme) { ModifierUtil.applyDiffToElement(ModifierUtil.diff(last, current), element, scheme); autoStyle.restoreModifier(element); } }, { key: 'refresh', value: function refresh(element, scheme) { ModifierUtil.applyDiffToElement(ModifierUtil.diff('', element.getAttribute('modifier') || ''), element, scheme); } /** * @param {HTMLElement} element * @param {Object} scheme */ }, { key: 'initModifier', value: function initModifier(element, scheme) { var modifier = element.getAttribute('modifier'); if (typeof modifier !== 'string') { return; } ModifierUtil.applyDiffToElement({ removed: [], added: ModifierUtil.split(modifier) }, element, scheme); } }, { key: 'split', value: function split(modifier) { if (typeof modifier !== 'string') { return []; } return modifier.trim().split(/ +/).filter(function (token) { return token !== ''; }); } /** * Add modifier token to an element. */ }, { key: 'addModifier', value: function addModifier(element, modifierToken) { if (!element.hasAttribute('modifier')) { element.setAttribute('modifier', modifierToken); } else { var tokens = ModifierUtil.split(element.getAttribute('modifier')); if (tokens.indexOf(modifierToken) == -1) { tokens.push(modifierToken); element.setAttribute('modifier', tokens.join(' ')); } } } /** * Remove modifier token from an element. */ }, { key: 'removeModifier', value: function removeModifier(element, modifierToken) { if (element.hasAttribute('modifier')) { var tokens = ModifierUtil.split(element.getAttribute('modifier')); var index = tokens.indexOf(modifierToken); if (index !== -1) { tokens.splice(index, 1); element.setAttribute('modifier', tokens.join(' ')); } } } }]); return ModifierUtil; }(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var util$3 = { _ready: false, _domContentLoaded: false, _onDOMContentLoaded: function _onDOMContentLoaded() { util$3._domContentLoaded = true; if (platform.isWebView()) { window.document.addEventListener('deviceready', function () { util$3._ready = true; }, false); } else { util$3._ready = true; } }, addBackButtonListener: function addBackButtonListener(fn) { if (!this._domContentLoaded) { throw new Error('This method is available after DOMContentLoaded'); } if (this._ready) { window.document.addEventListener('backbutton', fn, false); } else { window.document.addEventListener('deviceready', function () { window.document.addEventListener('backbutton', fn, false); }); } }, removeBackButtonListener: function removeBackButtonListener(fn) { if (!this._domContentLoaded) { throw new Error('This method is available after DOMContentLoaded'); } if (this._ready) { window.document.removeEventListener('backbutton', fn, false); } else { window.document.addEventListener('deviceready', function () { window.document.removeEventListener('backbutton', fn, false); }); } } }; window.addEventListener('DOMContentLoaded', function () { return util$3._onDOMContentLoaded(); }, false); var HandlerRepository = { _store: {}, _genId: function () { var i = 0; return function () { return i++; }; }(), set: function set$$1(element, handler) { if (element.dataset.deviceBackButtonHandlerId) { this.remove(element); } var id = element.dataset.deviceBackButtonHandlerId = HandlerRepository._genId(); this._store[id] = handler; }, remove: function remove(element) { if (element.dataset.deviceBackButtonHandlerId) { delete this._store[element.dataset.deviceBackButtonHandlerId]; delete element.dataset.deviceBackButtonHandlerId; } }, get: function get$$1(element) { if (!element.dataset.deviceBackButtonHandlerId) { return undefined; } var id = element.dataset.deviceBackButtonHandlerId; if (!this._store[id]) { throw new Error(); } return this._store[id]; }, has: function has(element) { if (!element.dataset) { return false; } var id = element.dataset.deviceBackButtonHandlerId; return !!this._store[id]; } }; var DeviceBackButtonDispatcher = function () { function DeviceBackButtonDispatcher() { classCallCheck(this, DeviceBackButtonDispatcher); this._isEnabled = false; this._boundCallback = this._callback.bind(this); } /** * Enable to handle 'backbutton' events. */ createClass(DeviceBackButtonDispatcher, [{ key: 'enable', value: function enable() { if (!this._isEnabled) { util$3.addBackButtonListener(this._boundCallback); this._isEnabled = true; } } /** * Disable to handle 'backbutton' events. */ }, { key: 'disable', value: function disable() { if (this._isEnabled) { util$3.removeBackButtonListener(this._boundCallback); this._isEnabled = false; } } /** * Fire a 'backbutton' event manually. */ }, { key: 'fireDeviceBackButtonEvent', value: function fireDeviceBackButtonEvent() { var event = document.createEvent('Event'); event.initEvent('backbutton', true, true); document.dispatchEvent(event); } }, { key: '_callback', value: function _callback() { this._dispatchDeviceBackButtonEvent(); } /** * @param {HTMLElement} element * @param {Function} callback */ }, { key: 'createHandler', value: function createHandler(element, callback) { if (!(element instanceof HTMLElement)) { throw new Error('element must be an instance of HTMLElement'); } if (!(callback instanceof Function)) { throw new Error('callback must be an instance of Function'); } var handler = { _callback: callback, _element: element, disable: function disable() { HandlerRepository.remove(element); }, setListener: function setListener(callback) { this._callback = callback; }, enable: function enable() { HandlerRepository.set(element, this); }, isEnabled: function isEnabled() { return HandlerRepository.get(element) === this; }, destroy: function destroy() { HandlerRepository.remove(element); this._callback = this._element = null; } }; handler.enable(); return handler; } }, { key: '_dispatchDeviceBackButtonEvent', value: function _dispatchDeviceBackButtonEvent() { var tree = this._captureTree(); var element = this._findHandlerLeafElement(tree); var handler = HandlerRepository.get(element); handler._callback(createEvent(element)); function createEvent(element) { return { _element: element, callParentHandler: function callParentHandler() { var parent = this._element.parentNode; while (parent) { handler = HandlerRepository.get(parent); if (handler) { return handler._callback(createEvent(parent)); } parent = parent.parentNode; } } }; } } /** * @return {Object} */ }, { key: '_captureTree', value: function _captureTree() { return createTree(document.body); function createTree(element) { var tree = { element: element, children: Array.prototype.concat.apply([], arrayOf(element.children).map(function (childElement) { if (childElement.style.display === 'none' || childElement._isShown === false) { return []; } if (childElement.children.length === 0 && !HandlerRepository.has(childElement)) { return []; } var result = createTree(childElement); if (result.children.length === 0 && !HandlerRepository.has(result.element)) { return []; } return [result]; })) }; if (!HandlerRepository.has(tree.element)) { for (var i = 0; i < tree.children.length; i++) { var subTree = tree.children[i]; if (HandlerRepository.has(subTree.element)) { return subTree; } } } return tree; } function arrayOf(target) { var result = []; for (var i = 0; i < target.length; i++) { result.push(target[i]); } return result; } } /** * @param {Object} tree * @return {HTMLElement} */ }, { key: '_findHandlerLeafElement', value: function _findHandlerLeafElement(tree) { return find(tree); function find(node) { if (node.children.length === 0) { return node.element; } if (node.children.length === 1) { return find(node.children[0]); } return node.children.map(function (childNode) { return childNode.element; }).reduce(function (left, right) { if (!left) { return right; } var leftZ = parseInt(window.getComputedStyle(left, '').zIndex, 10); var rightZ = parseInt(window.getComputedStyle(right, '').zIndex, 10); if (!isNaN(leftZ) && !isNaN(rightZ)) { return leftZ > rightZ ? left : right; } throw new Error('Capturing backbutton-handler is failure.'); }, null); } } }]); return DeviceBackButtonDispatcher; }(); var deviceBackButtonDispatcher = new DeviceBackButtonDispatcher(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ internal$1.AnimatorFactory = AnimatorFactory; internal$1.ModifierUtil = ModifierUtil; internal$1.dbbDispatcher = deviceBackButtonDispatcher; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var startsWith = function startsWith(s, c) { return s.substr(0, c.length) === c; }; var endsWith = function endsWith(s, c) { return s.substr(s.length - c.length, c.length) === c; }; var unwrap = function unwrap(s) { return s.slice(1, -1); }; var isObjectString = function isObjectString(s) { return startsWith(s, '{') && endsWith(s, '}'); }; var isArrayString = function isArrayString(s) { return startsWith(s, '[') && endsWith(s, ']'); }; var isQuotedString = function isQuotedString(s) { return startsWith(s, '\'') && endsWith(s, '\'') || startsWith(s, '"') && endsWith(s, '"'); }; var error$1 = function error(token, string, originalString) { throw new Error('Unexpected token \'' + token + '\' at position ' + (originalString.length - string.length - 1) + ' in string: \'' + originalString + '\''); }; var processToken = function processToken(token, string, originalString) { if (token === 'true' || token === 'false') { return token === 'true'; } else if (isQuotedString(token)) { return unwrap(token); } else if (!isNaN(token)) { return +token; } else if (isObjectString(token)) { return parseObject(unwrap(token)); } else if (isArrayString(token)) { return parseArray(unwrap(token)); } else { error$1(token, string, originalString); } }; var nextToken = function nextToken(string) { string = string.trim(); var limit = string.length; if (string[0] === ':' || string[0] === ',') { limit = 1; } else if (string[0] === '{' || string[0] === '[') { var c = string.charCodeAt(0); var nestedObject = 1; for (var i = 1; i < string.length; i++) { if (string.charCodeAt(i) === c) { nestedObject++; } else if (string.charCodeAt(i) === c + 2) { nestedObject--; if (nestedObject === 0) { limit = i + 1; break; } } } } else if (string[0] === '\'' || string[0] === '"') { for (var _i = 1; _i < string.length; _i++) { if (string[_i] === string[0]) { limit = _i + 1; break; } } } else { for (var _i2 = 1; _i2 < string.length; _i2++) { if ([' ', ',', ':'].indexOf(string[_i2]) !== -1) { limit = _i2; break; } } } return string.slice(0, limit); }; var parseObject = function parseObject(string) { var isValidKey = function isValidKey(key) { return (/^[A-Z_$][A-Z0-9_$]*$/i.test(key) ); }; string = string.trim(); var originalString = string; var object = {}; var readingKey = true, key = void 0, previousToken = void 0, token = void 0; while (string.length > 0) { previousToken = token; token = nextToken(string); string = string.slice(token.length, string.length).trim(); if (token === ':' && (!readingKey || !previousToken || previousToken === ',') || token === ',' && readingKey || token !== ':' && token !== ',' && previousToken && previousToken !== ',' && previousToken !== ':') { error$1(token, string, originalString); } else if (token === ':' && readingKey && previousToken) { previousToken = isQuotedString(previousToken) ? unwrap(previousToken) : previousToken; if (isValidKey(previousToken)) { key = previousToken; readingKey = false; } else { throw new Error('Invalid key token \'' + previousToken + '\' at position 0 in string: \'' + originalString + '\''); } } else if (token === ',' && !readingKey && previousToken) { object[key] = processToken(previousToken, string, originalString); readingKey = true; } } if (token) { object[key] = processToken(token, string, originalString); } return object; }; var parseArray = function parseArray(string) { string = string.trim(); var originalString = string; var array = []; var previousToken = void 0, token = void 0; while (string.length > 0) { previousToken = token; token = nextToken(string); string = string.slice(token.length, string.length).trim(); if (token === ',' && (!previousToken || previousToken === ',')) { error$1(token, string, originalString); } else if (token === ',') { array.push(processToken(previousToken, string, originalString)); } } if (token) { if (token !== ',') { array.push(processToken(token, string, originalString)); } else { error$1(token, string, originalString); } } return array; }; var parse = function parse(string) { string = string.trim(); if (isObjectString(string)) { return parseObject(unwrap(string)); } else if (isArrayString(string)) { return parseArray(unwrap(string)); } else { throw new Error('Provided string must be object or array like: ' + string); } }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var util$1 = {}; var errorPrefix = '[Onsen UI]'; util$1.globals = { fabOffset: 0, errorPrefix: errorPrefix, supportsPassive: false }; platform._runOnActualPlatform(function () { util$1.globals.actualMobileOS = platform.getMobileOS(); util$1.globals.isUIWebView = platform.isUIWebView(); util$1.globals.isWKWebView = platform.isWKWebView(); }); try { var opts = Object.defineProperty({}, 'passive', { get: function get$$1() { util$1.globals.supportsPassive = true; } }); window.addEventListener('testPassive', null, opts); window.removeEventListener('testPassive', null, opts); } catch (e) { } /** * @param {Element} el Target * @param {String} name Event name * @param {Function} handler Event handler * @param {Object} [opt] Event options (passive, capture...) * @param {Boolean} [isGD] If comes from GestureDetector. Just for testing. */ util$1.addEventListener = function (el, name, handler, opt, isGD) { el.addEventListener(name, handler, util$1.globals.supportsPassive ? opt : (opt || {}).capture); }; util$1.removeEventListener = function (el, name, handler, opt, isGD) { el.removeEventListener(name, handler, util$1.globals.supportsPassive ? opt : (opt || {}).capture); }; /** * @param {String/Function} query dot class name or node name or matcher function. * @return {Function} */ util$1.prepareQuery = function (query) { return query instanceof Function ? query : function (element) { return util$1.match(element, query); }; }; /** * @param {Element} e * @param {String/Function} s CSS Selector. * @return {Boolean} */ util$1.match = function (e, s) { return (e.matches || e.webkitMatchesSelector || e.mozMatchesSelector || e.msMatchesSelector).call(e, s); }; /** * @param {Element} element * @param {String/Function} query dot class name or node name or matcher function. * @return {HTMLElement/null} */ util$1.findChild = function (element, query) { var match = util$1.prepareQuery(query); // Caution: `element.children` is `undefined` in some environments if `element` is `svg` for (var i = 0; i < element.childNodes.length; i++) { var node = element.childNodes[i]; if (node.nodeType !== Node.ELEMENT_NODE) { // process only element nodes continue; } if (match(node)) { return node; } } return null; }; /** * @param {Element} element * @param {String/Function} query dot class name or node name or matcher function. * @return {HTMLElement/null} */ util$1.findParent = function (element, query, until) { var match = util$1.prepareQuery(query); var parent = element.parentNode; for (;;) { if (!parent || parent === document || parent instanceof DocumentFragment || until && until(parent)) { return null; } else if (match(parent)) { return parent; } parent = parent.parentNode; } }; /** * @param {Element} element * @return {boolean} */ util$1.isAttached = function (element) { return document.body.contains(element); }; /** * @param {Element} element * @return {boolean} */ util$1.hasAnyComponentAsParent = function (element) { while (element && document.documentElement !== element) { element = element.parentNode; if (element && element.nodeName.toLowerCase().match(/(ons-navigator|ons-tabbar|ons-modal)/)) { return true; } } return false; }; /** * @param {Object} element * @return {Array} */ util$1.getAllChildNodes = function (element) { var _ref; return (_ref = [element]).concat.apply(_ref, toConsumableArray(Array.from(element.children).map(function (childEl) { return util$1.getAllChildNodes(childEl); }))); }; /** * @param {Element} element * @return {boolean} */ util$1.isPageControl = function (element) { return element.nodeName.match(/^ons-(navigator|splitter|tabbar|page)$/i); }; /** * @param {Element} element * @param {String} action to propagate */ util$1.propagateAction = function (element, action) { for (var i = 0; i < element.childNodes.length; i++) { var child = element.childNodes[i]; if (child[action] instanceof Function) { child[action](); } else { util$1.propagateAction(child, action); } } }; /** * @param {String} string - string to be camelized * @return {String} Camelized string */ util$1.camelize = function (string) { return string.toLowerCase().replace(/-([a-z])/g, function (m, l) { return l.toUpperCase(); }); }; /** * @param {String} string - string to be hyphenated * @return {String} Hyphenated string */ util$1.hyphenate = function (string) { return string.replace(/([a-zA-Z])([A-Z])/g, '$1-$2').toLowerCase(); }; /** * @param {String} selector - tag and class only * @param {Object} style * @param {Element} */ util$1.create = function () { var selector = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var style = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var classList = selector.split('.'); var element = document.createElement(classList.shift() || 'div'); if (classList.length) { element.className = classList.join(' '); } styler(element, style); return element; }; /** * @param {String} html * @return {Element} */ util$1.createElement = function (html) { var wrapper = document.createElement('div'); if (html instanceof DocumentFragment) { wrapper.appendChild(document.importNode(html, true)); } else { wrapper.innerHTML = html.trim(); } if (wrapper.children.length > 1) { util$1.throw('HTML template must contain a single root element'); } var element = wrapper.children[0]; wrapper.children[0].remove(); return element; }; /** * @param {String} html * @return {HTMLFragment} */ util$1.createFragment = function (html) { var template = document.createElement('template'); template.innerHTML = html; return document.importNode(template.content, true); }; /* * @param {Object} dst Destination object. * @param {...Object} src Source object(s). * @returns {Object} Reference to `dst`. */ util$1.extend = function (dst) { for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } for (var i = 0; i < args.length; i++) { if (args[i]) { var keys = Object.keys(args[i]); for (var j = 0; j < keys.length; j++) { var key = keys[j]; dst[key] = args[i][key]; } } } return dst; }; /** * @param {Object} arrayLike * @return {Array} */ util$1.arrayFrom = function (arrayLike) { return Array.prototype.slice.apply(arrayLike); }; /** * @param {String} jsonString * @param {Object} [failSafe] * @return {Object} */ util$1.parseJSONObjectSafely = function (jsonString) { var failSafe = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; try { var result = JSON.parse('' + jsonString); if ((typeof result === 'undefined' ? 'undefined' : _typeof(result)) === 'object' && result !== null) { return result; } } catch (e) { return failSafe; } return failSafe; }; /** * @param {String} path - path such as 'myApp.controllers.data.loadData' * @return {Any} - whatever is located at that path */ util$1.findFromPath = function (path) { path = path.split('.'); var el = window, key; while (key = path.shift()) { // eslint-disable-line no-cond-assign el = el[key]; } return el; }; /** * @param {HTMLElement} container - Page or page-container that implements 'topPage' * @return {HTMLElement|null} - Visible page element or null if not found. */ util$1.getTopPage = function (container) { return container && (container.tagName.toLowerCase() === 'ons-page' ? container : container.topPage) || null; }; /** * @param {HTMLElement} container - Element where the search begins * @return {HTMLElement|null} - Page element that contains the visible toolbar or null. */ util$1.findToolbarPage = function (container) { var page = util$1.getTopPage(container); if (page) { if (page._canAnimateToolbar()) { return page; } for (var i = 0; i < page._contentElement.children.length; i++) { var nextPage = util$1.getTopPage(page._contentElement.children[i]); if (nextPage && !/ons-tabbar/i.test(page._contentElement.children[i].tagName)) { return util$1.findToolbarPage(nextPage); } } } return null; }; /** * @param {Element} element * @param {String} eventName * @param {Object} [detail] * @return {CustomEvent} */ util$1.triggerElementEvent = function (target, eventName) { var detail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var event = new CustomEvent(eventName, { bubbles: true, cancelable: true, detail: detail }); Object.keys(detail).forEach(function (key) { event[key] = detail[key]; }); target.dispatchEvent(event); return event; }; /** * @param {Element} target * @param {String} modifierName * @return {Boolean} */ util$1.hasModifier = function (target, modifierName) { if (!target.hasAttribute('modifier')) { return false; } return RegExp('(^|\\s+)' + modifierName + '($|\\s+)', 'i').test(target.getAttribute('modifier')); }; /** * @param {Element} target * @param {String} modifierName * @param {Object} options.autoStyle Maps the modifierName to the corresponding styled modifier. * @param {Object} options.forceAutoStyle Ignores platform limitation. * @return {Boolean} Whether it was added or not. */ util$1.addModifier = function (target, modifierName) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (options.autoStyle) { modifierName = autoStyle.mapModifier(modifierName, target, options.forceAutoStyle); } if (util$1.hasModifier(target, modifierName)) { return false; } target.setAttribute('modifier', ((target.getAttribute('modifier') || '') + ' ' + modifierName).trim()); return true; }; /** * @param {Element} target * @param {String} modifierName * @param {Object} options.autoStyle Maps the modifierName to the corresponding styled modifier. * @param {Object} options.forceAutoStyle Ignores platform limitation. * @return {Boolean} Whether it was found or not. */ util$1.removeModifier = function (target, modifierName) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (options.autoStyle) { modifierName = autoStyle.mapModifier(modifierName, target, options.forceAutoStyle); } if (!target.getAttribute('modifier') || !util$1.hasModifier(target, modifierName)) { return false; } var newModifiers = target.getAttribute('modifier').split(/\s+/).filter(function (m) { return m && m !== modifierName; }); newModifiers.length ? target.setAttribute('modifier', newModifiers.join(' ')) : target.removeAttribute('modifier'); return true; }; /** * @param {Element} target * @param {String} modifierName * @param {Boolean} options.force Forces modifier to be added or removed. * @param {Object} options.autoStyle Maps the modifierName to the corresponding styled modifier. * @param {Boolean} options.forceAutoStyle Ignores platform limitation. * @return {Boolean} Whether it was found or not. */ util$1.toggleModifier = function () { var options = arguments.length > 2 ? arguments.length <= 2 ? undefined : arguments[2] : {}; var force = typeof options === 'boolean' ? options : options.force; var toggle = typeof force === 'boolean' ? force : !util$1.hasModifier.apply(util$1, arguments); toggle ? util$1.addModifier.apply(util$1, arguments) : util$1.removeModifier.apply(util$1, arguments); }; /** * @param {Element} el * @param {String} defaultClass * @param {Object} scheme */ util$1.restoreClass = function (el, defaultClass, scheme) { defaultClass.split(/\s+/).forEach(function (c) { return c !== '' && !el.classList.contains(c) && el.classList.add(c); }); el.hasAttribute('modifier') && ModifierUtil.refresh(el, scheme); }; // TODO: FIX util$1.updateParentPosition = function (el) { if (!el._parentUpdated && el.parentElement) { if (window.getComputedStyle(el.parentElement).getPropertyValue('position') === 'static') { el.parentElement.style.position = 'relative'; } el._parentUpdated = true; } }; util$1.toggleAttribute = function (element, name, value) { if (value) { element.setAttribute(name, typeof value === 'boolean' ? '' : value); } else { element.removeAttribute(name); } }; util$1.bindListeners = function (element, listenerNames) { listenerNames.forEach(function (name) { var boundName = name.replace(/^_[a-z]/, '_bound' + name[1].toUpperCase()); element[boundName] = element[boundName] || element[name].bind(element); }); }; util$1.each = function (obj, f) { return Object.keys(obj).forEach(function (key) { return f(key, obj[key]); }); }; /** * @param {Element} target * @param {boolean} hasRipple * @param {Object} attrs */ util$1.updateRipple = function (target, hasRipple) { var attrs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; if (hasRipple === undefined) { hasRipple = target.hasAttribute('ripple'); } var rippleElement = util$1.findChild(target, 'ons-ripple'); if (hasRipple) { if (!rippleElement) { var element = document.createElement('ons-ripple'); Object.keys(attrs).forEach(function (key) { return element.setAttribute(key, attrs[key]); }); target.insertBefore(element, target.firstChild); } } else if (rippleElement) { rippleElement.remove(); } }; /** * @param {String} * @return {Object} */ util$1.animationOptionsParse = parse; /** * @param {*} value */ util$1.isInteger = function (value) { return typeof value === 'number' && isFinite(value) && Math.floor(value) === value; }; /** * @return {Object} Deferred promise. */ util$1.defer = function () { var deferred = {}; deferred.promise = new Promise(function (resolve, reject) { deferred.resolve = resolve; deferred.reject = reject; }); return deferred; }; /** * Show warnings when they are enabled. * * @param {*} arguments to console.warn */ util$1.warn = function () { for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } if (!internal$1.config.warningsDisabled) { var _console; (_console = console).warn.apply(_console, [errorPrefix].concat(args)); } }; util$1.throw = function (message) { throw new Error(errorPrefix + ' ' + message); }; util$1.throwAbstract = function () { return util$1.throw('Cannot instantiate abstract class'); }; util$1.throwMember = function () { return util$1.throw('Class member must be implemented'); }; util$1.throwPageLoader = function () { return util$1.throw('First parameter should be an instance of PageLoader'); }; util$1.throwAnimator = function (el) { return util$1.throw('"Animator" param must inherit ' + el + 'Animator'); }; var prevent = function prevent(e) { return e.cancelable && e.preventDefault(); }; /** * Prevent scrolling while draging horizontally on iOS. * * @param {gd} GestureDetector instance */ util$1.iosPreventScroll = function (gd) { if (util$1.globals.actualMobileOS === 'ios') { var clean = function clean(e) { gd.off('touchmove', prevent); gd.off('dragend', clean); }; gd.on('touchmove', prevent); gd.on('dragend', clean); } }; /** * Prevents scroll in underlying pages on iOS. See #2220 #2274 #1949 * * @param {el} HTMLElement that prevents the events * @param {add} Boolean Add or remove event listeners */ util$1.iosPageScrollFix = function (add) { // Full fix - May cause issues with UIWebView's momentum scroll if (util$1.globals.actualMobileOS === 'ios') { document.body.classList.toggle('ons-ios-scroll', add); // Allows custom and localized fixes (#2274) if (!util$1.globals.isUIWebView || internal$1.config.forceUIWebViewScrollFix) { document.body.classList.toggle('ons-ios-scroll-fix', add); } } }; util$1.iosMaskScrollFix = function (el, add) { // Half fix - only prevents scroll on masks if (util$1.globals.isUIWebView) { var action = (add ? 'add' : 'remove') + 'EventListener'; el[action]('touchmove', prevent, false); } }; /** * Distance and deltaTime filter some weird dragstart events that are not fired immediately. * * @param {event} */ util$1.isValidGesture = function (event) { return event.gesture !== undefined && (event.gesture.distance <= 15 || event.gesture.deltaTime <= 100); }; util$1.checkMissingImport = function () { for (var _len3 = arguments.length, elementNames = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { elementNames[_key3] = arguments[_key3]; } elementNames.forEach(function (name) { if (!onsElements[name]) { util$1.throw('Ons' + name + ' is required but was not imported (Custom Elements)'); } }); }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * Minimal animation library for managing css transition on mobile browsers. */ var TIMEOUT_RATIO = 1.4; var util$4 = {}; // capitalize string util$4.capitalize = function (str) { return str.charAt(0).toUpperCase() + str.slice(1); }; /** * @param {Object} params * @param {String} params.property * @param {Float} params.duration * @param {String} params.timing */ util$4.buildTransitionValue = function (params) { params.property = params.property || 'all'; params.duration = params.duration || 0.4; params.timing = params.timing || 'linear'; var props = params.property.split(/ +/); return props.map(function (prop) { return prop + ' ' + params.duration + 's ' + params.timing; }).join(', '); }; /** * Add an event handler on "transitionend" event. */ util$4.onceOnTransitionEnd = function (element, callback) { if (!element) { return function () {}; } var fn = function fn(event) { if (element == event.target) { event.stopPropagation(); removeListeners(); callback(); } }; var removeListeners = function removeListeners() { util$4._transitionEndEvents.forEach(function (eventName) { element.removeEventListener(eventName, fn, false); }); }; util$4._transitionEndEvents.forEach(function (eventName) { element.addEventListener(eventName, fn, false); }); return removeListeners; }; util$4._transitionEndEvents = function () { if ('ontransitionend' in window) { return ['transitionend']; } if ('onwebkittransitionend' in window) { return ['webkitTransitionEnd']; } if (util$4.vendorPrefix === 'webkit' || util$4.vendorPrefix === 'o' || util$4.vendorPrefix === 'moz' || util$4.vendorPrefix === 'ms') { return [util$4.vendorPrefix + 'TransitionEnd', 'transitionend']; } return []; }(); util$4._cssPropertyDict = function () { var styles = window.getComputedStyle(document.documentElement, ''); var dict = {}; var a = 'A'.charCodeAt(0); var z = 'z'.charCodeAt(0); var upper = function upper(s) { return s.substr(1).toUpperCase(); }; for (var i = 0; i < styles.length; i++) { var key = styles[i].replace(/^[-]+/, '').replace(/[-][a-z]/g, upper).replace(/^moz/, 'Moz'); if (a <= key.charCodeAt(0) && z >= key.charCodeAt(0)) { if (key !== 'cssText' && key !== 'parentText') { dict[key] = true; } } } return dict; }(); util$4.hasCssProperty = function (name) { return name in util$4._cssPropertyDict; }; /** * Vendor prefix for css property. */ util$4.vendorPrefix = function () { var styles = window.getComputedStyle(document.documentElement, ''), pre = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || styles.OLink === '' && ['', 'o'])[1]; return pre; }(); util$4.forceLayoutAtOnce = function (elements, callback) { this.batchImmediate(function () { elements.forEach(function (element) { // force layout element.offsetHeight; }); callback(); }); }; util$4.batchImmediate = function () { var callbacks = []; return function (callback) { if (callbacks.length === 0) { setImmediate(function () { var concreateCallbacks = callbacks.slice(0); callbacks = []; concreateCallbacks.forEach(function (callback) { callback(); }); }); } callbacks.push(callback); }; }(); util$4.batchAnimationFrame = function () { var callbacks = []; var raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { setTimeout(callback, 1000 / 60); }; return function (callback) { if (callbacks.length === 0) { raf(function () { var concreateCallbacks = callbacks.slice(0); callbacks = []; concreateCallbacks.forEach(function (callback) { callback(); }); }); } callbacks.push(callback); }; }(); util$4.transitionPropertyName = function () { if (util$4.hasCssProperty('transitionDuration')) { return 'transition'; } if (util$4.hasCssProperty(util$4.vendorPrefix + 'TransitionDuration')) { return util$4.vendorPrefix + 'Transition'; } throw new Error('Invalid state'); }(); /** * @param {HTMLElement} element */ var Animit = function Animit(element, defaults) { if (!(this instanceof Animit)) { return new Animit(element, defaults); } if (element instanceof HTMLElement) { this.elements = [element]; } else if (Object.prototype.toString.call(element) === '[object Array]') { this.elements = element; } else { throw new Error('First argument must be an array or an instance of HTMLElement.'); } this.defaults = defaults; this.transitionQueue = []; this.lastStyleAttributeDict = []; }; Animit.prototype = { /** * @property {Array} */ transitionQueue: undefined, /** * @property {Array} */ elements: undefined, /** * @property {Object} */ defaults: undefined, /** * Start animation sequence with passed animations. * * @param {Function} callback */ play: function play(callback) { if (typeof callback === 'function') { this.transitionQueue.push(function (done) { callback(); done(); }); } this.startAnimation(); return this; }, /** * Most of the animations follow this default process. * * @param {from} css or options object containing css * @param {to} css or options object containing css * @param {delay} delay to wait */ default: function _default(from, to, delay) { function step(params, duration, timing) { if (params.duration !== undefined) { duration = params.duration; } if (params.timing !== undefined) { timing = params.timing; } return { css: params.css || params, duration: duration, timing: timing }; } return this.saveStyle().queue(step(from, 0, this.defaults.timing)).wait(delay === undefined ? this.defaults.delay : delay).queue(step(to, this.defaults.duration, this.defaults.timing)).restoreStyle(); }, /** * Queue transition animations or other function. * * e.g. animit(elt).queue({color: 'red'}) * e.g. animit(elt).queue({color: 'red'}, {duration: 0.4}) * e.g. animit(elt).queue({css: {color: 'red'}, duration: 0.2}) * * @param {Object|Animit.Transition|Function} transition * @param {Object} [options] */ queue: function queue(transition, options) { var queue = this.transitionQueue; if (transition && options) { options.css = transition; transition = new Animit.Transition(options); } if (!(transition instanceof Function || transition instanceof Animit.Transition)) { if (transition.css) { transition = new Animit.Transition(transition); } else { transition = new Animit.Transition({ css: transition }); } } if (transition instanceof Function) { queue.push(transition); } else if (transition instanceof Animit.Transition) { queue.push(transition.build()); } else { throw new Error('Invalid arguments'); } return this; }, /** * Queue transition animations. * * @param {Float} seconds */ wait: function wait(seconds) { if (seconds > 0) { this.transitionQueue.push(function (done) { setTimeout(done, 1000 * seconds); }); } return this; }, saveStyle: function saveStyle() { this.transitionQueue.push(function (done) { this.elements.forEach(function (element, index) { var css = this.lastStyleAttributeDict[index] = {}; for (var i = 0; i < element.style.length; i++) { css[element.style[i]] = element.style[element.style[i]]; } }.bind(this)); done(); }.bind(this)); return this; }, /** * Restore element's style. * * @param {Object} [options] * @param {Float} [options.duration] * @param {String} [options.timing] * @param {String} [options.transition] */ restoreStyle: function restoreStyle(options) { options = options || {}; var self = this; if (options.transition && !options.duration) { throw new Error('"options.duration" is required when "options.transition" is enabled.'); } var transitionName = util$4.transitionPropertyName; if (options.transition || options.duration && options.duration > 0) { var transitionValue = options.transition || 'all ' + options.duration + 's ' + (options.timing || 'linear'); this.transitionQueue.push(function (done) { var elements = this.elements; var timeoutId; var clearTransition = function clearTransition() { elements.forEach(function (element) { element.style[transitionName] = ''; }); }; // add "transitionend" event handler var removeListeners = util$4.onceOnTransitionEnd(elements[0], function () { clearTimeout(timeoutId); clearTransition(); done(); }); // for fail safe. timeoutId = setTimeout(function () { removeListeners(); clearTransition(); done(); }, options.duration * 1000 * TIMEOUT_RATIO); // transition and style settings elements.forEach(function (element, index) { var css = self.lastStyleAttributeDict[index]; if (!css) { throw new Error('restoreStyle(): The style is not saved. Invoke saveStyle() before.'); } self.lastStyleAttributeDict[index] = undefined; var name; for (var i = 0, len = element.style.length; i < len; i++) { name = element.style[i]; if (css[name] === undefined) { css[name] = ''; } } element.style[transitionName] = transitionValue; Object.keys(css).forEach(function (key) { if (key !== transitionName) { element.style[key] = css[key]; } }); element.style[transitionName] = transitionValue; }); }); } else { this.transitionQueue.push(function (done) { reset(); done(); }); } return this; function reset() { // Clear transition animation settings. self.elements.forEach(function (element, index) { element.style[transitionName] = 'none'; var css = self.lastStyleAttributeDict[index]; if (!css) { throw new Error('restoreStyle(): The style is not saved. Invoke saveStyle() before.'); } self.lastStyleAttributeDict[index] = undefined; for (var i = 0, name = ''; i < element.style.length; i++) { name = element.style[i]; if (typeof css[element.style[i]] === 'undefined') { css[element.style[i]] = ''; } } Object.keys(css).forEach(function (key) { element.style[key] = css[key]; }); }); } }, /** * Start animation sequence. */ startAnimation: function startAnimation() { this._dequeueTransition(); return this; }, _dequeueTransition: function _dequeueTransition() { var transition = this.transitionQueue.shift(); if (this._currentTransition) { throw new Error('Current transition exists.'); } this._currentTransition = transition; var self = this; var called = false; var done = function done() { if (!called) { called = true; self._currentTransition = undefined; self._dequeueTransition(); } else { throw new Error('Invalid state: This callback is called twice.'); } }; if (transition) { transition.call(this, done); } } }; /** * @param {Animit} arguments */ Animit.runAll = function () /* arguments... */{ for (var i = 0; i < arguments.length; i++) { arguments[i].play(); } }; /** * @param {Object} options * @param {Float} [options.duration] * @param {String} [options.property] * @param {String} [options.timing] */ Animit.Transition = function (options) { this.options = options || {}; this.options.duration = this.options.duration || 0; this.options.timing = this.options.timing || 'linear'; this.options.css = this.options.css || {}; this.options.property = this.options.property || 'all'; }; Animit.Transition.prototype = { /** * @param {HTMLElement} element * @return {Function} */ build: function build() { if (Object.keys(this.options.css).length === 0) { throw new Error('options.css is required.'); } var css = createActualCssProps(this.options.css); if (this.options.duration > 0) { var transitionValue = util$4.buildTransitionValue(this.options); var self = this; return function (callback) { var elements = this.elements; var timeout = self.options.duration * 1000 * TIMEOUT_RATIO; var timeoutId; var removeListeners = util$4.onceOnTransitionEnd(elements[0], function () { clearTimeout(timeoutId); callback(); }); timeoutId = setTimeout(function () { removeListeners(); callback(); }, timeout); elements.forEach(function (element) { element.style[util$4.transitionPropertyName] = transitionValue; Object.keys(css).forEach(function (name) { element.style[name] = css[name]; }); }); }; } if (this.options.duration <= 0) { return function (callback) { var elements = this.elements; elements.forEach(function (element) { element.style[util$4.transitionPropertyName] = ''; Object.keys(css).forEach(function (name) { element.style[name] = css[name]; }); }); if (elements.length > 0) { util$4.forceLayoutAtOnce(elements, function () { util$4.batchAnimationFrame(callback); }); } else { util$4.batchAnimationFrame(callback); } }; } function createActualCssProps(css) { var result = {}; Object.keys(css).forEach(function (name) { var value = css[name]; if (util$4.hasCssProperty(name)) { result[name] = value; return; } var prefixed = util$4.vendorPrefix + util$4.capitalize(name); if (util$4.hasCssProperty(prefixed)) { result[prefixed] = value; } else { result[prefixed] = value; result[name] = value; } }); return result; } } }; /* * Gesture detector library that forked from github.com/EightMedia/hammer.js. */ var Event$1; var Utils; var Detection; var PointerEvent; /** * @object ons.GestureDetector * @category gesture * @description * [en]Utility class for gesture detection.[/en] * [ja]ジェスチャを検知するためのユーティリティクラスです。[/ja] */ /** * @method constructor * @signature constructor(element[, options]) * @description * [en]Create a new GestureDetector instance.[/en] * [ja]GestureDetectorのインスタンスを生成します。[/ja] * @param {Element} element * [en]Name of the event.[/en] * [ja]ジェスチャを検知するDOM要素を指定します。[/ja] * @param {Object} [options] * [en]Options object.[/en] * [ja]オプションを指定します。[/ja] * @return {ons.GestureDetector.Instance} */ var GestureDetector = function GestureDetector(element, options) { return new GestureDetector.Instance(element, options || {}); }; /** * default settings. * more settings are defined per gesture at `/gestures`. Each gesture can be disabled/enabled * by setting it's name (like `swipe`) to false. * You can set the defaults for all instances by changing this object before creating an instance. * @example * ```` * GestureDetector.defaults.drag = false; * GestureDetector.defaults.behavior.touchAction = 'pan-y'; * delete GestureDetector.defaults.behavior.userSelect; * ```` * @property defaults * @type {Object} */ GestureDetector.defaults = { behavior: { // userSelect: 'none', // Also disables selection in `input` children touchAction: 'pan-y', touchCallout: 'none', contentZooming: 'none', userDrag: 'none', tapHighlightColor: 'rgba(0,0,0,0)' } }; /** * GestureDetector document where the base events are added at * @property DOCUMENT * @type {HTMLElement} * @default window.document */ GestureDetector.DOCUMENT = document; /** * detect support for pointer events * @property HAS_POINTEREVENTS * @type {Boolean} */ GestureDetector.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled; /** * detect support for touch events * @property HAS_TOUCHEVENTS * @type {Boolean} */ GestureDetector.HAS_TOUCHEVENTS = 'ontouchstart' in window; /** * detect mobile browsers * @property IS_MOBILE * @type {Boolean} */ GestureDetector.IS_MOBILE = /mobile|tablet|ip(ad|hone|od)|android|silk/i.test(navigator.userAgent); /** * detect if we want to support mouseevents at all * @property NO_MOUSEEVENTS * @type {Boolean} */ GestureDetector.NO_MOUSEEVENTS = GestureDetector.HAS_TOUCHEVENTS && GestureDetector.IS_MOBILE || GestureDetector.HAS_POINTEREVENTS; /** * interval in which GestureDetector recalculates current velocity/direction/angle in ms * @property CALCULATE_INTERVAL * @type {Number} * @default 25 */ GestureDetector.CALCULATE_INTERVAL = 25; /** * eventtypes per touchevent (start, move, end) are filled by `Event.determineEventTypes` on `setup` * the object contains the DOM event names per type (`EVENT_START`, `EVENT_MOVE`, `EVENT_END`) * @property EVENT_TYPES * @private * @writeOnce * @type {Object} */ var EVENT_TYPES = {}; /** * direction strings, for safe comparisons * @property DIRECTION_DOWN|LEFT|UP|RIGHT * @final * @type {String} * @default 'down' 'left' 'up' 'right' */ var DIRECTION_DOWN = GestureDetector.DIRECTION_DOWN = 'down'; var DIRECTION_LEFT = GestureDetector.DIRECTION_LEFT = 'left'; var DIRECTION_UP = GestureDetector.DIRECTION_UP = 'up'; var DIRECTION_RIGHT = GestureDetector.DIRECTION_RIGHT = 'right'; /** * pointertype strings, for safe comparisons * @property POINTER_MOUSE|TOUCH|PEN * @final * @type {String} * @default 'mouse' 'touch' 'pen' */ var POINTER_MOUSE = GestureDetector.POINTER_MOUSE = 'mouse'; var POINTER_TOUCH = GestureDetector.POINTER_TOUCH = 'touch'; var POINTER_PEN = GestureDetector.POINTER_PEN = 'pen'; /** * eventtypes * @property EVENT_START|MOVE|END|RELEASE|TOUCH * @final * @type {String} * @default 'start' 'change' 'move' 'end' 'release' 'touch' */ var EVENT_START = GestureDetector.EVENT_START = 'start'; var EVENT_MOVE = GestureDetector.EVENT_MOVE = 'move'; var EVENT_END = GestureDetector.EVENT_END = 'end'; var EVENT_RELEASE = GestureDetector.EVENT_RELEASE = 'release'; var EVENT_TOUCH = GestureDetector.EVENT_TOUCH = 'touch'; /** * if the window events are set... * @property READY * @writeOnce * @type {Boolean} * @default false */ GestureDetector.READY = false; /** * plugins namespace * @property plugins * @type {Object} */ GestureDetector.plugins = GestureDetector.plugins || {}; /** * gestures namespace * see `/gestures` for the definitions * @property gestures * @type {Object} */ GestureDetector.gestures = GestureDetector.gestures || {}; /** * setup events to detect gestures on the document * this function is called when creating an new instance * @private */ function setup(opts) { if (GestureDetector.READY) { return; } // find what eventtypes we add listeners to Event$1.determineEventTypes(); // Register all gestures inside GestureDetector.gestures Utils.each(GestureDetector.gestures, function (gesture) { Detection.register(gesture); }); // Add touch events on the document Event$1.onTouch(GestureDetector.DOCUMENT, EVENT_MOVE, Detection.detect, opts); Event$1.onTouch(GestureDetector.DOCUMENT, EVENT_END, Detection.detect, opts); // GestureDetector is ready...! GestureDetector.READY = true; } /** * @module GestureDetector * * @class Utils * @static */ Utils = GestureDetector.utils = { /** * extend method, could also be used for cloning when `dest` is an empty object. * changes the dest object * @param {Object} dest * @param {Object} src * @param {Boolean} [merge=false] do a merge * @return {Object} dest */ extend: function extend(dest, src, merge) { for (var key in src) { if (src.hasOwnProperty(key) && (dest[key] === undefined || !merge)) { dest[key] = src[key]; } } return dest; }, /** * simple addEventListener wrapper * @param {HTMLElement} element * @param {String} type * @param {Function} handler */ on: function on(element, type, handler, opt) { util$1.addEventListener(element, type, handler, opt, true); }, /** * simple removeEventListener wrapper * @param {HTMLElement} element * @param {String} type * @param {Function} handler */ off: function off(element, type, handler, opt) { util$1.removeEventListener(element, type, handler, opt, true); }, /** * forEach over arrays and objects * @param {Object|Array} obj * @param {Function} iterator * @param {any} iterator.item * @param {Number} iterator.index * @param {Object|Array} iterator.obj the source object * @param {Object} context value to use as `this` in the iterator */ each: function each(obj, iterator, context) { var i, len; // native forEach on arrays if ('forEach' in obj) { obj.forEach(iterator, context); // arrays } else if (obj.length !== undefined) { for (i = 0, len = obj.length; i < len; i++) { if (iterator.call(context, obj[i], i, obj) === false) { return; } } // objects } else { for (i in obj) { if (obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj) === false) { return; } } } }, /** * find if a string contains the string using indexOf * @param {String} src * @param {String} find * @return {Boolean} found */ inStr: function inStr(src, find) { return src.indexOf(find) > -1; }, /** * find if a array contains the object using indexOf or a simple polyfill * @param {String} src * @param {String} find * @return {Boolean|Number} false when not found, or the index */ inArray: function inArray(src, find, deep) { if (deep) { for (var i = 0, len = src.length; i < len; i++) { // Array.findIndex if (Object.keys(find).every(function (key) { return src[i][key] === find[key]; })) { return i; } } return -1; } if (src.indexOf) { return src.indexOf(find); } else { for (var i = 0, len = src.length; i < len; i++) { if (src[i] === find) { return i; } } return -1; } }, /** * convert an array-like object (`arguments`, `touchlist`) to an array * @param {Object} obj * @return {Array} */ toArray: function toArray(obj) { return Array.prototype.slice.call(obj, 0); }, /** * find if a node is in the given parent * @param {HTMLElement} node * @param {HTMLElement} parent * @return {Boolean} found */ hasParent: function hasParent(node, parent) { while (node) { if (node == parent) { return true; } node = node.parentNode; } return false; }, /** * get the center of all the touches * @param {Array} touches * @return {Object} center contains `pageX`, `pageY`, `clientX` and `clientY` properties */ getCenter: function getCenter(touches) { var pageX = [], pageY = [], clientX = [], clientY = [], min = Math.min, max = Math.max; // no need to loop when only one touch if (touches.length === 1) { return { pageX: touches[0].pageX, pageY: touches[0].pageY, clientX: touches[0].clientX, clientY: touches[0].clientY }; } Utils.each(touches, function (touch) { pageX.push(touch.pageX); pageY.push(touch.pageY); clientX.push(touch.clientX); clientY.push(touch.clientY); }); return { pageX: (min.apply(Math, pageX) + max.apply(Math, pageX)) / 2, pageY: (min.apply(Math, pageY) + max.apply(Math, pageY)) / 2, clientX: (min.apply(Math, clientX) + max.apply(Math, clientX)) / 2, clientY: (min.apply(Math, clientY) + max.apply(Math, clientY)) / 2 }; }, /** * calculate the velocity between two points. unit is in px per ms. * @param {Number} deltaTime * @param {Number} deltaX * @param {Number} deltaY * @return {Object} velocity `x` and `y` */ getVelocity: function getVelocity(deltaTime, deltaX, deltaY) { return { x: Math.abs(deltaX / deltaTime) || 0, y: Math.abs(deltaY / deltaTime) || 0 }; }, /** * calculate the angle between two coordinates * @param {Touch} touch1 * @param {Touch} touch2 * @return {Number} angle */ getAngle: function getAngle(touch1, touch2) { var x = touch2.clientX - touch1.clientX, y = touch2.clientY - touch1.clientY; return Math.atan2(y, x) * 180 / Math.PI; }, /** * do a small comparison to get the direction between two touches. * @param {Touch} touch1 * @param {Touch} touch2 * @return {String} direction matches `DIRECTION_LEFT|RIGHT|UP|DOWN` */ getDirection: function getDirection(touch1, touch2) { var x = Math.abs(touch1.clientX - touch2.clientX), y = Math.abs(touch1.clientY - touch2.clientY); if (x >= y) { return touch1.clientX - touch2.clientX > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; } return touch1.clientY - touch2.clientY > 0 ? DIRECTION_UP : DIRECTION_DOWN; }, /** * calculate the distance between two touches * @param {Touch}touch1 * @param {Touch} touch2 * @return {Number} distance */ getDistance: function getDistance(touch1, touch2) { var x = touch2.clientX - touch1.clientX, y = touch2.clientY - touch1.clientY; return Math.sqrt(x * x + y * y); }, /** * calculate the scale factor between two touchLists * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out * @param {Array} start array of touches * @param {Array} end array of touches * @return {Number} scale */ getScale: function getScale(start, end) { // need two fingers... if (start.length >= 2 && end.length >= 2) { return this.getDistance(end[0], end[1]) / this.getDistance(start[0], start[1]); } return 1; }, /** * calculate the rotation degrees between two touchLists * @param {Array} start array of touches * @param {Array} end array of touches * @return {Number} rotation */ getRotation: function getRotation(start, end) { // need two fingers if (start.length >= 2 && end.length >= 2) { return this.getAngle(end[1], end[0]) - this.getAngle(start[1], start[0]); } return 0; }, /** * find out if the direction is vertical * * @param {String} direction matches `DIRECTION_UP|DOWN` * @return {Boolean} is_vertical */ isVertical: function isVertical(direction) { return direction == DIRECTION_UP || direction == DIRECTION_DOWN; }, /** * set css properties with their prefixes * @param {HTMLElement} element * @param {String} prop * @param {String} value * @param {Boolean} [toggle=true] * @return {Boolean} */ setPrefixedCss: function setPrefixedCss(element, prop, value, toggle) { var prefixes = ['', 'Webkit', 'Moz', 'O', 'ms']; prop = Utils.toCamelCase(prop); for (var i = 0; i < prefixes.length; i++) { var p = prop; // prefixes if (prefixes[i]) { p = prefixes[i] + p.slice(0, 1).toUpperCase() + p.slice(1); } // test the style if (p in element.style) { element.style[p] = (toggle === null || toggle) && value || ''; break; } } }, /** * toggle browser default behavior by setting css properties. * `userSelect='none'` also sets `element.onselectstart` to false * `userDrag='none'` also sets `element.ondragstart` to false * * @param {HtmlElement} element * @param {Object} props * @param {Boolean} [toggle=true] */ toggleBehavior: function toggleBehavior(element, props, toggle) { if (!props || !element || !element.style) { return; } // set the css properties Utils.each(props, function (value, prop) { Utils.setPrefixedCss(element, prop, value, toggle); }); var falseFn = toggle && function () { return false; }; // also the disable onselectstart if (props.userSelect == 'none') { element.onselectstart = falseFn; } // and disable ondragstart if (props.userDrag == 'none') { element.ondragstart = falseFn; } }, /** * convert a string with underscores to camelCase * so prevent_default becomes preventDefault * @param {String} str * @return {String} camelCaseStr */ toCamelCase: function toCamelCase(str) { return str.replace(/[_-]([a-z])/g, function (s) { return s[1].toUpperCase(); }); } }; /** * @module GestureDetector */ /** * @class Event * @static */ Event$1 = GestureDetector.event = { /** * when touch events have been fired, this is true * this is used to stop mouse events * @property prevent_mouseevents * @private * @type {Boolean} */ preventMouseEvents: false, /** * if EVENT_START has been fired * @property started * @private * @type {Boolean} */ started: false, /** * when the mouse is hold down, this is true * @property should_detect * @private * @type {Boolean} */ shouldDetect: false, /** * simple event binder with a hook and support for multiple types * @param {HTMLElement} element * @param {String} type * @param {Function} handler * @param {Object} [opt] * @param {Function} [hook] * @param {Object} hook.type */ on: function on(element, type, handler, opt, hook) { var types = type.split(' '); Utils.each(types, function (type) { Utils.on(element, type, handler, opt); hook && hook(type); }); }, /** * simple event unbinder with a hook and support for multiple types * @param {HTMLElement} element * @param {String} type * @param {Function} handler * @param {Object} [opt] * @param {Function} [hook] * @param {Object} hook.type */ off: function off(element, type, handler, opt, hook) { var types = type.split(' '); Utils.each(types, function (type) { Utils.off(element, type, handler, opt); hook && hook(type); }); }, /** * the core touch event handler. * this finds out if we should to detect gestures * @param {HTMLElement} element * @param {String} eventType matches `EVENT_START|MOVE|END` * @param {Function} handler * @return onTouchHandler {Function} the core event handler */ onTouch: function onTouch(element, eventType, handler, opt) { var self = this; var onTouchHandler = function onTouchHandler(ev) { var srcType = ev.type.toLowerCase(), isPointer = GestureDetector.HAS_POINTEREVENTS, isMouse = Utils.inStr(srcType, 'mouse'), triggerType; // if we are in a mouseevent, but there has been a touchevent triggered in this session // we want to do nothing. simply break out of the event. if (isMouse && self.preventMouseEvents) { return; // mousebutton must be down } else if (isMouse && eventType == EVENT_START && ev.button === 0) { self.preventMouseEvents = false; self.shouldDetect = true; } else if (isPointer && eventType == EVENT_START) { self.shouldDetect = ev.buttons === 1 || PointerEvent.matchType(POINTER_TOUCH, ev); // just a valid start event, but no mouse } else if (!isMouse && eventType == EVENT_START) { self.preventMouseEvents = true; self.shouldDetect = true; } // update the pointer event before entering the detection if (isPointer && eventType != EVENT_END) { PointerEvent.updatePointer(eventType, ev); } // we are in a touch/down state, so allowed detection of gestures if (self.shouldDetect) { triggerType = self.doDetect.call(self, ev, eventType, element, handler); } // ...and we are done with the detection // so reset everything to start each detection totally fresh if (triggerType == EVENT_END) { self.preventMouseEvents = false; self.shouldDetect = false; PointerEvent.reset(); // update the pointerevent object after the detection } if (isPointer && eventType == EVENT_END) { PointerEvent.updatePointer(eventType, ev); } }; this.on(element, EVENT_TYPES[eventType], onTouchHandler, opt); return onTouchHandler; }, /** * the core detection method * this finds out what GestureDetector-touch-events to trigger * @param {Object} ev * @param {String} eventType matches `EVENT_START|MOVE|END` * @param {HTMLElement} element * @param {Function} handler * @return {String} triggerType matches `EVENT_START|MOVE|END` */ doDetect: function doDetect(ev, eventType, element, handler) { var touchList = this.getTouchList(ev, eventType); var touchListLength = touchList.length; var triggerType = eventType; var triggerChange = touchList.trigger; // used by fakeMultitouch plugin var changedLength = touchListLength; // at each touchstart-like event we want also want to trigger a TOUCH event... if (eventType == EVENT_START) { triggerChange = EVENT_TOUCH; // ...the same for a touchend-like event } else if (eventType == EVENT_END) { triggerChange = EVENT_RELEASE; // keep track of how many touches have been removed changedLength = touchList.length - (ev.changedTouches ? ev.changedTouches.length : 1); } // after there are still touches on the screen, // we just want to trigger a MOVE event. so change the START or END to a MOVE // but only after detection has been started, the first time we actually want a START if (changedLength > 0 && this.started) { triggerType = EVENT_MOVE; } // detection has been started, we keep track of this, see above this.started = true; // generate some event data, some basic information var evData = this.collectEventData(element, triggerType, touchList, ev); // trigger the triggerType event before the change (TOUCH, RELEASE) events // but the END event should be at last if (eventType != EVENT_END) { handler.call(Detection, evData); } // trigger a change (TOUCH, RELEASE) event, this means the length of the touches changed if (triggerChange) { evData.changedLength = changedLength; evData.eventType = triggerChange; handler.call(Detection, evData); evData.eventType = triggerType; delete evData.changedLength; } // trigger the END event if (triggerType == EVENT_END) { handler.call(Detection, evData); // ...and we are done with the detection // so reset everything to start each detection totally fresh this.started = false; } return triggerType; }, /** * we have different events for each device/browser * determine what we need and set them in the EVENT_TYPES constant * the `onTouch` method is bind to these properties. * @return {Object} events */ determineEventTypes: function determineEventTypes() { var types; if (GestureDetector.HAS_POINTEREVENTS) { if (window.PointerEvent) { types = ['pointerdown', 'pointermove', 'pointerup pointercancel lostpointercapture']; } else { types = ['MSPointerDown', 'MSPointerMove', 'MSPointerUp MSPointerCancel MSLostPointerCapture']; } } else if (GestureDetector.NO_MOUSEEVENTS) { types = ['touchstart', 'touchmove', 'touchend touchcancel']; } else { types = ['touchstart mousedown', 'touchmove mousemove', 'touchend touchcancel mouseup']; } EVENT_TYPES[EVENT_START] = types[0]; EVENT_TYPES[EVENT_MOVE] = types[1]; EVENT_TYPES[EVENT_END] = types[2]; return EVENT_TYPES; }, /** * create touchList depending on the event * @param {Object} ev * @param {String} eventType * @return {Array} touches */ getTouchList: function getTouchList(ev, eventType) { // get the fake pointerEvent touchlist if (GestureDetector.HAS_POINTEREVENTS) { return PointerEvent.getTouchList(); } // get the touchlist if (ev.touches) { if (eventType == EVENT_MOVE) { return ev.touches; } var identifiers = []; var concat = [].concat(Utils.toArray(ev.touches), Utils.toArray(ev.changedTouches)); var touchList = []; Utils.each(concat, function (touch) { if (Utils.inArray(identifiers, touch.identifier) === -1) { touchList.push(touch); } identifiers.push(touch.identifier); }); return touchList; } // make fake touchList from mouse position ev.identifier = 1; return [ev]; }, /** * collect basic event data * @param {HTMLElement} element * @param {String} eventType matches `EVENT_START|MOVE|END` * @param {Array} touches * @param {Object} ev * @return {Object} ev */ collectEventData: function collectEventData(element, eventType, touches, ev) { // find out pointerType var pointerType = POINTER_TOUCH; if (Utils.inStr(ev.type, 'mouse') || PointerEvent.matchType(POINTER_MOUSE, ev)) { pointerType = POINTER_MOUSE; } else if (PointerEvent.matchType(POINTER_PEN, ev)) { pointerType = POINTER_PEN; } return { center: Utils.getCenter(touches), timeStamp: Date.now(), target: ev.target, touches: touches, eventType: eventType, pointerType: pointerType, srcEvent: ev, /** * prevent the browser default actions * mostly used to disable scrolling of the browser */ preventDefault: function preventDefault() { var srcEvent = this.srcEvent; srcEvent.preventManipulation && srcEvent.preventManipulation(); srcEvent.preventDefault && srcEvent.preventDefault(); }, /** * stop bubbling the event up to its parents */ stopPropagation: function stopPropagation() { this.srcEvent.stopPropagation(); }, /** * immediately stop gesture detection * might be useful after a swipe was detected * @return {*} */ stopDetect: function stopDetect() { return Detection.stopDetect(); } }; } }; /** * @module GestureDetector * * @class PointerEvent * @static */ PointerEvent = GestureDetector.PointerEvent = { /** * holds all pointers, by `identifier` * @property pointers * @type {Object} */ pointers: {}, /** * get the pointers as an array * @return {Array} touchlist */ getTouchList: function getTouchList() { var touchlist = []; // we can use forEach since pointerEvents only is in IE10 Utils.each(this.pointers, function (pointer) { touchlist.push(pointer); }); return touchlist; }, /** * update the position of a pointer * @param {String} eventType matches `EVENT_START|MOVE|END` * @param {Object} pointerEvent */ updatePointer: function updatePointer(eventType, pointerEvent) { if (eventType == EVENT_END || eventType != EVENT_END && pointerEvent.buttons !== 1) { delete this.pointers[pointerEvent.pointerId]; } else { pointerEvent.identifier = pointerEvent.pointerId; this.pointers[pointerEvent.pointerId] = pointerEvent; } }, /** * check if ev matches pointertype * @param {String} pointerType matches `POINTER_MOUSE|TOUCH|PEN` * @param {PointerEvent} ev */ matchType: function matchType(pointerType, ev) { if (!ev.pointerType) { return false; } var pt = ev.pointerType, types = {}; types[POINTER_MOUSE] = pt === (ev.MSPOINTER_TYPE_MOUSE || POINTER_MOUSE); types[POINTER_TOUCH] = pt === (ev.MSPOINTER_TYPE_TOUCH || POINTER_TOUCH); types[POINTER_PEN] = pt === (ev.MSPOINTER_TYPE_PEN || POINTER_PEN); return types[pointerType]; }, /** * reset the stored pointers */ reset: function resetList() { this.pointers = {}; } }; /** * @module GestureDetector * * @class Detection * @static */ Detection = GestureDetector.detection = { // contains all registered GestureDetector.gestures in the correct order gestures: [], // data of the current GestureDetector.gesture detection session current: null, // the previous GestureDetector.gesture session data // is a full clone of the previous gesture.current object previous: null, // when this becomes true, no gestures are fired stopped: false, /** * start GestureDetector.gesture detection * @param {GestureDetector.Instance} inst * @param {Object} eventData */ startDetect: function startDetect(inst, eventData) { // already busy with a GestureDetector.gesture detection on an element if (this.current) { return; } this.stopped = false; // holds current session this.current = { inst: inst, // reference to GestureDetectorInstance we're working for startEvent: Utils.extend({}, eventData), // start eventData for distances, timing etc lastEvent: false, // last eventData lastCalcEvent: false, // last eventData for calculations. futureCalcEvent: false, // last eventData for calculations. lastCalcData: {}, // last lastCalcData name: '' // current gesture we're in/detected, can be 'tap', 'hold' etc }; this.detect(eventData); }, /** * GestureDetector.gesture detection * @param {Object} eventData * @return {any} */ detect: function detect(eventData) { if (!this.current || this.stopped) { return; } // extend event data with calculations about scale, distance etc eventData = this.extendEventData(eventData); // GestureDetector instance and instance options var inst = this.current.inst, instOptions = inst.options; // call GestureDetector.gesture handlers Utils.each(this.gestures, function triggerGesture(gesture) { // only when the instance options have enabled this gesture if (!this.stopped && inst.enabled && instOptions[gesture.name]) { gesture.handler.call(gesture, eventData, inst); } }, this); // store as previous event event if (this.current) { this.current.lastEvent = eventData; } if (eventData.eventType == EVENT_END) { this.stopDetect(); } return eventData; // eslint-disable-line consistent-return }, /** * clear the GestureDetector.gesture vars * this is called on endDetect, but can also be used when a final GestureDetector.gesture has been detected * to stop other GestureDetector.gestures from being fired */ stopDetect: function stopDetect() { // clone current data to the store as the previous gesture // used for the double tap gesture, since this is an other gesture detect session this.previous = Utils.extend({}, this.current); // reset the current this.current = null; this.stopped = true; }, /** * calculate velocity, angle and direction * @param {Object} ev * @param {Object} center * @param {Number} deltaTime * @param {Number} deltaX * @param {Number} deltaY */ getCalculatedData: function getCalculatedData(ev, center, deltaTime, deltaX, deltaY) { var cur = this.current, recalc = false, calcEv = cur.lastCalcEvent, calcData = cur.lastCalcData; if (calcEv && ev.timeStamp - calcEv.timeStamp > GestureDetector.CALCULATE_INTERVAL) { center = calcEv.center; deltaTime = ev.timeStamp - calcEv.timeStamp; deltaX = ev.center.clientX - calcEv.center.clientX; deltaY = ev.center.clientY - calcEv.center.clientY; recalc = true; } if (ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) { cur.futureCalcEvent = ev; } if (!cur.lastCalcEvent || recalc) { calcData.velocity = Utils.getVelocity(deltaTime, deltaX, deltaY); calcData.angle = Utils.getAngle(center, ev.center); calcData.direction = Utils.getDirection(center, ev.center); cur.lastCalcEvent = cur.futureCalcEvent || ev; cur.futureCalcEvent = ev; } ev.velocityX = calcData.velocity.x; ev.velocityY = calcData.velocity.y; ev.interimAngle = calcData.angle; ev.interimDirection = calcData.direction; }, /** * extend eventData for GestureDetector.gestures * @param {Object} ev * @return {Object} ev */ extendEventData: function extendEventData(ev) { var cur = this.current, startEv = cur.startEvent, lastEv = cur.lastEvent || startEv; // update the start touchlist to calculate the scale/rotation if (ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) { startEv.touches = []; Utils.each(ev.touches, function (touch) { startEv.touches.push({ clientX: touch.clientX, clientY: touch.clientY }); }); } var deltaTime = ev.timeStamp - startEv.timeStamp, deltaX = ev.center.clientX - startEv.center.clientX, deltaY = ev.center.clientY - startEv.center.clientY; this.getCalculatedData(ev, lastEv.center, deltaTime, deltaX, deltaY); Utils.extend(ev, { startEvent: startEv, deltaTime: deltaTime, deltaX: deltaX, deltaY: deltaY, distance: Utils.getDistance(startEv.center, ev.center), angle: Utils.getAngle(startEv.center, ev.center), direction: Utils.getDirection(startEv.center, ev.center), scale: Utils.getScale(startEv.touches, ev.touches), rotation: Utils.getRotation(startEv.touches, ev.touches) }); return ev; }, /** * register new gesture * @param {Object} gesture object, see `gestures/` for documentation * @return {Array} gestures */ register: function register(gesture) { // add an enable gesture options if there is no given var options = gesture.defaults || {}; if (options[gesture.name] === undefined) { options[gesture.name] = true; } // extend GestureDetector default options with the GestureDetector.gesture options Utils.extend(GestureDetector.defaults, options, true); // set its index gesture.index = gesture.index || 1000; // add GestureDetector.gesture to the list this.gestures.push(gesture); // sort the list by index this.gestures.sort(function (a, b) { if (a.index < b.index) { return -1; } if (a.index > b.index) { return 1; } return 0; }); return this.gestures; } }; /** * @module GestureDetector */ /** * create new GestureDetector instance * all methods should return the instance itself, so it is chainable. * * @class Instance * @constructor * @param {HTMLElement} element * @param {Object} [options={}] options are merged with `GestureDetector.defaults` * @return {GestureDetector.Instance} */ GestureDetector.Instance = function (element, options) { var self = this; var listenerOptions = options && options.passive ? { passive: true } : undefined; // setup GestureDetectorJS window events and register all gestures // this also sets up the default options setup(listenerOptions); /** * @property element * @type {HTMLElement} */ this.element = element; /** * @property enabled * @type {Boolean} * @protected */ this.enabled = true; /** * options, merged with the defaults * options with an _ are converted to camelCase * @property options * @type {Object} */ Utils.each(options, function (value, name) { delete options[name]; options[Utils.toCamelCase(name)] = value; }); this.options = Utils.extend(Utils.extend({}, GestureDetector.defaults), options || {}); this.options.listenerOptions = listenerOptions; // add some css to the element to prevent the browser from doing its native behavior if (this.options.behavior) { Utils.toggleBehavior(this.element, this.options.behavior, true); } /** * event start handler on the element to start the detection * @property eventStartHandler * @type {Object} */ this.eventStartHandler = Event$1.onTouch(element, EVENT_START, function (ev) { if (self.enabled && ev.eventType == EVENT_START) { Detection.startDetect(self, ev); } else if (ev.eventType == EVENT_TOUCH) { Detection.detect(ev); } }, listenerOptions); /** * keep a list of user event handlers which needs to be removed when calling 'dispose' * @property eventHandlers * @type {Array} */ this.eventHandlers = []; }; GestureDetector.Instance.prototype = { /** * @method on * @signature on(gestures, handler) * @description * [en]Adds an event handler for a gesture. Available gestures are: drag, dragleft, dragright, dragup, dragdown, hold, release, swipe, swipeleft, swiperight, swipeup, swipedown, tap, doubletap, touch, transform, pinch, pinchin, pinchout and rotate. [/en] * [ja]ジェスチャに対するイベントハンドラを追加します。指定できるジェスチャ名は、drag dragleft dragright dragup dragdown hold release swipe swipeleft swiperight swipeup swipedown tap doubletap touch transform pinch pinchin pinchout rotate です。[/ja] * @param {String} gestures * [en]A space separated list of gestures.[/en] * [ja]検知するジェスチャ名を指定します。スペースで複数指定することができます。[/ja] * @param {Function} handler * [en]An event handling function.[/en] * [ja]イベントハンドラとなる関数オブジェクトを指定します。[/ja] */ on: function onEvent(gestures, handler, opt) { var self = this; Event$1.on(self.element, gestures, handler, util$1.extend({}, self.options.listenerOptions, opt), function (type) { self.eventHandlers.push({ gesture: type, handler: handler }); }); return self; }, /** * @method off * @signature off(gestures, handler) * @description * [en]Remove an event listener.[/en] * [ja]イベントリスナーを削除します。[/ja] * @param {String} gestures * [en]A space separated list of gestures.[/en] * [ja]ジェスチャ名を指定します。スペースで複数指定することができます。[/ja] * @param {Function} handler * [en]An event handling function.[/en] * [ja]イベントハンドラとなる関数オブジェクトを指定します。[/ja] */ off: function offEvent(gestures, handler, opt) { var self = this; Event$1.off(self.element, gestures, handler, util$1.extend({}, self.options.listenerOptions, opt), function (type) { var index = Utils.inArray(self.eventHandlers, { gesture: type, handler: handler }, true); if (index >= 0) { self.eventHandlers.splice(index, 1); } }); return self; }, /** * trigger gesture event * @method trigger * @signature trigger(gesture, eventData) * @param {String} gesture * @param {Object} [eventData] */ trigger: function triggerEvent(gesture, eventData) { // optional if (!eventData) { eventData = {}; } // create DOM event var event = GestureDetector.DOCUMENT.createEvent('Event'); event.initEvent(gesture, true, true); event.gesture = eventData; // trigger on the target if it is in the instance element, // this is for event delegation tricks var element = this.element; if (Utils.hasParent(eventData.target, element)) { element = eventData.target; } element.dispatchEvent(event); return this; }, /** * @method enable * @signature enable(state) * @description * [en]Enable or disable gesture detection.[/en] * [ja]ジェスチャ検知を有効化/無効化します。[/ja] * @param {Boolean} state * [en]Specify if it should be enabled or not.[/en] * [ja]有効にするかどうかを指定します。[/ja] */ enable: function enable(state) { this.enabled = state; return this; }, /** * @method dispose * @signature dispose() * @description * [en]Remove and destroy all event handlers for this instance.[/en] * [ja]このインスタンスでのジェスチャの検知や、イベントハンドラを全て解除して廃棄します。[/ja] */ dispose: function dispose() { var i, eh; // undo all changes made by stop_browser_behavior Utils.toggleBehavior(this.element, this.options.behavior, false); // unbind all custom event handlers for (i = -1; eh = this.eventHandlers[++i];) { // eslint-disable-line no-cond-assign Utils.off(this.element, eh.gesture, eh.handler); } this.eventHandlers = []; // unbind the start event listener Event$1.off(this.element, EVENT_TYPES[EVENT_START], this.eventStartHandler); return null; } }; /** * @module gestures */ /** * Move with x fingers (default 1) around on the page. * Preventing the default browser behavior is a good way to improve feel and working. * ```` * GestureDetectortime.on("drag", function(ev) { * console.log(ev); * ev.gesture.preventDefault(); * }); * ```` * * @class Drag * @static */ /** * @event drag * @param {Object} ev */ /** * @event dragstart * @param {Object} ev */ /** * @event dragend * @param {Object} ev */ /** * @event drapleft * @param {Object} ev */ /** * @event dragright * @param {Object} ev */ /** * @event dragup * @param {Object} ev */ /** * @event dragdown * @param {Object} ev */ /** * @param {String} name */ (function (name) { var triggered = false; function dragGesture(ev, inst) { var cur = Detection.current; // max touches if (inst.options.dragMaxTouches > 0 && ev.touches.length > inst.options.dragMaxTouches) { return; } switch (ev.eventType) { case EVENT_START: triggered = false; break; case EVENT_MOVE: // when the distance we moved is too small we skip this gesture // or we can be already in dragging if (ev.distance < inst.options.dragMinDistance && cur.name != name) { return; } var startCenter = cur.startEvent.center; // we are dragging! if (cur.name != name) { cur.name = name; if (inst.options.dragDistanceCorrection && ev.distance > 0) { // When a drag is triggered, set the event center to dragMinDistance pixels from the original event center. // Without this correction, the dragged distance would jumpstart at dragMinDistance pixels instead of at 0. // It might be useful to save the original start point somewhere var factor = Math.abs(inst.options.dragMinDistance / ev.distance); startCenter.pageX += ev.deltaX * factor; startCenter.pageY += ev.deltaY * factor; startCenter.clientX += ev.deltaX * factor; startCenter.clientY += ev.deltaY * factor; // recalculate event data using new start point ev = Detection.extendEventData(ev); } } // lock drag to axis? if (cur.lastEvent.dragLockToAxis || inst.options.dragLockToAxis && inst.options.dragLockMinDistance <= ev.distance) { ev.dragLockToAxis = true; } // keep direction on the axis that the drag gesture started on var lastDirection = cur.lastEvent.direction; if (ev.dragLockToAxis && lastDirection !== ev.direction) { if (Utils.isVertical(lastDirection)) { ev.direction = ev.deltaY < 0 ? DIRECTION_UP : DIRECTION_DOWN; } else { ev.direction = ev.deltaX < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; } } // first time, trigger dragstart event if (!triggered) { inst.trigger(name + 'start', ev); triggered = true; } // trigger events inst.trigger(name, ev); inst.trigger(name + ev.direction, ev); var isVertical = Utils.isVertical(ev.direction); // block the browser events if (inst.options.dragBlockVertical && isVertical || inst.options.dragBlockHorizontal && !isVertical) { ev.preventDefault(); } break; case EVENT_RELEASE: if (triggered && ev.changedLength <= inst.options.dragMaxTouches) { inst.trigger(name + 'end', ev); triggered = false; } break; case EVENT_END: triggered = false; break; } } GestureDetector.gestures.Drag = { name: name, index: 50, handler: dragGesture, defaults: { /** * minimal movement that have to be made before the drag event gets triggered * @property dragMinDistance * @type {Number} * @default 10 */ dragMinDistance: 10, /** * Set dragDistanceCorrection to true to make the starting point of the drag * be calculated from where the drag was triggered, not from where the touch started. * Useful to avoid a jerk-starting drag, which can make fine-adjustments * through dragging difficult, and be visually unappealing. * @property dragDistanceCorrection * @type {Boolean} * @default true */ dragDistanceCorrection: true, /** * set 0 for unlimited, but this can conflict with transform * @property dragMaxTouches * @type {Number} * @default 1 */ dragMaxTouches: 1, /** * prevent default browser behavior when dragging occurs * be careful with it, it makes the element a blocking element * when you are using the drag gesture, it is a good practice to set this true * @property dragBlockHorizontal * @type {Boolean} * @default false */ dragBlockHorizontal: false, /** * same as `dragBlockHorizontal`, but for vertical movement * @property dragBlockVertical * @type {Boolean} * @default false */ dragBlockVertical: false, /** * dragLockToAxis keeps the drag gesture on the axis that it started on, * It disallows vertical directions if the initial direction was horizontal, and vice versa. * @property dragLockToAxis * @type {Boolean} * @default false */ dragLockToAxis: false, /** * drag lock only kicks in when distance > dragLockMinDistance * This way, locking occurs only when the distance has become large enough to reliably determine the direction * @property dragLockMinDistance * @type {Number} * @default 25 */ dragLockMinDistance: 25 } }; })('drag'); /** * @module gestures */ /** * trigger a simple gesture event, so you can do anything in your handler. * only usable if you know what your doing... * * @class Gesture * @static */ /** * @event gesture * @param {Object} ev */ GestureDetector.gestures.Gesture = { name: 'gesture', index: 1337, handler: function releaseGesture(ev, inst) { inst.trigger(this.name, ev); } }; /** * @module gestures */ /** * Touch stays at the same place for x time * * @class Hold * @static */ /** * @event hold * @param {Object} ev */ /** * @param {String} name */ (function (name) { var timer; function holdGesture(ev, inst) { var options = inst.options, current = Detection.current; switch (ev.eventType) { case EVENT_START: clearTimeout(timer); // set the gesture so we can check in the timeout if it still is current.name = name; // set timer and if after the timeout it still is hold, // we trigger the hold event timer = setTimeout(function () { if (current && current.name == name) { inst.trigger(name, ev); } }, options.holdTimeout); break; case EVENT_MOVE: if (ev.distance > options.holdThreshold) { clearTimeout(timer); } break; case EVENT_RELEASE: clearTimeout(timer); break; } } GestureDetector.gestures.Hold = { name: name, index: 10, defaults: { /** * @property holdTimeout * @type {Number} * @default 500 */ holdTimeout: 500, /** * movement allowed while holding * @property holdThreshold * @type {Number} * @default 2 */ holdThreshold: 2 }, handler: holdGesture }; })('hold'); /** * @module gestures */ /** * when a touch is being released from the page * * @class Release * @static */ /** * @event release * @param {Object} ev */ GestureDetector.gestures.Release = { name: 'release', index: Infinity, handler: function releaseGesture(ev, inst) { if (ev.eventType == EVENT_RELEASE) { inst.trigger(this.name, ev); } } }; /** * @module gestures */ /** * triggers swipe events when the end velocity is above the threshold * for best usage, set `preventDefault` (on the drag gesture) to `true` * ```` * GestureDetectortime.on("dragleft swipeleft", function(ev) { * console.log(ev); * ev.gesture.preventDefault(); * }); * ```` * * @class Swipe * @static */ /** * @event swipe * @param {Object} ev */ /** * @event swipeleft * @param {Object} ev */ /** * @event swiperight * @param {Object} ev */ /** * @event swipeup * @param {Object} ev */ /** * @event swipedown * @param {Object} ev */ GestureDetector.gestures.Swipe = { name: 'swipe', index: 40, defaults: { /** * @property swipeMinTouches * @type {Number} * @default 1 */ swipeMinTouches: 1, /** * @property swipeMaxTouches * @type {Number} * @default 1 */ swipeMaxTouches: 1, /** * horizontal swipe velocity * @property swipeVelocityX * @type {Number} * @default 0.6 */ swipeVelocityX: 0.6, /** * vertical swipe velocity * @property swipeVelocityY * @type {Number} * @default 0.6 */ swipeVelocityY: 0.6 }, handler: function swipeGesture(ev, inst) { if (ev.eventType == EVENT_RELEASE) { var touches = ev.touches.length, options = inst.options; // max touches if (touches < options.swipeMinTouches || touches > options.swipeMaxTouches) { return; } // when the distance we moved is too small we skip this gesture // or we can be already in dragging if (ev.velocityX > options.swipeVelocityX || ev.velocityY > options.swipeVelocityY) { // trigger swipe events inst.trigger(this.name, ev); inst.trigger(this.name + ev.direction, ev); } } } }; /** * @module gestures */ /** * Single tap and a double tap on a place * * @class Tap * @static */ /** * @event tap * @param {Object} ev */ /** * @event doubletap * @param {Object} ev */ /** * @param {String} name */ (function (name) { var hasMoved = false; function tapGesture(ev, inst) { var options = inst.options, current = Detection.current, prev = Detection.previous, sincePrev, didDoubleTap; switch (ev.eventType) { case EVENT_START: hasMoved = false; break; case EVENT_MOVE: hasMoved = hasMoved || ev.distance > options.tapMaxDistance; break; case EVENT_END: if (!Utils.inStr(ev.srcEvent.type, 'cancel') && ev.deltaTime < options.tapMaxTime && !hasMoved) { // previous gesture, for the double tap since these are two different gesture detections sincePrev = prev && prev.lastEvent && ev.timeStamp - prev.lastEvent.timeStamp; didDoubleTap = false; // check if double tap if (prev && prev.name == name && sincePrev && sincePrev < options.doubleTapInterval && ev.distance < options.doubleTapDistance) { inst.trigger('doubletap', ev); didDoubleTap = true; } // do a single tap if (!didDoubleTap || options.tapAlways) { current.name = name; inst.trigger(current.name, ev); } } break; } } GestureDetector.gestures.Tap = { name: name, index: 100, handler: tapGesture, defaults: { /** * max time of a tap, this is for the slow tappers * @property tapMaxTime * @type {Number} * @default 250 */ tapMaxTime: 250, /** * max distance of movement of a tap, this is for the slow tappers * @property tapMaxDistance * @type {Number} * @default 10 */ tapMaxDistance: 10, /** * always trigger the `tap` event, even while double-tapping * @property tapAlways * @type {Boolean} * @default true */ tapAlways: true, /** * max distance between two taps * @property doubleTapDistance * @type {Number} * @default 20 */ doubleTapDistance: 20, /** * max time between two taps * @property doubleTapInterval * @type {Number} * @default 300 */ doubleTapInterval: 300 } }; })('tap'); /** * @module gestures */ /** * when a touch is being touched at the page * * @class Touch * @static */ /** * @event touch * @param {Object} ev */ GestureDetector.gestures.Touch = { name: 'touch', index: -Infinity, defaults: { /** * call preventDefault at touchstart, and makes the element blocking by disabling the scrolling of the page, * but it improves gestures like transforming and dragging. * be careful with using this, it can be very annoying for users to be stuck on the page * @property preventDefault * @type {Boolean} * @default false */ preventDefault: false, /** * disable mouse events, so only touch (or pen!) input triggers events * @property preventMouse * @type {Boolean} * @default false */ preventMouse: false }, handler: function touchGesture(ev, inst) { if (inst.options.preventMouse && ev.pointerType == POINTER_MOUSE) { ev.stopDetect(); return; } if (inst.options.preventDefault) { ev.preventDefault(); } if (ev.eventType == EVENT_TOUCH) { inst.trigger('touch', ev); } } }; /** * @module gestures */ /** * User want to scale or rotate with 2 fingers * Preventing the default browser behavior is a good way to improve feel and working. This can be done with the * `preventDefault` option. * * @class Transform * @static */ /** * @event transform * @param {Object} ev */ /** * @event transformstart * @param {Object} ev */ /** * @event transformend * @param {Object} ev */ /** * @event pinchin * @param {Object} ev */ /** * @event pinchout * @param {Object} ev */ /** * @event rotate * @param {Object} ev */ /** * @param {String} name */ (function (name) { var triggered = false; function transformGesture(ev, inst) { switch (ev.eventType) { case EVENT_START: triggered = false; break; case EVENT_MOVE: // at least multitouch if (ev.touches.length < 2) { return; } var scaleThreshold = Math.abs(1 - ev.scale); var rotationThreshold = Math.abs(ev.rotation); // when the distance we moved is too small we skip this gesture // or we can be already in dragging if (scaleThreshold < inst.options.transformMinScale && rotationThreshold < inst.options.transformMinRotation) { return; } // we are transforming! Detection.current.name = name; // first time, trigger dragstart event if (!triggered) { inst.trigger(name + 'start', ev); triggered = true; } inst.trigger(name, ev); // basic transform event // trigger rotate event if (rotationThreshold > inst.options.transformMinRotation) { inst.trigger('rotate', ev); } // trigger pinch event if (scaleThreshold > inst.options.transformMinScale) { inst.trigger('pinch', ev); inst.trigger('pinch' + (ev.scale < 1 ? 'in' : 'out'), ev); } break; case EVENT_RELEASE: if (triggered && ev.changedLength < 2) { inst.trigger(name + 'end', ev); triggered = false; } break; } } GestureDetector.gestures.Transform = { name: name, index: 45, defaults: { /** * minimal scale factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1 * @property transformMinScale * @type {Number} * @default 0.01 */ transformMinScale: 0.01, /** * rotation in degrees * @property transformMinRotation * @type {Number} * @default 1 */ transformMinRotation: 1 }, handler: transformGesture }; })('transform'); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var readyMap = void 0; var queueMap = void 0; function isContentReady(element) { if (element.childNodes.length > 0) { setContentReady(element); } return readyMap.has(element); } function setContentReady(element) { readyMap.set(element, true); } function addCallback(element, fn) { if (!queueMap.has(element)) { queueMap.set(element, []); } queueMap.get(element).push(fn); } function consumeQueue(element) { var callbacks = queueMap.get(element, []) || []; queueMap.delete(element); callbacks.forEach(function (callback) { return callback(); }); } function contentReady(element) { var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : function () {}; if (readyMap === undefined) { readyMap = new WeakMap(); queueMap = new WeakMap(); } addCallback(element, fn); if (isContentReady(element)) { consumeQueue(element); return; } var observer = new MutationObserver(function (changes) { setContentReady(element); consumeQueue(element); }); observer.observe(element, { childList: true, characterData: true }); // failback for elements has empty content. setImmediate(function () { setContentReady(element); consumeQueue(element); }); } /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var ToastQueue = function () { function ToastQueue() { classCallCheck(this, ToastQueue); this.queue = []; } createClass(ToastQueue, [{ key: "add", value: function add(fn, promise) { var _this = this; this.queue.push(fn); if (this.queue.length === 1) { setImmediate(this.queue[0]); } promise.then(function () { _this.queue.shift(); if (_this.queue.length > 0) { setTimeout(_this.queue[0], 1000 / 30); // Apply some visual delay } }); } }]); return ToastQueue; }(); var ToastQueue$1 = new ToastQueue(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var _setAttributes = function _setAttributes(element, options) { ['id', 'class', 'animation'].forEach(function (a) { return options.hasOwnProperty(a) && element.setAttribute(a, options[a]); }); if (options.modifier) { util$1.addModifier(element, options.modifier); } }; var _normalizeArguments = function _normalizeArguments(message) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var defaults$$1 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; options = _extends({}, options); typeof message === 'string' ? options.message = message : options = message; if (!options || !options.message && !options.messageHTML) { util$1.throw('Notifications must contain a message'); } if (options.hasOwnProperty('buttonLabels') || options.hasOwnProperty('buttonLabel')) { options.buttonLabels = options.buttonLabels || options.buttonLabel; if (!Array.isArray(options.buttonLabels)) { options.buttonLabels = [options.buttonLabels || '']; } } return util$1.extend({ compile: function compile(param) { return param; }, callback: function callback(param) { return param; }, animation: 'default', cancelable: false, primaryButtonIndex: (options.buttonLabels || defaults$$1.buttonLabels || []).length - 1 }, defaults$$1, options); }; /** * @object ons.notification * @category dialog * @tutorial vanilla/Reference/notification * @description * [en] * Utility methods to create different kinds of notifications. There are three methods available: * * * `ons.notification.alert()` * * `ons.notification.confirm()` * * `ons.notification.prompt()` * * `ons.notification.toast()` * * It will automatically display a Material Design dialog on Android devices. * [/en] * [ja]いくつかの種類のアラートダイアログを作成するためのユーティリティメソッドを収めたオブジェクトです。[/ja] * @example * ons.notification.alert('Hello, world!'); * * ons.notification.confirm('Are you ready?') * .then( * function(answer) { * if (answer === 1) { * ons.notification.alert('Let\'s go!'); * } * } * ); * * ons.notification.prompt('How old are ?') * .then( * function(age) { * ons.notification.alert('You are ' + age + ' years old.'); * } * ); */ var notification = {}; notification._createAlertDialog = function () { for (var _len = arguments.length, params = Array(_len), _key = 0; _key < _len; _key++) { params[_key] = arguments[_key]; } return new Promise(function (resolve) { var options = _normalizeArguments.apply(undefined, params); util$1.checkMissingImport('AlertDialog', 'AlertDialogButton'); // Prompt input string var inputString = ''; if (options.isPrompt) { inputString = '\n \n '; } // Buttons string var buttons = ''; options.buttonLabels.forEach(function (label, index) { buttons += '\n \n ' + label + '\n \n '; }); // Dialog Element var el = {}; var _destroyDialog = function _destroyDialog() { if (el.dialog.onDialogCancel) { el.dialog.removeEventListener('dialog-cancel', el.dialog.onDialogCancel); } Object.keys(el).forEach(function (key) { return delete el[key]; }); el = null; if (options.destroy instanceof Function) { options.destroy(); } }; el.dialog = document.createElement('ons-alert-dialog'); el.dialog.innerHTML = '\n
\n
\n
\n
\n ' + (options.title || '') + '\n
\n
\n ' + (options.message || options.messageHTML) + '\n ' + inputString + '\n
\n \n
\n
\n '; contentReady(el.dialog); // Set attributes _setAttributes(el.dialog, options); // Prompt events if (options.isPrompt && options.submitOnEnter) { el.input = el.dialog.querySelector('.text-input'); el.input.onkeypress = function (event) { if (event.keyCode === 13) { el.dialog.hide().then(function () { if (el) { var resolveValue = el.input.value; _destroyDialog(); options.callback(resolveValue); resolve(resolveValue); } }); } }; } // Button events el.footer = el.dialog.querySelector('.alert-dialog-footer'); util$1.arrayFrom(el.dialog.querySelectorAll('.alert-dialog-button')).forEach(function (buttonElement, index) { buttonElement.onclick = function () { el.dialog.hide().then(function () { if (el) { var resolveValue = index; if (options.isPrompt) { resolveValue = index === options.primaryButtonIndex ? el.input.value : null; } el.dialog.remove(); _destroyDialog(); options.callback(resolveValue); resolve(resolveValue); } }); }; el.footer.appendChild(buttonElement); }); // Cancel events if (options.cancelable) { el.dialog.cancelable = true; el.dialog.onDialogCancel = function () { setImmediate(function () { el.dialog.remove(); _destroyDialog(); }); var resolveValue = options.isPrompt ? null : -1; options.callback(resolveValue); resolve(resolveValue); }; el.dialog.addEventListener('dialog-cancel', el.dialog.onDialogCancel, false); } // Show dialog document.body.appendChild(el.dialog); options.compile(el.dialog); setImmediate(function () { el.dialog.show().then(function () { if (el.input && options.isPrompt && options.autofocus) { var strLength = el.input.value.length; el.input.focus(); el.input.setSelectionRange(strLength, strLength); } }); }); }); }; /** * @method alert * @signature alert(message [, options] | options) * @return {Promise} * [en]Will resolve to the index of the button that was pressed or `-1` when canceled.[/en] * [ja][/ja] * @param {String} message * [en]Notification message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en] * [ja][/ja] * @param {Object} options * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクトです。[/ja] * @param {String} [options.message] * [en]Notification message.[/en] * [ja]アラートダイアログに表示する文字列を指定します。[/ja] * @param {String} [options.messageHTML] * [en]Notification message in HTML.[/en] * [ja]アラートダイアログに表示するHTMLを指定します。[/ja] * @param {String | Array} [options.buttonLabels] * [en]Labels for the buttons. Default is `"OK"`.[/en] * [ja]確認ボタンのラベルを指定します。"OK"がデフォルトです。[/ja] * @param {Number} [options.primaryButtonIndex] * [en]Index of primary button. Default is the last one.[/en] * [ja]プライマリボタンのインデックスを指定します。デフォルトは 0 です。[/ja] * @param {Boolean} [options.cancelable] * [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] * [ja]ダイアログがキャンセル可能かどうかを指定します。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `none` and `fade`. Default is `fade`.[/en] * [ja]アラートダイアログを表示する際のアニメーション名を指定します。"none", "fade"のいずれかを指定できます。[/ja] * @param {String} [options.id] * [en]The `` element's ID.[/en] * [ja]ons-alert-dialog要素のID。[/ja] * @param {String} [options.class] * [en]The `` element's class.[/en] * [ja]ons-alert-dialog要素のclass。[/ja] * @param {String} [options.title] * [en]Dialog title. Default is `"Alert"`.[/en] * [ja]アラートダイアログの上部に表示するタイトルを指定します。"Alert"がデフォルトです。[/ja] * @param {String} [options.modifier] * [en]Modifier for the dialog.[/en] * [ja]アラートダイアログのmodifier属性の値を指定します。[/ja] * @param {String} [options.maskColor] * [en]Color of the background mask. Default is "rgba(0, 0, 0, 0.2)" ("rgba(0, 0, 0, 0.3)" for Material).[/en] * [ja]背景のマスクの色を指定します。"rgba(0, 0, 0, 0.2)"がデフォルト値です。[/ja] * @param {Function} [options.callback] * [en]Function that executes after dialog has been closed.[/en] * [ja]アラートダイアログが閉じられた時に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en] * Display an alert dialog to show the user a message. * * The content of the message can be either simple text or HTML. * * It can be called in the following ways: * * ``` * ons.notification.alert(message, options); * ons.notification.alert(options); * ``` * * Must specify either `message` or `messageHTML`. * [/en] * [ja] * ユーザーへメッセージを見せるためのアラートダイアログを表示します。 * 表示するメッセージは、テキストかもしくはHTMLを指定できます。 * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。 * [/ja] */ notification.alert = function (message, options) { return notification._createAlertDialog(message, options, { buttonLabels: ['OK'], title: 'Alert' }); }; /** * @method confirm * @signature confirm(message [, options] | options) * @return {Promise} * [en]Will resolve to the index of the button that was pressed or `-1` when canceled.[/en] * [ja][/ja] * @param {String} message * [en]Notification message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en] * [ja][/ja] * @param {Object} options * [en]Parameter object.[/en] * @param {Array} [options.buttonLabels] * [en]Labels for the buttons. Default is `["Cancel", "OK"]`.[/en] * [ja]ボタンのラベルの配列を指定します。["Cancel", "OK"]がデフォルトです。[/ja] * @param {Number} [options.primaryButtonIndex] * [en]Index of primary button. Default is the last one.[/en] * [ja]プライマリボタンのインデックスを指定します。デフォルトは 1 です。[/ja] * @description * [en] * Display a dialog to ask the user for confirmation. Extends `alert()` parameters. * The default button labels are `"Cancel"` and `"OK"` but they can be customized. * * It can be called in the following ways: * * ``` * ons.notification.confirm(message, options); * ons.notification.confirm(options); * ``` * * Must specify either `message` or `messageHTML`. * [/en] * [ja] * ユーザに確認を促すダイアログを表示します。 * デオルとのボタンラベルは、"Cancel"と"OK"ですが、これはこのメソッドの引数でカスタマイズできます。 * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。 * [/ja] */ notification.confirm = function (message, options) { return notification._createAlertDialog(message, options, { buttonLabels: ['Cancel', 'OK'], title: 'Confirm' }); }; /** * @method prompt * @signature prompt(message [, options] | options) * @param {String} message * [en]Notification message. This argument is optional but if it's not defined either `options.message` or `options.messageHTML` must be defined instead.[/en] * [ja][/ja] * @return {Promise} * [en]Will resolve to the input value when the dialog is closed or `null` when canceled.[/en] * [ja][/ja] * @param {Object} options * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクトです。[/ja] * @param {String | Array} [options.buttonLabels] * [en]Labels for the buttons. Default is `"OK"`.[/en] * [ja]確認ボタンのラベルを指定します。"OK"がデフォルトです。[/ja] * @param {Number} [options.primaryButtonIndex] * [en]Index of primary button. Default is the last one.[/en] * [ja]プライマリボタンのインデックスを指定します。デフォルトは 0 です。[/ja] * @param {String} [options.placeholder] * [en]Placeholder for the text input.[/en] * [ja]テキスト欄のプレースホルダに表示するテキストを指定します。[/ja] * @param {String} [options.defaultValue] * [en]Default value for the text input.[/en] * [ja]テキスト欄のデフォルトの値を指定します。[/ja] * @param {String} [options.inputType] * [en]Type of the input element (`password`, `date`...). Default is `text`.[/en] * [ja][/ja] * @param {Boolean} [options.autofocus] * [en]Autofocus the input element. Default is `true`. In Cordova, `KeyboardDisplayRequiresUserAction` in `config.xml` must be `false` to activate this feature.[/en] * [ja]input要素に自動的にフォーカスするかどうかを指定します。デフォルトはtrueです。Cordova環境では、この機能を有効にするためには `config.xml` で `KeyboardDisplayRequiresUserAction` を `false` に設定する必要があります。[/ja] * @param {Boolean} [options.submitOnEnter] * [en]Submit automatically when enter is pressed. Default is `true`.[/en] * [ja]Enterが押された際にそのformをsubmitするかどうかを指定します。デフォルトはtrueです。[/ja] * @description * [en] * Display a dialog with a prompt to ask the user a question. Extends `alert()` parameters. * * It can be called in the following ways: * * ``` * ons.notification.prompt(message, options); * ons.notification.prompt(options); * ``` * * Must specify either `message` or `messageHTML`. * [/en] * [ja] * ユーザーに入力を促すダイアログを表示します。 * このメソッドの引数には、options.messageもしくはoptions.messageHTMLのどちらかを必ず指定する必要があります。 * [/ja] */ notification.prompt = function (message, options) { return notification._createAlertDialog(message, options, { buttonLabels: ['OK'], title: 'Alert', isPrompt: true, autofocus: true, submitOnEnter: true }); }; /** * @method toast * @signature toast(message [, options] | options) * @return {Promise} * [en]Will resolve when the toast is hidden.[/en] * [ja][/ja] * @param {String} message * [en]Toast message. This argument is optional but if it's not defined then `options.message` must be defined instead.[/en] * [ja][/ja] * @param {Object} options * [en]Parameter object.[/en] * [ja]オプションを指定するオブジェクトです。[/ja] * @param {String} [options.message] * [en]Notification message.[/en] * [ja]トーストに表示する文字列を指定します。[/ja] * @param {String} [options.buttonLabel] * [en]Label for the button.[/en] * [ja]確認ボタンのラベルを指定します。[/ja] * @param {String} [options.animation] * [en]Animation name. Available animations are `none`, `fade`, `ascend`, `lift` and `fall`. Default is `ascend` for Android and `lift` for iOS.[/en] * [ja]トーストを表示する際のアニメーション名を指定します。"none", "fade", "ascend", "lift", "fall"のいずれかを指定できます。[/ja] * @param {Number} [options.timeout] * [en]Number of miliseconds where the toast is visible before hiding automatically.[/en] * [ja][/ja] * @param {Boolean} [options.force] * [en]If `true`, the toast skips the notification queue and is shown immediately. Defaults to `false`.[/en] * [ja][/ja] * @param {String} [options.id] * [en]The `` element's ID.[/en] * [ja]ons-toast要素のID。[/ja] * @param {String} [options.class] * [en]The `` element's class.[/en] * [ja]ons-toast要素のclass。[/ja] * @param {String} [options.modifier] * [en]Modifier for the element.[/en] * [ja]トーストのmodifier属性の値を指定します。[/ja] * @param {Function} [options.callback] * [en]Function that executes after toast has been hidden.[/en] * [ja]トーストが閉じられた時に呼び出される関数オブジェクトを指定します。[/ja] * @description * [en] * Display a simple notification toast with an optional button that can be used for simple actions. * * It can be called in the following ways: * * ``` * ons.notification.toast(message, options); * ons.notification.toast(options); * ``` * [/en] * [ja][/ja] */ notification.toast = function (message, options) { var promise = new Promise(function (resolve) { util$1.checkMissingImport('Toast'); // Throws error, must be inside promise options = _normalizeArguments(message, options, { timeout: 0, force: false }); var toast = util$1.createElement('\n \n ' + options.message + '\n ' + (options.buttonLabels ? '' : '') + '\n \n '); _setAttributes(toast, options); var finish = function finish(value) { if (toast) { toast.hide().then(function () { if (toast) { toast.remove(); toast = null; options.callback(value); resolve(value); } }); } }; if (options.buttonLabels) { util$1.findChild(toast._toast, 'button').onclick = function () { return finish(0); }; } document.body.appendChild(toast); options.compile(toast); var show = function show() { toast.parentElement && toast.show(options).then(function () { if (options.timeout) { setTimeout(function () { return finish(-1); }, options.timeout); } }); }; setImmediate(function () { return options.force ? show() : ToastQueue$1.add(show, promise); }); }); return promise; }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Validate parameters var checkOptions = function checkOptions(options) { var err = function err(prop) { var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Function'; return util$1.throw('"options.' + prop + '" must be an instance of ' + type); }; var hasOwnProperty = function hasOwnProperty(prop) { return Object.hasOwnProperty.call(options, prop); }; var instanceOf = function instanceOf(prop) { var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Function; return options[prop] instanceof type; }; var b = 'buttons', cb = 'callback', c = 'compile', d = 'destroy'; (!hasOwnProperty(b) || !instanceOf(b, Array)) && err(b, 'Array'); hasOwnProperty(cb) && !instanceOf(cb) && err(cb); hasOwnProperty(c) && !instanceOf(c) && err(c); hasOwnProperty(d) && !instanceOf(d) && err(d); }; // Action Sheet var actionSheet = (function () { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return new Promise(function (resolve) { util$1.checkMissingImport('ActionSheet'); checkOptions(options); // Main component var actionSheet = util$1.createElement('\n \n
\n \n '); // Resolve action and clean up var finish = function finish(event) { var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : -1; if (actionSheet) { options.destroy && options.destroy(actionSheet); actionSheet.removeEventListener('dialog-cancel', finish, false); actionSheet.remove(); actionSheet = null; options.callback && options.callback(index); resolve(index); } }; // Link cancel handler actionSheet.addEventListener('dialog-cancel', finish, false); // Create buttons and link action handler var buttons = document.createDocumentFragment(); options.buttons.forEach(function (item, index) { var buttonOptions = typeof item === 'string' ? { label: item } : _extends({}, item); if (options.destructive === index) { buttonOptions.modifier = (buttonOptions.modifier || '') + ' destructive'; } var button = util$1.createElement('\n \n ' + buttonOptions.label + '\n \n '); button.onclick = function (event) { return actionSheet.hide().then(function () { return finish(event, index); }); }; buttons.appendChild(button); }); // Finish component and attach util$1.findChild(actionSheet, '.action-sheet').appendChild(buttons); document.body.appendChild(actionSheet); options.compile && options.compile(el.dialog); // Show setImmediate(function () { return actionSheet.show({ animation: options.animation, animationOptions: options.animationOptions }); }); }); }); /** * MicroEvent - to make any js object an event emitter (server or browser) * * - pure javascript - server compatible, browser compatible * - dont rely on the browser doms * - super simple - you get it immediately, no mystery, no magic involved * * - create a MicroEventDebug with goodies to debug * - make it safer to use */ /** NOTE: This library is customized for Onsen UI. */ var MicroEvent = function MicroEvent() {}; MicroEvent.prototype = { on: function on(event, fct) { this._events = this._events || {}; this._events[event] = this._events[event] || []; this._events[event].push(fct); }, once: function once(event, fct) { var self = this; var wrapper = function wrapper() { self.off(event, wrapper); return fct.apply(null, arguments); }; this.on(event, wrapper); }, off: function off(event, fct) { this._events = this._events || {}; if (event in this._events === false) { return; } this._events[event] = this._events[event].filter(function (_fct) { if (fct) { return fct !== _fct; } else { return false; } }); }, emit: function emit(event /* , args... */) { this._events = this._events || {}; if (event in this._events === false) { return; } for (var i = 0; i < this._events[event].length; i++) { this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1)); } } }; /** * mixin will delegate all MicroEvent.js function in the destination object * * - require('MicroEvent').mixin(Foobar) will make Foobar able to use MicroEvent * * @param {Object} the object which will support MicroEvent */ MicroEvent.mixin = function (destObject) { var props = ['on', 'once', 'off', 'emit']; for (var i = 0; i < props.length; i++) { if (typeof destObject === 'function') { destObject.prototype[props[i]] = MicroEvent.prototype[props[i]]; } else { destObject[props[i]] = MicroEvent.prototype[props[i]]; } } }; window.MicroEvent = MicroEvent; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var create = function create() { /** * @object ons.orientation * @category util * @description * [en]Utility methods for orientation detection.[/en] * [ja]画面のオリエンテーション検知のためのユーティリティメソッドを収めているオブジェクトです。[/ja] */ var obj = { /** * @event change * @description * [en]Fired when the device orientation changes.[/en] * [ja]デバイスのオリエンテーションが変化した際に発火します。[/ja] * @param {Object} event * [en]Event object.[/en] * [ja]イベントオブジェクトです。[/ja] * @param {Boolean} event.isPortrait * [en]Will be true if the current orientation is portrait mode.[/en] * [ja]現在のオリエンテーションがportraitの場合にtrueを返します。[/ja] */ /** * @method on * @signature on(eventName, listener) * @description * [en]Add an event listener.[/en] * [ja]イベントリスナーを追加します。[/ja] * @param {String} eventName * [en]Name of the event.[/en] * [ja]イベント名を指定します。[/ja] * @param {Function} listener * [en]Function to execute when the event is triggered.[/en] * [ja]このイベントが発火された際に呼び出される関数オブジェクトを指定します。[/ja] */ /** * @method once * @signature once(eventName, listener) * @description * [en]Add an event listener that's only triggered once.[/en] * [ja]一度だけ呼び出されるイベントリスナーを追加します。[/ja] * @param {String} eventName * [en]Name of the event.[/en] * [ja]イベント名を指定します。[/ja] * @param {Function} listener * [en]Function to execute when the event is triggered.[/en] * [ja]イベントが発火した際に呼び出される関数オブジェクトを指定します。[/ja] */ /** * @method off * @signature off(eventName, [listener]) * @description * [en]Remove an event listener. If the listener is not specified all listeners for the event type will be removed.[/en] * [ja]イベントリスナーを削除します。もしイベントリスナーを指定しなかった場合には、そのイベントに紐づく全てのイベントリスナーが削除されます。[/ja] * @param {String} eventName * [en]Name of the event.[/en] * [ja]イベント名を指定します。[/ja] * @param {Function} listener * [en]Function to execute when the event is triggered.[/en] * [ja]削除するイベントリスナーを指定します。[/ja] */ // actual implementation to detect if whether current screen is portrait or not _isPortrait: false, /** * @method isPortrait * @signature isPortrait() * @return {Boolean} * [en]Will be true if the current orientation is portrait mode.[/en] * [ja]オリエンテーションがportraitモードの場合にtrueになります。[/ja] * @description * [en]Returns whether the current screen orientation is portrait or not.[/en] * [ja]オリエンテーションがportraitモードかどうかを返します。[/ja] */ isPortrait: function isPortrait() { return this._isPortrait(); }, /** * @method isLandscape * @signature isLandscape() * @return {Boolean} * [en]Will be true if the current orientation is landscape mode.[/en] * [ja]オリエンテーションがlandscapeモードの場合にtrueになります。[/ja] * @description * [en]Returns whether the current screen orientation is landscape or not.[/en] * [ja]オリエンテーションがlandscapeモードかどうかを返します。[/ja] */ isLandscape: function isLandscape() { return !this.isPortrait(); }, _init: function _init() { document.addEventListener('DOMContentLoaded', this._onDOMContentLoaded.bind(this), false); if ('orientation' in window) { window.addEventListener('orientationchange', this._onOrientationChange.bind(this), false); } else { window.addEventListener('resize', this._onResize.bind(this), false); } this._isPortrait = function () { return window.innerHeight > window.innerWidth; }; return this; }, _onDOMContentLoaded: function _onDOMContentLoaded() { this._installIsPortraitImplementation(); this.emit('change', { isPortrait: this.isPortrait() }); }, _installIsPortraitImplementation: function _installIsPortraitImplementation() { var isPortrait = window.innerWidth < window.innerHeight; if (!('orientation' in window)) { this._isPortrait = function () { return window.innerHeight > window.innerWidth; }; } else if (window.orientation % 180 === 0) { this._isPortrait = function () { return Math.abs(window.orientation % 180) === 0 ? isPortrait : !isPortrait; }; } else { this._isPortrait = function () { return Math.abs(window.orientation % 180) === 90 ? isPortrait : !isPortrait; }; } }, _onOrientationChange: function _onOrientationChange() { var _this = this; var isPortrait = this._isPortrait(); // Wait for the dimensions to change because // of Android inconsistency. var nIter = 0; var interval = setInterval(function () { nIter++; var w = window.innerWidth; var h = window.innerHeight; if (isPortrait && w <= h || !isPortrait && w >= h) { _this.emit('change', { isPortrait: isPortrait }); clearInterval(interval); } else if (nIter === 50) { _this.emit('change', { isPortrait: isPortrait }); clearInterval(interval); } }, 20); }, // Run on not mobile browser. _onResize: function _onResize() { this.emit('change', { isPortrait: this.isPortrait() }); } }; MicroEvent.mixin(obj); return obj; }; var orientation = create()._init(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @object ons.modifier * @category visual * @description * [en] * Utility methods to change modifier attributes of Onsen UI elements.. * [/en] * [ja][/ja] * @example * ons.modifier.add(myOnsInputElement, 'underbar'); * ons.modifier.toggle(myOnsToastElement, 'custom-modifier'); * */ var modifier = { /** * @method add * @signature add(element, modifier [, modifier]) * @description * [en]Add the specified modifiers to the element if they are not already included.[/en] * [ja][/ja] * @param {HTMLElement} element * [en]Target element.[/en] * [ja][/ja] * @param {String} modifier * [en]Name of the modifier.[/en] * [ja][/ja] */ add: function add(element) { for (var _len = arguments.length, modifiers = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { modifiers[_key - 1] = arguments[_key]; } return modifiers.forEach(function (modifier) { return util$1.addModifier(element, modifier); }); }, /** * @method remove * @signature remove(element, modifier [, modifier]) * @description * [en]Remove the specified modifiers from the element if they are included.[/en] * [ja][/ja] * @param {HTMLElement} element * [en]Target element.[/en] * [ja][/ja] * @param {String} modifier * [en]Name of the modifier.[/en] * [ja][/ja] */ remove: function remove(element) { for (var _len2 = arguments.length, modifiers = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { modifiers[_key2 - 1] = arguments[_key2]; } return modifiers.forEach(function (modifier) { return util$1.removeModifier(element, modifier); }); }, /** * @method contains * @signature contains(element, modifier) * @description * [en]Check whether the specified modifier is included in the element.[/en] * [ja][/ja] * @param {HTMLElement} element * [en]Target element.[/en] * [ja][/ja] * @param {String} modifier * [en]Name of the modifier.[/en] * [ja][/ja] * @return {Boolean} * [en]`true` when the specified modifier is found in the element's `modifier` attribute. `false` otherwise.[/en] * [ja][/ja] */ contains: util$1.hasModifier, /** * @method toggle * @signature toggle(element, modifier [, force]) * @description * [en]Toggle the specified modifier.[/en] * [ja][/ja] * @param {HTMLElement} element * [en]Target element.[/en] * [ja][/ja] * @param {String} modifier * [en]Name of the modifier.[/en] * [ja][/ja] * @param {String} force * [en]If it evaluates to true, add specified modifier value, and if it evaluates to false, remove it.[/en] * [ja][/ja] */ toggle: util$1.toggleModifier }; /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var softwareKeyboard = new MicroEvent(); softwareKeyboard._visible = false; var onShow = function onShow() { softwareKeyboard._visible = true; softwareKeyboard.emit('show'); }; var onHide = function onHide() { softwareKeyboard._visible = false; softwareKeyboard.emit('hide'); }; var bindEvents = function bindEvents() { if (typeof Keyboard !== 'undefined') { // https://github.com/martinmose/cordova-keyboard/blob/95f3da3a38d8f8e1fa41fbf40145352c13535a00/README.md Keyboard.onshow = onShow; Keyboard.onhide = onHide; softwareKeyboard.emit('init', { visible: Keyboard.isVisible }); return true; } else if (typeof cordova.plugins !== 'undefined' && typeof cordova.plugins.Keyboard !== 'undefined') { // https://github.com/driftyco/ionic-plugins-keyboard/blob/ca27ecf/README.md window.addEventListener('native.keyboardshow', onShow); window.addEventListener('native.keyboardhide', onHide); softwareKeyboard.emit('init', { visible: cordova.plugins.Keyboard.isVisible }); return true; } return false; }; var noPluginError = function noPluginError() { util$1.warn('ons-keyboard: Cordova Keyboard plugin is not present.'); }; document.addEventListener('deviceready', function () { if (!bindEvents()) { if (document.querySelector('[ons-keyboard-active]') || document.querySelector('[ons-keyboard-inactive]')) { noPluginError(); } softwareKeyboard.on = noPluginError; } }); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ var generateId = function () { var i = 0; return function () { return i++; }; }(); /** * Door locking system. * * @param {Object} [options] * @param {Function} [options.log] */ var DoorLock = function () { function DoorLock() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; classCallCheck(this, DoorLock); this._lockList = []; this._waitList = []; this._log = options.log || function () {}; } /** * Register a lock. * * @return {Function} Callback for unlocking. */ createClass(DoorLock, [{ key: 'lock', value: function lock() { var _this = this; var unlock = function unlock() { _this._unlock(unlock); }; unlock.id = generateId(); this._lockList.push(unlock); this._log('lock: ' + unlock.id); return unlock; } }, { key: '_unlock', value: function _unlock(fn) { var index = this._lockList.indexOf(fn); if (index === -1) { throw new Error('This function is not registered in the lock list.'); } this._lockList.splice(index, 1); this._log('unlock: ' + fn.id); this._tryToFreeWaitList(); } }, { key: '_tryToFreeWaitList', value: function _tryToFreeWaitList() { while (!this.isLocked() && this._waitList.length > 0) { this._waitList.shift()(); } } /** * Register a callback for waiting unlocked door. * * @params {Function} callback Callback on unlocking the door completely. */ }, { key: 'waitUnlock', value: function waitUnlock(callback) { if (!(callback instanceof Function)) { throw new Error('The callback param must be a function.'); } if (this.isLocked()) { this._waitList.push(callback); } else { callback(); } } /** * @return {Boolean} */ }, { key: 'isLocked', value: function isLocked() { return this._lockList.length > 0; } }]); return DoorLock; }(); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Default implementation for global PageLoader. function loadPage(_ref, done) { var page = _ref.page, parent = _ref.parent, _ref$params = _ref.params; internal$1.getPageHTMLAsync(page).then(function (html) { var pageElement = util$1.createElement(html); parent.appendChild(pageElement); done(pageElement); }); } function unloadPage(element) { if (element._destroy instanceof Function) { element._destroy(); } else { element.remove(); } } var PageLoader = function () { /** * @param {Function} [fn] Returns an object that has "element" property and "unload" function. */ function PageLoader(loader, unloader) { classCallCheck(this, PageLoader); this._loader = loader instanceof Function ? loader : loadPage; this._unloader = unloader instanceof Function ? unloader : unloadPage; } /** * Set internal loader implementation. */ createClass(PageLoader, [{ key: 'load', /** * @param {any} options.page * @param {Element} options.parent A location to load page. * @param {Object} [options.params] Extra parameters for ons-page. * @param {Function} done Take an object that has "element" property and "unload" function. */ value: function load(_ref2, done) { var page = _ref2.page, parent = _ref2.parent, _ref2$params = _ref2.params, params = _ref2$params === undefined ? {} : _ref2$params; this._loader({ page: page, parent: parent, params: params }, function (pageElement) { if (!(pageElement instanceof Element)) { throw Error('pageElement must be an instance of Element.'); } done(pageElement); }); } }, { key: 'unload', value: function unload(pageElement) { if (!(pageElement instanceof Element)) { throw Error('pageElement must be an instance of Element.'); } this._unloader(pageElement); } }, { key: 'internalLoader', set: function set$$1(fn) { if (!(fn instanceof Function)) { throw Error('First parameter must be an instance of Function'); } this._loader = fn; }, get: function get$$1() { return this._loader; } }]); return PageLoader; }(); var defaultPageLoader = new PageLoader(); var instantPageLoader = new PageLoader(function (_ref3, done) { var page = _ref3.page, parent = _ref3.parent, _ref3$params = _ref3.params; var element = util$1.createElement(page.trim()); parent.appendChild(element); done(element); }, unloadPage); /* Copyright 2013-2015 ASIAL CORPORATION Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /** * @object ons * @category util * @description * [ja]Onsen UIで利用できるグローバルなオブジェクトです。[/ja] * [en]A global object that's used in Onsen UI. [/en] */ var ons$1 = { animit: Animit, defaultPageLoader: defaultPageLoader, elements: onsElements, GestureDetector: GestureDetector, modifier: modifier, notification: notification, orientation: orientation, pageAttributeExpression: pageAttributeExpression, PageLoader: PageLoader, platform: platform, softwareKeyboard: softwareKeyboard, _autoStyle: autoStyle, _internal: internal$1, _readyLock: new DoorLock(), _util: util$1 }; ons$1.platform.select((window.location.search.match(/platform=([\w-]+)/) || [])[1]); waitDeviceReady(); var readyError = function readyError(after) { return util$1.throw('This method must be called ' + (after ? 'after' : 'before') + ' ons.isReady() is true'); }; /** * @method isReady * @signature isReady() * @return {Boolean} * [en]Will be true if Onsen UI is initialized.[/en] * [ja]初期化されているかどうかを返します。[/ja] * @description * [en]Returns true if Onsen UI is initialized.[/en] * [ja]Onsen UIがすでに初期化されているかどうかを返すメソッドです。[/ja] */ ons$1.isReady = function () { return !ons$1._readyLock.isLocked(); }; /** * @method isWebView * @signature isWebView() * @return {Boolean} * [en]Will be true if the app is running in Cordova.[/en] * [ja]Cordovaで実行されている場合にtrueになります。[/ja] * @description * [en]Returns true if running inside Cordova.[/en] * [ja]Cordovaで実行されているかどうかを返すメソッドです。[/ja] */ ons$1.isWebView = ons$1.platform.isWebView; /** * @method ready * @signature ready(callback) * @description * [ja]アプリの初期化に利用するメソッドです。渡された関数は、Onsen UIの初期化が終了している時点で必ず呼ばれます。[/ja] * [en]Method used to wait for app initialization. Waits for `DOMContentLoaded` and `deviceready`, when necessary, before executing the callback.[/en] * @param {Function} callback * [en]Function that executes after Onsen UI has been initialized.[/en] * [ja]Onsen UIが初期化が完了した後に呼び出される関数オブジェクトを指定します。[/ja] */ ons$1.ready = function (callback) { if (ons$1.isReady()) { callback(); } else { ons$1._readyLock.waitUnlock(callback); } }; /** * @method setDefaultDeviceBackButtonListener * @signature setDefaultDeviceBackButtonListener(listener) * @param {Function} listener * [en]Function that executes when device back button is pressed. Must be called on `ons.ready`.[/en] * [ja]デバイスのバックボタンが押された時に実行される関数オブジェクトを指定します。[/ja] * @description * [en]Set default handler for device back button.[/en] * [ja]デバイスのバックボタンのためのデフォルトのハンドラを設定します。[/ja] */ ons$1.setDefaultDeviceBackButtonListener = function (listener) { if (!ons$1.isReady()) { readyError(true); } ons$1._defaultDeviceBackButtonHandler.setListener(listener); }; /** * @method disableDeviceBackButtonHandler * @signature disableDeviceBackButtonHandler() * @description * [en]Disable device back button event handler. Must be called on `ons.ready`.[/en] * [ja]デバイスのバックボタンのイベントを受け付けないようにします。[/ja] */ ons$1.disableDeviceBackButtonHandler = function () { if (!ons$1.isReady()) { readyError(true); } internal$1.dbbDispatcher.disable(); }; /** * @method enableDeviceBackButtonHandler * @signature enableDeviceBackButtonHandler() * @description * [en]Enable device back button event handler. Must be called on `ons.ready`.[/en] * [ja]デバイスのバックボタンのイベントを受け付けるようにします。[/ja] */ ons$1.enableDeviceBackButtonHandler = function () { if (!ons$1.isReady()) { readyError(true); } internal$1.dbbDispatcher.enable(); }; ons$1.fireDeviceBackButtonEvent = function () { internal$1.dbbDispatcher.fireDeviceBackButtonEvent(); }; /** * @method enableAutoStatusBarFill * @signature enableAutoStatusBarFill() * @description * [en]Enable status bar fill feature on iOS7 and above (except for iPhone X). Must be called before `ons.ready`.[/en] * [ja]iOS7以上(iPhone Xは除く)で、ステータスバー部分の高さを自動的に埋める処理を有効にします。[/ja] */ ons$1.enableAutoStatusBarFill = function () { if (ons$1.isReady()) { readyError(false); } internal$1.config.autoStatusBarFill = true; }; /** * @method disableAutoStatusBarFill * @signature disableAutoStatusBarFill() * @description * [en]Disable status bar fill feature on iOS7 and above (except for iPhone X). Must be called before `ons.ready`.[/en] * [ja]iOS7以上(iPhone Xは除く)で、ステータスバー部分の高さを自動的に埋める処理を無効にします。[/ja] */ ons$1.disableAutoStatusBarFill = function () { if (ons$1.isReady()) { readyError(false); } internal$1.config.autoStatusBarFill = false; }; /** * @method mockStatusBar * @signature mockStatusBar() * @description * [en]Creates a static element similar to iOS status bar. Only useful for browser testing. Must be called before `ons.ready`.[/en] * [ja][/ja] */ ons$1.mockStatusBar = function () { if (ons$1.isReady()) { readyError(false); } var mock = function mock() { if (!document.body.children[0] || !document.body.children[0].classList.contains('ons-status-bar-mock')) { var android = platform.isAndroid(), i = function i(_i) { return ''; }; var left = android ? i('zmdi-twitter') + ' ' + i('zmdi-google-play') : 'No SIM ' + i('fa-wifi'), center = android ? '' : '12:28 PM', right = android ? i('zmdi-network') + ' ' + i('zmdi-wifi') + ' ' + i('zmdi-battery') + ' 12:28 PM' : '80% ' + i('fa-battery-three-quarters'); document.body.insertBefore(util$1.createElement('
' + ('
' + left + '
' + center + '
' + right + '
') + '
'), document.body.firstChild); } }; document.body ? mock() : internal$1.waitDOMContentLoaded(mock); }; /** * @method disableAnimations * @signature disableAnimations() * @description * [en]Disable all animations. Could be handy for testing and older devices.[/en] * [ja]アニメーションを全て無効にします。テストの際に便利です。[/ja] */ ons$1.disableAnimations = function () { internal$1.config.animationsDisabled = true; }; /** * @method enableAnimations * @signature enableAnimations() * @description * [en]Enable animations (default).[/en] * [ja]アニメーションを有効にします。[/ja] */ ons$1.enableAnimations = function () { internal$1.config.animationsDisabled = false; }; ons$1._disableWarnings = function () { internal$1.config.warningsDisabled = true; }; ons$1._enableWarnings = function () { internal$1.config.warningsDisabled = false; }; /** * @method disableAutoStyling * @signature disableAutoStyling() * @description * [en]Disable automatic styling.[/en] * [ja][/ja] */ ons$1.disableAutoStyling = autoStyle.disable; /** * @method enableAutoStyling * @signature enableAutoStyling() * @description * [en]Enable automatic styling based on OS (default).[/en] * [ja][/ja] */ ons$1.enableAutoStyling = autoStyle.enable; /** * @method disableIconAutoPrefix * @signature disableIconAutoPrefix() * @description * [en]Disable adding `fa-` prefix automatically to `ons-icon` classes. Useful when including custom icon packs.[/en] * [ja][/ja] */ ons$1.disableIconAutoPrefix = function () { util$1.checkMissingImport('Icon'); onsElements.Icon.setAutoPrefix(false); }; /** * @method forceUIWebViewScrollFix * @signature forceUIWebViewScrollFix() * @param {Boolean} force Enable or disable the fix. * @description * [en]Applies a fix for iOS UIWebView which prevents scroll events jumping to pages under the top layer. This may visually affect normal scrolling of UIWebView if you open a dialog/menu before the scroll momentum finished. Disabled by default.[/en] * [ja][/ja] */ ons$1.forceUIWebViewScrollFix = function () { var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; internal$1.config.forceUIWebViewScrollFix = force; }; /** * @method forcePlatformStyling * @signature forcePlatformStyling(platform) * @description * [en]Refresh styling for the given platform. Only useful for demos. Use `ons.platform.select(...)` instead for development and production.[/en] * [ja][/ja] * @param {string} platform New platform to style the elements. */ ons$1.forcePlatformStyling = function (newPlatform) { ons$1.enableAutoStyling(); ons$1.platform.select(newPlatform || 'ios'); ons$1._util.arrayFrom(document.querySelectorAll('*')).forEach(function (element) { if (element.tagName.toLowerCase() === 'ons-if') { element._platformUpdate(); } else if (element.tagName.match(/^ons-/i)) { autoStyle.prepare(element, true); if (element.tagName.toLowerCase() === 'ons-tabbar') { element._updatePosition(); } } }); }; /** * @method preload * @signature preload(templatePaths) * @param {String|Array} templatePaths * [en]Set of HTML file paths containing 'ons-page' elements.[/en] * [ja][/ja] * @return {Promise} * [en]Promise that resolves when all the templates are cached.[/en] * [ja][/ja] * @description * [en]Separated files need to be requested on demand and this can slightly delay pushing new pages. This method requests and caches templates for later use.[/en] * [ja][/ja] */ ons$1.preload = function () { var templates = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; return Promise.all((templates instanceof Array ? templates : [templates]).map(function (template) { if (typeof template !== 'string') { util$1.throw('Expected string arguments but got ' + (typeof template === 'undefined' ? 'undefined' : _typeof(template))); } return internal$1.getTemplateHTMLAsync(template); })); }; /** * @method createElement * @signature createElement(template, options) * @param {String} template * [en]Either an HTML file path, a `