Fixes #2715 - Adding Microsoft Edge UA string support to Browser.
[mootools.git] / Source / Browser / Browser.js
blob0d42a67f9c5e00f56f071e82720e523af37159b0
1 /*
2 ---
4 name: Browser
6 description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash.
8 license: MIT-style license.
10 requires: [Array, Function, Number, String]
12 provides: [Browser, Window, Document]
14 ...
17 (function(){
19 var document = this.document;
20 var window = document.window = this;
22 var parse = function(ua, platform){
23         ua = ua.toLowerCase();
24         platform = (platform ? platform.toLowerCase() : '');
26         // chrome is included in the edge UA, so need to check for edge first,
27         // before checking if it's chrome.
28         var UA = ua.match(/(edge)[\s\/:]([\w\d\.]+)/);
29         if (!UA){
30                 UA = ua.match(/(opera|ie|firefox|chrome|trident|crios|version)[\s\/:]([\w\d\.]+)?.*?(safari|(?:rv[\s\/:]|version[\s\/:])([\w\d\.]+)|$)/) || [null, 'unknown', 0];
31         }
33         if (UA[1] == 'trident'){
34                 UA[1] = 'ie';
35                 if (UA[4]) UA[2] = UA[4];
36         } else if (UA[1] == 'crios'){
37                 UA[1] = 'chrome';
38         }
40         platform = ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || ua.match(/mac|win|linux/) || ['other'])[0];
41         if (platform == 'win') platform = 'windows';
43         return {
44                 extend: Function.prototype.extend,
45                 name: (UA[1] == 'version') ? UA[3] : UA[1],
46                 version: parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]),
47                 platform: platform
48         };
51 var Browser = this.Browser = parse(navigator.userAgent, navigator.platform);
53 if (Browser.name == 'ie' && document.documentMode){
54         Browser.version = document.documentMode;
57 Browser.extend({
58         Features: {
59                 xpath: !!(document.evaluate),
60                 air: !!(window.runtime),
61                 query: !!(document.querySelector),
62                 json: !!(window.JSON)
63         },
64         parseUA: parse
65 });
67 //<1.4compat>
68 Browser[Browser.name] = true;
69 Browser[Browser.name + parseInt(Browser.version, 10)] = true;
71 if (Browser.name == 'ie' && Browser.version >= '11'){
72         delete Browser.ie;
75 var platform = Browser.platform;
76 if (platform == 'windows'){
77         platform = 'win';
79 Browser.Platform = {
80         name: platform
82 Browser.Platform[platform] = true;
83 //</1.4compat>
85 // Request
87 Browser.Request = (function(){
89         var XMLHTTP = function(){
90                 return new XMLHttpRequest();
91         };
93         var MSXML2 = function(){
94                 return new ActiveXObject('MSXML2.XMLHTTP');
95         };
97         var MSXML = function(){
98                 return new ActiveXObject('Microsoft.XMLHTTP');
99         };
101         return Function.attempt(function(){
102                 XMLHTTP();
103                 return XMLHTTP;
104         }, function(){
105                 MSXML2();
106                 return MSXML2;
107         }, function(){
108                 MSXML();
109                 return MSXML;
110         });
112 })();
114 Browser.Features.xhr = !!(Browser.Request);
116 //<1.4compat>
118 // Flash detection
120 var version = (Function.attempt(function(){
121         return navigator.plugins['Shockwave Flash'].description;
122 }, function(){
123         return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
124 }) || '0 r0').match(/\d+/g);
126 Browser.Plugins = {
127         Flash: {
128                 version: Number(version[0] || '0.' + version[1]) || 0,
129                 build: Number(version[2]) || 0
130         }
133 //</1.4compat>
135 // String scripts
137 Browser.exec = function(text){
138         if (!text) return text;
139         if (window.execScript){
140                 window.execScript(text);
141         } else {
142                 var script = document.createElement('script');
143                 script.setAttribute('type', 'text/javascript');
144                 script.text = text;
145                 document.head.appendChild(script);
146                 document.head.removeChild(script);
147         }
148         return text;
151 String.implement('stripScripts', function(exec){
152         var scripts = '';
153         var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){
154                 scripts += code + '\n';
155                 return '';
156         });
157         if (exec === true) Browser.exec(scripts);
158         else if (typeOf(exec) == 'function') exec(scripts, text);
159         return text;
162 // Window, Document
164 Browser.extend({
165         Document: this.Document,
166         Window: this.Window,
167         Element: this.Element,
168         Event: this.Event
171 this.Window = this.$constructor = new Type('Window', function(){});
173 this.$family = Function.from('window').hide();
175 Window.mirror(function(name, method){
176         window[name] = method;
179 this.Document = document.$constructor = new Type('Document', function(){});
181 document.$family = Function.from('document').hide();
183 Document.mirror(function(name, method){
184         document[name] = method;
187 document.html = document.documentElement;
188 if (!document.head) document.head = document.getElementsByTagName('head')[0];
190 if (document.execCommand) try {
191         document.execCommand("BackgroundImageCache", false, true);
192 } catch (e){}
194 /*<ltIE9>*/
195 if (this.attachEvent && !this.addEventListener){
196         var unloadEvent = function(){
197                 this.detachEvent('onunload', unloadEvent);
198                 document.head = document.html = document.window = null;
199                 window = this.Window = document = null;
200         };
201         this.attachEvent('onunload', unloadEvent);
204 // IE fails on collections and <select>.options (refers to <select>)
205 var arrayFrom = Array.from;
206 try {
207         arrayFrom(document.html.childNodes);
208 } catch(e){
209         Array.from = function(item){
210                 if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){
211                         var i = item.length, array = new Array(i);
212                         while (i--) array[i] = item[i];
213                         return array;
214                 }
215                 return arrayFrom(item);
216         };
218         var prototype = Array.prototype,
219                 slice = prototype.slice;
220         ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){
221                 var method = prototype[name];
222                 Array[name] = function(item){
223                         return method.apply(Array.from(item), slice.call(arguments, 1));
224                 };
225         });
227 /*</ltIE9>*/
229 //<1.2compat>
231 if (Browser.Platform.ios) Browser.Platform.ipod = true;
233 Browser.Engine = {};
235 var setEngine = function(name, version){
236         Browser.Engine.name = name;
237         Browser.Engine[name + version] = true;
238         Browser.Engine.version = version;
241 if (Browser.ie){
242         Browser.Engine.trident = true;
244         switch (Browser.version){
245                 case 6: setEngine('trident', 4); break;
246                 case 7: setEngine('trident', 5); break;
247                 case 8: setEngine('trident', 6);
248         }
251 if (Browser.firefox){
252         Browser.Engine.gecko = true;
254         if (Browser.version >= 3) setEngine('gecko', 19);
255         else setEngine('gecko', 18);
258 if (Browser.safari || Browser.chrome){
259         Browser.Engine.webkit = true;
261         switch (Browser.version){
262                 case 2: setEngine('webkit', 419); break;
263                 case 3: setEngine('webkit', 420); break;
264                 case 4: setEngine('webkit', 525);
265         }
268 if (Browser.opera){
269         Browser.Engine.presto = true;
271         if (Browser.version >= 9.6) setEngine('presto', 960);
272         else if (Browser.version >= 9.5) setEngine('presto', 950);
273         else setEngine('presto', 925);
276 if (Browser.name == 'unknown'){
277         switch ((navigator.userAgent.toLowerCase().match(/(?:webkit|khtml|gecko)/) || [])[0]){
278                 case 'webkit':
279                 case 'khtml':
280                         Browser.Engine.webkit = true;
281                 break;
282                 case 'gecko':
283                         Browser.Engine.gecko = true;
284         }
287 this.$exec = Browser.exec;
289 //</1.2compat>
291 })();