FeatureDetection-7bd32c34.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. /**
  2. * Cesium - https://github.com/AnalyticalGraphicsInc/cesium
  3. *
  4. * Copyright 2011-2017 Cesium Contributors
  5. *
  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. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * Columbus View (Pat. Pend.)
  19. *
  20. * Portions licensed separately.
  21. * See https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md for full licensing details.
  22. */
  23. define(['exports', './when-8d13db60'], function (exports, when) { 'use strict';
  24. var _supportsFullscreen;
  25. var _names = {
  26. requestFullscreen : undefined,
  27. exitFullscreen : undefined,
  28. fullscreenEnabled : undefined,
  29. fullscreenElement : undefined,
  30. fullscreenchange : undefined,
  31. fullscreenerror : undefined
  32. };
  33. /**
  34. * Browser-independent functions for working with the standard fullscreen API.
  35. *
  36. * @exports Fullscreen
  37. * @namespace
  38. *
  39. * @see {@link http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html|W3C Fullscreen Living Specification}
  40. */
  41. var Fullscreen = {};
  42. Object.defineProperties(Fullscreen, {
  43. /**
  44. * The element that is currently fullscreen, if any. To simply check if the
  45. * browser is in fullscreen mode or not, use {@link Fullscreen#fullscreen}.
  46. * @memberof Fullscreen
  47. * @type {Object}
  48. * @readonly
  49. */
  50. element : {
  51. get : function() {
  52. if (!Fullscreen.supportsFullscreen()) {
  53. return undefined;
  54. }
  55. return document[_names.fullscreenElement];
  56. }
  57. },
  58. /**
  59. * The name of the event on the document that is fired when fullscreen is
  60. * entered or exited. This event name is intended for use with addEventListener.
  61. * In your event handler, to determine if the browser is in fullscreen mode or not,
  62. * use {@link Fullscreen#fullscreen}.
  63. * @memberof Fullscreen
  64. * @type {String}
  65. * @readonly
  66. */
  67. changeEventName : {
  68. get : function() {
  69. if (!Fullscreen.supportsFullscreen()) {
  70. return undefined;
  71. }
  72. return _names.fullscreenchange;
  73. }
  74. },
  75. /**
  76. * The name of the event that is fired when a fullscreen error
  77. * occurs. This event name is intended for use with addEventListener.
  78. * @memberof Fullscreen
  79. * @type {String}
  80. * @readonly
  81. */
  82. errorEventName : {
  83. get : function() {
  84. if (!Fullscreen.supportsFullscreen()) {
  85. return undefined;
  86. }
  87. return _names.fullscreenerror;
  88. }
  89. },
  90. /**
  91. * Determine whether the browser will allow an element to be made fullscreen, or not.
  92. * For example, by default, iframes cannot go fullscreen unless the containing page
  93. * adds an "allowfullscreen" attribute (or prefixed equivalent).
  94. * @memberof Fullscreen
  95. * @type {Boolean}
  96. * @readonly
  97. */
  98. enabled : {
  99. get : function() {
  100. if (!Fullscreen.supportsFullscreen()) {
  101. return undefined;
  102. }
  103. return document[_names.fullscreenEnabled];
  104. }
  105. },
  106. /**
  107. * Determines if the browser is currently in fullscreen mode.
  108. * @memberof Fullscreen
  109. * @type {Boolean}
  110. * @readonly
  111. */
  112. fullscreen : {
  113. get : function() {
  114. if (!Fullscreen.supportsFullscreen()) {
  115. return undefined;
  116. }
  117. return Fullscreen.element !== null;
  118. }
  119. }
  120. });
  121. /**
  122. * Detects whether the browser supports the standard fullscreen API.
  123. *
  124. * @returns {Boolean} <code>true</code> if the browser supports the standard fullscreen API,
  125. * <code>false</code> otherwise.
  126. */
  127. Fullscreen.supportsFullscreen = function() {
  128. if (when.defined(_supportsFullscreen)) {
  129. return _supportsFullscreen;
  130. }
  131. _supportsFullscreen = false;
  132. var body = document.body;
  133. if (typeof body.requestFullscreen === 'function') {
  134. // go with the unprefixed, standard set of names
  135. _names.requestFullscreen = 'requestFullscreen';
  136. _names.exitFullscreen = 'exitFullscreen';
  137. _names.fullscreenEnabled = 'fullscreenEnabled';
  138. _names.fullscreenElement = 'fullscreenElement';
  139. _names.fullscreenchange = 'fullscreenchange';
  140. _names.fullscreenerror = 'fullscreenerror';
  141. _supportsFullscreen = true;
  142. return _supportsFullscreen;
  143. }
  144. //check for the correct combination of prefix plus the various names that browsers use
  145. var prefixes = ['webkit', 'moz', 'o', 'ms', 'khtml'];
  146. var name;
  147. for (var i = 0, len = prefixes.length; i < len; ++i) {
  148. var prefix = prefixes[i];
  149. // casing of Fullscreen differs across browsers
  150. name = prefix + 'RequestFullscreen';
  151. if (typeof body[name] === 'function') {
  152. _names.requestFullscreen = name;
  153. _supportsFullscreen = true;
  154. } else {
  155. name = prefix + 'RequestFullScreen';
  156. if (typeof body[name] === 'function') {
  157. _names.requestFullscreen = name;
  158. _supportsFullscreen = true;
  159. }
  160. }
  161. // disagreement about whether it's "exit" as per spec, or "cancel"
  162. name = prefix + 'ExitFullscreen';
  163. if (typeof document[name] === 'function') {
  164. _names.exitFullscreen = name;
  165. } else {
  166. name = prefix + 'CancelFullScreen';
  167. if (typeof document[name] === 'function') {
  168. _names.exitFullscreen = name;
  169. }
  170. }
  171. // casing of Fullscreen differs across browsers
  172. name = prefix + 'FullscreenEnabled';
  173. if (document[name] !== undefined) {
  174. _names.fullscreenEnabled = name;
  175. } else {
  176. name = prefix + 'FullScreenEnabled';
  177. if (document[name] !== undefined) {
  178. _names.fullscreenEnabled = name;
  179. }
  180. }
  181. // casing of Fullscreen differs across browsers
  182. name = prefix + 'FullscreenElement';
  183. if (document[name] !== undefined) {
  184. _names.fullscreenElement = name;
  185. } else {
  186. name = prefix + 'FullScreenElement';
  187. if (document[name] !== undefined) {
  188. _names.fullscreenElement = name;
  189. }
  190. }
  191. // thankfully, event names are all lowercase per spec
  192. name = prefix + 'fullscreenchange';
  193. // event names do not have 'on' in the front, but the property on the document does
  194. if (document['on' + name] !== undefined) {
  195. //except on IE
  196. if (prefix === 'ms') {
  197. name = 'MSFullscreenChange';
  198. }
  199. _names.fullscreenchange = name;
  200. }
  201. name = prefix + 'fullscreenerror';
  202. if (document['on' + name] !== undefined) {
  203. //except on IE
  204. if (prefix === 'ms') {
  205. name = 'MSFullscreenError';
  206. }
  207. _names.fullscreenerror = name;
  208. }
  209. }
  210. return _supportsFullscreen;
  211. };
  212. /**
  213. * Asynchronously requests the browser to enter fullscreen mode on the given element.
  214. * If fullscreen mode is not supported by the browser, does nothing.
  215. *
  216. * @param {Object} element The HTML element which will be placed into fullscreen mode.
  217. * @param {HMDVRDevice} [vrDevice] The VR device.
  218. *
  219. * @example
  220. * // Put the entire page into fullscreen.
  221. * Cesium.Fullscreen.requestFullscreen(document.body)
  222. *
  223. * // Place only the Cesium canvas into fullscreen.
  224. * Cesium.Fullscreen.requestFullscreen(scene.canvas)
  225. */
  226. Fullscreen.requestFullscreen = function(element, vrDevice) {
  227. if (!Fullscreen.supportsFullscreen()) {
  228. return;
  229. }
  230. element[_names.requestFullscreen]({ vrDisplay: vrDevice });
  231. };
  232. /**
  233. * Asynchronously exits fullscreen mode. If the browser is not currently
  234. * in fullscreen, or if fullscreen mode is not supported by the browser, does nothing.
  235. */
  236. Fullscreen.exitFullscreen = function() {
  237. if (!Fullscreen.supportsFullscreen()) {
  238. return;
  239. }
  240. document[_names.exitFullscreen]();
  241. };
  242. //For unit tests
  243. Fullscreen._names = _names;
  244. var theNavigator;
  245. if (typeof navigator !== 'undefined') {
  246. theNavigator = navigator;
  247. } else {
  248. theNavigator = {};
  249. }
  250. function extractVersion(versionString) {
  251. var parts = versionString.split('.');
  252. for (var i = 0, len = parts.length; i < len; ++i) {
  253. parts[i] = parseInt(parts[i], 10);
  254. }
  255. return parts;
  256. }
  257. var isChromeResult;
  258. var chromeVersionResult;
  259. function isChrome() {
  260. if (!when.defined(isChromeResult)) {
  261. isChromeResult = false;
  262. // Edge contains Chrome in the user agent too
  263. if (!isEdge()) {
  264. var fields = (/ Chrome\/([\.0-9]+)/).exec(theNavigator.userAgent);
  265. if (fields !== null) {
  266. isChromeResult = true;
  267. chromeVersionResult = extractVersion(fields[1]);
  268. }
  269. }
  270. }
  271. return isChromeResult;
  272. }
  273. function chromeVersion() {
  274. return isChrome() && chromeVersionResult;
  275. }
  276. var isSafariResult;
  277. var safariVersionResult;
  278. function isSafari() {
  279. if (!when.defined(isSafariResult)) {
  280. isSafariResult = false;
  281. // Chrome and Edge contain Safari in the user agent too
  282. if (!isChrome() && !isEdge() && (/ Safari\/[\.0-9]+/).test(theNavigator.userAgent)) {
  283. var fields = (/ Version\/([\.0-9]+)/).exec(theNavigator.userAgent);
  284. if (fields !== null) {
  285. isSafariResult = true;
  286. safariVersionResult = extractVersion(fields[1]);
  287. }
  288. }
  289. }
  290. return isSafariResult;
  291. }
  292. function safariVersion() {
  293. return isSafari() && safariVersionResult;
  294. }
  295. var isWebkitResult;
  296. var webkitVersionResult;
  297. function isWebkit() {
  298. if (!when.defined(isWebkitResult)) {
  299. isWebkitResult = false;
  300. var fields = (/ AppleWebKit\/([\.0-9]+)(\+?)/).exec(theNavigator.userAgent);
  301. if (fields !== null) {
  302. isWebkitResult = true;
  303. webkitVersionResult = extractVersion(fields[1]);
  304. webkitVersionResult.isNightly = !!fields[2];
  305. }
  306. }
  307. return isWebkitResult;
  308. }
  309. function webkitVersion() {
  310. return isWebkit() && webkitVersionResult;
  311. }
  312. var isInternetExplorerResult;
  313. var internetExplorerVersionResult;
  314. function isInternetExplorer() {
  315. if (!when.defined(isInternetExplorerResult)) {
  316. isInternetExplorerResult = false;
  317. var fields;
  318. if (theNavigator.appName === 'Microsoft Internet Explorer') {
  319. fields = /MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(theNavigator.userAgent);
  320. if (fields !== null) {
  321. isInternetExplorerResult = true;
  322. internetExplorerVersionResult = extractVersion(fields[1]);
  323. }
  324. } else if (theNavigator.appName === 'Netscape') {
  325. fields = /Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/.exec(theNavigator.userAgent);
  326. if (fields !== null) {
  327. isInternetExplorerResult = true;
  328. internetExplorerVersionResult = extractVersion(fields[1]);
  329. }
  330. }
  331. }
  332. return isInternetExplorerResult;
  333. }
  334. function internetExplorerVersion() {
  335. return isInternetExplorer() && internetExplorerVersionResult;
  336. }
  337. var isEdgeResult;
  338. var edgeVersionResult;
  339. function isEdge() {
  340. if (!when.defined(isEdgeResult)) {
  341. isEdgeResult = false;
  342. var fields = (/ Edge\/([\.0-9]+)/).exec(theNavigator.userAgent);
  343. if (fields !== null) {
  344. isEdgeResult = true;
  345. edgeVersionResult = extractVersion(fields[1]);
  346. }
  347. }
  348. return isEdgeResult;
  349. }
  350. function edgeVersion() {
  351. return isEdge() && edgeVersionResult;
  352. }
  353. var isFirefoxResult;
  354. var firefoxVersionResult;
  355. function isFirefox() {
  356. if (!when.defined(isFirefoxResult)) {
  357. isFirefoxResult = false;
  358. var fields = /Firefox\/([\.0-9]+)/.exec(theNavigator.userAgent);
  359. if (fields !== null) {
  360. isFirefoxResult = true;
  361. firefoxVersionResult = extractVersion(fields[1]);
  362. }
  363. }
  364. return isFirefoxResult;
  365. }
  366. var isWindowsResult;
  367. function isWindows() {
  368. if (!when.defined(isWindowsResult)) {
  369. isWindowsResult = /Windows/i.test(theNavigator.appVersion);
  370. }
  371. return isWindowsResult;
  372. }
  373. function firefoxVersion() {
  374. return isFirefox() && firefoxVersionResult;
  375. }
  376. var isNodeJsResult;
  377. function isNodeJs() {
  378. if (!when.defined(isNodeJsResult)) {
  379. isNodeJsResult = typeof process === 'object' && Object.prototype.toString.call(process) === '[object process]'; // eslint-disable-line
  380. }
  381. return isNodeJsResult;
  382. }
  383. var hasPointerEvents;
  384. function supportsPointerEvents() {
  385. if (!when.defined(hasPointerEvents)) {
  386. //While navigator.pointerEnabled is deprecated in the W3C specification
  387. //we still need to use it if it exists in order to support browsers
  388. //that rely on it, such as the Windows WebBrowser control which defines
  389. //PointerEvent but sets navigator.pointerEnabled to false.
  390. //Firefox disabled because of https://github.com/AnalyticalGraphicsInc/cesium/issues/6372
  391. hasPointerEvents = !isFirefox() && typeof PointerEvent !== 'undefined' && (!when.defined(theNavigator.pointerEnabled) || theNavigator.pointerEnabled);
  392. }
  393. return hasPointerEvents;
  394. }
  395. var imageRenderingValueResult;
  396. var supportsImageRenderingPixelatedResult;
  397. function supportsImageRenderingPixelated() {
  398. if (!when.defined(supportsImageRenderingPixelatedResult)) {
  399. var canvas = document.createElement('canvas');
  400. canvas.setAttribute('style',
  401. 'image-rendering: -moz-crisp-edges;' +
  402. 'image-rendering: pixelated;');
  403. //canvas.style.imageRendering will be undefined, null or an empty string on unsupported browsers.
  404. var tmp = canvas.style.imageRendering;
  405. supportsImageRenderingPixelatedResult = when.defined(tmp) && tmp !== '';
  406. if (supportsImageRenderingPixelatedResult) {
  407. imageRenderingValueResult = tmp;
  408. }
  409. }
  410. return supportsImageRenderingPixelatedResult;
  411. }
  412. function imageRenderingValue() {
  413. return supportsImageRenderingPixelated() ? imageRenderingValueResult : undefined;
  414. }
  415. var supportsWebPResult;
  416. var supportsWebPPromise;
  417. function supportsWebP() {
  418. // From https://developers.google.com/speed/webp/faq#how_can_i_detect_browser_support_for_webp
  419. if (when.defined(supportsWebPPromise)) {
  420. return supportsWebPPromise.promise;
  421. }
  422. supportsWebPPromise = when.when.defer();
  423. if (isEdge()) {
  424. // Edge's WebP support with WebGL is incomplete.
  425. // See bug report: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/19221241/
  426. supportsWebPResult = false;
  427. supportsWebPPromise.resolve(supportsWebPResult);
  428. }
  429. var image = new Image();
  430. image.onload = function () {
  431. supportsWebPResult = (image.width > 0) && (image.height > 0);
  432. supportsWebPPromise.resolve(supportsWebPResult);
  433. };
  434. image.onerror = function () {
  435. supportsWebPResult = false;
  436. supportsWebPPromise.resolve(supportsWebPResult);
  437. };
  438. image.src = 'data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA';
  439. return supportsWebPPromise.promise;
  440. }
  441. function supportsWebPSync() {
  442. if (!when.defined(supportsWebPPromise)) {
  443. supportsWebP();
  444. }
  445. return supportsWebPResult;
  446. }
  447. var typedArrayTypes = [];
  448. if (typeof ArrayBuffer !== 'undefined') {
  449. typedArrayTypes.push(Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array);
  450. if (typeof Uint8ClampedArray !== 'undefined') {
  451. typedArrayTypes.push(Uint8ClampedArray);
  452. }
  453. if (typeof CanvasPixelArray !== 'undefined') {
  454. typedArrayTypes.push(CanvasPixelArray);
  455. }
  456. }
  457. /**
  458. * A set of functions to detect whether the current browser supports
  459. * various features.
  460. *
  461. * @exports FeatureDetection
  462. */
  463. var FeatureDetection = {
  464. isChrome : isChrome,
  465. chromeVersion : chromeVersion,
  466. isSafari : isSafari,
  467. safariVersion : safariVersion,
  468. isWebkit : isWebkit,
  469. webkitVersion : webkitVersion,
  470. isInternetExplorer : isInternetExplorer,
  471. internetExplorerVersion : internetExplorerVersion,
  472. isEdge : isEdge,
  473. edgeVersion : edgeVersion,
  474. isFirefox : isFirefox,
  475. firefoxVersion : firefoxVersion,
  476. isWindows : isWindows,
  477. isNodeJs : isNodeJs,
  478. hardwareConcurrency : when.defaultValue(theNavigator.hardwareConcurrency, 3),
  479. supportsPointerEvents : supportsPointerEvents,
  480. supportsImageRenderingPixelated: supportsImageRenderingPixelated,
  481. supportsWebP: supportsWebP,
  482. supportsWebPSync: supportsWebPSync,
  483. imageRenderingValue: imageRenderingValue,
  484. typedArrayTypes: typedArrayTypes,
  485. isPCBroswer : isPCBroswer
  486. };
  487. /**
  488. * Detects whether the current browser supports the full screen standard.
  489. *
  490. * @returns {Boolean} true if the browser supports the full screen standard, false if not.
  491. *
  492. * @see Fullscreen
  493. * @see {@link http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html|W3C Fullscreen Living Specification}
  494. */
  495. FeatureDetection.supportsFullscreen = function() {
  496. return Fullscreen.supportsFullscreen();
  497. };
  498. /**
  499. * Detects whether the current browser supports typed arrays.
  500. *
  501. * @returns {Boolean} true if the browser supports typed arrays, false if not.
  502. *
  503. * @see {@link http://www.khronos.org/registry/typedarray/specs/latest/|Typed Array Specification}
  504. */
  505. FeatureDetection.supportsTypedArrays = function() {
  506. return typeof ArrayBuffer !== 'undefined';
  507. };
  508. /**
  509. * Detects whether the current browser supports Web Workers.
  510. *
  511. * @returns {Boolean} true if the browsers supports Web Workers, false if not.
  512. *
  513. * @see {@link http://www.w3.org/TR/workers/}
  514. */
  515. FeatureDetection.supportsWebWorkers = function() {
  516. return typeof Worker !== 'undefined';
  517. };
  518. /**
  519. * Detects whether the current browser supports Web Assembly.
  520. *
  521. * @returns {Boolean} true if the browsers supports Web Assembly, false if not.
  522. *
  523. * @see {@link https://developer.mozilla.org/en-US/docs/WebAssembly}
  524. */
  525. FeatureDetection.supportsWebAssembly = function() {
  526. return typeof WebAssembly !== 'undefined' && !FeatureDetection.isEdge();
  527. };
  528. /**
  529. * Detects whether the current browser supports OffscreenCanvas.
  530. * @returns {Boolean} true if the browsers supports OffscreenCanvas, false if not.
  531. */
  532. FeatureDetection.supportsOffscreenCanvas = function() {
  533. return typeof OffscreenCanvas !== 'undefined' && !FeatureDetection.isEdge();
  534. };
  535. function isPCBroswer() {
  536. var sUserAgent = window.navigator.userAgent.toLowerCase();
  537. var bIsIpad = sUserAgent.match(/ipad/i) == "ipad";
  538. var bIsIphoneOs = sUserAgent.match(/iphone os/i) == "iphone os";
  539. var bIsMidp = sUserAgent.match(/midp/i) == "midp";
  540. var bIsUc7 = sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4";
  541. var bIsUc = sUserAgent.match(/ucweb/i) == "ucweb";
  542. var bIsAndroid = sUserAgent.match(/android/i) == "android";
  543. var bIsCE = sUserAgent.match(/windows ce/i) == "windows ce";
  544. var bIsWM = sUserAgent.match(/windows mobile/i) == "windows mobile";
  545. if (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM) {
  546. return false;
  547. } else {
  548. return true;
  549. }
  550. }
  551. exports.FeatureDetection = FeatureDetection;
  552. });