7

我动态构建的一些 img 元素可能(确实)失败。对于这些情况,我有一些从这里得到的代码:有没有办法以编程方式确定图像链接是坏的?即:

    function getNatlBookCritics() {
        var htmlBuilder = '';

        // Doesn't do diddly-squat - wrong spot for it?
        $('img').error(function () {
            $(this).attr("src", "Content/NoImageAvailable.png");
        });

        $.getJSON('Content/NBCCJr.json', function (data) {
            $.each(data, function (i, dataPoint) {
    . . .

...但它不工作。Warum nicht?

更新

在 $.getJSON() 调用的 .each 部分中使用此代码:

var jObject = $('<img src=\"' + dataPoint.imghref + '\"/>');
$(jObject).error(function () {
    $(this).attr("src", "Content/NoImageAvailable.jpg");
});

...所有图像都失败了。dataPoint.imghref 包含以下值:

http://www.amazon.com/exec/obidos/ASIN/B00655KLOY/garrphotgall-20

更新 2

在一个疯狂的地狱中,我正在添加“img src”,如下所示:

function getNatlBookCritics() {
    var htmlBuilder = '';
    $.getJSON('Content/nbcc.json', function (data) {
        $.each(data, function (i, dataPoint) {
            if (IsYear(dataPoint.category)) {
                htmlBuilder += '<div class=\"yearBanner\">' + dataPoint.category + '</div>';
            } else {
                htmlBuilder += '<section class=\"wrapper\" ><a id=\"mainImage\" class=\"floatLeft\" href=\"' +
                    dataPoint.imghref + '\"' + ' target=\"_blank\"><img height=\"160\" width=\"107\" src=\"' +
                    dataPoint.imgsrc + '\"' +
                    dataPoint.imgalt + '></img></a>' +
    . . .
                htmlBuilder += '</section>';
            }
    // this is where I had the img err code
        }); //each
        $('#BooksContent').append(htmlBuilder);
    });     //getNatlBookCritics

...所以你可以看到 img 被添加到 DOM 中;也许我的 img 具有高度和宽度属性的事实是问题所在......

更新 3

ManMohan Vyas:你的意思是这样的:

}); //each
        $('#BooksContent').append(htmlBuilder).
    find("img").error(function(){ 
        $(this).attr("src", "Content/NoImageAvailable.png");
    });
    });     //getJSON()

?

更新 4

这个:

var jObject = $(htmlBuilder);
jObject.find("img").error(function () {
    $(this).attr("src", "Content/NoImageAvailable.png");
});
$('#BooksContent').append(jObject);

……没用。

FWIW,改变了这一点:

$('#BooksContent').html('');

. . . $('#BooksContent').append(htmlBuilder);

...对此:

$('#BooksContent').replaceWith(htmlBuilder);

...效果不佳(填充了正确的内容,但格式混乱了(而不是纯黑色背景,每个部分都有黑色背景,但整体背景是银色)。

更新 5

我只是想到了可能导致我的问题的一些事情:我试图显示的图像都是 jpg,但“图像不可用”图像是 png。这有什么区别吗?这可能是导致渲染引擎感到困惑的原因吗?如果是这样,我只会将后备 img 保存为 jpg ......

更新 6

不,这最后两次尝试也没有奏效。我尝试了 Joseph Myers 的想法,然后是 Prestauls,因为我改变了这个:

dataPoint.imghref + '\"' + ' onerror=\"imgError(this);\" target=\"_blank\"><img height=\"160\" width=\"107\" src=\"' +
dataPoint.imgsrc + '\"' +

..对此:

dataPoint.imgsrc + '\" onerror=\"imgError(this);\"' +
dataPoint.imgalt + '></img></a>' +

……没有区别。不久前我在 jQuery 论坛上问过这个问题:我在这里抓住了稻草,但我想知道不匹配的 jQuery/jQueryUI 版本是否会成为问题?为了支持旧版浏览器,我仍在使用 jQuery 1.9.1,但对于 1.10.3 版的 jQueryUI,我处于“前沿”。

更新 7

好的,这里是所有相关代码(为了符合 SO 的长度限制,一些将被重构的冗余和没有实际意义的代码已被省略)。(静态)CSS 应该没关系,对吧?唯一的其他“代码”是 Web.config 和那种性质的东西,所以这些都不会影响我为什么无法显示后备图像。

我的很多让 NoImageAvailable.png 显示失败的尝试都被注释掉了。

@{
    Layout = "~/_SiteLayout.cshtml";
    Page.Title = "My Next Winner";
}
<div id="tabs" class="content-wrapper">
    <ul>
        <li><a href="#tab-Books">Books</a></li>
        <li><a href="#tab-Movies">Movies</a></li>
        <li><a href="#tab-Music">Music</a></li>
    </ul>
    <div id="tab-Books">
        <select id="bookDropDown">
            <option value="Pulitzer">Pulitzer</option>
            <option value="NBCC">National Book Critics Circle</option>
            <option value="NBA">National Book Awards</option>
            <option value="NOBA">National Outdoors Book Awards</option>
        </select>
        <div id="BooksContent" class="clearfix">Content in Books tab</div>
    </div>
    <div id="tab-Movies">

. . . . . .

<script>
    $.ajaxSetup({ cache: false });
    var currentBookSelection = ''; 
    var currentMovieSelection = '';
    var currentMusicSelection = '';

    function imgError(image) {
        image.onerror = "";
        image.src = "Content/NoImageAvailable.png"; 
        return true;
    }

    // BOOKS
// TODO: Refactor: just have one "getBooks()" function, passing in the name of the json file
    function getNatlBookCritics() {
        var htmlBuilder = '';

        $.getJSON('Content/nbcc.json', function (data) {
            $.each(data, function (i, dataPoint) {
                if (IsYear(dataPoint.category)) {
                    htmlBuilder += '<div class=\"yearBanner\">' + dataPoint.category + '</div>';
                } else { // see snippet at top of unit for dealing with landscape-oriented books (such as some children's books) to change height and width of img
                    htmlBuilder += '<section class=\"wrapper\" ><a id=\"mainImage\" class=\"floatLeft\" href=\"' +
                        dataPoint.imghref + '\"' + ' target=\"_blank\"><img height=\"160\" width=\"107\" src=\"' +
                        //dataPoint.imghref + '\"' + ' onerror=\"imgError(this);\" target=\"_blank\"><img height=\"160\" width=\"107\" src=\"' +
                        //dataPoint.imgsrc + '\" onerror=\"imgError(this);\"' +
                        dataPoint.imgsrc + '\"' +
                        dataPoint.imgalt + '></img></a>' +
                        '<div id=\"prizeCategory\" class=\"category\">' +
                        dataPoint.category +
                        '</div><br/><cite id=\"prizeTitle\" >' +
                        dataPoint.title +
                        '</cite><br/><div id=\"prizeArtist\" class=\"author\">' +
                        dataPoint.author +
                        '</div><br/>';
                    if (dataPoint.kindle.trim().length > 2) {
                        htmlBuilder += '<button><a href=\"' + Urlify(dataPoint.kindle) + '\"' +
                            ' target=\"_blank\">Kindle</a></button>';
                    }
                    if (dataPoint.paperback.trim().length > 2) {
                        htmlBuilder += '<button><a href=\"' + Urlify(dataPoint.paperback) + '\"' +
                            ' target=\"_blank\">Paperback</a></button>';
                    }
                    if (dataPoint.hardbound.trim().length > 2) {
                        htmlBuilder += '<button><a href=\"' + Urlify(dataPoint.hardbound) + '\"' +
                            ' target=\"_blank\">Hardcover</a></button>';
                    }
                    htmlBuilder += '</section>';

                    //// Doesn't work
                    //$('img').error(function () {
                    //    $(this).attr("src", "Content/NoImageAvailable.png");
                    //});
                    // When get answer, try this: <-- they all fail with this
                    //var jObject = $('<img src=\"' + dataPoint.imghref + '\"/>');
                    //var jObject = $('<img src=' + dataPoint.imghref + ' />');
                    //$(jObject).error(function () {
                    //    $(this).attr("src", "Content/NoImageAvailable.jpg");
                    //});
                }
            }); //each
            //var jObject = $(htmlBuilder).find('img').error(function () {
            //    $(this).attr("src", "Content/NoImageAvailable.png")
            //});

            //$("#BooksContent").html(jObject);
            //var jObject = $(htmlBuilder);
            //jObject.find("img").error(function () {
            //    $(this).attr("src", "Content/NoImageAvailable.png");
            //});
            //$('#BooksContent').append(jObject);

            // 7/23
            //imageError = function (it) {
            //    $(it).attr("src", "Content/NoImageAvailable.png");
            //};
            //htmlBuilder = htmlBuilder.replace(/<img/g, '<img onerror="imageError(this)"');
            //var jObject = $(htmlBuilder);

            //$("#BooksContent").html(jObject);
            // </ 7/23

            //$('#BooksContent').html('');
            //$('#BooksContent').append(htmlBuilder);

            ////try this 7/24/2013
            //var $jObject = $('<img>');
            //$jObject.error(function () { //$jObject is already a jquery object, don't wrap it again
            //    $(this).attr("src", "Content/NoImageAvailable.jpg");
            //}).attr('src', dataPoint.imghref);
            //</try this 7/24/2013

            //$('#BooksContent').html(htmlBuilder);
            $('#BooksContent').html(htmlBuilder).
                 find('img, button').click(function (evt) {
                     $(this).css('border', '1px solid red')
                     //evt.preventDefault();
                     //find('img').error(function() {
                     //    this.src = "/Content/NoImageAvailable.png"
                     //})
                 });

            //$('#BooksContent').replaceWith(htmlBuilder);
                //.find('img').error(function() {
                //    this.src = "Content/NoImageAvailable.png"
                //    //this.src = "http://www.gravatar.com/avatar/317f4b62da2b0186feac9b6209793505?s=80&d=http%3A%2F%2Fimg.zohostatic.com%2Fdiscussions%2Fv1%2Fimages%2FdefaultPhoto.png";
                //});
            $('#BooksContent').css('background-color', 'black');
            $('button').button();
        }); //getJSONnbcc
        $largest = 0;
        $(".wrapper").each(function () {
            if ($(this).height() > $largest) {
                $largest = $(this).height();
            }
        });
        $(".wrapper").css("height", $largest);
    }   // getNatlBookCritics()

    function getPulitzers() {
        // Since pulitzers will be the one that shows when site first opens, added rel="nofollow"
        // in each href; in this way only this method differs from the other "getX" book methods
        var htmlBuilder = '';

        $.getJSON('Content/pulitzers2.json', function (data) {
            $.each(data, function (i, dataPoint) {
                if (IsYear(dataPoint.category)) {
                    htmlBuilder += '<div class=\"yearBanner\">' + dataPoint.category + '</div>';
                } else { // see snippet at top of unit for dealing with landscape-oriented books (such as some children's books) to change height and width of img
                    htmlBuilder += '<section class=\"wrapper\" ><a id=\"mainImage\" class=\"floatLeft\" href=\"' +
                        dataPoint.imghref + '\"' + ' target=\"_blank\"><img height=\"160\" width=\"107\" src=\"' +
                        dataPoint.imgsrc + '\"' +
                        dataPoint.imgalt + '></img></a>' +
                        '<div id=\"prizeCategory\" class=\"category\">' +
                        dataPoint.category +
                        '</div><br/><cite id=\"prizeTitle\" >' +
                        dataPoint.title +
                        '</cite><br/><div id=\"prizeArtist\" class=\"author\">' +
                        dataPoint.author +
                        '</div><br/>';
                    if (dataPoint.kindle.trim().length > 2) {
                        htmlBuilder += '<button><a href=\"' + Urlify(dataPoint.kindle) + '\"' +
                            ' target=\"_blank\" rel=\"nofollow\" >Kindle</a></button>';
                    }
                    if (dataPoint.hardbound.trim().length > 2) {
                        htmlBuilder += '<button><a href=\"' + Urlify(dataPoint.hardbound) + '\"' +
                            ' target=\"_blank\" rel=\"nofollow\" >Hardcover</a></button>';
                    }
                    if (dataPoint.paperback.trim().length > 2) {
                        htmlBuilder += '<button><a href=\"' + Urlify(dataPoint.paperback) + '\"' +
                            ' target=\"_blank\" rel=\"nofollow\" >Paperback</a></button>';
                    }
                    htmlBuilder += '</section>';
                }
            }); //each
            $('#BooksContent').html(htmlBuilder).
     find('img, button').click(function (evt) {
         $(this).css('border', '1px solid red')
     });

            $('#BooksContent').css('background-color', 'black');
            $('button').button();
        }); //getPulitzers
        $largest = 0;
        $(".wrapper").each(function () {
            if ($(this).height() > $largest) {
                $largest = $(this).height();
            }
        });
        $(".wrapper").css("height", $largest);
        // This is not working; axed a question on the jQuery forum
        $('img, button').click(function (evt) {
            $(this).css('border', '5px solid green');
            evt.preventDefault();
        });
        // added this 7/24/2013 - does nothing
        //$(function () {
        //    $('a').click(function () {
        //        open(this.href, 'NewWin', 'toolbar=yes');
        //        self.focus();
        //        return false;
        //    });
        //});
    } // getPulitzers()

    function getNatlBook() {

. . . } // getNatlBook()

    function getNOBA() {
        // load bookContents using getJSON
    }

    // MOVIES
    // Movies differ from books and music in that some of the awards do not always have a person as winner - just the movie
    // So we have to check for that and conditionally add that bit of html (what corresponds to author in books and
    // artist in music)
    function getMovies(pathToJsonFile) {
        var htmlBuilder = '';

        $.getJSON(pathToJsonFile, function (data) {
            // I tried renaming the above to nbcc.json, but it won't work with that name...?!? $.getJSON('Content/nbcc.json', function (data) {
            $.each(data, function (i, dataPoint) {
                if (IsYear(dataPoint.category)) {
                    htmlBuilder += '<div class=\"yearBanner\">' + dataPoint.category + '</div>';
                } else { // see snippet at top of unit for dealing with landscape-oriented books (such as some children's books) to change height and width of img
                    htmlBuilder += '<section class=\"wrapper\" ><a id=\"mainImage\" class=\"floatLeft\" href=\"' +
                        dataPoint.imghref + '\"' + ' target=\"_blank\"><img height=\"160\" width=\"107\" src=\"' +
                        dataPoint.imgsrc + '\"' +
                        dataPoint.imgalt + '></img></a>' +
                        '<div id=\"prizeCategory\" class=\"category\">' +
                        dataPoint.category +
                        '</div><br/><cite id=\"prizeTitle\" >' +
                        dataPoint.film +
                        '</cite><br/>';
                    if (dataPoint.person.trim().length > 2) {
                        htmlBuilder += '<div id=\"prizeArtist\" class=\"person\">' + dataPoint.person + '</div><br/>';
                    }
                    if (dataPoint.bluray.trim().length > 2) {
                        htmlBuilder += '<button><a href=\"' + Urlify(dataPoint.bluray) + '\"' +
                            ' target=\"_blank\" >BluRay</a></button>';
                    }
                    if (dataPoint.dvd.trim().length > 2) {
                        htmlBuilder += '<button><a href=\"' + Urlify(dataPoint.dvd) + '\"' +
                            ' target=\"_blank\" >DVD</a></button>';
                    }
                    htmlBuilder += '</section>';
                }
            }); //each
            $('#MoviesContent').html(htmlBuilder).
                 find('img, button').click(function (evt) {
                     $(this).css('border', '1px solid silver')
                 });
            $('#MoviesContent').css('background-color', 'black');
            $('button').button();
            //console.log(htmlBuilder); <-- may want this for response to click on tab when movie tab is selected
        }); //getOscars
        $largest = 0;
        $(".wrapper").each(function () {
            if ($(this).height() > $largest) {
                $largest = $(this).height();
            }
        });
        $(".wrapper").css("height", $largest);
    }

    // MUSIC 
    // "work" is used for "album or song or recording or performance"
//TODO: Make this a generic "Music" function a la Movies above
    function getGrammies() {
        var htmlBuilder = '';

        $.getJSON('Content/grammies.json', function (data) {
            $.each(data, function (i, dataPoint) {
                if (IsYear(dataPoint.category)) {
                    htmlBuilder += '<div class=\"yearBanner\">' + dataPoint.category + '</div>';
                } else { // see snippet at top of unit for dealing with landscape-oriented books (such as some children's books) to change height and width of img
                    htmlBuilder += '<section class=\"wrapper\" ><a id=\"mainImage\" class=\"floatLeft\" href=\"' +
                        dataPoint.imghref + '\"' + ' target=\"_blank\"><img height=\"160\" width=\"107\" src=\"' +
                        dataPoint.imgsrc + '\"' +
                        dataPoint.imgalt + '></img></a>' +
                        '<div id=\"prizeCategory\" class=\"category\">' +
                        dataPoint.category +
                        '</div><br/><cite id=\"prizeTitle\" >' +
                        dataPoint.work +
                        '</cite><br/><div id=\"prizeArtist\" class=\"work\">' +
                        dataPoint.artist +
                        '</div><br/>';
                    if (dataPoint.mp3.trim().length > 2) {
                        htmlBuilder += '<button><a href=\"' + Urlify(dataPoint.mp3) + '\"' +
                            ' target=\"_blank\">mp3</a></button>';
                    }
                    if (dataPoint.dvd.trim().length > 2) {
                        htmlBuilder += '<button><a href=\"' + Urlify(dataPoint.dvd) + '\"' +
                            ' target=\"_blank\">DVD</a></button>';
                    }
                    if (dataPoint.vinyl.trim().length > 2) {
                        htmlBuilder += '<button><a href=\"' + Urlify(dataPoint.vinyl) + '\"' +
                            ' target=\"_blank\">Vinyl</a></button>';
                    }
                    htmlBuilder += '</section>';

                    //// Doesn't work
                    //$('img').error(function () {
                    //    $(this).attr("src", "Content/NoImageAvailable.png");
                    //});
                }
            }); //each
            $('#MusicContent').html(htmlBuilder).
     find('img, button').click(function (evt) {
         $(this).css('border', '1px solid gold')
     });
            $('#MusicContent').css('background-color', 'black');
            $('button').button();
        }); //getJSONMusic
        $largest = 0;
        $(".wrapper").each(function () {
            if ($(this).height() > $largest) {
                $largest = $(this).height();
            }
        });
        $(".wrapper").css("height", $largest);
    }

    function configLoading() {
        $('#lblLoading').show();
// TODO: Not working for some reason - the configLoaded never sets them back to enabled...
        //$('bookDropDown').Attr('disabled', true);
        //$('moviesDropDown').Attr('disabled', true);
        //$('musicDropDown').Attr('disabled', true);
    }

    function configLoaded() {
        $('#lblLoading').hide();
        //$('bookDropDown').Attr('disabled', false);
        //$('moviesDropDown').Attr('disabled', false);
        //$('musicDropDown').Attr('disabled', false);
    }

        $(document).ready(function () {
            $('#tabs').tabs({
                beforeActivate: function (event, ui) {
                    // Pulitzers is loaded at first; any time the books tab is clicked, something will already be there
                    if (ui.newTab.index() == 1) {
                        moviesContent = $('#MoviesContent').html();
                        if (moviesContent == 'Content in Movies tab') {
                            // TODO: When it's ready, uncomment this: getOscars();
                        }
                    }
                    else if (ui.newTab.index() == 2) {
                        musicContent = $('#MusicContent').html();
                        if (musicContent == 'Content in Music tab') {
                            // TODO: When it's ready, uncomment this: getGrammies();
                        }
                    }
                }
            });

            $('body').on('error', 'img', function (e) {
                $(e.currentTarget).attr("src", "Content/NoImageAvailable.png");
            });

            // This makes the external hrefs / targets "pop up"; I don't think I want that...
            //$('body').on('click', 'a', function () {
            //    open(this.href, 'NewWin', 'toolbar=yes')
            //    self.focus();
            //    return false;
            //});

            // Books tab is default view; load the default list (Pulitzer); the other two default lists (oscars and grammies)
            // will load the first time the user selects the corresponding tab (see beforeActivate() above)
            getPulitzers();
            currentBookSelection = "Pulitzer";
            configLoaded();

            $('#bookDropDown').change(function () {
                // TODO: May want to keep track of when in loading mode, and if so, exit/return
                configLoading();
                $('#body').removeClass('bronzeBackground silverBackground goldBackground').addClass('bronzeBackground');
                var sel = this.value;
                if ((sel == "NBCC") && (currentBookSelection != "NBCC")) {
                    getNatlBookCritics();
                    currentBookSelection = "NBCC";
                }
                else if ((sel == "NBA") && (currentBookSelection != "NBA")) {
                    getNatlBook();
                    currentBookSelection = "NBA";
                }
                else if ((sel == "NOBA") && (currentBookSelection != "NOBA")) {
                    getNOBA();
                    currentBookSelection = "NOBA";
                }
                else if ((sel == "Pulitzer") && (currentBookSelection != "Pulitzer")) {
                    getPulitzers();
                    currentBookSelection = "Pulitzer";
                }
                configLoaded();
            }); //bookDropDown

            $('#moviesDropDown').change(function () {
                configLoading();
                $('#body').removeClass('bronzeBackground silverBackground goldBackground').addClass('silverBackground');
                var sel = this.value;
                if ((sel == "Oscars") && (currentMovieSelection != "Oscars")) {
                    currentMovieSelection = "Oscars";
                    getMovies('Content/oscars.json');
                }
                else if ((sel == "GoldenGlobe") && (currentMovieSelection != "GoldenGlobe")) {
                    currentMovieSelection = "GoldenGlobe";
                    getMovies('Content/goldenglobe.json');
                }
                else if ((sel == "Cannes") && (currentMovieSelection != "Cannes")) {
                    currentMovieSelection = "Cannes";
                    getMovies('Content/cannes.json');
                }
                else if ((sel == "Sundance") && (currentMovieSelection != "Sundance")) {
                    currentMovieSelection = "Sundance";
                    getMovies('Content/sundance.json');
                }
                configLoaded();
            }); //moviesDropDown

            $('#musicDropDown').change(function () {
                configLoading();
                $('#body').removeClass('bronzeBackground silverBackground goldBackground').addClass('goldBackground');
                var sel = this.value;
                if ((sel == "Grammies") && (currentMusicSelection != "Grammies")) {
                    currentMusicSelection = "Grammies";
                    getGrammies();
                }
                else if ((sel == "AMA") && (currentMusicSelection != "AMA")) {
                    currentMusicSelection = "AMA";
                    getAMA();
                }
                else if ((sel == "CMA") && (currentMusicSelection != "CMA")) {
                    currentMusicSelection = "CMA";
                    getCMA();
                }
                else if ((sel == "Indies") && (currentMusicSelection != "Indies")) {
                    currentMusicSelection = "Indies";
                    getIndies();
                }
                configLoaded();
            }); //musicDropDown

            // added 7/24/2013, changed nothing
            //$(function() {
            //    $('a').click(function() {
            //        open(this.href, 'NewWin', 'toolbar=yes');
            //        self.focus();
            //        return false;
            //    });
            //});

        }); //ready
</script>

更新 8

barvaz 的回答对我也不起作用;也许我做错了?根据他的回答,这是我添加的:

CSS

.noImg {
  background:url(~/Content/NoImageAvailable.png);    
}

jQuery

0)在准备好的处理程序中添加了这个:

replaceEmptyImage = function ($img) {
    $img.parent().addClass('noImg');
    $img.remove();
};

1)改变了这一行:

dataPoint.imghref + '\"' + ' target=\"_blank\"><img height=\"160\" width=\"107\" src=\"' +

...对此:

dataPoint.imghref + '\"' + ' target=\"_blank\"><img height=\"160\" width=\"107\" onerror=\"replaceEmptyImage($(this))\" src=\"' +

更新 9

这是它的样子(图像“块”或“对象”在那里,只是它是黑色/空白):

在此处输入图像描述

顺便说一句,杰米麦克菲特斯的游记无论如何都是一本很棒的书,但也许特别适合给你的孩子读(任何年龄,但也许青少年时期是最佳的)。

4

8 回答 8

6

虽然您的解释不是很清楚,但最可能的原因是您的<img>标签在调用函数时不存在$('img').error();

尝试

1)创建一个带有一些id的动态图像。
2) 将 img 标签放入 DOM 后调用错误函数。

