b471c09f7749c2a04f8e3485f2797ca55944c9fb
tdreszer
  Thu Jul 24 16:13:09 2014 -0700
Fixed many of the problems with IE version 11 going undetected. Redmine #13422.
diff --git src/hg/js/utils.js src/hg/js/utils.js
index 51bfe41..3963c35 100644
--- src/hg/js/utils.js
+++ src/hg/js/utils.js
@@ -97,30 +97,162 @@
 function normed(thing)
 {   // RETURNS undefined, the lone member of the set or the full set if more than one member.
     // Used for normalizing returns from jquery DOM selects (e.g. $('tr.track').children('td.data'))
     // jquery returns an "array like 'object'" with 0 or more entries.  
     // May be used on non-jquery objects and will reduce single element arrays to the element.
     // Use this to treat 0 entries the same as undefined and 1 entry as the item itself
     if (typeof(thing) === 'undefined' || thing === null
     ||  (thing.length !== undefined && thing.length === 0)  // Empty array (or 'array like object')
     ||  ($.isPlainObject(thing) && $.isEmptyObject(thing))) // Empty simple object
         return undefined;
     if (thing.length && thing.length === 1 && jQuery.type(thing) !== 'string') // string is overkill
         return thing[0]; // Container of one item should return the item itself.
     return thing;
 }
 
