/** * Env.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ import { URL } from '@ephox/sand'; /** * This class contains various environment constants like browser versions etc. * Normally you don't want to sniff specific browser versions but sometimes you have * to when it's impossible to feature detect. So use this with care. * * @class tinymce.Env * @static */ const nav = navigator, userAgent = nav.userAgent; let opera, webkit, ie, ie11, ie12, gecko, mac, iDevice, android, fileApi, phone, tablet, windowsPhone; const matchMediaQuery = function (query) { return 'matchMedia' in window ? matchMedia(query).matches : false; }; opera = false; android = /Android/.test(userAgent); webkit = /WebKit/.test(userAgent); ie = !webkit && !opera && (/MSIE/gi).test(userAgent) && (/Explorer/gi).test(nav.appName); ie = ie && /MSIE (\w+)\./.exec(userAgent)[1]; ie11 = userAgent.indexOf('Trident/') !== -1 && (userAgent.indexOf('rv:') !== -1 || nav.appName.indexOf('Netscape') !== -1) ? 11 : false; ie12 = (userAgent.indexOf('Edge/') !== -1 && !ie && !ie11) ? 12 : false; ie = ie || ie11 || ie12; gecko = !webkit && !ie11 && /Gecko/.test(userAgent); mac = userAgent.indexOf('Mac') !== -1; iDevice = /(iPad|iPhone)/.test(userAgent); fileApi = 'FormData' in window && 'FileReader' in window && 'URL' in window && !!URL.createObjectURL; phone = matchMediaQuery('only screen and (max-device-width: 480px)') && (android || iDevice); tablet = matchMediaQuery('only screen and (min-width: 800px)') && (android || iDevice); windowsPhone = userAgent.indexOf('Windows Phone') !== -1; if (ie12) { webkit = false; } // Is a iPad/iPhone and not on iOS5 sniff the WebKit version since older iOS WebKit versions // says it has contentEditable support but there is no visible caret. const contentEditable = !iDevice || fileApi || parseInt(userAgent.match(/AppleWebKit\/(\d*)/)[1], 10) >= 534; export default { /** * Constant that is true if the browser is Opera. * * @property opera * @type Boolean * @final */ opera, /** * Constant that is true if the browser is WebKit (Safari/Chrome). * * @property webKit * @type Boolean * @final */ webkit, /** * Constant that is more than zero if the browser is IE. * * @property ie * @type Boolean * @final */ ie, /** * Constant that is true if the browser is Gecko. * * @property gecko * @type Boolean * @final */ gecko, /** * Constant that is true if the os is Mac OS. * * @property mac * @type Boolean * @final */ mac, /** * Constant that is true if the os is iOS. * * @property iOS * @type Boolean * @final */ iOS: iDevice, /** * Constant that is true if the os is android. * * @property android * @type Boolean * @final */ android, /** * Constant that is true if the browser supports editing. * * @property contentEditable * @type Boolean * @final */ contentEditable, /** * Transparent image data url. * * @property transparentSrc * @type Boolean * @final */ transparentSrc: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7', /** * Returns true/false if the browser can or can't place the caret after a inline block like an image. * * @property noCaretAfter * @type Boolean * @final */ caretAfter: ie !== 8, /** * Constant that is true if the browser supports native DOM Ranges. IE 9+. * * @property range * @type Boolean */ range: window.getSelection && 'Range' in window, /** * Returns the IE document mode for non IE browsers this will fake IE 10. * * @property documentMode * @type Number */ documentMode: ie && !ie12 ? (( document).documentMode || 7) : 10, /** * Constant that is true if the browser has a modern file api. * * @property fileApi * @type Boolean */ fileApi, /** * Constant that is true if the browser supports contentEditable=false regions. * * @property ceFalse * @type Boolean */ ceFalse: (ie === false || ie > 8), cacheSuffix: null, container: null, overrideViewPort: null, experimentalShadowDom: false, /** * Constant if CSP mode is possible or not. Meaning we can't use script urls for the iframe. */ canHaveCSP: (ie === false || ie > 11), desktop: !phone && !tablet, windowsPhone };