检测IE的Metro UI版本

21

1
我认为他在问如何检测你的页面是作为一个Metro应用程序还是在IE 10中服务,因为它们都提供JavaScript / HTML / CSS。 - Brandon Boone
3
实际上,我认为msec在问如何检测运行于“Metro模式”下的IE10与运行于“桌面模式”下的IE10的网页请求(它们不同)。我的回答如下。 - Kurt Schindler
如前所述,我认为您无法特定地确定Metro UI。但是,您可以使用一个小函数在此处轻松解析IE版本。下一步真正需要决定的是要检测哪些“功能”。请查看Modernizr,它非常好用、干净且轻巧。我发现它在现代UI开发中非常有用。 - HankChizlJaw
我个人会选择触摸屏。请查看此处以获取有关触摸检测的信息:http://hankchizljaw.co.uk/tutorials/make-your-mouse-events-touch-friendly-with-jquery-tutorial/28/04/2012/。 - HankChizlJaw
看一下我的答案。它实际上是可靠的 - 如果你认为它比当前选中的项目更好,请打勾;) - robocat
显示剩余7条评论
11个回答

14

所以,似乎没有明确的测试方法可以区分Metro IE和桌面IE,但似乎有一些不同的数据可以尝试使用以假设它是Metro。不幸的是,我发现的所有项都可以通过其他设置来解释掉。换句话说,对于我发现的所有“特征”测试,桌面IE都可以被配置成以欺骗测试认为它正在运行Metro。

ActiveX是否已禁用(Metro不允许任何ActiveX内容,但桌面IE也可以将其设置为禁用):

function isActivexEnabled() {
    var supported = null;        
    try {
        supported = !!new ActiveXObject("htmlfile");
    } catch (e) {
        supported = false;
    }

    return supported;
}

用户代理字符串检查(Metro总是以64位模式运行,但在32位机器上不会运行,并且桌面IE也可以配置为以64位模式运行,但不确定这些选项有多受欢迎)

function isWin64() {
    return navigator.platform == "Win64";
}

全屏检查(Metro模式始终处于全屏模式,但是桌面版IE也可以运行在全屏模式下,这可能作为支持Metro模式的证据)

function isFullScreen() {
   return (window.innerWidth == screen.width && 
           window.innerHeight == screen.height);
}
简而言之,我认为您必须尝试检查一堆功能,然后猜测,没有明确的方法。或者您可以接受微软不希望您这样做,并针对您想使用的功能使用功能检测。
对于那些想要尝试提供UI以引用包含的浏览器UI(例如指示如何固定网页),请记住,其他Metro应用程序可以将IE10 Metro浏览器嵌入为控件,因此即使您可以识别浏览器是Metro还是桌面,UI也可能不在您尝试引用它的位置,因此这可能会是一个非常棘手的情况,难以百分之百地解决。所以,要么不要尝试,要么尝试其他检测技术,并接受可能存在显示错误UI的用例。

同时,window.innerHeightwindow.innerWidth都不能与屏幕高度/宽度进行比较,因为它们不是以物理像素为单位测量的。innerHeight/innerWidth值与窗口缩放成反比。 - robocat
1
如果要检测宽度,最好使用document.documentElement.clientWidth == screen.width,因为在Metro上,由于Metro中的一个错误,zoom不会改变clientWidth值。 在桌面上,根据缩放比例,该值会更改(正确的行为)。但是,如果用户在桌面IE10上按F11,则嗅探功能将无法正常工作。 请尝试以下链接:http://jsbin.com/iqibik/2(测试窗口/文档变量时必须使用jsbin而非嵌入式jsfiddle!) - robocat
2
我已经成功地使用这种方法一段时间了,但我发现包括全屏测试相对有些问题。首先,它在IE11上根本不起作用,因为IE11报告的高度不同(我认为地址栏的高度现在包含在屏幕大小中,而在IE10中不是)。但更重要的是,当IE被捆绑时,它不起作用,这是相当常见的。删除全屏测试会使检测不太安全,因此在使用时要小心。 - kkara
由于IE11 Metro底部有15像素的黑色条,导致高度嗅探在IE11中失效。如果被捆绑,则宽度嗅探也会失效(由kkara注意到)。如果使用F11全屏或触摸缩放,则宽度/高度嗅探可能会失效。请使用http://jsbin.com/uluFeKEW/3进行测试。 - robocat
请使用以下链接代替上面的链接:http://jsbin.com/uluFeKEW/5 - 改进了注释并修复了ActiveX嗅探。 - robocat
显示剩余2条评论

9

我不相信有一种方法可以确定请求是来自IE10的Metro版本还是常规桌面模式版本。 Metro IE没有唯一的HTTP标头或用户代理字符串可用于识别它。

