3

背景

我正在为我使用的 CMS 开发响应式图像插件,并且我选择使用立即 set-cookie 方法来告诉服务器用户屏幕的尺寸。

对于那些不熟悉这一点的人,这意味着您在文档顶部的 javascript 中设置了一个 cookie,因此当浏览器继续解析文档的其余部分时,它会发送您的 cookie 以及它发送的任何图像请求。

这适用于大多数浏览器,除了 IE9。对此流行的解释似乎是 IE9 在完成文档解析之前实际上并没有设置 cookie,这似乎是非常奇怪的行为。我已经完成了自己的测试,得出的结论是 cookie 不仅仅是一些特殊的例外,它实际上是 IE9 处理 javascript 的方式 - IE9 似乎在完成对文档的解析之前不会执行任何 javascript。

不幸的是,它在执行内联 JS 之前发送了所有对外部资源的请求。

问题

有没有办法强制 IE9(和其他表现出这种行为的浏览器)在文档仍在被解析时执行 javascript?

编辑

所以我开始取得进展,这可能与 IE9 javascript 引擎有关 - 它进行后台编译。我想它会等到它得到所有的 javascript 后再编译它。我想知道是否有一个鲜为人知的 IE 脚本标签属性可以切换特定块的行为。要去打猎,有什么发现我会告诉大家的。

编辑 2

似乎我对 IE9 使用 javascript 的方式的假设并不完全正确。这是科学界将其描述为“甚至没有错”的不幸情况之一!因此,我提出的问题不再有用,因为它依赖于一些错误的假设。但是,我将在下面发布我用于测试的修改后的代码:

测试.php

<?php
file_put_contents("log.txt", "\r\n\r\nTestResStart\r\n", FILE_APPEND);
?>
<!DOCTYPE HTML>
<html lang="en-US">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <img src="image.php?q=1" />
    <script type="text/javascript">
        document.write('<img src="image.php?q=4-js" />');
        alert("HALT!");
        document.write('<img src="image.php?q=5-js" />');
    </script>
    <img src="image.php?q=2" />
    <img src="image.php?q=3" />
</body>
</html>

图像.php

<?php
session_start();
file_put_contents("log.txt", "image".$_GET['q']."\r\n", FILE_APPEND);
$rImg = ImageCreate(300,50);
$cor = imagecolorallocate($rImg, 225, 225, 225);
$cor = imagecolorallocate($rImg, 0, 0, 0);
imagestring($rImg,2,0,0,$_GET['q'],$cor);
header('Content-type: image/jpeg');
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
imagejpeg($rImg,NULL,100);

运行 test.php 将通过 html 和 document.write 加载图像。image.php 将按照收到的顺序记录这些请求。您会注意到,即使显示警报,请求也会继续通过 - 因此警报不会停止执行(尽管大多数其他浏览器表现出类似的行为)。回到广场 1!

4

3 回答 3

1

将脚本标签写入文档document.write()可能会解决您的问题。

这可能看起来很奇怪,但我注意到这样做会导致 DOM 在每个脚本之后实际呈现到屏幕上(否则情况并非如此,如果您尝试在加载过程中为进度条设置动画,则非常烦人)

如果它们具有相同的原因,它也可以解决您的 cookie 问题。

于 2012-11-16T03:09:36.793 回答
0

您可以延迟 DOM 的构建。走“模板方式”:

1) 将 html 代码放入<script type="text/template" id="someID"></script>. 这将导致浏览器具有非 javascript 类型的脚本节点。这将导致浏览器简单地忽略其内容,但您可以通过获取脚本节点的 innerHTML 来访问它。

2) 在页面加载并设置好之后,您可以附加一个 document.ready 事件处理程序来执行您的 DOM 的实际构建。至此,解析和初始渲染已经完成,所以我希望 IE 现在已经设置了 cookie。如果没有,则在 setTimout(fn,1); 中触发 DOM 的构建;

3)做类似的事情:

var content = document.getElementById('someID');
var container = document.getElementById('containerID'); // This could be an empty DIV right next to the <script> tag. 
container.innerHTML = content.innerHTML;
于 2012-11-16T03:25:59.393 回答
0

所以,要回答这个问题已经变成的问题;

当你设置它们时,你如何让 IE9 尊重你设置的 cookie?

答案是特征检测。我们可以检测(使用老式元标记)浏览器是否支持即时 cookie 设置,如果不支持,我们会尽快重新加载页面(在我们浪费太多时间之前)。

编码

<script type="text/javascript">
    var c ='resolution='+Math.max(screen.width,screen.height)+("devicePixelRatio" in window ? ","+devicePixelRatio : ",1");
    var cSet = new RegExp(c);

    //If cookies are enabled and our cookie isn't set
    if(navigator.cookieEnabled && !cSet.test(document.cookie))
    {
        //Set the cookie via a meta tag
        document.write('<me'+'ta http-equiv="Set-Cookie" content="'+c+'; path=/" />');

        //If it hasn't been parsed yet
        if(!cSet.test(document.cookie))
        {
            //Reload the page
            document.location.reload();
        }
    }
</script>

在我的博客上还有一个更完整、更杂乱的解决方案:

http://iain-fraser.com/2012/11/cookie-based-responsive-images-that-work-in-ie9/

我会在周末之后更新这篇文章——我只需要在它还新鲜的时候把它全部写下来。当然,如果我进一步开发它,我会相应地更新它。

于 2012-11-16T09:24:26.167 回答