使用 Javascript 将 src 属性写为 data-src,因为页面正在加载
Use Javascript to write src attribute as data-src, as page is loading
Background: Back in December I wanted my (custom) PHP page-building
engine to build a page one-way if the User Agent (UA) could handle
Javascript and a different way if the UA could not. To achieve this, I
needed to learn:
How to detect UA Javascript capability via PHP, prior to PHP building the page on-the-fly:
Detecting javascript in PHP, before PHP builds page
Thanks to some very helpful guidance from @skobaljic, @Abhi Beckert
and @GolezTrol, I learned that we can use Javascript to place
a session cookie which PHP will be able to query on all subsequent page
loads. Consequently, for every page after the first one, PHP will
know whether the UA is Javascript-capable or not
So far, so good. Now I have reached the stage where I am no longer
building pages with PHP on-the-fly but pre-generating them and uploading
them to the server as static HTML documents.
If you're still with me, you'll have guessed correctly this means I am
currently needing to pre-generate two static documents for each page -
one for the non-JS-capable UAs and one for the JS-capable UAs.
This isn't really ideal, hence my question below.
从表面上看,这应该是一个简单的问题。
对于 Javascript-不支持的 UA,我想构建一个包含如下行的文档:
<img src="/myfolder/myimage.png" alt="My Image" />
对于 Javascript 可用的 UA,我想构建包含如下行的相同文档:
<img data-src="/myfolder/myimage.png" alt="My Image" />
(对于那些好奇的人,onload
之后的 javascript 将所有 data-src 属性转换为 src 属性,随后进行了数十次服务器往返但是 - 至关重要的是 - 仅在 页面已经充分加载之后)。
我已经通过 PHP 和一个会话 cookie(参见上面的 背景)实现了这一点,但是现在,如果可能的话,我想执行整个过程在前端。
如何将属性写入 DOM 中的 <img />
元素默认为 src
但是,另外,(如果 javascript 可用)前缀带有 data-
的属性,使其显示为 data-src
...
...这样...
[重要的一点]
如果 UA 是javascript-capable 它将自动并立即写入src
的所有实例因为 data-src
因为页面正在被 UA 下载 ,所以在 onload
之后 javascript 可以重新写入 data-src
又是 src
。
像这样 - 未经测试但应该可以工作:
var imgs = document.getElementsByTagName('img');
for(var i = 0; i < imgs.length; i++) {
var currentSrc = imgs[i].getAttribute('src');
imgs[i].setAttribute('src',''); // remove old src data
imgs[i].setAttribute('data-src','currentSrc');
}
所有这一切都是添加一个新的 data-src
属性,并清除当前的 src
(如果需要)
在 </body>
标签之前添加
这是一种 hacky 方式,但所有浏览器 (ie6+) 都支持它:
<body>
<noscript>
<style>.img-hide { display: none; }</style>
</noscript>
<noscript><img src="/path/to/image1.jpg"></noscript>
<img class="img-hide" data-src="/path/to/image1.jpg">
<noscript><img src="/path/to/image2.jpg"></noscript>
<img class="img-hide" data-src="/path/to/image2.jpg">
<!-- etc etc etc -->
</body>
经过将近3天的head-scratching,终于破解了
头部
<head>
<script>
function initialiseImages() {
var scripts = document.getElementsByTagName('script');
var section = scripts[scripts.length-1].parentNode;
var images = section.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) {
var src = images[i].getAttribute('src');
var datasrc = document.createAttribute('data-src');
datasrc.value = src;
images[i].setAttributeNode(datasrc);
images[i].removeAttribute('src');}}
</script>
</head>
BODY
<body>
<section>
<h2><img src="/myfolder/myimage.png" alt="My Image" />Second Level Heading</h2>
<ul><li><img src="/myfolder/myimage.png" alt="My Image" /></li></ul>
<script>initialiseImages();</script>
</section>
<section>
<h3>Third Level Heading</h3>
<ul>
<li><img src="/myfolder/myimage.png" alt="My Image" /></li>
<li><img src="/myfolder/myimage.png" alt="My Image" /></li>
<li><img src="/myfolder/myimage.png" alt="My Image" /></li>
</ul>
<script>initialiseImages();</script>
</section>
</body>
更新 1
感谢 Dave Walsh 的文章引用脚本自己的标签 (http://davidwalsh.name/script-tag),我 re-written function initialiseImages()
的前 3 行:
var scripts = document.getElementsByTagName('script');
var section = scripts[scripts.length-1].parentNode;
var images = section.getElementsByTagName('img');
单行:
var images = document.currentScript.parentNode.getElementsByTagName('img');
据我所知,这定义了 var images
稍微快一点,因此在 UA 向服务器发送 file-request 之前捕获了更多 <img src=
的实例。
开发人员注释如下...
尝试 #1:尝试让 Javascript 表现得像 PHP
相对于部署Javascript,我更熟悉在PHP中编写页面on-the-fly,所以我的初衷是想办法使用Javascript以 quasi-server-side 的方式 re-write DOM 在它到达的那一刻瞬间:
For Javascript-non-capable UAs, I want to build a document which
contains lines like this:
<img src="/myfolder/myimage.png" alt="My Image" />
For Javascript capable UAs, I want to build the same document which
contains lines like this:
<img data-src="/myfolder/myimage.png" alt="My Image" />
如果这样的方法可行,我找不到实现它的方法 - 而且,公平地说,Javascript 当然不是为瞬时 re-writing 元素属性设计的他们到了。
尝试 #2:通过 Javascript-added CSS
阻止图像下载
我的第二种方法是看看我是否可以通过 CSS.
行来阻止图像下载
如果我用 Javascript 添加该行,则只有 Javascript-capable 个 UA 能够读取 image-blocking 样式规则。
这也没有用。事实证明,您可以直接阻止 CSS background-images
下载,方法是将 display:none;
应用于元素的 parent 容器 有 background-image
。但是我想要阻止的图像(直到加载之后)具体是 <img>s
,而不是 background-images
- 事实证明,一旦 UA 命中 <img src
,它就会跑到服务器下载图片。
尝试 #3:在每个 <img>
中内联 Javascript
内联 Javascript 很漂亮 old-school,但@Darren Sweeney 已经提出了一个富有想象力的 <noscript>
解决方案,所以我不想自动忽略 old-school。我想像这样解决这个问题:
<img src="/myfolder/myimage.png" alt="My Image" onEvent="initialiseImage();" />
我 运行 进入这里的主要问题是我找不到任何合适的 onEvent
。我将 initialiseImage()
函数放在 <head>
中,然后我希望每次 UA 达到 <img>
时自动触发该函数 - 但经过广泛阅读后,我不确定自动内联执行是可能的。 (也许有人可以在下面的评论中让我知道,如果是...)
当然,我找不到 onParse
。
唯一有意义的 element-specific onEvent
是 onLoad
,在 <img>
的情况下(如果我理解正确的话)下载 <img>
在它触发之前。所以那一点都不好。
尝试 #4:终于成功了!
到目前为止:
1) 从一开始,问题就是等到 window.onload
才使用 Javascript 重写每个 <img src=
属性太晚了;
2) 我找不到使用 Javascript 在下载时立即重写每个 <img src=
的方法;
3) 在 UA 解析 <img>
;
时,我看不到使用 Javascript 重写每个 <img src=
属性的方法
我推断也许我仍然可以使用 Javascript 重写每个 <img src=
属性,此时 UA 完成解析每个 <section>
包含每组 <img>s
。
我很高兴地说我已经相当彻底地测试了上面的代码并且它似乎(到目前为止)工作完美 - 早在 UA 开始从服务器请求 <img>
文件之前,<img src=
属性已替换为 <img data-src=
属性 并且不再执行该请求。
Background: Back in December I wanted my (custom) PHP page-building engine to build a page one-way if the User Agent (UA) could handle Javascript and a different way if the UA could not. To achieve this, I needed to learn:
How to detect UA Javascript capability via PHP, prior to PHP building the page on-the-fly: Detecting javascript in PHP, before PHP builds page
Thanks to some very helpful guidance from @skobaljic, @Abhi Beckert and @GolezTrol, I learned that we can use Javascript to place a session cookie which PHP will be able to query on all subsequent page loads. Consequently, for every page after the first one, PHP will know whether the UA is Javascript-capable or not
So far, so good. Now I have reached the stage where I am no longer building pages with PHP on-the-fly but pre-generating them and uploading them to the server as static HTML documents.
If you're still with me, you'll have guessed correctly this means I am currently needing to pre-generate two static documents for each page - one for the non-JS-capable UAs and one for the JS-capable UAs. This isn't really ideal, hence my question below.
从表面上看,这应该是一个简单的问题。
对于 Javascript-不支持的 UA,我想构建一个包含如下行的文档:
<img src="/myfolder/myimage.png" alt="My Image" />
对于 Javascript 可用的 UA,我想构建包含如下行的相同文档:
<img data-src="/myfolder/myimage.png" alt="My Image" />
(对于那些好奇的人,onload
之后的 javascript 将所有 data-src 属性转换为 src 属性,随后进行了数十次服务器往返但是 - 至关重要的是 - 仅在 页面已经充分加载之后)。
我已经通过 PHP 和一个会话 cookie(参见上面的 背景)实现了这一点,但是现在,如果可能的话,我想执行整个过程在前端。
如何将属性写入 DOM 中的 <img />
元素默认为 src
但是,另外,(如果 javascript 可用)前缀带有 data-
的属性,使其显示为 data-src
...
...这样...
[重要的一点]
如果 UA 是javascript-capable 它将自动并立即写入src
的所有实例因为 data-src
因为页面正在被 UA 下载 ,所以在 onload
之后 javascript 可以重新写入 data-src
又是 src
。
像这样 - 未经测试但应该可以工作:
var imgs = document.getElementsByTagName('img');
for(var i = 0; i < imgs.length; i++) {
var currentSrc = imgs[i].getAttribute('src');
imgs[i].setAttribute('src',''); // remove old src data
imgs[i].setAttribute('data-src','currentSrc');
}
所有这一切都是添加一个新的 data-src
属性,并清除当前的 src
(如果需要)
在 </body>
标签之前添加
这是一种 hacky 方式,但所有浏览器 (ie6+) 都支持它:
<body>
<noscript>
<style>.img-hide { display: none; }</style>
</noscript>
<noscript><img src="/path/to/image1.jpg"></noscript>
<img class="img-hide" data-src="/path/to/image1.jpg">
<noscript><img src="/path/to/image2.jpg"></noscript>
<img class="img-hide" data-src="/path/to/image2.jpg">
<!-- etc etc etc -->
</body>
经过将近3天的head-scratching,终于破解了
头部
<head>
<script>
function initialiseImages() {
var scripts = document.getElementsByTagName('script');
var section = scripts[scripts.length-1].parentNode;
var images = section.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) {
var src = images[i].getAttribute('src');
var datasrc = document.createAttribute('data-src');
datasrc.value = src;
images[i].setAttributeNode(datasrc);
images[i].removeAttribute('src');}}
</script>
</head>
BODY
<body>
<section>
<h2><img src="/myfolder/myimage.png" alt="My Image" />Second Level Heading</h2>
<ul><li><img src="/myfolder/myimage.png" alt="My Image" /></li></ul>
<script>initialiseImages();</script>
</section>
<section>
<h3>Third Level Heading</h3>
<ul>
<li><img src="/myfolder/myimage.png" alt="My Image" /></li>
<li><img src="/myfolder/myimage.png" alt="My Image" /></li>
<li><img src="/myfolder/myimage.png" alt="My Image" /></li>
</ul>
<script>initialiseImages();</script>
</section>
</body>
更新 1
感谢 Dave Walsh 的文章引用脚本自己的标签 (http://davidwalsh.name/script-tag),我 re-written function initialiseImages()
的前 3 行:
var scripts = document.getElementsByTagName('script');
var section = scripts[scripts.length-1].parentNode;
var images = section.getElementsByTagName('img');
单行:
var images = document.currentScript.parentNode.getElementsByTagName('img');
据我所知,这定义了 var images
稍微快一点,因此在 UA 向服务器发送 file-request 之前捕获了更多 <img src=
的实例。
开发人员注释如下...
尝试 #1:尝试让 Javascript 表现得像 PHP
相对于部署Javascript,我更熟悉在PHP中编写页面on-the-fly,所以我的初衷是想办法使用Javascript以 quasi-server-side 的方式 re-write DOM 在它到达的那一刻瞬间:
For Javascript-non-capable UAs, I want to build a document which contains lines like this:
<img src="/myfolder/myimage.png" alt="My Image" />
For Javascript capable UAs, I want to build the same document which contains lines like this:
<img data-src="/myfolder/myimage.png" alt="My Image" />
如果这样的方法可行,我找不到实现它的方法 - 而且,公平地说,Javascript 当然不是为瞬时 re-writing 元素属性设计的他们到了。
尝试 #2:通过 Javascript-added CSS
阻止图像下载我的第二种方法是看看我是否可以通过 CSS.
行来阻止图像下载如果我用 Javascript 添加该行,则只有 Javascript-capable 个 UA 能够读取 image-blocking 样式规则。
这也没有用。事实证明,您可以直接阻止 CSS background-images
下载,方法是将 display:none;
应用于元素的 parent 容器 有 background-image
。但是我想要阻止的图像(直到加载之后)具体是 <img>s
,而不是 background-images
- 事实证明,一旦 UA 命中 <img src
,它就会跑到服务器下载图片。
尝试 #3:在每个 <img>
中内联 Javascript
内联 Javascript 很漂亮 old-school,但@Darren Sweeney 已经提出了一个富有想象力的 <noscript>
解决方案,所以我不想自动忽略 old-school。我想像这样解决这个问题:
<img src="/myfolder/myimage.png" alt="My Image" onEvent="initialiseImage();" />
我 运行 进入这里的主要问题是我找不到任何合适的 onEvent
。我将 initialiseImage()
函数放在 <head>
中,然后我希望每次 UA 达到 <img>
时自动触发该函数 - 但经过广泛阅读后,我不确定自动内联执行是可能的。 (也许有人可以在下面的评论中让我知道,如果是...)
当然,我找不到 onParse
。
唯一有意义的 element-specific onEvent
是 onLoad
,在 <img>
的情况下(如果我理解正确的话)下载 <img>
在它触发之前。所以那一点都不好。
尝试 #4:终于成功了!
到目前为止:
1) 从一开始,问题就是等到 window.onload
才使用 Javascript 重写每个 <img src=
属性太晚了;
2) 我找不到使用 Javascript 在下载时立即重写每个 <img src=
的方法;
3) 在 UA 解析 <img>
;
<img src=
属性的方法
我推断也许我仍然可以使用 Javascript 重写每个 <img src=
属性,此时 UA 完成解析每个 <section>
包含每组 <img>s
。
我很高兴地说我已经相当彻底地测试了上面的代码并且它似乎(到目前为止)工作完美 - 早在 UA 开始从服务器请求 <img>
文件之前,<img src=
属性已替换为 <img data-src=
属性 并且不再执行该请求。