加载生成内容中的图像时触发事件
Fire event when images in generated content are loaded
我对某些 Javascript 生成的内容有疑问:
我使用 html 页面的 onload()
事件从服务器加载 HTML 代码并将其注入页面。因为它已经是 html 我使用我想要填充内容的节点的 innerHtml
属性。
注入 HTML 后,我调用了一个手工制作的 adjustHeights()
函数,该函数对我以这种方式创建的元素的高度进行标准化,使它们都与最高元素的高度相匹配。
除非 innerHtml
中的代码包含某种需要时间加载的图像或其他媒体(尤其是视频),否则所有这一切都完美无缺,因为 adjustHeights()
在代码注入之间被调用和 image/video/etc.
的加载时间结束
有什么方法可以在调用 adjustHeights()
之前等待所有元素加载完毕?我已经尝试过 document.onreadystatechange
属性 但是当我开始注入代码时状态已经是 'completed'。
如果可能的话,我宁愿不在 adjustHeights()
上使用基于时间的调用。
为了更清楚这里有一个例子:
var mylist = document.getElementById('mycontent');
var li;
for (var i = 0; i < res.length; i++)
{
li = document.create('li');
li.innerHTML=res[i];
mylist.appendChild(li);
}
adjustHeights();
对于图像和其他类型的媒体,您应该使用 "onload" 事件,以便之后调用调整高度。
示例:
<img src="someimage.png" onload="loadImage()" >
<script>
function loadImage() {
// code to adjust heights
}
</script>
这里是标准版:
var img = document.querySelector('img')
function loaded() {
alert('loaded');
// do something to adjust height
}
if (img.complete) {
loaded()
} else {
img.addEventListener('load', loaded)
img.addEventListener('error', function() {
alert('error')
})
}
要在不向所有 images/videos/etc 添加内联 onload
属性的情况下执行此操作,您将必须观察 DOM 的更改。然后在每次更改时,您必须获取所有新媒体并从回调中向它们添加 onload
事件。为了防止每次都检查每个元素,一旦它们被加载,您可以通过添加 data-loaded="true"
属性 来标记它们。
观察 DOM 变化的跨浏览器解决方案可以在这个答案中找到:Detect changes in the DOM。我不会在这里重复它(但它包含在下面的演示中)。
注意:我以图像为例,但这也适用于视频和其他媒体。
在每次 DOM 更改时,首先通过检查 element.complete
.如果是,触发回调函数并向其添加属性。
如果 .complete
不是这种情况,请向它们添加一个 onload
事件,该事件也会在加载后触发回调。
// Observe the DOM for changes
observeDOM(document.body, function(){
checkNewMedia();
});
// Loop through all new media, add the event
var checkNewMedia = function() {
// extend this by using document.querySelectorAll("img:not([data-loaded), video:not([data-loaded])") etc.
var media = document.querySelectorAll('img:not([data-loaded]');
for(var i = 0; i < media.length; i++) {
addMediaLoadedEvent(media[i]);
}
}
// Fire the callback if complete, otherwise bind to onload
var addMediaLoadedEvent = function(element) {
if (element.complete) {
onMediaLoaded(element);
} else {
element.addEventListener('load', function(event) {
onMediaLoaded(event.target);
});
}
}
// The callback that is fired once an element is loaded
var onMediaLoaded = function(element) {
element.setAttribute('data-loaded', 'true');
adjustHeights(); // <-- your function
}
演示:fire event on each image load
如果您只想在加载 所有 图像后触发事件,您可以添加一个额外的检查来计算仍有多少图像未加载:
// The callback that is fired once an image is loaded
var onMediaLoaded = function(element) {
element.setAttribute('data-loaded', 'true');
// only fire when there are no media elements without the 'data-loaded' attribute left
// again, can be extended to use video, etc.
if(document.querySelectorAll('img:not([data-loaded])').length === 0) {
adjustHeights(); // <-- your function
}
}
演示:fire event on all images loaded
我对某些 Javascript 生成的内容有疑问:
我使用 html 页面的 onload()
事件从服务器加载 HTML 代码并将其注入页面。因为它已经是 html 我使用我想要填充内容的节点的 innerHtml
属性。
注入 HTML 后,我调用了一个手工制作的 adjustHeights()
函数,该函数对我以这种方式创建的元素的高度进行标准化,使它们都与最高元素的高度相匹配。
除非 innerHtml
中的代码包含某种需要时间加载的图像或其他媒体(尤其是视频),否则所有这一切都完美无缺,因为 adjustHeights()
在代码注入之间被调用和 image/video/etc.
有什么方法可以在调用 adjustHeights()
之前等待所有元素加载完毕?我已经尝试过 document.onreadystatechange
属性 但是当我开始注入代码时状态已经是 'completed'。
如果可能的话,我宁愿不在 adjustHeights()
上使用基于时间的调用。
为了更清楚这里有一个例子:
var mylist = document.getElementById('mycontent');
var li;
for (var i = 0; i < res.length; i++)
{
li = document.create('li');
li.innerHTML=res[i];
mylist.appendChild(li);
}
adjustHeights();
对于图像和其他类型的媒体,您应该使用 "onload" 事件,以便之后调用调整高度。 示例:
<img src="someimage.png" onload="loadImage()" >
<script>
function loadImage() {
// code to adjust heights
}
</script>
这里是标准版:
var img = document.querySelector('img')
function loaded() {
alert('loaded');
// do something to adjust height
}
if (img.complete) {
loaded()
} else {
img.addEventListener('load', loaded)
img.addEventListener('error', function() {
alert('error')
})
}
要在不向所有 images/videos/etc 添加内联 onload
属性的情况下执行此操作,您将必须观察 DOM 的更改。然后在每次更改时,您必须获取所有新媒体并从回调中向它们添加 onload
事件。为了防止每次都检查每个元素,一旦它们被加载,您可以通过添加 data-loaded="true"
属性 来标记它们。
观察 DOM 变化的跨浏览器解决方案可以在这个答案中找到:Detect changes in the DOM。我不会在这里重复它(但它包含在下面的演示中)。
注意:我以图像为例,但这也适用于视频和其他媒体。
在每次 DOM 更改时,首先通过检查 element.complete
.如果是,触发回调函数并向其添加属性。
如果 .complete
不是这种情况,请向它们添加一个 onload
事件,该事件也会在加载后触发回调。
// Observe the DOM for changes
observeDOM(document.body, function(){
checkNewMedia();
});
// Loop through all new media, add the event
var checkNewMedia = function() {
// extend this by using document.querySelectorAll("img:not([data-loaded), video:not([data-loaded])") etc.
var media = document.querySelectorAll('img:not([data-loaded]');
for(var i = 0; i < media.length; i++) {
addMediaLoadedEvent(media[i]);
}
}
// Fire the callback if complete, otherwise bind to onload
var addMediaLoadedEvent = function(element) {
if (element.complete) {
onMediaLoaded(element);
} else {
element.addEventListener('load', function(event) {
onMediaLoaded(event.target);
});
}
}
// The callback that is fired once an element is loaded
var onMediaLoaded = function(element) {
element.setAttribute('data-loaded', 'true');
adjustHeights(); // <-- your function
}
演示:fire event on each image load
如果您只想在加载 所有 图像后触发事件,您可以添加一个额外的检查来计算仍有多少图像未加载:
// The callback that is fired once an image is loaded
var onMediaLoaded = function(element) {
element.setAttribute('data-loaded', 'true');
// only fire when there are no media elements without the 'data-loaded' attribute left
// again, can be extended to use video, etc.
if(document.querySelectorAll('img:not([data-loaded])').length === 0) {
adjustHeights(); // <-- your function
}
}