Windows 8 64位上的Internet Explorer 10用户代理字符串

Metro IE10是一个64位应用程序,因此您将在用户代理字符串中看到“Win64”。默认情况下,常规桌面IE10为32位并显示“WOW64”。基于这个你可能会作出一个大致的判断,但你会错误地识别选择在桌面模式下运行64位版本的IE10的任何人。从该表中可以看出,用户代理字符串是相同的。[编辑:如评论中所述,这对32位PC无效。]

我能理解你想要检测Metro IE的原因,但这种“浏览器嗅探”通常不被鼓励,因为它很繁琐且容易出错。如果可以的话,最好使用类似Modernizr的东西对所需的特定浏览器功能进行功能测试。

1
很有趣的是,IE10有一个Metro版本和一个普通的桌面版本。我原本以为Metro只是另一种呈现网页内容的界面。 - Brandon Boone
在Consumer Preview上,还有其他人看到64位经典IE10的UA是“Mozilla/5.0(compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C; Media Center PC 6.0)”吗?请注意,“WOW64”而不是“Win64”。 - Bullines
对我来说问题在于IE10 Metro不允许您测试一些区别于非Metro的功能,特别是ActiveX扩展将永远不会被允许,因此您不应该尝试提供UI来安装它们。我写了一篇关于这个问题的博客文章。http://blog.bertlamb.com/2012/06/07/why-internet-explorer-10-metro-should-have-a-different-user-agent/ - Bert Lamb
1
这个解决方案在32位PC上不起作用,因为“WOW64”和“Win64”也不会出现在桌面UA中。 - Robert Levy
Modernizr在检测IE10 Metro模式时无法正常工作。显然,Modernizr只能检测WebKit兼容的触摸屏,详情请见https://github.com/Modernizr/Modernizr/issues/548。 - Jeff Atwood
1
在实际关心你正在运行哪个版本的设备上,如Surface和其他ARM设备上,既没有WOW64也没有Win64。 - mjaggard

4
感谢John Rajakumar和Alexis Pigeon。我能够使用你们的Metro IE检查作为基础来加载一个专门的CSS样式表,以适配Metro平板电脑(MS Surface)。为了更加确定,我首先使用cssuseragent来检测IE10,然后在最终的yepnope测试中结合两个测试。
var IEmetrotest = ((cssua.userAgent.ie > 9) && (metrotest()));
yepnope({
    test: IEmetrotest,
    yep : ['ie_metro.css']
    });

我在Browserstack中测试了它,结果符合预期。(我本想点赞你的,但是还没有足够的积分。)

// Minor revisions to isBrowserSupportPlugin() previously posted
// Renamed function to metrotest() and inverted the returned value. 
var errorName = null;
function metrotest() {
    var supported = null; 
    try {
        new ActiveXObject("");
    }
    catch (e) {
        // FF has ReferenceError here
        errorName = e.name; 
    }     
    try {
        supported = !!new ActiveXObject("htmlfile");
    } catch (e) {
        supported = false;
    }
    if(errorName != 'ReferenceError' && supported==false){
        supported = false;
    }else{
        supported =true;
    }
    return !supported;
}

1

这里提供一种一致的方法,不依赖于ActiveX检查,在IE10和IE11中经过测试。

if (window.screenY === 0 && (window.innerHeight+1) !== window.outerHeight){ //IE metro/modern UI }

第一个规则检测IE的全屏或现代视图(在IEMobile上也可能是真实的或可以实现的)。 历史上,最大化模式总是与正或负的screenX和screenY相关联。
最后一个规则排除了[全屏/F11]模式,由于某种原因,在IE10/Win8和IE11/Win8.1上测试时始终显示outerHeightinnerHeight之间的1像素差异。
PS:我自愿不声明window.screenX === 0。只使用screenY以覆盖窗口上下文捕捉到右侧的Modern/Metro快照模式(即screenX!== 0)。

这非常棒。我在IE 10+11、metro+desktop+fullscreen上进行了广泛的测试。我要补充的是,您需要检查自己是否正在运行IE(可能需要使用UA字符串),因为其他浏览器在某些情况下也可以通过这些测试(例如全屏状态下的Chrome)。 - aaaidan
似乎也可以在捕捉模式下工作,并且在任何缩放级别下都可以! - aaaidan
@aaaidan 我知道!我进行了广泛的测试 :) 实际上,IE检测是先决条件。在这种情况下,最好的选择可能是!!window.StyleMedia,考虑到IE 10、11和即将推出的IE12之间的根本用户代理更改。我最终会相应地更新我的答案。 - hexalys

1

METRO IE不支持ActiveX或任何插件对象。基于此,以下脚本已经测试并且运行良好。

