No Description

platform.js 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. import _typeof from 'babel-runtime/helpers/typeof';
  2. import _classCallCheck from 'babel-runtime/helpers/classCallCheck';
  3. import _createClass from 'babel-runtime/helpers/createClass';
  4. /*
  5. Copyright 2013-2015 ASIAL CORPORATION
  6. Licensed under the Apache License, Version 2.0 (the "License");
  7. you may not use this file except in compliance with the License.
  8. You may obtain a copy of the License at
  9. http://www.apache.org/licenses/LICENSE-2.0
  10. Unless required by applicable law or agreed to in writing, software
  11. distributed under the License is distributed on an "AS IS" BASIS,
  12. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. See the License for the specific language governing permissions and
  14. limitations under the License.
  15. */
  16. // Save HTMLElement object before Custom Elements polyfill patch global HTMLElement.
  17. var NativeHTMLElement = window.HTMLElement;
  18. /**
  19. * @object ons.platform
  20. * @category util
  21. * @description
  22. * [en]Utility methods to detect current platform.[/en]
  23. * [ja]現在実行されているプラットフォームを検知するためのユーティリティメソッドを収めたオブジェクトです。[/ja]
  24. */
  25. var Platform = function () {
  26. /**
  27. * All elements will be rendered as if the app was running on this platform.
  28. * @type {String}
  29. */
  30. function Platform() {
  31. _classCallCheck(this, Platform);
  32. this._selectedPlatform = null;
  33. this._ignorePlatformSelect = false;
  34. }
  35. /**
  36. * @method select
  37. * @signature select(platform)
  38. * @param {string} platform Name of the platform.
  39. * [en]Possible values are: "opera", "firefox", "safari", "chrome", "ie", "android", "blackberry", "ios" or "wp".[/en]
  40. * [ja]"opera", "firefox", "safari", "chrome", "ie", "android", "blackberry", "ios", "wp"のいずれかを指定します。[/ja]
  41. * @description
  42. * [en]Sets the platform used to render the elements. Useful for testing.[/en]
  43. * [ja]要素を描画するために利用するプラットフォーム名を設定します。テストに便利です。[/ja]
  44. */
  45. _createClass(Platform, [{
  46. key: 'select',
  47. value: function select(platform) {
  48. if (typeof platform === 'string') {
  49. this._selectedPlatform = platform.trim().toLowerCase();
  50. }
  51. }
  52. }, {
  53. key: '_getSelectedPlatform',
  54. value: function _getSelectedPlatform() {
  55. return this._ignorePlatformSelect ? null : this._selectedPlatform;
  56. }
  57. }, {
  58. key: '_runOnActualPlatform',
  59. value: function _runOnActualPlatform(fn) {
  60. this._ignorePlatformSelect = true;
  61. var result = fn();
  62. this._ignorePlatformSelect = false;
  63. return result;
  64. }
  65. //----------------
  66. // General
  67. //----------------
  68. /**
  69. * @method isWebView
  70. * @signature isWebView()
  71. * @description
  72. * [en]Returns whether app is running in Cordova.[/en]
  73. * [ja]Cordova内で実行されているかどうかを返します。[/ja]
  74. * @return {Boolean}
  75. */
  76. }, {
  77. key: 'isWebView',
  78. value: function isWebView() {
  79. if (document.readyState === 'loading' || document.readyState == 'uninitialized') {
  80. throw new Error('isWebView() method is available after dom contents loaded.');
  81. }
  82. return !!(window.cordova || window.phonegap || window.PhoneGap);
  83. }
  84. //----------------
  85. // iOS devices
  86. //----------------
  87. /**
  88. * @method isIPhone
  89. * @signature isIPhone()
  90. * @description
  91. * [en]Returns whether the device is iPhone.[/en]
  92. * [ja]iPhone上で実行されているかどうかを返します。[/ja]
  93. * @return {Boolean}
  94. */
  95. }, {
  96. key: 'isIPhone',
  97. value: function isIPhone() {
  98. return (/iPhone/i.test(navigator.userAgent)
  99. );
  100. }
  101. /**
  102. * @method isIPhoneX
  103. * @signature isIPhoneX()
  104. * @description
  105. * [en]Returns whether the device is iPhone X, XS, XS Max, or XR.[/en]
  106. * [ja]iPhone X や XS、XS Max、または XR 上で実行されているかどうかを返します。[/ja]
  107. * @return {Boolean}
  108. */
  109. }, {
  110. key: 'isIPhoneX',
  111. value: function isIPhoneX() {
  112. // iOS WebViews on the same iOS version have the same user agent.
  113. // We cannot avoid using window.screen.
  114. // We also cannot use cordova-plugin-device since its behavior is different between simulators and real devices.
  115. // This works well both in iOS Safari and (UI|WK)WebView of iPhone X.
  116. return this.isIPhone() && (window.screen.width === 375 && window.screen.height === 812 || // X, XS portrait
  117. window.screen.width === 812 && window.screen.height === 375 || // X, XS landscape
  118. window.screen.width === 414 && window.screen.height === 896 || // XS Max, XR portrait
  119. window.screen.width === 896 && window.screen.height === 414); // XS Max, XR landscape
  120. }
  121. /**
  122. * @method isIPad
  123. * @signature isIPad()
  124. * @description
  125. * [en]Returns whether the device is iPad.[/en]
  126. * [ja]iPad上で実行されているかどうかを返します。[/ja]
  127. * @return {Boolean}
  128. */
  129. }, {
  130. key: 'isIPad',
  131. value: function isIPad() {
  132. return (/iPad/i.test(navigator.userAgent)
  133. );
  134. }
  135. /**
  136. * @return {Boolean}
  137. */
  138. }, {
  139. key: 'isIPod',
  140. value: function isIPod() {
  141. return (/iPod/i.test(navigator.userAgent)
  142. );
  143. }
  144. //----------------
  145. // iOS versions
  146. //----------------
  147. /**
  148. * @method isIOS
  149. * @signature isIOS([forceActualPlatform])
  150. * @param {Boolean} forceActualPlatform
  151. * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
  152. * [ja][/ja]
  153. * @description
  154. * [en]Returns whether the OS is iOS. By default will return manually selected platform if it is set.[/en]
  155. * [ja]iOS上で実行されているかどうかを返します。[/ja]
  156. * @return {Boolean}
  157. */
  158. }, {
  159. key: 'isIOS',
  160. value: function isIOS(forceActualPlatform) {
  161. if (!forceActualPlatform && this._getSelectedPlatform()) {
  162. return this._getSelectedPlatform() === 'ios';
  163. }
  164. if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
  165. return (/iOS/i.test(device.platform)
  166. );
  167. } else {
  168. return (/iPhone|iPad|iPod/i.test(navigator.userAgent)
  169. );
  170. }
  171. }
  172. /**
  173. * @method isIOS7above
  174. * @signature isIOS7above()
  175. * @description
  176. * [en]Returns whether the iOS version is 7 or above.[/en]
  177. * [ja]iOS7以上で実行されているかどうかを返します。[/ja]
  178. * @return {Boolean}
  179. */
  180. }, {
  181. key: 'isIOS7above',
  182. value: function isIOS7above() {
  183. if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
  184. return (/iOS/i.test(device.platform) && parseInt(device.version.split('.')[0]) >= 7
  185. );
  186. } else if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {
  187. var ver = (navigator.userAgent.match(/\b[0-9]+_[0-9]+(?:_[0-9]+)?\b/) || [''])[0].replace(/_/g, '.');
  188. return parseInt(ver.split('.')[0]) >= 7;
  189. }
  190. return false;
  191. }
  192. //----------------
  193. // iOS browsers
  194. //----------------
  195. /**
  196. * @method isIOSSafari
  197. * @signature isIOSSafari()
  198. * @description
  199. * [en]Returns whether app is running in iOS Safari.[/en]
  200. * [ja]iOS Safariで実行されているかどうかを返します。[/ja]
  201. * @return {Boolean}
  202. */
  203. }, {
  204. key: 'isIOSSafari',
  205. value: function isIOSSafari() {
  206. var navigator = window.navigator;
  207. var ua = navigator.userAgent;
  208. return !!(this.isIOS() && ua.indexOf('Safari') !== -1 && ua.indexOf('Version') !== -1 && !navigator.standalone);
  209. }
  210. /**
  211. * @method isWKWebView
  212. * @signature isWKWebView()
  213. * @description
  214. * [en]Returns whether app is running in WKWebView.[/en]
  215. * [ja]WKWebViewで実行されているかどうかを返します。[/ja]
  216. * @return {Boolean}
  217. */
  218. }, {
  219. key: 'isWKWebView',
  220. value: function isWKWebView() {
  221. var lte9 = /constructor/i.test(NativeHTMLElement);
  222. return !!(this.isIOS() && window.webkit && window.webkit.messageHandlers && window.indexedDB && !lte9);
  223. }
  224. /**
  225. * @method isUIWebView
  226. * @signature isUIWebView()
  227. * @description
  228. * [en]Returns whether app is running in UIWebView.[/en]
  229. * [ja]UIWebViewで実行されているかどうかを返します。[/ja]
  230. * @return {Boolean}
  231. */
  232. }, {
  233. key: 'isUIWebView',
  234. value: function isUIWebView() {
  235. return !!(this.isIOS() && !this.isIOSSafari() && !this.isWKWebView());
  236. }
  237. //----------------
  238. // Android devices
  239. //----------------
  240. /**
  241. * @method isAndroidPhone
  242. * @signature isAndroidPhone()
  243. * @description
  244. * [en]Returns whether the device is Android phone.[/en]
  245. * [ja]Android携帯上で実行されているかどうかを返します。[/ja]
  246. * @return {Boolean}
  247. */
  248. }, {
  249. key: 'isAndroidPhone',
  250. value: function isAndroidPhone() {
  251. return (/Android/i.test(navigator.userAgent) && /Mobile/i.test(navigator.userAgent)
  252. );
  253. }
  254. /**
  255. * @method isAndroidTablet
  256. * @signature isAndroidTablet()
  257. * @description
  258. * [en]Returns whether the device is Android tablet.[/en]
  259. * [ja]Androidタブレット上で実行されているかどうかを返します。[/ja]
  260. * @return {Boolean}
  261. */
  262. }, {
  263. key: 'isAndroidTablet',
  264. value: function isAndroidTablet() {
  265. return (/Android/i.test(navigator.userAgent) && !/Mobile/i.test(navigator.userAgent)
  266. );
  267. }
  268. //----------------
  269. // Android versions
  270. //----------------
  271. /**
  272. * @method isAndroid
  273. * @signature isAndroid([forceActualPlatform])
  274. * @param {Boolean} forceActualPlatform
  275. * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
  276. * [ja][/ja]
  277. * @description
  278. * [en]Returns whether the OS is Android. By default will return manually selected platform if it is set.[/en]
  279. * [ja]Android上で実行されているかどうかを返します。[/ja]
  280. * @return {Boolean}
  281. */
  282. }, {
  283. key: 'isAndroid',
  284. value: function isAndroid(forceActualPlatform) {
  285. if (!forceActualPlatform && this._getSelectedPlatform()) {
  286. return this._getSelectedPlatform() === 'android';
  287. }
  288. if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
  289. return (/Android/i.test(device.platform)
  290. );
  291. } else {
  292. return (/Android/i.test(navigator.userAgent)
  293. );
  294. }
  295. }
  296. //----------------
  297. // Other devices
  298. //----------------
  299. /**
  300. * @method isWP
  301. * @signature isWP([forceActualPlatform])
  302. * @param {Boolean} forceActualPlatform
  303. * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
  304. * [ja][/ja]
  305. * @description
  306. * [en]Returns whether the OS is Windows phone. By default will return manually selected platform if it is set.[/en]
  307. * [ja][/ja]
  308. * @return {Boolean}
  309. */
  310. }, {
  311. key: 'isWP',
  312. value: function isWP(forceActualPlatform) {
  313. if (!forceActualPlatform && this._getSelectedPlatform()) {
  314. return this._getSelectedPlatform() === 'wp';
  315. }
  316. if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
  317. return (/Win32NT|WinCE/i.test(device.platform)
  318. );
  319. } else {
  320. return (/Windows Phone|IEMobile|WPDesktop/i.test(navigator.userAgent)
  321. );
  322. }
  323. }
  324. /**
  325. * @method isBlackBerry
  326. * @signature isBlackBerry([forceActualPlatform])
  327. * @param {Boolean} forceActualPlatform
  328. * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
  329. * [ja][/ja]
  330. * @description
  331. * [en]Returns whether the device is BlackBerry. By default will return manually selected platform if it is set.[/en]
  332. * [ja]BlackBerry上で実行されているかどうかを返します。[/ja]
  333. * @return {Boolean}
  334. */
  335. }, {
  336. key: 'isBlackBerry',
  337. value: function isBlackBerry(forceActualPlatform) {
  338. if (!forceActualPlatform && this._getSelectedPlatform()) {
  339. return this._getSelectedPlatform() === 'blackberry';
  340. }
  341. if ((typeof device === 'undefined' ? 'undefined' : _typeof(device)) === 'object' && !/browser/i.test(device.platform)) {
  342. return (/BlackBerry/i.test(device.platform)
  343. );
  344. } else {
  345. return (/BlackBerry|RIM Tablet OS|BB10/i.test(navigator.userAgent)
  346. );
  347. }
  348. }
  349. //----------------
  350. // Other browsers
  351. //----------------
  352. /**
  353. * @method isOpera
  354. * @signature isOpera([forceActualPlatform])
  355. * @param {Boolean} forceActualPlatform
  356. * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
  357. * [ja][/ja]
  358. * @description
  359. * [en]Returns whether the browser is Opera. By default will return manually selected platform if it is set.[/en]
  360. * [ja]Opera上で実行されているかどうかを返します。[/ja]
  361. * @return {Boolean}
  362. */
  363. }, {
  364. key: 'isOpera',
  365. value: function isOpera(forceActualPlatform) {
  366. if (!forceActualPlatform && this._getSelectedPlatform()) {
  367. return this._getSelectedPlatform() === 'opera';
  368. }
  369. return !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
  370. }
  371. /**
  372. * @method isFirefox
  373. * @signature isFirefox([forceActualPlatform])
  374. * @param {Boolean} forceActualPlatform
  375. * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
  376. * [ja][/ja]
  377. * @description
  378. * [en]Returns whether the browser is Firefox. By default will return manually selected platform if it is set.[/en]
  379. * [ja]Firefox上で実行されているかどうかを返します。[/ja]
  380. * @return {Boolean}
  381. */
  382. }, {
  383. key: 'isFirefox',
  384. value: function isFirefox(forceActualPlatform) {
  385. if (!forceActualPlatform && this._getSelectedPlatform()) {
  386. return this._getSelectedPlatform() === 'firefox';
  387. }
  388. return typeof InstallTrigger !== 'undefined';
  389. }
  390. /**
  391. * @method isSafari
  392. * @signature isSafari([forceActualPlatform])
  393. * @param {Boolean} forceActualPlatform
  394. * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
  395. * [ja][/ja]
  396. * @description
  397. * [en]Returns whether the browser is Safari. By default will return manually selected platform if it is set.[/en]
  398. * [ja]Safari上で実行されているかどうかを返します。[/ja]
  399. * @return {Boolean}
  400. */
  401. }, {
  402. key: 'isSafari',
  403. value: function isSafari(forceActualPlatform) {
  404. if (!forceActualPlatform && this._getSelectedPlatform()) {
  405. return this._getSelectedPlatform() === 'safari';
  406. }
  407. return Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0 || function (p) {
  408. return p.toString() === '[object SafariRemoteNotification]';
  409. }(!window['safari'] || safari.pushNotification);
  410. }
  411. /**
  412. * @method isChrome
  413. * @signature isChrome([forceActualPlatform])
  414. * @param {Boolean} forceActualPlatform
  415. * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
  416. * [ja][/ja]
  417. * @description
  418. * [en]Returns whether the browser is Chrome. By default will return manually selected platform if it is set.[/en]
  419. * [ja]Chrome上で実行されているかどうかを返します。[/ja]
  420. * @return {Boolean}
  421. */
  422. }, {
  423. key: 'isChrome',
  424. value: function isChrome(forceActualPlatform) {
  425. if (!forceActualPlatform && this._getSelectedPlatform()) {
  426. return this._getSelectedPlatform() === 'chrome';
  427. }
  428. return !!window.chrome && !(!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) && !(navigator.userAgent.indexOf(' Edge/') >= 0);
  429. }
  430. /**
  431. * @method isIE
  432. * @signature isIE([forceActualPlatform])
  433. * @param {Boolean} forceActualPlatform
  434. * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
  435. * [ja][/ja]
  436. * @description
  437. * [en]Returns whether the browser is Internet Explorer. By default will return manually selected platform if it is set.[/en]
  438. * [ja]Internet Explorer上で実行されているかどうかを返します。[/ja]
  439. * @return {Boolean}
  440. */
  441. }, {
  442. key: 'isIE',
  443. value: function isIE(forceActualPlatform) {
  444. if (!forceActualPlatform && this._getSelectedPlatform()) {
  445. return this._getSelectedPlatform() === 'ie';
  446. }
  447. return false || !!document.documentMode;
  448. }
  449. /**
  450. * @method isEdge
  451. * @signature isEdge([forceActualPlatform])
  452. * @param {Boolean} forceActualPlatform
  453. * [en]If true, selected platform is ignored and the actual platform is returned.[/en]
  454. * [ja][/ja]
  455. * @description
  456. * [en]Returns whether the browser is Edge. By default will return manually selected platform if it is set.[/en]
  457. * [ja]Edge上で実行されているかどうかを返します。[/ja]
  458. * @return {Boolean}
  459. */
  460. }, {
  461. key: 'isEdge',
  462. value: function isEdge(forceActualPlatform) {
  463. if (!forceActualPlatform && this._getSelectedPlatform()) {
  464. return this._getSelectedPlatform() === 'edge';
  465. }
  466. return navigator.userAgent.indexOf(' Edge/') >= 0;
  467. }
  468. //----------------
  469. // Utility functions
  470. //----------------
  471. /**
  472. * @return {String}
  473. */
  474. }, {
  475. key: 'getMobileOS',
  476. value: function getMobileOS() {
  477. if (this.isAndroid()) {
  478. return 'android';
  479. } else if (this.isIOS()) {
  480. return 'ios';
  481. } else if (this.isWP()) {
  482. return 'wp';
  483. } else {
  484. return 'other';
  485. }
  486. }
  487. /**
  488. * @return {String}
  489. */
  490. }, {
  491. key: 'getIOSDevice',
  492. value: function getIOSDevice() {
  493. if (this.isIPhone()) {
  494. return 'iphone';
  495. } else if (this.isIPad()) {
  496. return 'ipad';
  497. } else if (this.isIPod()) {
  498. return 'ipod';
  499. } else {
  500. return 'na';
  501. }
  502. }
  503. }]);
  504. return Platform;
  505. }();
  506. export default new Platform();