+var theClient = (function() {
+// Object that detects client browser if requested              
+    
+    // - - - - - Private variables and/or methods - - - - - 
+    var ieVersion = null;
+    var browserNamed = null;
+    
+    // - - - - - Public methods - - - - - 
+    return { // returns an object with public methods
+    
+        getIeVersion: function ()
+        { // Adapted from the web: stackOverflow.com answer by Joachim Isaksson
+            if (ieVersion === null) {
+                ieVersion = -1.0;
+                var re = null;
+                if (navigator.appName === 'Microsoft Internet Explorer') {
+                    browserNamed = 'MSIE';
+                    re = new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})");
+                    if (re.exec(navigator.userAgent) !== null)
+                        ieVersion = parseFloat( RegExp.$1 );
+                } else if (navigator.appName === 'Netscape') {
+                    re = new RegExp("Trident/.*rv:([0-9]{1,}[.0-9]{0,})");
+                    if (re.exec(navigator.userAgent) !== null) {
+                        browserNamed = 'MSIE';
+                        ieVersion = parseFloat( RegExp.$1 );
+                    }
+                }
+            }
+            return ieVersion;
+        },
+        
+        isIePre11: function ()
+        {
+            var ieVersion = theClient.getIeVersion();
+            if ( ieVersion !== -1.0 && ieVersion < 11.0 )
+                return true;
+            return false;
+        },
+        
+        isIePost11: function ()
+        {
+            if (theClient.getIeVersion() >= 11.0 )
+                return true;
+            return false;
+        },
+        
+        isIe: function ()
+        {
+            if (theClient.getIeVersion() === -1.0 )
+                return false;
+            return true;
+        },
+        
+        isChrome: function () 
+        {
+            if (browserNamed !== null)
+                return (browserNamed === 'Chrome');
+            
+            if (navigator.userAgent.indexOf("Chrome") !== -1) {
+                browserNamed = 'Chrome';
+                return true;
+            }
+            return false;
+        },
+        
+        isNetscape: function () 
+        {   // IE sometimes mimics netscape
+            if (browserNamed !== null)
+                return (browserNamed === 'Netscape');
+        
+            if (navigator.appName === 'Netscape'
+            &&  navigator.userAgent.indexOf("Trident") === -1) {
+                browserNamed = 'Netscape';
+                return true;
+            }
+            return false;
+        },
+        
+        isFirefox: function () 
+        {
+            if (browserNamed !== null)
+                return (browserNamed === 'FF');
+            
+            if (navigator.userAgent.indexOf("Firefox") !== -1) {
+                browserNamed = 'FF';
+                return true;
+            }
+            return false;
+        },
+        
+        isSafari: function () 
+        {   // Chrome sometimes mimics Safari
+            if (browserNamed !== null)
+                return (browserNamed === 'Safari');
+            
+            if (navigator.userAgent.indexOf("Safari") !== -1 
+            &&  navigator.userAgent.indexOf('Chrome') === -1) {
+                browserNamed = 'Safari';
+                return true;
+            }
+            return false;
+        },
+        
+        isOpera: function () 
+        {
+            if (browserNamed !== null)
+                return (browserNamed === 'Opera');
+            
+            if (navigator.userAgent.indexOf("Presto") !== -1) {
+                browserNamed = 'Opera';
+                return true;
+            }
+            return false;
+        },
+        
+        nameIs: function () 
+        {   // simple enough, this needs no comment!
+            if (browserNamed === null
+            &&  theClient.isChrome() === false   // Looking in the order of popularity
+            &&  theClient.isFirefox() === false
+            &&  theClient.isIe()       === false
+            &&  theClient.isSafari()    === false
+            &&  theClient.isOpera()      === false
+            &&  theClient.isNetscape()    === false)
+                browserNamed = navigator.appName; // Don't know what else to look for.
+            
+            return browserNamed;
+        }
+
+    };
+}());
+
 function waitCursor(obj)  // DEAD CODE?
 {
     //document.body.style.cursor="wait"
     obj.style.cursor="wait";
 }
 
 function endWaitCursor(obj)  // DEAD CODE?
 {
     obj.style.cursor="";
 }
 
 function getURLParam()
 {
 // Retrieve variable value from an url.
 // Can be called either:
@@ -289,31 +421,31 @@
 {
     return (!isNaN(parseInt(s)) && isFinite(s) && s.toString().indexOf('.') < 0);
 }
 function isFloat(s)
 {
     return (!isNaN(parseFloat(s)) && isFinite(s));
 }
 
 function validateInt(obj,min,max)
 {   // validates an integer which may be restricted to a range (if min and/or max are numbers)
     var title = obj.title;
     var rangeMin=parseInt(min);
     var rangeMax=parseInt(max);
     if (title.length === 0)
         title = "Value";
-    var popup=( $.browser.msie === false );
+    var popup=( theClient.isIePre11() === false );
     for (;;) {
         if ((obj.value === undefined || obj.value === null || obj.value === "") 
         &&  isInteger(obj.defaultValue))
             obj.value = obj.defaultValue;
         if (!isInteger(obj.value)) {
             if (popup) {
                 obj.value = prompt(title +" is invalid.\nMust be an integer.",obj.value);
                 continue;
             } else {
                 alert(title +" of '"+obj.value +"' is invalid.\nMust be an integer.");
                 obj.value = obj.defaultValue;
                 return false;
             }
         }
         var val = parseInt(obj.value);
@@ -356,31 +488,31 @@
                     return false;
                 }
             }
         }
         return true;
     }
 }
 
 function validateFloat(obj,min,max)
 {   // validates an float which may be restricted to a range (if min and/or max are numbers)
     var title = obj.title;
     var rangeMin=parseFloat(min);
     var rangeMax=parseFloat(max);
     if (title.length === 0)
         title = "Value";
-    var popup=( $.browser.msie === false );
+    var popup=( theClient.isIePre11() === false );
     for (;;) {
         if ((obj.value === undefined || obj.value === null || obj.value === "") 
         &&  isFloat(obj.defaultValue))
             obj.value = obj.defaultValue;
         if (!isFloat(obj.value)) {
             if (popup) {
                 obj.value = prompt(title +" is invalid.\nMust be a number.",obj.value);
                 continue;
             } else {
                 alert(title +" of '"+obj.value +"' is invalid.\nMust be a number."); // try a prompt box!
                 obj.value = obj.defaultValue;
                 return false;
             }
         }
         var val = parseFloat(obj.value);
@@ -1026,31 +1158,31 @@
 }
 
 function waitMaskSetup(timeOutInMs)
 { // Sets up the waitMask to block page manipulation until cleared
 
     // Find or create the waitMask (which masks the whole page)
     var  waitMask = normed($('#waitMask'));
     if (!waitMask) {
         // create the waitMask
         $("body").append("<div id='waitMask' class='waitMask');'></div>");
         waitMask = normed($('#waitMask'));
     }
     $(waitMask).css({opacity:0.0,display:'block',top: '0px', 
                         height: $(document).height().toString() + 'px' });
     // Special for IE, since it takes so long, make mask obvious
-    //if ($.browser.msie)
+    //if (theClient.isIePre11())
     //    $(waitMask).css({opacity:0.4,backgroundColor:'gray'});
 
     // Things could fail, so always have a timeout.
     if (!timeOutInMs)  // works for undefined, null and 0
         timeOutInMs = 30000; // IE can take forever!
 
     if (timeOutInMs > 0)
         setTimeout(waitMaskClear,timeOutInMs); // Just in case
 
     return waitMask;  // The caller could add css if they wanted.
 }
 
 function _launchWaitOnFunction()
 { // should ONLY be called by waitOnFunction()
   // Launches the saved function
@@ -2052,31 +2184,31 @@
                 $(this).addClass('sortable');
                 $(this).addClass('sort'+(ix+1));
                 //warn("Added class='sortable sort"+(ix+1)+"' to th:"+this.innerHTML);
             });
             sortColumns = new sortTable.columnsFromTr(tr,"silent");
             if (!sortColumns || sortColumns.cellIxs.length === 0) {
                 warn("sortable table's header row contains no sort columns.");
                 return;
             }
         }
         // Can wrap all columnn headers with link
         $(tr).find("th.sortable").each(function (ix) {
             if ( ! $(this).attr('onclick') ) {
                 $(this).click( function () { sortTable.sortOnButtonPress(this);} );
             }
-            if ($.browser.msie) { // Special case for IE since CSS :hover doesn't work
+            if (theClient.isIePre11()) { // Special case for IE since CSS :hover doesn't work
                 $(this).hover(
                     function () { $(this).css( { backgroundColor: '#CCFFCC', cursor: 'hand' } ); },
                     function () { $(this).css( { backgroundColor: '#FCECC0', cursor: '' } ); }
                 );
             }
             if ( $(this).attr('title').length === 0) {
                 var title = $(this).text().replace(/[^a-z0-9 ]/ig,'');
                 if (title.length > 0 && $(this).find('sup'))
                     title = title.replace(/[0-9]$/g,'');
                 if (title.length > 0)
                     $(this).attr('title',"Sort list on '" + title + "'." );
                 else
                     $(this).attr('title',"Sort list on column." );
             }
         });