1 | import * as Util from './Util';
|
2 | import {svgCreate} from '../layer/vector/SVG.Util';
|
3 |
|
4 | /*
|
5 | * @namespace Browser
|
6 | * @aka L.Browser
|
7 | *
|
8 | * A namespace with static properties for browser/feature detection used by Leaflet internally.
|
9 | *
|
10 | * @example
|
11 | *
|
12 | * ```js
|
13 | * if (L.Browser.ielt9) {
|
14 | * alert('Upgrade your browser, dude!');
|
15 | * }
|
16 | * ```
|
17 | */
|
18 |
|
19 | var style = document.documentElement.style;
|
20 |
|
21 | // @property ie: Boolean; `true` for all Internet Explorer versions (not Edge).
|
22 | export var ie = 'ActiveXObject' in window;
|
23 |
|
24 | // @property ielt9: Boolean; `true` for Internet Explorer versions less than 9.
|
25 | export var ielt9 = ie && !document.addEventListener;
|
26 |
|
27 | // @property edge: Boolean; `true` for the Edge web browser.
|
28 | export var edge = 'msLaunchUri' in navigator && !('documentMode' in document);
|
29 |
|
30 | // @property webkit: Boolean;
|
31 | // `true` for webkit-based browsers like Chrome and Safari (including mobile versions).
|
32 | export var webkit = userAgentContains('webkit');
|
33 |
|
34 | // @property android: Boolean
|
35 | // `true` for any browser running on an Android platform.
|
36 | export var android = userAgentContains('android');
|
37 |
|
38 | // @property android23: Boolean; `true` for browsers running on Android 2 or Android 3.
|
39 | export var android23 = userAgentContains('android 2') || userAgentContains('android 3');
|
40 |
|
41 | /* See https://stackoverflow.com/a/17961266 for details on detecting stock Android */
|
42 | var webkitVer = parseInt(/WebKit\/([0-9]+)|$/.exec(navigator.userAgent)[1], 10); // also matches AppleWebKit
|
43 | // @property androidStock: Boolean; `true` for the Android stock browser (i.e. not Chrome)
|
44 | export var androidStock = android && userAgentContains('Google') && webkitVer < 537 && !('AudioNode' in window);
|
45 |
|
46 | // @property opera: Boolean; `true` for the Opera browser
|
47 | export var opera = !!window.opera;
|
48 |
|
49 | // @property chrome: Boolean; `true` for the Chrome browser.
|
50 | export var chrome = userAgentContains('chrome');
|
51 |
|
52 | // @property gecko: Boolean; `true` for gecko-based browsers like Firefox.
|
53 | export var gecko = userAgentContains('gecko') && !webkit && !opera && !ie;
|
54 |
|
55 | // @property safari: Boolean; `true` for the Safari browser.
|
56 | export var safari = !chrome && userAgentContains('safari');
|
57 |
|
58 | export var phantom = userAgentContains('phantom');
|
59 |
|
60 | // @property opera12: Boolean
|
61 | // `true` for the Opera browser supporting CSS transforms (version 12 or later).
|
62 | export var opera12 = 'OTransition' in style;
|
63 |
|
64 | // @property win: Boolean; `true` when the browser is running in a Windows platform
|
65 | export var win = navigator.platform.indexOf('Win') === 0;
|
66 |
|
67 | // @property ie3d: Boolean; `true` for all Internet Explorer versions supporting CSS transforms.
|
68 | export var ie3d = ie && ('transition' in style);
|
69 |
|
70 | // @property webkit3d: Boolean; `true` for webkit-based browsers supporting CSS transforms.
|
71 | export var webkit3d = ('WebKitCSSMatrix' in window) && ('m11' in new window.WebKitCSSMatrix()) && !android23;
|
72 |
|
73 | // @property gecko3d: Boolean; `true` for gecko-based browsers supporting CSS transforms.
|
74 | export var gecko3d = 'MozPerspective' in style;
|
75 |
|
76 | // @property any3d: Boolean
|
77 | // `true` for all browsers supporting CSS transforms.
|
78 | export var any3d = !window.L_DISABLE_3D && (ie3d || webkit3d || gecko3d) && !opera12 && !phantom;
|
79 |
|
80 | // @property mobile: Boolean; `true` for all browsers running in a mobile device.
|
81 | export var mobile = typeof orientation !== 'undefined' || userAgentContains('mobile');
|
82 |
|
83 | // @property mobileWebkit: Boolean; `true` for all webkit-based browsers in a mobile device.
|
84 | export var mobileWebkit = mobile && webkit;
|
85 |
|
86 | // @property mobileWebkit3d: Boolean
|
87 | // `true` for all webkit-based browsers in a mobile device supporting CSS transforms.
|
88 | export var mobileWebkit3d = mobile && webkit3d;
|
89 |
|
90 | // @property msPointer: Boolean
|
91 | // `true` for browsers implementing the Microsoft touch events model (notably IE10).
|
92 | export var msPointer = !window.PointerEvent && window.MSPointerEvent;
|
93 |
|
94 | // @property pointer: Boolean
|
95 | // `true` for all browsers supporting [pointer events](https://msdn.microsoft.com/en-us/library/dn433244%28v=vs.85%29.aspx).
|
96 | export var pointer = !webkit && !!(window.PointerEvent || msPointer);
|
97 |
|
98 | // @property touch: Boolean
|
99 | // `true` for all browsers supporting [touch events](https://developer.mozilla.org/docs/Web/API/Touch_events).
|
100 | // This does not necessarily mean that the browser is running in a computer with
|
101 | // a touchscreen, it only means that the browser is capable of understanding
|
102 | // touch events.
|
103 | export var touch = !window.L_NO_TOUCH && (pointer || 'ontouchstart' in window ||
|
104 | (window.DocumentTouch && document instanceof window.DocumentTouch));
|
105 |
|
106 | // @property mobileOpera: Boolean; `true` for the Opera browser in a mobile device.
|
107 | export var mobileOpera = mobile && opera;
|
108 |
|
109 | // @property mobileGecko: Boolean
|
110 | // `true` for gecko-based browsers running in a mobile device.
|
111 | export var mobileGecko = mobile && gecko;
|
112 |
|
113 | // @property retina: Boolean
|
114 | // `true` for browsers on a high-resolution "retina" screen or on any screen when browser's display zoom is more than 100%.
|
115 | export var retina = (window.devicePixelRatio || (window.screen.deviceXDPI / window.screen.logicalXDPI)) > 1;
|
116 |
|
117 | // @property passiveEvents: Boolean
|
118 | // `true` for browsers that support passive events.
|
119 | export var passiveEvents = (function () {
|
120 | var supportsPassiveOption = false;
|
121 | try {
|
122 | var opts = Object.defineProperty({}, 'passive', {
|
123 | get: function () {
|
124 | supportsPassiveOption = true;
|
125 | }
|
126 | });
|
127 | window.addEventListener('testPassiveEventSupport', Util.falseFn, opts);
|
128 | window.removeEventListener('testPassiveEventSupport', Util.falseFn, opts);
|
129 | } catch (e) {
|
130 | // Errors can safely be ignored since this is only a browser support test.
|
131 | }
|
132 | return supportsPassiveOption;
|
133 | });
|
134 |
|
135 | // @property canvas: Boolean
|
136 | // `true` when the browser supports [`<canvas>`](https://developer.mozilla.org/docs/Web/API/Canvas_API).
|
137 | export var canvas = (function () {
|
138 | return !!document.createElement('canvas').getContext;
|
139 | }());
|
140 |
|
141 | // @property svg: Boolean
|
142 | // `true` when the browser supports [SVG](https://developer.mozilla.org/docs/Web/SVG).
|
143 | export var svg = !!(document.createElementNS && svgCreate('svg').createSVGRect);
|
144 |
|
145 | // @property vml: Boolean
|
146 | // `true` if the browser supports [VML](https://en.wikipedia.org/wiki/Vector_Markup_Language).
|
147 | export var vml = !svg && (function () {
|
148 | try {
|
149 | var div = document.createElement('div');
|
150 | div.innerHTML = '<v:shape adj="1"/>';
|
151 |
|
152 | var shape = div.firstChild;
|
153 | shape.style.behavior = 'url(#default#VML)';
|
154 |
|
155 | return shape && (typeof shape.adj === 'object');
|
156 |
|
157 | } catch (e) {
|
158 | return false;
|
159 | }
|
160 | }());
|
161 |
|
162 |
|
163 | function userAgentContains(str) {
|
164 | return navigator.userAgent.toLowerCase().indexOf(str) >= 0;
|
165 | }
|