diff --git a/CHANGELOG b/CHANGELOG index 8e7a79a..5bf716e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* Add unified Browser detection by providing Prototype.Browser.(IE|Gecko|WebKit|Opera) booleans. Closes #6800. [savetheclocktower] + * Add String.prototype.empty and String.prototype.blank (tests if empty or whitespace-only). Closes #7016. [Jonathan Viney, Thomas Fuchs] * Update README to reflect new URLs, update LICENSE copyright years. Closes #7426. [Tobie Langel] diff --git a/src/array.js b/src/array.js index dbf036d..9271f6a 100644 --- a/src/array.js +++ b/src/array.js @@ -96,7 +96,7 @@ function $w(string){ return string ? string.split(/\s+/) : []; } -if(window.opera){ +if(Prototype.Browser.Opera){ Array.prototype.concat = function(){ var array = []; for(var i = 0, length = this.length; i < length; i++) array.push(this[i]); diff --git a/src/dom.js b/src/dom.js index 046f96f..0c0a83a 100644 --- a/src/dom.js +++ b/src/dom.js @@ -479,7 +479,7 @@ Element.Methods.Simulated = { Element.Methods.ByTag = {}; // IE is missing .innerHTML support for TABLE-related elements -if (document.all && !window.opera){ +if (Prototype.Browser.IE){ Element.Methods.update = function(element, html) { element = $(element); html = typeof html == 'undefined' ? '' : html.toString(); diff --git a/src/event.js b/src/event.js index 2b4644c..e8da7c8 100644 --- a/src/event.js +++ b/src/event.js @@ -83,8 +83,7 @@ Object.extend(Event, { useCapture = useCapture || false; if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.attachEvent)) + (Prototype.Browser.WebKit || element.attachEvent)) name = 'keydown'; Event._observeAndCache(element, name, observer, useCapture); @@ -95,8 +94,7 @@ Object.extend(Event, { useCapture = useCapture || false; if (name == 'keypress' && - (navigator.appVersion.match(/Konqueror|Safari|KHTML/) - || element.detachEvent)) + (Prototype.Browser.WebKit || element.attachEvent)) name = 'keydown'; if (element.removeEventListener) { @@ -110,5 +108,5 @@ Object.extend(Event, { }); /* prevent memory leaks in IE */ -if (navigator.appVersion.match(/\bMSIE\b/)) +if (Prototype.Browser.IE) Event.observe(window, 'unload', Event.unloadCache, false); diff --git a/src/position.js b/src/position.js index cab42a2..e099ac8 100644 --- a/src/position.js +++ b/src/position.js @@ -110,7 +110,7 @@ var Position = { valueL += element.offsetLeft || 0; // Safari fix - if (element.offsetParent==document.body) + if (element.offsetParent == document.body) if (Element.getStyle(element,'position')=='absolute') break; } while (element = element.offsetParent); @@ -206,7 +206,7 @@ var Position = { // Safari returns margins on body which is incorrect if the child is absolutely // positioned. For performance reasons, redefine Position.cumulativeOffset for // KHTML/WebKit only. -if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { +if (Prototype.Browser.WebKit) { Position.cumulativeOffset = function(element) { var valueT = 0, valueL = 0; do { diff --git a/src/prototype.js b/src/prototype.js index 37c8fee..242cf30 100644 --- a/src/prototype.js +++ b/src/prototype.js @@ -2,6 +2,13 @@ var Prototype = { Version: '<%= PROTOTYPE_VERSION %>', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 + }, BrowserFeatures: { XPath: !!document.evaluate, ElementExtensions: !!window.HTMLElement, diff --git a/test/unit/base.html b/test/unit/base.html index fbd5269..c5e7ddf 100644 --- a/test/unit/base.html +++ b/test/unit/base.html @@ -123,7 +123,49 @@ this.assertEqual.bind(this,arg3), arg1, arg2, arg3 ); call(eventTest); } - } + }, + + testBrowserDetection: function() {with(this) { + var results = $H(Prototype.Browser).map(function(engine){ + return engine; + }).partition(function(engine){ + return engine[1] === true + }); + var trues = results[0], falses = results[1]; + + info('User agent string is: ' + navigator.userAgent); + + assert(trues.size() == 0 || trues.size() == 1, + 'There should be only one or no browser detected.'); + + // we should have definite trues or falses here + trues.each(function(result){ + assert(result[1] === true); + }); + falses.each(function(result){ + assert(result[1] === false); + }); + + if(navigator.userAgent.indexOf('AppleWebKit/') > -1) { + info('Running on WebKit'); + assert(Prototype.Browser.WebKit); + } + + if(!!window.opera) { + info('Running on Opera'); + assert(Prototype.Browser.Opera); + } + + if(!!(window.attachEvent && !window.opera)) { + info('Running on IE'); + assert(Prototype.Browser.IE); + } + + if(navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1) { + info('Running on Gecko'); + assert(Prototype.Browser.Gecko); + } + }} }, 'testlog');