//---------------------------Metro IE check-------------------------
    var errorName = null;
    function isBrowserSupportPlugin() {
        var supported = null; 
        try {
            new ActiveXObject("");
        }
        catch (e) {
            // FF has ReferenceError here
            errorName = e.name; 
        }     
        try {
            supported = !!new ActiveXObject("htmlfile");
        } catch (e) {
            supported = false;
        }
        if(errorName != 'ReferenceError' && supported==false){
            supported = false;
        }else{
            supported =true;
        }
        return supported;
    }
//----------------------------------------------------------------   

1

可靠的现代/ Metro 检测!

我找到了一种检测现代和桌面模式的方法,您可以在此处尝试:http://jsbin.com/genac/2(使用 Chrome 或 Firefox 进行编辑,而不是 IE http://jsbin.com/genac/2/edit)。

它似乎是一种相当强大的检测方式,因为:

  • 即使进行了捏合缩放,它也能正常工作
  • 即使在 Modern(Metro)上同时捕捉两个窗口,它也能正常工作
  • 即使使用 ctrl-+ 和 ctrl-- 缩放页面,它也能正常工作
  • 即使在桌面模式下使用 F11 键全屏(自动隐藏任务栏),它也能正常工作

诀窍在于,现代页面上的滚动条不会使客户端窗口大小变小(它们出现在页面上方),但桌面页面上的滚动条会影响客户端窗口大小(可用窗口大小更小)。

主要缺点是测试需要页面上有滚动条才能探测差异。在 iframe 或自动滚动的 div 中是否会出现相同的滚动条差异?

编辑:在使用此代码之前,我建议先测试浏览器是否为IE11,因为Windows 10没有Metro / Modern界面,而Edge表现略有不同。
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=EDGE" />
  <title>Metro width detector - robocat</title> 
  <script>
    function show() {
      var div = document.createElement('div');
      var s = [];
      s.push('IS METRO? ' + ((tester.offsetWidth == window.outerWidth) ? 'YES' : 'NO'));
      s.push('document.documentElement.clientWidth: ' + document.documentElement.clientWidth);
      s.push('document.documentElement.offsetWidth: ' + document.documentElement.offsetWidth);
      s.push('window.innerWidth: ' + window.innerWidth);
      s.push('window.outerWidth: ' + window.outerWidth);
      s.push('screen.width: ' + screen.width);
      s.push('screen.availWidth: ' + screen.availWidth);
      s.push('document.documentElement.getBoundingClientRect().width: ' + document.documentElement.getBoundingClientRect().width);
      s.push('tester.offsetWidth: ' + tester.offsetWidth);
      div.innerHTML = s.join('<br>');
      document.body.insertBefore(div, document.body.firstChild);
    }
    window.onresize = function() {
      show();
    }
  </script>
</head>
  <body onload="show()" style="margin:0">
    <div id="tester" style="position:absolute;left:0;right:0;"></div>
  <div style="height:10000px;width:10px;background-color:blue;"></div>
</body>
</html>

您可以使用以下方法查看页面/窗口尺寸: http://jsbin.com/AbimiQup/10 (请使用Chrome或Firefox进行编辑,不要使用IE http://jsbin.com/AbimiQup/10/edit)
PS:也许可以通过运行时样式的body或document.documentElement来嗅探滚动条差异,因为可能使用了-ms-overflow-style: -ms-autohiding-scrollbar(例如:document.documentElement.runtimeStyle.msOverflowStyle),但我找不到任何内容。
PPS:其他答案中提供的ActiveX方法并不特别可靠(例如:用户可以禁用它),并且它会导致UI难看,因为在IE11中它会显示一个“ActiveX”图标。

自己的笔记:// MS平板检测:查看ARM和Touch的用户代理?Pro平板呢?“Windows Phone”适用于Windows Phone吗?请注意,“Tablet PC”适用于IE8/IE9?// IE9 64位与32位不同:“IE 9 64位使用较旧、较慢的JavaScript引擎,而IE 9 32位使用更新、更高效的Chakra JIT。Internet Explorer 9 64位在JavaScript性能方面非常糟糕。”// 可靠的Metro与桌面测试?!:body上的滚动条宽度为零-外部宽度减去内部宽度。在IE10 Metro中,滚动条不透明地覆盖在顶部,并且宽度为零。 - robocat

0
听起来你想做的事情类似于将一个网站固定到Metro的开始屏幕上。为了实现这个功能,您可以使用IE9中引入的以下代码进行检查并将其执行如下...
function doChecks_Browser() {    
  // full pin abilities == can pin && Win7+    
  if (pinnedSiteDetection.hasFullPinAbilityBrowser)
}

关于此事的更多信息在这里

MSDN上的这篇文章中提到...

