Jquery Ajax 图像加载仅在 $(window).one 函数中插入警报语句后才起作用
我有一个特殊的问题。 我正在加载一个 JSON 文件,其中包含多个图像的 src、宽度和高度。
我正在尝试将它们加载到平滑脚本 jquery 插件中并让图像自动滚动。
“查看区域”div 可以并排放置三个图像。
当我第一次加载页面时,仅显示第一张图像。如果我重新加载它,则会显示前三张图像,然后加载其他图像(总共 11 张),但插件不会滚动,因此您看不到它们。
当我在 $(window).one 函数中插入警报(“whatever”)行时,一切正常。
我怀疑这与加载图像时和触发 .load 事件时有关。
以下是解析 JSON 文件并创建附加到可滚动 div 的 HTML 字符串的代码:
var aSectionImages = new Array;
var aImagesCount = new Array();
var aImagesLoaded = new Array();
var htmlString;
var jsonStyleImages = "images.json"
var jsonNavImages = "imagesNav.json";
var scrollableArea = $("#scrollableArea");
$.getJSON(jsonNavImages, getNavIcons);
$.getJSON(jsonStyleImages, makeScroller);
function imageLoaded(imgSrc){
var locId = (imageInSection(imgSrc)).replace(/\s|'/g, "_");
if (aImagesLoaded[locId]===undefined){
aImagesLoaded[locId] = 0;
};
aImagesLoaded[locId] = aImagesLoaded[locId]+1;
if (aImagesLoaded[locId]==aImagesCount[locId]){
//alert("section" + locId);
//$("#loaded").html(locId);
//aSectionLoaded = {locId:"loaded"};
//in theory, wait until all images in a section are loaded before
//appending the HTML to the div:
scrollableArea.append(htmlString);
}
}
function imageInSection(src){
var resultId=false;
var locSrc = src.split("/");
var locFileName = (locSrc[locSrc.length-1]);
for (i = 0; i < aSectionImages.length; i++){
for(j=0; j < aSectionImages[i].images.length; j++){
tempSrc = aSectionImages[i].images[j].src.split("/");
tempFileName = tempSrc[tempSrc.length-1];
if (tempFileName == locFileName) {
resultId = aSectionImages[i].id;
}
}
}
return resultId;
}
function makeScroller(data){
aSectionImages = data;
for (i=0; i<aSectionImages.length;i++){
locData = aSectionImages[i];
locId = locData.id.replace(/\s|'/g, "_");
aImagesCount[locId] = locData.images.length;
htmlString = "<div id=\"" + locId + "\">";
for (j=0; j<locData.images.length; j++){
oImage = new Image();
$(oImage)
.load(function(){
imageLoaded(this.src);
})
.attr("src", locData.images[j].src);
if (oImage.complete && oImage.naturalWidth !== 0){
$(this).trigger("load");
//$("#trigger").html(locData.images[j].src);
//return false;
}
locImage = locData.images[j];
locImage.id ? locImage.id = " id=\""+locImage.id+"\" " : locImage.id = "";
htmlString += "<img height=\"" + locImage.height + "\"" + " width=\"" + locImage.width + "\"" + locImage.id + " src=\"" + locImage.src + "\" />";
}
}
}
以下是处理加载时显示图像的插件的一部分:
// 加载后要做的事情 $(窗口).one("加载",function(){ //alert("如果我在此处添加警报,为什么它会起作用?");
// If the content of the scrolling area is not loaded through ajax,
// we assume it's already there and can run the code to calculate
// the width of the scrolling area, resize it to that width
if(options.ajaxContentURL.length === 0) {
$mom.scrollableAreaWidth = 0;
$mom.tempStartingPosition = 0;
$mom.find(options.scrollableArea).children().find("img").each(function() {
// Check to see if the current element in the loop is the one where the scrolling should start
if( (options.startAtElementId.length !== 0) && (($(this).attr("id")) == options.startAtElementId) ) {
$mom.tempStartingPosition = $mom.scrollableAreaWidth;
}
// Add the width of the current element in the loop to the total width
$mom.scrollableAreaWidth = $mom.scrollableAreaWidth + $(this).outerWidth(true);
});
// Set the width of the scrollableArea to the accumulated width
$mom.find(options.scrollableArea).css("width", $mom.scrollableAreaWidth + "px");
// Check to see if the whole thing should be hidden at start
if(options.hiddenOnStart) {
$mom.hide();
}
}
// Set the starting position of the scrollable area. If no startAtElementId is set, the starting position
// will be the default value (zero)
$mom.find(options.scrollWrapper).scrollLeft($mom.tempStartingPosition);
// If the user has set the option autoScroll, the scollable area will
// start scrolling automatically
if(options.autoScroll !== "") {
$mom.autoScrollInterval = setInterval(autoScroll, $mom.autoScrollDelay);
}
// If autoScroll is set to always, the hot spots should be disabled
if(options.autoScroll == "always")
{
hideLeftHotSpot();
hideRightHotSpot();
}
// If the user wants to have visible hot spots, here is where it's taken care of
switch(options.visibleHotSpots)
{
case "always":
makeHotSpotBackgroundsVisible();
break;
case "onstart":
makeHotSpotBackgroundsVisible();
$mom.hideHotSpotBackgroundsInterval = setInterval(hideHotSpotBackgrounds, (options.hotSpotsVisibleTime * 1000));
break;
default:
break;
}
});
完整代码位于 http://chereecheree.com/dagworthy/style.html
您会注意到,如果您重新加载页面,它会按预期工作,但是如果您点击以下链接 上一级(dagwothy/),仅加载第一个图像,除非在加载时抛出警报语句。
感谢您花时间调查此问题! ——丹尼尔.
I have a peculiar problem.
I am loading a JSON file that contains the src, width and height of a number of images.
I am trying to load them into the smooth script jquery plugin and have the images scroll automatically.
The "viewing area" div can fit three images side by side.
When I first load the page, only the first image is shown. If I reload it, the first three images are shown, and the others (there are 11 in total) are loaded, but the plugin does not scroll, so you can't see them.
When I insert an alert("whatever") line in the $(window).one function, everything works fine.
I suspect it would have something to do with when the images are loaded and when the .load event is being triggered.
Here is the code that parses the JSON files and creates an HTML string that is appended to the scrollable div:
var aSectionImages = new Array;
var aImagesCount = new Array();
var aImagesLoaded = new Array();
var htmlString;
var jsonStyleImages = "images.json"
var jsonNavImages = "imagesNav.json";
var scrollableArea = $("#scrollableArea");
$.getJSON(jsonNavImages, getNavIcons);
$.getJSON(jsonStyleImages, makeScroller);
function imageLoaded(imgSrc){
var locId = (imageInSection(imgSrc)).replace(/\s|'/g, "_");
if (aImagesLoaded[locId]===undefined){
aImagesLoaded[locId] = 0;
};
aImagesLoaded[locId] = aImagesLoaded[locId]+1;
if (aImagesLoaded[locId]==aImagesCount[locId]){
//alert("section" + locId);
//$("#loaded").html(locId);
//aSectionLoaded = {locId:"loaded"};
//in theory, wait until all images in a section are loaded before
//appending the HTML to the div:
scrollableArea.append(htmlString);
}
}
function imageInSection(src){
var resultId=false;
var locSrc = src.split("/");
var locFileName = (locSrc[locSrc.length-1]);
for (i = 0; i < aSectionImages.length; i++){
for(j=0; j < aSectionImages[i].images.length; j++){
tempSrc = aSectionImages[i].images[j].src.split("/");
tempFileName = tempSrc[tempSrc.length-1];
if (tempFileName == locFileName) {
resultId = aSectionImages[i].id;
}
}
}
return resultId;
}
function makeScroller(data){
aSectionImages = data;
for (i=0; i<aSectionImages.length;i++){
locData = aSectionImages[i];
locId = locData.id.replace(/\s|'/g, "_");
aImagesCount[locId] = locData.images.length;
htmlString = "<div id=\"" + locId + "\">";
for (j=0; j<locData.images.length; j++){
oImage = new Image();
$(oImage)
.load(function(){
imageLoaded(this.src);
})
.attr("src", locData.images[j].src);
if (oImage.complete && oImage.naturalWidth !== 0){
$(this).trigger("load");
//$("#trigger").html(locData.images[j].src);
//return false;
}
locImage = locData.images[j];
locImage.id ? locImage.id = " id=\""+locImage.id+"\" " : locImage.id = "";
htmlString += "<img height=\"" + locImage.height + "\"" + " width=\"" + locImage.width + "\"" + locImage.id + " src=\"" + locImage.src + "\" />";
}
}
}
Here is part of the pluging that deals with displaying images as they are loaded:
// Stuff to do once on load
$(window).one("load",function(){
//alert("why does it work if I include an alert here?");
// If the content of the scrolling area is not loaded through ajax,
// we assume it's already there and can run the code to calculate
// the width of the scrolling area, resize it to that width
if(options.ajaxContentURL.length === 0) {
$mom.scrollableAreaWidth = 0;
$mom.tempStartingPosition = 0;
$mom.find(options.scrollableArea).children().find("img").each(function() {
// Check to see if the current element in the loop is the one where the scrolling should start
if( (options.startAtElementId.length !== 0) && (($(this).attr("id")) == options.startAtElementId) ) {
$mom.tempStartingPosition = $mom.scrollableAreaWidth;
}
// Add the width of the current element in the loop to the total width
$mom.scrollableAreaWidth = $mom.scrollableAreaWidth + $(this).outerWidth(true);
});
// Set the width of the scrollableArea to the accumulated width
$mom.find(options.scrollableArea).css("width", $mom.scrollableAreaWidth + "px");
// Check to see if the whole thing should be hidden at start
if(options.hiddenOnStart) {
$mom.hide();
}
}
// Set the starting position of the scrollable area. If no startAtElementId is set, the starting position
// will be the default value (zero)
$mom.find(options.scrollWrapper).scrollLeft($mom.tempStartingPosition);
// If the user has set the option autoScroll, the scollable area will
// start scrolling automatically
if(options.autoScroll !== "") {
$mom.autoScrollInterval = setInterval(autoScroll, $mom.autoScrollDelay);
}
// If autoScroll is set to always, the hot spots should be disabled
if(options.autoScroll == "always")
{
hideLeftHotSpot();
hideRightHotSpot();
}
// If the user wants to have visible hot spots, here is where it's taken care of
switch(options.visibleHotSpots)
{
case "always":
makeHotSpotBackgroundsVisible();
break;
case "onstart":
makeHotSpotBackgroundsVisible();
$mom.hideHotSpotBackgroundsInterval = setInterval(hideHotSpotBackgrounds, (options.hotSpotsVisibleTime * 1000));
break;
default:
break;
}
});
The complete code is at
http://chereecheree.com/dagworthy/style.html
You'll notice that if you reload the page, it works as expected, but if you follow the link from
one level up (dagwothy/), only the first image loads, unless the alert statement is thrown in on load.
Thanks for taking the time to look into this!
--Daniel.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为你的问题就在这里,或者至少是我看到的第一个问题:
在这种情况下
this
不是oImage
(就像它在.each()
),它是文档,所以你'在错误的元素上重新触发load
,您需要$( oImage).trigger("load")
或$( oImage).load()
代替。您尝试处理的情况是,手动触发
load
,因为并非所有浏览器在从缓存加载图像时都会触发它,这是正确的想法......您只需要在正确的元素上触发事件,否则这个条件永远不会成立,因为所有这些图像都没有load
事件来增加计数:alert()
为图像提供了加载时间,因此一切都已准备就绪否则继续...这本身会将您拥有的任何竞争条件抛出窗外,因此当发生这种情况时,通常要么a)加载了一些之前没有时间的依赖项,要么b)一些事件顺序被抛出,通过给第一次加载时间...这通常也是一部分。I think your problem is here, or at least the first one I see:
In this context
this
isn'toImage
(like it would be in a.each()
), it's document, so you're firing theload
on the wrong element, you need to have$(oImage).trigger("load")
or$(oImage).load()
instead.The case you're trying to handle, firing
load
manually because not all browsers fire it when loading an image from cache is the right idea...you just need to fire the event on the right element, otherwise this condition's never true, because all those images never had aload
event to increment the count:The
alert()
gives the images time to load, so everything's ready before anything else continues...that in itself throws any race conditions you have out the window, so when that happens it's usually either a) some dependency gets loaded that didn't have time before, or b) some event order is thrown off, by giving the first one time to load...which is usually somewhat of part a as well.