-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbrowserDetect.js
271 lines (266 loc) · 12.4 KB
/
browserDetect.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
//detects which browser the user is using and stores in var Browserinfo//
var browserDetect = {
init: function () {
this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
this.version = this.searchVersion(navigator.userAgent) ||
this.searchVersion(navigator.appVersion) ||
"an unknown version";
this.OS = this.searchString(this.dataOS) || "an unknown OS";
},
searchString: function (data) {
for (var i = 0; i < data.length; i++) {
var dataString = data[i].string;
var dataProp = data[i].prop;
this.versionSearchString = data[i].versionSearch || data[i].identity;
if (dataString) {
if (dataString.indexOf(data[i].subString) != -1)
return data[i].identity;
} else if (dataProp)
return data[i].identity;
}
},
searchVersion: function (dataString) {
var index = dataString.indexOf(this.versionSearchString);
if (index == -1) return;
return parseFloat(dataString.substring(index + this.versionSearchString.length + 1));
},
dataBrowser: [{
string: navigator.userAgent,
subString: "Edge",
identity: "Edge"
}, {
string: navigator.userAgent,
subString: "Chrome",
identity: "Chrome"
}, {
string: navigator.userAgent,
subString: "OmniWeb",
versionSearch: "OmniWeb/",
identity: "OmniWeb"
}, {
string: navigator.vendor,
subString: "Apple",
identity: "Safari",
versionSearch: "Version"
}, {
prop: window.opera,
identity: "Opera",
versionSearch: "Version"
}, {
string: navigator.vendor,
subString: "iCab",
identity: "iCab"
}, {
string: navigator.vendor,
subString: "KDE",
identity: "Konqueror"
}, {
string: navigator.userAgent,
subString: "Firefox",
identity: "Firefox"
}, {
string: navigator.vendor,
subString: "Camino",
identity: "Camino"
}, { // for newer Netscapes (6+)
string: navigator.userAgent,
subString: "Netscape",
identity: "Netscape"
}, {
string: navigator.userAgent,
subString: "MSIE",
identity: "Explorer",
versionSearch: "MSIE"
}, {
string: navigator.userAgent,
subString: "Gecko",
identity: "Mozilla",
versionSearch: "rv"
}, { // for older Netscapes (4-)
string: navigator.userAgent,
subString: "Mozilla",
identity: "Netscape",
versionSearch: "Mozilla"
}],
dataOS: [{
string: navigator.platform,
subString: "Win",
identity: "Windows"
}, {
string: navigator.platform,
subString: "Mac",
identity: "Mac"
}, {
string: navigator.userAgent,
subString: "iPhone",
identity: "iPhone/iPod"
}, {
string: navigator.platform,
subString: "Linux",
identity: "Linux"
}]
};
// The script
//
// Copy this script into your JavaScript files. It works immediately, and you can query three properties of the BrowserDetect object:
//
// Browser name: BrowserDetect.browser
// Browser version: BrowserDetect.version
// OS name: BrowserDetect.OS
// This script will only continue to work if you regularly check whether newer browsers still follow the rules set forth in the dataBrowser and dataOS arrays.
//
// Browser detection
//
// The dataBrowser array is filled with objects that contain the properties that help the script detect your users' browser. Note its general syntax:
//
// dataBrowser: [
// {
// prop: window.opera,
// identity: "Opera",
// versionSearch: "Version" // note: no comma
// },
// {
// string: navigator.userAgent,
// subString: "MSIE",
// identity: "Explorer",
// versionSearch: "MSIE" // note: no comma
// } // note: no comma
// ];
// The [] define an array literal, and all of its elements are object literals. Each object literal is enclosed in curly braces {} and contains a few properties (name: value,). Note that a comma between the objects and between the properties is required, but that the last comma is always forbidden.
//
// Properties
//
// Every object in the dataBrowser array can contain the following properties:
//
// string and subString properties. These say: "search for subString in string". If the subString is found, the browser is identified.
// a prop property. It says "see if prop is supported". If it is, the browser is identified.
// an identity string. This string becomes the value of BrowserDetect.browser.
// a versionSearch string. This is for searching for the version number (see below). If this property is absent, the identity string is used instead.
// Every object must contain either 1 or 2 (never both!), must contain 3 and may contain 4.
//
// Example: Safari
//
// As an example, here's the Safari object:
//
// {
// string: navigator.vendor,
// subString: "Apple",
// identity: "Safari"
// },
// The script takes the value of navigator.vendor and sees if it contains the string "Apple". If it does, BrowserDetect.browser is set to "Safari" and the browser detection quits. If it doesn't, the script moves on to the next object.
//
// Example: Opera
//
// The next object is Opera:
//
// {
// prop: window.opera,
// identity: "Opera",
// versionSearch: "Version"
// },
// Here the script checks if the property window.opera exists. If it does, BrowserDetect.browser is set to "Opera". If it doesn't, the script moves on to the next object.
//
// If the browser turns out to be Opera the script looks for version information after the "Version" string.
//
// userAgent and vendor
//
// The trick of browser detection is knowing where to look for the information you need. Traditionally we use navigator.userAgent. However, precisely because this check is traditional many minor browsers change their navigator.userAgent string so that bad detects written by amateur web developers are fooled into identifying it as Explorer. Section 3D of the book discusses this problem, as well as some gory details of navigator.userAgent.
//
// More recently, new browsers have started to support the navigator.vendor property, which contains information about the vendor. In general I prefer to use this string for my detection, since it's less contaminated by obfuscation.
//
// Of course, as soon as amateurs start using my detection script to detect Safari, Opera, Konqueror or other browsers, the browser vendors will be forced to change the value of navigator.vendor and my detect will not work any more.
//
// Detection order
//
// The objects in dataBrowser are used in the order they appear; that's why dataBrowser is an array. As soon as a positive identification is made the script ends, and it doesn't check the remaining objects.
//
// Detection order is very important. The general rule is that you check for the minor browsers first. The reason is that many minor browsers give their users the opportunity to change identity in order to work around browser detects.
//
// For instance, the Opera navigator.userAgent may contain "MSIE". If we'd check for Explorer first, we'd find the "MSIE" and would incorrectly conclude that the browser is Explorer. In order to avoid this false detection, we should check for Opera first. If the browser is in fact Opera, the script never proceeds to the "MSIE" check.
//
// Safari's navigator.userAgent also contains "Gecko". This causes the same problem: a check for Mozilla would reveal "Gecko", and Safari would be identified as Mozilla. Therefore the Mozilla check only takes place if the browser is not Safari.
//
// If you add a new object to detect a new browser, always add it before the Explorer/Mozilla objects at the end of the array.
//
// Version number
//
// In general, the version number of a browser can be found directly after its name in navigator.userAgent. The script searches for this name and takes the number that appears after it. For instance, this is Konqueror's navigator.userAgent:
//
// Mozilla/5.0 (compatible; Konqueror/3; Linux)
// The script searches for the string "Konqueror", skips the next character, and takes the number after that. This is the version number. The script uses parseFloat, so that decimal places in the version number also become part of BrowserDetect.version.
//
// Unfortunately Safari's string never contains its official version; only its internal Apple version number (ie. not 1.3.2 but 312.6). Therefore the version number detect doesn't work in Safari. Since this is clearly Apple's fault (it doesn't follow established conventions), I don't care.
//
// versionSearch
//
// In general, the browser name as it appears in navigator.userAgent is the same as the identification string. If the browser is "iCab", the script searches for "iCab".
//
// However, Explorer needs "MSIE", Mozilla needs "rv", and older Netscape versions need "Mozilla". In order to accomodate these problems you may add a versionSearch property to the browser object. If it's there it's used for the version detect; if it's not there the identity string is used instead.
//
// Take the Firefox and Explorer objects:
//
// {
// string: navigator.userAgent,
// subString: "Firefox",
// identity: "Firefox"
// },
// {
// string: navigator.userAgent,
// subString: "MSIE",
// identity: "Explorer",
// versionSearch: "MSIE"
// },
// If the browser is Firefox, the script should look for the "Firefox" string. Since this is also the browser identity string, a special versionSearch is not necessary.
//
// Explorer, however, puts its version number after the string "MSIE". Since I use "Explorer" as identity string, I have to define the versionSearch property as "MSIE".
//
// userAgent and appVersion
//
// The version detect script searches for the browser name in both navigator.userAgent and navigator.appVersion. The reason is iCab: this browser's navigator.userAgent may not contain the string "iCab", but navigator.appVersion always does.
//
// Operating system
//
// The OS detect works the same as the browser detect. Currently all my OS detects use navigator.platform, since this property appears to always contain the correct information.
//
// navigator
//
// Below you see the objects contained by the object navigator. These variables can be read out and give information about the browser and computer of your users. Use this information to add new objects to the browser detect.
//
//
// navigator.vendorSub =
// navigator.productSub = 20030107
// navigator.vendor = Google Inc.
// navigator.maxTouchPoints = 0
// navigator.hardwareConcurrency = 4
// navigator.cookieEnabled = true
// navigator.appCodeName = Mozilla
// navigator.appName = Netscape
// navigator.appVersion = 5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36
// navigator.platform = MacIntel
// navigator.product = Gecko
// navigator.userAgent = Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36
// navigator.language = en-US
// navigator.languages = en-US,en
// navigator.onLine = true
// navigator.doNotTrack = null
// navigator.geolocation = [object Geolocation]
// navigator.mediaDevices = [object MediaDevices]
// navigator.plugins = [object PluginArray]
// navigator.mimeTypes = [object MimeTypeArray]
// navigator.webkitTemporaryStorage = [object DeprecatedStorageQuota]
// navigator.webkitPersistentStorage = [object DeprecatedStorageQuota]
// navigator.serviceWorker = [object ServiceWorkerContainer]
// navigator.getBattery = function getBattery() { [native code] }
// navigator.sendBeacon = function sendBeacon() { [native code] }
// navigator.getGamepads = function getGamepads() { [native code] }
// navigator.webkitGetUserMedia = function webkitGetUserMedia() { [native code] }
// navigator.javaEnabled = function javaEnabled() { [native code] }
// navigator.vibrate = function vibrate() { [native code] }
// navigator.requestMIDIAccess = function requestMIDIAccess() { [native code] }
// navigator.budget = [object BudgetService]
// navigator.permissions = [object Permissions]
// navigator.presentation = [object Presentation]
// navigator.bluetooth = [object Bluetooth]
// navigator.getUserMedia = function getUserMedia() { [native code] }
// navigator.registerProtocolHandler = function registerProtocolHandler() { [native code] }
// navigator.unregisterProtocolHandler = function unregisterProtocolHandler() { [native code] }