Windows 8 Release Preview通过在开始屏幕上使用磁贴来实现固定站点。当用户单击固定站点的磁贴时,该站点将在Windows Internet Explorer 10 Release Preview中以Windows Metro样式UI环境打开。

希望这可以帮助到您!


有点儿……我想通过视觉提示来引导用户如何像http://cubiq.org/add-to-home-screen在iOS上那样固定。这个UI需要根据我是在桌面IE还是Metro IE中而改变。 - Robert Levy
好的,这个链接展示了如何创建一个弹出窗口,提示用户将网站图标拖到任务栏中。不确定在Windows 8的Metro界面中是否适用或者有没有相应的替代方法,但是值得一试。[链接] (http://msdn.microsoft.com/en-us/library/ie/gg491729(v=vs.85).aspx#drag) - tcmorris

0
var _ua = window.navigator.userAgent;
var isIDevice = (/iphone|ipod|ipad/i).test(_ua);
var isMobileChrome = (_ua.indexOf('Android') > -1 && (/Chrome\/[.0-9]*/).test(_ua) && _ua.indexOf("Version") == -1);
var isMobileIE = _ua.indexOf('Windows Phone') > -1;
function isActivexEnabled()
{
    var supported = null;        
    try
    {
        supported = !!new ActiveXObject("htmlfile");
    } 
    catch (e) 
    {
        supported = false;
    }
    return supported;
}
if (!isIDevice && !isMobileChrome && !isMobileIE &&  _ua.toLowerCase().indexOf("wow") == -1 && !isActivexEnabled())
{ 
    //IE Metro UI
}

这对我有用。


0

我尝试了下面的代码,看起来是可以工作的。
但是如果用户在Internet选项->自定义级别->将ScriptActivexControlsMarkedSafeForScripting设置为false,它就无法捕获。如果用户这样做,代码会认为它是Metro/Modern界面。
目前我没有找到绕过这个问题的方法,比如检查操作系统、全屏模式之类的。

isWinModern用于检查Metro/Modern界面。
isWinDesktop用于检查Windows桌面(=非modern界面)。

以下代码不能保证能够正常工作。

    function isWin8Modern() {
        if (!!window.ActiveXObject) {
            try {
                !!new window.ActiveXObject('htmlfile');
                return false;
            } catch (exc) {
                return true;
            }
        } else {
            return false;
        }
    }

    function isWinDesktop() {
        if (window.ActiveXObject) {
            try {
                new window.ActiveXObject('htmlfile');
                return true;
            } catch (exc) {
                return false;
            }
        } else {
            return false;
        }
    }

0
我测试了以下内容,它有效,一个展示这个的 jsfiddle 可以在这里找到。

这可能有点冒险,但似乎是一个相当明智的解决方案:

为什么不检查浏览器是否全屏1,并根据此调用全屏元素metro。我在工作电脑上运行着Windows 8,所以明天我会尝试检查是否还有任何GUI(我不认为我记得有任何GUI),如果有,您需要手动减去它们。确实,这不是最美丽的解决方案,但据我所知,不会有任何“美丽”的解决方案,这可能证明是一个相当可靠的黑客,因为metro IE的GUI不能使用任何工具栏或类似软件更改(据我所知)。确实,这可能会导致桌面IE的错误识别,但即使如此,全屏桌面IE仍将提供类似的体验。


1 给出类似以下的内容:

if(window.innerWidth == screen.width && window.innerHeight == screen.height) {
  // metro
} else {
  // desktop
}

刚刚测试了一下,这确实可以识别Metro。请尝试在Metro和桌面上打开http://fiddle.jshell.net/JbGek/2/show/light/。 - David Mulder
嗯...你说得对,似乎确实可以工作,不确定为什么在我的测试页面上不能工作,可能是因为我在IE兼容模式下运行。 - Bert Lamb
在Firefox中,全屏模式下的innerHeight比screen.height少一个像素,这可能是因为顶部像素行激活了工具栏。 - Webveloper
1
有趣的是,在桌面和Metro中打开时,两者都报告为“桌面”,通过F11最大化桌面后则报告为“Metro”,所以这不幸地不可靠...这种情况发生在多个不同尺寸的显示器上! - jJ'
很奇怪,我当时使用发布候选版进行了测试,在那个版本中它正确地识别了两者在 fiddle 中的情况。我想可能需要进行一些额外的微调,例如在 Metro 中的备选设置,但至少这比什么都不做要好(因为在某些情况下,这确实可以工作),而在桌面全屏模式下的错误识别我已经在我的答案中提到了。(这是合理的,因为在这种情况下,你可能无论如何都想显示类似 Metro 的界面) - David Mulder
任何全屏模式下的浏览器都不能通过这个测试吗?可能需要加强一些其他测试,包括IE UA测试。 - aaaidan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接