<img>标记未与错误函数绑定,这是我能看到您的代码无法正常工作的唯一原因。现在工作样本:

html:

<div id="myId">
    h
</div>

jQuery 脚本:

var jObject = $("<img src='helo.png' />");

$(jObject).error(function(){
    $(this).attr("src", "http://rack.2.mshcdn.com/media/ZgkyMDEyLzEyLzAzL2U0L3NlZWhvd3lvdXJnLjlyMS5qcGcKcAl0aHVtYgk5NTB4NTM0IwplCWpwZw/8fec6ce4/e71/see-how-your-google-results-measure-up-with-google-grader-video--6b8bbb4b41.jpg");

});

$("#myId").html(jObject);

你可以在这里检查工作小提琴 [http://jsfiddle.net/jyXqw/][1]

编辑*

var jObject = $(htmlBuilder);
 jObject.find("img").error(function(){
      $(this).attr("src", "Content/NoImageAvailable.png");
    });
 $('#BooksContent').append(jObject);

EDIT-2 * 检查小提琴,您的代码似乎运行良好:http: //jsfiddle.net/jYbQx/

于 2013-07-18T02:12:48.123 回答
3

根据通过电子邮件发送给我的部分代码进行更新

这只是一个猜测,因为您的所有主要脚本和 JSON 数据都丢失了,所以我无法对其进行测试。但是,这些更改有望使它对您有用。请测试它们!

在你的代码说之前

<div id="tabs" class="content-wrapper">

您应该完全按照您的页面添加此代码(我注意到您尚未将其包含在您的页面中):

<script src="//desandro.github.io/imagesloaded/imagesloaded.pkgd.min.js">
</script>

然后,在您的函数内部,您configLoaded需要添加第二个代码块(对代码的新更改由 NEW 标记):

function configLoaded() {
    $('#lblLoading').hide();
    var imgLoad = imagesLoaded('body');                    /* NEW */
    imgLoad.on( 'progress', function( instance, image ) {  /* NEW */
        var result = image.isLoaded ? 'loaded' : 'broken'; /* NEW */
        image.img.src = 'Your-Placeholder-Image.png';      /* NEW */
    });                                                    /* NEW */
    //$('bookDropDown').Attr('disabled', false);
    //$('moviesDropDown').Attr('disabled', false);
    //$('musicDropDown').Attr('disabled', false);
}

这样,当您的菜单加载新图像时,将再次附加进度/错误处理程序(以防在生成新图像后需要)。当然,最重要的是包含imagesloaded.pkgd.min.js脚本代码,因为没有它,代码的第二部分将无能为力。

请注意问题的作者

我所有的建议对我来说都是 100% 的,经过全面测试,就像正确的 Stack Overflow 答案一样。不幸的是,这些解决方案没有机会正确地合并到您的代码中,因为我缺少您的完整代码或独立示例。

您给出的简而言之,以及您在另一个问题中提供的 JS Fiddle(那里只有一行 JavaScript),以及您和其他人在各种评论中的 JS Fiddles 都让我清楚了解您的问题是什么. 然而,如果没有足够的实际代码(理想情况下是全部),我无法向您展示如何正确整合解决方案——这就像汽车修理工在汽车不存在时试图修理汽车,或者数学老师试图用手势而不是写东西来教别人数学问题。

我可以让我的任何解决方案为您工作,但我只需要一个指向包含问题的完整代码的链接,或者如果由于某种原因它是机密的,那么至少是一个独立的示例。请参阅:http ://sscce.org

您介意提供完整代码或独立示例的链接吗?我很乐意对其进行修改,使其适合您。即,如果这些解决方案对您不起作用,那么您的代码中还有其他一些东西需要修复,在此之前,我提供这个答案是为了社区的利益。

更新推荐的解决方案

将此脚本添加到您的页面:

<script src="//desandro.github.io/imagesloaded/imagesloaded.pkgd.min.js">
</script>

该脚本提供了正确检测页面上所有损坏图像的能力。在这里阅读它,包括一个演示,它准确地显示了您希望为自己的站点实现的功能:http: //desandro.github.io/imagesloaded/

然后将以下代码选项之一添加到您现有的 JavaScript。(您可能还需要从代码中删除所有其他检测图像加载错误的尝试,以确保没有冲突。)

var imgLoad = imagesLoaded('body');
imgLoad.on( 'always', function() {
  console.log( imgLoad.images.length + ' images loaded' );
  // detect which image is broken
  for ( var i = 0, len = imgLoad.images.length; i < len; i++ ) {
    var image = imgLoad.images[i];
    var result = image.isLoaded ? 'loaded' : 'broken';
    console.log( 'image is ' + result + ' for ' + image.img.src );
    if (result == 'broken')
        image.img.src = 'Your-Placeholder-Image.png'; /* CHANGE THIS */
  }
});

这段代码应该工作得一样好或更好,甚至更短。

var imgLoad = imagesLoaded('body');
imgLoad.on( 'progress', function( instance, image ) {
  var result = image.isLoaded ? 'loaded' : 'broken';
  console.log( 'image is ' + result + ' for ' + image.img.src );
  image.img.src = 'Your-Placeholder-Image.png'; /* CHANGE THIS */
});

一般观察

“在所有浏览器中,加载、滚动和错误事件(例如,在 <img> 元素上)不会冒泡。在 Internet Explorer 8 及更低版本中,粘贴和重置事件不会冒泡。不支持使用此类事件使用委托,但它们可以在事件处理程序直接附加到生成事件的元素时使用。”

http://api.jquery.com/on/

解释:在从 jQuery 命令异步生成 HTML 内容的文档中,您无法使用 jQuery 选择器可靠地捕获图像加载错误。

因此,在为图像注册错误处理程序时(例如将其替换为“无可用图像”图像),在图像元素被插入到 DOM 或成为 live 之前,在图像上注册错误处理程序非常重要文档片段。如果您的图像src存在于纯 JavaScript 字符串中,您需要确保onerror在将该字符串转换为活动文档片段之前指定处理程序。如果您的图像src存在于 JavaScript 图像对象中,那么指定错误处理程序已经太迟了——在这种情况下,您必须在src.

否则,在图像元素被插入到 DOM 之后,在注册事件处理程序之前,会出现竞争条件。图像可以很快返回 404 Not Found,因为不需要加载图像数据。如果在检测到 404 之前事件处理程序没有完全附加,则不会调用事件处理程序。

将错误图像设为 PNG 而不是 JPEG 并不重要。

构建代码的方式是,它形成一个 HTML 字符串,然后通过将其用作 jQuery 构造函数的参数将其转换为实时 HTML 对象,然后才为其包含的元素设置错误处理程序。img这会导致与不包含任何属性的 HTML 源代码相同的问题onerror,然后尝试使用脚本设置错误处理程序。你提到的行为

这对我有用,只需更改 JS Fiddle 中的最后几行,并在将任何内容转换为实际活动元素之前在 HTML 字符串中设置属性:

imageError = function(it) {
    $(it).attr("src","placeholder.jpg");
};

htmlBuilder = htmlBuilder.replace(/<img/g, '<img onerror="imageError(this)"');
var jObject = $(htmlBuilder);

 $("#container").html(jObject);

您表示这不起作用,但它应该(在更改placeholder.jpg并更改#container为您自己的值之后),并且正确的诊断需要我查看您页面中的所有内容,因为您所做的任何其他事情都可能影响为什么这对您不起作用.

您拥有的其他选项(更新)

正确实施使用错误处理程序的解决方案需要您在指定活动文档片段中的图像之前onerror注册/error事件处理程序。src

但是,还有其他选择。例如,在整个文档加载后,您可以创建一个函数,循环遍历页面的所有图像元素,定位那些未能加载的元素,并更改它们的src属性。

此处概述了该解决方案:

https://stackoverflow.com/a/93017/2188862

我不能保证它会起作用,因为正如我所提到的,你正在做的任何其他事情都可能影响为什么某些东西对你不起作用。

这种解决问题的方法也有一个插件可以和你的代码一起工作。https://github.com/desandro/imagesloaded

在首先将插件http://desandro.github.io/imagesloaded/imagesloaded.pkgd.min.js的脚本标签插入到您的文档中后,您可以像这样使用它:

var imgLoad = imagesLoaded('body');
imgLoad.on( 'always', function() {
  console.log( imgLoad.images.length + ' images loaded' );
  // detect which image is broken
  for ( var i = 0, len = imgLoad.images.length; i < len; i++ ) {
    var image = imgLoad.images[i];
    var result = image.isLoaded ? 'loaded' : 'broken';
    console.log( 'image is ' + result + ' for ' + image.img.src );
    if (result == 'broken')
        image.img.src = 'Content/NoImageAvailable.png'; /* DOUBLE CHECK THE SRC */
  }
});

同样,您正在做的其他事情可能会与此插件发生冲突,但绝对值得一试!它在我的示例中完美运行:

http://jsfiddle.net/cookies/xdfjU/15/

概括

由于图像错误事件不会冒泡,因此无法使用全局错误跟踪功能解决方案,剩下两种处理此问题的通用方法:

  1. 为每个图像单独注册错误处理程序的本地方法,最好在src指定之前,但至少在它成为实时 HTML 片段或 JavaScript 图像对象之前。这种方法的优点是每个图像都会立即发生错误处理,一旦检测到 404 Not Found,就会用占位符图像替换损坏的图像图标。
  2. 一种在整个页面中定位损坏图像的全局方法。这种方法的缺点是不能立即修复损坏的图像(在最终修复损坏的图像之前可能会花费大量时间加载其他大图像)并且不适用于可能在初始加载事件之后稍后添加到页面的图像发生(例如,稍后从 Ajax 数据加载的图像),但它具有处理通过各种机制(如您的字符串)加载到页面中的图像的优势,hmtlBuilder这需要完全重新编程以允许图像单独具有错误处理程序分配的。

解决此问题(不存在)的理想方法是让浏览器将图像error事件“冒泡”为一般文档错误事件,该事件可以由单个事件处理程序监控,检查源是否错误事件是一个img元素,如果是,则检查错误类型并将未找到的图像替换为所需的占位符。

再次,如果您向我发送指向您的整个页面的链接,我将很乐意帮助您使这两种正确的解决方法之一起作用。使任何 JavaScript 与您的代码一起工作的细节要求您查看所有代码,因为可能存在其他潜伏变量。

于 2013-07-24T03:25:09.803 回答
3

关于您的UPDATE 5,不,没有理由。

您应该在设置属性 src 之前设置错误处理程序:

var $jObject = $('<img>');
$jObject.error(function () { //$jObject is already a jquery object, don't wrap it again
    $(this).attr("src", "Content/NoImageAvailable.jpg");
}).attr('src',dataPoint.imghref);

这通常是您应该这样做的方式。测试并查看。

于 2013-07-24T09:06:37.670 回答
3

使用图片加载插件

https://github.com/desandro/imagesloaded

利用 jQuery 延迟对象的强大功能。这甚至会处理确定是否为您加载了图像,因此您不必使用 jQuery.error (TBH,这不是一个真正合适的用途)。

于 2013-07-29T22:35:43.197 回答
2

您的编辑似乎是问题所在。有一个后备应该解决你的问题

于 2013-07-23T20:31:21.050 回答
2

这里可能存在多个问题...

事件创建/冒泡

您不需要绑定.error每个 img。而是在进入循环之前尝试一次:

$('body').on('error', 'img', function (e) {
    $(e.currentTarget).attr("src", "Content/NoImageAvailable.png");
});

由于事件冒泡,每个父元素也会img触发一个error事件。所以不需要.error在循环中绑定使用。

下一个...

在 JS 中使用模板/避免 HTML

您不需要使用把手或下划线的模板语言之类的东西;但是,您应该尝试至少避免在您的 JS 中使用任何 html。它很容易出错。您的 img 标记(例如)无效。

为您的图像尝试以下操作:

var $img = $('<img>', {
    'src': dataPoint.imgsrc
});

您可以通过创建一个部分来开始循环:

var $output = $('<section>', {
    'class': 'wrapper'
});

然后,当您循环时,您可以附加到它:

$output.append($img);

这减少了弄乱的表面积。如果你想进一步减少表面积,你可以使用像把手这样的模板语言。

最后...

图像 mime 类型?网络流量?

调用图像返回的网络流量是什么?是不是说200成功?是说400吗?打开 chrome 的开发者工具 -> 点击 Network 标签。观察流量并尝试查看它对您的图像的描述。

服务器代码是什么?是200吗?如果是 200,那么 mime 类型是什么?您是否正确配置了 S3?图像 URL 是否以某种方式从 JSON 中修改?

于 2013-07-25T04:09:21.607 回答
2

我有同样的问题。在 ajax 响应后动态创建的.error或其他委托方法(附加到窗口/文档/DOM 节点)对我不起作用。<img>我的解决方案是使用标记onerror内的属性<img>(w3c 标准),该属性调用 javascript 函数来删除图像并将 noImg 类添加到父节点。

<img>标签内:

onerror='replaceEmptyImage($(this))'

replaceEmptyImage 函数:

replaceEmptyImage = function($img) {
  $img.parent().addClass('noImg');
  $img.remove();
};

在 CSS 中:

.noImg {
  background:url(path/to/placeholder/image);    
}

http://jsfiddle.net/tJpaR/5/

于 2013-07-27T13:20:23.123 回答
1

.on('error' handler);可用,因为jQuery 1.7 图像加载错误不会冒泡并且委托不工作绑定一个简单的函数工作并且很干净

        function noImage(event){
            $(event.target).attr('src', 'media/noImg.jpg');
        }
        $(function (){
            $('img').on('error', noImage);
            $("#neues_bild_button").on('click', function(ev){
                var newImg = $("<img src='andersBild.jpg'/>");
                newImg.on('error', noImage);
                $('#i2').after(newImg);
            });
        });
于 2015-11-03T11:24:10.943 回答